diff options
Diffstat (limited to 'wqflask')
102 files changed, 33166 insertions, 2847 deletions
diff --git a/wqflask/base/data_set.py b/wqflask/base/data_set.py index 1b4e1195..fddfce58 100644 --- a/wqflask/base/data_set.py +++ b/wqflask/base/data_set.py @@ -107,7 +107,8 @@ Publish or ProbeSet. E.g. else: new_type = "ProbeSet" self.datasets[short_dataset_name] = new_type - logger.info("datasets",self.datasets) + # Set LOG_LEVEL_DEBUG=5 to see the following: + logger.debugf(5,"datasets",self.datasets) def __call__(self, name): return self.datasets[name] diff --git a/wqflask/base/mrna_assay_tissue_data.py b/wqflask/base/mrna_assay_tissue_data.py index e99ef7b5..eb836e6c 100644 --- a/wqflask/base/mrna_assay_tissue_data.py +++ b/wqflask/base/mrna_assay_tissue_data.py @@ -57,7 +57,7 @@ class MrnaAssayTissueData(object): as x inner join TissueProbeSetXRef as t on t.Symbol = x.Symbol and t.Mean = x.maxmean; '''.format(in_clause) - logger.sql(query) + results = g.db.execute(query).fetchall() lower_symbols = [] @@ -91,7 +91,7 @@ class MrnaAssayTissueData(object): def get_symbol_values_pairs(self): id_list = [self.data[symbol].data_id for symbol in self.data] - + symbol_values_dict = {} if len(id_list) > 0: @@ -100,8 +100,6 @@ class MrnaAssayTissueData(object): WHERE TissueProbeSetData.Id IN {} and TissueProbeSetXRef.DataId = TissueProbeSetData.Id""".format(db_tools.create_in_clause(id_list)) - logger.sql('tissue query',query) - results = g.db.execute(query).fetchall() for result in results: if result.Symbol.lower() not in symbol_values_dict: diff --git a/wqflask/base/trait.py b/wqflask/base/trait.py index 9566c192..32032ba7 100644 --- a/wqflask/base/trait.py +++ b/wqflask/base/trait.py @@ -116,7 +116,6 @@ class GeneralTrait(object): return stringy - def display_name(self): stringy = "" if self.dataset and self.name: @@ -323,7 +322,7 @@ class GeneralTrait(object): #phenotype traits, then display the pre-publication description instead #of the post-publication description if self.confidential: - self.description_display = "" + self.description_display = self.pre_publication_description #if not webqtlUtil.hasAccessToConfidentialPhenotypeTrait( # privilege=self.dataset.privilege, @@ -331,11 +330,11 @@ class GeneralTrait(object): # authorized_users=self.authorized_users): # # description = self.pre_publication_description - - if description: - self.description_display = description.strip() else: - self.description_display = "" + if description: + self.description_display = description.strip() + else: + self.description_display = "" if not self.year.isdigit(): self.pubmed_text = "N/A" @@ -364,7 +363,7 @@ class GeneralTrait(object): FROM Homologene, Species, InbredSet WHERE - Homologene.GeneId =%s AND + Homologene.GeneId ='%s' AND InbredSet.Name = '%s' AND InbredSet.SpeciesId = Species.Id AND Species.TaxonomyId = Homologene.TaxonomyId @@ -613,7 +612,10 @@ class GeneralTrait(object): if self.probe_target_description: formatted += "; " + self.probe_target_description elif self.dataset.type == 'Publish': - formatted = self.post_publication_description + if self.confidential: + formatted = self.pre_publication_description + else: + formatted = self.post_publication_description else: formatted = "Not available" return formatted.capitalize() diff --git a/wqflask/base/webqtlCaseData.py b/wqflask/base/webqtlCaseData.py index c80fcb65..2f88f778 100644 --- a/wqflask/base/webqtlCaseData.py +++ b/wqflask/base/webqtlCaseData.py @@ -16,8 +16,6 @@ # Contact Drs. Robert W. Williams and Xiaodong Zhou (2010) # at rwilliams@uthsc.edu and xzhou15@uthsc.edu # -# -# # This module is used by GeneNetwork project (www.genenetwork.org) # # Created by GeneNetwork Core Team 2010/08/10 @@ -52,6 +50,10 @@ class webqtlCaseData(object): str += " variance=%2.3f" % self.variance if self.num_cases != None: str += " ndata=%d" % self.num_cases + if self.name != None: + str += " name=%s" % self.name + if self.name2 != None: + str += " name2=%s" % self.name2 return str @property diff --git a/wqflask/base/webqtlConfig.py b/wqflask/base/webqtlConfig.py index f76d8140..e5f10edf 100644 --- a/wqflask/base/webqtlConfig.py +++ b/wqflask/base/webqtlConfig.py @@ -8,7 +8,7 @@ # ######################################### -from utility.tools import valid_path, mk_dir, assert_dir, flat_files, TEMPDIR +from utility.tools import valid_path, mk_dir, assert_dir, assert_writable_dir, flat_files, TEMPDIR #Debug Level #1 for debug, mod python will reload import each time @@ -60,24 +60,36 @@ ENSEMBLETRANSCRIPT_URL="http://useast.ensembl.org/Mus_musculus/Lucene/Details?sp # HTMLPATH is replaced by GENODIR # IMGDIR is replaced by GENERATED_IMAGE_DIR -# Temporary storage: +# Temporary storage (note that this TMPDIR can be set as an +# environment variable - use utility.tools.TEMPDIR when you +# want to reach this base dir +assert_writable_dir(TEMPDIR) + TMPDIR = mk_dir(TEMPDIR+'/gn2/') -CACHEDIR = mk_dir(TEMPDIR+'/cache/') +assert_writable_dir(TMPDIR) + +CACHEDIR = mk_dir(TMPDIR+'/cache/') # We can no longer write into the git tree: GENERATED_IMAGE_DIR = mk_dir(TMPDIR+'/generated/') GENERATED_TEXT_DIR = mk_dir(TMPDIR+'/generated_text/') +# Make sure we have permissions to access these +assert_writable_dir(CACHEDIR) +assert_writable_dir(GENERATED_IMAGE_DIR) +assert_writable_dir(GENERATED_TEXT_DIR) + # Flat file directories GENODIR = flat_files('genotype')+'/' +assert_dir(GENODIR) + +# JSON genotypes are OBSOLETE JSON_GENODIR = flat_files('genotype/json')+'/' if not valid_path(JSON_GENODIR): # fall back on old location (move the dir, FIXME) JSON_GENODIR = flat_files('json') -assert_dir(GENODIR) +# Are we using the following...? PORTADDR = "http://50.16.251.170" - INFOPAGEHREF = '/dbdoc/%s.html' CGIDIR = '/webqtl/' #XZ: The variable name 'CGIDIR' should be changed to 'PYTHONDIR' SCRIPTFILE = 'main.py' - diff --git a/wqflask/maintenance/gen_select_dataset.py b/wqflask/maintenance/gen_select_dataset.py index d39bf4a5..542c0d83 100644 --- a/wqflask/maintenance/gen_select_dataset.py +++ b/wqflask/maintenance/gen_select_dataset.py @@ -1,7 +1,9 @@ """Script that generates the data for the main dropdown menus on the home page Writes out data as /static/new/javascript/dataset_menu_structure.json -It needs to be run manually when database has been changed. +It needs to be run manually when database has been changed. Run it as + + ./bin/genenetwork2 ~/my_settings.py -c ./wqflask/maintenance/gen_select_dataset.py """ @@ -37,11 +39,17 @@ from __future__ import print_function, division #print("cdict is:", cdict) import sys -# import zach_settings # no hard code paths! -# import MySQLdb +# NEW: Note we prepend the current path - otherwise a guix instance of GN2 may be used instead +sys.path.insert(0,'./') +# NEW: import app to avoid a circular dependency on utility.tools +from wqflask import app + +from utility.tools import locate, locate_ignore_error, TEMPDIR, SQL_URI + +import MySQLdb -# import simplejson as json +import simplejson as json import urlparse @@ -55,14 +63,13 @@ from pprint import pformat as pf #conn = Engine.connect() -print('ERROR: This conversion is now OBSOLETE as the menu gets built from the database in Javascript using GN_SERVER instead!') -sys.exit() +print('WARNING: This conversion is now OBSOLETE as the menu gets built from the database in Javascript using GN_SERVER instead!') def parse_db_uri(db_uri): """Converts a database URI to the db name, host name, user name, and password""" - parsed_uri = urlparse.urlparse(zach_settings.DB_URI) + parsed_uri = urlparse.urlparse(SQL_URI) db_conn_info = dict( db = parsed_uri.path[1:], @@ -70,6 +77,7 @@ def parse_db_uri(db_uri): user = parsed_uri.username, passwd = parsed_uri.password) + print(db_conn_info) return db_conn_info @@ -258,7 +266,7 @@ def build_datasets(species, group, type_name): def main(): """Generates and outputs (as json file) the data for the main dropdown menus on the home page""" - parse_db_uri(zach_settings.SQL_URI) + parse_db_uri(SQL_URI) species = get_species() groups = get_groups(species) @@ -281,7 +289,7 @@ def main(): #print("data:", data) - output_file = """../wqflask/static/new/javascript/dataset_menu_structure.json""" + output_file = """./wqflask/static/new/javascript/dataset_menu_structure.json""" with open(output_file, 'w') as fh: json.dump(data, fh, indent=" ", sort_keys=True) @@ -297,6 +305,6 @@ def _test_it(): #print("build_datasets:", pf(datasets)) if __name__ == '__main__': - Conn = MySQLdb.Connect(**parse_db_uri(zach_settings.SQL_URI)) + Conn = MySQLdb.Connect(**parse_db_uri(SQL_URI)) Cursor = Conn.cursor() main() diff --git a/wqflask/runserver.py b/wqflask/runserver.py index 12ec904e..0342b7ad 100644 --- a/wqflask/runserver.py +++ b/wqflask/runserver.py @@ -16,34 +16,37 @@ GREEN = '\033[92m' BOLD = '\033[1m' ENDC = '\033[0m' -logger.info("GN2 is running. Visit %shttp://localhost:5003/%s" % (BLUE,ENDC)) - import os app.config['SECRET_KEY'] = os.urandom(24) -from utility.tools import WEBSERVER_MODE +from utility.tools import WEBSERVER_MODE,get_setting_int + +port = get_setting_int("SERVER_PORT") + +logger.info("GN2 is running. Visit %shttp://localhost:%s/%s" % (BLUE,port,ENDC)) werkzeug_logger = logging.getLogger('werkzeug') if WEBSERVER_MODE == 'DEBUG': app.run(host='0.0.0.0', - port=app.config['SERVER_PORT'], + port=port, debug=True, - use_debugger=True, + use_debugger=False, threaded=False, + processes=0, use_reloader=True) elif WEBSERVER_MODE == 'DEV': werkzeug_logger.setLevel(logging.WARNING) app.run(host='0.0.0.0', - port=app.config['SERVER_PORT'], + port=port, debug=False, use_debugger=False, threaded=False, processes=0, use_reloader=True) -else: #production mode +else: # staging/production modes app.run(host='0.0.0.0', - port=app.config['SERVER_PORT'], + port=port, debug=False, use_debugger=False, threaded=True, diff --git a/wqflask/utility/helper_functions.py b/wqflask/utility/helper_functions.py index 15f60765..377f6b26 100644 --- a/wqflask/utility/helper_functions.py +++ b/wqflask/utility/helper_functions.py @@ -4,18 +4,22 @@ from base.trait import GeneralTrait from base import data_set from base.species import TheSpecies +from wqflask import user_manager +import logging +logger = logging.getLogger(__name__ ) + def get_species_dataset_trait(self, start_vars): #assert type(read_genotype) == type(bool()), "Expecting boolean value for read_genotype" self.dataset = data_set.create_dataset(start_vars['dataset']) - print("After creating dataset") + logger.debug("After creating dataset") self.species = TheSpecies(dataset=self.dataset) - print("After creating species") + logger.debug("After creating species") self.this_trait = GeneralTrait(dataset=self.dataset, name=start_vars['trait_id'], cellid=None, get_qtl_info=True) - print("After creating trait") + logger.debug("After creating trait") #if read_genotype: #self.dataset.group.read_genotype_file() @@ -23,15 +27,17 @@ def get_species_dataset_trait(self, start_vars): def get_trait_db_obs(self, trait_db_list): + if isinstance(trait_db_list, basestring): + trait_db_list = trait_db_list.split(",") self.trait_list = [] - for i, trait_db in enumerate(trait_db_list): - if i == (len(trait_db_list) - 1): - break - trait_name, dataset_name = trait_db.split(":") - #print("dataset_name:", dataset_name) + for trait in trait_db_list: + data, _separator, hmac = trait.rpartition(':') + data = data.strip() + assert hmac==user_manager.actual_hmac_creation(data), "Data tampering?" + trait_name, dataset_name = data.split(":") dataset_ob = data_set.create_dataset(dataset_name) trait_ob = GeneralTrait(dataset=dataset_ob, name=trait_name, cellid=None) - self.trait_list.append((trait_ob, dataset_ob))
\ No newline at end of file + self.trait_list.append((trait_ob, dataset_ob)) diff --git a/wqflask/utility/logger.py b/wqflask/utility/logger.py index ddc0ea82..bacb0aa4 100644 --- a/wqflask/utility/logger.py +++ b/wqflask/utility/logger.py @@ -31,6 +31,7 @@ import string from inspect import isfunction from pprint import pformat as pf from inspect import stack +import datetime from utility.tools import LOG_LEVEL, LOG_LEVEL_DEBUG, LOG_SQL, LOG_FORMAT @@ -49,11 +50,20 @@ class GNLogger: self.logger.setLevel(value) def debug(self,*args): + """Call logging.debug for multiple args. Use (lazy) debugf and +level=num to filter on LOG_LEVEL_DEBUG. + + """ + self.collect(self.logger.debug,*args) + + def debug20(self,*args): """Call logging.debug for multiple args. Use level=num to filter on LOG_LEVEL_DEBUG (NYI). """ - self.collect(self.logger.debug,*args) + if level <= LOG_LEVEL_DEBUG: + if self.logger.getEffectiveLevel() < 20: + self.collect(self.logger.debug,*args) def info(self,*args): """Call logging.info for multiple args""" @@ -66,7 +76,10 @@ LOG_LEVEL_DEBUG (NYI). def error(self,*args): """Call logging.error for multiple args""" - self.collect(self.logger.error,*args) + now = datetime.datetime.utcnow() + time_str = now.strftime('%H:%M:%S UTC %Y%m%d') + l = [time_str]+list(args) + self.collect(self.logger.error,*l) def infof(self,*args): """Call logging.info for multiple args lazily""" @@ -75,7 +88,10 @@ LOG_LEVEL_DEBUG (NYI). self.collectf(self.logger.debug,*args) def debugf(self,level=0,*args): - """Call logging.debug for multiple args lazily""" + """Call logging.debug for multiple args lazily and handle + LOG_LEVEL_DEBUG correctly + + """ # only evaluate function when logging if level <= LOG_LEVEL_DEBUG: if self.logger.getEffectiveLevel() < 20: diff --git a/wqflask/utility/tools.py b/wqflask/utility/tools.py index bb8241f5..77cb6ac5 100644 --- a/wqflask/utility/tools.py +++ b/wqflask/utility/tools.py @@ -3,12 +3,16 @@ import os import sys +import json + from wqflask import app # Use the standard logger here to avoid a circular dependency import logging logger = logging.getLogger(__name__ ) +OVERRIDES = {} + def get_setting(command_id,guess=None): """Resolve a setting from the environment or the global settings in app.config, with valid_path is a function checking whether the @@ -44,13 +48,15 @@ def get_setting(command_id,guess=None): logger.debug("Looking for "+command_id+"\n") command = value(os.environ.get(command_id)) if command is None or command == "": - # ---- Check whether setting exists in app - command = value(app.config.get(command_id)) + command = OVERRIDES.get(command_id) if command is None: - command = value(guess) - if command is None or command == "": - print command - raise Exception(command_id+' setting unknown or faulty (update default_settings.py?).') + # ---- Check whether setting exists in app + command = value(app.config.get(command_id)) + if command is None: + command = value(guess) + if command is None or command == "": + # print command + raise Exception(command_id+' setting unknown or faulty (update default_settings.py?).') logger.debug("Set "+command_id+"="+str(command)) return command @@ -92,6 +98,10 @@ def gemma_command(guess=None): def plink_command(guess=None): return valid_bin(get_setting("PLINK_COMMAND",guess)) +def flat_file_exists(subdir): + base = get_setting("GENENETWORK_FILES") + return valid_path(base+"/"+subdir) + def flat_files(subdir=None): base = get_setting("GENENETWORK_FILES") if subdir: @@ -103,6 +113,17 @@ def assert_dir(dir): raise Exception("ERROR: can not find directory "+dir) return dir +def assert_writable_dir(dir): + try: + fn = dir + "/test.txt" + fh = open( fn, 'w' ) + fh.write("I am writing this text to the file\n") + fh.close() + os.remove(fn) + except IOError: + raise Exception('Unable to write test.txt to directory ' + dir ) + return dir + def mk_dir(dir): if not valid_path(dir): os.makedirs(dir) @@ -146,7 +167,10 @@ def locate_ignore_error(name, subdir=None): return None def tempdir(): - return valid_path(get_setting("TEMPDIR","/tmp")) + """ + Get UNIX TMPDIR by default + """ + return valid_path(get_setting("TMPDIR","/tmp")) BLUE = '\033[94m' GREEN = '\033[92m' @@ -160,18 +184,21 @@ def show_settings(): log_level = getattr(logging, LOG_LEVEL.upper()) logging.basicConfig(level=log_level) + logger.info(OVERRIDES) logger.info(BLUE+"Mr. Mojo Risin 2"+ENDC) - print "runserver.py: ****** The webserver has the following configuration ******" + print "runserver.py: ****** Webserver configuration ******" keylist = app.config.keys() keylist.sort() for k in keylist: try: - print("%s %s%s%s%s" % (k,BLUE,BOLD,get_setting(k),ENDC)) + print("%s: %s%s%s%s" % (k,BLUE,BOLD,get_setting(k),ENDC)) except: - print("%s %s%s%s%s" % (k,GREEN,BOLD,app.config[k],ENDC)) + print("%s: %s%s%s%s" % (k,GREEN,BOLD,app.config[k],ENDC)) # Cached values +GN_VERSION = get_setting('GN_VERSION') +HOME = get_setting('HOME') WEBSERVER_MODE = get_setting('WEBSERVER_MODE') GN_SERVER_URL = get_setting('GN_SERVER_URL') SQL_URI = get_setting('SQL_URI') @@ -184,8 +211,27 @@ LOG_FORMAT = "%(message)s" # not yet in use USE_REDIS = get_setting_bool('USE_REDIS') USE_GN_SERVER = get_setting_bool('USE_GN_SERVER') +GENENETWORK_FILES = get_setting('GENENETWORK_FILES') + PYLMM_COMMAND = pylmm_command() GEMMA_COMMAND = gemma_command() PLINK_COMMAND = plink_command() -FLAT_FILES = flat_files() -TEMPDIR = tempdir() +TEMPDIR = tempdir() # defaults to UNIX TMPDIR + +from six import string_types + +if os.environ.get('WQFLASK_OVERRIDES'): + jsonfn = get_setting('WQFLASK_OVERRIDES') + logger.error("WQFLASK_OVERRIDES: %s" % jsonfn) + with open(jsonfn) as data_file: + overrides = json.load(data_file) + for k in overrides: + cmd = overrides[k] + if isinstance(cmd, string_types): + OVERRIDES[k] = eval(cmd) + else: + OVERRIDES[k] = cmd + logger.debug(OVERRIDES) + +assert_dir(get_setting("JS_BIODALLIANCE")) +assert_dir(get_setting("JS_TWITTER_POST_FETCHER")) diff --git a/wqflask/wqflask/__init__.py b/wqflask/wqflask/__init__.py index af271d02..2188ce17 100644 --- a/wqflask/wqflask/__init__.py +++ b/wqflask/wqflask/__init__.py @@ -14,11 +14,7 @@ app = Flask(__name__) app.config.from_object('cfg.default_settings') # Get the defaults from cfg.default_settings app.config.from_envvar('WQFLASK_SETTINGS') # See http://flask.pocoo.org/docs/config/#configuring-from-files - -logger.debug("System path is") -logger.debug(sys.path) -logger.debug("App.config is") -logger.debug(app.config) +# Note we also use WQFLASK_OVERRIDES app.jinja_env.globals.update( undefined = jinja2.StrictUndefined, diff --git a/wqflask/wqflask/collect.py b/wqflask/wqflask/collect.py index 5484633b..81d03d6c 100644 --- a/wqflask/wqflask/collect.py +++ b/wqflask/wqflask/collect.py @@ -164,13 +164,20 @@ class UserCollection(object): if not uc: return create_new("Default") else: - uc = model.UserCollection.query.get(params['existing_collection']) - members = uc.members_as_set() #set(json.loads(uc.members)) + uc = model.UserCollection.query.get(params['existing_collection'].split(":")[0]) + members = list(uc.members_as_set()) #set(json.loads(uc.members)) len_before = len(members) traits = process_traits(params['traits']) - - members_now = list(members | traits) + + members_now = members + for trait in traits: + if trait in members: + continue + else: + members_now.append(trait) + + #members_now = list(members | traits) len_now = len(members_now) uc.members = json.dumps(members_now) @@ -184,28 +191,6 @@ class UserCollection(object): # Probably have to change that return redirect(url_for('view_collection', uc_id=uc.id)) - def remove_traits(self, params): - - #params = request.form - print("params are:", params) - uc_id = params['uc_id'] - uc = model.UserCollection.query.get(uc_id) - traits_to_remove = params.getlist('traits[]') - print("traits_to_remove are:", traits_to_remove) - traits_to_remove = process_traits(traits_to_remove) - print("\n\n after processing, traits_to_remove:", traits_to_remove) - all_traits = uc.members_as_set() - print(" all_traits:", all_traits) - members_now = all_traits - traits_to_remove - print(" members_now:", members_now) - print("Went from {} to {} members in set.".format(len(all_traits), len(members_now))) - uc.members = json.dumps(list(members_now)) - uc.changed_timestamp = datetime.datetime.utcnow() - db_session.commit() - - # We need to return something so we'll return this...maybe in the future - # we can use it to check the results - return str(len(members_now)) def report_change(len_before, len_now): new_length = len_now - len_before @@ -218,8 +203,6 @@ def report_change(len_before, len_now): print("No new traits were added.") - - @app.route("/collections/add") def collections_add(): traits=request.args['traits'] @@ -235,7 +218,6 @@ def collections_add(): anon_collections = user_manager.AnonUser().get_collections() collection_names = [] for collection in anon_collections: - print("COLLECTION:", collection) collection_names.append({'id':collection['id'], 'name':collection['name']}) return render_template("collections/add.html", traits = traits, @@ -246,21 +228,17 @@ def collections_add(): @app.route("/collections/new") def collections_new(): params = request.args - #print("request.args in collections_new are:", params) - - collection_name = params['new_collection'] - if "anonymous_add" in params: - AnonCollection(name=collection_name).add_traits(params, "Default") - return redirect(url_for('view_collection')) if "sign_in" in params: return redirect(url_for('login')) if "create_new" in params: print("in create_new") + collection_name = params['new_collection'] return create_new(collection_name) elif "add_to_existing" in params: print("in add to existing") + collection_name = params['existing_collection'].split(":")[1] if g.user_session.logged_in: return UserCollection().add_traits(params, collection_name) else: @@ -268,7 +246,6 @@ def collections_new(): ac.add_traits(params) return redirect(url_for('view_collection', collection_id=ac.id)) else: - print("ELSE") CauseAnError @@ -305,7 +282,6 @@ def create_new(collection_name): ac = AnonCollection(collection_name) ac.changed_timestamp = datetime.datetime.utcnow().strftime('%b %d %Y %I:%M%p') ac.add_traits(params) - print("Collection ID:", ac.id) return redirect(url_for('view_collection', collection_id=ac.id)) @app.route("/collections/list") @@ -329,7 +305,6 @@ def list_collections(): @app.route("/collections/remove", methods=('POST',)) def remove_traits(): - params = request.form print("params are:", params) @@ -337,14 +312,11 @@ def remove_traits(): uc_id = params['uc_id'] uc = model.UserCollection.query.get(uc_id) traits_to_remove = params.getlist('traits[]') - print("traits_to_remove are:", traits_to_remove) traits_to_remove = process_traits(traits_to_remove) print("\n\n after processing, traits_to_remove:", traits_to_remove) all_traits = uc.members_as_set() - print(" all_traits:", all_traits) members_now = all_traits - traits_to_remove print(" members_now:", members_now) - print("Went from {} to {} members in set.".format(len(all_traits), len(members_now))) uc.members = json.dumps(list(members_now)) uc.changed_timestamp = datetime.datetime.utcnow() db_session.commit() @@ -388,7 +360,6 @@ def view_collection(): uc_id = params['uc_id'] uc = model.UserCollection.query.get(uc_id) traits = json.loads(uc.members) - print("traits are:", traits) else: user_collections = json.loads(Redis.get(user_manager.AnonUser().key)) this_collection = {} @@ -405,7 +376,6 @@ def view_collection(): json_version = [] for atrait in traits: - print("atrait is:", atrait) name, dataset_name = atrait.split(':') trait_ob = trait.GeneralTrait(name=name, dataset_name=dataset_name) @@ -414,8 +384,6 @@ def view_collection(): json_version.append(trait_ob.jsonable()) - print("trait_obs:", trait_obs) - if "uc_id" in params: collection_info = dict(trait_obs=trait_obs, uc = uc) diff --git a/wqflask/wqflask/correlation_matrix/show_corr_matrix.py b/wqflask/wqflask/correlation_matrix/show_corr_matrix.py index caf48a45..70e21917 100644 --- a/wqflask/wqflask/correlation_matrix/show_corr_matrix.py +++ b/wqflask/wqflask/correlation_matrix/show_corr_matrix.py @@ -83,15 +83,12 @@ class CorrelationMatrix(object): this_trait = trait_db[0] this_sample_data = this_trait.data - #self.sample_data[this_trait.name] = [] this_trait_vals = [] for sample in self.all_sample_list: if sample in this_sample_data: this_trait_vals.append(this_sample_data[sample].value) - #self.sample_data[this_trait.name].append(this_sample_data[sample].value) else: this_trait_vals.append('') - #self.sample_data[this_trait.name].append('') self.sample_data.append(this_trait_vals) self.lowest_overlap = 8 #ZS: Variable set to the lowest overlapping samples in order to notify user, or 8, whichever is lower (since 8 is when we want to display warning) @@ -114,7 +111,6 @@ class CorrelationMatrix(object): target_samples = target_db.group.samplelist target_sample_data = target_trait.data - print("target_samples", len(target_samples)) this_trait_vals = [] target_vals = [] @@ -166,17 +162,7 @@ class CorrelationMatrix(object): sample_data = self.sample_data,) # corr_results = [result[1] for result in result_row for result_row in self.corr_results]) - - #self.js_data = dict(traits = self.traits, - # groups = groups, - # cols = range(len(self.traits)), - # rows = range(len(self.traits)), - # samples = self.all_sample_list, - # sample_data = self.sample_data, - # corr_results = self.corr_results,) - - - + def get_trait_db_obs(self, trait_db_list): self.trait_list = [] diff --git a/wqflask/wqflask/marker_regression/marker_regression.py b/wqflask/wqflask/marker_regression/marker_regression.py index 510b26af..200f2207 100644 --- a/wqflask/wqflask/marker_regression/marker_regression.py +++ b/wqflask/wqflask/marker_regression/marker_regression.py @@ -35,20 +35,21 @@ from utility import helper_functions from utility import Plot, Bunch from utility import temp_data from utility.benchmark import Bench -from wqflask.marker_regression import gemma_mapping +from wqflask.marker_regression import gemma_mapping, rqtl_mapping, qtlreaper_mapping from utility.tools import locate, locate_ignore_error, PYLMM_COMMAND, GEMMA_COMMAND, PLINK_COMMAND, TEMPDIR from utility.external import shell from base.webqtlConfig import TMPDIR, GENERATED_TEXT_DIR +import utility.logger +logger = utility.logger.getLogger(__name__ ) + class MarkerRegression(object): def __init__(self, start_vars, temp_uuid): helper_functions.get_species_dataset_trait(self, start_vars) - #tempdata = temp_data.TempData(temp_uuid) - self.temp_uuid = temp_uuid #needed to pass temp_uuid to gn1 mapping code (marker_regression_gn1.py) self.json_data = {} @@ -57,20 +58,24 @@ class MarkerRegression(object): self.samples = [] # Want only ones with values self.vals = [] - #for sample in self.this_trait.data.keys(): + all_samples_ordered = self.dataset.group.all_samples_ordered() + primary_sample_names = list(all_samples_ordered) + for sample in self.dataset.group.samplelist: + # sample is actually the name of an individual in_trait_data = False for item in self.this_trait.data: - if self.this_trait.data[item].name2 == sample: + if self.this_trait.data[item].name == sample: value = start_vars['value:' + self.this_trait.data[item].name] self.samples.append(self.this_trait.data[item].name) self.vals.append(value) in_trait_data = True break if not in_trait_data: - value = start_vars['value:' + sample] - self.samples.append(sample) - self.vals.append(value) + value = start_vars.get('value:' + sample) + if value: + self.samples.append(sample) + self.vals.append(value) self.mapping_method = start_vars['method'] if start_vars['manhattan_plot'] == "True": @@ -164,7 +169,10 @@ class MarkerRegression(object): self.model = start_vars['mapmodel_rqtl_geno'] if start_vars['pair_scan'] == "true": self.pair_scan = True - results = self.run_rqtl_geno() + if self.permCheck and self.num_perm > 0: + self.perm_output, self.suggestive, self.significant, results = rqtl_mapping.run_rqtl_geno(self.vals, self.dataset, self.method, self.model, self.permCheck, self.num_perm, self.do_control, self.control_marker, self.manhattan_plot, self.pair_scan) + else: + results = rqtl_mapping.run_rqtl_geno(self.vals, self.dataset, self.method, self.model, self.permCheck, self.num_perm, self.do_control, self.control_marker, self.manhattan_plot, self.pair_scan) elif self.mapping_method == "reaper": if "startMb" in start_vars: #ZS: Check if first time page loaded, so it can default to ON if "additiveCheck" in start_vars: @@ -192,16 +200,26 @@ class MarkerRegression(object): self.control_marker = start_vars['control_marker'] self.do_control = start_vars['do_control'] - results = self.gen_reaper_results() + logger.info("Running qtlreaper") + results, self.json_data, self.perm_output, self.suggestive, self.significant, self.bootstrap_results = qtlreaper_mapping.gen_reaper_results(self.this_trait, + self.dataset, + self.samples, + self.json_data, + self.num_perm, + self.bootCheck, + self.num_bootstrap, + self.do_control, + self.control_marker, + self.manhattan_plot) elif self.mapping_method == "plink": results = self.run_plink() elif self.mapping_method == "pylmm": - print("RUNNING PYLMM") + logger.debug("RUNNING PYLMM") if self.num_perm > 0: self.run_permutations(str(temp_uuid)) results = self.gen_data(str(temp_uuid)) else: - print("RUNNING NOTHING") + logger.debug("RUNNING NOTHING") if self.pair_scan == True: self.qtl_results = [] @@ -213,7 +231,6 @@ class MarkerRegression(object): if 'lod_score' in marker.keys(): self.qtl_results.append(marker) - self.trimmed_markers = results for qtl in enumerate(self.qtl_results): @@ -244,7 +261,7 @@ class MarkerRegression(object): self.qtl_results.append(marker) self.trimmed_markers = trim_markers_for_table(results) - + self.json_data['chr'] = [] self.json_data['pos'] = [] self.json_data['lod.hk'] = [] @@ -256,9 +273,9 @@ class MarkerRegression(object): #Need to convert the QTL objects that qtl reaper returns into a json serializable dictionary for index, qtl in enumerate(self.qtl_results): #if index<40: - # print("lod score is:", qtl['lod_score']) + # logger.debug("lod score is:", qtl['lod_score']) if qtl['chr'] == highest_chr and highest_chr != "X" and highest_chr != "X/Y": - #print("changing to X") + #logger.debug("changing to X") self.json_data['chr'].append("X") else: self.json_data['chr'].append(str(qtl['chr'])) @@ -276,8 +293,7 @@ class MarkerRegression(object): self.json_data['chrnames'].append([self.species.chromosomes.chromosomes[key].name, self.species.chromosomes.chromosomes[key].mb_length]) chromosome_mb_lengths[key] = self.species.chromosomes.chromosomes[key].mb_length - # print("json_data:", self.json_data) - + # logger.debug("json_data:", self.json_data) self.js_data = dict( result_score_type = self.score_type, @@ -305,7 +321,7 @@ class MarkerRegression(object): self.dataset.group.name, self.dataset.group.name, self.dataset.group.name) - #print("gemma_command:" + gemma_command) + #logger.debug("gemma_command:" + gemma_command) os.system(gemma_command) @@ -327,7 +343,7 @@ class MarkerRegression(object): included_markers.append(line.split("\t")[1]) p_values.append(float(line.split("\t")[10])) #p_values[line.split("\t")[1]] = float(line.split("\t")[10]) - #print("p_values: ", p_values) + #logger.debug("p_values: ", p_values) return included_markers, p_values def gen_pheno_txt_file(self): @@ -349,200 +365,13 @@ class MarkerRegression(object): count, p_values = self.parse_rqtl_output(plink_output_filename) - def geno_to_rqtl_function(self): # TODO: Need to figure out why some genofiles have the wrong format and don't convert properly - - ro.r(""" - trim <- function( x ) { gsub("(^[[:space:]]+|[[:space:]]+$)", "", x) } - - getGenoCode <- function(header, name = 'unk'){ - mat = which(unlist(lapply(header,function(x){ length(grep(paste('@',name,sep=''), x)) })) == 1) - return(trim(strsplit(header[mat],':')[[1]][2])) - } - - GENOtoCSVR <- function(genotypes = '%s', out = 'cross.csvr', phenotype = NULL, sex = NULL, verbose = FALSE){ - header = readLines(genotypes, 40) # Assume a geno header is not longer than 40 lines - toskip = which(unlist(lapply(header, function(x){ length(grep("Chr\t", x)) })) == 1)-1 # Major hack to skip the geno headers - - genocodes <- c(getGenoCode(header, 'mat'), getGenoCode(header, 'het'), getGenoCode(header, 'pat')) # Get the genotype codes - type <- getGenoCode(header, 'type') - genodata <- read.csv(genotypes, sep='\t', skip=toskip, header=TRUE, na.strings=getGenoCode(header,'unk'), colClasses='character', comment.char = '#') - cat('Genodata:', toskip, " ", dim(genodata), genocodes, '\n') - if(is.null(phenotype)) phenotype <- runif((ncol(genodata)-4)) # If there isn't a phenotype, generate a random one - if(is.null(sex)) sex <- rep('m', (ncol(genodata)-4)) # If there isn't a sex phenotype, treat all as males - outCSVR <- rbind(c('Pheno', '', '', phenotype), # Phenotype - c('sex', '', '', sex), # Sex phenotype for the mice - cbind(genodata[,c('Locus','Chr', 'cM')], genodata[, 5:ncol(genodata)])) # Genotypes - write.table(outCSVR, file = out, row.names=FALSE, col.names=FALSE,quote=FALSE, sep=',') # Save it to a file - require(qtl) - cross = read.cross(file=out, 'csvr', genotypes=genocodes) # Load the created cross file using R/qtl read.cross - if(type == 'riset') cross <- convert2riself(cross) # If its a RIL, convert to a RIL in R/qtl - return(cross) - } - """ % (self.dataset.group.name + ".geno")) - - def run_rqtl_geno(self): - self.geno_to_rqtl_function() - - ## Get pointers to some common R functions - r_library = ro.r["library"] # Map the library function - r_c = ro.r["c"] # Map the c function - r_sum = ro.r["sum"] # Map the sum function - plot = ro.r["plot"] # Map the plot function - postscript = ro.r["postscript"] # Map the postscript function - png = ro.r["png"] # Map the png function - dev_off = ro.r["dev.off"] # Map the device off function - - print(r_library("qtl")) # Load R/qtl - - ## Get pointers to some R/qtl functions - scanone = ro.r["scanone"] # Map the scanone function - scantwo = ro.r["scantwo"] # Map the scantwo function - calc_genoprob = ro.r["calc.genoprob"] # Map the calc.genoprob function - read_cross = ro.r["read.cross"] # Map the read.cross function - write_cross = ro.r["write.cross"] # Map the write.cross function - GENOtoCSVR = ro.r["GENOtoCSVR"] # Map the local GENOtoCSVR function - - crossname = self.dataset.group.name - genofilelocation = locate(crossname + ".geno", "genotype") - crossfilelocation = TMPDIR + crossname + ".cross" - - #print("Conversion of geno to cross at location:", genofilelocation, " to ", crossfilelocation) - - cross_object = GENOtoCSVR(genofilelocation, crossfilelocation) # TODO: Add the SEX if that is available - - if self.manhattan_plot: - cross_object = calc_genoprob(cross_object) - else: - cross_object = calc_genoprob(cross_object, step=1, stepwidth="max") - - cross_object = self.add_phenotype(cross_object, self.sanitize_rqtl_phenotype()) # Add the phenotype - - # for debug: write_cross(cross_object, "csvr", "test.csvr") - - # Scan for QTLs - covar = self.create_covariates(cross_object) # Create the additive covariate matrix - - if self.pair_scan: - if self.do_control == "true": # If sum(covar) > 0 we have a covariate matrix - print("Using covariate"); result_data_frame = scantwo(cross_object, pheno = "the_pheno", addcovar = covar, model=self.model, method=self.method, n_cluster = 16) - else: - print("No covariates"); result_data_frame = scantwo(cross_object, pheno = "the_pheno", model=self.model, method=self.method, n_cluster = 16) - - #print("Pair scan results:", result_data_frame) - - self.pair_scan_filename = webqtlUtil.genRandStr("scantwo_") + ".png" - png(file=TEMPDIR+self.pair_scan_filename) - plot(result_data_frame) - dev_off() - - return self.process_pair_scan_results(result_data_frame) - - else: - if self.do_control == "true": - print("Using covariate"); result_data_frame = scanone(cross_object, pheno = "the_pheno", addcovar = covar, model=self.model, method=self.method) - else: - print("No covariates"); result_data_frame = scanone(cross_object, pheno = "the_pheno", model=self.model, method=self.method) - - if self.num_perm > 0 and self.permCheck == "ON": # Do permutation (if requested by user) - if self.do_control == "true": - perm_data_frame = scanone(cross_object, pheno_col = "the_pheno", addcovar = covar, n_perm = self.num_perm, model=self.model, method=self.method) - else: - perm_data_frame = scanone(cross_object, pheno_col = "the_pheno", n_perm = self.num_perm, model=self.model, method=self.method) - - self.process_rqtl_perm_results(perm_data_frame) # Functions that sets the thresholds for the webinterface - - return self.process_rqtl_results(result_data_frame) - - def add_phenotype(self, cross, pheno_as_string): - ro.globalenv["the_cross"] = cross - ro.r('the_cross$pheno <- cbind(pull.pheno(the_cross), the_pheno = '+ pheno_as_string +')') - return ro.r["the_cross"] - - def create_covariates(self, cross): - ro.globalenv["the_cross"] = cross - ro.r('genotypes <- pull.geno(the_cross)') # Get the genotype matrix - userinputS = self.control_marker.replace(" ", "").split(",") # TODO: sanitize user input, Never Ever trust a user - covariate_names = ', '.join('"{0}"'.format(w) for w in userinputS) - #print("Marker names of selected covariates:", covariate_names) - ro.r('covnames <- c(' + covariate_names + ')') - ro.r('covInGeno <- which(covnames %in% colnames(genotypes))') - ro.r('covnames <- covnames[covInGeno]') - ro.r("cat('covnames (purged): ', covnames,'\n')") - ro.r('covariates <- genotypes[,covnames]') # Get the covariate matrix by using the marker name as index to the genotype file - #print("R/qtl matrix of covariates:", ro.r["covariates"]) - return ro.r["covariates"] - - def sanitize_rqtl_phenotype(self): - pheno_as_string = "c(" - for i, val in enumerate(self.vals): - if val == "x": - if i < (len(self.vals) - 1): - pheno_as_string += "NA," - else: - pheno_as_string += "NA" - else: - if i < (len(self.vals) - 1): - pheno_as_string += str(val) + "," - else: - pheno_as_string += str(val) - pheno_as_string += ")" - return pheno_as_string - - def process_pair_scan_results(self, result): - pair_scan_results = [] - - result = result[1] - output = [tuple([result[j][i] for j in range(result.ncol)]) for i in range(result.nrow)] - #print("R/qtl scantwo output:", output) - - for i, line in enumerate(result.iter_row()): - marker = {} - marker['name'] = result.rownames[i] - marker['chr1'] = output[i][0] - marker['Mb'] = output[i][1] - marker['chr2'] = int(output[i][2]) - pair_scan_results.append(marker) - - #print("pair_scan_results:", pair_scan_results) - - return pair_scan_results - - def process_rqtl_results(self, result): # TODO: how to make this a one liner and not copy the stuff in a loop - qtl_results = [] - - output = [tuple([result[j][i] for j in range(result.ncol)]) for i in range(result.nrow)] - #print("R/qtl scanone output:", output) - - for i, line in enumerate(result.iter_row()): - marker = {} - marker['name'] = result.rownames[i] - marker['chr'] = output[i][0] - marker['Mb'] = output[i][1] - marker['lod_score'] = output[i][2] - qtl_results.append(marker) - - return qtl_results - - def process_rqtl_perm_results(self, results): - perm_vals = [] - for line in str(results).split("\n")[1:(self.num_perm+1)]: - #print("R/qtl permutation line:", line.split()) - perm_vals.append(float(line.split()[1])) - - self.perm_output = perm_vals - self.suggestive = np.percentile(np.array(perm_vals), 67) - self.significant = np.percentile(np.array(perm_vals), 95) - - return self.suggestive, self.significant - - def run_plink(self): plink_output_filename = webqtlUtil.genRandStr("%s_%s_"%(self.dataset.group.name, self.this_trait.name)) self.gen_pheno_txt_file_plink(pheno_filename = plink_output_filename) plink_command = PLINK_COMMAND + ' --noweb --ped %s/%s.ped --no-fid --no-parents --no-sex --no-pheno --map %s/%s.map --pheno %s%s.txt --pheno-name %s --maf %s --missing-phenotype -9999 --out %s%s --assoc ' % (PLINK_PATH, self.dataset.group.name, PLINK_PATH, self.dataset.group.name, TMPDIR, plink_output_filename, self.this_trait.name, self.maf, TMPDIR, plink_output_filename) - print("plink_command:", plink_command) + logger.debug("plink_command:", plink_command) os.system(plink_command) @@ -550,11 +379,11 @@ class MarkerRegression(object): #for marker in self.dataset.group.markers.markers: # if marker['name'] not in included_markers: - # print("marker:", marker) + # logger.debug("marker:", marker) # self.dataset.group.markers.markers.remove(marker) # #del self.dataset.group.markers.markers[marker] - print("p_values:", pf(p_values)) + logger.debug("p_values:", pf(p_values)) self.dataset.group.markers.add_pvalues(p_values) @@ -562,7 +391,7 @@ class MarkerRegression(object): def gen_pheno_txt_file_plink(self, pheno_filename = ''): - ped_sample_list = self.get_samples_from_ped_file() + ped_sample_list = self.get_samples_from_ped_file() output_file = open("%s%s.txt" % (TMPDIR, pheno_filename), "wb") header = 'FID\tIID\t%s\n' % self.this_trait.name output_file.write(header) @@ -597,7 +426,7 @@ class MarkerRegression(object): output_file.close() def gen_pheno_txt_file_rqtl(self, pheno_filename = ''): - ped_sample_list = self.get_samples_from_ped_file() + ped_sample_list = self.get_samples_from_ped_file() output_file = open("%s%s.txt" % (TMPDIR, pheno_filename), "wb") header = 'FID\tIID\t%s\n' % self.this_trait.name output_file.write(header) @@ -648,99 +477,6 @@ class MarkerRegression(object): return sample_list - def gen_reaper_results(self): - genotype = self.dataset.group.read_genotype_file() - - if self.manhattan_plot != True: - genotype = genotype.addinterval() - - samples, values, variances, sample_aliases = self.this_trait.export_informative() - - trimmed_samples = [] - trimmed_values = [] - for i in range(0, len(samples)): - if self.this_trait.data[samples[i]].name2 in self.dataset.group.samplelist: - trimmed_samples.append(sample_aliases[i]) - trimmed_values.append(values[i]) - - #print("THE SAMPLES:", trimmed_samples) - - if self.num_perm < 100: - self.suggestive = 0 - self.significant = 0 - else: - self.perm_output = genotype.permutation(strains = trimmed_samples, trait = trimmed_values, nperm=self.num_perm) - self.suggestive = self.perm_output[int(self.num_perm*0.37-1)] - self.significant = self.perm_output[int(self.num_perm*0.95-1)] - self.highly_significant = self.perm_output[int(self.num_perm*0.99-1)] - - self.json_data['suggestive'] = self.suggestive - self.json_data['significant'] = self.significant - - if self.control_marker != "" and self.do_control == "true": - reaper_results = genotype.regression(strains = trimmed_samples, - trait = trimmed_values, - control = str(self.control_marker)) - if self.bootCheck: - control_geno = [] - control_geno2 = [] - _FIND = 0 - for _chr in genotype: - for _locus in _chr: - if _locus.name == self.control_marker: - control_geno2 = _locus.genotype - _FIND = 1 - break - if _FIND: - break - if control_geno2: - _prgy = list(genotype.prgy) - for _strain in trimmed_samples: - _idx = _prgy.index(_strain) - control_geno.append(control_geno2[_idx]) - - self.bootstrap_results = genotype.bootstrap(strains = trimmed_samples, - trait = trimmed_values, - control = control_geno, - nboot = self.num_bootstrap) - else: - reaper_results = genotype.regression(strains = trimmed_samples, - trait = trimmed_values) - - if self.bootCheck: - self.bootstrap_results = genotype.bootstrap(strains = trimmed_samples, - trait = trimmed_values, - nboot = self.num_bootstrap) - - self.json_data['chr'] = [] - self.json_data['pos'] = [] - self.json_data['lod.hk'] = [] - self.json_data['markernames'] = [] - #if self.additive: - # self.json_data['additive'] = [] - - #Need to convert the QTL objects that qtl reaper returns into a json serializable dictionary - qtl_results = [] - for qtl in reaper_results: - reaper_locus = qtl.locus - #ZS: Convert chr to int - converted_chr = reaper_locus.chr - if reaper_locus.chr != "X" and reaper_locus.chr != "X/Y": - converted_chr = int(reaper_locus.chr) - self.json_data['chr'].append(converted_chr) - self.json_data['pos'].append(reaper_locus.Mb) - self.json_data['lod.hk'].append(qtl.lrs) - self.json_data['markernames'].append(reaper_locus.name) - #if self.additive: - # self.json_data['additive'].append(qtl.additive) - locus = {"name":reaper_locus.name, "chr":reaper_locus.chr, "cM":reaper_locus.cM, "Mb":reaper_locus.Mb} - qtl = {"lrs_value": qtl.lrs, "chr":converted_chr, "Mb":reaper_locus.Mb, - "cM":reaper_locus.cM, "name":reaper_locus.name, "additive":qtl.additive, "dominance":qtl.dominance} - qtl_results.append(qtl) - - return qtl_results - - def parse_plink_output(self, output_filename): plink_results={} @@ -821,8 +557,8 @@ class MarkerRegression(object): """Runs permutations and gets significant and suggestive LOD scores""" top_lod_scores = [] - - #print("self.num_perm:", self.num_perm) + + #logger.debug("self.num_perm:", self.num_perm) for permutation in range(self.num_perm): @@ -867,10 +603,10 @@ class MarkerRegression(object): if p_value < lowest_p_value: lowest_p_value = p_value - #print("lowest_p_value:", lowest_p_value) + #logger.debug("lowest_p_value:", lowest_p_value) top_lod_scores.append(-math.log10(lowest_p_value)) - #print("top_lod_scores:", top_lod_scores) + #logger.debug("top_lod_scores:", top_lod_scores) self.suggestive = np.percentile(top_lod_scores, 67) self.significant = np.percentile(top_lod_scores, 95) @@ -878,14 +614,13 @@ class MarkerRegression(object): def gen_data(self, temp_uuid): """Generates p-values for each marker""" - - print("self.vals is:", self.vals) + logger.debug("self.vals is:", self.vals) pheno_vector = np.array([(val == "x" or val == "") and np.nan or float(val) for val in self.vals]) #lmm_uuid = str(uuid.uuid4()) key = "pylmm:input:" + temp_uuid - print("key is:", pf(key)) + logger.debug("key is:", pf(key)) #with Bench("Loading cache"): # result = Redis.get(key) @@ -894,7 +629,7 @@ class MarkerRegression(object): #p_values = self.trim_results(p_values) else: - print("NOW CWD IS:", os.getcwd()) + logger.debug("NOW CWD IS:", os.getcwd()) genotype_data = [marker['genotypes'] for marker in self.dataset.group.markers.markers] no_val_samples = self.identify_empty_samples() @@ -902,9 +637,9 @@ class MarkerRegression(object): genotype_matrix = np.array(genotype_data).T - #print("pheno_vector: ", pf(pheno_vector)) - #print("genotype_matrix: ", pf(genotype_matrix)) - #print("genotype_matrix.shape: ", pf(genotype_matrix.shape)) + #logger.debug("pheno_vector: ", pf(pheno_vector)) + #logger.debug("genotype_matrix: ", pf(genotype_matrix)) + #logger.debug("genotype_matrix.shape: ", pf(genotype_matrix.shape)) #params = {"pheno_vector": pheno_vector, # "genotype_matrix": genotype_matrix, @@ -912,8 +647,8 @@ class MarkerRegression(object): # "refit": False, # "temp_data": tempdata} - # print("genotype_matrix:", str(genotype_matrix.tolist())) - # print("pheno_vector:", str(pheno_vector.tolist())) + # logger.debug("genotype_matrix:", str(genotype_matrix.tolist())) + # logger.debug("pheno_vector:", str(pheno_vector.tolist())) params = dict(pheno_vector = pheno_vector.tolist(), genotype_matrix = genotype_matrix.tolist(), @@ -926,14 +661,14 @@ class MarkerRegression(object): ) json_params = json.dumps(params) - #print("json_params:", json_params) + #logger.debug("json_params:", json_params) Redis.set(key, json_params) Redis.expire(key, 60*60) - print("before printing command") + logger.debug("before printing command") command = PYLMM_COMMAND + ' --key {} --species {}'.format(key, "other") - print("command is:", command) - print("after printing command") + logger.debug("command is:", command) + logger.debug("after printing command") shell(command) @@ -943,7 +678,7 @@ class MarkerRegression(object): json_results = Redis.blpop("pylmm:results:" + temp_uuid, 45*60) results = json.loads(json_results[1]) p_values = [float(result) for result in results['p_values']] - #print("p_values:", p_values[:10]) + #logger.debug("p_values:", p_values[:10]) #p_values = self.trim_results(p_values) t_stats = results['t_stats'] @@ -954,7 +689,7 @@ class MarkerRegression(object): # refit=False, # temp_data=tempdata #) - #print("p_values:", p_values) + #logger.debug("p_values:", p_values) self.dataset.group.markers.add_pvalues(p_values) @@ -963,7 +698,7 @@ class MarkerRegression(object): return self.dataset.group.markers.markers def trim_results(self, p_values): - print("len_p_values:", len(p_values)) + logger.debug("len_p_values:", len(p_values)) if len(p_values) > 500: p_values.sort(reverse=True) trimmed_values = p_values[:500] @@ -982,7 +717,7 @@ class MarkerRegression(object): kinship_matrix = np.fromfile(open(file_base + '.kin','r'),sep=" ") kinship_matrix.resize((len(plink_input.indivs),len(plink_input.indivs))) - print("Before creating params") + logger.debug("Before creating params") params = dict(pheno_vector = pheno_vector.tolist(), covariate_matrix = covariate_matrix.tolist(), @@ -995,18 +730,18 @@ class MarkerRegression(object): timestamp = datetime.datetime.now().isoformat(), ) - print("After creating params") + logger.debug("After creating params") json_params = json.dumps(params) Redis.set(key, json_params) Redis.expire(key, 60*60) - print("Before creating the command") + logger.debug("Before creating the command") command = PYLMM_COMMAND+' --key {} --species {}'.format(key, "human") - print("command is:", command) + logger.debug("command is:", command) os.system(command) @@ -1029,7 +764,7 @@ class MarkerRegression(object): return p_values, t_stats def get_lod_score_cutoff(self): - print("INSIDE GET LOD CUTOFF") + logger.debug("INSIDE GET LOD CUTOFF") high_qtl_count = 0 for marker in self.dataset.group.markers.markers: if marker['lod_score'] > 1: @@ -1087,7 +822,7 @@ def create_snp_iterator_file(group): def trim_markers_for_table(markers): num_markers = len(markers) - + if 'lod_score' in markers[0].keys(): sorted_markers = sorted(markers, key=lambda k: k['lod_score'], reverse=True) else: diff --git a/wqflask/wqflask/marker_regression/marker_regression_gn1.py b/wqflask/wqflask/marker_regression/marker_regression_gn1.py index 33ebc527..bc147f75 100644 --- a/wqflask/wqflask/marker_regression/marker_regression_gn1.py +++ b/wqflask/wqflask/marker_regression/marker_regression_gn1.py @@ -44,6 +44,9 @@ from utility import Plot from wqflask.interval_analyst import GeneUtil from base.webqtlConfig import TMPDIR, GENERATED_TEXT_DIR, GENERATED_IMAGE_DIR +import utility.logger +logger = utility.logger.getLogger(__name__ ) + ######################################### # Inteval Mapping Plot Page ######################################### @@ -159,6 +162,7 @@ class MarkerRegression(object): #if not self.openMysql(): # return + logger.info("Running qtlreaper") #helper_functions.get_species_dataset_trait(self, start_vars) @@ -169,6 +173,7 @@ class MarkerRegression(object): self.species = start_vars['species'] #Needing for form submission when doing single chr mapping or remapping after changing options + self.samples = start_vars['samples'] self.vals = start_vars['vals'] self.mapping_method = start_vars['mapping_method'] if self.mapping_method == "rqtl_geno": @@ -211,6 +216,8 @@ class MarkerRegression(object): else: self.plotScale = "physic" + self.manhattan_plot = start_vars['manhattan_plot'] + if 'permCheck' in start_vars.keys(): self.permChecked = start_vars['permCheck'] else: @@ -260,6 +267,8 @@ class MarkerRegression(object): self.strainlist = self.dataset.group.samplelist self.genotype = self.dataset.group.read_genotype_file() + if self.mapping_method == "reaper" and self.manhattan_plot != True: + self.genotype = self.genotype.addinterval() #Darwing Options try: @@ -282,7 +291,6 @@ class MarkerRegression(object): ## END HaplotypeAnalyst self.graphHeight = self.GRAPH_DEFAULT_HEIGHT - self.manhattan_plot = start_vars['manhattan_plot'] self.dominanceChecked = False self.LRS_LOD = start_vars['LRSCheck'] self.cutoff = start_vars['cutoff'] @@ -505,14 +513,21 @@ class MarkerRegression(object): self.geneCol = None if self.plotScale == 'physic' and self.selectedChr > -1 and (self.intervalAnalystChecked or self.geneChecked): - chrName = self.selectedChr # Draw the genes for this chromosome / region of this chromosome webqtldatabase = self.dataset.name if self.dataset.group.species == "mouse": + if self.selectedChr == 20: + chrName = "X" + else: + chrName = self.selectedChr self.geneCol = GeneUtil.loadGenes(chrName, self.diffCol, self.startMb, self.endMb, webqtldatabase, "mouse") elif self.dataset.group.species == "rat": - self.geneCol = GeneUtil.loadGenes(chrName, self.diffCol, self.startMb, self.endMb, webqtldatabase, "rat") + if self.selectedChr == 21: + chrName = "X" + else: + chrName = self.selectedChr + self.geneCol = GeneUtil.loadGenes(chrName, self.diffCol, self.startMb, self.endMb, webqtldatabase, "rat") if self.geneCol and self.intervalAnalystChecked: ####################################################################### @@ -801,8 +816,8 @@ class MarkerRegression(object): plotXScale = self.drawGraphBackground(canvas, gifmap, offset=newoffset, zoom= zoom, startMb=startMb, endMb = endMb) #draw bootstap - if self.bootChecked and not self.multipleInterval: - self.drawBootStrapResult(canvas, self.nboot, drawAreaHeight, plotXScale, offset=newoffset) + if self.bootChecked and not self.multipleInterval and not self.manhattan_plot: + self.drawBootStrapResult(canvas, self.nboot, drawAreaHeight, plotXScale, offset=newoffset, zoom= zoom, startMb=startMb, endMb = endMb) # Draw clickable region and gene band if selected if self.plotScale == 'physic' and self.selectedChr > -1: @@ -868,7 +883,7 @@ class MarkerRegression(object): for _locus in _chr: if _chr.name == self.ChrList[self.selectedChr][0]: if self.plotScale == 'physic': - Xc = startX + (_locus.Mb-self.startMb)*plotXScale + Xc = startX + (_locus.Mb-startMb)*plotXScale else: Xc = startX + (_locus.cM-_chr[0].cM)*plotXScale BootCoord[-1].append([Xc, self.bootResult[i]]) @@ -1009,7 +1024,7 @@ class MarkerRegression(object): else: locPixel += (Mb*(_chr[-1].cM-_chr[0].cM)/self.ChrLengthCMList[i])*plotXScale break - if locPixel >= 0: + if locPixel >= 0 and self.plotScale == 'physic': traitPixel = ((locPixel, yZero), (locPixel-6, yZero+12), (locPixel+6, yZero+12)) canvas.drawPolygon(traitPixel, edgeColor=pid.black, fillColor=self.TRANSCRIPT_LOCATION_COLOR, closed=1) @@ -1754,6 +1769,7 @@ class MarkerRegression(object): strYLoc + canvas.fontHeight(MBLabelFont)+ 10*(zoom%2) + 10, font=megabaseLabelFont, color=pid.black) pass else: + strYLoc = yZero + spacingFromLabelToAxis + canvas.fontHeight(MBLabelFont) + 8 ChrAInfo = [] preLpos = -1 distinctCount = 0.0 @@ -1840,6 +1856,10 @@ class MarkerRegression(object): canvas.drawLine(startPosX,yZero,startPosX,yZero+40, color=lineColor) startPosX += (self.ChrLengthDistList[j]+self.GraphInterval)*plotXScale + centimorganLabelFont = pid.Font(ttf="verdana", size=18*zoom*1.5, bold=0) + canvas.drawString("Centimorgans", xLeftOffset + (plotWidth - canvas.stringWidth("Megabases", font=centimorganLabelFont))/2, + strYLoc + canvas.fontHeight(MBLabelFont)+ 10*(zoom%2) + 10, font=centimorganLabelFont, color=pid.black) + canvas.drawLine(xLeftOffset, yZero, xLeftOffset+plotWidth, yZero, color=pid.black, width=X_AXIS_THICKNESS) # Draw the X axis itself @@ -2010,7 +2030,7 @@ class MarkerRegression(object): if self.manhattan_plot != True: canvas.drawPolygon(LRSCoordXY,edgeColor=thisLRSColor,closed=0, edgeWidth=lrsEdgeWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth)) - if not self.multipleInterval and self.additiveChecked: + if not self.multipleInterval and not self.manhattan_plot and self.additiveChecked: plusColor = self.ADDITIVE_COLOR_POSITIVE minusColor = self.ADDITIVE_COLOR_NEGATIVE for k, aPoint in enumerate(AdditiveCoordXY): @@ -2855,6 +2875,10 @@ class MarkerRegression(object): polymiRTS = dic[theGO["GeneID"]] # If we have a referenceGene then we will show the Literature Correlation + if theGO["Chromosome"] == "X": + chr_as_int = 19 + else: + chr_as_int = int(theGO["Chromosome"]) - 1 if refGene: try: literatureCorrelation = self.getLiteratureCorrelation(self.cursor,refGene,theGO['GeneID']) @@ -2867,7 +2891,7 @@ class MarkerRegression(object): str(tableIterationsCnt), HT.Href(geneIdString, theGO["GeneSymbol"], target="_blank").__str__() + " " + probeSetSearch.__str__(), HT.Href(mouseStartString, "%0.6f" % txStart, target="_blank").__str__(), - HT.Href("javascript:rangeView('%s', %f, %f)" % (str(int(theGO["Chromosome"])-1), txStart-tenPercentLength, txEnd+tenPercentLength), "%0.3f" % geneLength).__str__(), + HT.Href("javascript:rangeView('%s', %f, %f)" % (str(chr_as_int), txStart-tenPercentLength, txEnd+tenPercentLength), "%0.3f" % geneLength).__str__(), snpString, snpDensityStr, avgExpr, @@ -2898,7 +2922,7 @@ class MarkerRegression(object): str(tableIterationsCnt), HT.Href(geneIdString, theGO["GeneSymbol"], target="_blank").__str__() + " " + probeSetSearch.__str__(), HT.Href(mouseStartString, "%0.6f" % txStart, target="_blank").__str__(), - HT.Href("javascript:rangeView('%s', %f, %f)" % (str(int(theGO["Chromosome"])-1), txStart-tenPercentLength, txEnd+tenPercentLength), "%0.3f" % geneLength).__str__(), + HT.Href("javascript:rangeView('%s', %f, %f)" % (str(chr_as_int), txStart-tenPercentLength, txEnd+tenPercentLength), "%0.3f" % geneLength).__str__(), snpString, snpDensityStr, avgExpr, @@ -2930,15 +2954,20 @@ class MarkerRegression(object): for gIndex, theGO in enumerate(geneCol): this_row = [] #container for the cells of each row - selectCheck = HT.Input(type="checkbox", name="searchResult", Class="checkbox", onClick="highlight(this)") #checkbox for each row + selectCheck = HT.Input(type="checkbox", name="searchResult", Class="checkbox", onClick="highlight(this)").__str__() #checkbox for each row - webqtlSearch = HT.Href(os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE)+"?cmd=sch&gene=%s&alias=1&species=rat" % theGO["GeneSymbol"], HT.Image("/images/webqtl_search.gif", border=0), target="_blank") + webqtlSearch = HT.Href(os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE)+"?cmd=sch&gene=%s&alias=1&species=rat" % theGO["GeneSymbol"], ">>", target="_blank").__str__() if theGO["GeneID"] != "": - geneSymbolNCBI = HT.Href("http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=gene&cmd=Retrieve&dopt=Graphics&list_uids=%s" % theGO["GeneID"], theGO["GeneSymbol"], Class="normalsize", target="_blanK") + geneSymbolNCBI = HT.Href("http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=gene&cmd=Retrieve&dopt=Graphics&list_uids=%s" % theGO["GeneID"], theGO["GeneSymbol"], Class="normalsize", target="_blank").__str__() else: geneSymbolNCBI = theGO["GeneSymbol"] + if theGO["Chromosome"] == "X": + chr_as_int = 20 + else: + chr_as_int = int(theGO["Chromosome"]) - 1 + geneLength = (float(theGO["TxEnd"]) - float(theGO["TxStart"])) #geneLengthURL = "javascript:centerIntervalMapOnRange2('%s', %f, %f, document.changeViewForm)" % (theGO["Chromosome"], float(theGO["TxStart"])-(geneLength*0.1), float(theGO["TxEnd"])+(geneLength*0.1)) geneLengthURL = "javascript:rangeView('%s', %f, %f)" % (theGO["Chromosome"], float(theGO["TxStart"])-(geneLength*0.1), float(theGO["TxEnd"])+(geneLength*0.1)) diff --git a/wqflask/wqflask/marker_regression/qtlreaper_mapping.py b/wqflask/wqflask/marker_regression/qtlreaper_mapping.py new file mode 100644 index 00000000..b072584c --- /dev/null +++ b/wqflask/wqflask/marker_regression/qtlreaper_mapping.py @@ -0,0 +1,93 @@ +def gen_reaper_results(this_trait, dataset, samples_before, json_data, num_perm, bootCheck, num_bootstrap, do_control, control_marker, manhattan_plot): + genotype = dataset.group.read_genotype_file() + + if manhattan_plot != True: + genotype = genotype.addinterval() + + samples, values, variances, sample_aliases = this_trait.export_informative() + + trimmed_samples = [] + trimmed_values = [] + for i in range(0, len(samples)): + if this_trait.data[samples[i]].name in samples_before: + trimmed_samples.append(samples[i]) + trimmed_values.append(values[i]) + + perm_output = [] + bootstrap_results = [] + + if num_perm < 100: + suggestive = 0 + significant = 0 + else: + perm_output = genotype.permutation(strains = trimmed_samples, trait = trimmed_values, nperm=num_perm) + suggestive = perm_output[int(num_perm*0.37-1)] + significant = perm_output[int(num_perm*0.95-1)] + highly_significant = perm_output[int(num_perm*0.99-1)] + + json_data['suggestive'] = suggestive + json_data['significant'] = significant + + if control_marker != "" and do_control == "true": + reaper_results = genotype.regression(strains = trimmed_samples, + trait = trimmed_values, + control = str(control_marker)) + if bootCheck: + control_geno = [] + control_geno2 = [] + _FIND = 0 + for _chr in genotype: + for _locus in _chr: + if _locus.name == control_marker: + control_geno2 = _locus.genotype + _FIND = 1 + break + if _FIND: + break + if control_geno2: + _prgy = list(genotype.prgy) + for _strain in trimmed_samples: + _idx = _prgy.index(_strain) + control_geno.append(control_geno2[_idx]) + + bootstrap_results = genotype.bootstrap(strains = trimmed_samples, + trait = trimmed_values, + control = control_geno, + nboot = num_bootstrap) + else: + reaper_results = genotype.regression(strains = trimmed_samples, + trait = trimmed_values) + + if bootCheck: + bootstrap_results = genotype.bootstrap(strains = trimmed_samples, + trait = trimmed_values, + nboot = num_bootstrap) + + json_data['chr'] = [] + json_data['pos'] = [] + json_data['lod.hk'] = [] + json_data['markernames'] = [] + #if self.additive: + # self.json_data['additive'] = [] + + #Need to convert the QTL objects that qtl reaper returns into a json serializable dictionary + qtl_results = [] + for qtl in reaper_results: + reaper_locus = qtl.locus + #ZS: Convert chr to int + converted_chr = reaper_locus.chr + if reaper_locus.chr != "X" and reaper_locus.chr != "X/Y": + converted_chr = int(reaper_locus.chr) + json_data['chr'].append(converted_chr) + json_data['pos'].append(reaper_locus.Mb) + json_data['lod.hk'].append(qtl.lrs) + json_data['markernames'].append(reaper_locus.name) + #if self.additive: + # self.json_data['additive'].append(qtl.additive) + locus = {"name":reaper_locus.name, "chr":reaper_locus.chr, "cM":reaper_locus.cM, "Mb":reaper_locus.Mb} + qtl = {"lrs_value": qtl.lrs, "chr":converted_chr, "Mb":reaper_locus.Mb, + "cM":reaper_locus.cM, "name":reaper_locus.name, "additive":qtl.additive, "dominance":qtl.dominance} + qtl_results.append(qtl) + + + return qtl_results, json_data, perm_output, suggestive, significant, bootstrap_results diff --git a/wqflask/wqflask/marker_regression/rqtl_mapping.py b/wqflask/wqflask/marker_regression/rqtl_mapping.py new file mode 100644 index 00000000..93bf717c --- /dev/null +++ b/wqflask/wqflask/marker_regression/rqtl_mapping.py @@ -0,0 +1,193 @@ +import rpy2.robjects as ro
+import numpy as np
+
+from base.webqtlConfig import TMPDIR
+from utility import webqtlUtil
+from utility.tools import locate, TEMPDIR
+
+def run_rqtl_geno(vals, dataset, method, model, permCheck, num_perm, do_control, control_marker, manhattan_plot, pair_scan):
+ geno_to_rqtl_function(dataset)
+
+ ## Get pointers to some common R functions
+ r_library = ro.r["library"] # Map the library function
+ r_c = ro.r["c"] # Map the c function
+ r_sum = ro.r["sum"] # Map the sum function
+ plot = ro.r["plot"] # Map the plot function
+ postscript = ro.r["postscript"] # Map the postscript function
+ png = ro.r["png"] # Map the png function
+ dev_off = ro.r["dev.off"] # Map the device off function
+
+ print(r_library("qtl")) # Load R/qtl
+
+ ## Get pointers to some R/qtl functions
+ scanone = ro.r["scanone"] # Map the scanone function
+ scantwo = ro.r["scantwo"] # Map the scantwo function
+ calc_genoprob = ro.r["calc.genoprob"] # Map the calc.genoprob function
+ read_cross = ro.r["read.cross"] # Map the read.cross function
+ write_cross = ro.r["write.cross"] # Map the write.cross function
+ GENOtoCSVR = ro.r["GENOtoCSVR"] # Map the local GENOtoCSVR function
+
+ crossname = dataset.group.name
+ genofilelocation = locate(crossname + ".geno", "genotype")
+ crossfilelocation = TMPDIR + crossname + ".cross"
+
+ #print("Conversion of geno to cross at location:", genofilelocation, " to ", crossfilelocation)
+
+ cross_object = GENOtoCSVR(genofilelocation, crossfilelocation) # TODO: Add the SEX if that is available
+
+ if manhattan_plot:
+ cross_object = calc_genoprob(cross_object)
+ else:
+ cross_object = calc_genoprob(cross_object, step=1, stepwidth="max")
+
+ cross_object = add_phenotype(cross_object, sanitize_rqtl_phenotype(vals)) # Add the phenotype
+
+ # for debug: write_cross(cross_object, "csvr", "test.csvr")
+
+ # Scan for QTLs
+ covar = create_covariates(control_marker, cross_object) # Create the additive covariate matrix
+
+ if pair_scan:
+ if do_control == "true": # If sum(covar) > 0 we have a covariate matrix
+ print("Using covariate"); result_data_frame = scantwo(cross_object, pheno = "the_pheno", addcovar = covar, model=model, method=method, n_cluster = 16)
+ else:
+ print("No covariates"); result_data_frame = scantwo(cross_object, pheno = "the_pheno", model=model, method=method, n_cluster = 16)
+
+ #print("Pair scan results:", result_data_frame)
+
+ pair_scan_filename = webqtlUtil.genRandStr("scantwo_") + ".png"
+ png(file=TEMPDIR+pair_scan_filename)
+ plot(result_data_frame)
+ dev_off()
+
+ return process_pair_scan_results(result_data_frame)
+ else:
+ if do_control == "true":
+ print("Using covariate"); result_data_frame = scanone(cross_object, pheno = "the_pheno", addcovar = covar, model=model, method=method)
+ else:
+ print("No covariates"); result_data_frame = scanone(cross_object, pheno = "the_pheno", model=model, method=method)
+
+ if num_perm > 0 and permCheck == "ON": # Do permutation (if requested by user)
+ if do_control == "true":
+ perm_data_frame = scanone(cross_object, pheno_col = "the_pheno", addcovar = covar, n_perm = num_perm, model=model, method=method)
+ else:
+ perm_data_frame = scanone(cross_object, pheno_col = "the_pheno", n_perm = num_perm, model=model, method=method)
+
+ perm_output, suggestive, significant = process_rqtl_perm_results(num_perm, perm_data_frame) # Functions that sets the thresholds for the webinterface
+ return perm_output, suggestive, significant, process_rqtl_results(result_data_frame)
+ else:
+ return process_rqtl_results(result_data_frame)
+
+def geno_to_rqtl_function(dataset): # TODO: Need to figure out why some genofiles have the wrong format and don't convert properly
+
+ ro.r("""
+ trim <- function( x ) { gsub("(^[[:space:]]+|[[:space:]]+$)", "", x) }
+
+ getGenoCode <- function(header, name = 'unk'){
+ mat = which(unlist(lapply(header,function(x){ length(grep(paste('@',name,sep=''), x)) })) == 1)
+ return(trim(strsplit(header[mat],':')[[1]][2]))
+ }
+
+ GENOtoCSVR <- function(genotypes = '%s', out = 'cross.csvr', phenotype = NULL, sex = NULL, verbose = FALSE){
+ header = readLines(genotypes, 40) # Assume a geno header is not longer than 40 lines
+ toskip = which(unlist(lapply(header, function(x){ length(grep("Chr\t", x)) })) == 1)-1 # Major hack to skip the geno headers
+
+ genocodes <- c(getGenoCode(header, 'mat'), getGenoCode(header, 'het'), getGenoCode(header, 'pat')) # Get the genotype codes
+ type <- getGenoCode(header, 'type')
+ genodata <- read.csv(genotypes, sep='\t', skip=toskip, header=TRUE, na.strings=getGenoCode(header,'unk'), colClasses='character', comment.char = '#')
+ cat('Genodata:', toskip, " ", dim(genodata), genocodes, '\n')
+ if(is.null(phenotype)) phenotype <- runif((ncol(genodata)-4)) # If there isn't a phenotype, generate a random one
+ if(is.null(sex)) sex <- rep('m', (ncol(genodata)-4)) # If there isn't a sex phenotype, treat all as males
+ outCSVR <- rbind(c('Pheno', '', '', phenotype), # Phenotype
+ c('sex', '', '', sex), # Sex phenotype for the mice
+ cbind(genodata[,c('Locus','Chr', 'cM')], genodata[, 5:ncol(genodata)])) # Genotypes
+ write.table(outCSVR, file = out, row.names=FALSE, col.names=FALSE,quote=FALSE, sep=',') # Save it to a file
+ require(qtl)
+ cross = read.cross(file=out, 'csvr', genotypes=genocodes) # Load the created cross file using R/qtl read.cross
+ if(type == 'riset') cross <- convert2riself(cross) # If its a RIL, convert to a RIL in R/qtl
+ return(cross)
+ }
+ """ % (dataset.group.name + ".geno"))
+
+def add_phenotype(cross, pheno_as_string):
+ ro.globalenv["the_cross"] = cross
+ ro.r('the_cross$pheno <- cbind(pull.pheno(the_cross), the_pheno = '+ pheno_as_string +')')
+ return ro.r["the_cross"]
+
+def create_covariates(control_marker, cross):
+ ro.globalenv["the_cross"] = cross
+ ro.r('genotypes <- pull.geno(the_cross)') # Get the genotype matrix
+ userinputS = control_marker.replace(" ", "").split(",") # TODO: sanitize user input, Never Ever trust a user
+ covariate_names = ', '.join('"{0}"'.format(w) for w in userinputS)
+ #print("Marker names of selected covariates:", covariate_names)
+ ro.r('covnames <- c(' + covariate_names + ')')
+ ro.r('covInGeno <- which(covnames %in% colnames(genotypes))')
+ ro.r('covnames <- covnames[covInGeno]')
+ ro.r("cat('covnames (purged): ', covnames,'\n')")
+ ro.r('covariates <- genotypes[,covnames]') # Get the covariate matrix by using the marker name as index to the genotype file
+ #print("R/qtl matrix of covariates:", ro.r["covariates"])
+ return ro.r["covariates"]
+
+def sanitize_rqtl_phenotype(vals):
+ pheno_as_string = "c("
+ for i, val in enumerate(vals):
+ if val == "x":
+ if i < (len(vals) - 1):
+ pheno_as_string += "NA,"
+ else:
+ pheno_as_string += "NA"
+ else:
+ if i < (len(vals) - 1):
+ pheno_as_string += str(val) + ","
+ else:
+ pheno_as_string += str(val)
+ pheno_as_string += ")"
+ return pheno_as_string
+
+def process_pair_scan_results(result):
+ pair_scan_results = []
+
+ result = result[1]
+ output = [tuple([result[j][i] for j in range(result.ncol)]) for i in range(result.nrow)]
+ #print("R/qtl scantwo output:", output)
+
+ for i, line in enumerate(result.iter_row()):
+ marker = {}
+ marker['name'] = result.rownames[i]
+ marker['chr1'] = output[i][0]
+ marker['Mb'] = output[i][1]
+ marker['chr2'] = int(output[i][2])
+ pair_scan_results.append(marker)
+
+ #print("pair_scan_results:", pair_scan_results)
+
+ return pair_scan_results
+
+def process_rqtl_perm_results(num_perm, results):
+ perm_vals = []
+ for line in str(results).split("\n")[1:(num_perm+1)]:
+ #print("R/qtl permutation line:", line.split())
+ perm_vals.append(float(line.split()[1]))
+
+ perm_output = perm_vals
+ suggestive = np.percentile(np.array(perm_vals), 67)
+ significant = np.percentile(np.array(perm_vals), 95)
+ print("SIGNIFICANT:", significant)
+
+ return perm_output, suggestive, significant
+
+def process_rqtl_results(result): # TODO: how to make this a one liner and not copy the stuff in a loop
+ qtl_results = []
+
+ output = [tuple([result[j][i] for j in range(result.ncol)]) for i in range(result.nrow)]
+ #print("R/qtl scanone output:", output)
+
+ for i, line in enumerate(result.iter_row()):
+ marker = {}
+ marker['name'] = result.rownames[i]
+ marker['chr'] = output[i][0]
+ marker['Mb'] = output[i][1]
+ marker['lod_score'] = output[i][2]
+ qtl_results.append(marker)
+
+ return qtl_results
\ No newline at end of file diff --git a/wqflask/wqflask/model.py b/wqflask/wqflask/model.py index 3b480e0c..5321e420 100644 --- a/wqflask/wqflask/model.py +++ b/wqflask/wqflask/model.py @@ -83,7 +83,7 @@ class User(Base): def get_collection_by_name(self, collection_name): try: - collect = self.user_collections.filter_by(name=collection_name).one() + collect = self.user_collections.filter_by(name=collection_name).first() except sqlalchemy.orm.exc.NoResultFound: collect = None return collect @@ -177,12 +177,10 @@ class UserCollection(Base): except: return 0 - #@property #def display_num_members(self): # return display_collapsible(self.num_members) - def members_as_set(self): return set(json.loads(self.members)) diff --git a/wqflask/wqflask/network_graph/__init__.py b/wqflask/wqflask/network_graph/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/wqflask/wqflask/network_graph/__init__.py diff --git a/wqflask/wqflask/network_graph/network_graph.py b/wqflask/wqflask/network_graph/network_graph.py new file mode 100644 index 00000000..cebe5c03 --- /dev/null +++ b/wqflask/wqflask/network_graph/network_graph.py @@ -0,0 +1,224 @@ +## Copyright (C) University of Tennessee Health Science Center, Memphis, TN. +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU Affero General Public License +# as published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Affero General Public License for more details. +# +# This program is available from Source Forge: at GeneNetwork Project +# (sourceforge.net/projects/genenetwork/). +# +# Contact Dr. Robert W. Williams at rwilliams@uthsc.edu +# +# +# This module is used by GeneNetwork project (www.genenetwork.org) + +from __future__ import absolute_import, print_function, division + +import sys +# sys.path.append(".") Never do this in a webserver! + +import gc +import string +import cPickle +import os +import time +import pp +import math +import collections +import resource + +import scipy + +import simplejson as json + +from rpy2.robjects.packages import importr +import rpy2.robjects as robjects + +from pprint import pformat as pf + +from htmlgen import HTMLgen2 as HT +import reaper + +from utility.THCell import THCell +from utility.TDCell import TDCell +from base.trait import GeneralTrait +from base import data_set +from utility import webqtlUtil, helper_functions, corr_result_helpers +from db import webqtlDatabaseFunction +import utility.webqtlUtil #this is for parallel computing only. +from wqflask.correlation import correlation_functions +from utility.benchmark import Bench + +from MySQLdb import escape_string as escape + +from pprint import pformat as pf + +from flask import Flask, g + + +class NetworkGraph(object): + + def __init__(self, start_vars): + trait_db_list = [trait.strip() for trait in start_vars['trait_list'].split(',')] + + helper_functions.get_trait_db_obs(self, trait_db_list) + + self.all_sample_list = [] + self.traits = [] + for trait_db in self.trait_list: + this_trait = trait_db[0] + self.traits.append(this_trait) + this_sample_data = this_trait.data + + for sample in this_sample_data: + if sample not in self.all_sample_list: + self.all_sample_list.append(sample) + + self.sample_data = [] + for trait_db in self.trait_list: + this_trait = trait_db[0] + this_sample_data = this_trait.data + + this_trait_vals = [] + for sample in self.all_sample_list: + if sample in this_sample_data: + this_trait_vals.append(this_sample_data[sample].value) + else: + this_trait_vals.append('') + self.sample_data.append(this_trait_vals) + + self.lowest_overlap = 8 #ZS: Variable set to the lowest overlapping samples in order to notify user, or 8, whichever is lower (since 8 is when we want to display warning) + + self.network_data = {} + self.nodes_list = [] + self.edges_list = [] + for trait_db in self.trait_list: + this_trait = trait_db[0] + this_db = trait_db[1] + + this_db_samples = this_db.group.samplelist + this_sample_data = this_trait.data + + corr_result_row = [] + is_spearman = False #ZS: To determine if it's above or below the diagonal + + max_corr = 0 #ZS: Used to determine whether node should be hidden when correlation coefficient slider is used + + for target in self.trait_list: + target_trait = target[0] + target_db = target[1] + target_samples = target_db.group.samplelist + + target_sample_data = target_trait.data + + this_trait_vals = [] + target_vals = [] + for index, sample in enumerate(target_samples): + + if (sample in this_sample_data) and (sample in target_sample_data): + sample_value = this_sample_data[sample].value + target_sample_value = target_sample_data[sample].value + this_trait_vals.append(sample_value) + target_vals.append(target_sample_value) + + this_trait_vals, target_vals, num_overlap = corr_result_helpers.normalize_values(this_trait_vals, target_vals) + + if num_overlap < self.lowest_overlap: + self.lowest_overlap = num_overlap + if num_overlap == 0: + continue + else: + pearson_r, pearson_p = scipy.stats.pearsonr(this_trait_vals, target_vals) + if is_spearman == False: + sample_r, sample_p = pearson_r, pearson_p + if sample_r == 1: + continue + else: + sample_r, sample_p = scipy.stats.spearmanr(this_trait_vals, target_vals) + + if -1 <= sample_r < -0.7: + color = "#0000ff" + width = 3 + elif -0.7 <= sample_r < -0.5: + color = "#00ff00" + width = 2 + elif -0.5 <= sample_r < 0: + color = "#000000" + width = 0.5 + elif 0 <= sample_r < 0.5: + color = "#ffc0cb" + width = 0.5 + elif 0.5 <= sample_r < 0.7: + color = "#ffa500" + width = 2 + elif 0.7 <= sample_r <= 1: + color = "#ff0000" + width = 3 + else: + color = "#000000" + width = 0 + + if abs(sample_r) > max_corr: + max_corr = abs(sample_r) + + edge_data = {'id' : str(this_trait.name) + '_to_' + str(target_trait.name), + 'source' : str(this_trait.name) + ":" + str(this_trait.dataset.name), + 'target' : str(target_trait.name) + ":" + str(target_trait.dataset.name), + 'correlation' : round(sample_r, 3), + 'abs_corr' : abs(round(sample_r, 3)), + 'p_value' : round(sample_p, 3), + 'overlap' : num_overlap, + 'color' : color, + 'width' : width } + + edge_dict = { 'data' : edge_data } + + self.edges_list.append(edge_dict) + + node_dict = { 'data' : {'id' : str(this_trait.name) + ":" + str(this_trait.dataset.name), + 'label' : this_trait.name, + 'symbol' : this_trait.symbol, + 'geneid' : this_trait.geneid, + 'omim' : this_trait.omim, + 'max_corr' : max_corr } } + self.nodes_list.append(node_dict) + + #self.network_data['dataSchema'] = {'nodes' : [{'name' : "label" , 'type' : "string"}], + # 'edges' : [{'name' : "label" , 'type' : "string"}] } + + #self.network_data['data'] = {'nodes' : self.nodes_list, + # 'edges' : self.edges_list } + + self.elements = json.dumps(self.nodes_list + self.edges_list) + + groups = [] + for sample in self.all_sample_list: + groups.append(1) + + self.js_data = dict(traits = [trait.name for trait in self.traits], + groups = groups, + cols = range(len(self.traits)), + rows = range(len(self.traits)), + samples = self.all_sample_list, + sample_data = self.sample_data, + elements = self.elements,) + # corr_results = [result[1] for result in result_row for result_row in self.corr_results]) + + def get_trait_db_obs(self, trait_db_list): + + self.trait_list = [] + for i, trait_db in enumerate(trait_db_list): + if i == (len(trait_db_list) - 1): + break + trait_name, dataset_name = trait_db.split(":") + dataset_ob = data_set.create_dataset(dataset_name) + trait_ob = GeneralTrait(dataset=dataset_ob, + name=trait_name, + cellid=None) + self.trait_list.append((trait_ob, dataset_ob)) diff --git a/wqflask/wqflask/show_trait/show_trait.py b/wqflask/wqflask/show_trait/show_trait.py index 912beabe..d9617c7c 100644 --- a/wqflask/wqflask/show_trait/show_trait.py +++ b/wqflask/wqflask/show_trait/show_trait.py @@ -23,8 +23,7 @@ from basicStatistics import BasicStatisticsFunctions from pprint import pformat as pf -from utility.tools import flat_files -MAPPING_PATH = flat_files("mapping") +from utility.tools import flat_files, flat_file_exists from utility.logger import getLogger logger = getLogger(__name__ ) @@ -163,11 +162,12 @@ class ShowTrait(object): def get_mapping_methods(self): '''Only display mapping methods when the dataset group's genotype file exists''' def check_plink_gemma(): - if (os.path.isfile(MAPPING_PATH+"/"+self.dataset.group.name+".bed") and - os.path.isfile(MAPPING_PATH+"/"+self.dataset.group.name+".map")): - return True - else: - return False + if flat_file_exists("mapping"): + MAPPING_PATH = flat_files("mapping")+"/" + if (os.path.isfile(MAPPING_PATH+self.dataset.group.name+".bed") and + os.path.isfile(MAPPING_PATH+self.dataset.group.name+".map")): + return True + return False def check_pylmm_rqtl(): if os.path.isfile(webqtlConfig.GENODIR+self.dataset.group.name+".geno") and (os.path.getsize(webqtlConfig.JSON_GENODIR+self.dataset.group.name+".json") > 0): diff --git a/wqflask/wqflask/static/gif/error/Wild-Type-Mouse.gif b/wqflask/wqflask/static/gif/error/Wild-Type-Mouse.gif Binary files differnew file mode 100644 index 00000000..2c68b5ee --- /dev/null +++ b/wqflask/wqflask/static/gif/error/Wild-Type-Mouse.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-aliens-29.gif b/wqflask/wqflask/static/gif/error/animated-gifs-aliens-29.gif Binary files differnew file mode 100644 index 00000000..e9d38277 --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-aliens-29.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-angels-04.gif b/wqflask/wqflask/static/gif/error/animated-gifs-angels-04.gif Binary files differnew file mode 100644 index 00000000..94e11847 --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-angels-04.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-cats-016.gif b/wqflask/wqflask/static/gif/error/animated-gifs-cats-016.gif Binary files differnew file mode 100644 index 00000000..7e6ec9a3 --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-cats-016.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-cats-031.gif b/wqflask/wqflask/static/gif/error/animated-gifs-cats-031.gif Binary files differnew file mode 100644 index 00000000..af7ef655 --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-cats-031.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-cell-phones-03.gif b/wqflask/wqflask/static/gif/error/animated-gifs-cell-phones-03.gif Binary files differnew file mode 100644 index 00000000..89c79ddf --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-cell-phones-03.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-cell-phones-16.gif b/wqflask/wqflask/static/gif/error/animated-gifs-cell-phones-16.gif Binary files differnew file mode 100644 index 00000000..7530d180 --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-cell-phones-16.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-computers-13.gif b/wqflask/wqflask/static/gif/error/animated-gifs-computers-13.gif Binary files differnew file mode 100644 index 00000000..afb05c62 --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-computers-13.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-computers-28.gif b/wqflask/wqflask/static/gif/error/animated-gifs-computers-28.gif Binary files differnew file mode 100644 index 00000000..f5b4a563 --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-computers-28.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-computers-32.gif b/wqflask/wqflask/static/gif/error/animated-gifs-computers-32.gif Binary files differnew file mode 100644 index 00000000..7258e594 --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-computers-32.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-computers-42.gif b/wqflask/wqflask/static/gif/error/animated-gifs-computers-42.gif Binary files differnew file mode 100644 index 00000000..ed1f8722 --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-computers-42.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-computers-60.gif b/wqflask/wqflask/static/gif/error/animated-gifs-computers-60.gif Binary files differnew file mode 100644 index 00000000..f58d69f1 --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-computers-60.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-computers-64.gif b/wqflask/wqflask/static/gif/error/animated-gifs-computers-64.gif Binary files differnew file mode 100644 index 00000000..5d5b4fdf --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-computers-64.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-computers-65.gif b/wqflask/wqflask/static/gif/error/animated-gifs-computers-65.gif Binary files differnew file mode 100644 index 00000000..b4b10845 --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-computers-65.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-computers-72.gif b/wqflask/wqflask/static/gif/error/animated-gifs-computers-72.gif Binary files differnew file mode 100644 index 00000000..e60cb4fe --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-computers-72.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-computers-74.gif b/wqflask/wqflask/static/gif/error/animated-gifs-computers-74.gif Binary files differnew file mode 100644 index 00000000..bd7b72f3 --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-computers-74.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-computers-75.gif b/wqflask/wqflask/static/gif/error/animated-gifs-computers-75.gif Binary files differnew file mode 100644 index 00000000..916d6b33 --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-computers-75.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-construction-sites-038.gif b/wqflask/wqflask/static/gif/error/animated-gifs-construction-sites-038.gif Binary files differnew file mode 100644 index 00000000..0ec782c4 --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-construction-sites-038.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-dogs-04.gif b/wqflask/wqflask/static/gif/error/animated-gifs-dogs-04.gif Binary files differnew file mode 100644 index 00000000..9515c18a --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-dogs-04.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-dogs-14.gif b/wqflask/wqflask/static/gif/error/animated-gifs-dogs-14.gif Binary files differnew file mode 100644 index 00000000..f1e2e1f5 --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-dogs-14.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-dogs-18.gif b/wqflask/wqflask/static/gif/error/animated-gifs-dogs-18.gif Binary files differnew file mode 100644 index 00000000..572849d5 --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-dogs-18.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-dogs-47.gif b/wqflask/wqflask/static/gif/error/animated-gifs-dogs-47.gif Binary files differnew file mode 100644 index 00000000..d808c9ee --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-dogs-47.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-dogs-50.gif b/wqflask/wqflask/static/gif/error/animated-gifs-dogs-50.gif Binary files differnew file mode 100644 index 00000000..9865ee45 --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-dogs-50.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-lava-lamps-01.gif b/wqflask/wqflask/static/gif/error/animated-gifs-lava-lamps-01.gif Binary files differnew file mode 100644 index 00000000..ee9c113d --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-lava-lamps-01.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-mice-02.gif b/wqflask/wqflask/static/gif/error/animated-gifs-mice-02.gif Binary files differnew file mode 100644 index 00000000..5ca2ee5c --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-mice-02.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-mice-09.gif b/wqflask/wqflask/static/gif/error/animated-gifs-mice-09.gif Binary files differnew file mode 100644 index 00000000..7cb361e4 --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-mice-09.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-mice-24.gif b/wqflask/wqflask/static/gif/error/animated-gifs-mice-24.gif Binary files differnew file mode 100644 index 00000000..96a26450 --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-mice-24.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-smileys-063.gif b/wqflask/wqflask/static/gif/error/animated-gifs-smileys-063.gif Binary files differnew file mode 100644 index 00000000..62de166c --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-smileys-063.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-smileys-068.gif b/wqflask/wqflask/static/gif/error/animated-gifs-smileys-068.gif Binary files differnew file mode 100644 index 00000000..3550e978 --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-smileys-068.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-smileys-134.gif b/wqflask/wqflask/static/gif/error/animated-gifs-smileys-134.gif Binary files differnew file mode 100644 index 00000000..954ab614 --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-smileys-134.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-smileys-211.gif b/wqflask/wqflask/static/gif/error/animated-gifs-smileys-211.gif Binary files differnew file mode 100644 index 00000000..596174d7 --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-smileys-211.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-smileys-234.gif b/wqflask/wqflask/static/gif/error/animated-gifs-smileys-234.gif Binary files differnew file mode 100644 index 00000000..5aba636b --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-smileys-234.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-001.gif b/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-001.gif Binary files differnew file mode 100644 index 00000000..7896ff1f --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-001.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-002.gif b/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-002.gif Binary files differnew file mode 100644 index 00000000..89da6441 --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-002.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-005.gif b/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-005.gif Binary files differnew file mode 100644 index 00000000..b7887630 --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-005.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-012.gif b/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-012.gif Binary files differnew file mode 100644 index 00000000..f6697d02 --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-012.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-056.gif b/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-056.gif Binary files differnew file mode 100644 index 00000000..2b2496a4 --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-056.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-059.gif b/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-059.gif Binary files differnew file mode 100644 index 00000000..f2188656 --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-059.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-060.gif b/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-060.gif Binary files differnew file mode 100644 index 00000000..aa8f7bd3 --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-060.gif diff --git a/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-069.gif b/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-069.gif Binary files differnew file mode 100644 index 00000000..473212e4 --- /dev/null +++ b/wqflask/wqflask/static/gif/error/animated-gifs-stickmen-069.gif diff --git a/wqflask/wqflask/static/new/css/network_graph.css b/wqflask/wqflask/static/new/css/network_graph.css new file mode 100644 index 00000000..1cba546a --- /dev/null +++ b/wqflask/wqflask/static/new/css/network_graph.css @@ -0,0 +1,38 @@ +#content h2, h3, h4, h5, h6 { + color: #545454; + margin-bottom: 1em; + border-bottom: dashed 1px #dfdfdf; + padding-bottom: 0.3em; +} + +#content table td { + padding: 0.5em; + /* border-right: solid 1px #fff; */ +} + +#secondaryContent { + position: relative; + float: left; + width: 18.5em; + padding: 1em 1em 1em 1em; + background: #fff url('/static/new/images/a1.gif') top right repeat-y; +} + + +input[type="button" i], input[type="submit" i], input[type="reset" i], input[type="file" i]::-webkit-file-upload-button, button { + align-items: flex-start; + text-align: center; + cursor: default; + color: buttontext; + border-image-source: initial; + border-image-slice: initial; + border-image-width: initial; + border-image-outset: initial; + border-image-repeat: initial; + background-color: buttonface; + box-sizing: border-box; + padding: 2px 6px 3px; + border-width: 2px; + border-style: outset; + border-color: buttonface; +}
\ No newline at end of file diff --git a/wqflask/wqflask/static/new/javascript/dataset_menu_structure.json b/wqflask/wqflask/static/new/javascript/dataset_menu_structure.json index 4ff90ca8..d3db1853 100644 --- a/wqflask/wqflask/static/new/javascript/dataset_menu_structure.json +++ b/wqflask/wqflask/static/new/javascript/dataset_menu_structure.json @@ -317,6 +317,30 @@ ] }, "GTEx": { + "Adipose tissue, subcutaneous mRNA": [ + [ + "580", + "GTEx_log2_Subcu_0314", + "GTEx Human Subcutaneous (Mar14) RPKM Log2" + ], + [ + "530", + "GTEx_Subcu_0414", + "GTEx Human Subcutaneous (Apr14) RPKM" + ] + ], + "Adipose tissue, visceral mRNA": [ + [ + "587", + "GTEx_log2_Visce_0314", + "GTEx Human Visceral (Mar14) RPKM Log2" + ], + [ + "537", + "GTEx_Visce_0414", + "GTEx Human Visceral (Apr14) RPKM" + ] + ], "Adrenal Gland mRNA": [ [ "545", @@ -773,18 +797,6 @@ "GTEx Human Stomach (Apr14) RPKM" ] ], - "Subcutaneous mRNA": [ - [ - "580", - "GTEx_log2_Subcu_0314", - "GTEx Human Subcutaneous (Mar14) RPKM Log2" - ], - [ - "530", - "GTEx_Subcu_0414", - "GTEx Human Subcutaneous (Apr14) RPKM" - ] - ], "Substantia Nigra mRNA": [ [ "581", @@ -857,18 +869,6 @@ "GTEx Human Vagina (Apr14) RPKM" ] ], - "Visceral mRNA": [ - [ - "587", - "GTEx_log2_Visce_0314", - "GTEx Human Visceral (Mar14) RPKM Log2" - ], - [ - "537", - "GTEx_Visce_0414", - "GTEx Human Visceral (Apr14) RPKM" - ] - ], "Whole Blood mRNA": [ [ "588", @@ -883,6 +883,20 @@ ] }, "GTEx_v5": { + "Adipose tissue, subcutaneous mRNA": [ + [ + "718", + "GTEXv5_AdipSub_0915", + "GTEXv5 Human Adipose Subcutaneous RefSeq (Sep15) RPKM log2" + ] + ], + "Adipose tissue, visceral mRNA": [ + [ + "719", + "GTEXv5_AdiVis_0915", + "GTEXv5 Human Adipose Visceral Omentum RefSeq (Sep15) RPKM log2" + ] + ], "Adrenal Gland mRNA": [ [ "720", @@ -1191,13 +1205,6 @@ "GTEXv5 Human Stomach RefSeq (Sep15) RPKM log2" ] ], - "Subcutaneous mRNA": [ - [ - "718", - "GTEXv5_AdipSub_0915", - "GTEXv5 Human Adipose Subcutaneous RefSeq (Sep15) RPKM log2" - ] - ], "Substantia Nigra mRNA": [ [ "737", @@ -1240,13 +1247,6 @@ "GTEXv5 Human Vagina RefSeq (Sep15) RPKM log2" ] ], - "Visceral mRNA": [ - [ - "719", - "GTEXv5_AdiVis_0915", - "GTEXv5 Human Adipose Visceral Omentum RefSeq (Sep15) RPKM log2" - ] - ], "Whole Blood mRNA": [ [ "770", @@ -1492,6 +1492,22 @@ "Human Ventrolateral Prefrontal Cortex Affy Hu-Exon 1.0 ST (Jul11) Quantile" ] ] + }, + "TIGEM-Retina-RNA-Seq": { + "Phenotypes": [ + [ + "None", + "TIGEM-Retina-RNA-SeqPublish", + "TIGEM-Retina-RNA-Seq Published Phenotypes" + ] + ], + "Retina mRNA": [ + [ + "802", + "TIGEM_hg38_ret_rna-seq_0916", + "TIGEM Human Retina RNA-Seq (Sep16) RPKM log2" + ] + ] } }, "mouse": { @@ -1593,14 +1609,25 @@ ] ] }, + "B6D2": { + "Phenotypes": [ + [ + "None", + "B6D2Publish", + "B6D2 Published Phenotypes" + ] + ], + "Retina mRNA": [ + [ + "803", + "UTHSC_mm9_B6D2_Ret_0916", + "UTHSC B6D2 Retina Affy MoGene 1.0ST (Sep16) Gene Level RMA" + ] + ] + }, "B6D2F2": { "Brain mRNA": [ [ - "76", - "BRF2_M_0805_M", - "OHSU/VA B6D2F2 Brain mRNA M430 (Aug05) MAS5" - ], - [ "78", "BRF2_M_0805_P", "OHSU/VA B6D2F2 Brain mRNA M430 (Aug05) PDNN" @@ -1611,6 +1638,11 @@ "OHSU/VA B6D2F2 Brain mRNA M430 (Aug05) RMA" ], [ + "76", + "BRF2_M_0805_M", + "OHSU/VA B6D2F2 Brain mRNA M430 (Aug05) MAS5" + ], + [ "33", "BRF2_M_0304_P", "OHSU/VA B6D2F2 Brain mRNA M430A (Mar04) PDNN" @@ -1933,16 +1965,16 @@ ], "Brain mRNA": [ [ - "590", - "UTHSC_BXD_WB_RNASeqtrim1_1112", - "UTHSC Mouse BXD Whole Brain RNA Sequence (Nov12) RPKM Trimmed 1.0" - ], - [ "164", "UTHSC_BXD_WB_RNASeq1112", "UTHSC Mouse BXD Whole Brain RNA Sequence (Nov12) RPKM Untrimmed" ], [ + "590", + "UTHSC_BXD_WB_RNASeqtrim1_1112", + "UTHSC Mouse BXD Whole Brain RNA Sequence (Nov12) RPKM Trimmed 1.0" + ], + [ "394", "UTHSC_BXD_WB_RNASeqEx1112", "UTHSC Mouse BXD Whole Brain RNA Sequence Exon Level (Nov12) RPKM" @@ -1958,11 +1990,6 @@ "UTHSC Brain mRNA U74Av2 (Nov05) PDNN" ], [ - "82", - "BR_U_0805_R", - "UTHSC Brain mRNA U74Av2 (Aug05) RMA" - ], - [ "81", "BR_U_0805_P", "UTHSC Brain mRNA U74Av2 (Aug05) PDNN" @@ -1973,6 +2000,11 @@ "UTHSC Brain mRNA U74Av2 (Aug05) MAS5" ], [ + "82", + "BR_U_0805_R", + "UTHSC Brain mRNA U74Av2 (Aug05) RMA" + ], + [ "42", "CB_M_0204_P", "INIA Brain mRNA M430 (Feb04) PDNN" @@ -2039,11 +2071,6 @@ "Eye M430v2 WT Gpnmb (Sep08) RMA" ], [ - "278", - "Eye_M2_0908_R_MT", - "Eye M430v2 Mutant Tyrp1 (Sep08) RMA" - ], - [ "382", "Eye_M2_0908_WTWT", "Eye M430v2 WT WT (Sep08) RMA" @@ -2054,6 +2081,11 @@ "Eye M430v2 WT Tyrp1 (Sep08) RMA" ], [ + "278", + "Eye_M2_0908_R_MT", + "Eye M430v2 Mutant Tyrp1 (Sep08) RMA" + ], + [ "400", "DBA2J-ONH-1212", "Howell et al. 2011, DBA/2J Glaucoma Optic Nerve Head M430 2.0 (Dec12) RMA" @@ -3001,11 +3033,6 @@ ], "Hippocampus mRNA": [ [ - "212", - "Illum_LXS_Hipp_RSE_1008", - "Hippocampus Illumina RSE (Oct08) RankInv beta" - ], - [ "214", "Illum_LXS_Hipp_NOE_1008", "Hippocampus Illumina NOE (Oct08) RankInv beta" @@ -3026,6 +3053,11 @@ "Hippocampus Illumina NON (Oct08) RankInv beta" ], [ + "212", + "Illum_LXS_Hipp_RSE_1008", + "Hippocampus Illumina RSE (Oct08) RankInv beta" + ], + [ "143", "Illum_LXS_Hipp_loess0807", "Hippocampus Illumina (Aug07) LOESS" @@ -3159,6 +3191,13 @@ "MDPPublish", "Mouse Phenome Database" ] + ], + "Spleen mRNA": [ + [ + "801", + "HMS_mm8_MDP_Spl_CD4_1116", + "HMS Spleen CD4+ T cells MDP Affy Mouse Gene 1.0 ST (Jul16) Gene Level" + ] ] }, "NZBXFVB-N2": { @@ -3404,11 +3443,11 @@ ], [ "GTEx", - "GTEx v3 All Tissues, RNA-Seq" + "GTEx v3 All Tissues, RNA-Seq with Genotypes" ], [ "GTEx_v5", - "GTEx v5 All Tissues, RNA-Seq" + "GTEx v5 All Tissues, RNA-Seq with Genotypes" ], [ "HB", @@ -3429,6 +3468,10 @@ [ "HSB", "Brain, Development: Normal Gene Expression (Yale/Sestan)" + ], + [ + "TIGEM-Retina-RNA-Seq", + "Retina: Normal Adult Gene Expression, RNA-Seq (TIGEM)" ] ], "mouse": [ @@ -3445,6 +3488,10 @@ "B6BTBRF2" ], [ + "B6D2", + "Glaucoma and Aged Retina, UTHSC" + ], + [ "B6D2F2", "B6D2F2" ], @@ -3766,6 +3813,14 @@ ], "GTEx": [ [ + "Adipose tissue, subcutaneous mRNA", + "Adipose tissue, subcutaneous mRNA" + ], + [ + "Adipose tissue, visceral mRNA", + "Adipose tissue, visceral mRNA" + ], + [ "Adrenal Gland mRNA", "Adrenal Gland mRNA" ], @@ -3918,10 +3973,6 @@ "Stomach mRNA" ], [ - "Subcutaneous mRNA", - "Subcutaneous mRNA" - ], - [ "Substantia Nigra mRNA", "Substantia Nigra mRNA" ], @@ -3946,16 +3997,20 @@ "Vagina mRNA" ], [ - "Visceral mRNA", - "Visceral mRNA" - ], - [ "Whole Blood mRNA", "Whole Blood mRNA" ] ], "GTEx_v5": [ [ + "Adipose tissue, subcutaneous mRNA", + "Adipose tissue, subcutaneous mRNA" + ], + [ + "Adipose tissue, visceral mRNA", + "Adipose tissue, visceral mRNA" + ], + [ "Adrenal Gland mRNA", "Adrenal Gland mRNA" ], @@ -4132,10 +4187,6 @@ "Stomach mRNA" ], [ - "Subcutaneous mRNA", - "Subcutaneous mRNA" - ], - [ "Substantia Nigra mRNA", "Substantia Nigra mRNA" ], @@ -4160,10 +4211,6 @@ "Vagina mRNA" ], [ - "Visceral mRNA", - "Visceral mRNA" - ], - [ "Whole Blood mRNA", "Whole Blood mRNA" ] @@ -4273,6 +4320,16 @@ "Ventrolateral Prefrontal Cortex mRNA", "Ventrolateral Prefrontal Cortex mRNA" ] + ], + "TIGEM-Retina-RNA-Seq": [ + [ + "Phenotypes", + "Phenotypes" + ], + [ + "Retina mRNA", + "Retina mRNA" + ] ] }, "mouse": { @@ -4326,6 +4383,16 @@ "Liver mRNA" ] ], + "B6D2": [ + [ + "Phenotypes", + "Phenotypes" + ], + [ + "Retina mRNA", + "Retina mRNA" + ] + ], "B6D2F2": [ [ "Genotypes", @@ -4722,6 +4789,10 @@ [ "Liver mRNA", "Liver mRNA" + ], + [ + "Spleen mRNA", + "Spleen mRNA" ] ], "NZBXFVB-N2": [ @@ -4827,4 +4898,4 @@ ] } } -} +}
\ No newline at end of file diff --git a/wqflask/wqflask/static/new/javascript/network_graph.js b/wqflask/wqflask/static/new/javascript/network_graph.js new file mode 100644 index 00000000..d1afd47c --- /dev/null +++ b/wqflask/wqflask/static/new/javascript/network_graph.js @@ -0,0 +1,200 @@ +window.onload=function() { + // id of Cytoscape Web container div + //var div_id = "cytoscapeweb"; + + var cy = cytoscape({ + container: $('#cytoscapeweb'), // container to render in + + elements: elements_list, + + style: [ // the stylesheet for the graph + { + selector: 'node', + style: { + 'background-color': '#666', + 'label': 'data(symbol)', + 'font-size': 10 + } + }, + + { + selector: 'edge', + style: { + 'width': 'data(width)', + 'line-color': 'data(color)', + 'target-arrow-color': '#ccc', + 'target-arrow-shape': 'triangle', + 'font-size': 8 + } + } + ], + + zoom: 12, + layout: { name: 'circle', + fit: true, // whether to fit the viewport to the graph + padding: 30 // the padding on fit + //idealEdgeLength: function( edge ){ return edge.data['correlation']*10; }, + }, + + + zoomingEnabled: true, + userZoomingEnabled: true, + panningEnabled: true, + userPanningEnabled: true, + boxSelectionEnabled: false, + selectionType: 'single', + + // rendering options: + styleEnabled: true + }); + + var eles = cy.$() // var containing all elements, so elements can be restored after being removed + + var defaults = { + zoomFactor: 0.05, // zoom factor per zoom tick + zoomDelay: 45, // how many ms between zoom ticks + minZoom: 0.1, // min zoom level + maxZoom: 10, // max zoom level + fitPadding: 30, // padding when fitting + panSpeed: 10, // how many ms in between pan ticks + panDistance: 10, // max pan distance per tick + panDragAreaSize: 75, // the length of the pan drag box in which the vector for panning is calculated (bigger = finer control of pan speed and direction) + panMinPercentSpeed: 0.25, // the slowest speed we can pan by (as a percent of panSpeed) + panInactiveArea: 8, // radius of inactive area in pan drag box + panIndicatorMinOpacity: 0.5, // min opacity of pan indicator (the draggable nib); scales from this to 1.0 + zoomOnly: false, // a minimal version of the ui only with zooming (useful on systems with bad mousewheel resolution) + fitSelector: undefined, // selector of elements to fit + animateOnFit: function(){ // whether to animate on fit + return false; + }, + fitAnimationDuration: 1000, // duration of animation on fit + + // icon class names + sliderHandleIcon: 'fa fa-minus', + zoomInIcon: 'fa fa-plus', + zoomOutIcon: 'fa fa-minus', + resetIcon: 'fa fa-expand' + }; + + cy.panzoom( defaults ); + + function create_qtips(cy){ + cy.nodes().qtip({ + content: function(){ + gn_link = '<b>'+'<a href="http://gn2.genenetwork.org/show_trait?trait_id=' + this.data().id + '&dataset=' + this.data().dataset + '" >'+this.data().id +'</a>'+'</b><br>' + ncbi_link = '<a href="http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=gene&cmd=Retrieve&dopt=Graphics&list_uids=' + this.data().geneid + '" >NCBI<a>'+'<br>' + omim_link = '<a href="http://www.ncbi.nlm.nih.gov/omim/' + this.data().omim + '" >OMIM<a>'+'<br>' + qtip_content = gn_link + ncbi_link + omim_link + return qtip_content + //return '<b>'+'<a href="http://gn2.genenetwork.org/show_trait?trait_id=' + this.data().id + '&dataset=' + this.data().dataset + '" >'+this.data().id +'<a>'+'</b>' + }, + // content: { + // title: '<b>'+'<a href="http://gn2.genenetwork.org/show_trait?trait_id=' + this.target() + '&dataset=' + this.dataset() + '" >'+this.target() +'<a>'+'</b>', + // text: this.target, + // button: true + // }, + position: { + my: 'top center', + at: 'bottom center' + }, + style: { + classes: 'qtip-bootstrap', + tip: { + width: 16, + height: 8 + } + } + }); + + cy.edges().qtip({ + content: function(){ + correlation_line = '<b>Sample r: ' + this.data().correlation + '</b><br>' + p_value_line = 'Sample p(r): ' + this.data().p_value + '<br>' + overlap_line = 'Overlap: ' + this.data().overlap + '<br>' + scatter_plot = '<a href="http://gn2-zach.genenetwork.org/corr_scatter_plot?dataset_1=' + this.data().source_dataset + '&dataset_2=' + this.data().target_dataset + '&trait_1=' + this.data().source + '&trait_2=' + this.data().target + '" >View Scatterplot</a>' + return correlation_line + p_value_line + overlap_line + scatter_plot + }, + position: { + my: 'top center', + at: 'bottom center' + }, + style: { + classes: 'qtip-bootstrap', + tip: { + width: 16, + height: 8 + } + } + }); + } + + create_qtips(cy) + + $('#slide').change(function() { + eles.restore() + + console.log(eles) + + // nodes_to_restore = eles.filter("node[max_corr >= " + $(this).val() + "], edge[correlation >= " + $(this).val() + "][correlation <= -" + $(this).val() + "]") + // nodes_to_restore.restore() + + // edges_to_restore = eles.filter("edge[correlation >= " + $(this).val() + "][correlation <= -" + $(this).val() + "]") + // edges_to_restore.restore() + + //cy.$("node[max_corr >= " + $(this).val() + "]").restore(); + //cy.$("edge[correlation >= " + $(this).val() + "][correlation <= -" + $(this).val() + "]").restore(); + + cy.$("node[max_corr < " + $(this).val() + "]").remove(); + cy.$("edge[correlation < " + $(this).val() + "][correlation > -" + $(this).val() + "]").remove(); + + cy.layout({ name: $('select[name=layout_select]').val(), + fit: true, // whether to fit the viewport to the graph + padding: 25 // the padding on fit + }); + + }); + + $('#reset_graph').click(function() { + eles.restore() + $('#slide').val(0) + cy.layout({ name: $('select[name=layout_select]').val(), + fit: true, // whether to fit the viewport to the graph + padding: 25 // the padding on fit + }); + }); + + $('select[name=focus_select]').change(function() { + focus_trait = $(this).val() + + eles.restore() + cy.$('edge[source != "' + focus_trait + '"][target != "' + focus_trait + '"]').remove() + + cy.layout({ name: $('select[name=layout_select]').val(), + fit: true, // whether to fit the viewport to the graph + padding: 25 // the padding on fit + }); + }); + + $('select[name=layout_select]').change(function() { + layout_type = $(this).val() + console.log("LAYOUT:", layout_type) + cy.layout({ name: layout_type, + fit: true, // whether to fit the viewport to the graph + padding: 25 // the padding on fit + }); + }); + + $("a#image_link").click(function(e) { + var pngData = cy.png(); + + $(this).attr('href', pngData); + $(this).attr('download', 'network_graph.png'); + + console.log("TESTING:", image_link) + + }); + + +}; + + diff --git a/wqflask/wqflask/static/new/javascript/show_trait.js b/wqflask/wqflask/static/new/javascript/show_trait.js index 419aa7a2..19955b07 100644 --- a/wqflask/wqflask/static/new/javascript/show_trait.js +++ b/wqflask/wqflask/static/new/javascript/show_trait.js @@ -173,13 +173,13 @@ }; make_table = function() { var header, key, row, row_line, table, the_id, the_rows, value, _i, _len, _ref, _ref1; - header = "<thead><tr><th> </th>"; + header = "<thead><tr><th style=\"padding-left: 5px;\">Statistic</th>"; _ref = js_data.sample_group_types; for (key in _ref) { if (!__hasProp.call(_ref, key)) continue; value = _ref[key]; the_id = process_id("column", key); - header += "<th id=\"" + the_id + "\">" + value + "</th>"; + header += "<th id=\"" + the_id + "\" style=\"padding-left: 5px;\">" + value + "</th>"; } header += "</thead>"; the_rows = "<tbody>"; diff --git a/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.js b/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.js index 474109a3..e9db0a12 100644 --- a/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.js +++ b/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.js @@ -133,7 +133,7 @@ }); }; - outlier_text = "One or more outliers exist in this data set. Please review values before mapping. Including outliers when mapping may lead to misleading results. We recommend <A HREF=\"http://en.wikipedia.org/wiki/Winsorising\">winsorising</A> the outliers or simply deleting them."; + outlier_text = "One or more outliers exist in this data set. Please review values before mapping. Including outliers when mapping may lead to misleading results."; runtime_warning_text = "This function could take as long as 10-20 minutes to run, so please do not close your browser window until it finishes." diff --git a/wqflask/wqflask/static/new/packages/DataTables/js/jquery.dataTables.js b/wqflask/wqflask/static/new/packages/DataTables/js/jquery.dataTables.js index 7bf65d02..5b032aee 100644 --- a/wqflask/wqflask/static/new/packages/DataTables/js/jquery.dataTables.js +++ b/wqflask/wqflask/static/new/packages/DataTables/js/jquery.dataTables.js @@ -1,15 +1,15 @@ -/*! DataTables 1.10.7 - * ©2008-2014 SpryMedia Ltd - datatables.net/license +/*! DataTables 1.10.12 + * ©2008-2015 SpryMedia Ltd - datatables.net/license */ /** * @summary DataTables * @description Paginate, search and order HTML tables - * @version 1.10.7 + * @version 1.10.12 * @file jquery.dataTables.js * @author SpryMedia Ltd (www.sprymedia.co.uk) * @contact www.sprymedia.co.uk/contact - * @copyright Copyright 2008-2014 SpryMedia Ltd. + * @copyright Copyright 2008-2015 SpryMedia Ltd. * * This source file is free software, available under the following license: * MIT license - http://datatables.net/license @@ -22,28 +22,41 @@ */ /*jslint evil: true, undef: true, browser: true */ -/*globals $,require,jQuery,define,_selector_run,_selector_opts,_selector_first,_selector_row_indexes,_ext,_Api,_api_register,_api_registerPlural,_re_new_lines,_re_html,_re_formatted_numeric,_re_escape_regex,_empty,_intVal,_numToDecimal,_isNumber,_isHtml,_htmlNumeric,_pluck,_pluck_order,_range,_stripHtml,_unique,_fnBuildAjax,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnAjaxDataSrc,_fnAddColumn,_fnColumnOptions,_fnAdjustColumnSizing,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnVisbleColumns,_fnGetColumns,_fnColumnTypes,_fnApplyColumnDefs,_fnHungarianMap,_fnCamelToHungarian,_fnLanguageCompat,_fnBrowserDetect,_fnAddData,_fnAddTr,_fnNodeToDataIndex,_fnNodeToColumnIndex,_fnGetCellData,_fnSetCellData,_fnSplitObjNotation,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnGetDataMaster,_fnClearTable,_fnDeleteIndex,_fnInvalidate,_fnGetRowElements,_fnCreateTr,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAddOptionsHtml,_fnDetectHeader,_fnGetUniqueThs,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnFilterCreateSearch,_fnEscapeRegex,_fnFilterData,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnInfoMacros,_fnInitialise,_fnInitComplete,_fnLengthChange,_fnFeatureHtmlLength,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnFeatureHtmlTable,_fnScrollDraw,_fnApplyToChildren,_fnCalculateColumnWidths,_fnThrottle,_fnConvertToWidth,_fnScrollingWidthAdjust,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnScrollBarWidth,_fnSortFlatten,_fnSort,_fnSortAria,_fnSortListener,_fnSortAttachListener,_fnSortingClasses,_fnSortData,_fnSaveState,_fnLoadState,_fnSettingsFromNode,_fnLog,_fnMap,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnLengthOverflow,_fnRenderer,_fnDataSource,_fnRowAttributes*/ - -(/** @lends <global> */function( window, document, undefined ) { +/*globals $,require,jQuery,define,_selector_run,_selector_opts,_selector_first,_selector_row_indexes,_ext,_Api,_api_register,_api_registerPlural,_re_new_lines,_re_html,_re_formatted_numeric,_re_escape_regex,_empty,_intVal,_numToDecimal,_isNumber,_isHtml,_htmlNumeric,_pluck,_pluck_order,_range,_stripHtml,_unique,_fnBuildAjax,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnAjaxDataSrc,_fnAddColumn,_fnColumnOptions,_fnAdjustColumnSizing,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnVisbleColumns,_fnGetColumns,_fnColumnTypes,_fnApplyColumnDefs,_fnHungarianMap,_fnCamelToHungarian,_fnLanguageCompat,_fnBrowserDetect,_fnAddData,_fnAddTr,_fnNodeToDataIndex,_fnNodeToColumnIndex,_fnGetCellData,_fnSetCellData,_fnSplitObjNotation,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnGetDataMaster,_fnClearTable,_fnDeleteIndex,_fnInvalidate,_fnGetRowElements,_fnCreateTr,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAddOptionsHtml,_fnDetectHeader,_fnGetUniqueThs,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnFilterCreateSearch,_fnEscapeRegex,_fnFilterData,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnInfoMacros,_fnInitialise,_fnInitComplete,_fnLengthChange,_fnFeatureHtmlLength,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnFeatureHtmlTable,_fnScrollDraw,_fnApplyToChildren,_fnCalculateColumnWidths,_fnThrottle,_fnConvertToWidth,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnSortFlatten,_fnSort,_fnSortAria,_fnSortListener,_fnSortAttachListener,_fnSortingClasses,_fnSortData,_fnSaveState,_fnLoadState,_fnSettingsFromNode,_fnLog,_fnMap,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnLengthOverflow,_fnRenderer,_fnDataSource,_fnRowAttributes*/ (function( factory ) { "use strict"; if ( typeof define === 'function' && define.amd ) { - // Define as an AMD module if possible - define( 'datatables', ['jquery'], factory ); + // AMD + define( ['jquery'], function ( $ ) { + return factory( $, window, document ); + } ); + } + else if ( typeof exports === 'object' ) { + // CommonJS + module.exports = function (root, $) { + if ( ! root ) { + // CommonJS environments without a window global must pass a + // root. This will give an error otherwise + root = window; + } + + if ( ! $ ) { + $ = typeof window !== 'undefined' ? // jQuery's factory checks for a global window + require('jquery') : + require('jquery')( root ); + } + + return factory( $, root, root.document ); + }; } - else if ( typeof exports === 'object' ) { - // Node/CommonJS - module.exports = factory( require( 'jquery' ) ); - } - else if ( jQuery && !jQuery.fn.dataTable ) { - // Define using browser globals otherwise - // Prevent multiple instantiations if the script is loaded twice - factory( jQuery ); + else { + // Browser + factory( jQuery, window, document ); } } -(/** @lends <global> */function( $ ) { +(function( $, window, document, undefined ) { "use strict"; /** @@ -78,7 +91,1257 @@ * } ); * } ); */ - var DataTable; + var DataTable = function ( options ) + { + /** + * Perform a jQuery selector action on the table's TR elements (from the tbody) and + * return the resulting jQuery object. + * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on + * @param {object} [oOpts] Optional parameters for modifying the rows to be included + * @param {string} [oOpts.filter=none] Select TR elements that meet the current filter + * criterion ("applied") or all TR elements (i.e. no filter). + * @param {string} [oOpts.order=current] Order of the TR elements in the processed array. + * Can be either 'current', whereby the current sorting of the table is used, or + * 'original' whereby the original order the data was read into the table is used. + * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page + * ("current") or not ("all"). If 'current' is given, then order is assumed to be + * 'current' and filter is 'applied', regardless of what they might be given as. + * @returns {object} jQuery object, filtered by the given selector. + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Highlight every second row + * oTable.$('tr:odd').css('backgroundColor', 'blue'); + * } ); + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Filter to rows with 'Webkit' in them, add a background colour and then + * // remove the filter, thus highlighting the 'Webkit' rows only. + * oTable.fnFilter('Webkit'); + * oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue'); + * oTable.fnFilter(''); + * } ); + */ + this.$ = function ( sSelector, oOpts ) + { + return this.api(true).$( sSelector, oOpts ); + }; + + + /** + * Almost identical to $ in operation, but in this case returns the data for the matched + * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes + * rather than any descendants, so the data can be obtained for the row/cell. If matching + * rows are found, the data returned is the original data array/object that was used to + * create the row (or a generated array if from a DOM source). + * + * This method is often useful in-combination with $ where both functions are given the + * same parameters and the array indexes will match identically. + * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on + * @param {object} [oOpts] Optional parameters for modifying the rows to be included + * @param {string} [oOpts.filter=none] Select elements that meet the current filter + * criterion ("applied") or all elements (i.e. no filter). + * @param {string} [oOpts.order=current] Order of the data in the processed array. + * Can be either 'current', whereby the current sorting of the table is used, or + * 'original' whereby the original order the data was read into the table is used. + * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page + * ("current") or not ("all"). If 'current' is given, then order is assumed to be + * 'current' and filter is 'applied', regardless of what they might be given as. + * @returns {array} Data for the matched elements. If any elements, as a result of the + * selector, were not TR, TD or TH elements in the DataTable, they will have a null + * entry in the array. + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Get the data from the first row in the table + * var data = oTable._('tr:first'); + * + * // Do something useful with the data + * alert( "First cell is: "+data[0] ); + * } ); + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Filter to 'Webkit' and get all data for + * oTable.fnFilter('Webkit'); + * var data = oTable._('tr', {"search": "applied"}); + * + * // Do something with the data + * alert( data.length+" rows matched the search" ); + * } ); + */ + this._ = function ( sSelector, oOpts ) + { + return this.api(true).rows( sSelector, oOpts ).data(); + }; + + + /** + * Create a DataTables Api instance, with the currently selected tables for + * the Api's context. + * @param {boolean} [traditional=false] Set the API instance's context to be + * only the table referred to by the `DataTable.ext.iApiIndex` option, as was + * used in the API presented by DataTables 1.9- (i.e. the traditional mode), + * or if all tables captured in the jQuery object should be used. + * @return {DataTables.Api} + */ + this.api = function ( traditional ) + { + return traditional ? + new _Api( + _fnSettingsFromNode( this[ _ext.iApiIndex ] ) + ) : + new _Api( this ); + }; + + + /** + * Add a single new row or multiple rows of data to the table. Please note + * that this is suitable for client-side processing only - if you are using + * server-side processing (i.e. "bServerSide": true), then to add data, you + * must add it to the data source, i.e. the server-side, through an Ajax call. + * @param {array|object} data The data to be added to the table. This can be: + * <ul> + * <li>1D array of data - add a single row with the data provided</li> + * <li>2D array of arrays - add multiple rows in a single call</li> + * <li>object - data object when using <i>mData</i></li> + * <li>array of objects - multiple data objects when using <i>mData</i></li> + * </ul> + * @param {bool} [redraw=true] redraw the table or not + * @returns {array} An array of integers, representing the list of indexes in + * <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to + * the table. + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * // Global var for counter + * var giCount = 2; + * + * $(document).ready(function() { + * $('#example').dataTable(); + * } ); + * + * function fnClickAddRow() { + * $('#example').dataTable().fnAddData( [ + * giCount+".1", + * giCount+".2", + * giCount+".3", + * giCount+".4" ] + * ); + * + * giCount++; + * } + */ + this.fnAddData = function( data, redraw ) + { + var api = this.api( true ); + + /* Check if we want to add multiple rows or not */ + var rows = $.isArray(data) && ( $.isArray(data[0]) || $.isPlainObject(data[0]) ) ? + api.rows.add( data ) : + api.row.add( data ); + + if ( redraw === undefined || redraw ) { + api.draw(); + } + + return rows.flatten().toArray(); + }; + + + /** + * This function will make DataTables recalculate the column sizes, based on the data + * contained in the table and the sizes applied to the columns (in the DOM, CSS or + * through the sWidth parameter). This can be useful when the width of the table's + * parent element changes (for example a window resize). + * @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable( { + * "sScrollY": "200px", + * "bPaginate": false + * } ); + * + * $(window).bind('resize', function () { + * oTable.fnAdjustColumnSizing(); + * } ); + * } ); + */ + this.fnAdjustColumnSizing = function ( bRedraw ) + { + var api = this.api( true ).columns.adjust(); + var settings = api.settings()[0]; + var scroll = settings.oScroll; + + if ( bRedraw === undefined || bRedraw ) { + api.draw( false ); + } + else if ( scroll.sX !== "" || scroll.sY !== "" ) { + /* If not redrawing, but scrolling, we want to apply the new column sizes anyway */ + _fnScrollDraw( settings ); + } + }; + + + /** + * Quickly and simply clear a table + * @param {bool} [bRedraw=true] redraw the table or not + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...) + * oTable.fnClearTable(); + * } ); + */ + this.fnClearTable = function( bRedraw ) + { + var api = this.api( true ).clear(); + + if ( bRedraw === undefined || bRedraw ) { + api.draw(); + } + }; + + + /** + * The exact opposite of 'opening' a row, this function will close any rows which + * are currently 'open'. + * @param {node} nTr the table row to 'close' + * @returns {int} 0 on success, or 1 if failed (can't find the row) + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable; + * + * // 'open' an information row when a row is clicked on + * $('#example tbody tr').click( function () { + * if ( oTable.fnIsOpen(this) ) { + * oTable.fnClose( this ); + * } else { + * oTable.fnOpen( this, "Temporary row opened", "info_row" ); + * } + * } ); + * + * oTable = $('#example').dataTable(); + * } ); + */ + this.fnClose = function( nTr ) + { + this.api( true ).row( nTr ).child.hide(); + }; + + + /** + * Remove a row for the table + * @param {mixed} target The index of the row from aoData to be deleted, or + * the TR element you want to delete + * @param {function|null} [callBack] Callback function + * @param {bool} [redraw=true] Redraw the table or not + * @returns {array} The row that was deleted + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Immediately remove the first row + * oTable.fnDeleteRow( 0 ); + * } ); + */ + this.fnDeleteRow = function( target, callback, redraw ) + { + var api = this.api( true ); + var rows = api.rows( target ); + var settings = rows.settings()[0]; + var data = settings.aoData[ rows[0][0] ]; + + rows.remove(); + + if ( callback ) { + callback.call( this, settings, data ); + } + + if ( redraw === undefined || redraw ) { + api.draw(); + } + + return data; + }; + + + /** + * Restore the table to it's original state in the DOM by removing all of DataTables + * enhancements, alterations to the DOM structure of the table and event listeners. + * @param {boolean} [remove=false] Completely remove the table from the DOM + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * // This example is fairly pointless in reality, but shows how fnDestroy can be used + * var oTable = $('#example').dataTable(); + * oTable.fnDestroy(); + * } ); + */ + this.fnDestroy = function ( remove ) + { + this.api( true ).destroy( remove ); + }; + + + /** + * Redraw the table + * @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw. + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Re-draw the table - you wouldn't want to do it here, but it's an example :-) + * oTable.fnDraw(); + * } ); + */ + this.fnDraw = function( complete ) + { + // Note that this isn't an exact match to the old call to _fnDraw - it takes + // into account the new data, but can hold position. + this.api( true ).draw( complete ); + }; + + + /** + * Filter the input based on data + * @param {string} sInput String to filter the table on + * @param {int|null} [iColumn] Column to limit filtering to + * @param {bool} [bRegex=false] Treat as regular expression or not + * @param {bool} [bSmart=true] Perform smart filtering or not + * @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es) + * @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false) + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Sometime later - filter... + * oTable.fnFilter( 'test string' ); + * } ); + */ + this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive ) + { + var api = this.api( true ); + + if ( iColumn === null || iColumn === undefined ) { + api.search( sInput, bRegex, bSmart, bCaseInsensitive ); + } + else { + api.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive ); + } + + api.draw(); + }; + + + /** + * Get the data for the whole table, an individual row or an individual cell based on the + * provided parameters. + * @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as + * a TR node then the data source for the whole row will be returned. If given as a + * TD/TH cell node then iCol will be automatically calculated and the data for the + * cell returned. If given as an integer, then this is treated as the aoData internal + * data index for the row (see fnGetPosition) and the data for that row used. + * @param {int} [col] Optional column index that you want the data of. + * @returns {array|object|string} If mRow is undefined, then the data for all rows is + * returned. If mRow is defined, just data for that row, and is iCol is + * defined, only data for the designated cell is returned. + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * // Row data + * $(document).ready(function() { + * oTable = $('#example').dataTable(); + * + * oTable.$('tr').click( function () { + * var data = oTable.fnGetData( this ); + * // ... do something with the array / object of data for the row + * } ); + * } ); + * + * @example + * // Individual cell data + * $(document).ready(function() { + * oTable = $('#example').dataTable(); + * + * oTable.$('td').click( function () { + * var sData = oTable.fnGetData( this ); + * alert( 'The cell clicked on had the value of '+sData ); + * } ); + * } ); + */ + this.fnGetData = function( src, col ) + { + var api = this.api( true ); + + if ( src !== undefined ) { + var type = src.nodeName ? src.nodeName.toLowerCase() : ''; + + return col !== undefined || type == 'td' || type == 'th' ? + api.cell( src, col ).data() : + api.row( src ).data() || null; + } + + return api.data().toArray(); + }; + + + /** + * Get an array of the TR nodes that are used in the table's body. Note that you will + * typically want to use the '$' API method in preference to this as it is more + * flexible. + * @param {int} [iRow] Optional row index for the TR element you want + * @returns {array|node} If iRow is undefined, returns an array of all TR elements + * in the table's body, or iRow is defined, just the TR element requested. + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Get the nodes from the table + * var nNodes = oTable.fnGetNodes( ); + * } ); + */ + this.fnGetNodes = function( iRow ) + { + var api = this.api( true ); + + return iRow !== undefined ? + api.row( iRow ).node() : + api.rows().nodes().flatten().toArray(); + }; + + + /** + * Get the array indexes of a particular cell from it's DOM element + * and column index including hidden columns + * @param {node} node this can either be a TR, TD or TH in the table's body + * @returns {int} If nNode is given as a TR, then a single index is returned, or + * if given as a cell, an array of [row index, column index (visible), + * column index (all)] is given. + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * $('#example tbody td').click( function () { + * // Get the position of the current data from the node + * var aPos = oTable.fnGetPosition( this ); + * + * // Get the data array for this row + * var aData = oTable.fnGetData( aPos[0] ); + * + * // Update the data array and return the value + * aData[ aPos[1] ] = 'clicked'; + * this.innerHTML = 'clicked'; + * } ); + * + * // Init DataTables + * oTable = $('#example').dataTable(); + * } ); + */ + this.fnGetPosition = function( node ) + { + var api = this.api( true ); + var nodeName = node.nodeName.toUpperCase(); + + if ( nodeName == 'TR' ) { + return api.row( node ).index(); + } + else if ( nodeName == 'TD' || nodeName == 'TH' ) { + var cell = api.cell( node ).index(); + + return [ + cell.row, + cell.columnVisible, + cell.column + ]; + } + return null; + }; + + + /** + * Check to see if a row is 'open' or not. + * @param {node} nTr the table row to check + * @returns {boolean} true if the row is currently open, false otherwise + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable; + * + * // 'open' an information row when a row is clicked on + * $('#example tbody tr').click( function () { + * if ( oTable.fnIsOpen(this) ) { + * oTable.fnClose( this ); + * } else { + * oTable.fnOpen( this, "Temporary row opened", "info_row" ); + * } + * } ); + * + * oTable = $('#example').dataTable(); + * } ); + */ + this.fnIsOpen = function( nTr ) + { + return this.api( true ).row( nTr ).child.isShown(); + }; + + + /** + * This function will place a new row directly after a row which is currently + * on display on the page, with the HTML contents that is passed into the + * function. This can be used, for example, to ask for confirmation that a + * particular record should be deleted. + * @param {node} nTr The table row to 'open' + * @param {string|node|jQuery} mHtml The HTML to put into the row + * @param {string} sClass Class to give the new TD cell + * @returns {node} The row opened. Note that if the table row passed in as the + * first parameter, is not found in the table, this method will silently + * return. + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable; + * + * // 'open' an information row when a row is clicked on + * $('#example tbody tr').click( function () { + * if ( oTable.fnIsOpen(this) ) { + * oTable.fnClose( this ); + * } else { + * oTable.fnOpen( this, "Temporary row opened", "info_row" ); + * } + * } ); + * + * oTable = $('#example').dataTable(); + * } ); + */ + this.fnOpen = function( nTr, mHtml, sClass ) + { + return this.api( true ) + .row( nTr ) + .child( mHtml, sClass ) + .show() + .child()[0]; + }; + + + /** + * Change the pagination - provides the internal logic for pagination in a simple API + * function. With this function you can have a DataTables table go to the next, + * previous, first or last pages. + * @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last" + * or page number to jump to (integer), note that page 0 is the first page. + * @param {bool} [bRedraw=true] Redraw the table or not + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * oTable.fnPageChange( 'next' ); + * } ); + */ + this.fnPageChange = function ( mAction, bRedraw ) + { + var api = this.api( true ).page( mAction ); + + if ( bRedraw === undefined || bRedraw ) { + api.draw(false); + } + }; + + + /** + * Show a particular column + * @param {int} iCol The column whose display should be changed + * @param {bool} bShow Show (true) or hide (false) the column + * @param {bool} [bRedraw=true] Redraw the table or not + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Hide the second column after initialisation + * oTable.fnSetColumnVis( 1, false ); + * } ); + */ + this.fnSetColumnVis = function ( iCol, bShow, bRedraw ) + { + var api = this.api( true ).column( iCol ).visible( bShow ); + + if ( bRedraw === undefined || bRedraw ) { + api.columns.adjust().draw(); + } + }; + + + /** + * Get the settings for a particular table for external manipulation + * @returns {object} DataTables settings object. See + * {@link DataTable.models.oSettings} + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * var oSettings = oTable.fnSettings(); + * + * // Show an example parameter from the settings + * alert( oSettings._iDisplayStart ); + * } ); + */ + this.fnSettings = function() + { + return _fnSettingsFromNode( this[_ext.iApiIndex] ); + }; + + + /** + * Sort the table by a particular column + * @param {int} iCol the data index to sort on. Note that this will not match the + * 'display index' if you have hidden data entries + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Sort immediately with columns 0 and 1 + * oTable.fnSort( [ [0,'asc'], [1,'asc'] ] ); + * } ); + */ + this.fnSort = function( aaSort ) + { + this.api( true ).order( aaSort ).draw(); + }; + + + /** + * Attach a sort listener to an element for a given column + * @param {node} nNode the element to attach the sort listener to + * @param {int} iColumn the column that a click on this node will sort on + * @param {function} [fnCallback] callback function when sort is run + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Sort on column 1, when 'sorter' is clicked on + * oTable.fnSortListener( document.getElementById('sorter'), 1 ); + * } ); + */ + this.fnSortListener = function( nNode, iColumn, fnCallback ) + { + this.api( true ).order.listener( nNode, iColumn, fnCallback ); + }; + + + /** + * Update a table cell or row - this method will accept either a single value to + * update the cell with, an array of values with one element for each column or + * an object in the same format as the original data source. The function is + * self-referencing in order to make the multi column updates easier. + * @param {object|array|string} mData Data to update the cell/row with + * @param {node|int} mRow TR element you want to update or the aoData index + * @param {int} [iColumn] The column to update, give as null or undefined to + * update a whole row. + * @param {bool} [bRedraw=true] Redraw the table or not + * @param {bool} [bAction=true] Perform pre-draw actions or not + * @returns {int} 0 on success, 1 on error + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell + * oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row + * } ); + */ + this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction ) + { + var api = this.api( true ); + + if ( iColumn === undefined || iColumn === null ) { + api.row( mRow ).data( mData ); + } + else { + api.cell( mRow, iColumn ).data( mData ); + } + + if ( bAction === undefined || bAction ) { + api.columns.adjust(); + } + + if ( bRedraw === undefined || bRedraw ) { + api.draw(); + } + return 0; + }; + + + /** + * Provide a common method for plug-ins to check the version of DataTables being used, in order + * to ensure compatibility. + * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the + * formats "X" and "X.Y" are also acceptable. + * @returns {boolean} true if this version of DataTables is greater or equal to the required + * version, or false if this version of DataTales is not suitable + * @method + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * alert( oTable.fnVersionCheck( '1.9.0' ) ); + * } ); + */ + this.fnVersionCheck = _ext.fnVersionCheck; + + + var _that = this; + var emptyInit = options === undefined; + var len = this.length; + + if ( emptyInit ) { + options = {}; + } + + this.oApi = this.internal = _ext.internal; + + // Extend with old style plug-in API methods + for ( var fn in DataTable.ext.internal ) { + if ( fn ) { + this[fn] = _fnExternApiFunc(fn); + } + } + + this.each(function() { + // For each initialisation we want to give it a clean initialisation + // object that can be bashed around + var o = {}; + var oInit = len > 1 ? // optimisation for single table case + _fnExtend( o, options, true ) : + options; + + /*global oInit,_that,emptyInit*/ + var i=0, iLen, j, jLen, k, kLen; + var sId = this.getAttribute( 'id' ); + var bInitHandedOff = false; + var defaults = DataTable.defaults; + var $this = $(this); + + + /* Sanity check */ + if ( this.nodeName.toLowerCase() != 'table' ) + { + _fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 ); + return; + } + + /* Backwards compatibility for the defaults */ + _fnCompatOpts( defaults ); + _fnCompatCols( defaults.column ); + + /* Convert the camel-case defaults to Hungarian */ + _fnCamelToHungarian( defaults, defaults, true ); + _fnCamelToHungarian( defaults.column, defaults.column, true ); + + /* Setting up the initialisation object */ + _fnCamelToHungarian( defaults, $.extend( oInit, $this.data() ) ); + + + + /* Check to see if we are re-initialising a table */ + var allSettings = DataTable.settings; + for ( i=0, iLen=allSettings.length ; i<iLen ; i++ ) + { + var s = allSettings[i]; + + /* Base check on table node */ + if ( s.nTable == this || s.nTHead.parentNode == this || (s.nTFoot && s.nTFoot.parentNode == this) ) + { + var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve; + var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy; + + if ( emptyInit || bRetrieve ) + { + return s.oInstance; + } + else if ( bDestroy ) + { + s.oInstance.fnDestroy(); + break; + } + else + { + _fnLog( s, 0, 'Cannot reinitialise DataTable', 3 ); + return; + } + } + + /* If the element we are initialising has the same ID as a table which was previously + * initialised, but the table nodes don't match (from before) then we destroy the old + * instance by simply deleting it. This is under the assumption that the table has been + * destroyed by other methods. Anyone using non-id selectors will need to do this manually + */ + if ( s.sTableId == this.id ) + { + allSettings.splice( i, 1 ); + break; + } + } + + /* Ensure the table has an ID - required for accessibility */ + if ( sId === null || sId === "" ) + { + sId = "DataTables_Table_"+(DataTable.ext._unique++); + this.id = sId; + } + + /* Create the settings object for this table and set some of the default parameters */ + var oSettings = $.extend( true, {}, DataTable.models.oSettings, { + "sDestroyWidth": $this[0].style.width, + "sInstance": sId, + "sTableId": sId + } ); + oSettings.nTable = this; + oSettings.oApi = _that.internal; + oSettings.oInit = oInit; + + allSettings.push( oSettings ); + + // Need to add the instance after the instance after the settings object has been added + // to the settings array, so we can self reference the table instance if more than one + oSettings.oInstance = (_that.length===1) ? _that : $this.dataTable(); + + // Backwards compatibility, before we apply all the defaults + _fnCompatOpts( oInit ); + + if ( oInit.oLanguage ) + { + _fnLanguageCompat( oInit.oLanguage ); + } + + // If the length menu is given, but the init display length is not, use the length menu + if ( oInit.aLengthMenu && ! oInit.iDisplayLength ) + { + oInit.iDisplayLength = $.isArray( oInit.aLengthMenu[0] ) ? + oInit.aLengthMenu[0][0] : oInit.aLengthMenu[0]; + } + + // Apply the defaults and init options to make a single init object will all + // options defined from defaults and instance options. + oInit = _fnExtend( $.extend( true, {}, defaults ), oInit ); + + + // Map the initialisation options onto the settings object + _fnMap( oSettings.oFeatures, oInit, [ + "bPaginate", + "bLengthChange", + "bFilter", + "bSort", + "bSortMulti", + "bInfo", + "bProcessing", + "bAutoWidth", + "bSortClasses", + "bServerSide", + "bDeferRender" + ] ); + _fnMap( oSettings, oInit, [ + "asStripeClasses", + "ajax", + "fnServerData", + "fnFormatNumber", + "sServerMethod", + "aaSorting", + "aaSortingFixed", + "aLengthMenu", + "sPaginationType", + "sAjaxSource", + "sAjaxDataProp", + "iStateDuration", + "sDom", + "bSortCellsTop", + "iTabIndex", + "fnStateLoadCallback", + "fnStateSaveCallback", + "renderer", + "searchDelay", + "rowId", + [ "iCookieDuration", "iStateDuration" ], // backwards compat + [ "oSearch", "oPreviousSearch" ], + [ "aoSearchCols", "aoPreSearchCols" ], + [ "iDisplayLength", "_iDisplayLength" ], + [ "bJQueryUI", "bJUI" ] + ] ); + _fnMap( oSettings.oScroll, oInit, [ + [ "sScrollX", "sX" ], + [ "sScrollXInner", "sXInner" ], + [ "sScrollY", "sY" ], + [ "bScrollCollapse", "bCollapse" ] + ] ); + _fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" ); + + /* Callback functions which are array driven */ + _fnCallbackReg( oSettings, 'aoDrawCallback', oInit.fnDrawCallback, 'user' ); + _fnCallbackReg( oSettings, 'aoServerParams', oInit.fnServerParams, 'user' ); + _fnCallbackReg( oSettings, 'aoStateSaveParams', oInit.fnStateSaveParams, 'user' ); + _fnCallbackReg( oSettings, 'aoStateLoadParams', oInit.fnStateLoadParams, 'user' ); + _fnCallbackReg( oSettings, 'aoStateLoaded', oInit.fnStateLoaded, 'user' ); + _fnCallbackReg( oSettings, 'aoRowCallback', oInit.fnRowCallback, 'user' ); + _fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow, 'user' ); + _fnCallbackReg( oSettings, 'aoHeaderCallback', oInit.fnHeaderCallback, 'user' ); + _fnCallbackReg( oSettings, 'aoFooterCallback', oInit.fnFooterCallback, 'user' ); + _fnCallbackReg( oSettings, 'aoInitComplete', oInit.fnInitComplete, 'user' ); + _fnCallbackReg( oSettings, 'aoPreDrawCallback', oInit.fnPreDrawCallback, 'user' ); + + oSettings.rowIdFn = _fnGetObjectDataFn( oInit.rowId ); + + /* Browser support detection */ + _fnBrowserDetect( oSettings ); + + var oClasses = oSettings.oClasses; + + // @todo Remove in 1.11 + if ( oInit.bJQueryUI ) + { + /* Use the JUI classes object for display. You could clone the oStdClasses object if + * you want to have multiple tables with multiple independent classes + */ + $.extend( oClasses, DataTable.ext.oJUIClasses, oInit.oClasses ); + + if ( oInit.sDom === defaults.sDom && defaults.sDom === "lfrtip" ) + { + /* Set the DOM to use a layout suitable for jQuery UI's theming */ + oSettings.sDom = '<"H"lfr>t<"F"ip>'; + } + + if ( ! oSettings.renderer ) { + oSettings.renderer = 'jqueryui'; + } + else if ( $.isPlainObject( oSettings.renderer ) && ! oSettings.renderer.header ) { + oSettings.renderer.header = 'jqueryui'; + } + } + else + { + $.extend( oClasses, DataTable.ext.classes, oInit.oClasses ); + } + $this.addClass( oClasses.sTable ); + + + if ( oSettings.iInitDisplayStart === undefined ) + { + /* Display start point, taking into account the save saving */ + oSettings.iInitDisplayStart = oInit.iDisplayStart; + oSettings._iDisplayStart = oInit.iDisplayStart; + } + + if ( oInit.iDeferLoading !== null ) + { + oSettings.bDeferLoading = true; + var tmp = $.isArray( oInit.iDeferLoading ); + oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading; + oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading; + } + + /* Language definitions */ + var oLanguage = oSettings.oLanguage; + $.extend( true, oLanguage, oInit.oLanguage ); + + if ( oLanguage.sUrl !== "" ) + { + /* Get the language definitions from a file - because this Ajax call makes the language + * get async to the remainder of this function we use bInitHandedOff to indicate that + * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor + */ + $.ajax( { + dataType: 'json', + url: oLanguage.sUrl, + success: function ( json ) { + _fnLanguageCompat( json ); + _fnCamelToHungarian( defaults.oLanguage, json ); + $.extend( true, oLanguage, json ); + _fnInitialise( oSettings ); + }, + error: function () { + // Error occurred loading language file, continue on as best we can + _fnInitialise( oSettings ); + } + } ); + bInitHandedOff = true; + } + + /* + * Stripes + */ + if ( oInit.asStripeClasses === null ) + { + oSettings.asStripeClasses =[ + oClasses.sStripeOdd, + oClasses.sStripeEven + ]; + } + + /* Remove row stripe classes if they are already on the table row */ + var stripeClasses = oSettings.asStripeClasses; + var rowOne = $this.children('tbody').find('tr').eq(0); + if ( $.inArray( true, $.map( stripeClasses, function(el, i) { + return rowOne.hasClass(el); + } ) ) !== -1 ) { + $('tbody tr', this).removeClass( stripeClasses.join(' ') ); + oSettings.asDestroyStripes = stripeClasses.slice(); + } + + /* + * Columns + * See if we should load columns automatically or use defined ones + */ + var anThs = []; + var aoColumnsInit; + var nThead = this.getElementsByTagName('thead'); + if ( nThead.length !== 0 ) + { + _fnDetectHeader( oSettings.aoHeader, nThead[0] ); + anThs = _fnGetUniqueThs( oSettings ); + } + + /* If not given a column array, generate one with nulls */ + if ( oInit.aoColumns === null ) + { + aoColumnsInit = []; + for ( i=0, iLen=anThs.length ; i<iLen ; i++ ) + { + aoColumnsInit.push( null ); + } + } + else + { + aoColumnsInit = oInit.aoColumns; + } + + /* Add the columns */ + for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ ) + { + _fnAddColumn( oSettings, anThs ? anThs[i] : null ); + } + + /* Apply the column definitions */ + _fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) { + _fnColumnOptions( oSettings, iCol, oDef ); + } ); + + /* HTML5 attribute detection - build an mData object automatically if the + * attributes are found + */ + if ( rowOne.length ) { + var a = function ( cell, name ) { + return cell.getAttribute( 'data-'+name ) !== null ? name : null; + }; + + $( rowOne[0] ).children('th, td').each( function (i, cell) { + var col = oSettings.aoColumns[i]; + + if ( col.mData === i ) { + var sort = a( cell, 'sort' ) || a( cell, 'order' ); + var filter = a( cell, 'filter' ) || a( cell, 'search' ); + + if ( sort !== null || filter !== null ) { + col.mData = { + _: i+'.display', + sort: sort !== null ? i+'.@data-'+sort : undefined, + type: sort !== null ? i+'.@data-'+sort : undefined, + filter: filter !== null ? i+'.@data-'+filter : undefined + }; + + _fnColumnOptions( oSettings, i ); + } + } + } ); + } + + var features = oSettings.oFeatures; + + /* Must be done after everything which can be overridden by the state saving! */ + if ( oInit.bStateSave ) + { + features.bStateSave = true; + _fnLoadState( oSettings, oInit ); + _fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' ); + } + + + /* + * Sorting + * @todo For modularisation (1.11) this needs to do into a sort start up handler + */ + + // If aaSorting is not defined, then we use the first indicator in asSorting + // in case that has been altered, so the default sort reflects that option + if ( oInit.aaSorting === undefined ) + { + var sorting = oSettings.aaSorting; + for ( i=0, iLen=sorting.length ; i<iLen ; i++ ) + { + sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0]; + } + } + + /* Do a first pass on the sorting classes (allows any size changes to be taken into + * account, and also will apply sorting disabled classes if disabled + */ + _fnSortingClasses( oSettings ); + + if ( features.bSort ) + { + _fnCallbackReg( oSettings, 'aoDrawCallback', function () { + if ( oSettings.bSorted ) { + var aSort = _fnSortFlatten( oSettings ); + var sortedColumns = {}; + + $.each( aSort, function (i, val) { + sortedColumns[ val.src ] = val.dir; + } ); + + _fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] ); + _fnSortAria( oSettings ); + } + } ); + } + + _fnCallbackReg( oSettings, 'aoDrawCallback', function () { + if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) { + _fnSortingClasses( oSettings ); + } + }, 'sc' ); + + + /* + * Final init + * Cache the header, body and footer as required, creating them if needed + */ + + // Work around for Webkit bug 83867 - store the caption-side before removing from doc + var captions = $this.children('caption').each( function () { + this._captionSide = $this.css('caption-side'); + } ); + + var thead = $this.children('thead'); + if ( thead.length === 0 ) + { + thead = $('<thead/>').appendTo(this); + } + oSettings.nTHead = thead[0]; + + var tbody = $this.children('tbody'); + if ( tbody.length === 0 ) + { + tbody = $('<tbody/>').appendTo(this); + } + oSettings.nTBody = tbody[0]; + + var tfoot = $this.children('tfoot'); + if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") ) + { + // If we are a scrolling table, and no footer has been given, then we need to create + // a tfoot element for the caption element to be appended to + tfoot = $('<tfoot/>').appendTo(this); + } + + if ( tfoot.length === 0 || tfoot.children().length === 0 ) { + $this.addClass( oClasses.sNoFooter ); + } + else if ( tfoot.length > 0 ) { + oSettings.nTFoot = tfoot[0]; + _fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot ); + } + + /* Check if there is data passing into the constructor */ + if ( oInit.aaData ) + { + for ( i=0 ; i<oInit.aaData.length ; i++ ) + { + _fnAddData( oSettings, oInit.aaData[ i ] ); + } + } + else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' ) + { + /* Grab the data from the page - only do this when deferred loading or no Ajax + * source since there is no point in reading the DOM data if we are then going + * to replace it with Ajax data + */ + _fnAddTr( oSettings, $(oSettings.nTBody).children('tr') ); + } + + /* Copy the data index array */ + oSettings.aiDisplay = oSettings.aiDisplayMaster.slice(); + + /* Initialisation complete - table can be drawn */ + oSettings.bInitialised = true; + + /* Check if we need to initialise the table (it might not have been handed off to the + * language processor) + */ + if ( bInitHandedOff === false ) + { + _fnInitialise( oSettings ); + } + } ); + _that = null; + return this; + }; /* @@ -317,6 +1580,65 @@ }; + /** + * DataTables utility methods + * + * This namespace provides helper methods that DataTables uses internally to + * create a DataTable, but which are not exclusively used only for DataTables. + * These methods can be used by extension authors to save the duplication of + * code. + * + * @namespace + */ + DataTable.util = { + /** + * Throttle the calls to a function. Arguments and context are maintained + * for the throttled function. + * + * @param {function} fn Function to be called + * @param {integer} freq Call frequency in mS + * @return {function} Wrapped function + */ + throttle: function ( fn, freq ) { + var + frequency = freq !== undefined ? freq : 200, + last, + timer; + + return function () { + var + that = this, + now = +new Date(), + args = arguments; + + if ( last && now < last + frequency ) { + clearTimeout( timer ); + + timer = setTimeout( function () { + last = undefined; + fn.apply( that, args ); + }, frequency ); + } + else { + last = now; + fn.apply( that, args ); + } + }; + }, + + + /** + * Escape a string such that it can be used in a regular expression + * + * @param {string} val string to escape + * @returns {string} escaped string + */ + escapeRegex: function ( val ) { + return val.replace( _re_escape_regex, '\\$1' ); + } + }; + + /** * Create a mapping object that allows camel case parameters to be looked up @@ -467,6 +1789,14 @@ _fnCompatMap( init, 'pageLength', 'iDisplayLength' ); _fnCompatMap( init, 'searching', 'bFilter' ); + // Boolean initialisation of x-scrolling + if ( typeof init.sScrollX === 'boolean' ) { + init.sScrollX = init.sScrollX ? '100%' : ''; + } + if ( typeof init.scrollX === 'boolean' ) { + init.scrollX = init.scrollX ? '100%' : ''; + } + // Column search objects are in an array, so it needs to be converted // element by element var searchCols = init.aoSearchCols; @@ -509,49 +1839,75 @@ */ function _fnBrowserDetect( settings ) { - var browser = settings.oBrowser; + // We don't need to do this every time DataTables is constructed, the values + // calculated are specific to the browser and OS configuration which we + // don't expect to change between initialisations + if ( ! DataTable.__browser ) { + var browser = {}; + DataTable.__browser = browser; + + // Scrolling feature / quirks detection + var n = $('<div/>') + .css( { + position: 'fixed', + top: 0, + left: 0, + height: 1, + width: 1, + overflow: 'hidden' + } ) + .append( + $('<div/>') + .css( { + position: 'absolute', + top: 1, + left: 1, + width: 100, + overflow: 'scroll' + } ) + .append( + $('<div/>') + .css( { + width: '100%', + height: 10 + } ) + ) + ) + .appendTo( 'body' ); - // Scrolling feature / quirks detection - var n = $('<div/>') - .css( { - position: 'absolute', - top: 0, - left: 0, - height: 1, - width: 1, - overflow: 'hidden' - } ) - .append( - $('<div/>') - .css( { - position: 'absolute', - top: 1, - left: 1, - width: 100, - overflow: 'scroll' - } ) - .append( - $('<div class="test"/>') - .css( { - width: '100%', - height: 10 - } ) - ) - ) - .appendTo( 'body' ); + var outer = n.children(); + var inner = outer.children(); - var test = n.find('.test'); + // Numbers below, in order, are: + // inner.offsetWidth, inner.clientWidth, outer.offsetWidth, outer.clientWidth + // + // IE6 XP: 100 100 100 83 + // IE7 Vista: 100 100 100 83 + // IE 8+ Windows: 83 83 100 83 + // Evergreen Windows: 83 83 100 83 + // Evergreen Mac with scrollbars: 85 85 100 85 + // Evergreen Mac without scrollbars: 100 100 100 100 - // IE6/7 will oversize a width 100% element inside a scrolling element, to - // include the width of the scrollbar, while other browsers ensure the inner - // element is contained without forcing scrolling - browser.bScrollOversize = test[0].offsetWidth === 100; + // Get scrollbar width + browser.barWidth = outer[0].offsetWidth - outer[0].clientWidth; - // In rtl text layout, some browsers (most, but not all) will place the - // scrollbar on the left, rather than the right. - browser.bScrollbarLeft = Math.round( test.offset().left ) !== 1; + // IE6/7 will oversize a width 100% element inside a scrolling element, to + // include the width of the scrollbar, while other browsers ensure the inner + // element is contained without forcing scrolling + browser.bScrollOversize = inner[0].offsetWidth === 100 && outer[0].clientWidth !== 100; - n.remove(); + // In rtl text layout, some browsers (most, but not all) will place the + // scrollbar on the left, rather than the right. + browser.bScrollbarLeft = Math.round( inner.offset().left ) !== 1; + + // IE8- don't provide height and width for getBoundingClientRect + browser.bBounding = n[0].getBoundingClientRect().width ? true : false; + + n.remove(); + } + + $.extend( settings.oBrowser, DataTable.__browser ); + settings.oScroll.iBarWidth = DataTable.__browser.barWidth; } @@ -640,7 +1996,7 @@ oCol.sWidthOrig = th.attr('width') || null; // Style attribute - var t = (th.attr('style') || '').match(/width:\s*(\d+[px|em|%]+)/); + var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/); if ( t ) { oCol.sWidthOrig = t[1]; } @@ -697,6 +2053,7 @@ oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && ( attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter) ); + oCol._setter = null; oCol.fnGetData = function (rowData, type, meta) { var innerData = mData( rowData, type, undefined, meta ); @@ -821,7 +2178,16 @@ */ function _fnVisbleColumns( oSettings ) { - return _fnGetColumns( oSettings, 'bVisible' ).length; + var vis = 0; + + // No reduce in IE8, use a loop for now + $.each( oSettings.aoColumns, function ( i, col ) { + if ( col.bVisible && $(col.nTh).css('display') !== 'none' ) { + vis++; + } + } ); + + return vis; } @@ -860,7 +2226,7 @@ var i, ien, j, jen, k, ken; var col, cell, detectedType, cache; - // For each column, spin over the + // For each column, spin over the for ( i=0, ien=columns.length ; i<ien ; i++ ) { col = columns[i]; cache = []; @@ -1008,7 +2374,8 @@ /* Create the object for storing information about this new row */ var iRow = oSettings.aoData.length; var oData = $.extend( true, {}, DataTable.models.oRow, { - src: nTr ? 'dom' : 'data' + src: nTr ? 'dom' : 'data', + idx: iRow } ); oData._aData = aDataIn; @@ -1017,20 +2384,21 @@ /* Create the cells */ var nTd, sThisType; var columns = oSettings.aoColumns; + + // Invalidate the column types as the new data needs to be revalidated for ( var i=0, iLen=columns.length ; i<iLen ; i++ ) { - // When working with a row, the data source object must be populated. In - // all other cases, the data source object is already populated, so we - // don't overwrite it, which might break bindings etc - if ( nTr ) { - _fnSetCellData( oSettings, iRow, i, _fnGetCellData( oSettings, iRow, i ) ); - } columns[i].sType = null; } /* Add to the display array */ oSettings.aiDisplayMaster.push( iRow ); + var id = oSettings.rowIdFn( aDataIn ); + if ( id !== undefined ) { + oSettings.aIds[ id ] = oData; + } + /* Create the DOM information, or register it if already present */ if ( nTr || ! oSettings.oFeatures.bDeferRender ) { @@ -1119,14 +2487,15 @@ if ( settings.iDrawError != draw && defaultContent === null ) { _fnLog( settings, 0, "Requested unknown parameter "+ (typeof col.mData=='function' ? '{function}' : "'"+col.mData+"'")+ - " for row "+rowIdx, 4 ); + " for row "+rowIdx+", column "+colIdx, 4 ); settings.iDrawError = draw; } return defaultContent; } - /* When the data source is null, we can use default column data */ - if ( (cellData === rowData || cellData === null) && defaultContent !== null ) { + // When the data source is null and a specific data type is requested (i.e. + // not the original data), we can use default column data + if ( (cellData === rowData || cellData === null) && defaultContent !== null && type !== undefined ) { cellData = defaultContent; } else if ( typeof cellData === 'function' ) { @@ -1174,7 +2543,7 @@ */ function _fnSplitObjNotation( str ) { - return $.map( str.match(/(\\.|[^\.])+/g), function ( s ) { + return $.map( str.match(/(\\.|[^\.])+/g) || [''], function ( s ) { return s.replace(/\\./g, '.'); } ); } @@ -1257,8 +2626,10 @@ innerSrc = a.join('.'); // Traverse each entry in the array getting the properties requested - for ( var j=0, jLen=data.length ; j<jLen ; j++ ) { - out.push( fetchData( data[j], type, innerSrc ) ); + if ( $.isArray( data ) ) { + for ( var j=0, jLen=data.length ; j<jLen ; j++ ) { + out.push( fetchData( data[j], type, innerSrc ) ); + } } // If a string is given in between the array notation indicators, that @@ -1358,11 +2729,21 @@ innerSrc = b.join('.'); // Traverse each entry in the array setting the properties requested - for ( var j=0, jLen=val.length ; j<jLen ; j++ ) + if ( $.isArray( val ) ) { - o = {}; - setData( o, val[j], innerSrc ); - data[ a[i] ].push( o ); + for ( var j=0, jLen=val.length ; j<jLen ; j++ ) + { + o = {}; + setData( o, val[j], innerSrc ); + data[ a[i] ].push( o ); + } + } + else + { + // We've been asked to save data to an array, but it + // isn't array data to be saved. Best that can be done + // is to just save the value. + data[ a[i] ] = val; } // The inner call to setData has already traversed through the remainder @@ -1435,6 +2816,7 @@ settings.aoData.length = 0; settings.aiDisplayMaster.length = 0; settings.aiDisplay.length = 0; + settings.aIds = {}; } @@ -1540,7 +2922,7 @@ } // Update DataTables special `DT_*` attributes for the row - _fnRowAttributes( row ); + _fnRowAttributes( settings, row ); } } @@ -1572,7 +2954,11 @@ objectRead = settings._rowReadObject; // Allow the data object to be passed in, or construct - d = d || objectRead ? {} : []; + d = d !== undefined ? + d : + objectRead ? + {} : + []; var attr = function ( str, td ) { if ( typeof str === 'string' ) { @@ -1635,12 +3021,23 @@ else { // Existing row object passed in tds = row.anCells; - + for ( var j=0, jen=tds.length ; j<jen ; j++ ) { cellProcess( tds[j] ); } } + // Read the ID from the DOM if present + var rowNode = row.firstChild ? row : row.nTr; + + if ( rowNode ) { + var id = rowNode.getAttribute( 'id' ); + + if ( id ) { + _fnSetObjectDataFn( settings.rowId )( d, id ); + } + } + return { data: d, cells: tds @@ -1678,7 +3075,7 @@ nTr._DT_RowIndex = iRow; /* Special parameters can be given by the data source to be used on the row */ - _fnRowAttributes( row ); + _fnRowAttributes( oSettings, row ); /* Process each column */ for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) @@ -1686,11 +3083,17 @@ oCol = oSettings.aoColumns[i]; nTd = nTrIn ? anTds[i] : document.createElement( oCol.sCellType ); + nTd._DT_CellIndex = { + row: iRow, + column: i + }; + cells.push( nTd ); // Need to create the HTML if new, or if a rendering function is defined - if ( !nTrIn || oCol.mRender || oCol.mData !== i ) - { + if ( (!nTrIn || oCol.mRender || oCol.mData !== i) && + (!$.isPlainObject(oCol.mData) || oCol.mData._ !== i+'.display') + ) { nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' ); } @@ -1730,17 +3133,20 @@ /** * Add attributes to a row based on the special `DT_*` parameters in a data * source object. + * @param {object} settings DataTables settings object * @param {object} DataTables row object for the row to be modified * @memberof DataTable#oApi */ - function _fnRowAttributes( row ) + function _fnRowAttributes( settings, row ) { var tr = row.nTr; var data = row._aData; if ( tr ) { - if ( data.DT_RowId ) { - tr.id = data.DT_RowId; + var id = settings.rowIdFn( data ); + + if ( id ) { + tr.id = id; } if ( data.DT_RowClass ) { @@ -1805,7 +3211,7 @@ } } - if ( column.sTitle != cell.html() ) { + if ( column.sTitle != cell[0].innerHTML ) { cell.html( column.sTitle ); } @@ -2277,6 +3683,7 @@ /* Built our DOM structure - replace the holding div with what we want */ holding.replaceWith( insert ); + oSettings.nHolding = null; } @@ -2909,7 +4316,7 @@ // So the array reference doesn't break set the results into the // existing array displayRows.length = 0; - displayRows.push.apply( displayRows, rows ); + $.merge( displayRows, rows ); } } @@ -3017,7 +4424,7 @@ * word order. We also want double quoted text to be preserved, so word * order is important - a la google. So this is what we want to * generate: - * + * * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$ */ var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || [''], function ( word ) { @@ -3042,12 +4449,7 @@ * @returns {string} escaped string * @memberof DataTable#oApi */ - function _fnEscapeRegex ( sVal ) - { - return sVal.replace( _re_escape_regex, '\\$1' ); - } - - + var _fnEscapeRegex = DataTable.util.escapeRegex; var __filter_div = $('<div>')[0]; var __filter_div_textContent = __filter_div.textContent !== undefined; @@ -3265,6 +4667,7 @@ var i, iLen, iAjaxStart=settings.iInitDisplayStart; var columns = settings.aoColumns, column; var features = settings.oFeatures; + var deferLoading = settings.bDeferLoading; // value modified by the draw /* Ensure that the table data is fully initialised */ if ( ! settings.bInitialised ) { @@ -3296,6 +4699,8 @@ } } + _fnCallbackFire( settings, null, 'preInit', [settings] ); + // If there is default sorting required - let's do it. The sort function // will do the drawing for us. Otherwise we draw the table regardless of the // Ajax source - this allows the table to look initialised for Ajax sourcing @@ -3304,7 +4709,7 @@ // Server-side processing init complete is done by _fnAjaxUpdateDraw var dataSrc = _fnDataSource( settings ); - if ( dataSrc != 'ssp' ) { + if ( dataSrc != 'ssp' || deferLoading ) { // if there is an ajax source load the data if ( dataSrc == 'ajax' ) { _fnBuildAjax( settings, [], function(json) { @@ -3345,12 +4750,13 @@ { settings._bInitComplete = true; - // On an Ajax load we now have data and therefore want to apply the column - // sizing - if ( json ) { + // When data was added after the initialisation (data or Ajax) we need to + // calculate the column sizing + if ( json || settings.oInit.aaData ) { _fnAdjustColumnSizing( settings ); } + _fnCallbackFire( settings, null, 'plugin-init', [settings, json] ); _fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] ); } @@ -3627,17 +5033,6 @@ return !s ? null : _fnStringToCss( s ); }; - // This is fairly messy, but with x scrolling enabled, if the table has a - // width attribute, regardless of any width applied using the column width - // options, the browser will shrink or grow the table as needed to fit into - // that 100%. That would make the width options useless. So we remove it. - // This is okay, under the assumption that width:100% is applied to the - // table in CSS (it is in the default stylesheet) which will set the table - // width as appropriate (the attribute and css behave differently...) - if ( scroll.sX && table.attr('width') === '100%' ) { - table.removeAttr('width'); - } - if ( ! footer.length ) { footer = null; } @@ -3687,8 +5082,8 @@ .append( $(_div, { 'class': classes.sScrollBody } ) .css( { + position: 'relative', overflow: 'auto', - height: size( scrollY ), width: size( scrollX ) } ) .append( table ) @@ -3735,6 +5130,11 @@ } ); } + $(scrollBody).css( + scrollY && scroll.bCollapse ? 'max-height' : 'height', + scrollY + ); + settings.nScrollHead = scrollHead; settings.nScrollBody = scrollBody; settings.nScrollFoot = scrollFoot; @@ -3792,11 +5192,12 @@ footer = settings.nTFoot ? $(settings.nTFoot) : null, browser = settings.oBrowser, ie67 = browser.bScrollOversize, + dtHeaderCells = _pluck( settings.aoColumns, 'nTh' ), headerTrgEls, footerTrgEls, headerSrcEls, footerSrcEls, headerCopy, footerCopy, headerWidths=[], footerWidths=[], - headerContent=[], + headerContent=[], footerContent=[], idx, correction, sanityWidth, zeroOut = function(nSizer) { var style = nSizer.style; @@ -3807,6 +5208,20 @@ style.height = 0; }; + // If the scrollbar visibility has changed from the last draw, we need to + // adjust the column sizes as the table width will have changed to account + // for the scrollbar + var scrollBarVis = divBodyEl.scrollHeight > divBodyEl.clientHeight; + + if ( settings.scrollBarVis !== scrollBarVis && settings.scrollBarVis !== undefined ) { + settings.scrollBarVis = scrollBarVis; + _fnAdjustColumnSizing( settings ); + return; // adjust column sizing will call this function again + } + else { + settings.scrollBarVis = scrollBarVis; + } + /* * 1. Re-create the table inside the scrolling div */ @@ -3814,18 +5229,18 @@ // Remove the old minimised thead and tfoot elements in the inner table table.children('thead, tfoot').remove(); - // Clone the current header and footer elements and then place it into the inner table - headerCopy = header.clone().prependTo( table ); - headerTrgEls = header.find('tr'); // original header is in its own table - headerSrcEls = headerCopy.find('tr'); - headerCopy.find('th, td').removeAttr('tabindex'); - if ( footer ) { footerCopy = footer.clone().prependTo( table ); footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized footerSrcEls = footerCopy.find('tr'); } + // Clone the current header and footer elements and then place it into the inner table + headerCopy = header.clone().prependTo( table ); + headerTrgEls = header.find('tr'); // original header is in its own table + headerSrcEls = headerCopy.find('tr'); + headerCopy.find('th, td').removeAttr('tabindex'); + /* * 2. Take live measurements from the DOM - do not alter the DOM itself! @@ -3851,13 +5266,6 @@ }, footerSrcEls ); } - // If scroll collapse is enabled, when we put the headers back into the body for sizing, we - // will end up forcing the scrollbar to appear, making our measurements wrong for when we - // then hide it (end of this function), so add the header height to the body scroller. - if ( scroll.bCollapse && scrollY !== "" ) { - divBodyStyle.height = (divBody[0].offsetHeight + header[0].offsetHeight)+"px"; - } - // Size the table as a whole sanityWidth = table.outerWidth(); if ( scrollX === "" ) { @@ -3872,32 +5280,17 @@ ) { tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth); } + + // Recalculate the sanity width + sanityWidth = table.outerWidth(); } - else - { - // x scrolling - if ( scrollXInner !== "" ) { - // x scroll inner has been given - use it - tableStyle.width = _fnStringToCss(scrollXInner); - } - else if ( sanityWidth == divBody.width() && divBody.height() < table.height() ) { - // There is y-scrolling - try to take account of the y scroll bar - tableStyle.width = _fnStringToCss( sanityWidth-barWidth ); - if ( table.outerWidth() > sanityWidth-barWidth ) { - // Not possible to take account of it - tableStyle.width = _fnStringToCss( sanityWidth ); - } - } - else { - // When all else fails - tableStyle.width = _fnStringToCss( sanityWidth ); - } - } + else if ( scrollXInner !== "" ) { + // legacy x scroll inner has been given - use it + tableStyle.width = _fnStringToCss(scrollXInner); - // Recalculate the sanity width - now that we've applied the required width, - // before it was a temporary variable. This is required because the column - // width calculation is done before this table DOM is created. - sanityWidth = table.outerWidth(); + // Recalculate the sanity width + sanityWidth = table.outerWidth(); + } // Hidden header should have zero height, so remove padding and borders. Then // set the width based on the real headers @@ -3913,7 +5306,11 @@ // Apply all widths in final pass _fnApplyToChildren( function(nToSize, i) { - nToSize.style.width = headerWidths[i]; + // Only apply widths to the DataTables detected header cells - this + // prevents complex headers from having contradictory sizes applied + if ( $.inArray( nToSize, dtHeaderCells ) !== -1 ) { + nToSize.style.width = headerWidths[i]; + } }, headerTrgEls ); $(headerSrcEls).height(0); @@ -3924,6 +5321,7 @@ _fnApplyToChildren( zeroOut, footerSrcEls ); _fnApplyToChildren( function(nSizer) { + footerContent.push( nSizer.innerHTML ); footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) ); }, footerSrcEls ); @@ -3951,7 +5349,7 @@ if ( footer ) { _fnApplyToChildren( function(nSizer, i) { - nSizer.innerHTML = ""; + nSizer.innerHTML = '<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+footerContent[i]+'</div>'; nSizer.style.width = footerWidths[i]; }, footerSrcEls ); } @@ -4005,18 +5403,6 @@ } } - if ( scrollY && scroll.bCollapse ) { - divBodyStyle.height = _fnStringToCss( scrollY ); - - var iExtra = (scrollX && tableEl.offsetWidth > divBodyEl.offsetWidth) ? - barWidth : - 0; - - if ( tableEl.offsetHeight < divBodyEl.offsetHeight ) { - divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+iExtra ); - } - } - /* Finally set the width's of the header and footer tables */ var iOuterWidth = table.outerWidth(); divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth ); @@ -4034,6 +5420,9 @@ divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px"; } + // Correct DOM ordering for colgroup - comes before the thead + table.children('colgroup').insertBefore( table.children('thead') ); + /* Adjust the position of the header in case we loose the y-scrollbar */ divBody.scroll(); @@ -4108,7 +5497,9 @@ tableWidthAttr = table.getAttribute('width'), // from DOM element tableContainer = table.parentNode, userInputs = false, - i, column, columnIdx, width, outerWidth; + i, column, columnIdx, width, outerWidth, + browser = oSettings.oBrowser, + ie67 = browser.bScrollOversize; var styleWidth = table.style.width; if ( styleWidth && styleWidth.indexOf('%') !== -1 ) { @@ -4131,12 +5522,16 @@ * the web- browser. No custom sizes can be set in order for this to happen, * nor scrolling used */ - if ( ! userInputs && ! scrollX && ! scrollY && - columnCount == _fnVisbleColumns( oSettings ) && - columnCount == headerCells.length + if ( ie67 || ! userInputs && ! scrollX && ! scrollY && + columnCount == _fnVisbleColumns( oSettings ) && + columnCount == headerCells.length ) { for ( i=0 ; i<columnCount ; i++ ) { - columns[i].sWidth = _fnStringToCss( headerCells.eq(i).width() ); + var colIdx = _fnVisibleToColumnIndex( oSettings, i ); + + if ( colIdx !== null ) { + columns[ colIdx ].sWidth = _fnStringToCss( headerCells.eq(i).width() ); + } } } else @@ -4153,6 +5548,14 @@ tmpTable.find('tbody tr').remove(); var tr = $('<tr/>').appendTo( tmpTable.find('tbody') ); + // Clone the table header and footer - we can't use the header / footer + // from the cloned table, since if scrolling is active, the table's + // real header and footer are contained in different table tags + tmpTable.find('thead, tfoot').remove(); + tmpTable + .append( $(oSettings.nTHead).clone() ) + .append( $(oSettings.nTFoot).clone() ); + // Remove any assigned widths from the footer (from scrolling) tmpTable.find('tfoot th, tfoot td').css('width', ''); @@ -4165,6 +5568,19 @@ headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ? _fnStringToCss( column.sWidthOrig ) : ''; + + // For scrollX we need to force the column width otherwise the + // browser will collapse it. If this width is smaller than the + // width the column requires, then it will have no effect + if ( column.sWidthOrig && scrollX ) { + $( headerCells[i] ).append( $('<div/>').css( { + width: column.sWidthOrig, + margin: 0, + padding: 0, + border: 0, + height: 1 + } ) ); + } } // Find the widest cell for each column and put it into the table @@ -4180,10 +5596,30 @@ } } - // Table has been built, attach to the document so we can work with it - tmpTable.appendTo( tableContainer ); + // Tidy the temporary table - remove name attributes so there aren't + // duplicated in the dom (radio elements for example) + $('[name]', tmpTable).removeAttr('name'); + + // Table has been built, attach to the document so we can work with it. + // A holding element is used, positioned at the top of the container + // with minimal height, so it has no effect on if the container scrolls + // or not. Otherwise it might trigger scrolling when it actually isn't + // needed + var holder = $('<div/>').css( scrollX || scrollY ? + { + position: 'absolute', + top: 0, + left: 0, + height: 1, + right: 0, + overflow: 'hidden' + } : + {} + ) + .append( tmpTable ) + .appendTo( tableContainer ); - // When scrolling (X or Y) we want to set the width of the table as + // When scrolling (X or Y) we want to set the width of the table as // appropriate. However, when not scrolling leave the table width as it // is. This results in slightly different, but I think correct behaviour if ( scrollX && scrollXInner ) { @@ -4191,57 +5627,50 @@ } else if ( scrollX ) { tmpTable.css( 'width', 'auto' ); + tmpTable.removeAttr('width'); - if ( tmpTable.width() < tableContainer.offsetWidth ) { - tmpTable.width( tableContainer.offsetWidth ); + // If there is no width attribute or style, then allow the table to + // collapse + if ( tmpTable.width() < tableContainer.clientWidth && tableWidthAttr ) { + tmpTable.width( tableContainer.clientWidth ); } } else if ( scrollY ) { - tmpTable.width( tableContainer.offsetWidth ); + tmpTable.width( tableContainer.clientWidth ); } else if ( tableWidthAttr ) { tmpTable.width( tableWidthAttr ); } - // Take into account the y scrollbar - _fnScrollingWidthAdjust( oSettings, tmpTable[0] ); - - // Browsers need a bit of a hand when a width is assigned to any columns - // when x-scrolling as they tend to collapse the table to the min-width, - // even if we sent the column widths. So we need to keep track of what - // the table width should be by summing the user given values, and the - // automatic values - if ( scrollX ) - { - var total = 0; - - for ( i=0 ; i<visibleColumns.length ; i++ ) { - column = columns[ visibleColumns[i] ]; - outerWidth = $(headerCells[i]).outerWidth(); - - total += column.sWidthOrig === null ? - outerWidth : - parseInt( column.sWidth, 10 ) + outerWidth - $(headerCells[i]).width(); - } + // Get the width of each column in the constructed table - we need to + // know the inner width (so it can be assigned to the other table's + // cells) and the outer width so we can calculate the full width of the + // table. This is safe since DataTables requires a unique cell for each + // column, but if ever a header can span multiple columns, this will + // need to be modified. + var total = 0; + for ( i=0 ; i<visibleColumns.length ; i++ ) { + var cell = $(headerCells[i]); + var border = cell.outerWidth() - cell.width(); - tmpTable.width( _fnStringToCss( total ) ); - table.style.width = _fnStringToCss( total ); - } + // Use getBounding... where possible (not IE8-) because it can give + // sub-pixel accuracy, which we then want to round up! + var bounding = browser.bBounding ? + Math.ceil( headerCells[i].getBoundingClientRect().width ) : + cell.outerWidth(); - // Get the width of each column in the constructed table - for ( i=0 ; i<visibleColumns.length ; i++ ) { - column = columns[ visibleColumns[i] ]; - width = $(headerCells[i]).width(); + // Total is tracked to remove any sub-pixel errors as the outerWidth + // of the table might not equal the total given here (IE!). + total += bounding; - if ( width ) { - column.sWidth = _fnStringToCss( width ); - } + // Width for each column to use + columns[ visibleColumns[i] ].sWidth = _fnStringToCss( bounding - border ); } - table.style.width = _fnStringToCss( tmpTable.css('width') ); + table.style.width = _fnStringToCss( total ); // Finished with the table - ditch it - tmpTable.remove(); + holder.remove(); } // If there is a width attr, we want to attach an event listener which @@ -4261,7 +5690,7 @@ // IE6/7 will crash if we bind a resize event handler on page load. // To be removed in 1.11 which drops IE6/7 support - if ( oSettings.oBrowser.bScrollOversize ) { + if ( ie67 ) { setTimeout( bindResize, 1000 ); } else { @@ -4281,32 +5710,7 @@ * @returns {function} wrapped function * @memberof DataTable#oApi */ - function _fnThrottle( fn, freq ) { - var - frequency = freq !== undefined ? freq : 200, - last, - timer; - - return function () { - var - that = this, - now = +new Date(), - args = arguments; - - if ( last && now < last + frequency ) { - clearTimeout( timer ); - - timer = setTimeout( function () { - last = undefined; - fn.apply( that, args ); - }, frequency ); - } - else { - last = now; - fn.apply( that, args ); - } - }; - } + var _fnThrottle = DataTable.util.throttle; /** @@ -4334,27 +5738,6 @@ /** - * Adjust a table's width to take account of vertical scroll bar - * @param {object} oSettings dataTables settings object - * @param {node} n table node - * @memberof DataTable#oApi - */ - - function _fnScrollingWidthAdjust ( settings, n ) - { - var scroll = settings.oScroll; - - if ( scroll.sX || scroll.sY ) { - // When y-scrolling only, we want to remove the width of the scroll bar - // so the table + scroll bar will fit into the area available, otherwise - // we fix the table at its current size with no adjustment - var correction = ! scroll.sX ? scroll.iBarWidth : 0; - n.style.width = _fnStringToCss( $(n).outerWidth() - correction ); - } - } - - - /** * Get the widest node * @param {object} settings dataTables settings object * @param {int} colIdx column of interest @@ -4389,6 +5772,7 @@ for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) { s = _fnGetCellData( settings, i, colIdx, 'display' )+''; s = s.replace( __re_html_remove, '' ); + s = s.replace( / /g, ' ' ); if ( s.length > max ) { max = s.length; @@ -4425,40 +5809,6 @@ } - /** - * Get the width of a scroll bar in this browser being used - * @returns {int} width in pixels - * @memberof DataTable#oApi - */ - function _fnScrollBarWidth () - { - // On first run a static variable is set, since this is only needed once. - // Subsequent runs will just use the previously calculated value - var width = DataTable.__scrollbarWidth; - - if ( width === undefined ) { - var sizer = $('<p/>').css( { - position: 'absolute', - top: 0, - left: 0, - width: '100%', - height: 150, - padding: 0, - overflow: 'scroll', - visibility: 'hidden' - } ) - .appendTo('body'); - - width = sizer[0].offsetWidth - sizer[0].clientWidth; - DataTable.__scrollbarWidth = width; - - sizer.remove(); - } - - return width; - } - - function _fnSortFlatten ( settings ) { @@ -4478,7 +5828,7 @@ } else { // 2D array - nestedSort.push.apply( nestedSort, a ); + $.merge( nestedSort, a ); } }; @@ -5055,7 +6405,7 @@ function _fnLog( settings, level, msg, tn ) { msg = 'DataTables warning: '+ - (settings!==null ? 'table id='+settings.sTableId+' - ' : '')+msg; + (settings ? 'table id='+settings.sTableId+' - ' : '')+msg; if ( tn ) { msg += '. For more information about this error, please see '+ @@ -5067,7 +6417,9 @@ var ext = DataTable.ext; var type = ext.sErrMode || ext.errMode; - _fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] ); + if ( settings ) { + _fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] ); + } if ( type == 'alert' ) { alert( msg ); @@ -5314,1263 +6666,6 @@ } - DataTable = function( options ) - { - /** - * Perform a jQuery selector action on the table's TR elements (from the tbody) and - * return the resulting jQuery object. - * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on - * @param {object} [oOpts] Optional parameters for modifying the rows to be included - * @param {string} [oOpts.filter=none] Select TR elements that meet the current filter - * criterion ("applied") or all TR elements (i.e. no filter). - * @param {string} [oOpts.order=current] Order of the TR elements in the processed array. - * Can be either 'current', whereby the current sorting of the table is used, or - * 'original' whereby the original order the data was read into the table is used. - * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page - * ("current") or not ("all"). If 'current' is given, then order is assumed to be - * 'current' and filter is 'applied', regardless of what they might be given as. - * @returns {object} jQuery object, filtered by the given selector. - * @dtopt API - * @deprecated Since v1.10 - * - * @example - * $(document).ready(function() { - * var oTable = $('#example').dataTable(); - * - * // Highlight every second row - * oTable.$('tr:odd').css('backgroundColor', 'blue'); - * } ); - * - * @example - * $(document).ready(function() { - * var oTable = $('#example').dataTable(); - * - * // Filter to rows with 'Webkit' in them, add a background colour and then - * // remove the filter, thus highlighting the 'Webkit' rows only. - * oTable.fnFilter('Webkit'); - * oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue'); - * oTable.fnFilter(''); - * } ); - */ - this.$ = function ( sSelector, oOpts ) - { - return this.api(true).$( sSelector, oOpts ); - }; - - - /** - * Almost identical to $ in operation, but in this case returns the data for the matched - * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes - * rather than any descendants, so the data can be obtained for the row/cell. If matching - * rows are found, the data returned is the original data array/object that was used to - * create the row (or a generated array if from a DOM source). - * - * This method is often useful in-combination with $ where both functions are given the - * same parameters and the array indexes will match identically. - * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on - * @param {object} [oOpts] Optional parameters for modifying the rows to be included - * @param {string} [oOpts.filter=none] Select elements that meet the current filter - * criterion ("applied") or all elements (i.e. no filter). - * @param {string} [oOpts.order=current] Order of the data in the processed array. - * Can be either 'current', whereby the current sorting of the table is used, or - * 'original' whereby the original order the data was read into the table is used. - * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page - * ("current") or not ("all"). If 'current' is given, then order is assumed to be - * 'current' and filter is 'applied', regardless of what they might be given as. - * @returns {array} Data for the matched elements. If any elements, as a result of the - * selector, were not TR, TD or TH elements in the DataTable, they will have a null - * entry in the array. - * @dtopt API - * @deprecated Since v1.10 - * - * @example - * $(document).ready(function() { - * var oTable = $('#example').dataTable(); - * - * // Get the data from the first row in the table - * var data = oTable._('tr:first'); - * - * // Do something useful with the data - * alert( "First cell is: "+data[0] ); - * } ); - * - * @example - * $(document).ready(function() { - * var oTable = $('#example').dataTable(); - * - * // Filter to 'Webkit' and get all data for - * oTable.fnFilter('Webkit'); - * var data = oTable._('tr', {"search": "applied"}); - * - * // Do something with the data - * alert( data.length+" rows matched the search" ); - * } ); - */ - this._ = function ( sSelector, oOpts ) - { - return this.api(true).rows( sSelector, oOpts ).data(); - }; - - - /** - * Create a DataTables Api instance, with the currently selected tables for - * the Api's context. - * @param {boolean} [traditional=false] Set the API instance's context to be - * only the table referred to by the `DataTable.ext.iApiIndex` option, as was - * used in the API presented by DataTables 1.9- (i.e. the traditional mode), - * or if all tables captured in the jQuery object should be used. - * @return {DataTables.Api} - */ - this.api = function ( traditional ) - { - return traditional ? - new _Api( - _fnSettingsFromNode( this[ _ext.iApiIndex ] ) - ) : - new _Api( this ); - }; - - - /** - * Add a single new row or multiple rows of data to the table. Please note - * that this is suitable for client-side processing only - if you are using - * server-side processing (i.e. "bServerSide": true), then to add data, you - * must add it to the data source, i.e. the server-side, through an Ajax call. - * @param {array|object} data The data to be added to the table. This can be: - * <ul> - * <li>1D array of data - add a single row with the data provided</li> - * <li>2D array of arrays - add multiple rows in a single call</li> - * <li>object - data object when using <i>mData</i></li> - * <li>array of objects - multiple data objects when using <i>mData</i></li> - * </ul> - * @param {bool} [redraw=true] redraw the table or not - * @returns {array} An array of integers, representing the list of indexes in - * <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to - * the table. - * @dtopt API - * @deprecated Since v1.10 - * - * @example - * // Global var for counter - * var giCount = 2; - * - * $(document).ready(function() { - * $('#example').dataTable(); - * } ); - * - * function fnClickAddRow() { - * $('#example').dataTable().fnAddData( [ - * giCount+".1", - * giCount+".2", - * giCount+".3", - * giCount+".4" ] - * ); - * - * giCount++; - * } - */ - this.fnAddData = function( data, redraw ) - { - var api = this.api( true ); - - /* Check if we want to add multiple rows or not */ - var rows = $.isArray(data) && ( $.isArray(data[0]) || $.isPlainObject(data[0]) ) ? - api.rows.add( data ) : - api.row.add( data ); - - if ( redraw === undefined || redraw ) { - api.draw(); - } - - return rows.flatten().toArray(); - }; - - - /** - * This function will make DataTables recalculate the column sizes, based on the data - * contained in the table and the sizes applied to the columns (in the DOM, CSS or - * through the sWidth parameter). This can be useful when the width of the table's - * parent element changes (for example a window resize). - * @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to - * @dtopt API - * @deprecated Since v1.10 - * - * @example - * $(document).ready(function() { - * var oTable = $('#example').dataTable( { - * "sScrollY": "200px", - * "bPaginate": false - * } ); - * - * $(window).bind('resize', function () { - * oTable.fnAdjustColumnSizing(); - * } ); - * } ); - */ - this.fnAdjustColumnSizing = function ( bRedraw ) - { - var api = this.api( true ).columns.adjust(); - var settings = api.settings()[0]; - var scroll = settings.oScroll; - - if ( bRedraw === undefined || bRedraw ) { - api.draw( false ); - } - else if ( scroll.sX !== "" || scroll.sY !== "" ) { - /* If not redrawing, but scrolling, we want to apply the new column sizes anyway */ - _fnScrollDraw( settings ); - } - }; - - - /** - * Quickly and simply clear a table - * @param {bool} [bRedraw=true] redraw the table or not - * @dtopt API - * @deprecated Since v1.10 - * - * @example - * $(document).ready(function() { - * var oTable = $('#example').dataTable(); - * - * // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...) - * oTable.fnClearTable(); - * } ); - */ - this.fnClearTable = function( bRedraw ) - { - var api = this.api( true ).clear(); - - if ( bRedraw === undefined || bRedraw ) { - api.draw(); - } - }; - - - /** - * The exact opposite of 'opening' a row, this function will close any rows which - * are currently 'open'. - * @param {node} nTr the table row to 'close' - * @returns {int} 0 on success, or 1 if failed (can't find the row) - * @dtopt API - * @deprecated Since v1.10 - * - * @example - * $(document).ready(function() { - * var oTable; - * - * // 'open' an information row when a row is clicked on - * $('#example tbody tr').click( function () { - * if ( oTable.fnIsOpen(this) ) { - * oTable.fnClose( this ); - * } else { - * oTable.fnOpen( this, "Temporary row opened", "info_row" ); - * } - * } ); - * - * oTable = $('#example').dataTable(); - * } ); - */ - this.fnClose = function( nTr ) - { - this.api( true ).row( nTr ).child.hide(); - }; - - - /** - * Remove a row for the table - * @param {mixed} target The index of the row from aoData to be deleted, or - * the TR element you want to delete - * @param {function|null} [callBack] Callback function - * @param {bool} [redraw=true] Redraw the table or not - * @returns {array} The row that was deleted - * @dtopt API - * @deprecated Since v1.10 - * - * @example - * $(document).ready(function() { - * var oTable = $('#example').dataTable(); - * - * // Immediately remove the first row - * oTable.fnDeleteRow( 0 ); - * } ); - */ - this.fnDeleteRow = function( target, callback, redraw ) - { - var api = this.api( true ); - var rows = api.rows( target ); - var settings = rows.settings()[0]; - var data = settings.aoData[ rows[0][0] ]; - - rows.remove(); - - if ( callback ) { - callback.call( this, settings, data ); - } - - if ( redraw === undefined || redraw ) { - api.draw(); - } - - return data; - }; - - - /** - * Restore the table to it's original state in the DOM by removing all of DataTables - * enhancements, alterations to the DOM structure of the table and event listeners. - * @param {boolean} [remove=false] Completely remove the table from the DOM - * @dtopt API - * @deprecated Since v1.10 - * - * @example - * $(document).ready(function() { - * // This example is fairly pointless in reality, but shows how fnDestroy can be used - * var oTable = $('#example').dataTable(); - * oTable.fnDestroy(); - * } ); - */ - this.fnDestroy = function ( remove ) - { - this.api( true ).destroy( remove ); - }; - - - /** - * Redraw the table - * @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw. - * @dtopt API - * @deprecated Since v1.10 - * - * @example - * $(document).ready(function() { - * var oTable = $('#example').dataTable(); - * - * // Re-draw the table - you wouldn't want to do it here, but it's an example :-) - * oTable.fnDraw(); - * } ); - */ - this.fnDraw = function( complete ) - { - // Note that this isn't an exact match to the old call to _fnDraw - it takes - // into account the new data, but can hold position. - this.api( true ).draw( complete ); - }; - - - /** - * Filter the input based on data - * @param {string} sInput String to filter the table on - * @param {int|null} [iColumn] Column to limit filtering to - * @param {bool} [bRegex=false] Treat as regular expression or not - * @param {bool} [bSmart=true] Perform smart filtering or not - * @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es) - * @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false) - * @dtopt API - * @deprecated Since v1.10 - * - * @example - * $(document).ready(function() { - * var oTable = $('#example').dataTable(); - * - * // Sometime later - filter... - * oTable.fnFilter( 'test string' ); - * } ); - */ - this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive ) - { - var api = this.api( true ); - - if ( iColumn === null || iColumn === undefined ) { - api.search( sInput, bRegex, bSmart, bCaseInsensitive ); - } - else { - api.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive ); - } - - api.draw(); - }; - - - /** - * Get the data for the whole table, an individual row or an individual cell based on the - * provided parameters. - * @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as - * a TR node then the data source for the whole row will be returned. If given as a - * TD/TH cell node then iCol will be automatically calculated and the data for the - * cell returned. If given as an integer, then this is treated as the aoData internal - * data index for the row (see fnGetPosition) and the data for that row used. - * @param {int} [col] Optional column index that you want the data of. - * @returns {array|object|string} If mRow is undefined, then the data for all rows is - * returned. If mRow is defined, just data for that row, and is iCol is - * defined, only data for the designated cell is returned. - * @dtopt API - * @deprecated Since v1.10 - * - * @example - * // Row data - * $(document).ready(function() { - * oTable = $('#example').dataTable(); - * - * oTable.$('tr').click( function () { - * var data = oTable.fnGetData( this ); - * // ... do something with the array / object of data for the row - * } ); - * } ); - * - * @example - * // Individual cell data - * $(document).ready(function() { - * oTable = $('#example').dataTable(); - * - * oTable.$('td').click( function () { - * var sData = oTable.fnGetData( this ); - * alert( 'The cell clicked on had the value of '+sData ); - * } ); - * } ); - */ - this.fnGetData = function( src, col ) - { - var api = this.api( true ); - - if ( src !== undefined ) { - var type = src.nodeName ? src.nodeName.toLowerCase() : ''; - - return col !== undefined || type == 'td' || type == 'th' ? - api.cell( src, col ).data() : - api.row( src ).data() || null; - } - - return api.data().toArray(); - }; - - - /** - * Get an array of the TR nodes that are used in the table's body. Note that you will - * typically want to use the '$' API method in preference to this as it is more - * flexible. - * @param {int} [iRow] Optional row index for the TR element you want - * @returns {array|node} If iRow is undefined, returns an array of all TR elements - * in the table's body, or iRow is defined, just the TR element requested. - * @dtopt API - * @deprecated Since v1.10 - * - * @example - * $(document).ready(function() { - * var oTable = $('#example').dataTable(); - * - * // Get the nodes from the table - * var nNodes = oTable.fnGetNodes( ); - * } ); - */ - this.fnGetNodes = function( iRow ) - { - var api = this.api( true ); - - return iRow !== undefined ? - api.row( iRow ).node() : - api.rows().nodes().flatten().toArray(); - }; - - - /** - * Get the array indexes of a particular cell from it's DOM element - * and column index including hidden columns - * @param {node} node this can either be a TR, TD or TH in the table's body - * @returns {int} If nNode is given as a TR, then a single index is returned, or - * if given as a cell, an array of [row index, column index (visible), - * column index (all)] is given. - * @dtopt API - * @deprecated Since v1.10 - * - * @example - * $(document).ready(function() { - * $('#example tbody td').click( function () { - * // Get the position of the current data from the node - * var aPos = oTable.fnGetPosition( this ); - * - * // Get the data array for this row - * var aData = oTable.fnGetData( aPos[0] ); - * - * // Update the data array and return the value - * aData[ aPos[1] ] = 'clicked'; - * this.innerHTML = 'clicked'; - * } ); - * - * // Init DataTables - * oTable = $('#example').dataTable(); - * } ); - */ - this.fnGetPosition = function( node ) - { - var api = this.api( true ); - var nodeName = node.nodeName.toUpperCase(); - - if ( nodeName == 'TR' ) { - return api.row( node ).index(); - } - else if ( nodeName == 'TD' || nodeName == 'TH' ) { - var cell = api.cell( node ).index(); - - return [ - cell.row, - cell.columnVisible, - cell.column - ]; - } - return null; - }; - - - /** - * Check to see if a row is 'open' or not. - * @param {node} nTr the table row to check - * @returns {boolean} true if the row is currently open, false otherwise - * @dtopt API - * @deprecated Since v1.10 - * - * @example - * $(document).ready(function() { - * var oTable; - * - * // 'open' an information row when a row is clicked on - * $('#example tbody tr').click( function () { - * if ( oTable.fnIsOpen(this) ) { - * oTable.fnClose( this ); - * } else { - * oTable.fnOpen( this, "Temporary row opened", "info_row" ); - * } - * } ); - * - * oTable = $('#example').dataTable(); - * } ); - */ - this.fnIsOpen = function( nTr ) - { - return this.api( true ).row( nTr ).child.isShown(); - }; - - - /** - * This function will place a new row directly after a row which is currently - * on display on the page, with the HTML contents that is passed into the - * function. This can be used, for example, to ask for confirmation that a - * particular record should be deleted. - * @param {node} nTr The table row to 'open' - * @param {string|node|jQuery} mHtml The HTML to put into the row - * @param {string} sClass Class to give the new TD cell - * @returns {node} The row opened. Note that if the table row passed in as the - * first parameter, is not found in the table, this method will silently - * return. - * @dtopt API - * @deprecated Since v1.10 - * - * @example - * $(document).ready(function() { - * var oTable; - * - * // 'open' an information row when a row is clicked on - * $('#example tbody tr').click( function () { - * if ( oTable.fnIsOpen(this) ) { - * oTable.fnClose( this ); - * } else { - * oTable.fnOpen( this, "Temporary row opened", "info_row" ); - * } - * } ); - * - * oTable = $('#example').dataTable(); - * } ); - */ - this.fnOpen = function( nTr, mHtml, sClass ) - { - return this.api( true ) - .row( nTr ) - .child( mHtml, sClass ) - .show() - .child()[0]; - }; - - - /** - * Change the pagination - provides the internal logic for pagination in a simple API - * function. With this function you can have a DataTables table go to the next, - * previous, first or last pages. - * @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last" - * or page number to jump to (integer), note that page 0 is the first page. - * @param {bool} [bRedraw=true] Redraw the table or not - * @dtopt API - * @deprecated Since v1.10 - * - * @example - * $(document).ready(function() { - * var oTable = $('#example').dataTable(); - * oTable.fnPageChange( 'next' ); - * } ); - */ - this.fnPageChange = function ( mAction, bRedraw ) - { - var api = this.api( true ).page( mAction ); - - if ( bRedraw === undefined || bRedraw ) { - api.draw(false); - } - }; - - - /** - * Show a particular column - * @param {int} iCol The column whose display should be changed - * @param {bool} bShow Show (true) or hide (false) the column - * @param {bool} [bRedraw=true] Redraw the table or not - * @dtopt API - * @deprecated Since v1.10 - * - * @example - * $(document).ready(function() { - * var oTable = $('#example').dataTable(); - * - * // Hide the second column after initialisation - * oTable.fnSetColumnVis( 1, false ); - * } ); - */ - this.fnSetColumnVis = function ( iCol, bShow, bRedraw ) - { - var api = this.api( true ).column( iCol ).visible( bShow ); - - if ( bRedraw === undefined || bRedraw ) { - api.columns.adjust().draw(); - } - }; - - - /** - * Get the settings for a particular table for external manipulation - * @returns {object} DataTables settings object. See - * {@link DataTable.models.oSettings} - * @dtopt API - * @deprecated Since v1.10 - * - * @example - * $(document).ready(function() { - * var oTable = $('#example').dataTable(); - * var oSettings = oTable.fnSettings(); - * - * // Show an example parameter from the settings - * alert( oSettings._iDisplayStart ); - * } ); - */ - this.fnSettings = function() - { - return _fnSettingsFromNode( this[_ext.iApiIndex] ); - }; - - - /** - * Sort the table by a particular column - * @param {int} iCol the data index to sort on. Note that this will not match the - * 'display index' if you have hidden data entries - * @dtopt API - * @deprecated Since v1.10 - * - * @example - * $(document).ready(function() { - * var oTable = $('#example').dataTable(); - * - * // Sort immediately with columns 0 and 1 - * oTable.fnSort( [ [0,'asc'], [1,'asc'] ] ); - * } ); - */ - this.fnSort = function( aaSort ) - { - this.api( true ).order( aaSort ).draw(); - }; - - - /** - * Attach a sort listener to an element for a given column - * @param {node} nNode the element to attach the sort listener to - * @param {int} iColumn the column that a click on this node will sort on - * @param {function} [fnCallback] callback function when sort is run - * @dtopt API - * @deprecated Since v1.10 - * - * @example - * $(document).ready(function() { - * var oTable = $('#example').dataTable(); - * - * // Sort on column 1, when 'sorter' is clicked on - * oTable.fnSortListener( document.getElementById('sorter'), 1 ); - * } ); - */ - this.fnSortListener = function( nNode, iColumn, fnCallback ) - { - this.api( true ).order.listener( nNode, iColumn, fnCallback ); - }; - - - /** - * Update a table cell or row - this method will accept either a single value to - * update the cell with, an array of values with one element for each column or - * an object in the same format as the original data source. The function is - * self-referencing in order to make the multi column updates easier. - * @param {object|array|string} mData Data to update the cell/row with - * @param {node|int} mRow TR element you want to update or the aoData index - * @param {int} [iColumn] The column to update, give as null or undefined to - * update a whole row. - * @param {bool} [bRedraw=true] Redraw the table or not - * @param {bool} [bAction=true] Perform pre-draw actions or not - * @returns {int} 0 on success, 1 on error - * @dtopt API - * @deprecated Since v1.10 - * - * @example - * $(document).ready(function() { - * var oTable = $('#example').dataTable(); - * oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell - * oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row - * } ); - */ - this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction ) - { - var api = this.api( true ); - - if ( iColumn === undefined || iColumn === null ) { - api.row( mRow ).data( mData ); - } - else { - api.cell( mRow, iColumn ).data( mData ); - } - - if ( bAction === undefined || bAction ) { - api.columns.adjust(); - } - - if ( bRedraw === undefined || bRedraw ) { - api.draw(); - } - return 0; - }; - - - /** - * Provide a common method for plug-ins to check the version of DataTables being used, in order - * to ensure compatibility. - * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the - * formats "X" and "X.Y" are also acceptable. - * @returns {boolean} true if this version of DataTables is greater or equal to the required - * version, or false if this version of DataTales is not suitable - * @method - * @dtopt API - * @deprecated Since v1.10 - * - * @example - * $(document).ready(function() { - * var oTable = $('#example').dataTable(); - * alert( oTable.fnVersionCheck( '1.9.0' ) ); - * } ); - */ - this.fnVersionCheck = _ext.fnVersionCheck; - - - var _that = this; - var emptyInit = options === undefined; - var len = this.length; - - if ( emptyInit ) { - options = {}; - } - - this.oApi = this.internal = _ext.internal; - - // Extend with old style plug-in API methods - for ( var fn in DataTable.ext.internal ) { - if ( fn ) { - this[fn] = _fnExternApiFunc(fn); - } - } - - this.each(function() { - // For each initialisation we want to give it a clean initialisation - // object that can be bashed around - var o = {}; - var oInit = len > 1 ? // optimisation for single table case - _fnExtend( o, options, true ) : - options; - - /*global oInit,_that,emptyInit*/ - var i=0, iLen, j, jLen, k, kLen; - var sId = this.getAttribute( 'id' ); - var bInitHandedOff = false; - var defaults = DataTable.defaults; - var $this = $(this); - - - /* Sanity check */ - if ( this.nodeName.toLowerCase() != 'table' ) - { - _fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 ); - return; - } - - /* Backwards compatibility for the defaults */ - _fnCompatOpts( defaults ); - _fnCompatCols( defaults.column ); - - /* Convert the camel-case defaults to Hungarian */ - _fnCamelToHungarian( defaults, defaults, true ); - _fnCamelToHungarian( defaults.column, defaults.column, true ); - - /* Setting up the initialisation object */ - _fnCamelToHungarian( defaults, $.extend( oInit, $this.data() ) ); - - - - /* Check to see if we are re-initialising a table */ - var allSettings = DataTable.settings; - for ( i=0, iLen=allSettings.length ; i<iLen ; i++ ) - { - var s = allSettings[i]; - - /* Base check on table node */ - if ( s.nTable == this || s.nTHead.parentNode == this || (s.nTFoot && s.nTFoot.parentNode == this) ) - { - var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve; - var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy; - - if ( emptyInit || bRetrieve ) - { - return s.oInstance; - } - else if ( bDestroy ) - { - s.oInstance.fnDestroy(); - break; - } - else - { - _fnLog( s, 0, 'Cannot reinitialise DataTable', 3 ); - return; - } - } - - /* If the element we are initialising has the same ID as a table which was previously - * initialised, but the table nodes don't match (from before) then we destroy the old - * instance by simply deleting it. This is under the assumption that the table has been - * destroyed by other methods. Anyone using non-id selectors will need to do this manually - */ - if ( s.sTableId == this.id ) - { - allSettings.splice( i, 1 ); - break; - } - } - - /* Ensure the table has an ID - required for accessibility */ - if ( sId === null || sId === "" ) - { - sId = "DataTables_Table_"+(DataTable.ext._unique++); - this.id = sId; - } - - /* Create the settings object for this table and set some of the default parameters */ - var oSettings = $.extend( true, {}, DataTable.models.oSettings, { - "sDestroyWidth": $this[0].style.width, - "sInstance": sId, - "sTableId": sId - } ); - oSettings.nTable = this; - oSettings.oApi = _that.internal; - oSettings.oInit = oInit; - - allSettings.push( oSettings ); - - // Need to add the instance after the instance after the settings object has been added - // to the settings array, so we can self reference the table instance if more than one - oSettings.oInstance = (_that.length===1) ? _that : $this.dataTable(); - - // Backwards compatibility, before we apply all the defaults - _fnCompatOpts( oInit ); - - if ( oInit.oLanguage ) - { - _fnLanguageCompat( oInit.oLanguage ); - } - - // If the length menu is given, but the init display length is not, use the length menu - if ( oInit.aLengthMenu && ! oInit.iDisplayLength ) - { - oInit.iDisplayLength = $.isArray( oInit.aLengthMenu[0] ) ? - oInit.aLengthMenu[0][0] : oInit.aLengthMenu[0]; - } - - // Apply the defaults and init options to make a single init object will all - // options defined from defaults and instance options. - oInit = _fnExtend( $.extend( true, {}, defaults ), oInit ); - - - // Map the initialisation options onto the settings object - _fnMap( oSettings.oFeatures, oInit, [ - "bPaginate", - "bLengthChange", - "bFilter", - "bSort", - "bSortMulti", - "bInfo", - "bProcessing", - "bAutoWidth", - "bSortClasses", - "bServerSide", - "bDeferRender" - ] ); - _fnMap( oSettings, oInit, [ - "asStripeClasses", - "ajax", - "fnServerData", - "fnFormatNumber", - "sServerMethod", - "aaSorting", - "aaSortingFixed", - "aLengthMenu", - "sPaginationType", - "sAjaxSource", - "sAjaxDataProp", - "iStateDuration", - "sDom", - "bSortCellsTop", - "iTabIndex", - "fnStateLoadCallback", - "fnStateSaveCallback", - "renderer", - "searchDelay", - [ "iCookieDuration", "iStateDuration" ], // backwards compat - [ "oSearch", "oPreviousSearch" ], - [ "aoSearchCols", "aoPreSearchCols" ], - [ "iDisplayLength", "_iDisplayLength" ], - [ "bJQueryUI", "bJUI" ] - ] ); - _fnMap( oSettings.oScroll, oInit, [ - [ "sScrollX", "sX" ], - [ "sScrollXInner", "sXInner" ], - [ "sScrollY", "sY" ], - [ "bScrollCollapse", "bCollapse" ] - ] ); - _fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" ); - - /* Callback functions which are array driven */ - _fnCallbackReg( oSettings, 'aoDrawCallback', oInit.fnDrawCallback, 'user' ); - _fnCallbackReg( oSettings, 'aoServerParams', oInit.fnServerParams, 'user' ); - _fnCallbackReg( oSettings, 'aoStateSaveParams', oInit.fnStateSaveParams, 'user' ); - _fnCallbackReg( oSettings, 'aoStateLoadParams', oInit.fnStateLoadParams, 'user' ); - _fnCallbackReg( oSettings, 'aoStateLoaded', oInit.fnStateLoaded, 'user' ); - _fnCallbackReg( oSettings, 'aoRowCallback', oInit.fnRowCallback, 'user' ); - _fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow, 'user' ); - _fnCallbackReg( oSettings, 'aoHeaderCallback', oInit.fnHeaderCallback, 'user' ); - _fnCallbackReg( oSettings, 'aoFooterCallback', oInit.fnFooterCallback, 'user' ); - _fnCallbackReg( oSettings, 'aoInitComplete', oInit.fnInitComplete, 'user' ); - _fnCallbackReg( oSettings, 'aoPreDrawCallback', oInit.fnPreDrawCallback, 'user' ); - - var oClasses = oSettings.oClasses; - - // @todo Remove in 1.11 - if ( oInit.bJQueryUI ) - { - /* Use the JUI classes object for display. You could clone the oStdClasses object if - * you want to have multiple tables with multiple independent classes - */ - $.extend( oClasses, DataTable.ext.oJUIClasses, oInit.oClasses ); - - if ( oInit.sDom === defaults.sDom && defaults.sDom === "lfrtip" ) - { - /* Set the DOM to use a layout suitable for jQuery UI's theming */ - oSettings.sDom = '<"H"lfr>t<"F"ip>'; - } - - if ( ! oSettings.renderer ) { - oSettings.renderer = 'jqueryui'; - } - else if ( $.isPlainObject( oSettings.renderer ) && ! oSettings.renderer.header ) { - oSettings.renderer.header = 'jqueryui'; - } - } - else - { - $.extend( oClasses, DataTable.ext.classes, oInit.oClasses ); - } - $this.addClass( oClasses.sTable ); - - /* Calculate the scroll bar width and cache it for use later on */ - if ( oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "" ) - { - oSettings.oScroll.iBarWidth = _fnScrollBarWidth(); - } - if ( oSettings.oScroll.sX === true ) { // Easy initialisation of x-scrolling - oSettings.oScroll.sX = '100%'; - } - - if ( oSettings.iInitDisplayStart === undefined ) - { - /* Display start point, taking into account the save saving */ - oSettings.iInitDisplayStart = oInit.iDisplayStart; - oSettings._iDisplayStart = oInit.iDisplayStart; - } - - if ( oInit.iDeferLoading !== null ) - { - oSettings.bDeferLoading = true; - var tmp = $.isArray( oInit.iDeferLoading ); - oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading; - oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading; - } - - /* Language definitions */ - var oLanguage = oSettings.oLanguage; - $.extend( true, oLanguage, oInit.oLanguage ); - - if ( oLanguage.sUrl !== "" ) - { - /* Get the language definitions from a file - because this Ajax call makes the language - * get async to the remainder of this function we use bInitHandedOff to indicate that - * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor - */ - $.ajax( { - dataType: 'json', - url: oLanguage.sUrl, - success: function ( json ) { - _fnLanguageCompat( json ); - _fnCamelToHungarian( defaults.oLanguage, json ); - $.extend( true, oLanguage, json ); - _fnInitialise( oSettings ); - }, - error: function () { - // Error occurred loading language file, continue on as best we can - _fnInitialise( oSettings ); - } - } ); - bInitHandedOff = true; - } - - /* - * Stripes - */ - if ( oInit.asStripeClasses === null ) - { - oSettings.asStripeClasses =[ - oClasses.sStripeOdd, - oClasses.sStripeEven - ]; - } - - /* Remove row stripe classes if they are already on the table row */ - var stripeClasses = oSettings.asStripeClasses; - var rowOne = $this.children('tbody').find('tr').eq(0); - if ( $.inArray( true, $.map( stripeClasses, function(el, i) { - return rowOne.hasClass(el); - } ) ) !== -1 ) { - $('tbody tr', this).removeClass( stripeClasses.join(' ') ); - oSettings.asDestroyStripes = stripeClasses.slice(); - } - - /* - * Columns - * See if we should load columns automatically or use defined ones - */ - var anThs = []; - var aoColumnsInit; - var nThead = this.getElementsByTagName('thead'); - if ( nThead.length !== 0 ) - { - _fnDetectHeader( oSettings.aoHeader, nThead[0] ); - anThs = _fnGetUniqueThs( oSettings ); - } - - /* If not given a column array, generate one with nulls */ - if ( oInit.aoColumns === null ) - { - aoColumnsInit = []; - for ( i=0, iLen=anThs.length ; i<iLen ; i++ ) - { - aoColumnsInit.push( null ); - } - } - else - { - aoColumnsInit = oInit.aoColumns; - } - - /* Add the columns */ - for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ ) - { - _fnAddColumn( oSettings, anThs ? anThs[i] : null ); - } - - /* Apply the column definitions */ - _fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) { - _fnColumnOptions( oSettings, iCol, oDef ); - } ); - - /* HTML5 attribute detection - build an mData object automatically if the - * attributes are found - */ - if ( rowOne.length ) { - var a = function ( cell, name ) { - return cell.getAttribute( 'data-'+name ) !== null ? name : null; - }; - - $.each( _fnGetRowElements( oSettings, rowOne[0] ).cells, function (i, cell) { - var col = oSettings.aoColumns[i]; - - if ( col.mData === i ) { - var sort = a( cell, 'sort' ) || a( cell, 'order' ); - var filter = a( cell, 'filter' ) || a( cell, 'search' ); - - if ( sort !== null || filter !== null ) { - col.mData = { - _: i+'.display', - sort: sort !== null ? i+'.@data-'+sort : undefined, - type: sort !== null ? i+'.@data-'+sort : undefined, - filter: filter !== null ? i+'.@data-'+filter : undefined - }; - - _fnColumnOptions( oSettings, i ); - } - } - } ); - } - - var features = oSettings.oFeatures; - - /* Must be done after everything which can be overridden by the state saving! */ - if ( oInit.bStateSave ) - { - features.bStateSave = true; - _fnLoadState( oSettings, oInit ); - _fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' ); - } - - - /* - * Sorting - * @todo For modularisation (1.11) this needs to do into a sort start up handler - */ - - // If aaSorting is not defined, then we use the first indicator in asSorting - // in case that has been altered, so the default sort reflects that option - if ( oInit.aaSorting === undefined ) - { - var sorting = oSettings.aaSorting; - for ( i=0, iLen=sorting.length ; i<iLen ; i++ ) - { - sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0]; - } - } - - /* Do a first pass on the sorting classes (allows any size changes to be taken into - * account, and also will apply sorting disabled classes if disabled - */ - _fnSortingClasses( oSettings ); - - if ( features.bSort ) - { - _fnCallbackReg( oSettings, 'aoDrawCallback', function () { - if ( oSettings.bSorted ) { - var aSort = _fnSortFlatten( oSettings ); - var sortedColumns = {}; - - $.each( aSort, function (i, val) { - sortedColumns[ val.src ] = val.dir; - } ); - - _fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] ); - _fnSortAria( oSettings ); - } - } ); - } - - _fnCallbackReg( oSettings, 'aoDrawCallback', function () { - if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) { - _fnSortingClasses( oSettings ); - } - }, 'sc' ); - - - /* - * Final init - * Cache the header, body and footer as required, creating them if needed - */ - - /* Browser support detection */ - _fnBrowserDetect( oSettings ); - - // Work around for Webkit bug 83867 - store the caption-side before removing from doc - var captions = $this.children('caption').each( function () { - this._captionSide = $this.css('caption-side'); - } ); - - var thead = $this.children('thead'); - if ( thead.length === 0 ) - { - thead = $('<thead/>').appendTo(this); - } - oSettings.nTHead = thead[0]; - - var tbody = $this.children('tbody'); - if ( tbody.length === 0 ) - { - tbody = $('<tbody/>').appendTo(this); - } - oSettings.nTBody = tbody[0]; - - var tfoot = $this.children('tfoot'); - if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") ) - { - // If we are a scrolling table, and no footer has been given, then we need to create - // a tfoot element for the caption element to be appended to - tfoot = $('<tfoot/>').appendTo(this); - } - - if ( tfoot.length === 0 || tfoot.children().length === 0 ) { - $this.addClass( oClasses.sNoFooter ); - } - else if ( tfoot.length > 0 ) { - oSettings.nTFoot = tfoot[0]; - _fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot ); - } - - /* Check if there is data passing into the constructor */ - if ( oInit.aaData ) - { - for ( i=0 ; i<oInit.aaData.length ; i++ ) - { - _fnAddData( oSettings, oInit.aaData[ i ] ); - } - } - else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' ) - { - /* Grab the data from the page - only do this when deferred loading or no Ajax - * source since there is no point in reading the DOM data if we are then going - * to replace it with Ajax data - */ - _fnAddTr( oSettings, $(oSettings.nTBody).children('tr') ); - } - - /* Copy the data index array */ - oSettings.aiDisplay = oSettings.aiDisplayMaster.slice(); - - /* Initialisation complete - table can be drawn */ - oSettings.bInitialised = true; - - /* Check if we need to initialise the table (it might not have been handed off to the - * language processor) - */ - if ( bInitHandedOff === false ) - { - _fnInitialise( oSettings ); - } - } ); - _that = null; - return this; - }; - /** @@ -6746,7 +6841,7 @@ var ctxSettings = function ( o ) { var a = _toSettings( o ); if ( a ) { - settings.push.apply( settings, a ); + settings = settings.concat( a ); } }; @@ -6764,7 +6859,7 @@ // Initial data if ( data ) { - this.push.apply( this, data.toArray ? data.toArray() : data ); + $.merge( this, data ); } // selector @@ -6779,10 +6874,12 @@ DataTable.Api = _Api; - _Api.prototype = /** @lends DataTables.Api */{ + // Don't destroy the existing prototype, just extend it. Required for jQuery 2's + // isPlainObject. + $.extend( _Api.prototype, { any: function () { - return this.flatten().length !== 0; + return this.count() !== 0; }, @@ -6792,6 +6889,12 @@ context: [], // array of table settings objects + count: function () + { + return this.flatten().length; + }, + + each: function ( fn ) { for ( var i=0, ien=this.length ; i<ien; i++ ) { @@ -7019,7 +7122,7 @@ unshift: __arrayProto.unshift - }; + } ); _Api.extend = function ( scope, obj, ext ) @@ -7274,15 +7377,21 @@ /** * Redraw the tables in the current context. - * - * @param {boolean} [reset=true] Reset (default) or hold the current paging - * position. A full re-sort and re-filter is performed when this method is - * called, which is why the pagination reset is the default action. - * @returns {DataTables.Api} this */ - _api_register( 'draw()', function ( resetPaging ) { + _api_register( 'draw()', function ( paging ) { return this.iterator( 'table', function ( settings ) { - _fnReDraw( settings, resetPaging===false ); + if ( paging === 'page' ) { + _fnDraw( settings ); + } + else { + if ( typeof paging === 'string' ) { + paging = paging === 'full-hold' ? + false : + true; + } + + _fnReDraw( settings, paging===false ); + } } ); } ); @@ -7345,7 +7454,7 @@ var settings = this.context[0], start = settings._iDisplayStart, - len = settings._iDisplayLength, + len = settings.oFeatures.bPaginate ? settings._iDisplayLength : -1, visRecords = settings.fnRecordsDisplay(), all = len === -1; @@ -7356,7 +7465,8 @@ "end": settings.fnDisplayEnd(), "length": len, "recordsTotal": settings.fnRecordsTotal(), - "recordsDisplay": visRecords + "recordsDisplay": visRecords, + "serverSide": _fnDataSource( settings ) === 'ssp' }; } ); @@ -7404,9 +7514,15 @@ _fnReDraw( settings, holdPosition ); } else { - // Trigger xhr _fnProcessingDisplay( settings, true ); + // Cancel an existing request + var xhr = settings.jqXHR; + if ( xhr && xhr.readyState !== 4 ) { + xhr.abort(); + } + + // Trigger xhr _fnBuildAjax( settings, [], function( json ) { _fnClearTable( settings ); @@ -7556,7 +7672,7 @@ res = selectFn( typeof a[j] === 'string' ? $.trim(a[j]) : a[j] ); if ( res && res.length ) { - out.push.apply( out, res ); + out = out.concat( res ); } } } @@ -7569,7 +7685,7 @@ } } - return out; + return _unique( out ); }; @@ -7725,12 +7841,40 @@ // Selector - node if ( sel.nodeName ) { - if ( $.inArray( sel, nodes ) !== -1 ) { - return [ sel._DT_RowIndex ]; // sel is a TR node that is in the table - // and DataTables adds a prop for fast lookup + if ( sel._DT_RowIndex !== undefined ) { + return [ sel._DT_RowIndex ]; // Property added by DT for fast lookup + } + else if ( sel._DT_CellIndex ) { + return [ sel._DT_CellIndex.row ]; + } + else { + var host = $(sel).closest('*[data-dt-row]'); + return host.length ? + [ host.data('dt-row') ] : + []; } } + // ID selector. Want to always be able to select rows by id, regardless + // of if the tr element has been created or not, so can't rely upon + // jQuery here - hence a custom implementation. This does not match + // Sizzle's fast selector or HTML4 - in HTML5 the ID can be anything, + // but to select it using a CSS selector engine (like Sizzle or + // querySelect) it would need to need to be escaped for some characters. + // DataTables simplifies this for row selectors since you can select + // only a row. A # indicates an id any anything that follows is the id - + // unescaped. + if ( typeof sel === 'string' && sel.charAt(0) === '#' ) { + // get row index from id + var rowObj = settings.aIds[ sel.replace( /^#/, '' ) ]; + if ( rowObj !== undefined ) { + return [ rowObj.idx ]; + } + + // need to fall through to jQuery in case there is DOM id that + // matches + } + // Selector - jQuery selector string, array of nodes or jQuery object/ // As jQuery's .filter() allows jQuery objects to be passed in filter, // it also allows arrays, so this will cope with all three options @@ -7800,23 +7944,49 @@ }, 1 ); } ); + _api_registerPlural( 'rows().ids()', 'row().id()', function ( hash ) { + var a = []; + var context = this.context; + + // `iterator` will drop undefined values, but in this case we want them + for ( var i=0, ien=context.length ; i<ien ; i++ ) { + for ( var j=0, jen=this[i].length ; j<jen ; j++ ) { + var id = context[i].rowIdFn( context[i].aoData[ this[i][j] ]._aData ); + a.push( (hash === true ? '#' : '' )+ id ); + } + } + + return new _Api( context, a ); + } ); + _api_registerPlural( 'rows().remove()', 'row().remove()', function () { var that = this; - return this.iterator( 'row', function ( settings, row, thatIdx ) { + this.iterator( 'row', function ( settings, row, thatIdx ) { var data = settings.aoData; + var rowData = data[ row ]; + var i, ien, j, jen; + var loopRow, loopCells; data.splice( row, 1 ); - // Update the _DT_RowIndex parameter on all rows in the table - for ( var i=0, ien=data.length ; i<ien ; i++ ) { - if ( data[i].nTr !== null ) { - data[i].nTr._DT_RowIndex = i; + // Update the cached indexes + for ( i=0, ien=data.length ; i<ien ; i++ ) { + loopRow = data[i]; + loopCells = loopRow.anCells; + + // Rows + if ( loopRow.nTr !== null ) { + loopRow.nTr._DT_RowIndex = i; } - } - // Remove the target row from the search array - var displayIndex = $.inArray( row, settings.aiDisplay ); + // Cells + if ( loopCells !== null ) { + for ( j=0, jen=loopCells.length ; j<jen ; j++ ) { + loopCells[j]._DT_CellIndex.row = i; + } + } + } // Delete from the display arrays _fnDeleteIndex( settings.aiDisplayMaster, row ); @@ -7825,7 +7995,21 @@ // Check for an 'overflow' they case for displaying the table _fnLengthOverflow( settings ); + + // Remove the row's ID reference if there is one + var id = settings.rowIdFn( rowData._aData ); + if ( id !== undefined ) { + delete settings.aIds[ id ]; + } + } ); + + this.iterator( 'table', function ( settings ) { + for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) { + settings.aoData[i].idx = i; + } } ); + + return this; } ); @@ -7851,7 +8035,7 @@ // Return an Api.rows() extended instance, so rows().nodes() etc can be used var modRows = this.rows( -1 ); modRows.pop(); - modRows.push.apply( modRows, newRows.toArray() ); + $.merge( modRows, newRows ); return modRows; } ); @@ -7969,7 +8153,7 @@ if ( ctx.length ) { var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ]; - if ( row._details ) { + if ( row && row._details ) { row._details.remove(); row._detailsShow = undefined; @@ -8179,7 +8363,7 @@ if ( s === '' ) { return _range( columns.length ); } - + // Selector - index if ( selInt !== null ) { return [ selInt >= 0 ? @@ -8187,7 +8371,7 @@ columns.length + selInt // Count from right (+ because its a negative value) ]; } - + // Selector = function if ( typeof s === 'function' ) { var rows = _selector_row_indexes( settings, opts ); @@ -8227,24 +8411,42 @@ return $.map( names, function (name, i) { return name === match[1] ? i : null; } ); + + default: + return []; } } - else { - // jQuery selector on the TH elements for the columns - return $( nodes ) - .filter( s ) - .map( function () { - return $.inArray( this, nodes ); // `nodes` is column index complete and in order - } ) - .toArray(); + + // Cell in the table body + if ( s.nodeName && s._DT_CellIndex ) { + return [ s._DT_CellIndex.column ]; + } + + // jQuery selector on the TH elements for the columns + var jqResult = $( nodes ) + .filter( s ) + .map( function () { + return $.inArray( this, nodes ); // `nodes` is column index complete and in order + } ) + .toArray(); + + if ( jqResult.length || ! s.nodeName ) { + return jqResult; } + + // Otherwise a node which might have a `dt-column` data attribute, or be + // a child or such an element + var host = $(s).closest('*[data-dt-column]'); + return host.length ? + [ host.data('dt-column') ] : + []; }; return _selector_run( 'column', selector, run, settings, opts ); }; - var __setColumnVis = function ( settings, column, vis, recalc ) { + var __setColumnVis = function ( settings, column, vis ) { var cols = settings.aoColumns, col = cols[ column ], @@ -8287,18 +8489,6 @@ _fnDrawHead( settings, settings.aoHeader ); _fnDrawHead( settings, settings.aoFooter ); - if ( recalc === undefined || recalc ) { - // Automatically adjust column sizing - _fnAdjustColumnSizing( settings ); - - // Realign columns for scrolling - if ( settings.oScroll.sX || settings.oScroll.sY ) { - _fnScrollDraw( settings ); - } - } - - _fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis] ); - _fnSaveState( settings ); }; @@ -8363,12 +8553,26 @@ } ); _api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) { - return this.iterator( 'column', function ( settings, column ) { + var ret = this.iterator( 'column', function ( settings, column ) { if ( vis === undefined ) { return settings.aoColumns[ column ].bVisible; } // else - __setColumnVis( settings, column, vis, calc ); + __setColumnVis( settings, column, vis ); } ); + + // Group the column visibility changes + if ( vis !== undefined ) { + // Second loop once the first is done for events + this.iterator( 'column', function ( settings, column ) { + _fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis, calc] ); + } ); + + if ( calc === undefined || calc ) { + this.columns.adjust(); + } + } + + return ret; } ); _api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) { @@ -8404,7 +8608,6 @@ - var __cell_selector = function ( settings, selector, opts ) { var data = settings.aoData; @@ -8433,7 +8636,7 @@ if ( fnSelector ) { // Selector - function - host = settings.aoData[ row ]; + host = data[ row ]; if ( s( o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null ) ) { a.push( o ); @@ -8455,17 +8658,30 @@ } // Selector - jQuery filtered cells - return allCells + var jqResult = allCells .filter( s ) .map( function (i, el) { - row = el.parentNode._DT_RowIndex; - - return { - row: row, - column: $.inArray( el, data[ row ].anCells ) - }; + return { // use a new object, in case someone changes the values + row: el._DT_CellIndex.row, + column: el._DT_CellIndex.column + }; } ) .toArray(); + + if ( jqResult.length || ! s.nodeName ) { + return jqResult; + } + + // Otherwise the selector is a node, and there is one last option - the + // element might be a child of an element which has dt-row and dt-column + // data attributes + host = $(s).closest('*[data-dt-row]'); + return host.length ? + [ { + row: host.data('dt-row'), + column: host.data('dt-column') + } ] : + []; }; return _selector_run( 'cell', selector, run, settings, opts ); @@ -8533,9 +8749,10 @@ _api_registerPlural( 'cells().nodes()', 'cell().node()', function () { return this.iterator( 'cell', function ( settings, row, column ) { - var cells = settings.aoData[ row ].anCells; - return cells ? - cells[ column ] : + var data = settings.aoData[ row ]; + + return data && data.anCells ? + data.anCells[ column ] : undefined; }, 1 ); } ); @@ -8651,7 +8868,7 @@ // Simple column / direction passed in order = [ [ order, dir ] ]; } - else if ( ! $.isArray( order[0] ) ) { + else if ( order.length && ! $.isArray( order[0] ) ) { // Arguments passed in (list of 1D arrays) order = Array.prototype.slice.call( arguments ); } @@ -8680,6 +8897,24 @@ } ); + _api_register( 'order.fixed()', function ( set ) { + if ( ! set ) { + var ctx = this.context; + var fixed = ctx.length ? + ctx[0].aaSortingFixed : + undefined; + + return $.isArray( fixed ) ? + { pre: fixed } : + fixed; + } + + return this.iterator( 'table', function ( settings ) { + settings.aaSortingFixed = $.extend( true, {}, set ); + } ); + } ); + + // Order by the selected column(s) _api_register( [ 'columns().order()', @@ -8878,43 +9113,22 @@ */ DataTable.tables = DataTable.fnTables = function ( visible ) { - return $.map( DataTable.settings, function (o) { + var api = false; + + if ( $.isPlainObject( visible ) ) { + api = visible.api; + visible = visible.visible; + } + + var a = $.map( DataTable.settings, function (o) { if ( !visible || (visible && $(o.nTable).is(':visible')) ) { return o.nTable; } } ); - }; - - /** - * DataTables utility methods - * - * This namespace provides helper methods that DataTables uses internally to - * create a DataTable, but which are not exclusively used only for DataTables. - * These methods can be used by extension authors to save the duplication of - * code. - * - * @namespace - */ - DataTable.util = { - /** - * Throttle the calls to a function. Arguments and context are maintained - * for the throttled function. - * - * @param {function} fn Function to be called - * @param {integer} freq Call frequency in mS - * @return {function} Wrapped function - */ - throttle: _fnThrottle, - - - /** - * Escape a string such that it can be used in a regular expression - * - * @param {string} sVal string to escape - * @returns {string} escaped string - */ - escapeRegex: _fnEscapeRegex + return api ? + new _Api( a ) : + a; }; @@ -9037,10 +9251,6 @@ jqTable.append( tfoot ); } - // Remove the DataTables generated nodes, events and classes - jqTable.detach(); - jqWrapper.detach(); - settings.aaSorting = []; settings.aaSortingFixed = []; _fnSortingClasses( settings ); @@ -9060,30 +9270,36 @@ } ); } - if ( ! remove && orig ) { - // insertBefore acts like appendChild if !arg[1] - orig.insertBefore( table, settings.nTableReinsertBefore ); - } - // Add the TR elements back into the table in their original order jqTbody.children().detach(); jqTbody.append( rows ); - // Restore the width of the original table - was read from the style property, - // so we can restore directly to that - jqTable - .css( 'width', settings.sDestroyWidth ) - .removeClass( classes.sTable ); + // Remove the DataTables generated nodes, events and classes + var removedMethod = remove ? 'remove' : 'detach'; + jqTable[ removedMethod ](); + jqWrapper[ removedMethod ](); - // If the were originally stripe classes - then we add them back here. - // Note this is not fool proof (for example if not all rows had stripe - // classes - but it's a good effort without getting carried away - ien = settings.asDestroyStripes.length; + // If we need to reattach the table to the document + if ( ! remove && orig ) { + // insertBefore acts like appendChild if !arg[1] + orig.insertBefore( table, settings.nTableReinsertBefore ); - if ( ien ) { - jqTbody.children().each( function (i) { - $(this).addClass( settings.asDestroyStripes[i % ien] ); - } ); + // Restore the width of the original table - was read from the style property, + // so we can restore directly to that + jqTable + .css( 'width', settings.sDestroyWidth ) + .removeClass( classes.sTable ); + + // If the were originally stripe classes - then we add them back here. + // Note this is not fool proof (for example if not all rows had stripe + // classes - but it's a good effort without getting carried away + ien = settings.asDestroyStripes.length; + + if ( ien ) { + jqTbody.children().each( function (i) { + $(this).addClass( settings.asDestroyStripes[i % ien] ); + } ); + } } /* Remove the settings object from the settings array */ @@ -9098,9 +9314,28 @@ // Add the `every()` method for rows, columns and cells in a compact form $.each( [ 'column', 'row', 'cell' ], function ( i, type ) { _api_register( type+'s().every()', function ( fn ) { - return this.iterator( type, function ( settings, idx, idx2 ) { - // idx2 is undefined for rows and columns. - fn.call( new _Api( settings )[ type ]( idx, idx2 ) ); + var opts = this.selector.opts; + var api = this; + + return this.iterator( type, function ( settings, arg1, arg2, arg3, arg4 ) { + // Rows and columns: + // arg1 - index + // arg2 - table counter + // arg3 - loop counter + // arg4 - undefined + // Cells: + // arg1 - row index + // arg2 - column index + // arg3 - table counter + // arg4 - loop counter + fn.call( + api[ type ]( + arg1, + type==='cell' ? arg2 : opts, + type==='cell' ? opts : undefined + ), + arg1, arg2, arg3, arg4 + ); } ); } ); } ); @@ -9133,7 +9368,7 @@ * @type string * @default Version number */ - DataTable.version = "1.10.7"; + DataTable.version = "1.10.12"; /** * Private data store, containing all of the settings objects that are @@ -9285,7 +9520,16 @@ * @default null * @private */ - "src": null + "src": null, + + /** + * Index in the aoData array. This saves an indexOf lookup when we have the + * object, but want to know the index + * @type integer + * @default -1 + * @private + */ + "idx": -1 }; @@ -11234,7 +11478,7 @@ * However, multiple different tables on the page can use different * decimal place characters. * @type string - * @default + * @default * * @dtopt Language * @name DataTable.defaults.language.decimal @@ -11399,7 +11643,7 @@ /** * Assign a `placeholder` attribute to the search `input` element * @type string - * @default + * @default * * @dtopt Language * @name DataTable.defaults.language.searchPlaceholder @@ -11602,7 +11846,7 @@ * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus * page numbers - * + * * Further methods can be added using {@link DataTable.ext.oPagination}. * @type string * @default simple_numbers @@ -11726,7 +11970,18 @@ * @name DataTable.defaults.renderer * */ - "renderer": null + "renderer": null, + + + /** + * Set the data property name that DataTables should use to get a row's id + * to set as the `id` property in the node. + * @type string + * @default DT_RowId + * + * @name DataTable.defaults.rowId + */ + "rowId": "DT_RowId" }; _fnHungarianMap( DataTable.defaults ); @@ -12825,7 +13080,21 @@ * @type boolean * @default false */ - "bScrollbarLeft": false + "bScrollbarLeft": false, + + /** + * Flag for if `getBoundingClientRect` is fully supported or not + * @type boolean + * @default false + */ + "bBounding": false, + + /** + * Browser scrollbar width + * @type integer + * @default 0 + */ + "barWidth": 0 }, @@ -12871,6 +13140,13 @@ "aiDisplayMaster": [], /** + * Map of row ids to data indexes + * @type object + * @default {} + */ + "aIds": {}, + + /** * Store information about each column that is in use * @type array * @default [] @@ -13478,7 +13754,21 @@ * @type object * @default {} */ - "oPlugins": {} + "oPlugins": {}, + + /** + * Function used to get a row's id from the row's data + * @type function + * @default null + */ + "rowIdFn": null, + + /** + * Data location where to store a row's id + * @type string + * @default null + */ + "rowId": null }; /** @@ -13495,7 +13785,7 @@ /** * DataTables extensions - * + * * This namespace acts as a collection area for plug-ins that can be used to * extend DataTables capabilities. Indeed many of the build in methods * use this method to provide their own capabilities (sorting methods for @@ -13528,8 +13818,16 @@ /** - * Error reporting. + * DataTables build type (expanded by the download builder) * + * @type string + */ + builder: "-source-", + + + /** + * Error reporting. + * * How should DataTables report an error. Can take the value 'alert', * 'throw', 'none' or a function. * @@ -13541,14 +13839,14 @@ /** * Feature plug-ins. - * + * * This is an array of objects which describe the feature plug-ins that are * available to DataTables. These feature plug-ins are then available for * use through the `dom` initialisation option. - * + * * Each feature plug-in is described by an object which must have the * following properties: - * + * * * `fnInit` - function that is used to initialise the plug-in, * * `cFeature` - a character so the feature can be enabled by the `dom` * instillation option. This is case sensitive. @@ -13559,7 +13857,7 @@ * {@link DataTable.models.oSettings} * * And the following return is expected: - * + * * * {node|null} The element which contains your feature. Note that the * return may also be void if your plug-in does not require to inject any * DOM elements into DataTables control (`dom`) - for example this might @@ -13581,7 +13879,7 @@ /** * Row searching. - * + * * This method of searching is complimentary to the default type based * searching, and a lot more comprehensive as it allows you complete control * over the searching logic. Each element in this array is a function @@ -13673,7 +13971,7 @@ /** * Internal functions, exposed for used in plug-ins. - * + * * Please note that you should not need to use the internal methods for * anything other than a plug-in (and even then, try to avoid if possible). * The internal function may change between releases. @@ -13704,7 +14002,7 @@ /** * Pagination plug-in methods. - * + * * Each entry in this object is a function and defines which buttons should * be shown by the pagination rendering method that is used for the table: * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the @@ -13758,16 +14056,16 @@ /** * Ordering plug-ins - custom data source - * + * * The extension options for ordering of data available here is complimentary * to the default type based ordering that DataTables typically uses. It * allows much greater control over the the data that is being used to * order a column, but is necessarily therefore more complex. - * + * * This type of ordering is useful if you want to do ordering based on data * live from the DOM (for example the contents of an 'input' element) rather * than just the static string that DataTables knows of. - * + * * The way these plug-ins work is that you create an array of the values you * wish to be ordering for the column in question and then return that * array. The data in the array much be in the index order of the rows in @@ -13862,7 +14160,7 @@ * * Note that is a search is not defined for a column of a given type, * no search formatting will be performed. - * + * * Pre-processing of searching data plug-ins - When you assign the sType * for a column (or have it automatically detected for you by DataTables * or a type detection plug-in), you will typically be using this for @@ -13932,7 +14230,7 @@ * than the second parameter, ===0 if the two parameters are equal and * >0 if the first parameter should be sorted height than the second * parameter. - * + * * @type object * @default {} * @@ -14185,6 +14483,10 @@ return [ 'first', 'previous', 'next', 'last' ]; }, + numbers: function ( page, pages ) { + return [ _numbers(page, pages) ]; + }, + simple_numbers: function ( page, pages ) { return [ 'previous', _numbers(page, pages), 'next' ]; }, @@ -14206,6 +14508,7 @@ _: function ( settings, host, idx, buttons, page, pages ) { var classes = settings.oClasses; var lang = settings.oLanguage.oPaginate; + var aria = settings.oLanguage.oAria.paginate || {}; var btnDisplay, btnClass, counter=0; var attach = function( container, buttons ) { @@ -14223,7 +14526,7 @@ attach( inner, button ); } else { - btnDisplay = ''; + btnDisplay = null; btnClass = ''; switch ( button ) { @@ -14262,10 +14565,11 @@ break; } - if ( btnDisplay ) { + if ( btnDisplay !== null ) { node = $('<a>', { 'class': classes.sPageButton+' '+btnClass, 'aria-controls': settings.sTableId, + 'aria-label': aria[ button ], 'data-dt-idx': counter, 'tabindex': settings.iTabIndex, 'id': idx === 0 && typeof button === 'string' ? @@ -14295,7 +14599,7 @@ // elements, focus is lost on the select button which is bad for // accessibility. So we want to restore focus once the draw has // completed - activeEl = $(document.activeElement).data('dt-idx'); + activeEl = $(host).find(document.activeElement).data('dt-idx'); } catch (e) {} @@ -14367,7 +14671,7 @@ // Filter formatting functions. See model.ext.ofnSearch for information about // what is required from these methods. - // + // // Note that additional search methods are added for the html numbers and // html formatted numbers by `_addNumericSort()` when we know what the decimal // place is @@ -14585,6 +14889,12 @@ * to make working with DataTables a little bit easier. */ + var __htmlEscapeEntities = function ( d ) { + return typeof d === 'string' ? + d.replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"') : + d; + }; + /** * Helpers for `columns.render`. * @@ -14593,11 +14903,14 @@ * * * `number` - Will format numeric data (defined by `columns.data`) for * display, retaining the original unformatted data for sorting and filtering. - * It takes 4 parameters: + * It takes 5 parameters: * * `string` - Thousands grouping separator * * `string` - Decimal point indicator * * `integer` - Number of decimal points to show * * `string` (optional) - Prefix. + * * `string` (optional) - Postfix (/suffix). + * * `text` - Escape HTML to help prevent XSS attacks. It has no optional + * parameters. * * @example * // Column definition using the number renderer @@ -14609,7 +14922,7 @@ * @namespace */ DataTable.render = { - number: function ( thousands, decimal, precision, prefix ) { + number: function ( thousands, decimal, precision, prefix, postfix ) { return { display: function ( d ) { if ( typeof d !== 'number' && typeof d !== 'string' ) { @@ -14617,7 +14930,16 @@ } var negative = d < 0 ? '-' : ''; - d = Math.abs( parseFloat( d ) ); + var flo = parseFloat( d ); + + // If NaN then there isn't much formatting that we can do - just + // return immediately, escaping any HTML (this was supposed to + // be a number after all) + if ( isNaN( flo ) ) { + return __htmlEscapeEntities( d ); + } + + d = Math.abs( flo ); var intPart = parseInt( d, 10 ); var floatPart = precision ? @@ -14628,9 +14950,16 @@ intPart.toString().replace( /\B(?=(\d{3})+(?!\d))/g, thousands ) + - floatPart; + floatPart + + (postfix||''); } }; + }, + + text: function () { + return { + display: __htmlEscapeEntities + }; } }; @@ -14732,11 +15061,9 @@ _fnCalculateColumnWidths: _fnCalculateColumnWidths, _fnThrottle: _fnThrottle, _fnConvertToWidth: _fnConvertToWidth, - _fnScrollingWidthAdjust: _fnScrollingWidthAdjust, _fnGetWidestNode: _fnGetWidestNode, _fnGetMaxLenString: _fnGetMaxLenString, _fnStringToCss: _fnStringToCss, - _fnScrollBarWidth: _fnScrollBarWidth, _fnSortFlatten: _fnSortFlatten, _fnSort: _fnSort, _fnSortAria: _fnSortAria, @@ -14765,6 +15092,9 @@ // jQuery access $.fn.dataTable = DataTable; + // Provide access to the host jQuery object (circular reference) + DataTable.$ = $; + // Legacy aliases $.fn.dataTableSettings = DataTable.settings; $.fn.dataTableExt = DataTable.ext; @@ -14946,6 +15276,3 @@ return $.fn.dataTable; })); - -}(window, document)); - diff --git a/wqflask/wqflask/static/new/packages/DataTables/js/jquery.dataTables.min.js b/wqflask/wqflask/static/new/packages/DataTables/js/jquery.dataTables.min.js index 85dd817e..f1277251 100644 --- a/wqflask/wqflask/static/new/packages/DataTables/js/jquery.dataTables.min.js +++ b/wqflask/wqflask/static/new/packages/DataTables/js/jquery.dataTables.min.js @@ -1,160 +1,166 @@ -/*! DataTables 1.10.7 - * ©2008-2015 SpryMedia Ltd - datatables.net/license - */ -(function(Ea,Q,k){var P=function(h){function W(a){var b,c,e={};h.each(a,function(d){if((b=d.match(/^([^A-Z]+?)([A-Z])/))&&-1!=="a aa ai ao as b fn i m o s ".indexOf(b[1]+" "))c=d.replace(b[0],b[2].toLowerCase()),e[c]=d,"o"===b[1]&&W(a[d])});a._hungarianMap=e}function H(a,b,c){a._hungarianMap||W(a);var e;h.each(b,function(d){e=a._hungarianMap[d];if(e!==k&&(c||b[e]===k))"o"===e.charAt(0)?(b[e]||(b[e]={}),h.extend(!0,b[e],b[d]),H(a[e],b[e],c)):b[e]=b[d]})}function P(a){var b=m.defaults.oLanguage,c=a.sZeroRecords; -!a.sEmptyTable&&(c&&"No data available in table"===b.sEmptyTable)&&E(a,a,"sZeroRecords","sEmptyTable");!a.sLoadingRecords&&(c&&"Loading..."===b.sLoadingRecords)&&E(a,a,"sZeroRecords","sLoadingRecords");a.sInfoThousands&&(a.sThousands=a.sInfoThousands);(a=a.sDecimal)&&db(a)}function eb(a){A(a,"ordering","bSort");A(a,"orderMulti","bSortMulti");A(a,"orderClasses","bSortClasses");A(a,"orderCellsTop","bSortCellsTop");A(a,"order","aaSorting");A(a,"orderFixed","aaSortingFixed");A(a,"paging","bPaginate"); -A(a,"pagingType","sPaginationType");A(a,"pageLength","iDisplayLength");A(a,"searching","bFilter");if(a=a.aoSearchCols)for(var b=0,c=a.length;b<c;b++)a[b]&&H(m.models.oSearch,a[b])}function fb(a){A(a,"orderable","bSortable");A(a,"orderData","aDataSort");A(a,"orderSequence","asSorting");A(a,"orderDataType","sortDataType");var b=a.aDataSort;b&&!h.isArray(b)&&(a.aDataSort=[b])}function gb(a){var a=a.oBrowser,b=h("<div/>").css({position:"absolute",top:0,left:0,height:1,width:1,overflow:"hidden"}).append(h("<div/>").css({position:"absolute", -top:1,left:1,width:100,overflow:"scroll"}).append(h('<div class="test"/>').css({width:"100%",height:10}))).appendTo("body"),c=b.find(".test");a.bScrollOversize=100===c[0].offsetWidth;a.bScrollbarLeft=1!==Math.round(c.offset().left);b.remove()}function hb(a,b,c,e,d,f){var g,j=!1;c!==k&&(g=c,j=!0);for(;e!==d;)a.hasOwnProperty(e)&&(g=j?b(g,a[e],e,a):a[e],j=!0,e+=f);return g}function Fa(a,b){var c=m.defaults.column,e=a.aoColumns.length,c=h.extend({},m.models.oColumn,c,{nTh:b?b:Q.createElement("th"),sTitle:c.sTitle? -c.sTitle:b?b.innerHTML:"",aDataSort:c.aDataSort?c.aDataSort:[e],mData:c.mData?c.mData:e,idx:e});a.aoColumns.push(c);c=a.aoPreSearchCols;c[e]=h.extend({},m.models.oSearch,c[e]);ka(a,e,h(b).data())}function ka(a,b,c){var b=a.aoColumns[b],e=a.oClasses,d=h(b.nTh);if(!b.sWidthOrig){b.sWidthOrig=d.attr("width")||null;var f=(d.attr("style")||"").match(/width:\s*(\d+[pxem%]+)/);f&&(b.sWidthOrig=f[1])}c!==k&&null!==c&&(fb(c),H(m.defaults.column,c),c.mDataProp!==k&&!c.mData&&(c.mData=c.mDataProp),c.sType&& -(b._sManualType=c.sType),c.className&&!c.sClass&&(c.sClass=c.className),h.extend(b,c),E(b,c,"sWidth","sWidthOrig"),c.iDataSort!==k&&(b.aDataSort=[c.iDataSort]),E(b,c,"aDataSort"));var g=b.mData,j=R(g),i=b.mRender?R(b.mRender):null,c=function(a){return"string"===typeof a&&-1!==a.indexOf("@")};b._bAttrSrc=h.isPlainObject(g)&&(c(g.sort)||c(g.type)||c(g.filter));b.fnGetData=function(a,b,c){var e=j(a,b,k,c);return i&&b?i(e,b,a,c):e};b.fnSetData=function(a,b,c){return S(g)(a,b,c)};"number"!==typeof g&& -(a._rowReadObject=!0);a.oFeatures.bSort||(b.bSortable=!1,d.addClass(e.sSortableNone));a=-1!==h.inArray("asc",b.asSorting);c=-1!==h.inArray("desc",b.asSorting);!b.bSortable||!a&&!c?(b.sSortingClass=e.sSortableNone,b.sSortingClassJUI=""):a&&!c?(b.sSortingClass=e.sSortableAsc,b.sSortingClassJUI=e.sSortJUIAscAllowed):!a&&c?(b.sSortingClass=e.sSortableDesc,b.sSortingClassJUI=e.sSortJUIDescAllowed):(b.sSortingClass=e.sSortable,b.sSortingClassJUI=e.sSortJUI)}function X(a){if(!1!==a.oFeatures.bAutoWidth){var b= -a.aoColumns;Ga(a);for(var c=0,e=b.length;c<e;c++)b[c].nTh.style.width=b[c].sWidth}b=a.oScroll;(""!==b.sY||""!==b.sX)&&Y(a);w(a,null,"column-sizing",[a])}function la(a,b){var c=Z(a,"bVisible");return"number"===typeof c[b]?c[b]:null}function $(a,b){var c=Z(a,"bVisible"),c=h.inArray(b,c);return-1!==c?c:null}function aa(a){return Z(a,"bVisible").length}function Z(a,b){var c=[];h.map(a.aoColumns,function(a,d){a[b]&&c.push(d)});return c}function Ha(a){var b=a.aoColumns,c=a.aoData,e=m.ext.type.detect,d, -f,g,j,i,h,l,q,n;d=0;for(f=b.length;d<f;d++)if(l=b[d],n=[],!l.sType&&l._sManualType)l.sType=l._sManualType;else if(!l.sType){g=0;for(j=e.length;g<j;g++){i=0;for(h=c.length;i<h;i++){n[i]===k&&(n[i]=x(a,i,d,"type"));q=e[g](n[i],a);if(!q&&g!==e.length-1)break;if("html"===q)break}if(q){l.sType=q;break}}l.sType||(l.sType="string")}}function ib(a,b,c,e){var d,f,g,j,i,o,l=a.aoColumns;if(b)for(d=b.length-1;0<=d;d--){o=b[d];var q=o.targets!==k?o.targets:o.aTargets;h.isArray(q)||(q=[q]);f=0;for(g=q.length;f< -g;f++)if("number"===typeof q[f]&&0<=q[f]){for(;l.length<=q[f];)Fa(a);e(q[f],o)}else if("number"===typeof q[f]&&0>q[f])e(l.length+q[f],o);else if("string"===typeof q[f]){j=0;for(i=l.length;j<i;j++)("_all"==q[f]||h(l[j].nTh).hasClass(q[f]))&&e(j,o)}}if(c){d=0;for(a=c.length;d<a;d++)e(d,c[d])}}function K(a,b,c,e){var d=a.aoData.length,f=h.extend(!0,{},m.models.oRow,{src:c?"dom":"data"});f._aData=b;a.aoData.push(f);for(var b=a.aoColumns,f=0,g=b.length;f<g;f++)c&&Ia(a,d,f,x(a,d,f)),b[f].sType=null;a.aiDisplayMaster.push(d); -(c||!a.oFeatures.bDeferRender)&&Ja(a,d,c,e);return d}function ma(a,b){var c;b instanceof h||(b=h(b));return b.map(function(b,d){c=na(a,d);return K(a,c.data,d,c.cells)})}function x(a,b,c,e){var d=a.iDraw,f=a.aoColumns[c],g=a.aoData[b]._aData,j=f.sDefaultContent,c=f.fnGetData(g,e,{settings:a,row:b,col:c});if(c===k)return a.iDrawError!=d&&null===j&&(I(a,0,"Requested unknown parameter "+("function"==typeof f.mData?"{function}":"'"+f.mData+"'")+" for row "+b,4),a.iDrawError=d),j;if((c===g||null===c)&& -null!==j)c=j;else if("function"===typeof c)return c.call(g);return null===c&&"display"==e?"":c}function Ia(a,b,c,e){a.aoColumns[c].fnSetData(a.aoData[b]._aData,e,{settings:a,row:b,col:c})}function Ka(a){return h.map(a.match(/(\\.|[^\.])+/g),function(a){return a.replace(/\\./g,".")})}function R(a){if(h.isPlainObject(a)){var b={};h.each(a,function(a,c){c&&(b[a]=R(c))});return function(a,c,f,g){var j=b[c]||b._;return j!==k?j(a,c,f,g):a}}if(null===a)return function(a){return a};if("function"===typeof a)return function(b, -c,f,g){return a(b,c,f,g)};if("string"===typeof a&&(-1!==a.indexOf(".")||-1!==a.indexOf("[")||-1!==a.indexOf("("))){var c=function(a,b,f){var g,j;if(""!==f){j=Ka(f);for(var i=0,h=j.length;i<h;i++){f=j[i].match(ba);g=j[i].match(T);if(f){j[i]=j[i].replace(ba,"");""!==j[i]&&(a=a[j[i]]);g=[];j.splice(0,i+1);j=j.join(".");i=0;for(h=a.length;i<h;i++)g.push(c(a[i],b,j));a=f[0].substring(1,f[0].length-1);a=""===a?g:g.join(a);break}else if(g){j[i]=j[i].replace(T,"");a=a[j[i]]();continue}if(null===a||a[j[i]]=== -k)return k;a=a[j[i]]}}return a};return function(b,d){return c(b,d,a)}}return function(b){return b[a]}}function S(a){if(h.isPlainObject(a))return S(a._);if(null===a)return function(){};if("function"===typeof a)return function(b,e,d){a(b,"set",e,d)};if("string"===typeof a&&(-1!==a.indexOf(".")||-1!==a.indexOf("[")||-1!==a.indexOf("("))){var b=function(a,e,d){var d=Ka(d),f;f=d[d.length-1];for(var g,j,i=0,h=d.length-1;i<h;i++){g=d[i].match(ba);j=d[i].match(T);if(g){d[i]=d[i].replace(ba,"");a[d[i]]=[]; -f=d.slice();f.splice(0,i+1);g=f.join(".");j=0;for(h=e.length;j<h;j++)f={},b(f,e[j],g),a[d[i]].push(f);return}j&&(d[i]=d[i].replace(T,""),a=a[d[i]](e));if(null===a[d[i]]||a[d[i]]===k)a[d[i]]={};a=a[d[i]]}if(f.match(T))a[f.replace(T,"")](e);else a[f.replace(ba,"")]=e};return function(c,e){return b(c,e,a)}}return function(b,e){b[a]=e}}function La(a){return D(a.aoData,"_aData")}function oa(a){a.aoData.length=0;a.aiDisplayMaster.length=0;a.aiDisplay.length=0}function pa(a,b,c){for(var e=-1,d=0,f=a.length;d< -f;d++)a[d]==b?e=d:a[d]>b&&a[d]--; -1!=e&&c===k&&a.splice(e,1)}function ca(a,b,c,e){var d=a.aoData[b],f,g=function(c,f){for(;c.childNodes.length;)c.removeChild(c.firstChild);c.innerHTML=x(a,b,f,"display")};if("dom"===c||(!c||"auto"===c)&&"dom"===d.src)d._aData=na(a,d,e,e===k?k:d._aData).data;else{var j=d.anCells;if(j)if(e!==k)g(j[e],e);else{c=0;for(f=j.length;c<f;c++)g(j[c],c)}}d._aSortData=null;d._aFilterData=null;g=a.aoColumns;if(e!==k)g[e].sType=null;else{c=0;for(f=g.length;c<f;c++)g[c].sType=null; -Ma(d)}}function na(a,b,c,e){var d=[],f=b.firstChild,g,j=0,i,o=a.aoColumns,l=a._rowReadObject,e=e||l?{}:[],q=function(a,b){if("string"===typeof a){var c=a.indexOf("@");-1!==c&&(c=a.substring(c+1),S(a)(e,b.getAttribute(c)))}},a=function(a){if(c===k||c===j)g=o[j],i=h.trim(a.innerHTML),g&&g._bAttrSrc?(S(g.mData._)(e,i),q(g.mData.sort,a),q(g.mData.type,a),q(g.mData.filter,a)):l?(g._setter||(g._setter=S(g.mData)),g._setter(e,i)):e[j]=i;j++};if(f)for(;f;){b=f.nodeName.toUpperCase();if("TD"==b||"TH"==b)a(f), -d.push(f);f=f.nextSibling}else{d=b.anCells;f=0;for(b=d.length;f<b;f++)a(d[f])}return{data:e,cells:d}}function Ja(a,b,c,e){var d=a.aoData[b],f=d._aData,g=[],j,i,h,l,q;if(null===d.nTr){j=c||Q.createElement("tr");d.nTr=j;d.anCells=g;j._DT_RowIndex=b;Ma(d);l=0;for(q=a.aoColumns.length;l<q;l++){h=a.aoColumns[l];i=c?e[l]:Q.createElement(h.sCellType);g.push(i);if(!c||h.mRender||h.mData!==l)i.innerHTML=x(a,b,l,"display");h.sClass&&(i.className+=" "+h.sClass);h.bVisible&&!c?j.appendChild(i):!h.bVisible&&c&& -i.parentNode.removeChild(i);h.fnCreatedCell&&h.fnCreatedCell.call(a.oInstance,i,x(a,b,l),f,b,l)}w(a,"aoRowCreatedCallback",null,[j,f,b])}d.nTr.setAttribute("role","row")}function Ma(a){var b=a.nTr,c=a._aData;if(b){c.DT_RowId&&(b.id=c.DT_RowId);if(c.DT_RowClass){var e=c.DT_RowClass.split(" ");a.__rowc=a.__rowc?Na(a.__rowc.concat(e)):e;h(b).removeClass(a.__rowc.join(" ")).addClass(c.DT_RowClass)}c.DT_RowAttr&&h(b).attr(c.DT_RowAttr);c.DT_RowData&&h(b).data(c.DT_RowData)}}function jb(a){var b,c,e,d, -f,g=a.nTHead,j=a.nTFoot,i=0===h("th, td",g).length,o=a.oClasses,l=a.aoColumns;i&&(d=h("<tr/>").appendTo(g));b=0;for(c=l.length;b<c;b++)f=l[b],e=h(f.nTh).addClass(f.sClass),i&&e.appendTo(d),a.oFeatures.bSort&&(e.addClass(f.sSortingClass),!1!==f.bSortable&&(e.attr("tabindex",a.iTabIndex).attr("aria-controls",a.sTableId),Oa(a,f.nTh,b))),f.sTitle!=e.html()&&e.html(f.sTitle),Pa(a,"header")(a,e,f,o);i&&da(a.aoHeader,g);h(g).find(">tr").attr("role","row");h(g).find(">tr>th, >tr>td").addClass(o.sHeaderTH); -h(j).find(">tr>th, >tr>td").addClass(o.sFooterTH);if(null!==j){a=a.aoFooter[0];b=0;for(c=a.length;b<c;b++)f=l[b],f.nTf=a[b].cell,f.sClass&&h(f.nTf).addClass(f.sClass)}}function ea(a,b,c){var e,d,f,g=[],j=[],i=a.aoColumns.length,o;if(b){c===k&&(c=!1);e=0;for(d=b.length;e<d;e++){g[e]=b[e].slice();g[e].nTr=b[e].nTr;for(f=i-1;0<=f;f--)!a.aoColumns[f].bVisible&&!c&&g[e].splice(f,1);j.push([])}e=0;for(d=g.length;e<d;e++){if(a=g[e].nTr)for(;f=a.firstChild;)a.removeChild(f);f=0;for(b=g[e].length;f<b;f++)if(o= -i=1,j[e][f]===k){a.appendChild(g[e][f].cell);for(j[e][f]=1;g[e+i]!==k&&g[e][f].cell==g[e+i][f].cell;)j[e+i][f]=1,i++;for(;g[e][f+o]!==k&&g[e][f].cell==g[e][f+o].cell;){for(c=0;c<i;c++)j[e+c][f+o]=1;o++}h(g[e][f].cell).attr("rowspan",i).attr("colspan",o)}}}}function M(a){var b=w(a,"aoPreDrawCallback","preDraw",[a]);if(-1!==h.inArray(!1,b))C(a,!1);else{var b=[],c=0,e=a.asStripeClasses,d=e.length,f=a.oLanguage,g=a.iInitDisplayStart,j="ssp"==B(a),i=a.aiDisplay;a.bDrawing=!0;g!==k&&-1!==g&&(a._iDisplayStart= -j?g:g>=a.fnRecordsDisplay()?0:g,a.iInitDisplayStart=-1);var g=a._iDisplayStart,o=a.fnDisplayEnd();if(a.bDeferLoading)a.bDeferLoading=!1,a.iDraw++,C(a,!1);else if(j){if(!a.bDestroying&&!kb(a))return}else a.iDraw++;if(0!==i.length){f=j?a.aoData.length:o;for(j=j?0:g;j<f;j++){var l=i[j],q=a.aoData[l];null===q.nTr&&Ja(a,l);l=q.nTr;if(0!==d){var n=e[c%d];q._sRowStripe!=n&&(h(l).removeClass(q._sRowStripe).addClass(n),q._sRowStripe=n)}w(a,"aoRowCallback",null,[l,q._aData,c,j]);b.push(l);c++}}else c=f.sZeroRecords, -1==a.iDraw&&"ajax"==B(a)?c=f.sLoadingRecords:f.sEmptyTable&&0===a.fnRecordsTotal()&&(c=f.sEmptyTable),b[0]=h("<tr/>",{"class":d?e[0]:""}).append(h("<td />",{valign:"top",colSpan:aa(a),"class":a.oClasses.sRowEmpty}).html(c))[0];w(a,"aoHeaderCallback","header",[h(a.nTHead).children("tr")[0],La(a),g,o,i]);w(a,"aoFooterCallback","footer",[h(a.nTFoot).children("tr")[0],La(a),g,o,i]);e=h(a.nTBody);e.children().detach();e.append(h(b));w(a,"aoDrawCallback","draw",[a]);a.bSorted=!1;a.bFiltered=!1;a.bDrawing= -!1}}function N(a,b){var c=a.oFeatures,e=c.bFilter;c.bSort&&lb(a);e?fa(a,a.oPreviousSearch):a.aiDisplay=a.aiDisplayMaster.slice();!0!==b&&(a._iDisplayStart=0);a._drawHold=b;M(a);a._drawHold=!1}function mb(a){var b=a.oClasses,c=h(a.nTable),c=h("<div/>").insertBefore(c),e=a.oFeatures,d=h("<div/>",{id:a.sTableId+"_wrapper","class":b.sWrapper+(a.nTFoot?"":" "+b.sNoFooter)});a.nHolding=c[0];a.nTableWrapper=d[0];a.nTableReinsertBefore=a.nTable.nextSibling;for(var f=a.sDom.split(""),g,j,i,o,l,q,n=0;n<f.length;n++){g= -null;j=f[n];if("<"==j){i=h("<div/>")[0];o=f[n+1];if("'"==o||'"'==o){l="";for(q=2;f[n+q]!=o;)l+=f[n+q],q++;"H"==l?l=b.sJUIHeader:"F"==l&&(l=b.sJUIFooter);-1!=l.indexOf(".")?(o=l.split("."),i.id=o[0].substr(1,o[0].length-1),i.className=o[1]):"#"==l.charAt(0)?i.id=l.substr(1,l.length-1):i.className=l;n+=q}d.append(i);d=h(i)}else if(">"==j)d=d.parent();else if("l"==j&&e.bPaginate&&e.bLengthChange)g=nb(a);else if("f"==j&&e.bFilter)g=ob(a);else if("r"==j&&e.bProcessing)g=pb(a);else if("t"==j)g=qb(a);else if("i"== -j&&e.bInfo)g=rb(a);else if("p"==j&&e.bPaginate)g=sb(a);else if(0!==m.ext.feature.length){i=m.ext.feature;q=0;for(o=i.length;q<o;q++)if(j==i[q].cFeature){g=i[q].fnInit(a);break}}g&&(i=a.aanFeatures,i[j]||(i[j]=[]),i[j].push(g),d.append(g))}c.replaceWith(d)}function da(a,b){var c=h(b).children("tr"),e,d,f,g,j,i,o,l,q,n;a.splice(0,a.length);f=0;for(i=c.length;f<i;f++)a.push([]);f=0;for(i=c.length;f<i;f++){e=c[f];for(d=e.firstChild;d;){if("TD"==d.nodeName.toUpperCase()||"TH"==d.nodeName.toUpperCase()){l= -1*d.getAttribute("colspan");q=1*d.getAttribute("rowspan");l=!l||0===l||1===l?1:l;q=!q||0===q||1===q?1:q;g=0;for(j=a[f];j[g];)g++;o=g;n=1===l?!0:!1;for(j=0;j<l;j++)for(g=0;g<q;g++)a[f+g][o+j]={cell:d,unique:n},a[f+g].nTr=e}d=d.nextSibling}}}function qa(a,b,c){var e=[];c||(c=a.aoHeader,b&&(c=[],da(c,b)));for(var b=0,d=c.length;b<d;b++)for(var f=0,g=c[b].length;f<g;f++)if(c[b][f].unique&&(!e[f]||!a.bSortCellsTop))e[f]=c[b][f].cell;return e}function ra(a,b,c){w(a,"aoServerParams","serverParams",[b]); -if(b&&h.isArray(b)){var e={},d=/(.*?)\[\]$/;h.each(b,function(a,b){var c=b.name.match(d);c?(c=c[0],e[c]||(e[c]=[]),e[c].push(b.value)):e[b.name]=b.value});b=e}var f,g=a.ajax,j=a.oInstance,i=function(b){w(a,null,"xhr",[a,b,a.jqXHR]);c(b)};if(h.isPlainObject(g)&&g.data){f=g.data;var o=h.isFunction(f)?f(b,a):f,b=h.isFunction(f)&&o?o:h.extend(!0,b,o);delete g.data}o={data:b,success:function(b){var c=b.error||b.sError;c&&I(a,0,c);a.json=b;i(b)},dataType:"json",cache:!1,type:a.sServerMethod,error:function(b, -c){var f=w(a,null,"xhr",[a,null,a.jqXHR]);-1===h.inArray(!0,f)&&("parsererror"==c?I(a,0,"Invalid JSON response",1):4===b.readyState&&I(a,0,"Ajax error",7));C(a,!1)}};a.oAjaxData=b;w(a,null,"preXhr",[a,b]);a.fnServerData?a.fnServerData.call(j,a.sAjaxSource,h.map(b,function(a,b){return{name:b,value:a}}),i,a):a.sAjaxSource||"string"===typeof g?a.jqXHR=h.ajax(h.extend(o,{url:g||a.sAjaxSource})):h.isFunction(g)?a.jqXHR=g.call(j,b,i,a):(a.jqXHR=h.ajax(h.extend(o,g)),g.data=f)}function kb(a){return a.bAjaxDataGet? -(a.iDraw++,C(a,!0),ra(a,tb(a),function(b){ub(a,b)}),!1):!0}function tb(a){var b=a.aoColumns,c=b.length,e=a.oFeatures,d=a.oPreviousSearch,f=a.aoPreSearchCols,g,j=[],i,o,l,q=U(a);g=a._iDisplayStart;i=!1!==e.bPaginate?a._iDisplayLength:-1;var n=function(a,b){j.push({name:a,value:b})};n("sEcho",a.iDraw);n("iColumns",c);n("sColumns",D(b,"sName").join(","));n("iDisplayStart",g);n("iDisplayLength",i);var k={draw:a.iDraw,columns:[],order:[],start:g,length:i,search:{value:d.sSearch,regex:d.bRegex}};for(g= -0;g<c;g++)o=b[g],l=f[g],i="function"==typeof o.mData?"function":o.mData,k.columns.push({data:i,name:o.sName,searchable:o.bSearchable,orderable:o.bSortable,search:{value:l.sSearch,regex:l.bRegex}}),n("mDataProp_"+g,i),e.bFilter&&(n("sSearch_"+g,l.sSearch),n("bRegex_"+g,l.bRegex),n("bSearchable_"+g,o.bSearchable)),e.bSort&&n("bSortable_"+g,o.bSortable);e.bFilter&&(n("sSearch",d.sSearch),n("bRegex",d.bRegex));e.bSort&&(h.each(q,function(a,b){k.order.push({column:b.col,dir:b.dir});n("iSortCol_"+a,b.col); -n("sSortDir_"+a,b.dir)}),n("iSortingCols",q.length));b=m.ext.legacy.ajax;return null===b?a.sAjaxSource?j:k:b?j:k}function ub(a,b){var c=sa(a,b),e=b.sEcho!==k?b.sEcho:b.draw,d=b.iTotalRecords!==k?b.iTotalRecords:b.recordsTotal,f=b.iTotalDisplayRecords!==k?b.iTotalDisplayRecords:b.recordsFiltered;if(e){if(1*e<a.iDraw)return;a.iDraw=1*e}oa(a);a._iRecordsTotal=parseInt(d,10);a._iRecordsDisplay=parseInt(f,10);e=0;for(d=c.length;e<d;e++)K(a,c[e]);a.aiDisplay=a.aiDisplayMaster.slice();a.bAjaxDataGet=!1; -M(a);a._bInitComplete||ta(a,b);a.bAjaxDataGet=!0;C(a,!1)}function sa(a,b){var c=h.isPlainObject(a.ajax)&&a.ajax.dataSrc!==k?a.ajax.dataSrc:a.sAjaxDataProp;return"data"===c?b.aaData||b[c]:""!==c?R(c)(b):b}function ob(a){var b=a.oClasses,c=a.sTableId,e=a.oLanguage,d=a.oPreviousSearch,f=a.aanFeatures,g='<input type="search" class="'+b.sFilterInput+'"/>',j=e.sSearch,j=j.match(/_INPUT_/)?j.replace("_INPUT_",g):j+g,b=h("<div/>",{id:!f.f?c+"_filter":null,"class":b.sFilter}).append(h("<label/>").append(j)), -f=function(){var b=!this.value?"":this.value;b!=d.sSearch&&(fa(a,{sSearch:b,bRegex:d.bRegex,bSmart:d.bSmart,bCaseInsensitive:d.bCaseInsensitive}),a._iDisplayStart=0,M(a))},g=null!==a.searchDelay?a.searchDelay:"ssp"===B(a)?400:0,i=h("input",b).val(d.sSearch).attr("placeholder",e.sSearchPlaceholder).bind("keyup.DT search.DT input.DT paste.DT cut.DT",g?ua(f,g):f).bind("keypress.DT",function(a){if(13==a.keyCode)return!1}).attr("aria-controls",c);h(a.nTable).on("search.dt.DT",function(b,c){if(a===c)try{i[0]!== -Q.activeElement&&i.val(d.sSearch)}catch(f){}});return b[0]}function fa(a,b,c){var e=a.oPreviousSearch,d=a.aoPreSearchCols,f=function(a){e.sSearch=a.sSearch;e.bRegex=a.bRegex;e.bSmart=a.bSmart;e.bCaseInsensitive=a.bCaseInsensitive};Ha(a);if("ssp"!=B(a)){vb(a,b.sSearch,c,b.bEscapeRegex!==k?!b.bEscapeRegex:b.bRegex,b.bSmart,b.bCaseInsensitive);f(b);for(b=0;b<d.length;b++)wb(a,d[b].sSearch,b,d[b].bEscapeRegex!==k?!d[b].bEscapeRegex:d[b].bRegex,d[b].bSmart,d[b].bCaseInsensitive);xb(a)}else f(b);a.bFiltered= -!0;w(a,null,"search",[a])}function xb(a){for(var b=m.ext.search,c=a.aiDisplay,e,d,f=0,g=b.length;f<g;f++){for(var j=[],i=0,h=c.length;i<h;i++)d=c[i],e=a.aoData[d],b[f](a,e._aFilterData,d,e._aData,i)&&j.push(d);c.length=0;c.push.apply(c,j)}}function wb(a,b,c,e,d,f){if(""!==b)for(var g=a.aiDisplay,e=Qa(b,e,d,f),d=g.length-1;0<=d;d--)b=a.aoData[g[d]]._aFilterData[c],e.test(b)||g.splice(d,1)}function vb(a,b,c,e,d,f){var e=Qa(b,e,d,f),d=a.oPreviousSearch.sSearch,f=a.aiDisplayMaster,g;0!==m.ext.search.length&& -(c=!0);g=yb(a);if(0>=b.length)a.aiDisplay=f.slice();else{if(g||c||d.length>b.length||0!==b.indexOf(d)||a.bSorted)a.aiDisplay=f.slice();b=a.aiDisplay;for(c=b.length-1;0<=c;c--)e.test(a.aoData[b[c]]._sFilterRow)||b.splice(c,1)}}function Qa(a,b,c,e){a=b?a:va(a);c&&(a="^(?=.*?"+h.map(a.match(/"[^"]+"|[^ ]+/g)||[""],function(a){if('"'===a.charAt(0))var b=a.match(/^"(.*)"$/),a=b?b[1]:a;return a.replace('"',"")}).join(")(?=.*?")+").*$");return RegExp(a,e?"i":"")}function va(a){return a.replace(Yb,"\\$1")} -function yb(a){var b=a.aoColumns,c,e,d,f,g,j,i,h,l=m.ext.type.search;c=!1;e=0;for(f=a.aoData.length;e<f;e++)if(h=a.aoData[e],!h._aFilterData){j=[];d=0;for(g=b.length;d<g;d++)c=b[d],c.bSearchable?(i=x(a,e,d,"filter"),l[c.sType]&&(i=l[c.sType](i)),null===i&&(i=""),"string"!==typeof i&&i.toString&&(i=i.toString())):i="",i.indexOf&&-1!==i.indexOf("&")&&(wa.innerHTML=i,i=Zb?wa.textContent:wa.innerText),i.replace&&(i=i.replace(/[\r\n]/g,"")),j.push(i);h._aFilterData=j;h._sFilterRow=j.join(" ");c=!0}return c} -function zb(a){return{search:a.sSearch,smart:a.bSmart,regex:a.bRegex,caseInsensitive:a.bCaseInsensitive}}function Ab(a){return{sSearch:a.search,bSmart:a.smart,bRegex:a.regex,bCaseInsensitive:a.caseInsensitive}}function rb(a){var b=a.sTableId,c=a.aanFeatures.i,e=h("<div/>",{"class":a.oClasses.sInfo,id:!c?b+"_info":null});c||(a.aoDrawCallback.push({fn:Bb,sName:"information"}),e.attr("role","status").attr("aria-live","polite"),h(a.nTable).attr("aria-describedby",b+"_info"));return e[0]}function Bb(a){var b= -a.aanFeatures.i;if(0!==b.length){var c=a.oLanguage,e=a._iDisplayStart+1,d=a.fnDisplayEnd(),f=a.fnRecordsTotal(),g=a.fnRecordsDisplay(),j=g?c.sInfo:c.sInfoEmpty;g!==f&&(j+=" "+c.sInfoFiltered);j+=c.sInfoPostFix;j=Cb(a,j);c=c.fnInfoCallback;null!==c&&(j=c.call(a.oInstance,a,e,d,f,g,j));h(b).html(j)}}function Cb(a,b){var c=a.fnFormatNumber,e=a._iDisplayStart+1,d=a._iDisplayLength,f=a.fnRecordsDisplay(),g=-1===d;return b.replace(/_START_/g,c.call(a,e)).replace(/_END_/g,c.call(a,a.fnDisplayEnd())).replace(/_MAX_/g, -c.call(a,a.fnRecordsTotal())).replace(/_TOTAL_/g,c.call(a,f)).replace(/_PAGE_/g,c.call(a,g?1:Math.ceil(e/d))).replace(/_PAGES_/g,c.call(a,g?1:Math.ceil(f/d)))}function ga(a){var b,c,e=a.iInitDisplayStart,d=a.aoColumns,f;c=a.oFeatures;if(a.bInitialised){mb(a);jb(a);ea(a,a.aoHeader);ea(a,a.aoFooter);C(a,!0);c.bAutoWidth&&Ga(a);b=0;for(c=d.length;b<c;b++)f=d[b],f.sWidth&&(f.nTh.style.width=s(f.sWidth));N(a);d=B(a);"ssp"!=d&&("ajax"==d?ra(a,[],function(c){var f=sa(a,c);for(b=0;b<f.length;b++)K(a,f[b]); -a.iInitDisplayStart=e;N(a);C(a,!1);ta(a,c)},a):(C(a,!1),ta(a)))}else setTimeout(function(){ga(a)},200)}function ta(a,b){a._bInitComplete=!0;b&&X(a);w(a,"aoInitComplete","init",[a,b])}function Ra(a,b){var c=parseInt(b,10);a._iDisplayLength=c;Sa(a);w(a,null,"length",[a,c])}function nb(a){for(var b=a.oClasses,c=a.sTableId,e=a.aLengthMenu,d=h.isArray(e[0]),f=d?e[0]:e,e=d?e[1]:e,d=h("<select/>",{name:c+"_length","aria-controls":c,"class":b.sLengthSelect}),g=0,j=f.length;g<j;g++)d[0][g]=new Option(e[g], -f[g]);var i=h("<div><label/></div>").addClass(b.sLength);a.aanFeatures.l||(i[0].id=c+"_length");i.children().append(a.oLanguage.sLengthMenu.replace("_MENU_",d[0].outerHTML));h("select",i).val(a._iDisplayLength).bind("change.DT",function(){Ra(a,h(this).val());M(a)});h(a.nTable).bind("length.dt.DT",function(b,c,f){a===c&&h("select",i).val(f)});return i[0]}function sb(a){var b=a.sPaginationType,c=m.ext.pager[b],e="function"===typeof c,d=function(a){M(a)},b=h("<div/>").addClass(a.oClasses.sPaging+b)[0], -f=a.aanFeatures;e||c.fnInit(a,b,d);f.p||(b.id=a.sTableId+"_paginate",a.aoDrawCallback.push({fn:function(a){if(e){var b=a._iDisplayStart,i=a._iDisplayLength,h=a.fnRecordsDisplay(),l=-1===i,b=l?0:Math.ceil(b/i),i=l?1:Math.ceil(h/i),h=c(b,i),q,l=0;for(q=f.p.length;l<q;l++)Pa(a,"pageButton")(a,f.p[l],l,h,b,i)}else c.fnUpdate(a,d)},sName:"pagination"}));return b}function Ta(a,b,c){var e=a._iDisplayStart,d=a._iDisplayLength,f=a.fnRecordsDisplay();0===f||-1===d?e=0:"number"===typeof b?(e=b*d,e>f&&(e=0)): -"first"==b?e=0:"previous"==b?(e=0<=d?e-d:0,0>e&&(e=0)):"next"==b?e+d<f&&(e+=d):"last"==b?e=Math.floor((f-1)/d)*d:I(a,0,"Unknown paging action: "+b,5);b=a._iDisplayStart!==e;a._iDisplayStart=e;b&&(w(a,null,"page",[a]),c&&M(a));return b}function pb(a){return h("<div/>",{id:!a.aanFeatures.r?a.sTableId+"_processing":null,"class":a.oClasses.sProcessing}).html(a.oLanguage.sProcessing).insertBefore(a.nTable)[0]}function C(a,b){a.oFeatures.bProcessing&&h(a.aanFeatures.r).css("display",b?"block":"none");w(a, -null,"processing",[a,b])}function qb(a){var b=h(a.nTable);b.attr("role","grid");var c=a.oScroll;if(""===c.sX&&""===c.sY)return a.nTable;var e=c.sX,d=c.sY,f=a.oClasses,g=b.children("caption"),j=g.length?g[0]._captionSide:null,i=h(b[0].cloneNode(!1)),o=h(b[0].cloneNode(!1)),l=b.children("tfoot");c.sX&&"100%"===b.attr("width")&&b.removeAttr("width");l.length||(l=null);c=h("<div/>",{"class":f.sScrollWrapper}).append(h("<div/>",{"class":f.sScrollHead}).css({overflow:"hidden",position:"relative",border:0, -width:e?!e?null:s(e):"100%"}).append(h("<div/>",{"class":f.sScrollHeadInner}).css({"box-sizing":"content-box",width:c.sXInner||"100%"}).append(i.removeAttr("id").css("margin-left",0).append("top"===j?g:null).append(b.children("thead"))))).append(h("<div/>",{"class":f.sScrollBody}).css({overflow:"auto",height:!d?null:s(d),width:!e?null:s(e)}).append(b));l&&c.append(h("<div/>",{"class":f.sScrollFoot}).css({overflow:"hidden",border:0,width:e?!e?null:s(e):"100%"}).append(h("<div/>",{"class":f.sScrollFootInner}).append(o.removeAttr("id").css("margin-left", -0).append("bottom"===j?g:null).append(b.children("tfoot")))));var b=c.children(),q=b[0],f=b[1],n=l?b[2]:null;if(e)h(f).on("scroll.DT",function(){var a=this.scrollLeft;q.scrollLeft=a;l&&(n.scrollLeft=a)});a.nScrollHead=q;a.nScrollBody=f;a.nScrollFoot=n;a.aoDrawCallback.push({fn:Y,sName:"scrolling"});return c[0]}function Y(a){var b=a.oScroll,c=b.sX,e=b.sXInner,d=b.sY,f=b.iBarWidth,g=h(a.nScrollHead),j=g[0].style,i=g.children("div"),o=i[0].style,l=i.children("table"),i=a.nScrollBody,q=h(i),n=i.style, -k=h(a.nScrollFoot).children("div"),p=k.children("table"),m=h(a.nTHead),r=h(a.nTable),t=r[0],O=t.style,L=a.nTFoot?h(a.nTFoot):null,ha=a.oBrowser,w=ha.bScrollOversize,v,u,y,x,z,A=[],B=[],C=[],D,E=function(a){a=a.style;a.paddingTop="0";a.paddingBottom="0";a.borderTopWidth="0";a.borderBottomWidth="0";a.height=0};r.children("thead, tfoot").remove();z=m.clone().prependTo(r);v=m.find("tr");y=z.find("tr");z.find("th, td").removeAttr("tabindex");L&&(x=L.clone().prependTo(r),u=L.find("tr"),x=x.find("tr")); -c||(n.width="100%",g[0].style.width="100%");h.each(qa(a,z),function(b,c){D=la(a,b);c.style.width=a.aoColumns[D].sWidth});L&&G(function(a){a.style.width=""},x);b.bCollapse&&""!==d&&(n.height=q[0].offsetHeight+m[0].offsetHeight+"px");g=r.outerWidth();if(""===c){if(O.width="100%",w&&(r.find("tbody").height()>i.offsetHeight||"scroll"==q.css("overflow-y")))O.width=s(r.outerWidth()-f)}else""!==e?O.width=s(e):g==q.width()&&q.height()<r.height()?(O.width=s(g-f),r.outerWidth()>g-f&&(O.width=s(g))):O.width= -s(g);g=r.outerWidth();G(E,y);G(function(a){C.push(a.innerHTML);A.push(s(h(a).css("width")))},y);G(function(a,b){a.style.width=A[b]},v);h(y).height(0);L&&(G(E,x),G(function(a){B.push(s(h(a).css("width")))},x),G(function(a,b){a.style.width=B[b]},u),h(x).height(0));G(function(a,b){a.innerHTML='<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+C[b]+"</div>";a.style.width=A[b]},y);L&&G(function(a,b){a.innerHTML="";a.style.width=B[b]},x);if(r.outerWidth()<g){u=i.scrollHeight>i.offsetHeight|| -"scroll"==q.css("overflow-y")?g+f:g;if(w&&(i.scrollHeight>i.offsetHeight||"scroll"==q.css("overflow-y")))O.width=s(u-f);(""===c||""!==e)&&I(a,1,"Possible column misalignment",6)}else u="100%";n.width=s(u);j.width=s(u);L&&(a.nScrollFoot.style.width=s(u));!d&&w&&(n.height=s(t.offsetHeight+f));d&&b.bCollapse&&(n.height=s(d),b=c&&t.offsetWidth>i.offsetWidth?f:0,t.offsetHeight<i.offsetHeight&&(n.height=s(t.offsetHeight+b)));b=r.outerWidth();l[0].style.width=s(b);o.width=s(b);l=r.height()>i.clientHeight|| -"scroll"==q.css("overflow-y");ha="padding"+(ha.bScrollbarLeft?"Left":"Right");o[ha]=l?f+"px":"0px";L&&(p[0].style.width=s(b),k[0].style.width=s(b),k[0].style[ha]=l?f+"px":"0px");q.scroll();if((a.bSorted||a.bFiltered)&&!a._drawHold)i.scrollTop=0}function G(a,b,c){for(var e=0,d=0,f=b.length,g,j;d<f;){g=b[d].firstChild;for(j=c?c[d].firstChild:null;g;)1===g.nodeType&&(c?a(g,j,e):a(g,e),e++),g=g.nextSibling,j=c?j.nextSibling:null;d++}}function Ga(a){var b=a.nTable,c=a.aoColumns,e=a.oScroll,d=e.sY,f=e.sX, -g=e.sXInner,j=c.length,e=Z(a,"bVisible"),i=h("th",a.nTHead),o=b.getAttribute("width"),l=b.parentNode,k=!1,n,m;(n=b.style.width)&&-1!==n.indexOf("%")&&(o=n);for(n=0;n<e.length;n++)m=c[e[n]],null!==m.sWidth&&(m.sWidth=Db(m.sWidthOrig,l),k=!0);if(!k&&!f&&!d&&j==aa(a)&&j==i.length)for(n=0;n<j;n++)c[n].sWidth=s(i.eq(n).width());else{j=h(b).clone().css("visibility","hidden").removeAttr("id");j.find("tbody tr").remove();var p=h("<tr/>").appendTo(j.find("tbody"));j.find("tfoot th, tfoot td").css("width", -"");i=qa(a,j.find("thead")[0]);for(n=0;n<e.length;n++)m=c[e[n]],i[n].style.width=null!==m.sWidthOrig&&""!==m.sWidthOrig?s(m.sWidthOrig):"";if(a.aoData.length)for(n=0;n<e.length;n++)k=e[n],m=c[k],h(Eb(a,k)).clone(!1).append(m.sContentPadding).appendTo(p);j.appendTo(l);f&&g?j.width(g):f?(j.css("width","auto"),j.width()<l.offsetWidth&&j.width(l.offsetWidth)):d?j.width(l.offsetWidth):o&&j.width(o);Fb(a,j[0]);if(f){for(n=g=0;n<e.length;n++)m=c[e[n]],d=h(i[n]).outerWidth(),g+=null===m.sWidthOrig?d:parseInt(m.sWidth, -10)+d-h(i[n]).width();j.width(s(g));b.style.width=s(g)}for(n=0;n<e.length;n++)if(m=c[e[n]],d=h(i[n]).width())m.sWidth=s(d);b.style.width=s(j.css("width"));j.remove()}o&&(b.style.width=s(o));if((o||f)&&!a._reszEvt)b=function(){h(Ea).bind("resize.DT-"+a.sInstance,ua(function(){X(a)}))},a.oBrowser.bScrollOversize?setTimeout(b,1E3):b(),a._reszEvt=!0}function ua(a,b){var c=b!==k?b:200,e,d;return function(){var b=this,g=+new Date,j=arguments;e&&g<e+c?(clearTimeout(d),d=setTimeout(function(){e=k;a.apply(b, -j)},c)):(e=g,a.apply(b,j))}}function Db(a,b){if(!a)return 0;var c=h("<div/>").css("width",s(a)).appendTo(b||Q.body),e=c[0].offsetWidth;c.remove();return e}function Fb(a,b){var c=a.oScroll;if(c.sX||c.sY)c=!c.sX?c.iBarWidth:0,b.style.width=s(h(b).outerWidth()-c)}function Eb(a,b){var c=Gb(a,b);if(0>c)return null;var e=a.aoData[c];return!e.nTr?h("<td/>").html(x(a,c,b,"display"))[0]:e.anCells[b]}function Gb(a,b){for(var c,e=-1,d=-1,f=0,g=a.aoData.length;f<g;f++)c=x(a,f,b,"display")+"",c=c.replace($b,""), -c.length>e&&(e=c.length,d=f);return d}function s(a){return null===a?"0px":"number"==typeof a?0>a?"0px":a+"px":a.match(/\d$/)?a+"px":a}function Hb(){var a=m.__scrollbarWidth;if(a===k){var b=h("<p/>").css({position:"absolute",top:0,left:0,width:"100%",height:150,padding:0,overflow:"scroll",visibility:"hidden"}).appendTo("body"),a=b[0].offsetWidth-b[0].clientWidth;m.__scrollbarWidth=a;b.remove()}return a}function U(a){var b,c,e=[],d=a.aoColumns,f,g,j,i;b=a.aaSortingFixed;c=h.isPlainObject(b);var o=[]; -f=function(a){a.length&&!h.isArray(a[0])?o.push(a):o.push.apply(o,a)};h.isArray(b)&&f(b);c&&b.pre&&f(b.pre);f(a.aaSorting);c&&b.post&&f(b.post);for(a=0;a<o.length;a++){i=o[a][0];f=d[i].aDataSort;b=0;for(c=f.length;b<c;b++)g=f[b],j=d[g].sType||"string",o[a]._idx===k&&(o[a]._idx=h.inArray(o[a][1],d[g].asSorting)),e.push({src:i,col:g,dir:o[a][1],index:o[a]._idx,type:j,formatter:m.ext.type.order[j+"-pre"]})}return e}function lb(a){var b,c,e=[],d=m.ext.type.order,f=a.aoData,g=0,j,i=a.aiDisplayMaster,h; -Ha(a);h=U(a);b=0;for(c=h.length;b<c;b++)j=h[b],j.formatter&&g++,Ib(a,j.col);if("ssp"!=B(a)&&0!==h.length){b=0;for(c=i.length;b<c;b++)e[i[b]]=b;g===h.length?i.sort(function(a,b){var c,d,g,j,i=h.length,k=f[a]._aSortData,m=f[b]._aSortData;for(g=0;g<i;g++)if(j=h[g],c=k[j.col],d=m[j.col],c=c<d?-1:c>d?1:0,0!==c)return"asc"===j.dir?c:-c;c=e[a];d=e[b];return c<d?-1:c>d?1:0}):i.sort(function(a,b){var c,g,j,i,k=h.length,m=f[a]._aSortData,r=f[b]._aSortData;for(j=0;j<k;j++)if(i=h[j],c=m[i.col],g=r[i.col],i=d[i.type+ -"-"+i.dir]||d["string-"+i.dir],c=i(c,g),0!==c)return c;c=e[a];g=e[b];return c<g?-1:c>g?1:0})}a.bSorted=!0}function Jb(a){for(var b,c,e=a.aoColumns,d=U(a),a=a.oLanguage.oAria,f=0,g=e.length;f<g;f++){c=e[f];var j=c.asSorting;b=c.sTitle.replace(/<.*?>/g,"");var i=c.nTh;i.removeAttribute("aria-sort");c.bSortable&&(0<d.length&&d[0].col==f?(i.setAttribute("aria-sort","asc"==d[0].dir?"ascending":"descending"),c=j[d[0].index+1]||j[0]):c=j[0],b+="asc"===c?a.sSortAscending:a.sSortDescending);i.setAttribute("aria-label", -b)}}function Ua(a,b,c,e){var d=a.aaSorting,f=a.aoColumns[b].asSorting,g=function(a,b){var c=a._idx;c===k&&(c=h.inArray(a[1],f));return c+1<f.length?c+1:b?null:0};"number"===typeof d[0]&&(d=a.aaSorting=[d]);c&&a.oFeatures.bSortMulti?(c=h.inArray(b,D(d,"0")),-1!==c?(b=g(d[c],!0),null===b&&1===d.length&&(b=0),null===b?d.splice(c,1):(d[c][1]=f[b],d[c]._idx=b)):(d.push([b,f[0],0]),d[d.length-1]._idx=0)):d.length&&d[0][0]==b?(b=g(d[0]),d.length=1,d[0][1]=f[b],d[0]._idx=b):(d.length=0,d.push([b,f[0]]),d[0]._idx= -0);N(a);"function"==typeof e&&e(a)}function Oa(a,b,c,e){var d=a.aoColumns[c];Va(b,{},function(b){!1!==d.bSortable&&(a.oFeatures.bProcessing?(C(a,!0),setTimeout(function(){Ua(a,c,b.shiftKey,e);"ssp"!==B(a)&&C(a,!1)},0)):Ua(a,c,b.shiftKey,e))})}function xa(a){var b=a.aLastSort,c=a.oClasses.sSortColumn,e=U(a),d=a.oFeatures,f,g;if(d.bSort&&d.bSortClasses){d=0;for(f=b.length;d<f;d++)g=b[d].src,h(D(a.aoData,"anCells",g)).removeClass(c+(2>d?d+1:3));d=0;for(f=e.length;d<f;d++)g=e[d].src,h(D(a.aoData,"anCells", -g)).addClass(c+(2>d?d+1:3))}a.aLastSort=e}function Ib(a,b){var c=a.aoColumns[b],e=m.ext.order[c.sSortDataType],d;e&&(d=e.call(a.oInstance,a,b,$(a,b)));for(var f,g=m.ext.type.order[c.sType+"-pre"],j=0,i=a.aoData.length;j<i;j++)if(c=a.aoData[j],c._aSortData||(c._aSortData=[]),!c._aSortData[b]||e)f=e?d[j]:x(a,j,b,"sort"),c._aSortData[b]=g?g(f):f}function ya(a){if(a.oFeatures.bStateSave&&!a.bDestroying){var b={time:+new Date,start:a._iDisplayStart,length:a._iDisplayLength,order:h.extend(!0,[],a.aaSorting), -search:zb(a.oPreviousSearch),columns:h.map(a.aoColumns,function(b,e){return{visible:b.bVisible,search:zb(a.aoPreSearchCols[e])}})};w(a,"aoStateSaveParams","stateSaveParams",[a,b]);a.oSavedState=b;a.fnStateSaveCallback.call(a.oInstance,a,b)}}function Kb(a){var b,c,e=a.aoColumns;if(a.oFeatures.bStateSave){var d=a.fnStateLoadCallback.call(a.oInstance,a);if(d&&d.time&&(b=w(a,"aoStateLoadParams","stateLoadParams",[a,d]),-1===h.inArray(!1,b)&&(b=a.iStateDuration,!(0<b&&d.time<+new Date-1E3*b)&&e.length=== -d.columns.length))){a.oLoadedState=h.extend(!0,{},d);d.start!==k&&(a._iDisplayStart=d.start,a.iInitDisplayStart=d.start);d.length!==k&&(a._iDisplayLength=d.length);d.order!==k&&(a.aaSorting=[],h.each(d.order,function(b,c){a.aaSorting.push(c[0]>=e.length?[0,c[1]]:c)}));d.search!==k&&h.extend(a.oPreviousSearch,Ab(d.search));b=0;for(c=d.columns.length;b<c;b++){var f=d.columns[b];f.visible!==k&&(e[b].bVisible=f.visible);f.search!==k&&h.extend(a.aoPreSearchCols[b],Ab(f.search))}w(a,"aoStateLoaded","stateLoaded", -[a,d])}}}function za(a){var b=m.settings,a=h.inArray(a,D(b,"nTable"));return-1!==a?b[a]:null}function I(a,b,c,e){c="DataTables warning: "+(null!==a?"table id="+a.sTableId+" - ":"")+c;e&&(c+=". For more information about this error, please see http://datatables.net/tn/"+e);if(b)Ea.console&&console.log&&console.log(c);else if(b=m.ext,b=b.sErrMode||b.errMode,w(a,null,"error",[a,e,c]),"alert"==b)alert(c);else{if("throw"==b)throw Error(c);"function"==typeof b&&b(a,e,c)}}function E(a,b,c,e){h.isArray(c)? -h.each(c,function(c,f){h.isArray(f)?E(a,b,f[0],f[1]):E(a,b,f)}):(e===k&&(e=c),b[c]!==k&&(a[e]=b[c]))}function Lb(a,b,c){var e,d;for(d in b)b.hasOwnProperty(d)&&(e=b[d],h.isPlainObject(e)?(h.isPlainObject(a[d])||(a[d]={}),h.extend(!0,a[d],e)):a[d]=c&&"data"!==d&&"aaData"!==d&&h.isArray(e)?e.slice():e);return a}function Va(a,b,c){h(a).bind("click.DT",b,function(b){a.blur();c(b)}).bind("keypress.DT",b,function(a){13===a.which&&(a.preventDefault(),c(a))}).bind("selectstart.DT",function(){return!1})}function z(a, -b,c,e){c&&a[b].push({fn:c,sName:e})}function w(a,b,c,e){var d=[];b&&(d=h.map(a[b].slice().reverse(),function(b){return b.fn.apply(a.oInstance,e)}));null!==c&&(b=h.Event(c+".dt"),h(a.nTable).trigger(b,e),d.push(b.result));return d}function Sa(a){var b=a._iDisplayStart,c=a.fnDisplayEnd(),e=a._iDisplayLength;b>=c&&(b=c-e);b-=b%e;if(-1===e||0>b)b=0;a._iDisplayStart=b}function Pa(a,b){var c=a.renderer,e=m.ext.renderer[b];return h.isPlainObject(c)&&c[b]?e[c[b]]||e._:"string"===typeof c?e[c]||e._:e._}function B(a){return a.oFeatures.bServerSide? -"ssp":a.ajax||a.sAjaxSource?"ajax":"dom"}function Wa(a,b){var c=[],c=Mb.numbers_length,e=Math.floor(c/2);b<=c?c=V(0,b):a<=e?(c=V(0,c-2),c.push("ellipsis"),c.push(b-1)):(a>=b-1-e?c=V(b-(c-2),b):(c=V(a-e+2,a+e-1),c.push("ellipsis"),c.push(b-1)),c.splice(0,0,"ellipsis"),c.splice(0,0,0));c.DT_el="span";return c}function db(a){h.each({num:function(b){return Aa(b,a)},"num-fmt":function(b){return Aa(b,a,Xa)},"html-num":function(b){return Aa(b,a,Ba)},"html-num-fmt":function(b){return Aa(b,a,Ba,Xa)}},function(b, -c){u.type.order[b+a+"-pre"]=c;b.match(/^html\-/)&&(u.type.search[b+a]=u.type.search.html)})}function Nb(a){return function(){var b=[za(this[m.ext.iApiIndex])].concat(Array.prototype.slice.call(arguments));return m.ext.internal[a].apply(this,b)}}var m,u,t,r,v,Ya={},Ob=/[\r\n]/g,Ba=/<.*?>/g,ac=/^[\w\+\-]/,bc=/[\w\+\-]$/,Yb=RegExp("(\\/|\\.|\\*|\\+|\\?|\\||\\(|\\)|\\[|\\]|\\{|\\}|\\\\|\\$|\\^|\\-)","g"),Xa=/[',$\u00a3\u20ac\u00a5%\u2009\u202F\u20BD\u20a9\u20BArfk]/gi,J=function(a){return!a||!0===a|| -"-"===a?!0:!1},Pb=function(a){var b=parseInt(a,10);return!isNaN(b)&&isFinite(a)?b:null},Qb=function(a,b){Ya[b]||(Ya[b]=RegExp(va(b),"g"));return"string"===typeof a&&"."!==b?a.replace(/\./g,"").replace(Ya[b],"."):a},Za=function(a,b,c){var e="string"===typeof a;if(J(a))return!0;b&&e&&(a=Qb(a,b));c&&e&&(a=a.replace(Xa,""));return!isNaN(parseFloat(a))&&isFinite(a)},Rb=function(a,b,c){return J(a)?!0:!(J(a)||"string"===typeof a)?null:Za(a.replace(Ba,""),b,c)?!0:null},D=function(a,b,c){var e=[],d=0,f=a.length; -if(c!==k)for(;d<f;d++)a[d]&&a[d][b]&&e.push(a[d][b][c]);else for(;d<f;d++)a[d]&&e.push(a[d][b]);return e},ia=function(a,b,c,e){var d=[],f=0,g=b.length;if(e!==k)for(;f<g;f++)a[b[f]][c]&&d.push(a[b[f]][c][e]);else for(;f<g;f++)d.push(a[b[f]][c]);return d},V=function(a,b){var c=[],e;b===k?(b=0,e=a):(e=b,b=a);for(var d=b;d<e;d++)c.push(d);return c},Sb=function(a){for(var b=[],c=0,e=a.length;c<e;c++)a[c]&&b.push(a[c]);return b},Na=function(a){var b=[],c,e,d=a.length,f,g=0;e=0;a:for(;e<d;e++){c=a[e];for(f= -0;f<g;f++)if(b[f]===c)continue a;b.push(c);g++}return b},A=function(a,b,c){a[b]!==k&&(a[c]=a[b])},ba=/\[.*?\]$/,T=/\(\)$/,wa=h("<div>")[0],Zb=wa.textContent!==k,$b=/<.*?>/g;m=function(a){this.$=function(a,b){return this.api(!0).$(a,b)};this._=function(a,b){return this.api(!0).rows(a,b).data()};this.api=function(a){return a?new t(za(this[u.iApiIndex])):new t(this)};this.fnAddData=function(a,b){var c=this.api(!0),e=h.isArray(a)&&(h.isArray(a[0])||h.isPlainObject(a[0]))?c.rows.add(a):c.row.add(a);(b=== -k||b)&&c.draw();return e.flatten().toArray()};this.fnAdjustColumnSizing=function(a){var b=this.api(!0).columns.adjust(),c=b.settings()[0],e=c.oScroll;a===k||a?b.draw(!1):(""!==e.sX||""!==e.sY)&&Y(c)};this.fnClearTable=function(a){var b=this.api(!0).clear();(a===k||a)&&b.draw()};this.fnClose=function(a){this.api(!0).row(a).child.hide()};this.fnDeleteRow=function(a,b,c){var e=this.api(!0),a=e.rows(a),d=a.settings()[0],h=d.aoData[a[0][0]];a.remove();b&&b.call(this,d,h);(c===k||c)&&e.draw();return h}; -this.fnDestroy=function(a){this.api(!0).destroy(a)};this.fnDraw=function(a){this.api(!0).draw(a)};this.fnFilter=function(a,b,c,e,d,h){d=this.api(!0);null===b||b===k?d.search(a,c,e,h):d.column(b).search(a,c,e,h);d.draw()};this.fnGetData=function(a,b){var c=this.api(!0);if(a!==k){var e=a.nodeName?a.nodeName.toLowerCase():"";return b!==k||"td"==e||"th"==e?c.cell(a,b).data():c.row(a).data()||null}return c.data().toArray()};this.fnGetNodes=function(a){var b=this.api(!0);return a!==k?b.row(a).node():b.rows().nodes().flatten().toArray()}; -this.fnGetPosition=function(a){var b=this.api(!0),c=a.nodeName.toUpperCase();return"TR"==c?b.row(a).index():"TD"==c||"TH"==c?(a=b.cell(a).index(),[a.row,a.columnVisible,a.column]):null};this.fnIsOpen=function(a){return this.api(!0).row(a).child.isShown()};this.fnOpen=function(a,b,c){return this.api(!0).row(a).child(b,c).show().child()[0]};this.fnPageChange=function(a,b){var c=this.api(!0).page(a);(b===k||b)&&c.draw(!1)};this.fnSetColumnVis=function(a,b,c){a=this.api(!0).column(a).visible(b);(c=== -k||c)&&a.columns.adjust().draw()};this.fnSettings=function(){return za(this[u.iApiIndex])};this.fnSort=function(a){this.api(!0).order(a).draw()};this.fnSortListener=function(a,b,c){this.api(!0).order.listener(a,b,c)};this.fnUpdate=function(a,b,c,e,d){var h=this.api(!0);c===k||null===c?h.row(b).data(a):h.cell(b,c).data(a);(d===k||d)&&h.columns.adjust();(e===k||e)&&h.draw();return 0};this.fnVersionCheck=u.fnVersionCheck;var b=this,c=a===k,e=this.length;c&&(a={});this.oApi=this.internal=u.internal;for(var d in m.ext.internal)d&& -(this[d]=Nb(d));this.each(function(){var d={},d=1<e?Lb(d,a,!0):a,g=0,j,i=this.getAttribute("id"),o=!1,l=m.defaults,q=h(this);if("table"!=this.nodeName.toLowerCase())I(null,0,"Non-table node initialisation ("+this.nodeName+")",2);else{eb(l);fb(l.column);H(l,l,!0);H(l.column,l.column,!0);H(l,h.extend(d,q.data()));var n=m.settings,g=0;for(j=n.length;g<j;g++){var r=n[g];if(r.nTable==this||r.nTHead.parentNode==this||r.nTFoot&&r.nTFoot.parentNode==this){g=d.bRetrieve!==k?d.bRetrieve:l.bRetrieve;if(c||g)return r.oInstance; -if(d.bDestroy!==k?d.bDestroy:l.bDestroy){r.oInstance.fnDestroy();break}else{I(r,0,"Cannot reinitialise DataTable",3);return}}if(r.sTableId==this.id){n.splice(g,1);break}}if(null===i||""===i)this.id=i="DataTables_Table_"+m.ext._unique++;var p=h.extend(!0,{},m.models.oSettings,{sDestroyWidth:q[0].style.width,sInstance:i,sTableId:i});p.nTable=this;p.oApi=b.internal;p.oInit=d;n.push(p);p.oInstance=1===b.length?b:q.dataTable();eb(d);d.oLanguage&&P(d.oLanguage);d.aLengthMenu&&!d.iDisplayLength&&(d.iDisplayLength= -h.isArray(d.aLengthMenu[0])?d.aLengthMenu[0][0]:d.aLengthMenu[0]);d=Lb(h.extend(!0,{},l),d);E(p.oFeatures,d,"bPaginate bLengthChange bFilter bSort bSortMulti bInfo bProcessing bAutoWidth bSortClasses bServerSide bDeferRender".split(" "));E(p,d,["asStripeClasses","ajax","fnServerData","fnFormatNumber","sServerMethod","aaSorting","aaSortingFixed","aLengthMenu","sPaginationType","sAjaxSource","sAjaxDataProp","iStateDuration","sDom","bSortCellsTop","iTabIndex","fnStateLoadCallback","fnStateSaveCallback", -"renderer","searchDelay",["iCookieDuration","iStateDuration"],["oSearch","oPreviousSearch"],["aoSearchCols","aoPreSearchCols"],["iDisplayLength","_iDisplayLength"],["bJQueryUI","bJUI"]]);E(p.oScroll,d,[["sScrollX","sX"],["sScrollXInner","sXInner"],["sScrollY","sY"],["bScrollCollapse","bCollapse"]]);E(p.oLanguage,d,"fnInfoCallback");z(p,"aoDrawCallback",d.fnDrawCallback,"user");z(p,"aoServerParams",d.fnServerParams,"user");z(p,"aoStateSaveParams",d.fnStateSaveParams,"user");z(p,"aoStateLoadParams", -d.fnStateLoadParams,"user");z(p,"aoStateLoaded",d.fnStateLoaded,"user");z(p,"aoRowCallback",d.fnRowCallback,"user");z(p,"aoRowCreatedCallback",d.fnCreatedRow,"user");z(p,"aoHeaderCallback",d.fnHeaderCallback,"user");z(p,"aoFooterCallback",d.fnFooterCallback,"user");z(p,"aoInitComplete",d.fnInitComplete,"user");z(p,"aoPreDrawCallback",d.fnPreDrawCallback,"user");i=p.oClasses;d.bJQueryUI?(h.extend(i,m.ext.oJUIClasses,d.oClasses),d.sDom===l.sDom&&"lfrtip"===l.sDom&&(p.sDom='<"H"lfr>t<"F"ip>'),p.renderer)? -h.isPlainObject(p.renderer)&&!p.renderer.header&&(p.renderer.header="jqueryui"):p.renderer="jqueryui":h.extend(i,m.ext.classes,d.oClasses);q.addClass(i.sTable);if(""!==p.oScroll.sX||""!==p.oScroll.sY)p.oScroll.iBarWidth=Hb();!0===p.oScroll.sX&&(p.oScroll.sX="100%");p.iInitDisplayStart===k&&(p.iInitDisplayStart=d.iDisplayStart,p._iDisplayStart=d.iDisplayStart);null!==d.iDeferLoading&&(p.bDeferLoading=!0,g=h.isArray(d.iDeferLoading),p._iRecordsDisplay=g?d.iDeferLoading[0]:d.iDeferLoading,p._iRecordsTotal= -g?d.iDeferLoading[1]:d.iDeferLoading);var t=p.oLanguage;h.extend(!0,t,d.oLanguage);""!==t.sUrl&&(h.ajax({dataType:"json",url:t.sUrl,success:function(a){P(a);H(l.oLanguage,a);h.extend(true,t,a);ga(p)},error:function(){ga(p)}}),o=!0);null===d.asStripeClasses&&(p.asStripeClasses=[i.sStripeOdd,i.sStripeEven]);var g=p.asStripeClasses,s=q.children("tbody").find("tr").eq(0);-1!==h.inArray(!0,h.map(g,function(a){return s.hasClass(a)}))&&(h("tbody tr",this).removeClass(g.join(" ")),p.asDestroyStripes=g.slice()); -n=[];g=this.getElementsByTagName("thead");0!==g.length&&(da(p.aoHeader,g[0]),n=qa(p));if(null===d.aoColumns){r=[];g=0;for(j=n.length;g<j;g++)r.push(null)}else r=d.aoColumns;g=0;for(j=r.length;g<j;g++)Fa(p,n?n[g]:null);ib(p,d.aoColumnDefs,r,function(a,b){ka(p,a,b)});if(s.length){var u=function(a,b){return a.getAttribute("data-"+b)!==null?b:null};h.each(na(p,s[0]).cells,function(a,b){var c=p.aoColumns[a];if(c.mData===a){var d=u(b,"sort")||u(b,"order"),e=u(b,"filter")||u(b,"search");if(d!==null||e!== -null){c.mData={_:a+".display",sort:d!==null?a+".@data-"+d:k,type:d!==null?a+".@data-"+d:k,filter:e!==null?a+".@data-"+e:k};ka(p,a)}}})}var v=p.oFeatures;d.bStateSave&&(v.bStateSave=!0,Kb(p,d),z(p,"aoDrawCallback",ya,"state_save"));if(d.aaSorting===k){n=p.aaSorting;g=0;for(j=n.length;g<j;g++)n[g][1]=p.aoColumns[g].asSorting[0]}xa(p);v.bSort&&z(p,"aoDrawCallback",function(){if(p.bSorted){var a=U(p),b={};h.each(a,function(a,c){b[c.src]=c.dir});w(p,null,"order",[p,a,b]);Jb(p)}});z(p,"aoDrawCallback", -function(){(p.bSorted||B(p)==="ssp"||v.bDeferRender)&&xa(p)},"sc");gb(p);g=q.children("caption").each(function(){this._captionSide=q.css("caption-side")});j=q.children("thead");0===j.length&&(j=h("<thead/>").appendTo(this));p.nTHead=j[0];j=q.children("tbody");0===j.length&&(j=h("<tbody/>").appendTo(this));p.nTBody=j[0];j=q.children("tfoot");if(0===j.length&&0<g.length&&(""!==p.oScroll.sX||""!==p.oScroll.sY))j=h("<tfoot/>").appendTo(this);0===j.length||0===j.children().length?q.addClass(i.sNoFooter): -0<j.length&&(p.nTFoot=j[0],da(p.aoFooter,p.nTFoot));if(d.aaData)for(g=0;g<d.aaData.length;g++)K(p,d.aaData[g]);else(p.bDeferLoading||"dom"==B(p))&&ma(p,h(p.nTBody).children("tr"));p.aiDisplay=p.aiDisplayMaster.slice();p.bInitialised=!0;!1===o&&ga(p)}});b=null;return this};var Tb=[],y=Array.prototype,cc=function(a){var b,c,e=m.settings,d=h.map(e,function(a){return a.nTable});if(a){if(a.nTable&&a.oApi)return[a];if(a.nodeName&&"table"===a.nodeName.toLowerCase())return b=h.inArray(a,d),-1!==b?[e[b]]: -null;if(a&&"function"===typeof a.settings)return a.settings().toArray();"string"===typeof a?c=h(a):a instanceof h&&(c=a)}else return[];if(c)return c.map(function(){b=h.inArray(this,d);return-1!==b?e[b]:null}).toArray()};t=function(a,b){if(!(this instanceof t))return new t(a,b);var c=[],e=function(a){(a=cc(a))&&c.push.apply(c,a)};if(h.isArray(a))for(var d=0,f=a.length;d<f;d++)e(a[d]);else e(a);this.context=Na(c);b&&this.push.apply(this,b.toArray?b.toArray():b);this.selector={rows:null,cols:null,opts:null}; -t.extend(this,this,Tb)};m.Api=t;t.prototype={any:function(){return 0!==this.flatten().length},concat:y.concat,context:[],each:function(a){for(var b=0,c=this.length;b<c;b++)a.call(this,this[b],b,this);return this},eq:function(a){var b=this.context;return b.length>a?new t(b[a],this[a]):null},filter:function(a){var b=[];if(y.filter)b=y.filter.call(this,a,this);else for(var c=0,e=this.length;c<e;c++)a.call(this,this[c],c,this)&&b.push(this[c]);return new t(this.context,b)},flatten:function(){var a=[]; -return new t(this.context,a.concat.apply(a,this.toArray()))},join:y.join,indexOf:y.indexOf||function(a,b){for(var c=b||0,e=this.length;c<e;c++)if(this[c]===a)return c;return-1},iterator:function(a,b,c,e){var d=[],f,g,h,i,o,l=this.context,q,n,m=this.selector;"string"===typeof a&&(e=c,c=b,b=a,a=!1);g=0;for(h=l.length;g<h;g++){var p=new t(l[g]);if("table"===b)f=c.call(p,l[g],g),f!==k&&d.push(f);else if("columns"===b||"rows"===b)f=c.call(p,l[g],this[g],g),f!==k&&d.push(f);else if("column"===b||"column-rows"=== -b||"row"===b||"cell"===b){n=this[g];"column-rows"===b&&(q=Ca(l[g],m.opts));i=0;for(o=n.length;i<o;i++)f=n[i],f="cell"===b?c.call(p,l[g],f.row,f.column,g,i):c.call(p,l[g],f,g,i,q),f!==k&&d.push(f)}}return d.length||e?(a=new t(l,a?d.concat.apply([],d):d),b=a.selector,b.rows=m.rows,b.cols=m.cols,b.opts=m.opts,a):this},lastIndexOf:y.lastIndexOf||function(a,b){return this.indexOf.apply(this.toArray.reverse(),arguments)},length:0,map:function(a){var b=[];if(y.map)b=y.map.call(this,a,this);else for(var c= -0,e=this.length;c<e;c++)b.push(a.call(this,this[c],c));return new t(this.context,b)},pluck:function(a){return this.map(function(b){return b[a]})},pop:y.pop,push:y.push,reduce:y.reduce||function(a,b){return hb(this,a,b,0,this.length,1)},reduceRight:y.reduceRight||function(a,b){return hb(this,a,b,this.length-1,-1,-1)},reverse:y.reverse,selector:null,shift:y.shift,sort:y.sort,splice:y.splice,toArray:function(){return y.slice.call(this)},to$:function(){return h(this)},toJQuery:function(){return h(this)}, -unique:function(){return new t(this.context,Na(this))},unshift:y.unshift};t.extend=function(a,b,c){if(c.length&&b&&(b instanceof t||b.__dt_wrapper)){var e,d,f,g=function(a,b,c){return function(){var d=b.apply(a,arguments);t.extend(d,d,c.methodExt);return d}};e=0;for(d=c.length;e<d;e++)f=c[e],b[f.name]="function"===typeof f.val?g(a,f.val,f):h.isPlainObject(f.val)?{}:f.val,b[f.name].__dt_wrapper=!0,t.extend(a,b[f.name],f.propExt)}};t.register=r=function(a,b){if(h.isArray(a))for(var c=0,e=a.length;c< -e;c++)t.register(a[c],b);else for(var d=a.split("."),f=Tb,g,j,c=0,e=d.length;c<e;c++){g=(j=-1!==d[c].indexOf("()"))?d[c].replace("()",""):d[c];var i;a:{i=0;for(var o=f.length;i<o;i++)if(f[i].name===g){i=f[i];break a}i=null}i||(i={name:g,val:{},methodExt:[],propExt:[]},f.push(i));c===e-1?i.val=b:f=j?i.methodExt:i.propExt}};t.registerPlural=v=function(a,b,c){t.register(a,c);t.register(b,function(){var a=c.apply(this,arguments);return a===this?this:a instanceof t?a.length?h.isArray(a[0])?new t(a.context, -a[0]):a[0]:k:a})};r("tables()",function(a){var b;if(a){b=t;var c=this.context;if("number"===typeof a)a=[c[a]];else var e=h.map(c,function(a){return a.nTable}),a=h(e).filter(a).map(function(){var a=h.inArray(this,e);return c[a]}).toArray();b=new b(a)}else b=this;return b});r("table()",function(a){var a=this.tables(a),b=a.context;return b.length?new t(b[0]):a});v("tables().nodes()","table().node()",function(){return this.iterator("table",function(a){return a.nTable},1)});v("tables().body()","table().body()", -function(){return this.iterator("table",function(a){return a.nTBody},1)});v("tables().header()","table().header()",function(){return this.iterator("table",function(a){return a.nTHead},1)});v("tables().footer()","table().footer()",function(){return this.iterator("table",function(a){return a.nTFoot},1)});v("tables().containers()","table().container()",function(){return this.iterator("table",function(a){return a.nTableWrapper},1)});r("draw()",function(a){return this.iterator("table",function(b){N(b, -!1===a)})});r("page()",function(a){return a===k?this.page.info().page:this.iterator("table",function(b){Ta(b,a)})});r("page.info()",function(){if(0===this.context.length)return k;var a=this.context[0],b=a._iDisplayStart,c=a._iDisplayLength,e=a.fnRecordsDisplay(),d=-1===c;return{page:d?0:Math.floor(b/c),pages:d?1:Math.ceil(e/c),start:b,end:a.fnDisplayEnd(),length:c,recordsTotal:a.fnRecordsTotal(),recordsDisplay:e}});r("page.len()",function(a){return a===k?0!==this.context.length?this.context[0]._iDisplayLength: -k:this.iterator("table",function(b){Ra(b,a)})});var Ub=function(a,b,c){if(c){var e=new t(a);e.one("draw",function(){c(e.ajax.json())})}"ssp"==B(a)?N(a,b):(C(a,!0),ra(a,[],function(c){oa(a);for(var c=sa(a,c),e=0,g=c.length;e<g;e++)K(a,c[e]);N(a,b);C(a,!1)}))};r("ajax.json()",function(){var a=this.context;if(0<a.length)return a[0].json});r("ajax.params()",function(){var a=this.context;if(0<a.length)return a[0].oAjaxData});r("ajax.reload()",function(a,b){return this.iterator("table",function(c){Ub(c, -!1===b,a)})});r("ajax.url()",function(a){var b=this.context;if(a===k){if(0===b.length)return k;b=b[0];return b.ajax?h.isPlainObject(b.ajax)?b.ajax.url:b.ajax:b.sAjaxSource}return this.iterator("table",function(b){h.isPlainObject(b.ajax)?b.ajax.url=a:b.ajax=a})});r("ajax.url().load()",function(a,b){return this.iterator("table",function(c){Ub(c,!1===b,a)})});var $a=function(a,b,c,e,d){var f=[],g,j,i,o,l,q;i=typeof b;if(!b||"string"===i||"function"===i||b.length===k)b=[b];i=0;for(o=b.length;i<o;i++){j= -b[i]&&b[i].split?b[i].split(","):[b[i]];l=0;for(q=j.length;l<q;l++)(g=c("string"===typeof j[l]?h.trim(j[l]):j[l]))&&g.length&&f.push.apply(f,g)}a=u.selector[a];if(a.length){i=0;for(o=a.length;i<o;i++)f=a[i](e,d,f)}return f},ab=function(a){a||(a={});a.filter&&a.search===k&&(a.search=a.filter);return h.extend({search:"none",order:"current",page:"all"},a)},bb=function(a){for(var b=0,c=a.length;b<c;b++)if(0<a[b].length)return a[0]=a[b],a[0].length=1,a.length=1,a.context=[a.context[b]],a;a.length=0;return a}, -Ca=function(a,b){var c,e,d,f=[],g=a.aiDisplay;c=a.aiDisplayMaster;var j=b.search;e=b.order;d=b.page;if("ssp"==B(a))return"removed"===j?[]:V(0,c.length);if("current"==d){c=a._iDisplayStart;for(e=a.fnDisplayEnd();c<e;c++)f.push(g[c])}else if("current"==e||"applied"==e)f="none"==j?c.slice():"applied"==j?g.slice():h.map(c,function(a){return-1===h.inArray(a,g)?a:null});else if("index"==e||"original"==e){c=0;for(e=a.aoData.length;c<e;c++)"none"==j?f.push(c):(d=h.inArray(c,g),(-1===d&&"removed"==j||0<=d&& -"applied"==j)&&f.push(c))}return f};r("rows()",function(a,b){a===k?a="":h.isPlainObject(a)&&(b=a,a="");var b=ab(b),c=this.iterator("table",function(c){var d=b;return $a("row",a,function(a){var b=Pb(a);if(b!==null&&!d)return[b];var j=Ca(c,d);if(b!==null&&h.inArray(b,j)!==-1)return[b];if(!a)return j;if(typeof a==="function")return h.map(j,function(b){var d=c.aoData[b];return a(b,d._aData,d.nTr)?b:null});b=Sb(ia(c.aoData,j,"nTr"));return a.nodeName&&h.inArray(a,b)!==-1?[a._DT_RowIndex]:h(b).filter(a).map(function(){return this._DT_RowIndex}).toArray()}, -c,d)},1);c.selector.rows=a;c.selector.opts=b;return c});r("rows().nodes()",function(){return this.iterator("row",function(a,b){return a.aoData[b].nTr||k},1)});r("rows().data()",function(){return this.iterator(!0,"rows",function(a,b){return ia(a.aoData,b,"_aData")},1)});v("rows().cache()","row().cache()",function(a){return this.iterator("row",function(b,c){var e=b.aoData[c];return"search"===a?e._aFilterData:e._aSortData},1)});v("rows().invalidate()","row().invalidate()",function(a){return this.iterator("row", -function(b,c){ca(b,c,a)})});v("rows().indexes()","row().index()",function(){return this.iterator("row",function(a,b){return b},1)});v("rows().remove()","row().remove()",function(){var a=this;return this.iterator("row",function(b,c,e){var d=b.aoData;d.splice(c,1);for(var f=0,g=d.length;f<g;f++)null!==d[f].nTr&&(d[f].nTr._DT_RowIndex=f);h.inArray(c,b.aiDisplay);pa(b.aiDisplayMaster,c);pa(b.aiDisplay,c);pa(a[e],c,!1);Sa(b)})});r("rows.add()",function(a){var b=this.iterator("table",function(b){var c, -f,g,h=[];f=0;for(g=a.length;f<g;f++)c=a[f],c.nodeName&&"TR"===c.nodeName.toUpperCase()?h.push(ma(b,c)[0]):h.push(K(b,c));return h},1),c=this.rows(-1);c.pop();c.push.apply(c,b.toArray());return c});r("row()",function(a,b){return bb(this.rows(a,b))});r("row().data()",function(a){var b=this.context;if(a===k)return b.length&&this.length?b[0].aoData[this[0]]._aData:k;b[0].aoData[this[0]]._aData=a;ca(b[0],this[0],"data");return this});r("row().node()",function(){var a=this.context;return a.length&&this.length? -a[0].aoData[this[0]].nTr||null:null});r("row.add()",function(a){a instanceof h&&a.length&&(a=a[0]);var b=this.iterator("table",function(b){return a.nodeName&&"TR"===a.nodeName.toUpperCase()?ma(b,a)[0]:K(b,a)});return this.row(b[0])});var cb=function(a,b){var c=a.context;c.length&&(c=c[0].aoData[b!==k?b:a[0]],c._details&&(c._details.remove(),c._detailsShow=k,c._details=k))},Vb=function(a,b){var c=a.context;if(c.length&&a.length){var e=c[0].aoData[a[0]];if(e._details){(e._detailsShow=b)?e._details.insertAfter(e.nTr): -e._details.detach();var d=c[0],f=new t(d),g=d.aoData;f.off("draw.dt.DT_details column-visibility.dt.DT_details destroy.dt.DT_details");0<D(g,"_details").length&&(f.on("draw.dt.DT_details",function(a,b){d===b&&f.rows({page:"current"}).eq(0).each(function(a){a=g[a];a._detailsShow&&a._details.insertAfter(a.nTr)})}),f.on("column-visibility.dt.DT_details",function(a,b){if(d===b)for(var c,e=aa(b),f=0,h=g.length;f<h;f++)c=g[f],c._details&&c._details.children("td[colspan]").attr("colspan",e)}),f.on("destroy.dt.DT_details", -function(a,b){if(d===b)for(var c=0,e=g.length;c<e;c++)g[c]._details&&cb(f,c)}))}}};r("row().child()",function(a,b){var c=this.context;if(a===k)return c.length&&this.length?c[0].aoData[this[0]]._details:k;if(!0===a)this.child.show();else if(!1===a)cb(this);else if(c.length&&this.length){var e=c[0],c=c[0].aoData[this[0]],d=[],f=function(a,b){if(h.isArray(a)||a instanceof h)for(var c=0,k=a.length;c<k;c++)f(a[c],b);else a.nodeName&&"tr"===a.nodeName.toLowerCase()?d.push(a):(c=h("<tr><td/></tr>").addClass(b), -h("td",c).addClass(b).html(a)[0].colSpan=aa(e),d.push(c[0]))};f(a,b);c._details&&c._details.remove();c._details=h(d);c._detailsShow&&c._details.insertAfter(c.nTr)}return this});r(["row().child.show()","row().child().show()"],function(){Vb(this,!0);return this});r(["row().child.hide()","row().child().hide()"],function(){Vb(this,!1);return this});r(["row().child.remove()","row().child().remove()"],function(){cb(this);return this});r("row().child.isShown()",function(){var a=this.context;return a.length&& -this.length?a[0].aoData[this[0]]._detailsShow||!1:!1});var dc=/^(.+):(name|visIdx|visible)$/,Wb=function(a,b,c,e,d){for(var c=[],e=0,f=d.length;e<f;e++)c.push(x(a,d[e],b));return c};r("columns()",function(a,b){a===k?a="":h.isPlainObject(a)&&(b=a,a="");var b=ab(b),c=this.iterator("table",function(c){var d=a,f=b,g=c.aoColumns,j=D(g,"sName"),i=D(g,"nTh");return $a("column",d,function(a){var b=Pb(a);if(a==="")return V(g.length);if(b!==null)return[b>=0?b:g.length+b];if(typeof a==="function"){var d=Ca(c, -f);return h.map(g,function(b,f){return a(f,Wb(c,f,0,0,d),i[f])?f:null})}var k=typeof a==="string"?a.match(dc):"";if(k)switch(k[2]){case "visIdx":case "visible":b=parseInt(k[1],10);if(b<0){var m=h.map(g,function(a,b){return a.bVisible?b:null});return[m[m.length+b]]}return[la(c,b)];case "name":return h.map(j,function(a,b){return a===k[1]?b:null})}else return h(i).filter(a).map(function(){return h.inArray(this,i)}).toArray()},c,f)},1);c.selector.cols=a;c.selector.opts=b;return c});v("columns().header()", -"column().header()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].nTh},1)});v("columns().footer()","column().footer()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].nTf},1)});v("columns().data()","column().data()",function(){return this.iterator("column-rows",Wb,1)});v("columns().dataSrc()","column().dataSrc()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].mData},1)});v("columns().cache()","column().cache()", -function(a){return this.iterator("column-rows",function(b,c,e,d,f){return ia(b.aoData,f,"search"===a?"_aFilterData":"_aSortData",c)},1)});v("columns().nodes()","column().nodes()",function(){return this.iterator("column-rows",function(a,b,c,e,d){return ia(a.aoData,d,"anCells",b)},1)});v("columns().visible()","column().visible()",function(a,b){return this.iterator("column",function(c,e){if(a===k)return c.aoColumns[e].bVisible;var d=c.aoColumns,f=d[e],g=c.aoData,j,i,m;if(a!==k&&f.bVisible!==a){if(a){var l= -h.inArray(!0,D(d,"bVisible"),e+1);j=0;for(i=g.length;j<i;j++)m=g[j].nTr,d=g[j].anCells,m&&m.insertBefore(d[e],d[l]||null)}else h(D(c.aoData,"anCells",e)).detach();f.bVisible=a;ea(c,c.aoHeader);ea(c,c.aoFooter);if(b===k||b)X(c),(c.oScroll.sX||c.oScroll.sY)&&Y(c);w(c,null,"column-visibility",[c,e,a]);ya(c)}})});v("columns().indexes()","column().index()",function(a){return this.iterator("column",function(b,c){return"visible"===a?$(b,c):c},1)});r("columns.adjust()",function(){return this.iterator("table", -function(a){X(a)},1)});r("column.index()",function(a,b){if(0!==this.context.length){var c=this.context[0];if("fromVisible"===a||"toData"===a)return la(c,b);if("fromData"===a||"toVisible"===a)return $(c,b)}});r("column()",function(a,b){return bb(this.columns(a,b))});r("cells()",function(a,b,c){h.isPlainObject(a)&&(a.row===k?(c=a,a=null):(c=b,b=null));h.isPlainObject(b)&&(c=b,b=null);if(null===b||b===k)return this.iterator("table",function(b){var d=a,e=ab(c),f=b.aoData,g=Ca(b,e),i=Sb(ia(f,g,"anCells")), -j=h([].concat.apply([],i)),l,m=b.aoColumns.length,o,r,t,s,u,v;return $a("cell",d,function(a){var c=typeof a==="function";if(a===null||a===k||c){o=[];r=0;for(t=g.length;r<t;r++){l=g[r];for(s=0;s<m;s++){u={row:l,column:s};if(c){v=b.aoData[l];a(u,x(b,l,s),v.anCells?v.anCells[s]:null)&&o.push(u)}else o.push(u)}}return o}return h.isPlainObject(a)?[a]:j.filter(a).map(function(a,b){l=b.parentNode._DT_RowIndex;return{row:l,column:h.inArray(b,f[l].anCells)}}).toArray()},b,e)});var e=this.columns(b,c),d=this.rows(a, -c),f,g,j,i,m,l=this.iterator("table",function(a,b){f=[];g=0;for(j=d[b].length;g<j;g++){i=0;for(m=e[b].length;i<m;i++)f.push({row:d[b][g],column:e[b][i]})}return f},1);h.extend(l.selector,{cols:b,rows:a,opts:c});return l});v("cells().nodes()","cell().node()",function(){return this.iterator("cell",function(a,b,c){return(a=a.aoData[b].anCells)?a[c]:k},1)});r("cells().data()",function(){return this.iterator("cell",function(a,b,c){return x(a,b,c)},1)});v("cells().cache()","cell().cache()",function(a){a= -"search"===a?"_aFilterData":"_aSortData";return this.iterator("cell",function(b,c,e){return b.aoData[c][a][e]},1)});v("cells().render()","cell().render()",function(a){return this.iterator("cell",function(b,c,e){return x(b,c,e,a)},1)});v("cells().indexes()","cell().index()",function(){return this.iterator("cell",function(a,b,c){return{row:b,column:c,columnVisible:$(a,c)}},1)});v("cells().invalidate()","cell().invalidate()",function(a){return this.iterator("cell",function(b,c,e){ca(b,c,a,e)})});r("cell()", -function(a,b,c){return bb(this.cells(a,b,c))});r("cell().data()",function(a){var b=this.context,c=this[0];if(a===k)return b.length&&c.length?x(b[0],c[0].row,c[0].column):k;Ia(b[0],c[0].row,c[0].column,a);ca(b[0],c[0].row,"data",c[0].column);return this});r("order()",function(a,b){var c=this.context;if(a===k)return 0!==c.length?c[0].aaSorting:k;"number"===typeof a?a=[[a,b]]:h.isArray(a[0])||(a=Array.prototype.slice.call(arguments));return this.iterator("table",function(b){b.aaSorting=a.slice()})}); -r("order.listener()",function(a,b,c){return this.iterator("table",function(e){Oa(e,a,b,c)})});r(["columns().order()","column().order()"],function(a){var b=this;return this.iterator("table",function(c,e){var d=[];h.each(b[e],function(b,c){d.push([c,a])});c.aaSorting=d})});r("search()",function(a,b,c,e){var d=this.context;return a===k?0!==d.length?d[0].oPreviousSearch.sSearch:k:this.iterator("table",function(d){d.oFeatures.bFilter&&fa(d,h.extend({},d.oPreviousSearch,{sSearch:a+"",bRegex:null===b?!1: -b,bSmart:null===c?!0:c,bCaseInsensitive:null===e?!0:e}),1)})});v("columns().search()","column().search()",function(a,b,c,e){return this.iterator("column",function(d,f){var g=d.aoPreSearchCols;if(a===k)return g[f].sSearch;d.oFeatures.bFilter&&(h.extend(g[f],{sSearch:a+"",bRegex:null===b?!1:b,bSmart:null===c?!0:c,bCaseInsensitive:null===e?!0:e}),fa(d,d.oPreviousSearch,1))})});r("state()",function(){return this.context.length?this.context[0].oSavedState:null});r("state.clear()",function(){return this.iterator("table", -function(a){a.fnStateSaveCallback.call(a.oInstance,a,{})})});r("state.loaded()",function(){return this.context.length?this.context[0].oLoadedState:null});r("state.save()",function(){return this.iterator("table",function(a){ya(a)})});m.versionCheck=m.fnVersionCheck=function(a){for(var b=m.version.split("."),a=a.split("."),c,e,d=0,f=a.length;d<f;d++)if(c=parseInt(b[d],10)||0,e=parseInt(a[d],10)||0,c!==e)return c>e;return!0};m.isDataTable=m.fnIsDataTable=function(a){var b=h(a).get(0),c=!1;h.each(m.settings, -function(a,d){var f=d.nScrollHead?h("table",d.nScrollHead)[0]:null,g=d.nScrollFoot?h("table",d.nScrollFoot)[0]:null;if(d.nTable===b||f===b||g===b)c=!0});return c};m.tables=m.fnTables=function(a){return h.map(m.settings,function(b){if(!a||a&&h(b.nTable).is(":visible"))return b.nTable})};m.util={throttle:ua,escapeRegex:va};m.camelToHungarian=H;r("$()",function(a,b){var c=this.rows(b).nodes(),c=h(c);return h([].concat(c.filter(a).toArray(),c.find(a).toArray()))});h.each(["on","one","off"],function(a, -b){r(b+"()",function(){var a=Array.prototype.slice.call(arguments);a[0].match(/\.dt\b/)||(a[0]+=".dt");var e=h(this.tables().nodes());e[b].apply(e,a);return this})});r("clear()",function(){return this.iterator("table",function(a){oa(a)})});r("settings()",function(){return new t(this.context,this.context)});r("init()",function(){var a=this.context;return a.length?a[0].oInit:null});r("data()",function(){return this.iterator("table",function(a){return D(a.aoData,"_aData")}).flatten()});r("destroy()", -function(a){a=a||!1;return this.iterator("table",function(b){var c=b.nTableWrapper.parentNode,e=b.oClasses,d=b.nTable,f=b.nTBody,g=b.nTHead,j=b.nTFoot,i=h(d),f=h(f),k=h(b.nTableWrapper),l=h.map(b.aoData,function(a){return a.nTr}),q;b.bDestroying=!0;w(b,"aoDestroyCallback","destroy",[b]);a||(new t(b)).columns().visible(!0);k.unbind(".DT").find(":not(tbody *)").unbind(".DT");h(Ea).unbind(".DT-"+b.sInstance);d!=g.parentNode&&(i.children("thead").detach(),i.append(g));j&&d!=j.parentNode&&(i.children("tfoot").detach(), -i.append(j));i.detach();k.detach();b.aaSorting=[];b.aaSortingFixed=[];xa(b);h(l).removeClass(b.asStripeClasses.join(" "));h("th, td",g).removeClass(e.sSortable+" "+e.sSortableAsc+" "+e.sSortableDesc+" "+e.sSortableNone);b.bJUI&&(h("th span."+e.sSortIcon+", td span."+e.sSortIcon,g).detach(),h("th, td",g).each(function(){var a=h("div."+e.sSortJUIWrapper,this);h(this).append(a.contents());a.detach()}));!a&&c&&c.insertBefore(d,b.nTableReinsertBefore);f.children().detach();f.append(l);i.css("width",b.sDestroyWidth).removeClass(e.sTable); -(q=b.asDestroyStripes.length)&&f.children().each(function(a){h(this).addClass(b.asDestroyStripes[a%q])});c=h.inArray(b,m.settings);-1!==c&&m.settings.splice(c,1)})});h.each(["column","row","cell"],function(a,b){r(b+"s().every()",function(a){return this.iterator(b,function(e,d,f){a.call((new t(e))[b](d,f))})})});r("i18n()",function(a,b,c){var e=this.context[0],a=R(a)(e.oLanguage);a===k&&(a=b);c!==k&&h.isPlainObject(a)&&(a=a[c]!==k?a[c]:a._);return a.replace("%d",c)});m.version="1.10.7";m.settings= -[];m.models={};m.models.oSearch={bCaseInsensitive:!0,sSearch:"",bRegex:!1,bSmart:!0};m.models.oRow={nTr:null,anCells:null,_aData:[],_aSortData:null,_aFilterData:null,_sFilterRow:null,_sRowStripe:"",src:null};m.models.oColumn={idx:null,aDataSort:null,asSorting:null,bSearchable:null,bSortable:null,bVisible:null,_sManualType:null,_bAttrSrc:!1,fnCreatedCell:null,fnGetData:null,fnSetData:null,mData:null,mRender:null,nTh:null,nTf:null,sClass:null,sContentPadding:null,sDefaultContent:null,sName:null,sSortDataType:"std", -sSortingClass:null,sSortingClassJUI:null,sTitle:null,sType:null,sWidth:null,sWidthOrig:null};m.defaults={aaData:null,aaSorting:[[0,"asc"]],aaSortingFixed:[],ajax:null,aLengthMenu:[10,25,50,100],aoColumns:null,aoColumnDefs:null,aoSearchCols:[],asStripeClasses:null,bAutoWidth:!0,bDeferRender:!1,bDestroy:!1,bFilter:!0,bInfo:!0,bJQueryUI:!1,bLengthChange:!0,bPaginate:!0,bProcessing:!1,bRetrieve:!1,bScrollCollapse:!1,bServerSide:!1,bSort:!0,bSortMulti:!0,bSortCellsTop:!1,bSortClasses:!0,bStateSave:!1, -fnCreatedRow:null,fnDrawCallback:null,fnFooterCallback:null,fnFormatNumber:function(a){return a.toString().replace(/\B(?=(\d{3})+(?!\d))/g,this.oLanguage.sThousands)},fnHeaderCallback:null,fnInfoCallback:null,fnInitComplete:null,fnPreDrawCallback:null,fnRowCallback:null,fnServerData:null,fnServerParams:null,fnStateLoadCallback:function(a){try{return JSON.parse((-1===a.iStateDuration?sessionStorage:localStorage).getItem("DataTables_"+a.sInstance+"_"+location.pathname))}catch(b){}},fnStateLoadParams:null, -fnStateLoaded:null,fnStateSaveCallback:function(a,b){try{(-1===a.iStateDuration?sessionStorage:localStorage).setItem("DataTables_"+a.sInstance+"_"+location.pathname,JSON.stringify(b))}catch(c){}},fnStateSaveParams:null,iStateDuration:7200,iDeferLoading:null,iDisplayLength:10,iDisplayStart:0,iTabIndex:0,oClasses:{},oLanguage:{oAria:{sSortAscending:": activate to sort column ascending",sSortDescending:": activate to sort column descending"},oPaginate:{sFirst:"First",sLast:"Last",sNext:"Next",sPrevious:"Previous"}, -sEmptyTable:"No data available in table",sInfo:"Showing _START_ to _END_ of _TOTAL_ entries",sInfoEmpty:"Showing 0 to 0 of 0 entries",sInfoFiltered:"(filtered from _MAX_ total entries)",sInfoPostFix:"",sDecimal:"",sThousands:",",sLengthMenu:"Show _MENU_ entries",sLoadingRecords:"Loading...",sProcessing:"Processing...",sSearch:"Search:",sSearchPlaceholder:"",sUrl:"",sZeroRecords:"No matching records found"},oSearch:h.extend({},m.models.oSearch),sAjaxDataProp:"data",sAjaxSource:null,sDom:"lfrtip",searchDelay:null, -sPaginationType:"simple_numbers",sScrollX:"",sScrollXInner:"",sScrollY:"",sServerMethod:"GET",renderer:null};W(m.defaults);m.defaults.column={aDataSort:null,iDataSort:-1,asSorting:["asc","desc"],bSearchable:!0,bSortable:!0,bVisible:!0,fnCreatedCell:null,mData:null,mRender:null,sCellType:"td",sClass:"",sContentPadding:"",sDefaultContent:null,sName:"",sSortDataType:"std",sTitle:null,sType:null,sWidth:null};W(m.defaults.column);m.models.oSettings={oFeatures:{bAutoWidth:null,bDeferRender:null,bFilter:null, -bInfo:null,bLengthChange:null,bPaginate:null,bProcessing:null,bServerSide:null,bSort:null,bSortMulti:null,bSortClasses:null,bStateSave:null},oScroll:{bCollapse:null,iBarWidth:0,sX:null,sXInner:null,sY:null},oLanguage:{fnInfoCallback:null},oBrowser:{bScrollOversize:!1,bScrollbarLeft:!1},ajax:null,aanFeatures:[],aoData:[],aiDisplay:[],aiDisplayMaster:[],aoColumns:[],aoHeader:[],aoFooter:[],oPreviousSearch:{},aoPreSearchCols:[],aaSorting:null,aaSortingFixed:[],asStripeClasses:null,asDestroyStripes:[], -sDestroyWidth:0,aoRowCallback:[],aoHeaderCallback:[],aoFooterCallback:[],aoDrawCallback:[],aoRowCreatedCallback:[],aoPreDrawCallback:[],aoInitComplete:[],aoStateSaveParams:[],aoStateLoadParams:[],aoStateLoaded:[],sTableId:"",nTable:null,nTHead:null,nTFoot:null,nTBody:null,nTableWrapper:null,bDeferLoading:!1,bInitialised:!1,aoOpenRows:[],sDom:null,searchDelay:null,sPaginationType:"two_button",iStateDuration:0,aoStateSave:[],aoStateLoad:[],oSavedState:null,oLoadedState:null,sAjaxSource:null,sAjaxDataProp:null, -bAjaxDataGet:!0,jqXHR:null,json:k,oAjaxData:k,fnServerData:null,aoServerParams:[],sServerMethod:null,fnFormatNumber:null,aLengthMenu:null,iDraw:0,bDrawing:!1,iDrawError:-1,_iDisplayLength:10,_iDisplayStart:0,_iRecordsTotal:0,_iRecordsDisplay:0,bJUI:null,oClasses:{},bFiltered:!1,bSorted:!1,bSortCellsTop:null,oInit:null,aoDestroyCallback:[],fnRecordsTotal:function(){return"ssp"==B(this)?1*this._iRecordsTotal:this.aiDisplayMaster.length},fnRecordsDisplay:function(){return"ssp"==B(this)?1*this._iRecordsDisplay: -this.aiDisplay.length},fnDisplayEnd:function(){var a=this._iDisplayLength,b=this._iDisplayStart,c=b+a,e=this.aiDisplay.length,d=this.oFeatures,f=d.bPaginate;return d.bServerSide?!1===f||-1===a?b+e:Math.min(b+a,this._iRecordsDisplay):!f||c>e||-1===a?e:c},oInstance:null,sInstance:null,iTabIndex:0,nScrollHead:null,nScrollFoot:null,aLastSort:[],oPlugins:{}};m.ext=u={buttons:{},classes:{},errMode:"alert",feature:[],search:[],selector:{cell:[],column:[],row:[]},internal:{},legacy:{ajax:null},pager:{},renderer:{pageButton:{}, -header:{}},order:{},type:{detect:[],search:{},order:{}},_unique:0,fnVersionCheck:m.fnVersionCheck,iApiIndex:0,oJUIClasses:{},sVersion:m.version};h.extend(u,{afnFiltering:u.search,aTypes:u.type.detect,ofnSearch:u.type.search,oSort:u.type.order,afnSortData:u.order,aoFeatures:u.feature,oApi:u.internal,oStdClasses:u.classes,oPagination:u.pager});h.extend(m.ext.classes,{sTable:"dataTable",sNoFooter:"no-footer",sPageButton:"paginate_button",sPageButtonActive:"current",sPageButtonDisabled:"disabled",sStripeOdd:"odd", +/*! + DataTables 1.10.12 + ©2008-2015 SpryMedia Ltd - datatables.net/license +*/ +(function(h){"function"===typeof define&&define.amd?define(["jquery"],function(D){return h(D,window,document)}):"object"===typeof exports?module.exports=function(D,I){D||(D=window);I||(I="undefined"!==typeof window?require("jquery"):require("jquery")(D));return h(I,D,D.document)}:h(jQuery,window,document)})(function(h,D,I,k){function X(a){var b,c,d={};h.each(a,function(e){if((b=e.match(/^([^A-Z]+?)([A-Z])/))&&-1!=="a aa ai ao as b fn i m o s ".indexOf(b[1]+" "))c=e.replace(b[0],b[2].toLowerCase()), +d[c]=e,"o"===b[1]&&X(a[e])});a._hungarianMap=d}function K(a,b,c){a._hungarianMap||X(a);var d;h.each(b,function(e){d=a._hungarianMap[e];if(d!==k&&(c||b[d]===k))"o"===d.charAt(0)?(b[d]||(b[d]={}),h.extend(!0,b[d],b[e]),K(a[d],b[d],c)):b[d]=b[e]})}function Da(a){var b=m.defaults.oLanguage,c=a.sZeroRecords;!a.sEmptyTable&&(c&&"No data available in table"===b.sEmptyTable)&&E(a,a,"sZeroRecords","sEmptyTable");!a.sLoadingRecords&&(c&&"Loading..."===b.sLoadingRecords)&&E(a,a,"sZeroRecords","sLoadingRecords"); +a.sInfoThousands&&(a.sThousands=a.sInfoThousands);(a=a.sDecimal)&&db(a)}function eb(a){A(a,"ordering","bSort");A(a,"orderMulti","bSortMulti");A(a,"orderClasses","bSortClasses");A(a,"orderCellsTop","bSortCellsTop");A(a,"order","aaSorting");A(a,"orderFixed","aaSortingFixed");A(a,"paging","bPaginate");A(a,"pagingType","sPaginationType");A(a,"pageLength","iDisplayLength");A(a,"searching","bFilter");"boolean"===typeof a.sScrollX&&(a.sScrollX=a.sScrollX?"100%":"");"boolean"===typeof a.scrollX&&(a.scrollX= +a.scrollX?"100%":"");if(a=a.aoSearchCols)for(var b=0,c=a.length;b<c;b++)a[b]&&K(m.models.oSearch,a[b])}function fb(a){A(a,"orderable","bSortable");A(a,"orderData","aDataSort");A(a,"orderSequence","asSorting");A(a,"orderDataType","sortDataType");var b=a.aDataSort;b&&!h.isArray(b)&&(a.aDataSort=[b])}function gb(a){if(!m.__browser){var b={};m.__browser=b;var c=h("<div/>").css({position:"fixed",top:0,left:0,height:1,width:1,overflow:"hidden"}).append(h("<div/>").css({position:"absolute",top:1,left:1, +width:100,overflow:"scroll"}).append(h("<div/>").css({width:"100%",height:10}))).appendTo("body"),d=c.children(),e=d.children();b.barWidth=d[0].offsetWidth-d[0].clientWidth;b.bScrollOversize=100===e[0].offsetWidth&&100!==d[0].clientWidth;b.bScrollbarLeft=1!==Math.round(e.offset().left);b.bBounding=c[0].getBoundingClientRect().width?!0:!1;c.remove()}h.extend(a.oBrowser,m.__browser);a.oScroll.iBarWidth=m.__browser.barWidth}function hb(a,b,c,d,e,f){var g,j=!1;c!==k&&(g=c,j=!0);for(;d!==e;)a.hasOwnProperty(d)&& +(g=j?b(g,a[d],d,a):a[d],j=!0,d+=f);return g}function Ea(a,b){var c=m.defaults.column,d=a.aoColumns.length,c=h.extend({},m.models.oColumn,c,{nTh:b?b:I.createElement("th"),sTitle:c.sTitle?c.sTitle:b?b.innerHTML:"",aDataSort:c.aDataSort?c.aDataSort:[d],mData:c.mData?c.mData:d,idx:d});a.aoColumns.push(c);c=a.aoPreSearchCols;c[d]=h.extend({},m.models.oSearch,c[d]);ja(a,d,h(b).data())}function ja(a,b,c){var b=a.aoColumns[b],d=a.oClasses,e=h(b.nTh);if(!b.sWidthOrig){b.sWidthOrig=e.attr("width")||null;var f= +(e.attr("style")||"").match(/width:\s*(\d+[pxem%]+)/);f&&(b.sWidthOrig=f[1])}c!==k&&null!==c&&(fb(c),K(m.defaults.column,c),c.mDataProp!==k&&!c.mData&&(c.mData=c.mDataProp),c.sType&&(b._sManualType=c.sType),c.className&&!c.sClass&&(c.sClass=c.className),h.extend(b,c),E(b,c,"sWidth","sWidthOrig"),c.iDataSort!==k&&(b.aDataSort=[c.iDataSort]),E(b,c,"aDataSort"));var g=b.mData,j=Q(g),i=b.mRender?Q(b.mRender):null,c=function(a){return"string"===typeof a&&-1!==a.indexOf("@")};b._bAttrSrc=h.isPlainObject(g)&& +(c(g.sort)||c(g.type)||c(g.filter));b._setter=null;b.fnGetData=function(a,b,c){var d=j(a,b,k,c);return i&&b?i(d,b,a,c):d};b.fnSetData=function(a,b,c){return R(g)(a,b,c)};"number"!==typeof g&&(a._rowReadObject=!0);a.oFeatures.bSort||(b.bSortable=!1,e.addClass(d.sSortableNone));a=-1!==h.inArray("asc",b.asSorting);c=-1!==h.inArray("desc",b.asSorting);!b.bSortable||!a&&!c?(b.sSortingClass=d.sSortableNone,b.sSortingClassJUI=""):a&&!c?(b.sSortingClass=d.sSortableAsc,b.sSortingClassJUI=d.sSortJUIAscAllowed): +!a&&c?(b.sSortingClass=d.sSortableDesc,b.sSortingClassJUI=d.sSortJUIDescAllowed):(b.sSortingClass=d.sSortable,b.sSortingClassJUI=d.sSortJUI)}function Y(a){if(!1!==a.oFeatures.bAutoWidth){var b=a.aoColumns;Fa(a);for(var c=0,d=b.length;c<d;c++)b[c].nTh.style.width=b[c].sWidth}b=a.oScroll;(""!==b.sY||""!==b.sX)&&ka(a);u(a,null,"column-sizing",[a])}function Z(a,b){var c=la(a,"bVisible");return"number"===typeof c[b]?c[b]:null}function $(a,b){var c=la(a,"bVisible"),c=h.inArray(b,c);return-1!==c?c:null} +function aa(a){var b=0;h.each(a.aoColumns,function(a,d){d.bVisible&&"none"!==h(d.nTh).css("display")&&b++});return b}function la(a,b){var c=[];h.map(a.aoColumns,function(a,e){a[b]&&c.push(e)});return c}function Ga(a){var b=a.aoColumns,c=a.aoData,d=m.ext.type.detect,e,f,g,j,i,h,l,q,t;e=0;for(f=b.length;e<f;e++)if(l=b[e],t=[],!l.sType&&l._sManualType)l.sType=l._sManualType;else if(!l.sType){g=0;for(j=d.length;g<j;g++){i=0;for(h=c.length;i<h;i++){t[i]===k&&(t[i]=B(a,i,e,"type"));q=d[g](t[i],a);if(!q&& +g!==d.length-1)break;if("html"===q)break}if(q){l.sType=q;break}}l.sType||(l.sType="string")}}function ib(a,b,c,d){var e,f,g,j,i,n,l=a.aoColumns;if(b)for(e=b.length-1;0<=e;e--){n=b[e];var q=n.targets!==k?n.targets:n.aTargets;h.isArray(q)||(q=[q]);f=0;for(g=q.length;f<g;f++)if("number"===typeof q[f]&&0<=q[f]){for(;l.length<=q[f];)Ea(a);d(q[f],n)}else if("number"===typeof q[f]&&0>q[f])d(l.length+q[f],n);else if("string"===typeof q[f]){j=0;for(i=l.length;j<i;j++)("_all"==q[f]||h(l[j].nTh).hasClass(q[f]))&& +d(j,n)}}if(c){e=0;for(a=c.length;e<a;e++)d(e,c[e])}}function N(a,b,c,d){var e=a.aoData.length,f=h.extend(!0,{},m.models.oRow,{src:c?"dom":"data",idx:e});f._aData=b;a.aoData.push(f);for(var g=a.aoColumns,j=0,i=g.length;j<i;j++)g[j].sType=null;a.aiDisplayMaster.push(e);b=a.rowIdFn(b);b!==k&&(a.aIds[b]=f);(c||!a.oFeatures.bDeferRender)&&Ha(a,e,c,d);return e}function ma(a,b){var c;b instanceof h||(b=h(b));return b.map(function(b,e){c=Ia(a,e);return N(a,c.data,e,c.cells)})}function B(a,b,c,d){var e=a.iDraw, +f=a.aoColumns[c],g=a.aoData[b]._aData,j=f.sDefaultContent,i=f.fnGetData(g,d,{settings:a,row:b,col:c});if(i===k)return a.iDrawError!=e&&null===j&&(L(a,0,"Requested unknown parameter "+("function"==typeof f.mData?"{function}":"'"+f.mData+"'")+" for row "+b+", column "+c,4),a.iDrawError=e),j;if((i===g||null===i)&&null!==j&&d!==k)i=j;else if("function"===typeof i)return i.call(g);return null===i&&"display"==d?"":i}function jb(a,b,c,d){a.aoColumns[c].fnSetData(a.aoData[b]._aData,d,{settings:a,row:b,col:c})} +function Ja(a){return h.map(a.match(/(\\.|[^\.])+/g)||[""],function(a){return a.replace(/\\./g,".")})}function Q(a){if(h.isPlainObject(a)){var b={};h.each(a,function(a,c){c&&(b[a]=Q(c))});return function(a,c,f,g){var j=b[c]||b._;return j!==k?j(a,c,f,g):a}}if(null===a)return function(a){return a};if("function"===typeof a)return function(b,c,f,g){return a(b,c,f,g)};if("string"===typeof a&&(-1!==a.indexOf(".")||-1!==a.indexOf("[")||-1!==a.indexOf("("))){var c=function(a,b,f){var g,j;if(""!==f){j=Ja(f); +for(var i=0,n=j.length;i<n;i++){f=j[i].match(ba);g=j[i].match(U);if(f){j[i]=j[i].replace(ba,"");""!==j[i]&&(a=a[j[i]]);g=[];j.splice(0,i+1);j=j.join(".");if(h.isArray(a)){i=0;for(n=a.length;i<n;i++)g.push(c(a[i],b,j))}a=f[0].substring(1,f[0].length-1);a=""===a?g:g.join(a);break}else if(g){j[i]=j[i].replace(U,"");a=a[j[i]]();continue}if(null===a||a[j[i]]===k)return k;a=a[j[i]]}}return a};return function(b,e){return c(b,e,a)}}return function(b){return b[a]}}function R(a){if(h.isPlainObject(a))return R(a._); +if(null===a)return function(){};if("function"===typeof a)return function(b,d,e){a(b,"set",d,e)};if("string"===typeof a&&(-1!==a.indexOf(".")||-1!==a.indexOf("[")||-1!==a.indexOf("("))){var b=function(a,d,e){var e=Ja(e),f;f=e[e.length-1];for(var g,j,i=0,n=e.length-1;i<n;i++){g=e[i].match(ba);j=e[i].match(U);if(g){e[i]=e[i].replace(ba,"");a[e[i]]=[];f=e.slice();f.splice(0,i+1);g=f.join(".");if(h.isArray(d)){j=0;for(n=d.length;j<n;j++)f={},b(f,d[j],g),a[e[i]].push(f)}else a[e[i]]=d;return}j&&(e[i]=e[i].replace(U, +""),a=a[e[i]](d));if(null===a[e[i]]||a[e[i]]===k)a[e[i]]={};a=a[e[i]]}if(f.match(U))a[f.replace(U,"")](d);else a[f.replace(ba,"")]=d};return function(c,d){return b(c,d,a)}}return function(b,d){b[a]=d}}function Ka(a){return G(a.aoData,"_aData")}function na(a){a.aoData.length=0;a.aiDisplayMaster.length=0;a.aiDisplay.length=0;a.aIds={}}function oa(a,b,c){for(var d=-1,e=0,f=a.length;e<f;e++)a[e]==b?d=e:a[e]>b&&a[e]--; -1!=d&&c===k&&a.splice(d,1)}function ca(a,b,c,d){var e=a.aoData[b],f,g=function(c,d){for(;c.childNodes.length;)c.removeChild(c.firstChild); +c.innerHTML=B(a,b,d,"display")};if("dom"===c||(!c||"auto"===c)&&"dom"===e.src)e._aData=Ia(a,e,d,d===k?k:e._aData).data;else{var j=e.anCells;if(j)if(d!==k)g(j[d],d);else{c=0;for(f=j.length;c<f;c++)g(j[c],c)}}e._aSortData=null;e._aFilterData=null;g=a.aoColumns;if(d!==k)g[d].sType=null;else{c=0;for(f=g.length;c<f;c++)g[c].sType=null;La(a,e)}}function Ia(a,b,c,d){var e=[],f=b.firstChild,g,j,i=0,n,l=a.aoColumns,q=a._rowReadObject,d=d!==k?d:q?{}:[],t=function(a,b){if("string"===typeof a){var c=a.indexOf("@"); +-1!==c&&(c=a.substring(c+1),R(a)(d,b.getAttribute(c)))}},S=function(a){if(c===k||c===i)j=l[i],n=h.trim(a.innerHTML),j&&j._bAttrSrc?(R(j.mData._)(d,n),t(j.mData.sort,a),t(j.mData.type,a),t(j.mData.filter,a)):q?(j._setter||(j._setter=R(j.mData)),j._setter(d,n)):d[i]=n;i++};if(f)for(;f;){g=f.nodeName.toUpperCase();if("TD"==g||"TH"==g)S(f),e.push(f);f=f.nextSibling}else{e=b.anCells;f=0;for(g=e.length;f<g;f++)S(e[f])}if(b=b.firstChild?b:b.nTr)(b=b.getAttribute("id"))&&R(a.rowId)(d,b);return{data:d,cells:e}} +function Ha(a,b,c,d){var e=a.aoData[b],f=e._aData,g=[],j,i,n,l,q;if(null===e.nTr){j=c||I.createElement("tr");e.nTr=j;e.anCells=g;j._DT_RowIndex=b;La(a,e);l=0;for(q=a.aoColumns.length;l<q;l++){n=a.aoColumns[l];i=c?d[l]:I.createElement(n.sCellType);i._DT_CellIndex={row:b,column:l};g.push(i);if((!c||n.mRender||n.mData!==l)&&(!h.isPlainObject(n.mData)||n.mData._!==l+".display"))i.innerHTML=B(a,b,l,"display");n.sClass&&(i.className+=" "+n.sClass);n.bVisible&&!c?j.appendChild(i):!n.bVisible&&c&&i.parentNode.removeChild(i); +n.fnCreatedCell&&n.fnCreatedCell.call(a.oInstance,i,B(a,b,l),f,b,l)}u(a,"aoRowCreatedCallback",null,[j,f,b])}e.nTr.setAttribute("role","row")}function La(a,b){var c=b.nTr,d=b._aData;if(c){var e=a.rowIdFn(d);e&&(c.id=e);d.DT_RowClass&&(e=d.DT_RowClass.split(" "),b.__rowc=b.__rowc?pa(b.__rowc.concat(e)):e,h(c).removeClass(b.__rowc.join(" ")).addClass(d.DT_RowClass));d.DT_RowAttr&&h(c).attr(d.DT_RowAttr);d.DT_RowData&&h(c).data(d.DT_RowData)}}function kb(a){var b,c,d,e,f,g=a.nTHead,j=a.nTFoot,i=0=== +h("th, td",g).length,n=a.oClasses,l=a.aoColumns;i&&(e=h("<tr/>").appendTo(g));b=0;for(c=l.length;b<c;b++)f=l[b],d=h(f.nTh).addClass(f.sClass),i&&d.appendTo(e),a.oFeatures.bSort&&(d.addClass(f.sSortingClass),!1!==f.bSortable&&(d.attr("tabindex",a.iTabIndex).attr("aria-controls",a.sTableId),Ma(a,f.nTh,b))),f.sTitle!=d[0].innerHTML&&d.html(f.sTitle),Na(a,"header")(a,d,f,n);i&&da(a.aoHeader,g);h(g).find(">tr").attr("role","row");h(g).find(">tr>th, >tr>td").addClass(n.sHeaderTH);h(j).find(">tr>th, >tr>td").addClass(n.sFooterTH); +if(null!==j){a=a.aoFooter[0];b=0;for(c=a.length;b<c;b++)f=l[b],f.nTf=a[b].cell,f.sClass&&h(f.nTf).addClass(f.sClass)}}function ea(a,b,c){var d,e,f,g=[],j=[],i=a.aoColumns.length,n;if(b){c===k&&(c=!1);d=0;for(e=b.length;d<e;d++){g[d]=b[d].slice();g[d].nTr=b[d].nTr;for(f=i-1;0<=f;f--)!a.aoColumns[f].bVisible&&!c&&g[d].splice(f,1);j.push([])}d=0;for(e=g.length;d<e;d++){if(a=g[d].nTr)for(;f=a.firstChild;)a.removeChild(f);f=0;for(b=g[d].length;f<b;f++)if(n=i=1,j[d][f]===k){a.appendChild(g[d][f].cell); +for(j[d][f]=1;g[d+i]!==k&&g[d][f].cell==g[d+i][f].cell;)j[d+i][f]=1,i++;for(;g[d][f+n]!==k&&g[d][f].cell==g[d][f+n].cell;){for(c=0;c<i;c++)j[d+c][f+n]=1;n++}h(g[d][f].cell).attr("rowspan",i).attr("colspan",n)}}}}function O(a){var b=u(a,"aoPreDrawCallback","preDraw",[a]);if(-1!==h.inArray(!1,b))C(a,!1);else{var b=[],c=0,d=a.asStripeClasses,e=d.length,f=a.oLanguage,g=a.iInitDisplayStart,j="ssp"==y(a),i=a.aiDisplay;a.bDrawing=!0;g!==k&&-1!==g&&(a._iDisplayStart=j?g:g>=a.fnRecordsDisplay()?0:g,a.iInitDisplayStart= +-1);var g=a._iDisplayStart,n=a.fnDisplayEnd();if(a.bDeferLoading)a.bDeferLoading=!1,a.iDraw++,C(a,!1);else if(j){if(!a.bDestroying&&!lb(a))return}else a.iDraw++;if(0!==i.length){f=j?a.aoData.length:n;for(j=j?0:g;j<f;j++){var l=i[j],q=a.aoData[l];null===q.nTr&&Ha(a,l);l=q.nTr;if(0!==e){var t=d[c%e];q._sRowStripe!=t&&(h(l).removeClass(q._sRowStripe).addClass(t),q._sRowStripe=t)}u(a,"aoRowCallback",null,[l,q._aData,c,j]);b.push(l);c++}}else c=f.sZeroRecords,1==a.iDraw&&"ajax"==y(a)?c=f.sLoadingRecords: +f.sEmptyTable&&0===a.fnRecordsTotal()&&(c=f.sEmptyTable),b[0]=h("<tr/>",{"class":e?d[0]:""}).append(h("<td />",{valign:"top",colSpan:aa(a),"class":a.oClasses.sRowEmpty}).html(c))[0];u(a,"aoHeaderCallback","header",[h(a.nTHead).children("tr")[0],Ka(a),g,n,i]);u(a,"aoFooterCallback","footer",[h(a.nTFoot).children("tr")[0],Ka(a),g,n,i]);d=h(a.nTBody);d.children().detach();d.append(h(b));u(a,"aoDrawCallback","draw",[a]);a.bSorted=!1;a.bFiltered=!1;a.bDrawing=!1}}function T(a,b){var c=a.oFeatures,d=c.bFilter; +c.bSort&&mb(a);d?fa(a,a.oPreviousSearch):a.aiDisplay=a.aiDisplayMaster.slice();!0!==b&&(a._iDisplayStart=0);a._drawHold=b;O(a);a._drawHold=!1}function nb(a){var b=a.oClasses,c=h(a.nTable),c=h("<div/>").insertBefore(c),d=a.oFeatures,e=h("<div/>",{id:a.sTableId+"_wrapper","class":b.sWrapper+(a.nTFoot?"":" "+b.sNoFooter)});a.nHolding=c[0];a.nTableWrapper=e[0];a.nTableReinsertBefore=a.nTable.nextSibling;for(var f=a.sDom.split(""),g,j,i,n,l,q,t=0;t<f.length;t++){g=null;j=f[t];if("<"==j){i=h("<div/>")[0]; +n=f[t+1];if("'"==n||'"'==n){l="";for(q=2;f[t+q]!=n;)l+=f[t+q],q++;"H"==l?l=b.sJUIHeader:"F"==l&&(l=b.sJUIFooter);-1!=l.indexOf(".")?(n=l.split("."),i.id=n[0].substr(1,n[0].length-1),i.className=n[1]):"#"==l.charAt(0)?i.id=l.substr(1,l.length-1):i.className=l;t+=q}e.append(i);e=h(i)}else if(">"==j)e=e.parent();else if("l"==j&&d.bPaginate&&d.bLengthChange)g=ob(a);else if("f"==j&&d.bFilter)g=pb(a);else if("r"==j&&d.bProcessing)g=qb(a);else if("t"==j)g=rb(a);else if("i"==j&&d.bInfo)g=sb(a);else if("p"== +j&&d.bPaginate)g=tb(a);else if(0!==m.ext.feature.length){i=m.ext.feature;q=0;for(n=i.length;q<n;q++)if(j==i[q].cFeature){g=i[q].fnInit(a);break}}g&&(i=a.aanFeatures,i[j]||(i[j]=[]),i[j].push(g),e.append(g))}c.replaceWith(e);a.nHolding=null}function da(a,b){var c=h(b).children("tr"),d,e,f,g,j,i,n,l,q,t;a.splice(0,a.length);f=0;for(i=c.length;f<i;f++)a.push([]);f=0;for(i=c.length;f<i;f++){d=c[f];for(e=d.firstChild;e;){if("TD"==e.nodeName.toUpperCase()||"TH"==e.nodeName.toUpperCase()){l=1*e.getAttribute("colspan"); +q=1*e.getAttribute("rowspan");l=!l||0===l||1===l?1:l;q=!q||0===q||1===q?1:q;g=0;for(j=a[f];j[g];)g++;n=g;t=1===l?!0:!1;for(j=0;j<l;j++)for(g=0;g<q;g++)a[f+g][n+j]={cell:e,unique:t},a[f+g].nTr=d}e=e.nextSibling}}}function qa(a,b,c){var d=[];c||(c=a.aoHeader,b&&(c=[],da(c,b)));for(var b=0,e=c.length;b<e;b++)for(var f=0,g=c[b].length;f<g;f++)if(c[b][f].unique&&(!d[f]||!a.bSortCellsTop))d[f]=c[b][f].cell;return d}function ra(a,b,c){u(a,"aoServerParams","serverParams",[b]);if(b&&h.isArray(b)){var d={}, +e=/(.*?)\[\]$/;h.each(b,function(a,b){var c=b.name.match(e);c?(c=c[0],d[c]||(d[c]=[]),d[c].push(b.value)):d[b.name]=b.value});b=d}var f,g=a.ajax,j=a.oInstance,i=function(b){u(a,null,"xhr",[a,b,a.jqXHR]);c(b)};if(h.isPlainObject(g)&&g.data){f=g.data;var n=h.isFunction(f)?f(b,a):f,b=h.isFunction(f)&&n?n:h.extend(!0,b,n);delete g.data}n={data:b,success:function(b){var c=b.error||b.sError;c&&L(a,0,c);a.json=b;i(b)},dataType:"json",cache:!1,type:a.sServerMethod,error:function(b,c){var d=u(a,null,"xhr", +[a,null,a.jqXHR]);-1===h.inArray(!0,d)&&("parsererror"==c?L(a,0,"Invalid JSON response",1):4===b.readyState&&L(a,0,"Ajax error",7));C(a,!1)}};a.oAjaxData=b;u(a,null,"preXhr",[a,b]);a.fnServerData?a.fnServerData.call(j,a.sAjaxSource,h.map(b,function(a,b){return{name:b,value:a}}),i,a):a.sAjaxSource||"string"===typeof g?a.jqXHR=h.ajax(h.extend(n,{url:g||a.sAjaxSource})):h.isFunction(g)?a.jqXHR=g.call(j,b,i,a):(a.jqXHR=h.ajax(h.extend(n,g)),g.data=f)}function lb(a){return a.bAjaxDataGet?(a.iDraw++,C(a, +!0),ra(a,ub(a),function(b){vb(a,b)}),!1):!0}function ub(a){var b=a.aoColumns,c=b.length,d=a.oFeatures,e=a.oPreviousSearch,f=a.aoPreSearchCols,g,j=[],i,n,l,q=V(a);g=a._iDisplayStart;i=!1!==d.bPaginate?a._iDisplayLength:-1;var k=function(a,b){j.push({name:a,value:b})};k("sEcho",a.iDraw);k("iColumns",c);k("sColumns",G(b,"sName").join(","));k("iDisplayStart",g);k("iDisplayLength",i);var S={draw:a.iDraw,columns:[],order:[],start:g,length:i,search:{value:e.sSearch,regex:e.bRegex}};for(g=0;g<c;g++)n=b[g], +l=f[g],i="function"==typeof n.mData?"function":n.mData,S.columns.push({data:i,name:n.sName,searchable:n.bSearchable,orderable:n.bSortable,search:{value:l.sSearch,regex:l.bRegex}}),k("mDataProp_"+g,i),d.bFilter&&(k("sSearch_"+g,l.sSearch),k("bRegex_"+g,l.bRegex),k("bSearchable_"+g,n.bSearchable)),d.bSort&&k("bSortable_"+g,n.bSortable);d.bFilter&&(k("sSearch",e.sSearch),k("bRegex",e.bRegex));d.bSort&&(h.each(q,function(a,b){S.order.push({column:b.col,dir:b.dir});k("iSortCol_"+a,b.col);k("sSortDir_"+ +a,b.dir)}),k("iSortingCols",q.length));b=m.ext.legacy.ajax;return null===b?a.sAjaxSource?j:S:b?j:S}function vb(a,b){var c=sa(a,b),d=b.sEcho!==k?b.sEcho:b.draw,e=b.iTotalRecords!==k?b.iTotalRecords:b.recordsTotal,f=b.iTotalDisplayRecords!==k?b.iTotalDisplayRecords:b.recordsFiltered;if(d){if(1*d<a.iDraw)return;a.iDraw=1*d}na(a);a._iRecordsTotal=parseInt(e,10);a._iRecordsDisplay=parseInt(f,10);d=0;for(e=c.length;d<e;d++)N(a,c[d]);a.aiDisplay=a.aiDisplayMaster.slice();a.bAjaxDataGet=!1;O(a);a._bInitComplete|| +ta(a,b);a.bAjaxDataGet=!0;C(a,!1)}function sa(a,b){var c=h.isPlainObject(a.ajax)&&a.ajax.dataSrc!==k?a.ajax.dataSrc:a.sAjaxDataProp;return"data"===c?b.aaData||b[c]:""!==c?Q(c)(b):b}function pb(a){var b=a.oClasses,c=a.sTableId,d=a.oLanguage,e=a.oPreviousSearch,f=a.aanFeatures,g='<input type="search" class="'+b.sFilterInput+'"/>',j=d.sSearch,j=j.match(/_INPUT_/)?j.replace("_INPUT_",g):j+g,b=h("<div/>",{id:!f.f?c+"_filter":null,"class":b.sFilter}).append(h("<label/>").append(j)),f=function(){var b=!this.value? +"":this.value;b!=e.sSearch&&(fa(a,{sSearch:b,bRegex:e.bRegex,bSmart:e.bSmart,bCaseInsensitive:e.bCaseInsensitive}),a._iDisplayStart=0,O(a))},g=null!==a.searchDelay?a.searchDelay:"ssp"===y(a)?400:0,i=h("input",b).val(e.sSearch).attr("placeholder",d.sSearchPlaceholder).bind("keyup.DT search.DT input.DT paste.DT cut.DT",g?Oa(f,g):f).bind("keypress.DT",function(a){if(13==a.keyCode)return!1}).attr("aria-controls",c);h(a.nTable).on("search.dt.DT",function(b,c){if(a===c)try{i[0]!==I.activeElement&&i.val(e.sSearch)}catch(d){}}); +return b[0]}function fa(a,b,c){var d=a.oPreviousSearch,e=a.aoPreSearchCols,f=function(a){d.sSearch=a.sSearch;d.bRegex=a.bRegex;d.bSmart=a.bSmart;d.bCaseInsensitive=a.bCaseInsensitive};Ga(a);if("ssp"!=y(a)){wb(a,b.sSearch,c,b.bEscapeRegex!==k?!b.bEscapeRegex:b.bRegex,b.bSmart,b.bCaseInsensitive);f(b);for(b=0;b<e.length;b++)xb(a,e[b].sSearch,b,e[b].bEscapeRegex!==k?!e[b].bEscapeRegex:e[b].bRegex,e[b].bSmart,e[b].bCaseInsensitive);yb(a)}else f(b);a.bFiltered=!0;u(a,null,"search",[a])}function yb(a){for(var b= +m.ext.search,c=a.aiDisplay,d,e,f=0,g=b.length;f<g;f++){for(var j=[],i=0,n=c.length;i<n;i++)e=c[i],d=a.aoData[e],b[f](a,d._aFilterData,e,d._aData,i)&&j.push(e);c.length=0;h.merge(c,j)}}function xb(a,b,c,d,e,f){if(""!==b)for(var g=a.aiDisplay,d=Pa(b,d,e,f),e=g.length-1;0<=e;e--)b=a.aoData[g[e]]._aFilterData[c],d.test(b)||g.splice(e,1)}function wb(a,b,c,d,e,f){var d=Pa(b,d,e,f),e=a.oPreviousSearch.sSearch,f=a.aiDisplayMaster,g;0!==m.ext.search.length&&(c=!0);g=zb(a);if(0>=b.length)a.aiDisplay=f.slice(); +else{if(g||c||e.length>b.length||0!==b.indexOf(e)||a.bSorted)a.aiDisplay=f.slice();b=a.aiDisplay;for(c=b.length-1;0<=c;c--)d.test(a.aoData[b[c]]._sFilterRow)||b.splice(c,1)}}function Pa(a,b,c,d){a=b?a:Qa(a);c&&(a="^(?=.*?"+h.map(a.match(/"[^"]+"|[^ ]+/g)||[""],function(a){if('"'===a.charAt(0))var b=a.match(/^"(.*)"$/),a=b?b[1]:a;return a.replace('"',"")}).join(")(?=.*?")+").*$");return RegExp(a,d?"i":"")}function zb(a){var b=a.aoColumns,c,d,e,f,g,j,i,h,l=m.ext.type.search;c=!1;d=0;for(f=a.aoData.length;d< +f;d++)if(h=a.aoData[d],!h._aFilterData){j=[];e=0;for(g=b.length;e<g;e++)c=b[e],c.bSearchable?(i=B(a,d,e,"filter"),l[c.sType]&&(i=l[c.sType](i)),null===i&&(i=""),"string"!==typeof i&&i.toString&&(i=i.toString())):i="",i.indexOf&&-1!==i.indexOf("&")&&(ua.innerHTML=i,i=Zb?ua.textContent:ua.innerText),i.replace&&(i=i.replace(/[\r\n]/g,"")),j.push(i);h._aFilterData=j;h._sFilterRow=j.join(" ");c=!0}return c}function Ab(a){return{search:a.sSearch,smart:a.bSmart,regex:a.bRegex,caseInsensitive:a.bCaseInsensitive}} +function Bb(a){return{sSearch:a.search,bSmart:a.smart,bRegex:a.regex,bCaseInsensitive:a.caseInsensitive}}function sb(a){var b=a.sTableId,c=a.aanFeatures.i,d=h("<div/>",{"class":a.oClasses.sInfo,id:!c?b+"_info":null});c||(a.aoDrawCallback.push({fn:Cb,sName:"information"}),d.attr("role","status").attr("aria-live","polite"),h(a.nTable).attr("aria-describedby",b+"_info"));return d[0]}function Cb(a){var b=a.aanFeatures.i;if(0!==b.length){var c=a.oLanguage,d=a._iDisplayStart+1,e=a.fnDisplayEnd(),f=a.fnRecordsTotal(), +g=a.fnRecordsDisplay(),j=g?c.sInfo:c.sInfoEmpty;g!==f&&(j+=" "+c.sInfoFiltered);j+=c.sInfoPostFix;j=Db(a,j);c=c.fnInfoCallback;null!==c&&(j=c.call(a.oInstance,a,d,e,f,g,j));h(b).html(j)}}function Db(a,b){var c=a.fnFormatNumber,d=a._iDisplayStart+1,e=a._iDisplayLength,f=a.fnRecordsDisplay(),g=-1===e;return b.replace(/_START_/g,c.call(a,d)).replace(/_END_/g,c.call(a,a.fnDisplayEnd())).replace(/_MAX_/g,c.call(a,a.fnRecordsTotal())).replace(/_TOTAL_/g,c.call(a,f)).replace(/_PAGE_/g,c.call(a,g?1:Math.ceil(d/ +e))).replace(/_PAGES_/g,c.call(a,g?1:Math.ceil(f/e)))}function ga(a){var b,c,d=a.iInitDisplayStart,e=a.aoColumns,f;c=a.oFeatures;var g=a.bDeferLoading;if(a.bInitialised){nb(a);kb(a);ea(a,a.aoHeader);ea(a,a.aoFooter);C(a,!0);c.bAutoWidth&&Fa(a);b=0;for(c=e.length;b<c;b++)f=e[b],f.sWidth&&(f.nTh.style.width=x(f.sWidth));u(a,null,"preInit",[a]);T(a);e=y(a);if("ssp"!=e||g)"ajax"==e?ra(a,[],function(c){var f=sa(a,c);for(b=0;b<f.length;b++)N(a,f[b]);a.iInitDisplayStart=d;T(a);C(a,!1);ta(a,c)},a):(C(a,!1), +ta(a))}else setTimeout(function(){ga(a)},200)}function ta(a,b){a._bInitComplete=!0;(b||a.oInit.aaData)&&Y(a);u(a,null,"plugin-init",[a,b]);u(a,"aoInitComplete","init",[a,b])}function Ra(a,b){var c=parseInt(b,10);a._iDisplayLength=c;Sa(a);u(a,null,"length",[a,c])}function ob(a){for(var b=a.oClasses,c=a.sTableId,d=a.aLengthMenu,e=h.isArray(d[0]),f=e?d[0]:d,d=e?d[1]:d,e=h("<select/>",{name:c+"_length","aria-controls":c,"class":b.sLengthSelect}),g=0,j=f.length;g<j;g++)e[0][g]=new Option(d[g],f[g]);var i= +h("<div><label/></div>").addClass(b.sLength);a.aanFeatures.l||(i[0].id=c+"_length");i.children().append(a.oLanguage.sLengthMenu.replace("_MENU_",e[0].outerHTML));h("select",i).val(a._iDisplayLength).bind("change.DT",function(){Ra(a,h(this).val());O(a)});h(a.nTable).bind("length.dt.DT",function(b,c,d){a===c&&h("select",i).val(d)});return i[0]}function tb(a){var b=a.sPaginationType,c=m.ext.pager[b],d="function"===typeof c,e=function(a){O(a)},b=h("<div/>").addClass(a.oClasses.sPaging+b)[0],f=a.aanFeatures; +d||c.fnInit(a,b,e);f.p||(b.id=a.sTableId+"_paginate",a.aoDrawCallback.push({fn:function(a){if(d){var b=a._iDisplayStart,i=a._iDisplayLength,h=a.fnRecordsDisplay(),l=-1===i,b=l?0:Math.ceil(b/i),i=l?1:Math.ceil(h/i),h=c(b,i),k,l=0;for(k=f.p.length;l<k;l++)Na(a,"pageButton")(a,f.p[l],l,h,b,i)}else c.fnUpdate(a,e)},sName:"pagination"}));return b}function Ta(a,b,c){var d=a._iDisplayStart,e=a._iDisplayLength,f=a.fnRecordsDisplay();0===f||-1===e?d=0:"number"===typeof b?(d=b*e,d>f&&(d=0)):"first"==b?d=0: +"previous"==b?(d=0<=e?d-e:0,0>d&&(d=0)):"next"==b?d+e<f&&(d+=e):"last"==b?d=Math.floor((f-1)/e)*e:L(a,0,"Unknown paging action: "+b,5);b=a._iDisplayStart!==d;a._iDisplayStart=d;b&&(u(a,null,"page",[a]),c&&O(a));return b}function qb(a){return h("<div/>",{id:!a.aanFeatures.r?a.sTableId+"_processing":null,"class":a.oClasses.sProcessing}).html(a.oLanguage.sProcessing).insertBefore(a.nTable)[0]}function C(a,b){a.oFeatures.bProcessing&&h(a.aanFeatures.r).css("display",b?"block":"none");u(a,null,"processing", +[a,b])}function rb(a){var b=h(a.nTable);b.attr("role","grid");var c=a.oScroll;if(""===c.sX&&""===c.sY)return a.nTable;var d=c.sX,e=c.sY,f=a.oClasses,g=b.children("caption"),j=g.length?g[0]._captionSide:null,i=h(b[0].cloneNode(!1)),n=h(b[0].cloneNode(!1)),l=b.children("tfoot");l.length||(l=null);i=h("<div/>",{"class":f.sScrollWrapper}).append(h("<div/>",{"class":f.sScrollHead}).css({overflow:"hidden",position:"relative",border:0,width:d?!d?null:x(d):"100%"}).append(h("<div/>",{"class":f.sScrollHeadInner}).css({"box-sizing":"content-box", +width:c.sXInner||"100%"}).append(i.removeAttr("id").css("margin-left",0).append("top"===j?g:null).append(b.children("thead"))))).append(h("<div/>",{"class":f.sScrollBody}).css({position:"relative",overflow:"auto",width:!d?null:x(d)}).append(b));l&&i.append(h("<div/>",{"class":f.sScrollFoot}).css({overflow:"hidden",border:0,width:d?!d?null:x(d):"100%"}).append(h("<div/>",{"class":f.sScrollFootInner}).append(n.removeAttr("id").css("margin-left",0).append("bottom"===j?g:null).append(b.children("tfoot"))))); +var b=i.children(),k=b[0],f=b[1],t=l?b[2]:null;if(d)h(f).on("scroll.DT",function(){var a=this.scrollLeft;k.scrollLeft=a;l&&(t.scrollLeft=a)});h(f).css(e&&c.bCollapse?"max-height":"height",e);a.nScrollHead=k;a.nScrollBody=f;a.nScrollFoot=t;a.aoDrawCallback.push({fn:ka,sName:"scrolling"});return i[0]}function ka(a){var b=a.oScroll,c=b.sX,d=b.sXInner,e=b.sY,b=b.iBarWidth,f=h(a.nScrollHead),g=f[0].style,j=f.children("div"),i=j[0].style,n=j.children("table"),j=a.nScrollBody,l=h(j),q=j.style,t=h(a.nScrollFoot).children("div"), +m=t.children("table"),o=h(a.nTHead),F=h(a.nTable),p=F[0],r=p.style,u=a.nTFoot?h(a.nTFoot):null,Eb=a.oBrowser,Ua=Eb.bScrollOversize,s=G(a.aoColumns,"nTh"),P,v,w,y,z=[],A=[],B=[],C=[],D,E=function(a){a=a.style;a.paddingTop="0";a.paddingBottom="0";a.borderTopWidth="0";a.borderBottomWidth="0";a.height=0};v=j.scrollHeight>j.clientHeight;if(a.scrollBarVis!==v&&a.scrollBarVis!==k)a.scrollBarVis=v,Y(a);else{a.scrollBarVis=v;F.children("thead, tfoot").remove();u&&(w=u.clone().prependTo(F),P=u.find("tr"),w= +w.find("tr"));y=o.clone().prependTo(F);o=o.find("tr");v=y.find("tr");y.find("th, td").removeAttr("tabindex");c||(q.width="100%",f[0].style.width="100%");h.each(qa(a,y),function(b,c){D=Z(a,b);c.style.width=a.aoColumns[D].sWidth});u&&J(function(a){a.style.width=""},w);f=F.outerWidth();if(""===c){r.width="100%";if(Ua&&(F.find("tbody").height()>j.offsetHeight||"scroll"==l.css("overflow-y")))r.width=x(F.outerWidth()-b);f=F.outerWidth()}else""!==d&&(r.width=x(d),f=F.outerWidth());J(E,v);J(function(a){B.push(a.innerHTML); +z.push(x(h(a).css("width")))},v);J(function(a,b){if(h.inArray(a,s)!==-1)a.style.width=z[b]},o);h(v).height(0);u&&(J(E,w),J(function(a){C.push(a.innerHTML);A.push(x(h(a).css("width")))},w),J(function(a,b){a.style.width=A[b]},P),h(w).height(0));J(function(a,b){a.innerHTML='<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+B[b]+"</div>";a.style.width=z[b]},v);u&&J(function(a,b){a.innerHTML='<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+C[b]+"</div>";a.style.width= +A[b]},w);if(F.outerWidth()<f){P=j.scrollHeight>j.offsetHeight||"scroll"==l.css("overflow-y")?f+b:f;if(Ua&&(j.scrollHeight>j.offsetHeight||"scroll"==l.css("overflow-y")))r.width=x(P-b);(""===c||""!==d)&&L(a,1,"Possible column misalignment",6)}else P="100%";q.width=x(P);g.width=x(P);u&&(a.nScrollFoot.style.width=x(P));!e&&Ua&&(q.height=x(p.offsetHeight+b));c=F.outerWidth();n[0].style.width=x(c);i.width=x(c);d=F.height()>j.clientHeight||"scroll"==l.css("overflow-y");e="padding"+(Eb.bScrollbarLeft?"Left": +"Right");i[e]=d?b+"px":"0px";u&&(m[0].style.width=x(c),t[0].style.width=x(c),t[0].style[e]=d?b+"px":"0px");F.children("colgroup").insertBefore(F.children("thead"));l.scroll();if((a.bSorted||a.bFiltered)&&!a._drawHold)j.scrollTop=0}}function J(a,b,c){for(var d=0,e=0,f=b.length,g,j;e<f;){g=b[e].firstChild;for(j=c?c[e].firstChild:null;g;)1===g.nodeType&&(c?a(g,j,d):a(g,d),d++),g=g.nextSibling,j=c?j.nextSibling:null;e++}}function Fa(a){var b=a.nTable,c=a.aoColumns,d=a.oScroll,e=d.sY,f=d.sX,g=d.sXInner, +j=c.length,i=la(a,"bVisible"),n=h("th",a.nTHead),l=b.getAttribute("width"),k=b.parentNode,t=!1,m,o,p=a.oBrowser,d=p.bScrollOversize;(m=b.style.width)&&-1!==m.indexOf("%")&&(l=m);for(m=0;m<i.length;m++)o=c[i[m]],null!==o.sWidth&&(o.sWidth=Fb(o.sWidthOrig,k),t=!0);if(d||!t&&!f&&!e&&j==aa(a)&&j==n.length)for(m=0;m<j;m++)i=Z(a,m),null!==i&&(c[i].sWidth=x(n.eq(m).width()));else{j=h(b).clone().css("visibility","hidden").removeAttr("id");j.find("tbody tr").remove();var r=h("<tr/>").appendTo(j.find("tbody")); +j.find("thead, tfoot").remove();j.append(h(a.nTHead).clone()).append(h(a.nTFoot).clone());j.find("tfoot th, tfoot td").css("width","");n=qa(a,j.find("thead")[0]);for(m=0;m<i.length;m++)o=c[i[m]],n[m].style.width=null!==o.sWidthOrig&&""!==o.sWidthOrig?x(o.sWidthOrig):"",o.sWidthOrig&&f&&h(n[m]).append(h("<div/>").css({width:o.sWidthOrig,margin:0,padding:0,border:0,height:1}));if(a.aoData.length)for(m=0;m<i.length;m++)t=i[m],o=c[t],h(Gb(a,t)).clone(!1).append(o.sContentPadding).appendTo(r);h("[name]", +j).removeAttr("name");o=h("<div/>").css(f||e?{position:"absolute",top:0,left:0,height:1,right:0,overflow:"hidden"}:{}).append(j).appendTo(k);f&&g?j.width(g):f?(j.css("width","auto"),j.removeAttr("width"),j.width()<k.clientWidth&&l&&j.width(k.clientWidth)):e?j.width(k.clientWidth):l&&j.width(l);for(m=e=0;m<i.length;m++)k=h(n[m]),g=k.outerWidth()-k.width(),k=p.bBounding?Math.ceil(n[m].getBoundingClientRect().width):k.outerWidth(),e+=k,c[i[m]].sWidth=x(k-g);b.style.width=x(e);o.remove()}l&&(b.style.width= +x(l));if((l||f)&&!a._reszEvt)b=function(){h(D).bind("resize.DT-"+a.sInstance,Oa(function(){Y(a)}))},d?setTimeout(b,1E3):b(),a._reszEvt=!0}function Fb(a,b){if(!a)return 0;var c=h("<div/>").css("width",x(a)).appendTo(b||I.body),d=c[0].offsetWidth;c.remove();return d}function Gb(a,b){var c=Hb(a,b);if(0>c)return null;var d=a.aoData[c];return!d.nTr?h("<td/>").html(B(a,c,b,"display"))[0]:d.anCells[b]}function Hb(a,b){for(var c,d=-1,e=-1,f=0,g=a.aoData.length;f<g;f++)c=B(a,f,b,"display")+"",c=c.replace($b, +""),c=c.replace(/ /g," "),c.length>d&&(d=c.length,e=f);return e}function x(a){return null===a?"0px":"number"==typeof a?0>a?"0px":a+"px":a.match(/\d$/)?a+"px":a}function V(a){var b,c,d=[],e=a.aoColumns,f,g,j,i;b=a.aaSortingFixed;c=h.isPlainObject(b);var n=[];f=function(a){a.length&&!h.isArray(a[0])?n.push(a):h.merge(n,a)};h.isArray(b)&&f(b);c&&b.pre&&f(b.pre);f(a.aaSorting);c&&b.post&&f(b.post);for(a=0;a<n.length;a++){i=n[a][0];f=e[i].aDataSort;b=0;for(c=f.length;b<c;b++)g=f[b],j=e[g].sType|| +"string",n[a]._idx===k&&(n[a]._idx=h.inArray(n[a][1],e[g].asSorting)),d.push({src:i,col:g,dir:n[a][1],index:n[a]._idx,type:j,formatter:m.ext.type.order[j+"-pre"]})}return d}function mb(a){var b,c,d=[],e=m.ext.type.order,f=a.aoData,g=0,j,i=a.aiDisplayMaster,h;Ga(a);h=V(a);b=0;for(c=h.length;b<c;b++)j=h[b],j.formatter&&g++,Ib(a,j.col);if("ssp"!=y(a)&&0!==h.length){b=0;for(c=i.length;b<c;b++)d[i[b]]=b;g===h.length?i.sort(function(a,b){var c,e,g,j,i=h.length,k=f[a]._aSortData,m=f[b]._aSortData;for(g= +0;g<i;g++)if(j=h[g],c=k[j.col],e=m[j.col],c=c<e?-1:c>e?1:0,0!==c)return"asc"===j.dir?c:-c;c=d[a];e=d[b];return c<e?-1:c>e?1:0}):i.sort(function(a,b){var c,g,j,i,k=h.length,m=f[a]._aSortData,p=f[b]._aSortData;for(j=0;j<k;j++)if(i=h[j],c=m[i.col],g=p[i.col],i=e[i.type+"-"+i.dir]||e["string-"+i.dir],c=i(c,g),0!==c)return c;c=d[a];g=d[b];return c<g?-1:c>g?1:0})}a.bSorted=!0}function Jb(a){for(var b,c,d=a.aoColumns,e=V(a),a=a.oLanguage.oAria,f=0,g=d.length;f<g;f++){c=d[f];var j=c.asSorting;b=c.sTitle.replace(/<.*?>/g, +"");var i=c.nTh;i.removeAttribute("aria-sort");c.bSortable&&(0<e.length&&e[0].col==f?(i.setAttribute("aria-sort","asc"==e[0].dir?"ascending":"descending"),c=j[e[0].index+1]||j[0]):c=j[0],b+="asc"===c?a.sSortAscending:a.sSortDescending);i.setAttribute("aria-label",b)}}function Va(a,b,c,d){var e=a.aaSorting,f=a.aoColumns[b].asSorting,g=function(a,b){var c=a._idx;c===k&&(c=h.inArray(a[1],f));return c+1<f.length?c+1:b?null:0};"number"===typeof e[0]&&(e=a.aaSorting=[e]);c&&a.oFeatures.bSortMulti?(c=h.inArray(b, +G(e,"0")),-1!==c?(b=g(e[c],!0),null===b&&1===e.length&&(b=0),null===b?e.splice(c,1):(e[c][1]=f[b],e[c]._idx=b)):(e.push([b,f[0],0]),e[e.length-1]._idx=0)):e.length&&e[0][0]==b?(b=g(e[0]),e.length=1,e[0][1]=f[b],e[0]._idx=b):(e.length=0,e.push([b,f[0]]),e[0]._idx=0);T(a);"function"==typeof d&&d(a)}function Ma(a,b,c,d){var e=a.aoColumns[c];Wa(b,{},function(b){!1!==e.bSortable&&(a.oFeatures.bProcessing?(C(a,!0),setTimeout(function(){Va(a,c,b.shiftKey,d);"ssp"!==y(a)&&C(a,!1)},0)):Va(a,c,b.shiftKey,d))})} +function va(a){var b=a.aLastSort,c=a.oClasses.sSortColumn,d=V(a),e=a.oFeatures,f,g;if(e.bSort&&e.bSortClasses){e=0;for(f=b.length;e<f;e++)g=b[e].src,h(G(a.aoData,"anCells",g)).removeClass(c+(2>e?e+1:3));e=0;for(f=d.length;e<f;e++)g=d[e].src,h(G(a.aoData,"anCells",g)).addClass(c+(2>e?e+1:3))}a.aLastSort=d}function Ib(a,b){var c=a.aoColumns[b],d=m.ext.order[c.sSortDataType],e;d&&(e=d.call(a.oInstance,a,b,$(a,b)));for(var f,g=m.ext.type.order[c.sType+"-pre"],j=0,i=a.aoData.length;j<i;j++)if(c=a.aoData[j], +c._aSortData||(c._aSortData=[]),!c._aSortData[b]||d)f=d?e[j]:B(a,j,b,"sort"),c._aSortData[b]=g?g(f):f}function wa(a){if(a.oFeatures.bStateSave&&!a.bDestroying){var b={time:+new Date,start:a._iDisplayStart,length:a._iDisplayLength,order:h.extend(!0,[],a.aaSorting),search:Ab(a.oPreviousSearch),columns:h.map(a.aoColumns,function(b,d){return{visible:b.bVisible,search:Ab(a.aoPreSearchCols[d])}})};u(a,"aoStateSaveParams","stateSaveParams",[a,b]);a.oSavedState=b;a.fnStateSaveCallback.call(a.oInstance,a, +b)}}function Kb(a){var b,c,d=a.aoColumns;if(a.oFeatures.bStateSave){var e=a.fnStateLoadCallback.call(a.oInstance,a);if(e&&e.time&&(b=u(a,"aoStateLoadParams","stateLoadParams",[a,e]),-1===h.inArray(!1,b)&&(b=a.iStateDuration,!(0<b&&e.time<+new Date-1E3*b)&&d.length===e.columns.length))){a.oLoadedState=h.extend(!0,{},e);e.start!==k&&(a._iDisplayStart=e.start,a.iInitDisplayStart=e.start);e.length!==k&&(a._iDisplayLength=e.length);e.order!==k&&(a.aaSorting=[],h.each(e.order,function(b,c){a.aaSorting.push(c[0]>= +d.length?[0,c[1]]:c)}));e.search!==k&&h.extend(a.oPreviousSearch,Bb(e.search));b=0;for(c=e.columns.length;b<c;b++){var f=e.columns[b];f.visible!==k&&(d[b].bVisible=f.visible);f.search!==k&&h.extend(a.aoPreSearchCols[b],Bb(f.search))}u(a,"aoStateLoaded","stateLoaded",[a,e])}}}function xa(a){var b=m.settings,a=h.inArray(a,G(b,"nTable"));return-1!==a?b[a]:null}function L(a,b,c,d){c="DataTables warning: "+(a?"table id="+a.sTableId+" - ":"")+c;d&&(c+=". For more information about this error, please see http://datatables.net/tn/"+ +d);if(b)D.console&&console.log&&console.log(c);else if(b=m.ext,b=b.sErrMode||b.errMode,a&&u(a,null,"error",[a,d,c]),"alert"==b)alert(c);else{if("throw"==b)throw Error(c);"function"==typeof b&&b(a,d,c)}}function E(a,b,c,d){h.isArray(c)?h.each(c,function(c,d){h.isArray(d)?E(a,b,d[0],d[1]):E(a,b,d)}):(d===k&&(d=c),b[c]!==k&&(a[d]=b[c]))}function Lb(a,b,c){var d,e;for(e in b)b.hasOwnProperty(e)&&(d=b[e],h.isPlainObject(d)?(h.isPlainObject(a[e])||(a[e]={}),h.extend(!0,a[e],d)):a[e]=c&&"data"!==e&&"aaData"!== +e&&h.isArray(d)?d.slice():d);return a}function Wa(a,b,c){h(a).bind("click.DT",b,function(b){a.blur();c(b)}).bind("keypress.DT",b,function(a){13===a.which&&(a.preventDefault(),c(a))}).bind("selectstart.DT",function(){return!1})}function z(a,b,c,d){c&&a[b].push({fn:c,sName:d})}function u(a,b,c,d){var e=[];b&&(e=h.map(a[b].slice().reverse(),function(b){return b.fn.apply(a.oInstance,d)}));null!==c&&(b=h.Event(c+".dt"),h(a.nTable).trigger(b,d),e.push(b.result));return e}function Sa(a){var b=a._iDisplayStart, +c=a.fnDisplayEnd(),d=a._iDisplayLength;b>=c&&(b=c-d);b-=b%d;if(-1===d||0>b)b=0;a._iDisplayStart=b}function Na(a,b){var c=a.renderer,d=m.ext.renderer[b];return h.isPlainObject(c)&&c[b]?d[c[b]]||d._:"string"===typeof c?d[c]||d._:d._}function y(a){return a.oFeatures.bServerSide?"ssp":a.ajax||a.sAjaxSource?"ajax":"dom"}function ya(a,b){var c=[],c=Mb.numbers_length,d=Math.floor(c/2);b<=c?c=W(0,b):a<=d?(c=W(0,c-2),c.push("ellipsis"),c.push(b-1)):(a>=b-1-d?c=W(b-(c-2),b):(c=W(a-d+2,a+d-1),c.push("ellipsis"), +c.push(b-1)),c.splice(0,0,"ellipsis"),c.splice(0,0,0));c.DT_el="span";return c}function db(a){h.each({num:function(b){return za(b,a)},"num-fmt":function(b){return za(b,a,Xa)},"html-num":function(b){return za(b,a,Aa)},"html-num-fmt":function(b){return za(b,a,Aa,Xa)}},function(b,c){v.type.order[b+a+"-pre"]=c;b.match(/^html\-/)&&(v.type.search[b+a]=v.type.search.html)})}function Nb(a){return function(){var b=[xa(this[m.ext.iApiIndex])].concat(Array.prototype.slice.call(arguments));return m.ext.internal[a].apply(this, +b)}}var m=function(a){this.$=function(a,b){return this.api(!0).$(a,b)};this._=function(a,b){return this.api(!0).rows(a,b).data()};this.api=function(a){return a?new r(xa(this[v.iApiIndex])):new r(this)};this.fnAddData=function(a,b){var c=this.api(!0),d=h.isArray(a)&&(h.isArray(a[0])||h.isPlainObject(a[0]))?c.rows.add(a):c.row.add(a);(b===k||b)&&c.draw();return d.flatten().toArray()};this.fnAdjustColumnSizing=function(a){var b=this.api(!0).columns.adjust(),c=b.settings()[0],d=c.oScroll;a===k||a?b.draw(!1): +(""!==d.sX||""!==d.sY)&&ka(c)};this.fnClearTable=function(a){var b=this.api(!0).clear();(a===k||a)&&b.draw()};this.fnClose=function(a){this.api(!0).row(a).child.hide()};this.fnDeleteRow=function(a,b,c){var d=this.api(!0),a=d.rows(a),e=a.settings()[0],h=e.aoData[a[0][0]];a.remove();b&&b.call(this,e,h);(c===k||c)&&d.draw();return h};this.fnDestroy=function(a){this.api(!0).destroy(a)};this.fnDraw=function(a){this.api(!0).draw(a)};this.fnFilter=function(a,b,c,d,e,h){e=this.api(!0);null===b||b===k?e.search(a, +c,d,h):e.column(b).search(a,c,d,h);e.draw()};this.fnGetData=function(a,b){var c=this.api(!0);if(a!==k){var d=a.nodeName?a.nodeName.toLowerCase():"";return b!==k||"td"==d||"th"==d?c.cell(a,b).data():c.row(a).data()||null}return c.data().toArray()};this.fnGetNodes=function(a){var b=this.api(!0);return a!==k?b.row(a).node():b.rows().nodes().flatten().toArray()};this.fnGetPosition=function(a){var b=this.api(!0),c=a.nodeName.toUpperCase();return"TR"==c?b.row(a).index():"TD"==c||"TH"==c?(a=b.cell(a).index(), +[a.row,a.columnVisible,a.column]):null};this.fnIsOpen=function(a){return this.api(!0).row(a).child.isShown()};this.fnOpen=function(a,b,c){return this.api(!0).row(a).child(b,c).show().child()[0]};this.fnPageChange=function(a,b){var c=this.api(!0).page(a);(b===k||b)&&c.draw(!1)};this.fnSetColumnVis=function(a,b,c){a=this.api(!0).column(a).visible(b);(c===k||c)&&a.columns.adjust().draw()};this.fnSettings=function(){return xa(this[v.iApiIndex])};this.fnSort=function(a){this.api(!0).order(a).draw()};this.fnSortListener= +function(a,b,c){this.api(!0).order.listener(a,b,c)};this.fnUpdate=function(a,b,c,d,e){var h=this.api(!0);c===k||null===c?h.row(b).data(a):h.cell(b,c).data(a);(e===k||e)&&h.columns.adjust();(d===k||d)&&h.draw();return 0};this.fnVersionCheck=v.fnVersionCheck;var b=this,c=a===k,d=this.length;c&&(a={});this.oApi=this.internal=v.internal;for(var e in m.ext.internal)e&&(this[e]=Nb(e));this.each(function(){var e={},e=1<d?Lb(e,a,!0):a,g=0,j,i=this.getAttribute("id"),n=!1,l=m.defaults,q=h(this);if("table"!= +this.nodeName.toLowerCase())L(null,0,"Non-table node initialisation ("+this.nodeName+")",2);else{eb(l);fb(l.column);K(l,l,!0);K(l.column,l.column,!0);K(l,h.extend(e,q.data()));var t=m.settings,g=0;for(j=t.length;g<j;g++){var p=t[g];if(p.nTable==this||p.nTHead.parentNode==this||p.nTFoot&&p.nTFoot.parentNode==this){g=e.bRetrieve!==k?e.bRetrieve:l.bRetrieve;if(c||g)return p.oInstance;if(e.bDestroy!==k?e.bDestroy:l.bDestroy){p.oInstance.fnDestroy();break}else{L(p,0,"Cannot reinitialise DataTable",3); +return}}if(p.sTableId==this.id){t.splice(g,1);break}}if(null===i||""===i)this.id=i="DataTables_Table_"+m.ext._unique++;var o=h.extend(!0,{},m.models.oSettings,{sDestroyWidth:q[0].style.width,sInstance:i,sTableId:i});o.nTable=this;o.oApi=b.internal;o.oInit=e;t.push(o);o.oInstance=1===b.length?b:q.dataTable();eb(e);e.oLanguage&&Da(e.oLanguage);e.aLengthMenu&&!e.iDisplayLength&&(e.iDisplayLength=h.isArray(e.aLengthMenu[0])?e.aLengthMenu[0][0]:e.aLengthMenu[0]);e=Lb(h.extend(!0,{},l),e);E(o.oFeatures, +e,"bPaginate bLengthChange bFilter bSort bSortMulti bInfo bProcessing bAutoWidth bSortClasses bServerSide bDeferRender".split(" "));E(o,e,["asStripeClasses","ajax","fnServerData","fnFormatNumber","sServerMethod","aaSorting","aaSortingFixed","aLengthMenu","sPaginationType","sAjaxSource","sAjaxDataProp","iStateDuration","sDom","bSortCellsTop","iTabIndex","fnStateLoadCallback","fnStateSaveCallback","renderer","searchDelay","rowId",["iCookieDuration","iStateDuration"],["oSearch","oPreviousSearch"],["aoSearchCols", +"aoPreSearchCols"],["iDisplayLength","_iDisplayLength"],["bJQueryUI","bJUI"]]);E(o.oScroll,e,[["sScrollX","sX"],["sScrollXInner","sXInner"],["sScrollY","sY"],["bScrollCollapse","bCollapse"]]);E(o.oLanguage,e,"fnInfoCallback");z(o,"aoDrawCallback",e.fnDrawCallback,"user");z(o,"aoServerParams",e.fnServerParams,"user");z(o,"aoStateSaveParams",e.fnStateSaveParams,"user");z(o,"aoStateLoadParams",e.fnStateLoadParams,"user");z(o,"aoStateLoaded",e.fnStateLoaded,"user");z(o,"aoRowCallback",e.fnRowCallback, +"user");z(o,"aoRowCreatedCallback",e.fnCreatedRow,"user");z(o,"aoHeaderCallback",e.fnHeaderCallback,"user");z(o,"aoFooterCallback",e.fnFooterCallback,"user");z(o,"aoInitComplete",e.fnInitComplete,"user");z(o,"aoPreDrawCallback",e.fnPreDrawCallback,"user");o.rowIdFn=Q(e.rowId);gb(o);i=o.oClasses;e.bJQueryUI?(h.extend(i,m.ext.oJUIClasses,e.oClasses),e.sDom===l.sDom&&"lfrtip"===l.sDom&&(o.sDom='<"H"lfr>t<"F"ip>'),o.renderer)?h.isPlainObject(o.renderer)&&!o.renderer.header&&(o.renderer.header="jqueryui"): +o.renderer="jqueryui":h.extend(i,m.ext.classes,e.oClasses);q.addClass(i.sTable);o.iInitDisplayStart===k&&(o.iInitDisplayStart=e.iDisplayStart,o._iDisplayStart=e.iDisplayStart);null!==e.iDeferLoading&&(o.bDeferLoading=!0,g=h.isArray(e.iDeferLoading),o._iRecordsDisplay=g?e.iDeferLoading[0]:e.iDeferLoading,o._iRecordsTotal=g?e.iDeferLoading[1]:e.iDeferLoading);var r=o.oLanguage;h.extend(!0,r,e.oLanguage);""!==r.sUrl&&(h.ajax({dataType:"json",url:r.sUrl,success:function(a){Da(a);K(l.oLanguage,a);h.extend(true, +r,a);ga(o)},error:function(){ga(o)}}),n=!0);null===e.asStripeClasses&&(o.asStripeClasses=[i.sStripeOdd,i.sStripeEven]);var g=o.asStripeClasses,v=q.children("tbody").find("tr").eq(0);-1!==h.inArray(!0,h.map(g,function(a){return v.hasClass(a)}))&&(h("tbody tr",this).removeClass(g.join(" ")),o.asDestroyStripes=g.slice());t=[];g=this.getElementsByTagName("thead");0!==g.length&&(da(o.aoHeader,g[0]),t=qa(o));if(null===e.aoColumns){p=[];g=0;for(j=t.length;g<j;g++)p.push(null)}else p=e.aoColumns;g=0;for(j= +p.length;g<j;g++)Ea(o,t?t[g]:null);ib(o,e.aoColumnDefs,p,function(a,b){ja(o,a,b)});if(v.length){var s=function(a,b){return a.getAttribute("data-"+b)!==null?b:null};h(v[0]).children("th, td").each(function(a,b){var c=o.aoColumns[a];if(c.mData===a){var d=s(b,"sort")||s(b,"order"),e=s(b,"filter")||s(b,"search");if(d!==null||e!==null){c.mData={_:a+".display",sort:d!==null?a+".@data-"+d:k,type:d!==null?a+".@data-"+d:k,filter:e!==null?a+".@data-"+e:k};ja(o,a)}}})}var w=o.oFeatures;e.bStateSave&&(w.bStateSave= +!0,Kb(o,e),z(o,"aoDrawCallback",wa,"state_save"));if(e.aaSorting===k){t=o.aaSorting;g=0;for(j=t.length;g<j;g++)t[g][1]=o.aoColumns[g].asSorting[0]}va(o);w.bSort&&z(o,"aoDrawCallback",function(){if(o.bSorted){var a=V(o),b={};h.each(a,function(a,c){b[c.src]=c.dir});u(o,null,"order",[o,a,b]);Jb(o)}});z(o,"aoDrawCallback",function(){(o.bSorted||y(o)==="ssp"||w.bDeferRender)&&va(o)},"sc");g=q.children("caption").each(function(){this._captionSide=q.css("caption-side")});j=q.children("thead");0===j.length&& +(j=h("<thead/>").appendTo(this));o.nTHead=j[0];j=q.children("tbody");0===j.length&&(j=h("<tbody/>").appendTo(this));o.nTBody=j[0];j=q.children("tfoot");if(0===j.length&&0<g.length&&(""!==o.oScroll.sX||""!==o.oScroll.sY))j=h("<tfoot/>").appendTo(this);0===j.length||0===j.children().length?q.addClass(i.sNoFooter):0<j.length&&(o.nTFoot=j[0],da(o.aoFooter,o.nTFoot));if(e.aaData)for(g=0;g<e.aaData.length;g++)N(o,e.aaData[g]);else(o.bDeferLoading||"dom"==y(o))&&ma(o,h(o.nTBody).children("tr"));o.aiDisplay= +o.aiDisplayMaster.slice();o.bInitialised=!0;!1===n&&ga(o)}});b=null;return this},v,r,p,s,Ya={},Ob=/[\r\n]/g,Aa=/<.*?>/g,ac=/^[\w\+\-]/,bc=/[\w\+\-]$/,cc=RegExp("(\\/|\\.|\\*|\\+|\\?|\\||\\(|\\)|\\[|\\]|\\{|\\}|\\\\|\\$|\\^|\\-)","g"),Xa=/[',$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfk]/gi,M=function(a){return!a||!0===a||"-"===a?!0:!1},Pb=function(a){var b=parseInt(a,10);return!isNaN(b)&&isFinite(a)?b:null},Qb=function(a,b){Ya[b]||(Ya[b]=RegExp(Qa(b),"g"));return"string"===typeof a&&"."!==b?a.replace(/\./g, +"").replace(Ya[b],"."):a},Za=function(a,b,c){var d="string"===typeof a;if(M(a))return!0;b&&d&&(a=Qb(a,b));c&&d&&(a=a.replace(Xa,""));return!isNaN(parseFloat(a))&&isFinite(a)},Rb=function(a,b,c){return M(a)?!0:!(M(a)||"string"===typeof a)?null:Za(a.replace(Aa,""),b,c)?!0:null},G=function(a,b,c){var d=[],e=0,f=a.length;if(c!==k)for(;e<f;e++)a[e]&&a[e][b]&&d.push(a[e][b][c]);else for(;e<f;e++)a[e]&&d.push(a[e][b]);return d},ha=function(a,b,c,d){var e=[],f=0,g=b.length;if(d!==k)for(;f<g;f++)a[b[f]][c]&& +e.push(a[b[f]][c][d]);else for(;f<g;f++)e.push(a[b[f]][c]);return e},W=function(a,b){var c=[],d;b===k?(b=0,d=a):(d=b,b=a);for(var e=b;e<d;e++)c.push(e);return c},Sb=function(a){for(var b=[],c=0,d=a.length;c<d;c++)a[c]&&b.push(a[c]);return b},pa=function(a){var b=[],c,d,e=a.length,f,g=0;d=0;a:for(;d<e;d++){c=a[d];for(f=0;f<g;f++)if(b[f]===c)continue a;b.push(c);g++}return b};m.util={throttle:function(a,b){var c=b!==k?b:200,d,e;return function(){var b=this,g=+new Date,h=arguments;d&&g<d+c?(clearTimeout(e), +e=setTimeout(function(){d=k;a.apply(b,h)},c)):(d=g,a.apply(b,h))}},escapeRegex:function(a){return a.replace(cc,"\\$1")}};var A=function(a,b,c){a[b]!==k&&(a[c]=a[b])},ba=/\[.*?\]$/,U=/\(\)$/,Qa=m.util.escapeRegex,ua=h("<div>")[0],Zb=ua.textContent!==k,$b=/<.*?>/g,Oa=m.util.throttle,Tb=[],w=Array.prototype,dc=function(a){var b,c,d=m.settings,e=h.map(d,function(a){return a.nTable});if(a){if(a.nTable&&a.oApi)return[a];if(a.nodeName&&"table"===a.nodeName.toLowerCase())return b=h.inArray(a,e),-1!==b?[d[b]]: +null;if(a&&"function"===typeof a.settings)return a.settings().toArray();"string"===typeof a?c=h(a):a instanceof h&&(c=a)}else return[];if(c)return c.map(function(){b=h.inArray(this,e);return-1!==b?d[b]:null}).toArray()};r=function(a,b){if(!(this instanceof r))return new r(a,b);var c=[],d=function(a){(a=dc(a))&&(c=c.concat(a))};if(h.isArray(a))for(var e=0,f=a.length;e<f;e++)d(a[e]);else d(a);this.context=pa(c);b&&h.merge(this,b);this.selector={rows:null,cols:null,opts:null};r.extend(this,this,Tb)}; +m.Api=r;h.extend(r.prototype,{any:function(){return 0!==this.count()},concat:w.concat,context:[],count:function(){return this.flatten().length},each:function(a){for(var b=0,c=this.length;b<c;b++)a.call(this,this[b],b,this);return this},eq:function(a){var b=this.context;return b.length>a?new r(b[a],this[a]):null},filter:function(a){var b=[];if(w.filter)b=w.filter.call(this,a,this);else for(var c=0,d=this.length;c<d;c++)a.call(this,this[c],c,this)&&b.push(this[c]);return new r(this.context,b)},flatten:function(){var a= +[];return new r(this.context,a.concat.apply(a,this.toArray()))},join:w.join,indexOf:w.indexOf||function(a,b){for(var c=b||0,d=this.length;c<d;c++)if(this[c]===a)return c;return-1},iterator:function(a,b,c,d){var e=[],f,g,h,i,n,l=this.context,m,t,p=this.selector;"string"===typeof a&&(d=c,c=b,b=a,a=!1);g=0;for(h=l.length;g<h;g++){var o=new r(l[g]);if("table"===b)f=c.call(o,l[g],g),f!==k&&e.push(f);else if("columns"===b||"rows"===b)f=c.call(o,l[g],this[g],g),f!==k&&e.push(f);else if("column"===b||"column-rows"=== +b||"row"===b||"cell"===b){t=this[g];"column-rows"===b&&(m=Ba(l[g],p.opts));i=0;for(n=t.length;i<n;i++)f=t[i],f="cell"===b?c.call(o,l[g],f.row,f.column,g,i):c.call(o,l[g],f,g,i,m),f!==k&&e.push(f)}}return e.length||d?(a=new r(l,a?e.concat.apply([],e):e),b=a.selector,b.rows=p.rows,b.cols=p.cols,b.opts=p.opts,a):this},lastIndexOf:w.lastIndexOf||function(a,b){return this.indexOf.apply(this.toArray.reverse(),arguments)},length:0,map:function(a){var b=[];if(w.map)b=w.map.call(this,a,this);else for(var c= +0,d=this.length;c<d;c++)b.push(a.call(this,this[c],c));return new r(this.context,b)},pluck:function(a){return this.map(function(b){return b[a]})},pop:w.pop,push:w.push,reduce:w.reduce||function(a,b){return hb(this,a,b,0,this.length,1)},reduceRight:w.reduceRight||function(a,b){return hb(this,a,b,this.length-1,-1,-1)},reverse:w.reverse,selector:null,shift:w.shift,sort:w.sort,splice:w.splice,toArray:function(){return w.slice.call(this)},to$:function(){return h(this)},toJQuery:function(){return h(this)}, +unique:function(){return new r(this.context,pa(this))},unshift:w.unshift});r.extend=function(a,b,c){if(c.length&&b&&(b instanceof r||b.__dt_wrapper)){var d,e,f,g=function(a,b,c){return function(){var d=b.apply(a,arguments);r.extend(d,d,c.methodExt);return d}};d=0;for(e=c.length;d<e;d++)f=c[d],b[f.name]="function"===typeof f.val?g(a,f.val,f):h.isPlainObject(f.val)?{}:f.val,b[f.name].__dt_wrapper=!0,r.extend(a,b[f.name],f.propExt)}};r.register=p=function(a,b){if(h.isArray(a))for(var c=0,d=a.length;c< +d;c++)r.register(a[c],b);else for(var e=a.split("."),f=Tb,g,j,c=0,d=e.length;c<d;c++){g=(j=-1!==e[c].indexOf("()"))?e[c].replace("()",""):e[c];var i;a:{i=0;for(var n=f.length;i<n;i++)if(f[i].name===g){i=f[i];break a}i=null}i||(i={name:g,val:{},methodExt:[],propExt:[]},f.push(i));c===d-1?i.val=b:f=j?i.methodExt:i.propExt}};r.registerPlural=s=function(a,b,c){r.register(a,c);r.register(b,function(){var a=c.apply(this,arguments);return a===this?this:a instanceof r?a.length?h.isArray(a[0])?new r(a.context, +a[0]):a[0]:k:a})};p("tables()",function(a){var b;if(a){b=r;var c=this.context;if("number"===typeof a)a=[c[a]];else var d=h.map(c,function(a){return a.nTable}),a=h(d).filter(a).map(function(){var a=h.inArray(this,d);return c[a]}).toArray();b=new b(a)}else b=this;return b});p("table()",function(a){var a=this.tables(a),b=a.context;return b.length?new r(b[0]):a});s("tables().nodes()","table().node()",function(){return this.iterator("table",function(a){return a.nTable},1)});s("tables().body()","table().body()", +function(){return this.iterator("table",function(a){return a.nTBody},1)});s("tables().header()","table().header()",function(){return this.iterator("table",function(a){return a.nTHead},1)});s("tables().footer()","table().footer()",function(){return this.iterator("table",function(a){return a.nTFoot},1)});s("tables().containers()","table().container()",function(){return this.iterator("table",function(a){return a.nTableWrapper},1)});p("draw()",function(a){return this.iterator("table",function(b){"page"=== +a?O(b):("string"===typeof a&&(a="full-hold"===a?!1:!0),T(b,!1===a))})});p("page()",function(a){return a===k?this.page.info().page:this.iterator("table",function(b){Ta(b,a)})});p("page.info()",function(){if(0===this.context.length)return k;var a=this.context[0],b=a._iDisplayStart,c=a.oFeatures.bPaginate?a._iDisplayLength:-1,d=a.fnRecordsDisplay(),e=-1===c;return{page:e?0:Math.floor(b/c),pages:e?1:Math.ceil(d/c),start:b,end:a.fnDisplayEnd(),length:c,recordsTotal:a.fnRecordsTotal(),recordsDisplay:d, +serverSide:"ssp"===y(a)}});p("page.len()",function(a){return a===k?0!==this.context.length?this.context[0]._iDisplayLength:k:this.iterator("table",function(b){Ra(b,a)})});var Ub=function(a,b,c){if(c){var d=new r(a);d.one("draw",function(){c(d.ajax.json())})}if("ssp"==y(a))T(a,b);else{C(a,!0);var e=a.jqXHR;e&&4!==e.readyState&&e.abort();ra(a,[],function(c){na(a);for(var c=sa(a,c),d=0,e=c.length;d<e;d++)N(a,c[d]);T(a,b);C(a,!1)})}};p("ajax.json()",function(){var a=this.context;if(0<a.length)return a[0].json}); +p("ajax.params()",function(){var a=this.context;if(0<a.length)return a[0].oAjaxData});p("ajax.reload()",function(a,b){return this.iterator("table",function(c){Ub(c,!1===b,a)})});p("ajax.url()",function(a){var b=this.context;if(a===k){if(0===b.length)return k;b=b[0];return b.ajax?h.isPlainObject(b.ajax)?b.ajax.url:b.ajax:b.sAjaxSource}return this.iterator("table",function(b){h.isPlainObject(b.ajax)?b.ajax.url=a:b.ajax=a})});p("ajax.url().load()",function(a,b){return this.iterator("table",function(c){Ub(c, +!1===b,a)})});var $a=function(a,b,c,d,e){var f=[],g,j,i,n,l,m;i=typeof b;if(!b||"string"===i||"function"===i||b.length===k)b=[b];i=0;for(n=b.length;i<n;i++){j=b[i]&&b[i].split?b[i].split(","):[b[i]];l=0;for(m=j.length;l<m;l++)(g=c("string"===typeof j[l]?h.trim(j[l]):j[l]))&&g.length&&(f=f.concat(g))}a=v.selector[a];if(a.length){i=0;for(n=a.length;i<n;i++)f=a[i](d,e,f)}return pa(f)},ab=function(a){a||(a={});a.filter&&a.search===k&&(a.search=a.filter);return h.extend({search:"none",order:"current", +page:"all"},a)},bb=function(a){for(var b=0,c=a.length;b<c;b++)if(0<a[b].length)return a[0]=a[b],a[0].length=1,a.length=1,a.context=[a.context[b]],a;a.length=0;return a},Ba=function(a,b){var c,d,e,f=[],g=a.aiDisplay;c=a.aiDisplayMaster;var j=b.search;d=b.order;e=b.page;if("ssp"==y(a))return"removed"===j?[]:W(0,c.length);if("current"==e){c=a._iDisplayStart;for(d=a.fnDisplayEnd();c<d;c++)f.push(g[c])}else if("current"==d||"applied"==d)f="none"==j?c.slice():"applied"==j?g.slice():h.map(c,function(a){return-1=== +h.inArray(a,g)?a:null});else if("index"==d||"original"==d){c=0;for(d=a.aoData.length;c<d;c++)"none"==j?f.push(c):(e=h.inArray(c,g),(-1===e&&"removed"==j||0<=e&&"applied"==j)&&f.push(c))}return f};p("rows()",function(a,b){a===k?a="":h.isPlainObject(a)&&(b=a,a="");var b=ab(b),c=this.iterator("table",function(c){var e=b;return $a("row",a,function(a){var b=Pb(a);if(b!==null&&!e)return[b];var j=Ba(c,e);if(b!==null&&h.inArray(b,j)!==-1)return[b];if(!a)return j;if(typeof a==="function")return h.map(j,function(b){var e= +c.aoData[b];return a(b,e._aData,e.nTr)?b:null});b=Sb(ha(c.aoData,j,"nTr"));if(a.nodeName){if(a._DT_RowIndex!==k)return[a._DT_RowIndex];if(a._DT_CellIndex)return[a._DT_CellIndex.row];b=h(a).closest("*[data-dt-row]");return b.length?[b.data("dt-row")]:[]}if(typeof a==="string"&&a.charAt(0)==="#"){j=c.aIds[a.replace(/^#/,"")];if(j!==k)return[j.idx]}return h(b).filter(a).map(function(){return this._DT_RowIndex}).toArray()},c,e)},1);c.selector.rows=a;c.selector.opts=b;return c});p("rows().nodes()",function(){return this.iterator("row", +function(a,b){return a.aoData[b].nTr||k},1)});p("rows().data()",function(){return this.iterator(!0,"rows",function(a,b){return ha(a.aoData,b,"_aData")},1)});s("rows().cache()","row().cache()",function(a){return this.iterator("row",function(b,c){var d=b.aoData[c];return"search"===a?d._aFilterData:d._aSortData},1)});s("rows().invalidate()","row().invalidate()",function(a){return this.iterator("row",function(b,c){ca(b,c,a)})});s("rows().indexes()","row().index()",function(){return this.iterator("row", +function(a,b){return b},1)});s("rows().ids()","row().id()",function(a){for(var b=[],c=this.context,d=0,e=c.length;d<e;d++)for(var f=0,g=this[d].length;f<g;f++){var h=c[d].rowIdFn(c[d].aoData[this[d][f]]._aData);b.push((!0===a?"#":"")+h)}return new r(c,b)});s("rows().remove()","row().remove()",function(){var a=this;this.iterator("row",function(b,c,d){var e=b.aoData,f=e[c],g,h,i,n,l;e.splice(c,1);g=0;for(h=e.length;g<h;g++)if(i=e[g],l=i.anCells,null!==i.nTr&&(i.nTr._DT_RowIndex=g),null!==l){i=0;for(n= +l.length;i<n;i++)l[i]._DT_CellIndex.row=g}oa(b.aiDisplayMaster,c);oa(b.aiDisplay,c);oa(a[d],c,!1);Sa(b);c=b.rowIdFn(f._aData);c!==k&&delete b.aIds[c]});this.iterator("table",function(a){for(var c=0,d=a.aoData.length;c<d;c++)a.aoData[c].idx=c});return this});p("rows.add()",function(a){var b=this.iterator("table",function(b){var c,f,g,h=[];f=0;for(g=a.length;f<g;f++)c=a[f],c.nodeName&&"TR"===c.nodeName.toUpperCase()?h.push(ma(b,c)[0]):h.push(N(b,c));return h},1),c=this.rows(-1);c.pop();h.merge(c,b); +return c});p("row()",function(a,b){return bb(this.rows(a,b))});p("row().data()",function(a){var b=this.context;if(a===k)return b.length&&this.length?b[0].aoData[this[0]]._aData:k;b[0].aoData[this[0]]._aData=a;ca(b[0],this[0],"data");return this});p("row().node()",function(){var a=this.context;return a.length&&this.length?a[0].aoData[this[0]].nTr||null:null});p("row.add()",function(a){a instanceof h&&a.length&&(a=a[0]);var b=this.iterator("table",function(b){return a.nodeName&&"TR"===a.nodeName.toUpperCase()? +ma(b,a)[0]:N(b,a)});return this.row(b[0])});var cb=function(a,b){var c=a.context;if(c.length&&(c=c[0].aoData[b!==k?b:a[0]])&&c._details)c._details.remove(),c._detailsShow=k,c._details=k},Vb=function(a,b){var c=a.context;if(c.length&&a.length){var d=c[0].aoData[a[0]];if(d._details){(d._detailsShow=b)?d._details.insertAfter(d.nTr):d._details.detach();var e=c[0],f=new r(e),g=e.aoData;f.off("draw.dt.DT_details column-visibility.dt.DT_details destroy.dt.DT_details");0<G(g,"_details").length&&(f.on("draw.dt.DT_details", +function(a,b){e===b&&f.rows({page:"current"}).eq(0).each(function(a){a=g[a];a._detailsShow&&a._details.insertAfter(a.nTr)})}),f.on("column-visibility.dt.DT_details",function(a,b){if(e===b)for(var c,d=aa(b),f=0,h=g.length;f<h;f++)c=g[f],c._details&&c._details.children("td[colspan]").attr("colspan",d)}),f.on("destroy.dt.DT_details",function(a,b){if(e===b)for(var c=0,d=g.length;c<d;c++)g[c]._details&&cb(f,c)}))}}};p("row().child()",function(a,b){var c=this.context;if(a===k)return c.length&&this.length? +c[0].aoData[this[0]]._details:k;if(!0===a)this.child.show();else if(!1===a)cb(this);else if(c.length&&this.length){var d=c[0],c=c[0].aoData[this[0]],e=[],f=function(a,b){if(h.isArray(a)||a instanceof h)for(var c=0,k=a.length;c<k;c++)f(a[c],b);else a.nodeName&&"tr"===a.nodeName.toLowerCase()?e.push(a):(c=h("<tr><td/></tr>").addClass(b),h("td",c).addClass(b).html(a)[0].colSpan=aa(d),e.push(c[0]))};f(a,b);c._details&&c._details.remove();c._details=h(e);c._detailsShow&&c._details.insertAfter(c.nTr)}return this}); +p(["row().child.show()","row().child().show()"],function(){Vb(this,!0);return this});p(["row().child.hide()","row().child().hide()"],function(){Vb(this,!1);return this});p(["row().child.remove()","row().child().remove()"],function(){cb(this);return this});p("row().child.isShown()",function(){var a=this.context;return a.length&&this.length?a[0].aoData[this[0]]._detailsShow||!1:!1});var ec=/^(.+):(name|visIdx|visible)$/,Wb=function(a,b,c,d,e){for(var c=[],d=0,f=e.length;d<f;d++)c.push(B(a,e[d],b)); +return c};p("columns()",function(a,b){a===k?a="":h.isPlainObject(a)&&(b=a,a="");var b=ab(b),c=this.iterator("table",function(c){var e=a,f=b,g=c.aoColumns,j=G(g,"sName"),i=G(g,"nTh");return $a("column",e,function(a){var b=Pb(a);if(a==="")return W(g.length);if(b!==null)return[b>=0?b:g.length+b];if(typeof a==="function"){var e=Ba(c,f);return h.map(g,function(b,f){return a(f,Wb(c,f,0,0,e),i[f])?f:null})}var k=typeof a==="string"?a.match(ec):"";if(k)switch(k[2]){case "visIdx":case "visible":b=parseInt(k[1], +10);if(b<0){var m=h.map(g,function(a,b){return a.bVisible?b:null});return[m[m.length+b]]}return[Z(c,b)];case "name":return h.map(j,function(a,b){return a===k[1]?b:null});default:return[]}if(a.nodeName&&a._DT_CellIndex)return[a._DT_CellIndex.column];b=h(i).filter(a).map(function(){return h.inArray(this,i)}).toArray();if(b.length||!a.nodeName)return b;b=h(a).closest("*[data-dt-column]");return b.length?[b.data("dt-column")]:[]},c,f)},1);c.selector.cols=a;c.selector.opts=b;return c});s("columns().header()", +"column().header()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].nTh},1)});s("columns().footer()","column().footer()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].nTf},1)});s("columns().data()","column().data()",function(){return this.iterator("column-rows",Wb,1)});s("columns().dataSrc()","column().dataSrc()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].mData},1)});s("columns().cache()","column().cache()", +function(a){return this.iterator("column-rows",function(b,c,d,e,f){return ha(b.aoData,f,"search"===a?"_aFilterData":"_aSortData",c)},1)});s("columns().nodes()","column().nodes()",function(){return this.iterator("column-rows",function(a,b,c,d,e){return ha(a.aoData,e,"anCells",b)},1)});s("columns().visible()","column().visible()",function(a,b){var c=this.iterator("column",function(b,c){if(a===k)return b.aoColumns[c].bVisible;var f=b.aoColumns,g=f[c],j=b.aoData,i,n,l;if(a!==k&&g.bVisible!==a){if(a){var m= +h.inArray(!0,G(f,"bVisible"),c+1);i=0;for(n=j.length;i<n;i++)l=j[i].nTr,f=j[i].anCells,l&&l.insertBefore(f[c],f[m]||null)}else h(G(b.aoData,"anCells",c)).detach();g.bVisible=a;ea(b,b.aoHeader);ea(b,b.aoFooter);wa(b)}});a!==k&&(this.iterator("column",function(c,e){u(c,null,"column-visibility",[c,e,a,b])}),(b===k||b)&&this.columns.adjust());return c});s("columns().indexes()","column().index()",function(a){return this.iterator("column",function(b,c){return"visible"===a?$(b,c):c},1)});p("columns.adjust()", +function(){return this.iterator("table",function(a){Y(a)},1)});p("column.index()",function(a,b){if(0!==this.context.length){var c=this.context[0];if("fromVisible"===a||"toData"===a)return Z(c,b);if("fromData"===a||"toVisible"===a)return $(c,b)}});p("column()",function(a,b){return bb(this.columns(a,b))});p("cells()",function(a,b,c){h.isPlainObject(a)&&(a.row===k?(c=a,a=null):(c=b,b=null));h.isPlainObject(b)&&(c=b,b=null);if(null===b||b===k)return this.iterator("table",function(b){var d=a,e=ab(c),f= +b.aoData,g=Ba(b,e),j=Sb(ha(f,g,"anCells")),i=h([].concat.apply([],j)),l,n=b.aoColumns.length,m,p,r,u,v,s;return $a("cell",d,function(a){var c=typeof a==="function";if(a===null||a===k||c){m=[];p=0;for(r=g.length;p<r;p++){l=g[p];for(u=0;u<n;u++){v={row:l,column:u};if(c){s=f[l];a(v,B(b,l,u),s.anCells?s.anCells[u]:null)&&m.push(v)}else m.push(v)}}return m}if(h.isPlainObject(a))return[a];c=i.filter(a).map(function(a,b){return{row:b._DT_CellIndex.row,column:b._DT_CellIndex.column}}).toArray();if(c.length|| +!a.nodeName)return c;s=h(a).closest("*[data-dt-row]");return s.length?[{row:s.data("dt-row"),column:s.data("dt-column")}]:[]},b,e)});var d=this.columns(b,c),e=this.rows(a,c),f,g,j,i,n,l=this.iterator("table",function(a,b){f=[];g=0;for(j=e[b].length;g<j;g++){i=0;for(n=d[b].length;i<n;i++)f.push({row:e[b][g],column:d[b][i]})}return f},1);h.extend(l.selector,{cols:b,rows:a,opts:c});return l});s("cells().nodes()","cell().node()",function(){return this.iterator("cell",function(a,b,c){return(a=a.aoData[b])&& +a.anCells?a.anCells[c]:k},1)});p("cells().data()",function(){return this.iterator("cell",function(a,b,c){return B(a,b,c)},1)});s("cells().cache()","cell().cache()",function(a){a="search"===a?"_aFilterData":"_aSortData";return this.iterator("cell",function(b,c,d){return b.aoData[c][a][d]},1)});s("cells().render()","cell().render()",function(a){return this.iterator("cell",function(b,c,d){return B(b,c,d,a)},1)});s("cells().indexes()","cell().index()",function(){return this.iterator("cell",function(a, +b,c){return{row:b,column:c,columnVisible:$(a,c)}},1)});s("cells().invalidate()","cell().invalidate()",function(a){return this.iterator("cell",function(b,c,d){ca(b,c,a,d)})});p("cell()",function(a,b,c){return bb(this.cells(a,b,c))});p("cell().data()",function(a){var b=this.context,c=this[0];if(a===k)return b.length&&c.length?B(b[0],c[0].row,c[0].column):k;jb(b[0],c[0].row,c[0].column,a);ca(b[0],c[0].row,"data",c[0].column);return this});p("order()",function(a,b){var c=this.context;if(a===k)return 0!== +c.length?c[0].aaSorting:k;"number"===typeof a?a=[[a,b]]:a.length&&!h.isArray(a[0])&&(a=Array.prototype.slice.call(arguments));return this.iterator("table",function(b){b.aaSorting=a.slice()})});p("order.listener()",function(a,b,c){return this.iterator("table",function(d){Ma(d,a,b,c)})});p("order.fixed()",function(a){if(!a){var b=this.context,b=b.length?b[0].aaSortingFixed:k;return h.isArray(b)?{pre:b}:b}return this.iterator("table",function(b){b.aaSortingFixed=h.extend(!0,{},a)})});p(["columns().order()", +"column().order()"],function(a){var b=this;return this.iterator("table",function(c,d){var e=[];h.each(b[d],function(b,c){e.push([c,a])});c.aaSorting=e})});p("search()",function(a,b,c,d){var e=this.context;return a===k?0!==e.length?e[0].oPreviousSearch.sSearch:k:this.iterator("table",function(e){e.oFeatures.bFilter&&fa(e,h.extend({},e.oPreviousSearch,{sSearch:a+"",bRegex:null===b?!1:b,bSmart:null===c?!0:c,bCaseInsensitive:null===d?!0:d}),1)})});s("columns().search()","column().search()",function(a, +b,c,d){return this.iterator("column",function(e,f){var g=e.aoPreSearchCols;if(a===k)return g[f].sSearch;e.oFeatures.bFilter&&(h.extend(g[f],{sSearch:a+"",bRegex:null===b?!1:b,bSmart:null===c?!0:c,bCaseInsensitive:null===d?!0:d}),fa(e,e.oPreviousSearch,1))})});p("state()",function(){return this.context.length?this.context[0].oSavedState:null});p("state.clear()",function(){return this.iterator("table",function(a){a.fnStateSaveCallback.call(a.oInstance,a,{})})});p("state.loaded()",function(){return this.context.length? +this.context[0].oLoadedState:null});p("state.save()",function(){return this.iterator("table",function(a){wa(a)})});m.versionCheck=m.fnVersionCheck=function(a){for(var b=m.version.split("."),a=a.split("."),c,d,e=0,f=a.length;e<f;e++)if(c=parseInt(b[e],10)||0,d=parseInt(a[e],10)||0,c!==d)return c>d;return!0};m.isDataTable=m.fnIsDataTable=function(a){var b=h(a).get(0),c=!1;h.each(m.settings,function(a,e){var f=e.nScrollHead?h("table",e.nScrollHead)[0]:null,g=e.nScrollFoot?h("table",e.nScrollFoot)[0]: +null;if(e.nTable===b||f===b||g===b)c=!0});return c};m.tables=m.fnTables=function(a){var b=!1;h.isPlainObject(a)&&(b=a.api,a=a.visible);var c=h.map(m.settings,function(b){if(!a||a&&h(b.nTable).is(":visible"))return b.nTable});return b?new r(c):c};m.camelToHungarian=K;p("$()",function(a,b){var c=this.rows(b).nodes(),c=h(c);return h([].concat(c.filter(a).toArray(),c.find(a).toArray()))});h.each(["on","one","off"],function(a,b){p(b+"()",function(){var a=Array.prototype.slice.call(arguments);a[0].match(/\.dt\b/)|| +(a[0]+=".dt");var d=h(this.tables().nodes());d[b].apply(d,a);return this})});p("clear()",function(){return this.iterator("table",function(a){na(a)})});p("settings()",function(){return new r(this.context,this.context)});p("init()",function(){var a=this.context;return a.length?a[0].oInit:null});p("data()",function(){return this.iterator("table",function(a){return G(a.aoData,"_aData")}).flatten()});p("destroy()",function(a){a=a||!1;return this.iterator("table",function(b){var c=b.nTableWrapper.parentNode, +d=b.oClasses,e=b.nTable,f=b.nTBody,g=b.nTHead,j=b.nTFoot,i=h(e),f=h(f),k=h(b.nTableWrapper),l=h.map(b.aoData,function(a){return a.nTr}),p;b.bDestroying=!0;u(b,"aoDestroyCallback","destroy",[b]);a||(new r(b)).columns().visible(!0);k.unbind(".DT").find(":not(tbody *)").unbind(".DT");h(D).unbind(".DT-"+b.sInstance);e!=g.parentNode&&(i.children("thead").detach(),i.append(g));j&&e!=j.parentNode&&(i.children("tfoot").detach(),i.append(j));b.aaSorting=[];b.aaSortingFixed=[];va(b);h(l).removeClass(b.asStripeClasses.join(" ")); +h("th, td",g).removeClass(d.sSortable+" "+d.sSortableAsc+" "+d.sSortableDesc+" "+d.sSortableNone);b.bJUI&&(h("th span."+d.sSortIcon+", td span."+d.sSortIcon,g).detach(),h("th, td",g).each(function(){var a=h("div."+d.sSortJUIWrapper,this);h(this).append(a.contents());a.detach()}));f.children().detach();f.append(l);g=a?"remove":"detach";i[g]();k[g]();!a&&c&&(c.insertBefore(e,b.nTableReinsertBefore),i.css("width",b.sDestroyWidth).removeClass(d.sTable),(p=b.asDestroyStripes.length)&&f.children().each(function(a){h(this).addClass(b.asDestroyStripes[a% +p])}));c=h.inArray(b,m.settings);-1!==c&&m.settings.splice(c,1)})});h.each(["column","row","cell"],function(a,b){p(b+"s().every()",function(a){var d=this.selector.opts,e=this;return this.iterator(b,function(f,g,h,i,n){a.call(e[b](g,"cell"===b?h:d,"cell"===b?d:k),g,h,i,n)})})});p("i18n()",function(a,b,c){var d=this.context[0],a=Q(a)(d.oLanguage);a===k&&(a=b);c!==k&&h.isPlainObject(a)&&(a=a[c]!==k?a[c]:a._);return a.replace("%d",c)});m.version="1.10.12";m.settings=[];m.models={};m.models.oSearch={bCaseInsensitive:!0, +sSearch:"",bRegex:!1,bSmart:!0};m.models.oRow={nTr:null,anCells:null,_aData:[],_aSortData:null,_aFilterData:null,_sFilterRow:null,_sRowStripe:"",src:null,idx:-1};m.models.oColumn={idx:null,aDataSort:null,asSorting:null,bSearchable:null,bSortable:null,bVisible:null,_sManualType:null,_bAttrSrc:!1,fnCreatedCell:null,fnGetData:null,fnSetData:null,mData:null,mRender:null,nTh:null,nTf:null,sClass:null,sContentPadding:null,sDefaultContent:null,sName:null,sSortDataType:"std",sSortingClass:null,sSortingClassJUI:null, +sTitle:null,sType:null,sWidth:null,sWidthOrig:null};m.defaults={aaData:null,aaSorting:[[0,"asc"]],aaSortingFixed:[],ajax:null,aLengthMenu:[10,25,50,100],aoColumns:null,aoColumnDefs:null,aoSearchCols:[],asStripeClasses:null,bAutoWidth:!0,bDeferRender:!1,bDestroy:!1,bFilter:!0,bInfo:!0,bJQueryUI:!1,bLengthChange:!0,bPaginate:!0,bProcessing:!1,bRetrieve:!1,bScrollCollapse:!1,bServerSide:!1,bSort:!0,bSortMulti:!0,bSortCellsTop:!1,bSortClasses:!0,bStateSave:!1,fnCreatedRow:null,fnDrawCallback:null,fnFooterCallback:null, +fnFormatNumber:function(a){return a.toString().replace(/\B(?=(\d{3})+(?!\d))/g,this.oLanguage.sThousands)},fnHeaderCallback:null,fnInfoCallback:null,fnInitComplete:null,fnPreDrawCallback:null,fnRowCallback:null,fnServerData:null,fnServerParams:null,fnStateLoadCallback:function(a){try{return JSON.parse((-1===a.iStateDuration?sessionStorage:localStorage).getItem("DataTables_"+a.sInstance+"_"+location.pathname))}catch(b){}},fnStateLoadParams:null,fnStateLoaded:null,fnStateSaveCallback:function(a,b){try{(-1=== +a.iStateDuration?sessionStorage:localStorage).setItem("DataTables_"+a.sInstance+"_"+location.pathname,JSON.stringify(b))}catch(c){}},fnStateSaveParams:null,iStateDuration:7200,iDeferLoading:null,iDisplayLength:10,iDisplayStart:0,iTabIndex:0,oClasses:{},oLanguage:{oAria:{sSortAscending:": activate to sort column ascending",sSortDescending:": activate to sort column descending"},oPaginate:{sFirst:"First",sLast:"Last",sNext:"Next",sPrevious:"Previous"},sEmptyTable:"No data available in table",sInfo:"Showing _START_ to _END_ of _TOTAL_ entries", +sInfoEmpty:"Showing 0 to 0 of 0 entries",sInfoFiltered:"(filtered from _MAX_ total entries)",sInfoPostFix:"",sDecimal:"",sThousands:",",sLengthMenu:"Show _MENU_ entries",sLoadingRecords:"Loading...",sProcessing:"Processing...",sSearch:"Search:",sSearchPlaceholder:"",sUrl:"",sZeroRecords:"No matching records found"},oSearch:h.extend({},m.models.oSearch),sAjaxDataProp:"data",sAjaxSource:null,sDom:"lfrtip",searchDelay:null,sPaginationType:"simple_numbers",sScrollX:"",sScrollXInner:"",sScrollY:"",sServerMethod:"GET", +renderer:null,rowId:"DT_RowId"};X(m.defaults);m.defaults.column={aDataSort:null,iDataSort:-1,asSorting:["asc","desc"],bSearchable:!0,bSortable:!0,bVisible:!0,fnCreatedCell:null,mData:null,mRender:null,sCellType:"td",sClass:"",sContentPadding:"",sDefaultContent:null,sName:"",sSortDataType:"std",sTitle:null,sType:null,sWidth:null};X(m.defaults.column);m.models.oSettings={oFeatures:{bAutoWidth:null,bDeferRender:null,bFilter:null,bInfo:null,bLengthChange:null,bPaginate:null,bProcessing:null,bServerSide:null, +bSort:null,bSortMulti:null,bSortClasses:null,bStateSave:null},oScroll:{bCollapse:null,iBarWidth:0,sX:null,sXInner:null,sY:null},oLanguage:{fnInfoCallback:null},oBrowser:{bScrollOversize:!1,bScrollbarLeft:!1,bBounding:!1,barWidth:0},ajax:null,aanFeatures:[],aoData:[],aiDisplay:[],aiDisplayMaster:[],aIds:{},aoColumns:[],aoHeader:[],aoFooter:[],oPreviousSearch:{},aoPreSearchCols:[],aaSorting:null,aaSortingFixed:[],asStripeClasses:null,asDestroyStripes:[],sDestroyWidth:0,aoRowCallback:[],aoHeaderCallback:[], +aoFooterCallback:[],aoDrawCallback:[],aoRowCreatedCallback:[],aoPreDrawCallback:[],aoInitComplete:[],aoStateSaveParams:[],aoStateLoadParams:[],aoStateLoaded:[],sTableId:"",nTable:null,nTHead:null,nTFoot:null,nTBody:null,nTableWrapper:null,bDeferLoading:!1,bInitialised:!1,aoOpenRows:[],sDom:null,searchDelay:null,sPaginationType:"two_button",iStateDuration:0,aoStateSave:[],aoStateLoad:[],oSavedState:null,oLoadedState:null,sAjaxSource:null,sAjaxDataProp:null,bAjaxDataGet:!0,jqXHR:null,json:k,oAjaxData:k, +fnServerData:null,aoServerParams:[],sServerMethod:null,fnFormatNumber:null,aLengthMenu:null,iDraw:0,bDrawing:!1,iDrawError:-1,_iDisplayLength:10,_iDisplayStart:0,_iRecordsTotal:0,_iRecordsDisplay:0,bJUI:null,oClasses:{},bFiltered:!1,bSorted:!1,bSortCellsTop:null,oInit:null,aoDestroyCallback:[],fnRecordsTotal:function(){return"ssp"==y(this)?1*this._iRecordsTotal:this.aiDisplayMaster.length},fnRecordsDisplay:function(){return"ssp"==y(this)?1*this._iRecordsDisplay:this.aiDisplay.length},fnDisplayEnd:function(){var a= +this._iDisplayLength,b=this._iDisplayStart,c=b+a,d=this.aiDisplay.length,e=this.oFeatures,f=e.bPaginate;return e.bServerSide?!1===f||-1===a?b+d:Math.min(b+a,this._iRecordsDisplay):!f||c>d||-1===a?d:c},oInstance:null,sInstance:null,iTabIndex:0,nScrollHead:null,nScrollFoot:null,aLastSort:[],oPlugins:{},rowIdFn:null,rowId:null};m.ext=v={buttons:{},classes:{},builder:"-source-",errMode:"alert",feature:[],search:[],selector:{cell:[],column:[],row:[]},internal:{},legacy:{ajax:null},pager:{},renderer:{pageButton:{}, +header:{}},order:{},type:{detect:[],search:{},order:{}},_unique:0,fnVersionCheck:m.fnVersionCheck,iApiIndex:0,oJUIClasses:{},sVersion:m.version};h.extend(v,{afnFiltering:v.search,aTypes:v.type.detect,ofnSearch:v.type.search,oSort:v.type.order,afnSortData:v.order,aoFeatures:v.feature,oApi:v.internal,oStdClasses:v.classes,oPagination:v.pager});h.extend(m.ext.classes,{sTable:"dataTable",sNoFooter:"no-footer",sPageButton:"paginate_button",sPageButtonActive:"current",sPageButtonDisabled:"disabled",sStripeOdd:"odd", sStripeEven:"even",sRowEmpty:"dataTables_empty",sWrapper:"dataTables_wrapper",sFilter:"dataTables_filter",sInfo:"dataTables_info",sPaging:"dataTables_paginate paging_",sLength:"dataTables_length",sProcessing:"dataTables_processing",sSortAsc:"sorting_asc",sSortDesc:"sorting_desc",sSortable:"sorting",sSortableAsc:"sorting_asc_disabled",sSortableDesc:"sorting_desc_disabled",sSortableNone:"sorting_disabled",sSortColumn:"sorting_",sFilterInput:"",sLengthSelect:"",sScrollWrapper:"dataTables_scroll",sScrollHead:"dataTables_scrollHead", -sScrollHeadInner:"dataTables_scrollHeadInner",sScrollBody:"dataTables_scrollBody",sScrollFoot:"dataTables_scrollFoot",sScrollFootInner:"dataTables_scrollFootInner",sHeaderTH:"",sFooterTH:"",sSortJUIAsc:"",sSortJUIDesc:"",sSortJUI:"",sSortJUIAscAllowed:"",sSortJUIDescAllowed:"",sSortJUIWrapper:"",sSortIcon:"",sJUIHeader:"",sJUIFooter:""});var Da="",Da="",F=Da+"ui-state-default",ja=Da+"css_right ui-icon ui-icon-",Xb=Da+"fg-toolbar ui-toolbar ui-widget-header ui-helper-clearfix";h.extend(m.ext.oJUIClasses, -m.ext.classes,{sPageButton:"fg-button ui-button "+F,sPageButtonActive:"ui-state-disabled",sPageButtonDisabled:"ui-state-disabled",sPaging:"dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi ui-buttonset-multi paging_",sSortAsc:F+" sorting_asc",sSortDesc:F+" sorting_desc",sSortable:F+" sorting",sSortableAsc:F+" sorting_asc_disabled",sSortableDesc:F+" sorting_desc_disabled",sSortableNone:F+" sorting_disabled",sSortJUIAsc:ja+"triangle-1-n",sSortJUIDesc:ja+"triangle-1-s",sSortJUI:ja+"carat-2-n-s", -sSortJUIAscAllowed:ja+"carat-1-n",sSortJUIDescAllowed:ja+"carat-1-s",sSortJUIWrapper:"DataTables_sort_wrapper",sSortIcon:"DataTables_sort_icon",sScrollHead:"dataTables_scrollHead "+F,sScrollFoot:"dataTables_scrollFoot "+F,sHeaderTH:F,sFooterTH:F,sJUIHeader:Xb+" ui-corner-tl ui-corner-tr",sJUIFooter:Xb+" ui-corner-bl ui-corner-br"});var Mb=m.ext.pager;h.extend(Mb,{simple:function(){return["previous","next"]},full:function(){return["first","previous","next","last"]},simple_numbers:function(a,b){return["previous", -Wa(a,b),"next"]},full_numbers:function(a,b){return["first","previous",Wa(a,b),"next","last"]},_numbers:Wa,numbers_length:7});h.extend(!0,m.ext.renderer,{pageButton:{_:function(a,b,c,e,d,f){var g=a.oClasses,j=a.oLanguage.oPaginate,i,k,l=0,m=function(b,e){var n,r,t,s,u=function(b){Ta(a,b.data.action,true)};n=0;for(r=e.length;n<r;n++){s=e[n];if(h.isArray(s)){t=h("<"+(s.DT_el||"div")+"/>").appendTo(b);m(t,s)}else{k=i="";switch(s){case "ellipsis":b.append('<span class="ellipsis">…</span>');break; -case "first":i=j.sFirst;k=s+(d>0?"":" "+g.sPageButtonDisabled);break;case "previous":i=j.sPrevious;k=s+(d>0?"":" "+g.sPageButtonDisabled);break;case "next":i=j.sNext;k=s+(d<f-1?"":" "+g.sPageButtonDisabled);break;case "last":i=j.sLast;k=s+(d<f-1?"":" "+g.sPageButtonDisabled);break;default:i=s+1;k=d===s?g.sPageButtonActive:""}if(i){t=h("<a>",{"class":g.sPageButton+" "+k,"aria-controls":a.sTableId,"data-dt-idx":l,tabindex:a.iTabIndex,id:c===0&&typeof s==="string"?a.sTableId+"_"+s:null}).html(i).appendTo(b); -Va(t,{action:s},u);l++}}}},n;try{n=h(Q.activeElement).data("dt-idx")}catch(r){}m(h(b).empty(),e);n&&h(b).find("[data-dt-idx="+n+"]").focus()}}});h.extend(m.ext.type.detect,[function(a,b){var c=b.oLanguage.sDecimal;return Za(a,c)?"num"+c:null},function(a){if(a&&!(a instanceof Date)&&(!ac.test(a)||!bc.test(a)))return null;var b=Date.parse(a);return null!==b&&!isNaN(b)||J(a)?"date":null},function(a,b){var c=b.oLanguage.sDecimal;return Za(a,c,!0)?"num-fmt"+c:null},function(a,b){var c=b.oLanguage.sDecimal; -return Rb(a,c)?"html-num"+c:null},function(a,b){var c=b.oLanguage.sDecimal;return Rb(a,c,!0)?"html-num-fmt"+c:null},function(a){return J(a)||"string"===typeof a&&-1!==a.indexOf("<")?"html":null}]);h.extend(m.ext.type.search,{html:function(a){return J(a)?a:"string"===typeof a?a.replace(Ob," ").replace(Ba,""):""},string:function(a){return J(a)?a:"string"===typeof a?a.replace(Ob," "):a}});var Aa=function(a,b,c,e){if(0!==a&&(!a||"-"===a))return-Infinity;b&&(a=Qb(a,b));a.replace&&(c&&(a=a.replace(c,"")), -e&&(a=a.replace(e,"")));return 1*a};h.extend(u.type.order,{"date-pre":function(a){return Date.parse(a)||0},"html-pre":function(a){return J(a)?"":a.replace?a.replace(/<.*?>/g,"").toLowerCase():a+""},"string-pre":function(a){return J(a)?"":"string"===typeof a?a.toLowerCase():!a.toString?"":a.toString()},"string-asc":function(a,b){return a<b?-1:a>b?1:0},"string-desc":function(a,b){return a<b?1:a>b?-1:0}});db("");h.extend(!0,m.ext.renderer,{header:{_:function(a,b,c,e){h(a.nTable).on("order.dt.DT",function(d, -f,g,h){if(a===f){d=c.idx;b.removeClass(c.sSortingClass+" "+e.sSortAsc+" "+e.sSortDesc).addClass(h[d]=="asc"?e.sSortAsc:h[d]=="desc"?e.sSortDesc:c.sSortingClass)}})},jqueryui:function(a,b,c,e){h("<div/>").addClass(e.sSortJUIWrapper).append(b.contents()).append(h("<span/>").addClass(e.sSortIcon+" "+c.sSortingClassJUI)).appendTo(b);h(a.nTable).on("order.dt.DT",function(d,f,g,h){if(a===f){d=c.idx;b.removeClass(e.sSortAsc+" "+e.sSortDesc).addClass(h[d]=="asc"?e.sSortAsc:h[d]=="desc"?e.sSortDesc:c.sSortingClass); -b.find("span."+e.sSortIcon).removeClass(e.sSortJUIAsc+" "+e.sSortJUIDesc+" "+e.sSortJUI+" "+e.sSortJUIAscAllowed+" "+e.sSortJUIDescAllowed).addClass(h[d]=="asc"?e.sSortJUIAsc:h[d]=="desc"?e.sSortJUIDesc:c.sSortingClassJUI)}})}}});m.render={number:function(a,b,c,e){return{display:function(d){if("number"!==typeof d&&"string"!==typeof d)return d;var f=0>d?"-":"",d=Math.abs(parseFloat(d)),g=parseInt(d,10),d=c?b+(d-g).toFixed(c).substring(2):"";return f+(e||"")+g.toString().replace(/\B(?=(\d{3})+(?!\d))/g, -a)+d}}}};h.extend(m.ext.internal,{_fnExternApiFunc:Nb,_fnBuildAjax:ra,_fnAjaxUpdate:kb,_fnAjaxParameters:tb,_fnAjaxUpdateDraw:ub,_fnAjaxDataSrc:sa,_fnAddColumn:Fa,_fnColumnOptions:ka,_fnAdjustColumnSizing:X,_fnVisibleToColumnIndex:la,_fnColumnIndexToVisible:$,_fnVisbleColumns:aa,_fnGetColumns:Z,_fnColumnTypes:Ha,_fnApplyColumnDefs:ib,_fnHungarianMap:W,_fnCamelToHungarian:H,_fnLanguageCompat:P,_fnBrowserDetect:gb,_fnAddData:K,_fnAddTr:ma,_fnNodeToDataIndex:function(a,b){return b._DT_RowIndex!==k?b._DT_RowIndex: -null},_fnNodeToColumnIndex:function(a,b,c){return h.inArray(c,a.aoData[b].anCells)},_fnGetCellData:x,_fnSetCellData:Ia,_fnSplitObjNotation:Ka,_fnGetObjectDataFn:R,_fnSetObjectDataFn:S,_fnGetDataMaster:La,_fnClearTable:oa,_fnDeleteIndex:pa,_fnInvalidate:ca,_fnGetRowElements:na,_fnCreateTr:Ja,_fnBuildHead:jb,_fnDrawHead:ea,_fnDraw:M,_fnReDraw:N,_fnAddOptionsHtml:mb,_fnDetectHeader:da,_fnGetUniqueThs:qa,_fnFeatureHtmlFilter:ob,_fnFilterComplete:fa,_fnFilterCustom:xb,_fnFilterColumn:wb,_fnFilter:vb,_fnFilterCreateSearch:Qa, -_fnEscapeRegex:va,_fnFilterData:yb,_fnFeatureHtmlInfo:rb,_fnUpdateInfo:Bb,_fnInfoMacros:Cb,_fnInitialise:ga,_fnInitComplete:ta,_fnLengthChange:Ra,_fnFeatureHtmlLength:nb,_fnFeatureHtmlPaginate:sb,_fnPageChange:Ta,_fnFeatureHtmlProcessing:pb,_fnProcessingDisplay:C,_fnFeatureHtmlTable:qb,_fnScrollDraw:Y,_fnApplyToChildren:G,_fnCalculateColumnWidths:Ga,_fnThrottle:ua,_fnConvertToWidth:Db,_fnScrollingWidthAdjust:Fb,_fnGetWidestNode:Eb,_fnGetMaxLenString:Gb,_fnStringToCss:s,_fnScrollBarWidth:Hb,_fnSortFlatten:U, -_fnSort:lb,_fnSortAria:Jb,_fnSortListener:Ua,_fnSortAttachListener:Oa,_fnSortingClasses:xa,_fnSortData:Ib,_fnSaveState:ya,_fnLoadState:Kb,_fnSettingsFromNode:za,_fnLog:I,_fnMap:E,_fnBindAction:Va,_fnCallbackReg:z,_fnCallbackFire:w,_fnLengthOverflow:Sa,_fnRenderer:Pa,_fnDataSource:B,_fnRowAttributes:Ma,_fnCalculateEnd:function(){}});h.fn.dataTable=m;h.fn.dataTableSettings=m.settings;h.fn.dataTableExt=m.ext;h.fn.DataTable=function(a){return h(this).dataTable(a).api()};h.each(m,function(a,b){h.fn.DataTable[a]= -b});return h.fn.dataTable};"function"===typeof define&&define.amd?define("datatables",["jquery"],P):"object"===typeof exports?module.exports=P(require("jquery")):jQuery&&!jQuery.fn.dataTable&&P(jQuery)})(window,document); +sScrollHeadInner:"dataTables_scrollHeadInner",sScrollBody:"dataTables_scrollBody",sScrollFoot:"dataTables_scrollFoot",sScrollFootInner:"dataTables_scrollFootInner",sHeaderTH:"",sFooterTH:"",sSortJUIAsc:"",sSortJUIDesc:"",sSortJUI:"",sSortJUIAscAllowed:"",sSortJUIDescAllowed:"",sSortJUIWrapper:"",sSortIcon:"",sJUIHeader:"",sJUIFooter:""});var Ca="",Ca="",H=Ca+"ui-state-default",ia=Ca+"css_right ui-icon ui-icon-",Xb=Ca+"fg-toolbar ui-toolbar ui-widget-header ui-helper-clearfix";h.extend(m.ext.oJUIClasses, +m.ext.classes,{sPageButton:"fg-button ui-button "+H,sPageButtonActive:"ui-state-disabled",sPageButtonDisabled:"ui-state-disabled",sPaging:"dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi ui-buttonset-multi paging_",sSortAsc:H+" sorting_asc",sSortDesc:H+" sorting_desc",sSortable:H+" sorting",sSortableAsc:H+" sorting_asc_disabled",sSortableDesc:H+" sorting_desc_disabled",sSortableNone:H+" sorting_disabled",sSortJUIAsc:ia+"triangle-1-n",sSortJUIDesc:ia+"triangle-1-s",sSortJUI:ia+"carat-2-n-s", +sSortJUIAscAllowed:ia+"carat-1-n",sSortJUIDescAllowed:ia+"carat-1-s",sSortJUIWrapper:"DataTables_sort_wrapper",sSortIcon:"DataTables_sort_icon",sScrollHead:"dataTables_scrollHead "+H,sScrollFoot:"dataTables_scrollFoot "+H,sHeaderTH:H,sFooterTH:H,sJUIHeader:Xb+" ui-corner-tl ui-corner-tr",sJUIFooter:Xb+" ui-corner-bl ui-corner-br"});var Mb=m.ext.pager;h.extend(Mb,{simple:function(){return["previous","next"]},full:function(){return["first","previous","next","last"]},numbers:function(a,b){return[ya(a, +b)]},simple_numbers:function(a,b){return["previous",ya(a,b),"next"]},full_numbers:function(a,b){return["first","previous",ya(a,b),"next","last"]},_numbers:ya,numbers_length:7});h.extend(!0,m.ext.renderer,{pageButton:{_:function(a,b,c,d,e,f){var g=a.oClasses,j=a.oLanguage.oPaginate,i=a.oLanguage.oAria.paginate||{},k,l,m=0,p=function(b,d){var o,r,u,s,v=function(b){Ta(a,b.data.action,true)};o=0;for(r=d.length;o<r;o++){s=d[o];if(h.isArray(s)){u=h("<"+(s.DT_el||"div")+"/>").appendTo(b);p(u,s)}else{k=null; +l="";switch(s){case "ellipsis":b.append('<span class="ellipsis">…</span>');break;case "first":k=j.sFirst;l=s+(e>0?"":" "+g.sPageButtonDisabled);break;case "previous":k=j.sPrevious;l=s+(e>0?"":" "+g.sPageButtonDisabled);break;case "next":k=j.sNext;l=s+(e<f-1?"":" "+g.sPageButtonDisabled);break;case "last":k=j.sLast;l=s+(e<f-1?"":" "+g.sPageButtonDisabled);break;default:k=s+1;l=e===s?g.sPageButtonActive:""}if(k!==null){u=h("<a>",{"class":g.sPageButton+" "+l,"aria-controls":a.sTableId,"aria-label":i[s], +"data-dt-idx":m,tabindex:a.iTabIndex,id:c===0&&typeof s==="string"?a.sTableId+"_"+s:null}).html(k).appendTo(b);Wa(u,{action:s},v);m++}}}},r;try{r=h(b).find(I.activeElement).data("dt-idx")}catch(o){}p(h(b).empty(),d);r&&h(b).find("[data-dt-idx="+r+"]").focus()}}});h.extend(m.ext.type.detect,[function(a,b){var c=b.oLanguage.sDecimal;return Za(a,c)?"num"+c:null},function(a){if(a&&!(a instanceof Date)&&(!ac.test(a)||!bc.test(a)))return null;var b=Date.parse(a);return null!==b&&!isNaN(b)||M(a)?"date": +null},function(a,b){var c=b.oLanguage.sDecimal;return Za(a,c,!0)?"num-fmt"+c:null},function(a,b){var c=b.oLanguage.sDecimal;return Rb(a,c)?"html-num"+c:null},function(a,b){var c=b.oLanguage.sDecimal;return Rb(a,c,!0)?"html-num-fmt"+c:null},function(a){return M(a)||"string"===typeof a&&-1!==a.indexOf("<")?"html":null}]);h.extend(m.ext.type.search,{html:function(a){return M(a)?a:"string"===typeof a?a.replace(Ob," ").replace(Aa,""):""},string:function(a){return M(a)?a:"string"===typeof a?a.replace(Ob, +" "):a}});var za=function(a,b,c,d){if(0!==a&&(!a||"-"===a))return-Infinity;b&&(a=Qb(a,b));a.replace&&(c&&(a=a.replace(c,"")),d&&(a=a.replace(d,"")));return 1*a};h.extend(v.type.order,{"date-pre":function(a){return Date.parse(a)||0},"html-pre":function(a){return M(a)?"":a.replace?a.replace(/<.*?>/g,"").toLowerCase():a+""},"string-pre":function(a){return M(a)?"":"string"===typeof a?a.toLowerCase():!a.toString?"":a.toString()},"string-asc":function(a,b){return a<b?-1:a>b?1:0},"string-desc":function(a, +b){return a<b?1:a>b?-1:0}});db("");h.extend(!0,m.ext.renderer,{header:{_:function(a,b,c,d){h(a.nTable).on("order.dt.DT",function(e,f,g,h){if(a===f){e=c.idx;b.removeClass(c.sSortingClass+" "+d.sSortAsc+" "+d.sSortDesc).addClass(h[e]=="asc"?d.sSortAsc:h[e]=="desc"?d.sSortDesc:c.sSortingClass)}})},jqueryui:function(a,b,c,d){h("<div/>").addClass(d.sSortJUIWrapper).append(b.contents()).append(h("<span/>").addClass(d.sSortIcon+" "+c.sSortingClassJUI)).appendTo(b);h(a.nTable).on("order.dt.DT",function(e, +f,g,h){if(a===f){e=c.idx;b.removeClass(d.sSortAsc+" "+d.sSortDesc).addClass(h[e]=="asc"?d.sSortAsc:h[e]=="desc"?d.sSortDesc:c.sSortingClass);b.find("span."+d.sSortIcon).removeClass(d.sSortJUIAsc+" "+d.sSortJUIDesc+" "+d.sSortJUI+" "+d.sSortJUIAscAllowed+" "+d.sSortJUIDescAllowed).addClass(h[e]=="asc"?d.sSortJUIAsc:h[e]=="desc"?d.sSortJUIDesc:c.sSortingClassJUI)}})}}});var Yb=function(a){return"string"===typeof a?a.replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):a};m.render={number:function(a, +b,c,d,e){return{display:function(f){if("number"!==typeof f&&"string"!==typeof f)return f;var g=0>f?"-":"",h=parseFloat(f);if(isNaN(h))return Yb(f);f=Math.abs(h);h=parseInt(f,10);f=c?b+(f-h).toFixed(c).substring(2):"";return g+(d||"")+h.toString().replace(/\B(?=(\d{3})+(?!\d))/g,a)+f+(e||"")}}},text:function(){return{display:Yb}}};h.extend(m.ext.internal,{_fnExternApiFunc:Nb,_fnBuildAjax:ra,_fnAjaxUpdate:lb,_fnAjaxParameters:ub,_fnAjaxUpdateDraw:vb,_fnAjaxDataSrc:sa,_fnAddColumn:Ea,_fnColumnOptions:ja, +_fnAdjustColumnSizing:Y,_fnVisibleToColumnIndex:Z,_fnColumnIndexToVisible:$,_fnVisbleColumns:aa,_fnGetColumns:la,_fnColumnTypes:Ga,_fnApplyColumnDefs:ib,_fnHungarianMap:X,_fnCamelToHungarian:K,_fnLanguageCompat:Da,_fnBrowserDetect:gb,_fnAddData:N,_fnAddTr:ma,_fnNodeToDataIndex:function(a,b){return b._DT_RowIndex!==k?b._DT_RowIndex:null},_fnNodeToColumnIndex:function(a,b,c){return h.inArray(c,a.aoData[b].anCells)},_fnGetCellData:B,_fnSetCellData:jb,_fnSplitObjNotation:Ja,_fnGetObjectDataFn:Q,_fnSetObjectDataFn:R, +_fnGetDataMaster:Ka,_fnClearTable:na,_fnDeleteIndex:oa,_fnInvalidate:ca,_fnGetRowElements:Ia,_fnCreateTr:Ha,_fnBuildHead:kb,_fnDrawHead:ea,_fnDraw:O,_fnReDraw:T,_fnAddOptionsHtml:nb,_fnDetectHeader:da,_fnGetUniqueThs:qa,_fnFeatureHtmlFilter:pb,_fnFilterComplete:fa,_fnFilterCustom:yb,_fnFilterColumn:xb,_fnFilter:wb,_fnFilterCreateSearch:Pa,_fnEscapeRegex:Qa,_fnFilterData:zb,_fnFeatureHtmlInfo:sb,_fnUpdateInfo:Cb,_fnInfoMacros:Db,_fnInitialise:ga,_fnInitComplete:ta,_fnLengthChange:Ra,_fnFeatureHtmlLength:ob, +_fnFeatureHtmlPaginate:tb,_fnPageChange:Ta,_fnFeatureHtmlProcessing:qb,_fnProcessingDisplay:C,_fnFeatureHtmlTable:rb,_fnScrollDraw:ka,_fnApplyToChildren:J,_fnCalculateColumnWidths:Fa,_fnThrottle:Oa,_fnConvertToWidth:Fb,_fnGetWidestNode:Gb,_fnGetMaxLenString:Hb,_fnStringToCss:x,_fnSortFlatten:V,_fnSort:mb,_fnSortAria:Jb,_fnSortListener:Va,_fnSortAttachListener:Ma,_fnSortingClasses:va,_fnSortData:Ib,_fnSaveState:wa,_fnLoadState:Kb,_fnSettingsFromNode:xa,_fnLog:L,_fnMap:E,_fnBindAction:Wa,_fnCallbackReg:z, +_fnCallbackFire:u,_fnLengthOverflow:Sa,_fnRenderer:Na,_fnDataSource:y,_fnRowAttributes:La,_fnCalculateEnd:function(){}});h.fn.dataTable=m;m.$=h;h.fn.dataTableSettings=m.settings;h.fn.dataTableExt=m.ext;h.fn.DataTable=function(a){return h(this).dataTable(a).api()};h.each(m,function(a,b){h.fn.DataTable[a]=b});return h.fn.dataTable}); diff --git a/wqflask/wqflask/static/new/packages/DataTables/js/jquery.js b/wqflask/wqflask/static/new/packages/DataTables/js/jquery.js index fdd413a6..71b96edb 100644 --- a/wqflask/wqflask/static/new/packages/DataTables/js/jquery.js +++ b/wqflask/wqflask/static/new/packages/DataTables/js/jquery.js @@ -1,5 +1,5 @@ -/*! jQuery v1.11.3 | (c) 2005, 2015 jQuery Foundation, Inc. | jquery.org/license */ -!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.3",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b){return b.toUpperCase()};m.fn=m.prototype={jquery:l,constructor:m,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b="length"in a&&a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,aa=/[+~]/,ba=/'|\\/g,ca=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),da=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ea=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fa){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(ba,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+ra(o[l]);w=aa.test(a)&&pa(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",ea,!1):e.attachEvent&&e.attachEvent("onunload",ea)),p=!f(g),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="<a id='"+u+"'></a><select id='"+u+"-\f]' msallowcapture=''><option selected=''></option></select>",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?la(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ca,da),a[3]=(a[3]||a[4]||a[5]||"").replace(ca,da),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ca,da).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(ca,da),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return W.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(ca,da).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:oa(function(){return[0]}),last:oa(function(a,b){return[b-1]}),eq:oa(function(a,b,c){return[0>c?c+b:c]}),even:oa(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:oa(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:oa(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:oa(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=ma(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=na(b);function qa(){}qa.prototype=d.filters=d.pseudos,d.setFilters=new qa,g=ga.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){(!c||(e=S.exec(h)))&&(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=T.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(R," ")}),h=h.slice(c.length));for(g in d.filter)!(e=X[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?ga.error(a):z(a,i).slice(0)};function ra(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function sa(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function ta(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ua(a,b,c){for(var d=0,e=b.length;e>d;d++)ga(a,b[d],c);return c}function va(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wa(a,b,c,d,e,f){return d&&!d[u]&&(d=wa(d)),e&&!e[u]&&(e=wa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ua(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:va(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=va(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=va(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sa(function(a){return a===b},h,!0),l=sa(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sa(ta(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wa(i>1&&ta(m),i>1&&ra(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xa(a.slice(i,e)),f>e&&xa(a=a.slice(e)),f>e&&ra(a))}m.push(c)}return ta(m)}function ya(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=va(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&ga.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,ya(e,d)),f.selector=a}return f},i=ga.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ca,da),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ca,da),aa.test(j[0].type)&&pa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&ra(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,aa.test(a)&&pa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ja(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?m.extend(a,d):d}},e={};return d.pipe=d.then,m.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&m.isFunction(a.promise)?e:0,g=1===f?a:m.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&m.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1; - -return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?m.queue(this[0],a):void 0===b?this:this.each(function(){var c=m.queue(this,a,b);m._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&m.dequeue(this,a)})},dequeue:function(a){return this.each(function(){m.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=m.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=m._data(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var S=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,T=["Top","Right","Bottom","Left"],U=function(a,b){return a=b||a,"none"===m.css(a,"display")||!m.contains(a.ownerDocument,a)},V=m.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===m.type(c)){e=!0;for(h in c)m.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,m.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(m(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav></:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="<textarea>x</textarea>",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="<input type='radio' checked='checked' name='t'/>",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function aa(){return!0}function ba(){return!1}function ca(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},fix:function(a){if(a[m.expando])return a;var b,c,d,e=a.type,f=a,g=this.fixHooks[e];g||(this.fixHooks[e]=g=Z.test(e)?this.mouseHooks:Y.test(e)?this.keyHooks:{}),d=g.props?this.props.concat(g.props):this.props,a=new m.Event(f),b=d.length;while(b--)c=d[b],a[c]=f[c];return a.target||(a.target=f.srcElement||y),3===a.target.nodeType&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,g.filter?g.filter(a,f):a},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,d,e,f=b.button,g=b.fromElement;return null==a.pageX&&null!=b.clientX&&(d=a.target.ownerDocument||y,e=d.documentElement,c=d.body,a.pageX=b.clientX+(e&&e.scrollLeft||c&&c.scrollLeft||0)-(e&&e.clientLeft||c&&c.clientLeft||0),a.pageY=b.clientY+(e&&e.scrollTop||c&&c.scrollTop||0)-(e&&e.clientTop||c&&c.clientTop||0)),!a.relatedTarget&&g&&(a.relatedTarget=g===a.target?b.toElement:g),a.which||void 0===f||(a.which=1&f?1:2&f?3:4&f?2:0),a}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==ca()&&this.focus)try{return this.focus(),!1}catch(a){}},delegateType:"focusin"},blur:{trigger:function(){return this===ca()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return m.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):void 0},_default:function(a){return m.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}},simulate:function(a,b,c,d){var e=m.extend(new m.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?m.event.trigger(e,null,b):m.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},m.removeEvent=y.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){var d="on"+b;a.detachEvent&&(typeof a[d]===K&&(a[d]=null),a.detachEvent(d,c))},m.Event=function(a,b){return this instanceof m.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?aa:ba):this.type=a,b&&m.extend(this,b),this.timeStamp=a&&a.timeStamp||m.now(),void(this[m.expando]=!0)):new m.Event(a,b)},m.Event.prototype={isDefaultPrevented:ba,isPropagationStopped:ba,isImmediatePropagationStopped:ba,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=aa,a&&(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=aa,a&&(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=aa,a&&a.stopImmediatePropagation&&a.stopImmediatePropagation(),this.stopPropagation()}},m.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){m.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return(!e||e!==d&&!m.contains(d,e))&&(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),k.submitBubbles||(m.event.special.submit={setup:function(){return m.nodeName(this,"form")?!1:void m.event.add(this,"click._submit keypress._submit",function(a){var b=a.target,c=m.nodeName(b,"input")||m.nodeName(b,"button")?b.form:void 0;c&&!m._data(c,"submitBubbles")&&(m.event.add(c,"submit._submit",function(a){a._submit_bubble=!0}),m._data(c,"submitBubbles",!0))})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&m.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){return m.nodeName(this,"form")?!1:void m.event.remove(this,"._submit")}}),k.changeBubbles||(m.event.special.change={setup:function(){return X.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(m.event.add(this,"propertychange._change",function(a){"checked"===a.originalEvent.propertyName&&(this._just_changed=!0)}),m.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1),m.event.simulate("change",this,a,!0)})),!1):void m.event.add(this,"beforeactivate._change",function(a){var b=a.target;X.test(b.nodeName)&&!m._data(b,"changeBubbles")&&(m.event.add(b,"change._change",function(a){!this.parentNode||a.isSimulated||a.isTrigger||m.event.simulate("change",this.parentNode,a,!0)}),m._data(b,"changeBubbles",!0))})},handle:function(a){var b=a.target;return this!==b||a.isSimulated||a.isTrigger||"radio"!==b.type&&"checkbox"!==b.type?a.handleObj.handler.apply(this,arguments):void 0},teardown:function(){return m.event.remove(this,"._change"),!X.test(this.nodeName)}}),k.focusinBubbles||m.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){m.event.simulate(b,a.target,m.event.fix(a),!0)};m.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=m._data(d,b);e||d.addEventListener(a,c,!0),m._data(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=m._data(d,b)-1;e?m._data(d,b,e):(d.removeEventListener(a,c,!0),m._removeData(d,b))}}}),m.fn.extend({on:function(a,b,c,d,e){var f,g;if("object"==typeof a){"string"!=typeof b&&(c=c||b,b=void 0);for(f in a)this.on(f,b,c,a[f],e);return this}if(null==c&&null==d?(d=b,c=b=void 0):null==d&&("string"==typeof b?(d=c,c=void 0):(d=c,c=b,b=void 0)),d===!1)d=ba;else if(!d)return this;return 1===e&&(g=d,d=function(a){return m().off(a),g.apply(this,arguments)},d.guid=g.guid||(g.guid=m.guid++)),this.each(function(){m.event.add(this,a,d,c,b)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,m(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return(b===!1||"function"==typeof b)&&(c=b,b=void 0),c===!1&&(c=ba),this.each(function(){m.event.remove(this,a,c,b)})},trigger:function(a,b){return this.each(function(){m.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?m.event.trigger(a,b,c,!0):void 0}});function da(a){var b=ea.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}var ea="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",fa=/ jQuery\d+="(?:null|\d+)"/g,ga=new RegExp("<(?:"+ea+")[\\s/>]","i"),ha=/^\s+/,ia=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,ja=/<([\w:]+)/,ka=/<tbody/i,la=/<|&#?\w+;/,ma=/<(?:script|style|link)/i,na=/checked\s*(?:[^=]|=\s*.checked.)/i,oa=/^$|\/(?:java|ecma)script/i,pa=/^true\/(.*)/,qa=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,ra={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:k.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},sa=da(y),ta=sa.appendChild(y.createElement("div"));ra.optgroup=ra.option,ra.tbody=ra.tfoot=ra.colgroup=ra.caption=ra.thead,ra.th=ra.td;function ua(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ua(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function va(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wa(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xa(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function ya(a){var b=pa.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function za(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Aa(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Ba(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xa(b).text=a.text,ya(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!ga.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(ta.innerHTML=a.outerHTML,ta.removeChild(f=ta.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ua(f),h=ua(a),g=0;null!=(e=h[g]);++g)d[g]&&Ba(e,d[g]);if(b)if(c)for(h=h||ua(a),d=d||ua(f),g=0;null!=(e=h[g]);g++)Aa(e,d[g]);else Aa(a,f);return d=ua(f,"script"),d.length>0&&za(d,!i&&ua(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=da(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(la.test(f)){h=h||o.appendChild(b.createElement("div")),i=(ja.exec(f)||["",""])[1].toLowerCase(),l=ra[i]||ra._default,h.innerHTML=l[1]+f.replace(ia,"<$1></$2>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&ha.test(f)&&p.push(b.createTextNode(ha.exec(f)[0])),!k.tbody){f="table"!==i||ka.test(f)?"<table>"!==l[1]||ka.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ua(p,"input"),va),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ua(o.appendChild(f),"script"),g&&za(h),c)){e=0;while(f=h[e++])oa.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wa(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wa(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ua(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&za(ua(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ua(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fa,""):void 0;if(!("string"!=typeof a||ma.test(a)||!k.htmlSerialize&&ga.test(a)||!k.leadingWhitespace&&ha.test(a)||ra[(ja.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ia,"<$1></$2>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ua(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ua(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&na.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ua(i,"script"),xa),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ua(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,ya),j=0;f>j;j++)d=g[j],oa.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qa,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Ca,Da={};function Ea(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fa(a){var b=y,c=Da[a];return c||(c=Ea(a,b),"none"!==c&&c||(Ca=(Ca||m("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=(Ca[0].contentWindow||Ca[0].contentDocument).document,b.write(),b.close(),c=Ea(a,b),Ca.detach()),Da[a]=c),c}!function(){var a;k.shrinkWrapBlocks=function(){if(null!=a)return a;a=!1;var b,c,d;return c=y.getElementsByTagName("body")[0],c&&c.style?(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:1px;width:1px;zoom:1",b.appendChild(y.createElement("div")).style.width="5px",a=3!==b.offsetWidth),c.removeChild(d),a):void 0}}();var Ga=/^margin/,Ha=new RegExp("^("+S+")(?!px)[a-z%]+$","i"),Ia,Ja,Ka=/^(top|right|bottom|left)$/;a.getComputedStyle?(Ia=function(b){return b.ownerDocument.defaultView.opener?b.ownerDocument.defaultView.getComputedStyle(b,null):a.getComputedStyle(b,null)},Ja=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ia(a),g=c?c.getPropertyValue(b)||c[b]:void 0,c&&(""!==g||m.contains(a.ownerDocument,a)||(g=m.style(a,b)),Ha.test(g)&&Ga.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0===g?g:g+""}):y.documentElement.currentStyle&&(Ia=function(a){return a.currentStyle},Ja=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ia(a),g=c?c[b]:void 0,null==g&&h&&h[b]&&(g=h[b]),Ha.test(g)&&!Ka.test(b)&&(d=h.left,e=a.runtimeStyle,f=e&&e.left,f&&(e.left=a.currentStyle.left),h.left="fontSize"===b?"1em":g,g=h.pixelLeft+"px",h.left=d,f&&(e.left=f)),void 0===g?g:g+""||"auto"});function La(a,b){return{get:function(){var c=a();if(null!=c)return c?void delete this.get:(this.get=b).apply(this,arguments)}}}!function(){var b,c,d,e,f,g,h;if(b=y.createElement("div"),b.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",d=b.getElementsByTagName("a")[0],c=d&&d.style){c.cssText="float:left;opacity:.5",k.opacity="0.5"===c.opacity,k.cssFloat=!!c.cssFloat,b.style.backgroundClip="content-box",b.cloneNode(!0).style.backgroundClip="",k.clearCloneStyle="content-box"===b.style.backgroundClip,k.boxSizing=""===c.boxSizing||""===c.MozBoxSizing||""===c.WebkitBoxSizing,m.extend(k,{reliableHiddenOffsets:function(){return null==g&&i(),g},boxSizingReliable:function(){return null==f&&i(),f},pixelPosition:function(){return null==e&&i(),e},reliableMarginRight:function(){return null==h&&i(),h}});function i(){var b,c,d,i;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),b.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;margin-top:1%;top:1%;border:1px;padding:1px;width:4px;position:absolute",e=f=!1,h=!0,a.getComputedStyle&&(e="1%"!==(a.getComputedStyle(b,null)||{}).top,f="4px"===(a.getComputedStyle(b,null)||{width:"4px"}).width,i=b.appendChild(y.createElement("div")),i.style.cssText=b.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",i.style.marginRight=i.style.width="0",b.style.width="1px",h=!parseFloat((a.getComputedStyle(i,null)||{}).marginRight),b.removeChild(i)),b.innerHTML="<table><tr><td></td><td>t</td></tr></table>",i=b.getElementsByTagName("td"),i[0].style.cssText="margin:0;border:0;padding:0;display:none",g=0===i[0].offsetHeight,g&&(i[0].style.display="",i[1].style.display="none",g=0===i[0].offsetHeight),c.removeChild(d))}}}(),m.swap=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};var Ma=/alpha\([^)]*\)/i,Na=/opacity\s*=\s*([^)]*)/,Oa=/^(none|table(?!-c[ea]).+)/,Pa=new RegExp("^("+S+")(.*)$","i"),Qa=new RegExp("^([+-])=("+S+")","i"),Ra={position:"absolute",visibility:"hidden",display:"block"},Sa={letterSpacing:"0",fontWeight:"400"},Ta=["Webkit","O","Moz","ms"];function Ua(a,b){if(b in a)return b;var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=Ta.length;while(e--)if(b=Ta[e]+c,b in a)return b;return d}function Va(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=m._data(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&U(d)&&(f[g]=m._data(d,"olddisplay",Fa(d.nodeName)))):(e=U(d),(c&&"none"!==c||!e)&&m._data(d,"olddisplay",e?c:m.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}function Wa(a,b,c){var d=Pa.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function Xa(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=m.css(a,c+T[f],!0,e)),d?("content"===c&&(g-=m.css(a,"padding"+T[f],!0,e)),"margin"!==c&&(g-=m.css(a,"border"+T[f]+"Width",!0,e))):(g+=m.css(a,"padding"+T[f],!0,e),"padding"!==c&&(g+=m.css(a,"border"+T[f]+"Width",!0,e)));return g}function Ya(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=Ia(a),g=k.boxSizing&&"border-box"===m.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=Ja(a,b,f),(0>e||null==e)&&(e=a.style[b]),Ha.test(e))return e;d=g&&(k.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+Xa(a,b,c||(g?"border":"content"),d,f)+"px"}m.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Ja(a,"opacity");return""===c?"1":c}}}},cssNumber:{columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":k.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=m.camelCase(b),i=a.style;if(b=m.cssProps[h]||(m.cssProps[h]=Ua(i,h)),g=m.cssHooks[b]||m.cssHooks[h],void 0===c)return g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b];if(f=typeof c,"string"===f&&(e=Qa.exec(c))&&(c=(e[1]+1)*e[2]+parseFloat(m.css(a,b)),f="number"),null!=c&&c===c&&("number"!==f||m.cssNumber[h]||(c+="px"),k.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),!(g&&"set"in g&&void 0===(c=g.set(a,c,d)))))try{i[b]=c}catch(j){}}},css:function(a,b,c,d){var e,f,g,h=m.camelCase(b);return b=m.cssProps[h]||(m.cssProps[h]=Ua(a.style,h)),g=m.cssHooks[b]||m.cssHooks[h],g&&"get"in g&&(f=g.get(a,!0,c)),void 0===f&&(f=Ja(a,b,d)),"normal"===f&&b in Sa&&(f=Sa[b]),""===c||c?(e=parseFloat(f),c===!0||m.isNumeric(e)?e||0:f):f}}),m.each(["height","width"],function(a,b){m.cssHooks[b]={get:function(a,c,d){return c?Oa.test(m.css(a,"display"))&&0===a.offsetWidth?m.swap(a,Ra,function(){return Ya(a,b,d)}):Ya(a,b,d):void 0},set:function(a,c,d){var e=d&&Ia(a);return Wa(a,c,d?Xa(a,b,d,k.boxSizing&&"border-box"===m.css(a,"boxSizing",!1,e),e):0)}}}),k.opacity||(m.cssHooks.opacity={get:function(a,b){return Na.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=m.isNumeric(b)?"alpha(opacity="+100*b+")":"",f=d&&d.filter||c.filter||"";c.zoom=1,(b>=1||""===b)&&""===m.trim(f.replace(Ma,""))&&c.removeAttribute&&(c.removeAttribute("filter"),""===b||d&&!d.filter)||(c.filter=Ma.test(f)?f.replace(Ma,e):f+" "+e)}}),m.cssHooks.marginRight=La(k.reliableMarginRight,function(a,b){return b?m.swap(a,{display:"inline-block"},Ja,[a,"marginRight"]):void 0}),m.each({margin:"",padding:"",border:"Width"},function(a,b){m.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+T[d]+b]=f[d]||f[d-2]||f[0];return e}},Ga.test(a)||(m.cssHooks[a+b].set=Wa)}),m.fn.extend({css:function(a,b){return V(this,function(a,b,c){var d,e,f={},g=0;if(m.isArray(b)){for(d=Ia(a),e=b.length;e>g;g++)f[b[g]]=m.css(a,b[g],!1,d);return f}return void 0!==c?m.style(a,b,c):m.css(a,b)},a,b,arguments.length>1)},show:function(){return Va(this,!0)},hide:function(){return Va(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){U(this)?m(this).show():m(this).hide()})}});function Za(a,b,c,d,e){ -return new Za.prototype.init(a,b,c,d,e)}m.Tween=Za,Za.prototype={constructor:Za,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(m.cssNumber[c]?"":"px")},cur:function(){var a=Za.propHooks[this.prop];return a&&a.get?a.get(this):Za.propHooks._default.get(this)},run:function(a){var b,c=Za.propHooks[this.prop];return this.options.duration?this.pos=b=m.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Za.propHooks._default.set(this),this}},Za.prototype.init.prototype=Za.prototype,Za.propHooks={_default:{get:function(a){var b;return null==a.elem[a.prop]||a.elem.style&&null!=a.elem.style[a.prop]?(b=m.css(a.elem,a.prop,""),b&&"auto"!==b?b:0):a.elem[a.prop]},set:function(a){m.fx.step[a.prop]?m.fx.step[a.prop](a):a.elem.style&&(null!=a.elem.style[m.cssProps[a.prop]]||m.cssHooks[a.prop])?m.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},Za.propHooks.scrollTop=Za.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},m.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},m.fx=Za.prototype.init,m.fx.step={};var $a,_a,ab=/^(?:toggle|show|hide)$/,bb=new RegExp("^(?:([+-])=|)("+S+")([a-z%]*)$","i"),cb=/queueHooks$/,db=[ib],eb={"*":[function(a,b){var c=this.createTween(a,b),d=c.cur(),e=bb.exec(b),f=e&&e[3]||(m.cssNumber[a]?"":"px"),g=(m.cssNumber[a]||"px"!==f&&+d)&&bb.exec(m.css(c.elem,a)),h=1,i=20;if(g&&g[3]!==f){f=f||g[3],e=e||[],g=+d||1;do h=h||".5",g/=h,m.style(c.elem,a,g+f);while(h!==(h=c.cur()/d)&&1!==h&&--i)}return e&&(g=c.start=+g||+d||0,c.unit=f,c.end=e[1]?g+(e[1]+1)*e[2]:+e[2]),c}]};function fb(){return setTimeout(function(){$a=void 0}),$a=m.now()}function gb(a,b){var c,d={height:a},e=0;for(b=b?1:0;4>e;e+=2-b)c=T[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function hb(a,b,c){for(var d,e=(eb[b]||[]).concat(eb["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function ib(a,b,c){var d,e,f,g,h,i,j,l,n=this,o={},p=a.style,q=a.nodeType&&U(a),r=m._data(a,"fxshow");c.queue||(h=m._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,n.always(function(){n.always(function(){h.unqueued--,m.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[p.overflow,p.overflowX,p.overflowY],j=m.css(a,"display"),l="none"===j?m._data(a,"olddisplay")||Fa(a.nodeName):j,"inline"===l&&"none"===m.css(a,"float")&&(k.inlineBlockNeedsLayout&&"inline"!==Fa(a.nodeName)?p.zoom=1:p.display="inline-block")),c.overflow&&(p.overflow="hidden",k.shrinkWrapBlocks()||n.always(function(){p.overflow=c.overflow[0],p.overflowX=c.overflow[1],p.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],ab.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(q?"hide":"show")){if("show"!==e||!r||void 0===r[d])continue;q=!0}o[d]=r&&r[d]||m.style(a,d)}else j=void 0;if(m.isEmptyObject(o))"inline"===("none"===j?Fa(a.nodeName):j)&&(p.display=j);else{r?"hidden"in r&&(q=r.hidden):r=m._data(a,"fxshow",{}),f&&(r.hidden=!q),q?m(a).show():n.done(function(){m(a).hide()}),n.done(function(){var b;m._removeData(a,"fxshow");for(b in o)m.style(a,b,o[b])});for(d in o)g=hb(q?r[d]:0,d,n),d in r||(r[d]=g.start,q&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function jb(a,b){var c,d,e,f,g;for(c in a)if(d=m.camelCase(c),e=b[d],f=a[c],m.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=m.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function kb(a,b,c){var d,e,f=0,g=db.length,h=m.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=$a||fb(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:m.extend({},b),opts:m.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:$a||fb(),duration:c.duration,tweens:[],createTween:function(b,c){var d=m.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;for(jb(k,j.opts.specialEasing);g>f;f++)if(d=db[f].call(j,a,k,j.opts))return d;return m.map(k,hb,j),m.isFunction(j.opts.start)&&j.opts.start.call(a,j),m.fx.timer(m.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}m.Animation=m.extend(kb,{tweener:function(a,b){m.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");for(var c,d=0,e=a.length;e>d;d++)c=a[d],eb[c]=eb[c]||[],eb[c].unshift(b)},prefilter:function(a,b){b?db.unshift(a):db.push(a)}}),m.speed=function(a,b,c){var d=a&&"object"==typeof a?m.extend({},a):{complete:c||!c&&b||m.isFunction(a)&&a,duration:a,easing:c&&b||b&&!m.isFunction(b)&&b};return d.duration=m.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in m.fx.speeds?m.fx.speeds[d.duration]:m.fx.speeds._default,(null==d.queue||d.queue===!0)&&(d.queue="fx"),d.old=d.complete,d.complete=function(){m.isFunction(d.old)&&d.old.call(this),d.queue&&m.dequeue(this,d.queue)},d},m.fn.extend({fadeTo:function(a,b,c,d){return this.filter(U).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=m.isEmptyObject(a),f=m.speed(b,c,d),g=function(){var b=kb(this,m.extend({},a),f);(e||m._data(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=m.timers,g=m._data(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&cb.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));(b||!c)&&m.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=m._data(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=m.timers,g=d?d.length:0;for(c.finish=!0,m.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),m.each(["toggle","show","hide"],function(a,b){var c=m.fn[b];m.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(gb(b,!0),a,d,e)}}),m.each({slideDown:gb("show"),slideUp:gb("hide"),slideToggle:gb("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){m.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),m.timers=[],m.fx.tick=function(){var a,b=m.timers,c=0;for($a=m.now();c<b.length;c++)a=b[c],a()||b[c]!==a||b.splice(c--,1);b.length||m.fx.stop(),$a=void 0},m.fx.timer=function(a){m.timers.push(a),a()?m.fx.start():m.timers.pop()},m.fx.interval=13,m.fx.start=function(){_a||(_a=setInterval(m.fx.tick,m.fx.interval))},m.fx.stop=function(){clearInterval(_a),_a=null},m.fx.speeds={slow:600,fast:200,_default:400},m.fn.delay=function(a,b){return a=m.fx?m.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},function(){var a,b,c,d,e;b=y.createElement("div"),b.setAttribute("className","t"),b.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",d=b.getElementsByTagName("a")[0],c=y.createElement("select"),e=c.appendChild(y.createElement("option")),a=b.getElementsByTagName("input")[0],d.style.cssText="top:1px",k.getSetAttribute="t"!==b.className,k.style=/top/.test(d.getAttribute("style")),k.hrefNormalized="/a"===d.getAttribute("href"),k.checkOn=!!a.value,k.optSelected=e.selected,k.enctype=!!y.createElement("form").enctype,c.disabled=!0,k.optDisabled=!e.disabled,a=y.createElement("input"),a.setAttribute("value",""),k.input=""===a.getAttribute("value"),a.value="t",a.setAttribute("type","radio"),k.radioValue="t"===a.value}();var lb=/\r/g;m.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=m.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,m(this).val()):a,null==e?e="":"number"==typeof e?e+="":m.isArray(e)&&(e=m.map(e,function(a){return null==a?"":a+""})),b=m.valHooks[this.type]||m.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=m.valHooks[e.type]||m.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(lb,""):null==c?"":c)}}}),m.extend({valHooks:{option:{get:function(a){var b=m.find.attr(a,"value");return null!=b?b:m.trim(m.text(a))}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],!(!c.selected&&i!==e||(k.optDisabled?c.disabled:null!==c.getAttribute("disabled"))||c.parentNode.disabled&&m.nodeName(c.parentNode,"optgroup"))){if(b=m(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=m.makeArray(b),g=e.length;while(g--)if(d=e[g],m.inArray(m.valHooks.option.get(d),f)>=0)try{d.selected=c=!0}catch(h){d.scrollHeight}else d.selected=!1;return c||(a.selectedIndex=-1),e}}}}),m.each(["radio","checkbox"],function(){m.valHooks[this]={set:function(a,b){return m.isArray(b)?a.checked=m.inArray(m(a).val(),b)>=0:void 0}},k.checkOn||(m.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var mb,nb,ob=m.expr.attrHandle,pb=/^(?:checked|selected)$/i,qb=k.getSetAttribute,rb=k.input;m.fn.extend({attr:function(a,b){return V(this,m.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){m.removeAttr(this,a)})}}),m.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(a&&3!==f&&8!==f&&2!==f)return typeof a.getAttribute===K?m.prop(a,b,c):(1===f&&m.isXMLDoc(a)||(b=b.toLowerCase(),d=m.attrHooks[b]||(m.expr.match.bool.test(b)?nb:mb)),void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=m.find.attr(a,b),null==e?void 0:e):null!==c?d&&"set"in d&&void 0!==(e=d.set(a,c,b))?e:(a.setAttribute(b,c+""),c):void m.removeAttr(a,b))},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(E);if(f&&1===a.nodeType)while(c=f[e++])d=m.propFix[c]||c,m.expr.match.bool.test(c)?rb&&qb||!pb.test(c)?a[d]=!1:a[m.camelCase("default-"+c)]=a[d]=!1:m.attr(a,c,""),a.removeAttribute(qb?c:d)},attrHooks:{type:{set:function(a,b){if(!k.radioValue&&"radio"===b&&m.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}}}),nb={set:function(a,b,c){return b===!1?m.removeAttr(a,c):rb&&qb||!pb.test(c)?a.setAttribute(!qb&&m.propFix[c]||c,c):a[m.camelCase("default-"+c)]=a[c]=!0,c}},m.each(m.expr.match.bool.source.match(/\w+/g),function(a,b){var c=ob[b]||m.find.attr;ob[b]=rb&&qb||!pb.test(b)?function(a,b,d){var e,f;return d||(f=ob[b],ob[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,ob[b]=f),e}:function(a,b,c){return c?void 0:a[m.camelCase("default-"+b)]?b.toLowerCase():null}}),rb&&qb||(m.attrHooks.value={set:function(a,b,c){return m.nodeName(a,"input")?void(a.defaultValue=b):mb&&mb.set(a,b,c)}}),qb||(mb={set:function(a,b,c){var d=a.getAttributeNode(c);return d||a.setAttributeNode(d=a.ownerDocument.createAttribute(c)),d.value=b+="","value"===c||b===a.getAttribute(c)?b:void 0}},ob.id=ob.name=ob.coords=function(a,b,c){var d;return c?void 0:(d=a.getAttributeNode(b))&&""!==d.value?d.value:null},m.valHooks.button={get:function(a,b){var c=a.getAttributeNode(b);return c&&c.specified?c.value:void 0},set:mb.set},m.attrHooks.contenteditable={set:function(a,b,c){mb.set(a,""===b?!1:b,c)}},m.each(["width","height"],function(a,b){m.attrHooks[b]={set:function(a,c){return""===c?(a.setAttribute(b,"auto"),c):void 0}}})),k.style||(m.attrHooks.style={get:function(a){return a.style.cssText||void 0},set:function(a,b){return a.style.cssText=b+""}});var sb=/^(?:input|select|textarea|button|object)$/i,tb=/^(?:a|area)$/i;m.fn.extend({prop:function(a,b){return V(this,m.prop,a,b,arguments.length>1)},removeProp:function(a){return a=m.propFix[a]||a,this.each(function(){try{this[a]=void 0,delete this[a]}catch(b){}})}}),m.extend({propFix:{"for":"htmlFor","class":"className"},prop:function(a,b,c){var d,e,f,g=a.nodeType;if(a&&3!==g&&8!==g&&2!==g)return f=1!==g||!m.isXMLDoc(a),f&&(b=m.propFix[b]||b,e=m.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=m.find.attr(a,"tabindex");return b?parseInt(b,10):sb.test(a.nodeName)||tb.test(a.nodeName)&&a.href?0:-1}}}}),k.hrefNormalized||m.each(["href","src"],function(a,b){m.propHooks[b]={get:function(a){return a.getAttribute(b,4)}}}),k.optSelected||(m.propHooks.selected={get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null}}),m.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){m.propFix[this.toLowerCase()]=this}),k.enctype||(m.propFix.enctype="encoding");var ub=/[\t\r\n\f]/g;m.fn.extend({addClass:function(a){var b,c,d,e,f,g,h=0,i=this.length,j="string"==typeof a&&a;if(m.isFunction(a))return this.each(function(b){m(this).addClass(a.call(this,b,this.className))});if(j)for(b=(a||"").match(E)||[];i>h;h++)if(c=this[h],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(ub," "):" ")){f=0;while(e=b[f++])d.indexOf(" "+e+" ")<0&&(d+=e+" ");g=m.trim(d),c.className!==g&&(c.className=g)}return this},removeClass:function(a){var b,c,d,e,f,g,h=0,i=this.length,j=0===arguments.length||"string"==typeof a&&a;if(m.isFunction(a))return this.each(function(b){m(this).removeClass(a.call(this,b,this.className))});if(j)for(b=(a||"").match(E)||[];i>h;h++)if(c=this[h],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(ub," "):"")){f=0;while(e=b[f++])while(d.indexOf(" "+e+" ")>=0)d=d.replace(" "+e+" "," ");g=a?m.trim(d):"",c.className!==g&&(c.className=g)}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):this.each(m.isFunction(a)?function(c){m(this).toggleClass(a.call(this,c,this.className,b),b)}:function(){if("string"===c){var b,d=0,e=m(this),f=a.match(E)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else(c===K||"boolean"===c)&&(this.className&&m._data(this,"__className__",this.className),this.className=this.className||a===!1?"":m._data(this,"__className__")||"")})},hasClass:function(a){for(var b=" "+a+" ",c=0,d=this.length;d>c;c++)if(1===this[c].nodeType&&(" "+this[c].className+" ").replace(ub," ").indexOf(b)>=0)return!0;return!1}}),m.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){m.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),m.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}});var vb=m.now(),wb=/\?/,xb=/(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;m.parseJSON=function(b){if(a.JSON&&a.JSON.parse)return a.JSON.parse(b+"");var c,d=null,e=m.trim(b+"");return e&&!m.trim(e.replace(xb,function(a,b,e,f){return c&&b&&(d=0),0===d?a:(c=e||b,d+=!f-!e,"")}))?Function("return "+e)():m.error("Invalid JSON: "+b)},m.parseXML=function(b){var c,d;if(!b||"string"!=typeof b)return null;try{a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b))}catch(e){c=void 0}return c&&c.documentElement&&!c.getElementsByTagName("parsererror").length||m.error("Invalid XML: "+b),c};var yb,zb,Ab=/#.*$/,Bb=/([?&])_=[^&]*/,Cb=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Db=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Eb=/^(?:GET|HEAD)$/,Fb=/^\/\//,Gb=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,Hb={},Ib={},Jb="*/".concat("*");try{zb=location.href}catch(Kb){zb=y.createElement("a"),zb.href="",zb=zb.href}yb=Gb.exec(zb.toLowerCase())||[];function Lb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(E)||[];if(m.isFunction(c))while(d=f[e++])"+"===d.charAt(0)?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Mb(a,b,c,d){var e={},f=a===Ib;function g(h){var i;return e[h]=!0,m.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Nb(a,b){var c,d,e=m.ajaxSettings.flatOptions||{};for(d in b)void 0!==b[d]&&((e[d]?a:c||(c={}))[d]=b[d]);return c&&m.extend(!0,a,c),a}function Ob(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===e&&(e=a.mimeType||b.getResponseHeader("Content-Type"));if(e)for(g in h)if(h[g]&&h[g].test(e)){i.unshift(g);break}if(i[0]in c)f=i[0];else{for(g in c){if(!i[0]||a.converters[g+" "+i[0]]){f=g;break}d||(d=g)}f=f||d}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function Pb(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}m.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:zb,type:"GET",isLocal:Db.test(yb[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Jb,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":m.parseJSON,"text xml":m.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Nb(Nb(a,m.ajaxSettings),b):Nb(m.ajaxSettings,a)},ajaxPrefilter:Lb(Hb),ajaxTransport:Lb(Ib),ajax:function(a,b){"object"==typeof a&&(b=a,a=void 0),b=b||{};var c,d,e,f,g,h,i,j,k=m.ajaxSetup({},b),l=k.context||k,n=k.context&&(l.nodeType||l.jquery)?m(l):m.event,o=m.Deferred(),p=m.Callbacks("once memory"),q=k.statusCode||{},r={},s={},t=0,u="canceled",v={readyState:0,getResponseHeader:function(a){var b;if(2===t){if(!j){j={};while(b=Cb.exec(f))j[b[1].toLowerCase()]=b[2]}b=j[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===t?f:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return t||(a=s[c]=s[c]||a,r[a]=b),this},overrideMimeType:function(a){return t||(k.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>t)for(b in a)q[b]=[q[b],a[b]];else v.always(a[v.status]);return this},abort:function(a){var b=a||u;return i&&i.abort(b),x(0,b),this}};if(o.promise(v).complete=p.add,v.success=v.done,v.error=v.fail,k.url=((a||k.url||zb)+"").replace(Ab,"").replace(Fb,yb[1]+"//"),k.type=b.method||b.type||k.method||k.type,k.dataTypes=m.trim(k.dataType||"*").toLowerCase().match(E)||[""],null==k.crossDomain&&(c=Gb.exec(k.url.toLowerCase()),k.crossDomain=!(!c||c[1]===yb[1]&&c[2]===yb[2]&&(c[3]||("http:"===c[1]?"80":"443"))===(yb[3]||("http:"===yb[1]?"80":"443")))),k.data&&k.processData&&"string"!=typeof k.data&&(k.data=m.param(k.data,k.traditional)),Mb(Hb,k,b,v),2===t)return v;h=m.event&&k.global,h&&0===m.active++&&m.event.trigger("ajaxStart"),k.type=k.type.toUpperCase(),k.hasContent=!Eb.test(k.type),e=k.url,k.hasContent||(k.data&&(e=k.url+=(wb.test(e)?"&":"?")+k.data,delete k.data),k.cache===!1&&(k.url=Bb.test(e)?e.replace(Bb,"$1_="+vb++):e+(wb.test(e)?"&":"?")+"_="+vb++)),k.ifModified&&(m.lastModified[e]&&v.setRequestHeader("If-Modified-Since",m.lastModified[e]),m.etag[e]&&v.setRequestHeader("If-None-Match",m.etag[e])),(k.data&&k.hasContent&&k.contentType!==!1||b.contentType)&&v.setRequestHeader("Content-Type",k.contentType),v.setRequestHeader("Accept",k.dataTypes[0]&&k.accepts[k.dataTypes[0]]?k.accepts[k.dataTypes[0]]+("*"!==k.dataTypes[0]?", "+Jb+"; q=0.01":""):k.accepts["*"]);for(d in k.headers)v.setRequestHeader(d,k.headers[d]);if(k.beforeSend&&(k.beforeSend.call(l,v,k)===!1||2===t))return v.abort();u="abort";for(d in{success:1,error:1,complete:1})v[d](k[d]);if(i=Mb(Ib,k,b,v)){v.readyState=1,h&&n.trigger("ajaxSend",[v,k]),k.async&&k.timeout>0&&(g=setTimeout(function(){v.abort("timeout")},k.timeout));try{t=1,i.send(r,x)}catch(w){if(!(2>t))throw w;x(-1,w)}}else x(-1,"No Transport");function x(a,b,c,d){var j,r,s,u,w,x=b;2!==t&&(t=2,g&&clearTimeout(g),i=void 0,f=d||"",v.readyState=a>0?4:0,j=a>=200&&300>a||304===a,c&&(u=Ob(k,v,c)),u=Pb(k,u,v,j),j?(k.ifModified&&(w=v.getResponseHeader("Last-Modified"),w&&(m.lastModified[e]=w),w=v.getResponseHeader("etag"),w&&(m.etag[e]=w)),204===a||"HEAD"===k.type?x="nocontent":304===a?x="notmodified":(x=u.state,r=u.data,s=u.error,j=!s)):(s=x,(a||!x)&&(x="error",0>a&&(a=0))),v.status=a,v.statusText=(b||x)+"",j?o.resolveWith(l,[r,x,v]):o.rejectWith(l,[v,x,s]),v.statusCode(q),q=void 0,h&&n.trigger(j?"ajaxSuccess":"ajaxError",[v,k,j?r:s]),p.fireWith(l,[v,x]),h&&(n.trigger("ajaxComplete",[v,k]),--m.active||m.event.trigger("ajaxStop")))}return v},getJSON:function(a,b,c){return m.get(a,b,c,"json")},getScript:function(a,b){return m.get(a,void 0,b,"script")}}),m.each(["get","post"],function(a,b){m[b]=function(a,c,d,e){return m.isFunction(c)&&(e=e||d,d=c,c=void 0),m.ajax({url:a,type:b,dataType:e,data:c,success:d})}}),m._evalUrl=function(a){return m.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},m.fn.extend({wrapAll:function(a){if(m.isFunction(a))return this.each(function(b){m(this).wrapAll(a.call(this,b))});if(this[0]){var b=m(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&1===a.firstChild.nodeType)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return this.each(m.isFunction(a)?function(b){m(this).wrapInner(a.call(this,b))}:function(){var b=m(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=m.isFunction(a);return this.each(function(c){m(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){m.nodeName(this,"body")||m(this).replaceWith(this.childNodes)}).end()}}),m.expr.filters.hidden=function(a){return a.offsetWidth<=0&&a.offsetHeight<=0||!k.reliableHiddenOffsets()&&"none"===(a.style&&a.style.display||m.css(a,"display"))},m.expr.filters.visible=function(a){return!m.expr.filters.hidden(a)};var Qb=/%20/g,Rb=/\[\]$/,Sb=/\r?\n/g,Tb=/^(?:submit|button|image|reset|file)$/i,Ub=/^(?:input|select|textarea|keygen)/i;function Vb(a,b,c,d){var e;if(m.isArray(b))m.each(b,function(b,e){c||Rb.test(a)?d(a,e):Vb(a+"["+("object"==typeof e?b:"")+"]",e,c,d)});else if(c||"object"!==m.type(b))d(a,b);else for(e in b)Vb(a+"["+e+"]",b[e],c,d)}m.param=function(a,b){var c,d=[],e=function(a,b){b=m.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=m.ajaxSettings&&m.ajaxSettings.traditional),m.isArray(a)||a.jquery&&!m.isPlainObject(a))m.each(a,function(){e(this.name,this.value)});else for(c in a)Vb(c,a[c],b,e);return d.join("&").replace(Qb,"+")},m.fn.extend({serialize:function(){return m.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=m.prop(this,"elements");return a?m.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!m(this).is(":disabled")&&Ub.test(this.nodeName)&&!Tb.test(a)&&(this.checked||!W.test(a))}).map(function(a,b){var c=m(this).val();return null==c?null:m.isArray(c)?m.map(c,function(a){return{name:b.name,value:a.replace(Sb,"\r\n")}}):{name:b.name,value:c.replace(Sb,"\r\n")}}).get()}}),m.ajaxSettings.xhr=void 0!==a.ActiveXObject?function(){return!this.isLocal&&/^(get|post|head|put|delete|options)$/i.test(this.type)&&Zb()||$b()}:Zb;var Wb=0,Xb={},Yb=m.ajaxSettings.xhr();a.attachEvent&&a.attachEvent("onunload",function(){for(var a in Xb)Xb[a](void 0,!0)}),k.cors=!!Yb&&"withCredentials"in Yb,Yb=k.ajax=!!Yb,Yb&&m.ajaxTransport(function(a){if(!a.crossDomain||k.cors){var b;return{send:function(c,d){var e,f=a.xhr(),g=++Wb;if(f.open(a.type,a.url,a.async,a.username,a.password),a.xhrFields)for(e in a.xhrFields)f[e]=a.xhrFields[e];a.mimeType&&f.overrideMimeType&&f.overrideMimeType(a.mimeType),a.crossDomain||c["X-Requested-With"]||(c["X-Requested-With"]="XMLHttpRequest");for(e in c)void 0!==c[e]&&f.setRequestHeader(e,c[e]+"");f.send(a.hasContent&&a.data||null),b=function(c,e){var h,i,j;if(b&&(e||4===f.readyState))if(delete Xb[g],b=void 0,f.onreadystatechange=m.noop,e)4!==f.readyState&&f.abort();else{j={},h=f.status,"string"==typeof f.responseText&&(j.text=f.responseText);try{i=f.statusText}catch(k){i=""}h||!a.isLocal||a.crossDomain?1223===h&&(h=204):h=j.text?200:404}j&&d(h,i,j,f.getAllResponseHeaders())},a.async?4===f.readyState?setTimeout(b):f.onreadystatechange=Xb[g]=b:b()},abort:function(){b&&b(void 0,!0)}}}});function Zb(){try{return new a.XMLHttpRequest}catch(b){}}function $b(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}m.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(a){return m.globalEval(a),a}}}),m.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),m.ajaxTransport("script",function(a){if(a.crossDomain){var b,c=y.head||m("head")[0]||y.documentElement;return{send:function(d,e){b=y.createElement("script"),b.async=!0,a.scriptCharset&&(b.charset=a.scriptCharset),b.src=a.url,b.onload=b.onreadystatechange=function(a,c){(c||!b.readyState||/loaded|complete/.test(b.readyState))&&(b.onload=b.onreadystatechange=null,b.parentNode&&b.parentNode.removeChild(b),b=null,c||e(200,"success"))},c.insertBefore(b,c.firstChild)},abort:function(){b&&b.onload(void 0,!0)}}}});var _b=[],ac=/(=)\?(?=&|$)|\?\?/;m.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=_b.pop()||m.expando+"_"+vb++;return this[a]=!0,a}}),m.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(ac.test(b.url)?"url":"string"==typeof b.data&&!(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&ac.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=m.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(ac,"$1"+e):b.jsonp!==!1&&(b.url+=(wb.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||m.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,_b.push(e)),g&&m.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),m.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||y;var d=u.exec(a),e=!c&&[];return d?[b.createElement(d[1])]:(d=m.buildFragment([a],b,e),e&&e.length&&m(e).remove(),m.merge([],d.childNodes))};var bc=m.fn.load;m.fn.load=function(a,b,c){if("string"!=typeof a&&bc)return bc.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>=0&&(d=m.trim(a.slice(h,a.length)),a=a.slice(0,h)),m.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(f="POST"),g.length>0&&m.ajax({url:a,type:f,dataType:"html",data:b}).done(function(a){e=arguments,g.html(d?m("<div>").append(m.parseHTML(a)).find(d):a)}).complete(c&&function(a,b){g.each(c,e||[a.responseText,b,a])}),this},m.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){m.fn[b]=function(a){return this.on(b,a)}}),m.expr.filters.animated=function(a){return m.grep(m.timers,function(b){return a===b.elem}).length};var cc=a.document.documentElement;function dc(a){return m.isWindow(a)?a:9===a.nodeType?a.defaultView||a.parentWindow:!1}m.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=m.css(a,"position"),l=m(a),n={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=m.css(a,"top"),i=m.css(a,"left"),j=("absolute"===k||"fixed"===k)&&m.inArray("auto",[f,i])>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),m.isFunction(b)&&(b=b.call(a,c,h)),null!=b.top&&(n.top=b.top-h.top+g),null!=b.left&&(n.left=b.left-h.left+e),"using"in b?b.using.call(a,n):l.css(n)}},m.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){m.offset.setOffset(this,a,b)});var b,c,d={top:0,left:0},e=this[0],f=e&&e.ownerDocument;if(f)return b=f.documentElement,m.contains(b,e)?(typeof e.getBoundingClientRect!==K&&(d=e.getBoundingClientRect()),c=dc(f),{top:d.top+(c.pageYOffset||b.scrollTop)-(b.clientTop||0),left:d.left+(c.pageXOffset||b.scrollLeft)-(b.clientLeft||0)}):d},position:function(){if(this[0]){var a,b,c={top:0,left:0},d=this[0];return"fixed"===m.css(d,"position")?b=d.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),m.nodeName(a[0],"html")||(c=a.offset()),c.top+=m.css(a[0],"borderTopWidth",!0),c.left+=m.css(a[0],"borderLeftWidth",!0)),{top:b.top-c.top-m.css(d,"marginTop",!0),left:b.left-c.left-m.css(d,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||cc;while(a&&!m.nodeName(a,"html")&&"static"===m.css(a,"position"))a=a.offsetParent;return a||cc})}}),m.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c=/Y/.test(b);m.fn[a]=function(d){return V(this,function(a,d,e){var f=dc(a);return void 0===e?f?b in f?f[b]:f.document.documentElement[d]:a[d]:void(f?f.scrollTo(c?m(f).scrollLeft():e,c?e:m(f).scrollTop()):a[d]=e)},a,d,arguments.length,null)}}),m.each(["top","left"],function(a,b){m.cssHooks[b]=La(k.pixelPosition,function(a,c){return c?(c=Ja(a,b),Ha.test(c)?m(a).position()[b]+"px":c):void 0})}),m.each({Height:"height",Width:"width"},function(a,b){m.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){m.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return V(this,function(b,c,d){var e;return m.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?m.css(b,c,g):m.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),m.fn.size=function(){return this.length},m.fn.andSelf=m.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return m});var ec=a.jQuery,fc=a.$;return m.noConflict=function(b){return a.$===m&&(a.$=fc),b&&a.jQuery===m&&(a.jQuery=ec),m},typeof b===K&&(a.jQuery=a.$=m),m});
\ No newline at end of file +/*! jQuery v1.12.0 | (c) jQuery Foundation | jquery.org/license */ +!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=a.document,e=c.slice,f=c.concat,g=c.push,h=c.indexOf,i={},j=i.toString,k=i.hasOwnProperty,l={},m="1.12.0",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return e.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:e.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a){return n.each(this,a)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(e.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:g,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(n.isPlainObject(c)||(b=n.isArray(c)))?(b?(b=!1,f=a&&n.isArray(a)?a:[]):f=a&&n.isPlainObject(a)?a:{},g[d]=n.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray||function(a){return"array"===n.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){var b=a&&a.toString();return!n.isArray(a)&&b-parseFloat(b)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;try{if(a.constructor&&!k.call(a,"constructor")&&!k.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(!l.ownFirst)for(b in a)return k.call(a,b);for(b in a);return void 0===b||k.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?i[j.call(a)]||"object":typeof a},globalEval:function(b){b&&n.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b){var c,d=0;if(s(a)){for(c=a.length;c>d;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):g.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(h)return h.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,g=0,h=[];if(s(a))for(d=a.length;d>g;g++)e=b(a[g],g,c),null!=e&&h.push(e);else for(g in a)e=b(a[g],g,c),null!=e&&h.push(e);return f.apply([],h)},guid:1,proxy:function(a,b){var c,d,f;return"string"==typeof b&&(f=a[b],b=a,a=f),n.isFunction(a)?(c=e.call(arguments,2),d=function(){return a.apply(b||this,c.concat(e.call(arguments)))},d.guid=a.guid=a.guid||n.guid++,d):void 0},now:function(){return+new Date},support:l}),"function"==typeof Symbol&&(n.fn[Symbol.iterator]=c[Symbol.iterator]),n.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){i["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=!!a&&"length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ga(),z=ga(),A=ga(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+M+"))|)"+L+"*\\]",O=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+N+")*)|.*)\\)|)",P=new RegExp(L+"+","g"),Q=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),R=new RegExp("^"+L+"*,"+L+"*"),S=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),T=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),U=new RegExp(O),V=new RegExp("^"+M+"$"),W={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M+"|[*])"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},X=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Z=/^[^{]+\{\s*\[native \w/,$=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,_=/[+~]/,aa=/'|\\/g,ba=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),ca=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},da=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(ea){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fa(a,b,d,e){var f,h,j,k,l,o,r,s,w=b&&b.ownerDocument,x=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==x&&9!==x&&11!==x)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==x&&(o=$.exec(a)))if(f=o[1]){if(9===x){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(w&&(j=w.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(o[2])return H.apply(d,b.getElementsByTagName(a)),d;if((f=o[3])&&c.getElementsByClassName&&b.getElementsByClassName)return H.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==x)w=b,s=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(aa,"\\$&"):b.setAttribute("id",k=u),r=g(a),h=r.length,l=V.test(k)?"#"+k:"[id='"+k+"']";while(h--)r[h]=l+" "+qa(r[h]);s=r.join(","),w=_.test(a)&&oa(b.parentNode)||b}if(s)try{return H.apply(d,w.querySelectorAll(s)),d}catch(y){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(Q,"$1"),b,d,e)}function ga(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ha(a){return a[u]=!0,a}function ia(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ja(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function ka(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function la(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function na(a){return ha(function(b){return b=+b,ha(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function oa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=fa.support={},f=fa.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fa.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ia(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ia(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Z.test(n.getElementsByClassName),c.getById=ia(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return"undefined"!=typeof b.getElementsByClassName&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=Z.test(n.querySelectorAll))&&(ia(function(a){o.appendChild(a).innerHTML="<a id='"+u+"'></a><select id='"+u+"-\r\\' msallowcapture=''><option selected=''></option></select>",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ia(function(a){var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Z.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ia(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",O)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Z.test(o.compareDocumentPosition),t=b||Z.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return ka(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?ka(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},fa.matches=function(a,b){return fa(a,null,null,b)},fa.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(T,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fa(b,n,null,[a]).length>0},fa.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fa.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fa.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fa.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fa.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fa.selectors={cacheLength:50,createPseudo:ha,match:W,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ba,ca),a[3]=(a[3]||a[4]||a[5]||"").replace(ba,ca),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fa.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fa.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return W.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&U.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ba,ca).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fa.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(P," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fa.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ha(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ha(function(a){var b=[],c=[],d=h(a.replace(Q,"$1"));return d[u]?ha(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ha(function(a){return function(b){return fa(a,b).length>0}}),contains:ha(function(a){return a=a.replace(ba,ca),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ha(function(a){return V.test(a||"")||fa.error("unsupported lang: "+a),a=a.replace(ba,ca).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Y.test(a.nodeName)},input:function(a){return X.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:na(function(){return[0]}),last:na(function(a,b){return[b-1]}),eq:na(function(a,b,c){return[0>c?c+b:c]}),even:na(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:na(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:na(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:na(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=la(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=ma(b);function pa(){}pa.prototype=d.filters=d.pseudos,d.setFilters=new pa,g=fa.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){(!c||(e=R.exec(h)))&&(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=S.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(Q," ")}),h=h.slice(c.length));for(g in d.filter)!(e=W[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?fa.error(a):z(a,i).slice(0)};function qa(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function ra(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j,k=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(j=b[u]||(b[u]={}),i=j[b.uniqueID]||(j[b.uniqueID]={}),(h=i[d])&&h[0]===w&&h[1]===f)return k[2]=h[2];if(i[d]=k,k[2]=a(b,c,g))return!0}}}function sa(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ta(a,b,c){for(var d=0,e=b.length;e>d;d++)fa(a,b[d],c);return c}function ua(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function va(a,b,c,d,e,f){return d&&!d[u]&&(d=va(d)),e&&!e[u]&&(e=va(e,f)),ha(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ta(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ua(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ua(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ua(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function wa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ra(function(a){return a===b},h,!0),l=ra(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[ra(sa(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return va(i>1&&sa(m),i>1&&qa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(Q,"$1"),c,e>i&&wa(a.slice(i,e)),f>e&&wa(a=a.slice(e)),f>e&&qa(a))}m.push(c)}return sa(m)}function xa(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=F.call(i));u=ua(u)}H.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&fa.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ha(f):f}return h=fa.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xa(e,d)),f.selector=a}return f},i=fa.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ba,ca),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=W.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ba,ca),_.test(j[0].type)&&oa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qa(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||_.test(a)&&oa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ia(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ia(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||ja("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ia(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ja("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ia(function(a){return null==a.getAttribute("disabled")})||ja(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fa}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.uniqueSort=n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},v=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},w=n.expr.match.needsContext,x=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,y=/^.[^:#\[\.,]*$/;function z(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(y.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return n.inArray(a,b)>-1!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;e>b;b++)if(n.contains(d[b],this))return!0}));for(b=0;e>b;b++)n.find(a,d[b],c);return c=this.pushStack(e>1?n.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(z(this,a||[],!1))},not:function(a){return this.pushStack(z(this,a||[],!0))},is:function(a){return!!z(this,"string"==typeof a&&w.test(a)?n(a):a||[],!1).length}});var A,B=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=n.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||A,"string"==typeof a){if(e="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:B.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),x.test(e[1])&&n.isPlainObject(b))for(e in b)n.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}if(f=d.getElementById(e[2]),f&&f.parentNode){if(f.id!==e[2])return A.find(a);this.length=1,this[0]=f}return this.context=d,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof c.ready?c.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};C.prototype=n.fn,A=n(d);var D=/^(?:parents|prev(?:Until|All))/,E={children:!0,contents:!0,next:!0,prev:!0};n.fn.extend({has:function(a){var b,c=n(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(n.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=w.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?n.inArray(this[0],n(a)):n.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.uniqueSort(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function F(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return u(a,"parentNode")},parentsUntil:function(a,b,c){return u(a,"parentNode",c)},next:function(a){return F(a,"nextSibling")},prev:function(a){return F(a,"previousSibling")},nextAll:function(a){return u(a,"nextSibling")},prevAll:function(a){return u(a,"previousSibling")},nextUntil:function(a,b,c){return u(a,"nextSibling",c)},prevUntil:function(a,b,c){return u(a,"previousSibling",c)},siblings:function(a){return v((a.parentNode||{}).firstChild,a)},children:function(a){return v(a.firstChild)},contents:function(a){return n.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(E[a]||(e=n.uniqueSort(e)),D.test(a)&&(e=e.reverse())),this.pushStack(e)}});var G=/\S+/g;function H(a){var b={};return n.each(a.match(G)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?H(a):n.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h<f.length)f[h].apply(c[0],c[1])===!1&&a.stopOnFalse&&(h=f.length,c=!1)}a.memory||(c=!1),b=!1,e&&(f=c?[]:"")},j={add:function(){return f&&(c&&!b&&(h=f.length-1,g.push(c)),function d(b){n.each(b,function(b,c){n.isFunction(c)?a.unique&&j.has(c)||f.push(c):c&&c.length&&"string"!==n.type(c)&&d(c)})}(arguments),c&&!b&&i()),this},remove:function(){return n.each(arguments,function(a,b){var c;while((c=n.inArray(b,f,c))>-1)f.splice(c,1),h>=c&&h--}),this},has:function(a){return a?n.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=!0,c||j.disable(),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().progress(c.notify).done(c.resolve).fail(c.reject):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=e.call(arguments),d=c.length,f=1!==d||a&&n.isFunction(a.promise)?d:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?e.call(arguments):d,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(d>1)for(i=new Array(d),j=new Array(d),k=new Array(d);d>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().progress(h(b,j,i)).done(h(b,k,c)).fail(g.reject):--f;return f||g.resolveWith(k,c),g.promise()}});var I;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(I.resolveWith(d,[n]),n.fn.triggerHandler&&(n(d).triggerHandler("ready"),n(d).off("ready"))))}});function J(){d.addEventListener?(d.removeEventListener("DOMContentLoaded",K),a.removeEventListener("load",K)):(d.detachEvent("onreadystatechange",K),a.detachEvent("onload",K))}function K(){(d.addEventListener||"load"===a.event.type||"complete"===d.readyState)&&(J(),n.ready())}n.ready.promise=function(b){if(!I)if(I=n.Deferred(),"complete"===d.readyState)a.setTimeout(n.ready);else if(d.addEventListener)d.addEventListener("DOMContentLoaded",K),a.addEventListener("load",K);else{d.attachEvent("onreadystatechange",K),a.attachEvent("onload",K);var c=!1;try{c=null==a.frameElement&&d.documentElement}catch(e){}c&&c.doScroll&&!function f(){if(!n.isReady){try{c.doScroll("left")}catch(b){return a.setTimeout(f,50)}J(),n.ready()}}()}return I.promise(b)},n.ready.promise();var L;for(L in n(l))break;l.ownFirst="0"===L,l.inlineBlockNeedsLayout=!1,n(function(){var a,b,c,e;c=d.getElementsByTagName("body")[0],c&&c.style&&(b=d.createElement("div"),e=d.createElement("div"),e.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(e).appendChild(b),"undefined"!=typeof b.style.zoom&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",l.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(e))}),function(){var a=d.createElement("div");l.deleteExpando=!0;try{delete a.test}catch(b){l.deleteExpando=!1}a=null}();var M=function(a){var b=n.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b},N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(O,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}n.data(a,b,c)}else c=void 0}return c}function Q(a){var b;for(b in a)if(("data"!==b||!n.isEmptyObject(a[b]))&&"toJSON"!==b)return!1; +return!0}function R(a,b,d,e){if(M(a)){var f,g,h=n.expando,i=a.nodeType,j=i?n.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||n.guid++:h),j[k]||(j[k]=i?{}:{toJSON:n.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=n.extend(j[k],b):j[k].data=n.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[n.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[n.camelCase(b)])):f=g,f}}function S(a,b,c){if(M(a)){var d,e,f=a.nodeType,g=f?n.cache:a,h=f?a[n.expando]:n.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){n.isArray(b)?b=b.concat(n.map(b,n.camelCase)):b in d?b=[b]:(b=n.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!Q(d):!n.isEmptyObject(d))return}(c||(delete g[h].data,Q(g[h])))&&(f?n.cleanData([a],!0):l.deleteExpando||g!=g.window?delete g[h]:g[h]=void 0)}}}n.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?n.cache[a[n.expando]]:a[n.expando],!!a&&!Q(a)},data:function(a,b,c){return R(a,b,c)},removeData:function(a,b){return S(a,b)},_data:function(a,b,c){return R(a,b,c,!0)},_removeData:function(a,b){return S(a,b,!0)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=n.data(f),1===f.nodeType&&!n._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));n._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){n.data(this,a)}):arguments.length>1?this.each(function(){n.data(this,a,b)}):f?P(f,a,n.data(f,a)):void 0},removeData:function(a){return this.each(function(){n.removeData(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=n._data(a,b),c&&(!d||n.isArray(c)?d=n._data(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return n._data(a,c)||n._data(a,c,{empty:n.Callbacks("once memory").add(function(){n._removeData(a,b+"queue"),n._removeData(a,c)})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?n.queue(this[0],a):void 0===b?this:this.each(function(){var c=n.queue(this,a,b);n._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&n.dequeue(this,a)})},dequeue:function(a){return this.each(function(){n.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=n.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=n._data(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}}),function(){var a;l.shrinkWrapBlocks=function(){if(null!=a)return a;a=!1;var b,c,e;return c=d.getElementsByTagName("body")[0],c&&c.style?(b=d.createElement("div"),e=d.createElement("div"),e.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(e).appendChild(b),"undefined"!=typeof b.style.zoom&&(b.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:1px;width:1px;zoom:1",b.appendChild(d.createElement("div")).style.width="5px",a=3!==b.offsetWidth),c.removeChild(e),a):void 0}}();var T=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,U=new RegExp("^(?:([+-])=|)("+T+")([a-z%]*)$","i"),V=["Top","Right","Bottom","Left"],W=function(a,b){return a=b||a,"none"===n.css(a,"display")||!n.contains(a.ownerDocument,a)};function X(a,b,c,d){var e,f=1,g=20,h=d?function(){return d.cur()}:function(){return n.css(a,b,"")},i=h(),j=c&&c[3]||(n.cssNumber[b]?"":"px"),k=(n.cssNumber[b]||"px"!==j&&+i)&&U.exec(n.css(a,b));if(k&&k[3]!==j){j=j||k[3],c=c||[],k=+i||1;do f=f||".5",k/=f,n.style(a,b,k+j);while(f!==(f=h()/i)&&1!==f&&--g)}return c&&(k=+k||+i||0,e=c[1]?k+(c[1]+1)*c[2]:+c[2],d&&(d.unit=j,d.start=k,d.end=e)),e}var Y=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)Y(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},Z=/^(?:checkbox|radio)$/i,$=/<([\w:-]+)/,_=/^$|\/(?:java|ecma)script/i,aa=/^\s+/,ba="abbr|article|aside|audio|bdi|canvas|data|datalist|details|dialog|figcaption|figure|footer|header|hgroup|main|mark|meter|nav|output|picture|progress|section|summary|template|time|video";function ca(a){var b=ba.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}!function(){var a=d.createElement("div"),b=d.createDocumentFragment(),c=d.createElement("input");a.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",l.leadingWhitespace=3===a.firstChild.nodeType,l.tbody=!a.getElementsByTagName("tbody").length,l.htmlSerialize=!!a.getElementsByTagName("link").length,l.html5Clone="<:nav></:nav>"!==d.createElement("nav").cloneNode(!0).outerHTML,c.type="checkbox",c.checked=!0,b.appendChild(c),l.appendChecked=c.checked,a.innerHTML="<textarea>x</textarea>",l.noCloneChecked=!!a.cloneNode(!0).lastChild.defaultValue,b.appendChild(a),c=d.createElement("input"),c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),a.appendChild(c),l.checkClone=a.cloneNode(!0).cloneNode(!0).lastChild.checked,l.noCloneEvent=!!a.addEventListener,a[n.expando]=1,l.attributes=!a.getAttribute(n.expando)}();var da={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:l.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]};da.optgroup=da.option,da.tbody=da.tfoot=da.colgroup=da.caption=da.thead,da.th=da.td;function ea(a,b){var c,d,e=0,f="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||n.nodeName(d,b)?f.push(d):n.merge(f,ea(d,b));return void 0===b||b&&n.nodeName(a,b)?n.merge([a],f):f}function fa(a,b){for(var c,d=0;null!=(c=a[d]);d++)n._data(c,"globalEval",!b||n._data(b[d],"globalEval"))}var ga=/<|&#?\w+;/,ha=/<tbody/i;function ia(a){Z.test(a.type)&&(a.defaultChecked=a.checked)}function ja(a,b,c,d,e){for(var f,g,h,i,j,k,m,o=a.length,p=ca(b),q=[],r=0;o>r;r++)if(g=a[r],g||0===g)if("object"===n.type(g))n.merge(q,g.nodeType?[g]:g);else if(ga.test(g)){i=i||p.appendChild(b.createElement("div")),j=($.exec(g)||["",""])[1].toLowerCase(),m=da[j]||da._default,i.innerHTML=m[1]+n.htmlPrefilter(g)+m[2],f=m[0];while(f--)i=i.lastChild;if(!l.leadingWhitespace&&aa.test(g)&&q.push(b.createTextNode(aa.exec(g)[0])),!l.tbody){g="table"!==j||ha.test(g)?"<table>"!==m[1]||ha.test(g)?0:i:i.firstChild,f=g&&g.childNodes.length;while(f--)n.nodeName(k=g.childNodes[f],"tbody")&&!k.childNodes.length&&g.removeChild(k)}n.merge(q,i.childNodes),i.textContent="";while(i.firstChild)i.removeChild(i.firstChild);i=p.lastChild}else q.push(b.createTextNode(g));i&&p.removeChild(i),l.appendChecked||n.grep(ea(q,"input"),ia),r=0;while(g=q[r++])if(d&&n.inArray(g,d)>-1)e&&e.push(g);else if(h=n.contains(g.ownerDocument,g),i=ea(p.appendChild(g),"script"),h&&fa(i),c){f=0;while(g=i[f++])_.test(g.type||"")&&c.push(g)}return i=null,p}!function(){var b,c,e=d.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(l[b]=c in a)||(e.setAttribute(c,"t"),l[b]=e.attributes[c].expando===!1);e=null}();var ka=/^(?:input|select|textarea)$/i,la=/^key/,ma=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,na=/^(?:focusinfocus|focusoutblur)$/,oa=/^([^.]*)(?:\.(.+)|)/;function pa(){return!0}function qa(){return!1}function ra(){try{return d.activeElement}catch(a){}}function sa(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)sa(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=qa;else if(!e)return a;return 1===f&&(g=e,e=function(a){return n().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=n.guid++)),a.each(function(){n.event.add(this,b,e,d,c)})}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=n.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return"undefined"==typeof n||a&&n.event.triggered===a.type?void 0:n.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(G)||[""],h=b.length;while(h--)f=oa.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=n.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=n.event.special[o]||{},l=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},i),(m=g[o])||(m=g[o]=[],m.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,l):m.push(l),n.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n.hasData(a)&&n._data(a);if(r&&(k=r.events)){b=(b||"").match(G)||[""],j=b.length;while(j--)if(h=oa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=m.length;while(f--)g=m[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(m.splice(f,1),g.selector&&m.delegateCount--,l.remove&&l.remove.call(a,g));i&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(k)&&(delete r.handle,n._removeData(a,"events"))}},trigger:function(b,c,e,f){var g,h,i,j,l,m,o,p=[e||d],q=k.call(b,"type")?b.type:b,r=k.call(b,"namespace")?b.namespace.split("."):[];if(i=m=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!na.test(q+n.event.triggered)&&(q.indexOf(".")>-1&&(r=q.split("."),q=r.shift(),r.sort()),h=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=r.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:n.makeArray(c,[b]),l=n.event.special[q]||{},f||!l.trigger||l.trigger.apply(e,c)!==!1)){if(!f&&!l.noBubble&&!n.isWindow(e)){for(j=l.delegateType||q,na.test(j+q)||(i=i.parentNode);i;i=i.parentNode)p.push(i),m=i;m===(e.ownerDocument||d)&&p.push(m.defaultView||m.parentWindow||a)}o=0;while((i=p[o++])&&!b.isPropagationStopped())b.type=o>1?j:l.bindType||q,g=(n._data(i,"events")||{})[b.type]&&n._data(i,"handle"),g&&g.apply(i,c),g=h&&i[h],g&&g.apply&&M(i)&&(b.result=g.apply(i,c),b.result===!1&&b.preventDefault());if(b.type=q,!f&&!b.isDefaultPrevented()&&(!l._default||l._default.apply(p.pop(),c)===!1)&&M(e)&&h&&e[q]&&!n.isWindow(e)){m=e[h],m&&(e[h]=null),n.event.triggered=q;try{e[q]()}catch(s){}n.event.triggered=void 0,m&&(e[h]=m)}return b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,d,f,g,h=[],i=e.call(arguments),j=(n._data(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.rnamespace||a.rnamespace.test(g.namespace))&&(a.handleObj=g,a.data=g.data,d=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==d&&(a.result=d)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&("click"!==a.type||isNaN(a.button)||a.button<1))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>-1:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},fix:function(a){if(a[n.expando])return a;var b,c,e,f=a.type,g=a,h=this.fixHooks[f];h||(this.fixHooks[f]=h=ma.test(f)?this.mouseHooks:la.test(f)?this.keyHooks:{}),e=h.props?this.props.concat(h.props):this.props,a=new n.Event(g),b=e.length;while(b--)c=e[b],a[c]=g[c];return a.target||(a.target=g.srcElement||d),3===a.target.nodeType&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,h.filter?h.filter(a,g):a},props:"altKey bubbles cancelable ctrlKey currentTarget detail eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,e,f,g=b.button,h=b.fromElement;return null==a.pageX&&null!=b.clientX&&(e=a.target.ownerDocument||d,f=e.documentElement,c=e.body,a.pageX=b.clientX+(f&&f.scrollLeft||c&&c.scrollLeft||0)-(f&&f.clientLeft||c&&c.clientLeft||0),a.pageY=b.clientY+(f&&f.scrollTop||c&&c.scrollTop||0)-(f&&f.clientTop||c&&c.clientTop||0)),!a.relatedTarget&&h&&(a.relatedTarget=h===a.target?b.toElement:h),a.which||void 0===g||(a.which=1&g?1:2&g?3:4&g?2:0),a}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==ra()&&this.focus)try{return this.focus(),!1}catch(a){}},delegateType:"focusin"},blur:{trigger:function(){return this===ra()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return n.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):void 0},_default:function(a){return n.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}},simulate:function(a,b,c){var d=n.extend(new n.Event,c,{type:a,isSimulated:!0});n.event.trigger(d,null,b),d.isDefaultPrevented()&&c.preventDefault()}},n.removeEvent=d.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c)}:function(a,b,c){var d="on"+b;a.detachEvent&&("undefined"==typeof a[d]&&(a[d]=null),a.detachEvent(d,c))},n.Event=function(a,b){return this instanceof n.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?pa:qa):this.type=a,b&&n.extend(this,b),this.timeStamp=a&&a.timeStamp||n.now(),void(this[n.expando]=!0)):new n.Event(a,b)},n.Event.prototype={constructor:n.Event,isDefaultPrevented:qa,isPropagationStopped:qa,isImmediatePropagationStopped:qa,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=pa,a&&(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=pa,a&&!this.isSimulated&&(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=pa,a&&a.stopImmediatePropagation&&a.stopImmediatePropagation(),this.stopPropagation()}},n.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){n.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return(!e||e!==d&&!n.contains(d,e))&&(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),l.submit||(n.event.special.submit={setup:function(){return n.nodeName(this,"form")?!1:void n.event.add(this,"click._submit keypress._submit",function(a){var b=a.target,c=n.nodeName(b,"input")||n.nodeName(b,"button")?n.prop(b,"form"):void 0;c&&!n._data(c,"submit")&&(n.event.add(c,"submit._submit",function(a){a._submitBubble=!0}),n._data(c,"submit",!0))})},postDispatch:function(a){a._submitBubble&&(delete a._submitBubble,this.parentNode&&!a.isTrigger&&n.event.simulate("submit",this.parentNode,a))},teardown:function(){return n.nodeName(this,"form")?!1:void n.event.remove(this,"._submit")}}),l.change||(n.event.special.change={setup:function(){return ka.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(n.event.add(this,"propertychange._change",function(a){"checked"===a.originalEvent.propertyName&&(this._justChanged=!0)}),n.event.add(this,"click._change",function(a){this._justChanged&&!a.isTrigger&&(this._justChanged=!1),n.event.simulate("change",this,a)})),!1):void n.event.add(this,"beforeactivate._change",function(a){var b=a.target;ka.test(b.nodeName)&&!n._data(b,"change")&&(n.event.add(b,"change._change",function(a){!this.parentNode||a.isSimulated||a.isTrigger||n.event.simulate("change",this.parentNode,a)}),n._data(b,"change",!0))})},handle:function(a){var b=a.target;return this!==b||a.isSimulated||a.isTrigger||"radio"!==b.type&&"checkbox"!==b.type?a.handleObj.handler.apply(this,arguments):void 0},teardown:function(){return n.event.remove(this,"._change"),!ka.test(this.nodeName)}}),l.focusin||n.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){n.event.simulate(b,a.target,n.event.fix(a))};n.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=n._data(d,b);e||d.addEventListener(a,c,!0),n._data(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=n._data(d,b)-1;e?n._data(d,b,e):(d.removeEventListener(a,c,!0),n._removeData(d,b))}}}),n.fn.extend({on:function(a,b,c,d){return sa(this,a,b,c,d)},one:function(a,b,c,d){return sa(this,a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,n(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return(b===!1||"function"==typeof b)&&(c=b,b=void 0),c===!1&&(c=qa),this.each(function(){n.event.remove(this,a,c,b)})},trigger:function(a,b){return this.each(function(){n.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?n.event.trigger(a,b,c,!0):void 0}});var ta=/ jQuery\d+="(?:null|\d+)"/g,ua=new RegExp("<(?:"+ba+")[\\s/>]","i"),va=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,wa=/<script|<style|<link/i,xa=/checked\s*(?:[^=]|=\s*.checked.)/i,ya=/^true\/(.*)/,za=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,Aa=ca(d),Ba=Aa.appendChild(d.createElement("div"));function Ca(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function Da(a){return a.type=(null!==n.find.attr(a,"type"))+"/"+a.type,a}function Ea(a){var b=ya.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Fa(a,b){if(1===b.nodeType&&n.hasData(a)){var c,d,e,f=n._data(a),g=n._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)n.event.add(b,c,h[c][d])}g.data&&(g.data=n.extend({},g.data))}}function Ga(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!l.noCloneEvent&&b[n.expando]){e=n._data(b);for(d in e.events)n.removeEvent(b,d,e.handle);b.removeAttribute(n.expando)}"script"===c&&b.text!==a.text?(Da(b).text=a.text,Ea(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),l.html5Clone&&a.innerHTML&&!n.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&Z.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}function Ha(a,b,c,d){b=f.apply([],b);var e,g,h,i,j,k,m=0,o=a.length,p=o-1,q=b[0],r=n.isFunction(q);if(r||o>1&&"string"==typeof q&&!l.checkClone&&xa.test(q))return a.each(function(e){var f=a.eq(e);r&&(b[0]=q.call(this,e,f.html())),Ha(f,b,c,d)});if(o&&(k=ja(b,a[0].ownerDocument,!1,a,d),e=k.firstChild,1===k.childNodes.length&&(k=e),e||d)){for(i=n.map(ea(k,"script"),Da),h=i.length;o>m;m++)g=k,m!==p&&(g=n.clone(g,!0,!0),h&&n.merge(i,ea(g,"script"))),c.call(a[m],g,m);if(h)for(j=i[i.length-1].ownerDocument,n.map(i,Ea),m=0;h>m;m++)g=i[m],_.test(g.type||"")&&!n._data(g,"globalEval")&&n.contains(j,g)&&(g.src?n._evalUrl&&n._evalUrl(g.src):n.globalEval((g.text||g.textContent||g.innerHTML||"").replace(za,"")));k=e=null}return a}function Ia(a,b,c){for(var d,e=b?n.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||n.cleanData(ea(d)),d.parentNode&&(c&&n.contains(d.ownerDocument,d)&&fa(ea(d,"script")),d.parentNode.removeChild(d));return a}n.extend({htmlPrefilter:function(a){return a.replace(va,"<$1></$2>")},clone:function(a,b,c){var d,e,f,g,h,i=n.contains(a.ownerDocument,a);if(l.html5Clone||n.isXMLDoc(a)||!ua.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(Ba.innerHTML=a.outerHTML,Ba.removeChild(f=Ba.firstChild)),!(l.noCloneEvent&&l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(d=ea(f),h=ea(a),g=0;null!=(e=h[g]);++g)d[g]&&Ga(e,d[g]);if(b)if(c)for(h=h||ea(a),d=d||ea(f),g=0;null!=(e=h[g]);g++)Fa(e,d[g]);else Fa(a,f);return d=ea(f,"script"),d.length>0&&fa(d,!i&&ea(a,"script")),d=h=e=null,f},cleanData:function(a,b){for(var d,e,f,g,h=0,i=n.expando,j=n.cache,k=l.attributes,m=n.event.special;null!=(d=a[h]);h++)if((b||M(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)m[e]?n.event.remove(d,e):n.removeEvent(d,e,g.handle);j[f]&&(delete j[f],k||"undefined"==typeof d.removeAttribute?d[i]=void 0:d.removeAttribute(i),c.push(f))}}}),n.fn.extend({domManip:Ha,detach:function(a){return Ia(this,a,!0)},remove:function(a){return Ia(this,a)},text:function(a){return Y(this,function(a){return void 0===a?n.text(this):this.empty().append((this[0]&&this[0].ownerDocument||d).createTextNode(a))},null,a,arguments.length)},append:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.appendChild(a)}})},prepend:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&n.cleanData(ea(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&n.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return Y(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(ta,""):void 0;if("string"==typeof a&&!wa.test(a)&&(l.htmlSerialize||!ua.test(a))&&(l.leadingWhitespace||!aa.test(a))&&!da[($.exec(a)||["",""])[1].toLowerCase()]){a=n.htmlPrefilter(a);try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ea(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return Ha(this,arguments,function(b){var c=this.parentNode;n.inArray(this,a)<0&&(n.cleanData(ea(this)),c&&c.replaceChild(b,this))},a)}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=0,e=[],f=n(a),h=f.length-1;h>=d;d++)c=d===h?this:this.clone(!0),n(f[d])[b](c),g.apply(e,c.get());return this.pushStack(e)}});var Ja,Ka={HTML:"block",BODY:"block"};function La(a,b){var c=n(b.createElement(a)).appendTo(b.body),d=n.css(c[0],"display");return c.detach(),d}function Ma(a){var b=d,c=Ka[a];return c||(c=La(a,b),"none"!==c&&c||(Ja=(Ja||n("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=(Ja[0].contentWindow||Ja[0].contentDocument).document,b.write(),b.close(),c=La(a,b),Ja.detach()),Ka[a]=c),c}var Na=/^margin/,Oa=new RegExp("^("+T+")(?!px)[a-z%]+$","i"),Pa=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e},Qa=d.documentElement;!function(){var b,c,e,f,g,h,i=d.createElement("div"),j=d.createElement("div");if(j.style){j.style.cssText="float:left;opacity:.5",l.opacity="0.5"===j.style.opacity,l.cssFloat=!!j.style.cssFloat,j.style.backgroundClip="content-box",j.cloneNode(!0).style.backgroundClip="",l.clearCloneStyle="content-box"===j.style.backgroundClip,i=d.createElement("div"),i.style.cssText="border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute",j.innerHTML="",i.appendChild(j),l.boxSizing=""===j.style.boxSizing||""===j.style.MozBoxSizing||""===j.style.WebkitBoxSizing,n.extend(l,{reliableHiddenOffsets:function(){return null==b&&k(),f},boxSizingReliable:function(){return null==b&&k(),e},pixelMarginRight:function(){return null==b&&k(),c},pixelPosition:function(){return null==b&&k(),b},reliableMarginRight:function(){return null==b&&k(),g},reliableMarginLeft:function(){return null==b&&k(),h}});function k(){var k,l,m=d.documentElement;m.appendChild(i),j.style.cssText="-webkit-box-sizing:border-box;box-sizing:border-box;position:relative;display:block;margin:auto;border:1px;padding:1px;top:1%;width:50%",b=e=h=!1,c=g=!0,a.getComputedStyle&&(l=a.getComputedStyle(j),b="1%"!==(l||{}).top,h="2px"===(l||{}).marginLeft,e="4px"===(l||{width:"4px"}).width,j.style.marginRight="50%",c="4px"===(l||{marginRight:"4px"}).marginRight,k=j.appendChild(d.createElement("div")),k.style.cssText=j.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",k.style.marginRight=k.style.width="0",j.style.width="1px",g=!parseFloat((a.getComputedStyle(k)||{}).marginRight),j.removeChild(k)),j.style.display="none",f=0===j.getClientRects().length,f&&(j.style.display="",j.innerHTML="<table><tr><td></td><td>t</td></tr></table>",k=j.getElementsByTagName("td"),k[0].style.cssText="margin:0;border:0;padding:0;display:none",f=0===k[0].offsetHeight,f&&(k[0].style.display="",k[1].style.display="none",f=0===k[0].offsetHeight)),m.removeChild(i)}}}();var Ra,Sa,Ta=/^(top|right|bottom|left)$/;a.getComputedStyle?(Ra=function(b){var c=b.ownerDocument.defaultView;return c.opener||(c=a),c.getComputedStyle(b)},Sa=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ra(a),g=c?c.getPropertyValue(b)||c[b]:void 0,c&&(""!==g||n.contains(a.ownerDocument,a)||(g=n.style(a,b)),!l.pixelMarginRight()&&Oa.test(g)&&Na.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0===g?g:g+""}):Qa.currentStyle&&(Ra=function(a){return a.currentStyle},Sa=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ra(a),g=c?c[b]:void 0,null==g&&h&&h[b]&&(g=h[b]),Oa.test(g)&&!Ta.test(b)&&(d=h.left,e=a.runtimeStyle,f=e&&e.left,f&&(e.left=a.currentStyle.left),h.left="fontSize"===b?"1em":g,g=h.pixelLeft+"px",h.left=d,f&&(e.left=f)),void 0===g?g:g+""||"auto"});function Ua(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}var Va=/alpha\([^)]*\)/i,Wa=/opacity\s*=\s*([^)]*)/i,Xa=/^(none|table(?!-c[ea]).+)/,Ya=new RegExp("^("+T+")(.*)$","i"),Za={position:"absolute",visibility:"hidden",display:"block"},$a={letterSpacing:"0",fontWeight:"400"},_a=["Webkit","O","Moz","ms"],ab=d.createElement("div").style;function bb(a){if(a in ab)return a;var b=a.charAt(0).toUpperCase()+a.slice(1),c=_a.length;while(c--)if(a=_a[c]+b,a in ab)return a}function cb(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=n._data(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&W(d)&&(f[g]=n._data(d,"olddisplay",Ma(d.nodeName)))):(e=W(d),(c&&"none"!==c||!e)&&n._data(d,"olddisplay",e?c:n.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}function db(a,b,c){var d=Ya.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function eb(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=n.css(a,c+V[f],!0,e)),d?("content"===c&&(g-=n.css(a,"padding"+V[f],!0,e)),"margin"!==c&&(g-=n.css(a,"border"+V[f]+"Width",!0,e))):(g+=n.css(a,"padding"+V[f],!0,e),"padding"!==c&&(g+=n.css(a,"border"+V[f]+"Width",!0,e)));return g}function fb(b,c,e){var f=!0,g="width"===c?b.offsetWidth:b.offsetHeight,h=Ra(b),i=l.boxSizing&&"border-box"===n.css(b,"boxSizing",!1,h);if(d.msFullscreenElement&&a.top!==a&&b.getClientRects().length&&(g=Math.round(100*b.getBoundingClientRect()[c])),0>=g||null==g){if(g=Sa(b,c,h),(0>g||null==g)&&(g=b.style[c]),Oa.test(g))return g;f=i&&(l.boxSizingReliable()||g===b.style[c]),g=parseFloat(g)||0}return g+eb(b,c,e||(i?"border":"content"),f,h)+"px"}n.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Sa(a,"opacity");return""===c?"1":c}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":l.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=n.camelCase(b),i=a.style;if(b=n.cssProps[h]||(n.cssProps[h]=bb(h)||h),g=n.cssHooks[b]||n.cssHooks[h],void 0===c)return g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b];if(f=typeof c,"string"===f&&(e=U.exec(c))&&e[1]&&(c=X(a,b,e),f="number"),null!=c&&c===c&&("number"===f&&(c+=e&&e[3]||(n.cssNumber[h]?"":"px")),l.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),!(g&&"set"in g&&void 0===(c=g.set(a,c,d)))))try{i[b]=c}catch(j){}}},css:function(a,b,c,d){var e,f,g,h=n.camelCase(b);return b=n.cssProps[h]||(n.cssProps[h]=bb(h)||h),g=n.cssHooks[b]||n.cssHooks[h],g&&"get"in g&&(f=g.get(a,!0,c)),void 0===f&&(f=Sa(a,b,d)),"normal"===f&&b in $a&&(f=$a[b]),""===c||c?(e=parseFloat(f),c===!0||isFinite(e)?e||0:f):f}}),n.each(["height","width"],function(a,b){n.cssHooks[b]={get:function(a,c,d){return c?Xa.test(n.css(a,"display"))&&0===a.offsetWidth?Pa(a,Za,function(){return fb(a,b,d)}):fb(a,b,d):void 0},set:function(a,c,d){var e=d&&Ra(a);return db(a,c,d?eb(a,b,d,l.boxSizing&&"border-box"===n.css(a,"boxSizing",!1,e),e):0)}}}),l.opacity||(n.cssHooks.opacity={get:function(a,b){return Wa.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=n.isNumeric(b)?"alpha(opacity="+100*b+")":"",f=d&&d.filter||c.filter||"";c.zoom=1,(b>=1||""===b)&&""===n.trim(f.replace(Va,""))&&c.removeAttribute&&(c.removeAttribute("filter"),""===b||d&&!d.filter)||(c.filter=Va.test(f)?f.replace(Va,e):f+" "+e)}}),n.cssHooks.marginRight=Ua(l.reliableMarginRight,function(a,b){return b?Pa(a,{display:"inline-block"},Sa,[a,"marginRight"]):void 0}),n.cssHooks.marginLeft=Ua(l.reliableMarginLeft,function(a,b){return b?(parseFloat(Sa(a,"marginLeft"))||(n.contains(a.ownerDocument,a)?a.getBoundingClientRect().left-Pa(a,{ +marginLeft:0},function(){return a.getBoundingClientRect().left}):0))+"px":void 0}),n.each({margin:"",padding:"",border:"Width"},function(a,b){n.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+V[d]+b]=f[d]||f[d-2]||f[0];return e}},Na.test(a)||(n.cssHooks[a+b].set=db)}),n.fn.extend({css:function(a,b){return Y(this,function(a,b,c){var d,e,f={},g=0;if(n.isArray(b)){for(d=Ra(a),e=b.length;e>g;g++)f[b[g]]=n.css(a,b[g],!1,d);return f}return void 0!==c?n.style(a,b,c):n.css(a,b)},a,b,arguments.length>1)},show:function(){return cb(this,!0)},hide:function(){return cb(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){W(this)?n(this).show():n(this).hide()})}});function gb(a,b,c,d,e){return new gb.prototype.init(a,b,c,d,e)}n.Tween=gb,gb.prototype={constructor:gb,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||n.easing._default,this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(n.cssNumber[c]?"":"px")},cur:function(){var a=gb.propHooks[this.prop];return a&&a.get?a.get(this):gb.propHooks._default.get(this)},run:function(a){var b,c=gb.propHooks[this.prop];return this.options.duration?this.pos=b=n.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):gb.propHooks._default.set(this),this}},gb.prototype.init.prototype=gb.prototype,gb.propHooks={_default:{get:function(a){var b;return 1!==a.elem.nodeType||null!=a.elem[a.prop]&&null==a.elem.style[a.prop]?a.elem[a.prop]:(b=n.css(a.elem,a.prop,""),b&&"auto"!==b?b:0)},set:function(a){n.fx.step[a.prop]?n.fx.step[a.prop](a):1!==a.elem.nodeType||null==a.elem.style[n.cssProps[a.prop]]&&!n.cssHooks[a.prop]?a.elem[a.prop]=a.now:n.style(a.elem,a.prop,a.now+a.unit)}}},gb.propHooks.scrollTop=gb.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},n.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2},_default:"swing"},n.fx=gb.prototype.init,n.fx.step={};var hb,ib,jb=/^(?:toggle|show|hide)$/,kb=/queueHooks$/;function lb(){return a.setTimeout(function(){hb=void 0}),hb=n.now()}function mb(a,b){var c,d={height:a},e=0;for(b=b?1:0;4>e;e+=2-b)c=V[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function nb(a,b,c){for(var d,e=(qb.tweeners[b]||[]).concat(qb.tweeners["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function ob(a,b,c){var d,e,f,g,h,i,j,k,m=this,o={},p=a.style,q=a.nodeType&&W(a),r=n._data(a,"fxshow");c.queue||(h=n._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,m.always(function(){m.always(function(){h.unqueued--,n.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[p.overflow,p.overflowX,p.overflowY],j=n.css(a,"display"),k="none"===j?n._data(a,"olddisplay")||Ma(a.nodeName):j,"inline"===k&&"none"===n.css(a,"float")&&(l.inlineBlockNeedsLayout&&"inline"!==Ma(a.nodeName)?p.zoom=1:p.display="inline-block")),c.overflow&&(p.overflow="hidden",l.shrinkWrapBlocks()||m.always(function(){p.overflow=c.overflow[0],p.overflowX=c.overflow[1],p.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],jb.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(q?"hide":"show")){if("show"!==e||!r||void 0===r[d])continue;q=!0}o[d]=r&&r[d]||n.style(a,d)}else j=void 0;if(n.isEmptyObject(o))"inline"===("none"===j?Ma(a.nodeName):j)&&(p.display=j);else{r?"hidden"in r&&(q=r.hidden):r=n._data(a,"fxshow",{}),f&&(r.hidden=!q),q?n(a).show():m.done(function(){n(a).hide()}),m.done(function(){var b;n._removeData(a,"fxshow");for(b in o)n.style(a,b,o[b])});for(d in o)g=nb(q?r[d]:0,d,m),d in r||(r[d]=g.start,q&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function pb(a,b){var c,d,e,f,g;for(c in a)if(d=n.camelCase(c),e=b[d],f=a[c],n.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=n.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function qb(a,b,c){var d,e,f=0,g=qb.prefilters.length,h=n.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=hb||lb(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:n.extend({},b),opts:n.extend(!0,{specialEasing:{},easing:n.easing._default},c),originalProperties:b,originalOptions:c,startTime:hb||lb(),duration:c.duration,tweens:[],createTween:function(b,c){var d=n.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?(h.notifyWith(a,[j,1,0]),h.resolveWith(a,[j,b])):h.rejectWith(a,[j,b]),this}}),k=j.props;for(pb(k,j.opts.specialEasing);g>f;f++)if(d=qb.prefilters[f].call(j,a,k,j.opts))return n.isFunction(d.stop)&&(n._queueHooks(j.elem,j.opts.queue).stop=n.proxy(d.stop,d)),d;return n.map(k,nb,j),n.isFunction(j.opts.start)&&j.opts.start.call(a,j),n.fx.timer(n.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}n.Animation=n.extend(qb,{tweeners:{"*":[function(a,b){var c=this.createTween(a,b);return X(c.elem,a,U.exec(b),c),c}]},tweener:function(a,b){n.isFunction(a)?(b=a,a=["*"]):a=a.match(G);for(var c,d=0,e=a.length;e>d;d++)c=a[d],qb.tweeners[c]=qb.tweeners[c]||[],qb.tweeners[c].unshift(b)},prefilters:[ob],prefilter:function(a,b){b?qb.prefilters.unshift(a):qb.prefilters.push(a)}}),n.speed=function(a,b,c){var d=a&&"object"==typeof a?n.extend({},a):{complete:c||!c&&b||n.isFunction(a)&&a,duration:a,easing:c&&b||b&&!n.isFunction(b)&&b};return d.duration=n.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in n.fx.speeds?n.fx.speeds[d.duration]:n.fx.speeds._default,(null==d.queue||d.queue===!0)&&(d.queue="fx"),d.old=d.complete,d.complete=function(){n.isFunction(d.old)&&d.old.call(this),d.queue&&n.dequeue(this,d.queue)},d},n.fn.extend({fadeTo:function(a,b,c,d){return this.filter(W).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=n.isEmptyObject(a),f=n.speed(b,c,d),g=function(){var b=qb(this,n.extend({},a),f);(e||n._data(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=n.timers,g=n._data(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&kb.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));(b||!c)&&n.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=n._data(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=n.timers,g=d?d.length:0;for(c.finish=!0,n.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),n.each(["toggle","show","hide"],function(a,b){var c=n.fn[b];n.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(mb(b,!0),a,d,e)}}),n.each({slideDown:mb("show"),slideUp:mb("hide"),slideToggle:mb("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){n.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),n.timers=[],n.fx.tick=function(){var a,b=n.timers,c=0;for(hb=n.now();c<b.length;c++)a=b[c],a()||b[c]!==a||b.splice(c--,1);b.length||n.fx.stop(),hb=void 0},n.fx.timer=function(a){n.timers.push(a),a()?n.fx.start():n.timers.pop()},n.fx.interval=13,n.fx.start=function(){ib||(ib=a.setInterval(n.fx.tick,n.fx.interval))},n.fx.stop=function(){a.clearInterval(ib),ib=null},n.fx.speeds={slow:600,fast:200,_default:400},n.fn.delay=function(b,c){return b=n.fx?n.fx.speeds[b]||b:b,c=c||"fx",this.queue(c,function(c,d){var e=a.setTimeout(c,b);d.stop=function(){a.clearTimeout(e)}})},function(){var a,b=d.createElement("input"),c=d.createElement("div"),e=d.createElement("select"),f=e.appendChild(d.createElement("option"));c=d.createElement("div"),c.setAttribute("className","t"),c.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",a=c.getElementsByTagName("a")[0],b.setAttribute("type","checkbox"),c.appendChild(b),a=c.getElementsByTagName("a")[0],a.style.cssText="top:1px",l.getSetAttribute="t"!==c.className,l.style=/top/.test(a.getAttribute("style")),l.hrefNormalized="/a"===a.getAttribute("href"),l.checkOn=!!b.value,l.optSelected=f.selected,l.enctype=!!d.createElement("form").enctype,e.disabled=!0,l.optDisabled=!f.disabled,b=d.createElement("input"),b.setAttribute("value",""),l.input=""===b.getAttribute("value"),b.value="t",b.setAttribute("type","radio"),l.radioValue="t"===b.value}();var rb=/\r/g;n.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=n.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,n(this).val()):a,null==e?e="":"number"==typeof e?e+="":n.isArray(e)&&(e=n.map(e,function(a){return null==a?"":a+""})),b=n.valHooks[this.type]||n.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=n.valHooks[e.type]||n.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(rb,""):null==c?"":c)}}}),n.extend({valHooks:{option:{get:function(a){var b=n.find.attr(a,"value");return null!=b?b:n.trim(n.text(a))}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],(c.selected||i===e)&&(l.optDisabled?!c.disabled:null===c.getAttribute("disabled"))&&(!c.parentNode.disabled||!n.nodeName(c.parentNode,"optgroup"))){if(b=n(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=n.makeArray(b),g=e.length;while(g--)if(d=e[g],n.inArray(n.valHooks.option.get(d),f)>=0)try{d.selected=c=!0}catch(h){d.scrollHeight}else d.selected=!1;return c||(a.selectedIndex=-1),e}}}}),n.each(["radio","checkbox"],function(){n.valHooks[this]={set:function(a,b){return n.isArray(b)?a.checked=n.inArray(n(a).val(),b)>-1:void 0}},l.checkOn||(n.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var sb,tb,ub=n.expr.attrHandle,vb=/^(?:checked|selected)$/i,wb=l.getSetAttribute,xb=l.input;n.fn.extend({attr:function(a,b){return Y(this,n.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){n.removeAttr(this,a)})}}),n.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return"undefined"==typeof a.getAttribute?n.prop(a,b,c):(1===f&&n.isXMLDoc(a)||(b=b.toLowerCase(),e=n.attrHooks[b]||(n.expr.match.bool.test(b)?tb:sb)),void 0!==c?null===c?void n.removeAttr(a,b):e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:(a.setAttribute(b,c+""),c):e&&"get"in e&&null!==(d=e.get(a,b))?d:(d=n.find.attr(a,b),null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!l.radioValue&&"radio"===b&&n.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(G);if(f&&1===a.nodeType)while(c=f[e++])d=n.propFix[c]||c,n.expr.match.bool.test(c)?xb&&wb||!vb.test(c)?a[d]=!1:a[n.camelCase("default-"+c)]=a[d]=!1:n.attr(a,c,""),a.removeAttribute(wb?c:d)}}),tb={set:function(a,b,c){return b===!1?n.removeAttr(a,c):xb&&wb||!vb.test(c)?a.setAttribute(!wb&&n.propFix[c]||c,c):a[n.camelCase("default-"+c)]=a[c]=!0,c}},n.each(n.expr.match.bool.source.match(/\w+/g),function(a,b){var c=ub[b]||n.find.attr;xb&&wb||!vb.test(b)?ub[b]=function(a,b,d){var e,f;return d||(f=ub[b],ub[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,ub[b]=f),e}:ub[b]=function(a,b,c){return c?void 0:a[n.camelCase("default-"+b)]?b.toLowerCase():null}}),xb&&wb||(n.attrHooks.value={set:function(a,b,c){return n.nodeName(a,"input")?void(a.defaultValue=b):sb&&sb.set(a,b,c)}}),wb||(sb={set:function(a,b,c){var d=a.getAttributeNode(c);return d||a.setAttributeNode(d=a.ownerDocument.createAttribute(c)),d.value=b+="","value"===c||b===a.getAttribute(c)?b:void 0}},ub.id=ub.name=ub.coords=function(a,b,c){var d;return c?void 0:(d=a.getAttributeNode(b))&&""!==d.value?d.value:null},n.valHooks.button={get:function(a,b){var c=a.getAttributeNode(b);return c&&c.specified?c.value:void 0},set:sb.set},n.attrHooks.contenteditable={set:function(a,b,c){sb.set(a,""===b?!1:b,c)}},n.each(["width","height"],function(a,b){n.attrHooks[b]={set:function(a,c){return""===c?(a.setAttribute(b,"auto"),c):void 0}}})),l.style||(n.attrHooks.style={get:function(a){return a.style.cssText||void 0},set:function(a,b){return a.style.cssText=b+""}});var yb=/^(?:input|select|textarea|button|object)$/i,zb=/^(?:a|area)$/i;n.fn.extend({prop:function(a,b){return Y(this,n.prop,a,b,arguments.length>1)},removeProp:function(a){return a=n.propFix[a]||a,this.each(function(){try{this[a]=void 0,delete this[a]}catch(b){}})}}),n.extend({prop:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return 1===f&&n.isXMLDoc(a)||(b=n.propFix[b]||b,e=n.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=n.find.attr(a,"tabindex");return b?parseInt(b,10):yb.test(a.nodeName)||zb.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),l.hrefNormalized||n.each(["href","src"],function(a,b){n.propHooks[b]={get:function(a){return a.getAttribute(b,4)}}}),l.optSelected||(n.propHooks.selected={get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null}}),n.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){n.propFix[this.toLowerCase()]=this}),l.enctype||(n.propFix.enctype="encoding");var Ab=/[\t\r\n\f]/g;function Bb(a){return n.attr(a,"class")||""}n.fn.extend({addClass:function(a){var b,c,d,e,f,g,h,i=0;if(n.isFunction(a))return this.each(function(b){n(this).addClass(a.call(this,b,Bb(this)))});if("string"==typeof a&&a){b=a.match(G)||[];while(c=this[i++])if(e=Bb(c),d=1===c.nodeType&&(" "+e+" ").replace(Ab," ")){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=n.trim(d),e!==h&&n.attr(c,"class",h)}}return this},removeClass:function(a){var b,c,d,e,f,g,h,i=0;if(n.isFunction(a))return this.each(function(b){n(this).removeClass(a.call(this,b,Bb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(G)||[];while(c=this[i++])if(e=Bb(c),d=1===c.nodeType&&(" "+e+" ").replace(Ab," ")){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=n.trim(d),e!==h&&n.attr(c,"class",h)}}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):n.isFunction(a)?this.each(function(c){n(this).toggleClass(a.call(this,c,Bb(this),b),b)}):this.each(function(){var b,d,e,f;if("string"===c){d=0,e=n(this),f=a.match(G)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else(void 0===a||"boolean"===c)&&(b=Bb(this),b&&n._data(this,"__className__",b),n.attr(this,"class",b||a===!1?"":n._data(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+Bb(c)+" ").replace(Ab," ").indexOf(b)>-1)return!0;return!1}}),n.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){n.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),n.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var Cb=a.location,Db=n.now(),Eb=/\?/,Fb=/(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;n.parseJSON=function(b){if(a.JSON&&a.JSON.parse)return a.JSON.parse(b+"");var c,d=null,e=n.trim(b+"");return e&&!n.trim(e.replace(Fb,function(a,b,e,f){return c&&b&&(d=0),0===d?a:(c=e||b,d+=!f-!e,"")}))?Function("return "+e)():n.error("Invalid JSON: "+b)},n.parseXML=function(b){var c,d;if(!b||"string"!=typeof b)return null;try{a.DOMParser?(d=new a.DOMParser,c=d.parseFromString(b,"text/xml")):(c=new a.ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b))}catch(e){c=void 0}return c&&c.documentElement&&!c.getElementsByTagName("parsererror").length||n.error("Invalid XML: "+b),c};var Gb=/#.*$/,Hb=/([?&])_=[^&]*/,Ib=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Jb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Kb=/^(?:GET|HEAD)$/,Lb=/^\/\//,Mb=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,Nb={},Ob={},Pb="*/".concat("*"),Qb=Cb.href,Rb=Mb.exec(Qb.toLowerCase())||[];function Sb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(G)||[];if(n.isFunction(c))while(d=f[e++])"+"===d.charAt(0)?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Tb(a,b,c,d){var e={},f=a===Ob;function g(h){var i;return e[h]=!0,n.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Ub(a,b){var c,d,e=n.ajaxSettings.flatOptions||{};for(d in b)void 0!==b[d]&&((e[d]?a:c||(c={}))[d]=b[d]);return c&&n.extend(!0,a,c),a}function Vb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===e&&(e=a.mimeType||b.getResponseHeader("Content-Type"));if(e)for(g in h)if(h[g]&&h[g].test(e)){i.unshift(g);break}if(i[0]in c)f=i[0];else{for(g in c){if(!i[0]||a.converters[g+" "+i[0]]){f=g;break}d||(d=g)}f=f||d}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function Wb(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}n.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Qb,type:"GET",isLocal:Jb.test(Rb[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Pb,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":n.parseJSON,"text xml":n.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Ub(Ub(a,n.ajaxSettings),b):Ub(n.ajaxSettings,a)},ajaxPrefilter:Sb(Nb),ajaxTransport:Sb(Ob),ajax:function(b,c){"object"==typeof b&&(c=b,b=void 0),c=c||{};var d,e,f,g,h,i,j,k,l=n.ajaxSetup({},c),m=l.context||l,o=l.context&&(m.nodeType||m.jquery)?n(m):n.event,p=n.Deferred(),q=n.Callbacks("once memory"),r=l.statusCode||{},s={},t={},u=0,v="canceled",w={readyState:0,getResponseHeader:function(a){var b;if(2===u){if(!k){k={};while(b=Ib.exec(g))k[b[1].toLowerCase()]=b[2]}b=k[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===u?g:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return u||(a=t[c]=t[c]||a,s[a]=b),this},overrideMimeType:function(a){return u||(l.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>u)for(b in a)r[b]=[r[b],a[b]];else w.always(a[w.status]);return this},abort:function(a){var b=a||v;return j&&j.abort(b),y(0,b),this}};if(p.promise(w).complete=q.add,w.success=w.done,w.error=w.fail,l.url=((b||l.url||Qb)+"").replace(Gb,"").replace(Lb,Rb[1]+"//"),l.type=c.method||c.type||l.method||l.type,l.dataTypes=n.trim(l.dataType||"*").toLowerCase().match(G)||[""],null==l.crossDomain&&(d=Mb.exec(l.url.toLowerCase()),l.crossDomain=!(!d||d[1]===Rb[1]&&d[2]===Rb[2]&&(d[3]||("http:"===d[1]?"80":"443"))===(Rb[3]||("http:"===Rb[1]?"80":"443")))),l.data&&l.processData&&"string"!=typeof l.data&&(l.data=n.param(l.data,l.traditional)),Tb(Nb,l,c,w),2===u)return w;i=n.event&&l.global,i&&0===n.active++&&n.event.trigger("ajaxStart"),l.type=l.type.toUpperCase(),l.hasContent=!Kb.test(l.type),f=l.url,l.hasContent||(l.data&&(f=l.url+=(Eb.test(f)?"&":"?")+l.data,delete l.data),l.cache===!1&&(l.url=Hb.test(f)?f.replace(Hb,"$1_="+Db++):f+(Eb.test(f)?"&":"?")+"_="+Db++)),l.ifModified&&(n.lastModified[f]&&w.setRequestHeader("If-Modified-Since",n.lastModified[f]),n.etag[f]&&w.setRequestHeader("If-None-Match",n.etag[f])),(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&w.setRequestHeader("Content-Type",l.contentType),w.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+("*"!==l.dataTypes[0]?", "+Pb+"; q=0.01":""):l.accepts["*"]);for(e in l.headers)w.setRequestHeader(e,l.headers[e]);if(l.beforeSend&&(l.beforeSend.call(m,w,l)===!1||2===u))return w.abort();v="abort";for(e in{success:1,error:1,complete:1})w[e](l[e]);if(j=Tb(Ob,l,c,w)){if(w.readyState=1,i&&o.trigger("ajaxSend",[w,l]),2===u)return w;l.async&&l.timeout>0&&(h=a.setTimeout(function(){w.abort("timeout")},l.timeout));try{u=1,j.send(s,y)}catch(x){if(!(2>u))throw x;y(-1,x)}}else y(-1,"No Transport");function y(b,c,d,e){var k,s,t,v,x,y=c;2!==u&&(u=2,h&&a.clearTimeout(h),j=void 0,g=e||"",w.readyState=b>0?4:0,k=b>=200&&300>b||304===b,d&&(v=Vb(l,w,d)),v=Wb(l,v,w,k),k?(l.ifModified&&(x=w.getResponseHeader("Last-Modified"),x&&(n.lastModified[f]=x),x=w.getResponseHeader("etag"),x&&(n.etag[f]=x)),204===b||"HEAD"===l.type?y="nocontent":304===b?y="notmodified":(y=v.state,s=v.data,t=v.error,k=!t)):(t=y,(b||!y)&&(y="error",0>b&&(b=0))),w.status=b,w.statusText=(c||y)+"",k?p.resolveWith(m,[s,y,w]):p.rejectWith(m,[w,y,t]),w.statusCode(r),r=void 0,i&&o.trigger(k?"ajaxSuccess":"ajaxError",[w,l,k?s:t]),q.fireWith(m,[w,y]),i&&(o.trigger("ajaxComplete",[w,l]),--n.active||n.event.trigger("ajaxStop")))}return w},getJSON:function(a,b,c){return n.get(a,b,c,"json")},getScript:function(a,b){return n.get(a,void 0,b,"script")}}),n.each(["get","post"],function(a,b){n[b]=function(a,c,d,e){return n.isFunction(c)&&(e=e||d,d=c,c=void 0),n.ajax(n.extend({url:a,type:b,dataType:e,data:c,success:d},n.isPlainObject(a)&&a))}}),n._evalUrl=function(a){return n.ajax({url:a,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},n.fn.extend({wrapAll:function(a){if(n.isFunction(a))return this.each(function(b){n(this).wrapAll(a.call(this,b))});if(this[0]){var b=n(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&1===a.firstChild.nodeType)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return n.isFunction(a)?this.each(function(b){n(this).wrapInner(a.call(this,b))}):this.each(function(){var b=n(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=n.isFunction(a);return this.each(function(c){n(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){n.nodeName(this,"body")||n(this).replaceWith(this.childNodes)}).end()}});function Xb(a){return a.style&&a.style.display||n.css(a,"display")}function Yb(a){while(a&&1===a.nodeType){if("none"===Xb(a)||"hidden"===a.type)return!0;a=a.parentNode}return!1}n.expr.filters.hidden=function(a){return l.reliableHiddenOffsets()?a.offsetWidth<=0&&a.offsetHeight<=0&&!a.getClientRects().length:Yb(a)},n.expr.filters.visible=function(a){return!n.expr.filters.hidden(a)};var Zb=/%20/g,$b=/\[\]$/,_b=/\r?\n/g,ac=/^(?:submit|button|image|reset|file)$/i,bc=/^(?:input|select|textarea|keygen)/i;function cc(a,b,c,d){var e;if(n.isArray(b))n.each(b,function(b,e){c||$b.test(a)?d(a,e):cc(a+"["+("object"==typeof e&&null!=e?b:"")+"]",e,c,d)});else if(c||"object"!==n.type(b))d(a,b);else for(e in b)cc(a+"["+e+"]",b[e],c,d)}n.param=function(a,b){var c,d=[],e=function(a,b){b=n.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=n.ajaxSettings&&n.ajaxSettings.traditional),n.isArray(a)||a.jquery&&!n.isPlainObject(a))n.each(a,function(){e(this.name,this.value)});else for(c in a)cc(c,a[c],b,e);return d.join("&").replace(Zb,"+")},n.fn.extend({serialize:function(){return n.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=n.prop(this,"elements");return a?n.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!n(this).is(":disabled")&&bc.test(this.nodeName)&&!ac.test(a)&&(this.checked||!Z.test(a))}).map(function(a,b){var c=n(this).val();return null==c?null:n.isArray(c)?n.map(c,function(a){return{name:b.name,value:a.replace(_b,"\r\n")}}):{name:b.name,value:c.replace(_b,"\r\n")}}).get()}}),n.ajaxSettings.xhr=void 0!==a.ActiveXObject?function(){return this.isLocal?hc():d.documentMode>8?gc():/^(get|post|head|put|delete|options)$/i.test(this.type)&&gc()||hc()}:gc;var dc=0,ec={},fc=n.ajaxSettings.xhr();a.attachEvent&&a.attachEvent("onunload",function(){for(var a in ec)ec[a](void 0,!0)}),l.cors=!!fc&&"withCredentials"in fc,fc=l.ajax=!!fc,fc&&n.ajaxTransport(function(b){if(!b.crossDomain||l.cors){var c;return{send:function(d,e){var f,g=b.xhr(),h=++dc;if(g.open(b.type,b.url,b.async,b.username,b.password),b.xhrFields)for(f in b.xhrFields)g[f]=b.xhrFields[f];b.mimeType&&g.overrideMimeType&&g.overrideMimeType(b.mimeType),b.crossDomain||d["X-Requested-With"]||(d["X-Requested-With"]="XMLHttpRequest");for(f in d)void 0!==d[f]&&g.setRequestHeader(f,d[f]+"");g.send(b.hasContent&&b.data||null),c=function(a,d){var f,i,j;if(c&&(d||4===g.readyState))if(delete ec[h],c=void 0,g.onreadystatechange=n.noop,d)4!==g.readyState&&g.abort();else{j={},f=g.status,"string"==typeof g.responseText&&(j.text=g.responseText);try{i=g.statusText}catch(k){i=""}f||!b.isLocal||b.crossDomain?1223===f&&(f=204):f=j.text?200:404}j&&e(f,i,j,g.getAllResponseHeaders())},b.async?4===g.readyState?a.setTimeout(c):g.onreadystatechange=ec[h]=c:c()},abort:function(){c&&c(void 0,!0)}}}});function gc(){try{return new a.XMLHttpRequest}catch(b){}}function hc(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}n.ajaxPrefilter(function(a){a.crossDomain&&(a.contents.script=!1)}),n.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(a){return n.globalEval(a),a}}}),n.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),n.ajaxTransport("script",function(a){if(a.crossDomain){var b,c=d.head||n("head")[0]||d.documentElement;return{send:function(e,f){b=d.createElement("script"),b.async=!0,a.scriptCharset&&(b.charset=a.scriptCharset),b.src=a.url,b.onload=b.onreadystatechange=function(a,c){(c||!b.readyState||/loaded|complete/.test(b.readyState))&&(b.onload=b.onreadystatechange=null,b.parentNode&&b.parentNode.removeChild(b),b=null,c||f(200,"success"))},c.insertBefore(b,c.firstChild)},abort:function(){b&&b.onload(void 0,!0)}}}});var ic=[],jc=/(=)\?(?=&|$)|\?\?/;n.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=ic.pop()||n.expando+"_"+Db++;return this[a]=!0,a}}),n.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(jc.test(b.url)?"url":"string"==typeof b.data&&0===(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&jc.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=n.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(jc,"$1"+e):b.jsonp!==!1&&(b.url+=(Eb.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||n.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){void 0===f?n(a).removeProp(e):a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,ic.push(e)),g&&n.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),l.createHTMLDocument=function(){if(!d.implementation.createHTMLDocument)return!1;var a=d.implementation.createHTMLDocument("");return a.body.innerHTML="<form></form><form></form>",2===a.body.childNodes.length}(),n.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||(l.createHTMLDocument?d.implementation.createHTMLDocument(""):d);var e=x.exec(a),f=!c&&[];return e?[b.createElement(e[1])]:(e=ja([a],b,f),f&&f.length&&n(f).remove(),n.merge([],e.childNodes))};var kc=n.fn.load;n.fn.load=function(a,b,c){if("string"!=typeof a&&kc)return kc.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>-1&&(d=n.trim(a.slice(h,a.length)),a=a.slice(0,h)),n.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(e="POST"),g.length>0&&n.ajax({url:a,type:e||"GET",dataType:"html",data:b}).done(function(a){f=arguments,g.html(d?n("<div>").append(n.parseHTML(a)).find(d):a)}).always(c&&function(a,b){g.each(function(){c.apply(g,f||[a.responseText,b,a])})}),this},n.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){n.fn[b]=function(a){return this.on(b,a)}}),n.expr.filters.animated=function(a){return n.grep(n.timers,function(b){return a===b.elem}).length};function lc(a){return n.isWindow(a)?a:9===a.nodeType?a.defaultView||a.parentWindow:!1}n.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=n.css(a,"position"),l=n(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=n.css(a,"top"),i=n.css(a,"left"),j=("absolute"===k||"fixed"===k)&&n.inArray("auto",[f,i])>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),n.isFunction(b)&&(b=b.call(a,c,n.extend({},h))),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},n.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){n.offset.setOffset(this,a,b)});var b,c,d={top:0,left:0},e=this[0],f=e&&e.ownerDocument;if(f)return b=f.documentElement,n.contains(b,e)?("undefined"!=typeof e.getBoundingClientRect&&(d=e.getBoundingClientRect()),c=lc(f),{top:d.top+(c.pageYOffset||b.scrollTop)-(b.clientTop||0),left:d.left+(c.pageXOffset||b.scrollLeft)-(b.clientLeft||0)}):d},position:function(){if(this[0]){var a,b,c={top:0,left:0},d=this[0];return"fixed"===n.css(d,"position")?b=d.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),n.nodeName(a[0],"html")||(c=a.offset()),c.top+=n.css(a[0],"borderTopWidth",!0)-a.scrollTop(),c.left+=n.css(a[0],"borderLeftWidth",!0)-a.scrollLeft()),{top:b.top-c.top-n.css(d,"marginTop",!0),left:b.left-c.left-n.css(d,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent;while(a&&!n.nodeName(a,"html")&&"static"===n.css(a,"position"))a=a.offsetParent;return a||Qa})}}),n.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c=/Y/.test(b);n.fn[a]=function(d){return Y(this,function(a,d,e){var f=lc(a);return void 0===e?f?b in f?f[b]:f.document.documentElement[d]:a[d]:void(f?f.scrollTo(c?n(f).scrollLeft():e,c?e:n(f).scrollTop()):a[d]=e)},a,d,arguments.length,null)}}),n.each(["top","left"],function(a,b){ +n.cssHooks[b]=Ua(l.pixelPosition,function(a,c){return c?(c=Sa(a,b),Oa.test(c)?n(a).position()[b]+"px":c):void 0})}),n.each({Height:"height",Width:"width"},function(a,b){n.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){n.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return Y(this,function(b,c,d){var e;return n.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?n.css(b,c,g):n.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),n.fn.extend({bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}}),n.fn.size=function(){return this.length},n.fn.andSelf=n.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return n});var mc=a.jQuery,nc=a.$;return n.noConflict=function(b){return a.$===n&&(a.$=nc),b&&a.jQuery===n&&(a.jQuery=mc),n},b||(a.jQuery=a.$=n),n});
\ No newline at end of file diff --git a/wqflask/wqflask/static/packages/bootstrap/css/bootstrap.css b/wqflask/wqflask/static/packages/bootstrap/css/bootstrap.css index 461fd089..2c20f635 100644 --- a/wqflask/wqflask/static/packages/bootstrap/css/bootstrap.css +++ b/wqflask/wqflask/static/packages/bootstrap/css/bootstrap.css @@ -261,7 +261,7 @@ th { } .table-bordered th, .table-bordered td { - border: 1px solid #ddd !important; + border: 1px solid #000 !important; } } @font-face { @@ -2114,7 +2114,7 @@ th { padding: 5px; } .table-bordered { - border: 1px solid #ddd; + border: 1px solid #000; } .table-bordered > thead > tr > th, .table-bordered > tbody > tr > th, @@ -2122,7 +2122,7 @@ th { .table-bordered > thead > tr > td, .table-bordered > tbody > tr > td, .table-bordered > tfoot > tr > td { - border: 1px solid #ddd; + border: 1px solid #000; } .table-bordered > thead > tr > th, .table-bordered > thead > tr > td { diff --git a/wqflask/wqflask/static/packages/cytoscape/css/cytoscape.js-panzoom.css b/wqflask/wqflask/static/packages/cytoscape/css/cytoscape.js-panzoom.css new file mode 100644 index 00000000..a7cb7740 --- /dev/null +++ b/wqflask/wqflask/static/packages/cytoscape/css/cytoscape.js-panzoom.css @@ -0,0 +1,220 @@ +.cy-panzoom {
+ position: absolute;
+ font-size: 12px;
+ color: #fff;
+ font-family: arial, helvetica, sans-serif;
+ line-height: 1;
+ color: #666;
+ font-size: 11px;
+ z-index: 99999;
+ box-sizing: content-box;
+}
+
+.cy-panzoom-zoom-button {
+ cursor: pointer;
+ padding: 3px;
+ text-align: center;
+ position: absolute;
+ border-radius: 3px;
+ width: 10px;
+ height: 10px;
+ left: 16px;
+ background: #fff;
+ border: 1px solid #999;
+ margin-left: -1px;
+ margin-top: -1px;
+ z-index: 1;
+ box-sizing: content-box;
+}
+
+.cy-panzoom-zoom-button:active,
+.cy-panzoom-slider-handle:active,
+.cy-panzoom-slider-handle.active {
+ background: #ddd;
+ box-sizing: content-box;
+}
+
+.cy-panzoom-pan-button {
+ position: absolute;
+ z-index: 1;
+ height: 16px;
+ width: 16px;
+ box-sizing: content-box;
+}
+
+.cy-panzoom-reset {
+ top: 55px;
+ box-sizing: content-box;
+}
+
+.cy-panzoom-zoom-in {
+ top: 80px;
+ box-sizing: content-box;
+}
+
+.cy-panzoom-zoom-out {
+ top: 197px;
+ box-sizing: content-box;
+}
+
+.cy-panzoom-pan-up {
+ top: 0;
+ left: 50%;
+ margin-left: -5px;
+ width: 0;
+ height: 0;
+ border-left: 5px solid transparent;
+ border-right: 5px solid transparent;
+ border-bottom: 5px solid #666;
+ box-sizing: content-box;
+}
+
+.cy-panzoom-pan-down {
+ bottom: 0;
+ left: 50%;
+ margin-left: -5px;
+ width: 0;
+ height: 0;
+ border-left: 5px solid transparent;
+ border-right: 5px solid transparent;
+ border-top: 5px solid #666;
+ box-sizing: content-box;
+}
+
+.cy-panzoom-pan-left {
+ top: 50%;
+ left: 0;
+ margin-top: -5px;
+ width: 0;
+ height: 0;
+ border-top: 5px solid transparent;
+ border-bottom: 5px solid transparent;
+ border-right: 5px solid #666;
+ box-sizing: content-box;
+}
+
+.cy-panzoom-pan-right {
+ top: 50%;
+ right: 0;
+ margin-top: -5px;
+ width: 0;
+ height: 0;
+ border-top: 5px solid transparent;
+ border-bottom: 5px solid transparent;
+ border-left: 5px solid #666;
+ box-sizing: content-box;
+}
+
+.cy-panzoom-pan-indicator {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 8px;
+ height: 8px;
+ border-radius: 8px;
+ background: #000;
+ border-radius: 8px;
+ margin-left: -5px;
+ margin-top: -5px;
+ display: none;
+ z-index: 999;
+ opacity: 0.6;
+ box-sizing: content-box;
+}
+
+.cy-panzoom-slider {
+ position: absolute;
+ top: 97px;
+ left: 17px;
+ height: 100px;
+ width: 15px;
+ box-sizing: content-box;
+}
+
+.cy-panzoom-slider-background {
+ position: absolute;
+ top: 0;
+ width: 2px;
+ height: 100px;
+ left: 5px;
+ background: #fff;
+ border-left: 1px solid #999;
+ border-right: 1px solid #999;
+ box-sizing: content-box;
+}
+
+.cy-panzoom-slider-handle {
+ position: absolute;
+ width: 16px;
+ height: 8px;
+ background: #fff;
+ border: 1px solid #999;
+ border-radius: 2px;
+ margin-left: -2px;
+ z-index: 999;
+ line-height: 8px;
+ cursor: default;
+ box-sizing: content-box;
+}
+
+.cy-panzoom-slider-handle .icon {
+ margin: 0 4px;
+ line-height: 10px;
+ box-sizing: content-box;
+}
+
+.cy-panzoom-no-zoom-tick {
+ position: absolute;
+ background: #666;
+ border: 1px solid #fff;
+ border-radius: 2px;
+ margin-left: -1px;
+ width: 8px;
+ height: 2px;
+ left: 3px;
+ z-index: 1;
+ margin-top: 3px;
+ box-sizing: content-box;
+}
+
+.cy-panzoom-panner {
+ position: absolute;
+ left: 5px;
+ top: 5px;
+ height: 40px;
+ width: 40px;
+ background: #fff;
+ border: 1px solid #999;
+ border-radius: 40px;
+ margin-left: -1px;
+ box-sizing: content-box;
+}
+
+.cy-panzoom-panner-handle {
+ position: absolute;
+ left: 0;
+ top: 0;
+ outline: none;
+ height: 40px;
+ width: 40px;
+ position: absolute;
+ z-index: 999;
+ box-sizing: content-box;
+}
+
+.cy-panzoom-zoom-only .cy-panzoom-slider,
+.cy-panzoom-zoom-only .cy-panzoom-panner {
+ display: none;
+}
+
+.cy-panzoom-zoom-only .cy-panzoom-reset {
+ top: 20px;
+}
+
+.cy-panzoom-zoom-only .cy-panzoom-zoom-in {
+ top: 45px;
+}
+
+.cy-panzoom-zoom-only .cy-panzoom-zoom-out {
+ top: 70px;
+}
diff --git a/wqflask/wqflask/static/packages/cytoscape/js/min/AC_OETags.min.js b/wqflask/wqflask/static/packages/cytoscape/js/min/AC_OETags.min.js new file mode 100644 index 00000000..2f6b122a --- /dev/null +++ b/wqflask/wqflask/static/packages/cytoscape/js/min/AC_OETags.min.js @@ -0,0 +1 @@ +var isIE=(navigator.appVersion.indexOf("MSIE")!=-1)?true:false;var isWin=(navigator.appVersion.toLowerCase().indexOf("win")!=-1)?true:false;var isOpera=(navigator.userAgent.indexOf("Opera")!=-1)?true:false;function ControlVersion(){var a;var b;var c;try{b=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");a=b.GetVariable("$version")}catch(c){}if(!a){try{b=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");a="WIN 6,0,21,0";b.AllowScriptAccess="always";a=b.GetVariable("$version")}catch(c){}}if(!a){try{b=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.3");a=b.GetVariable("$version")}catch(c){}}if(!a){try{b=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.3");a="WIN 3,0,18,0"}catch(c){}}if(!a){try{b=new ActiveXObject("ShockwaveFlash.ShockwaveFlash");a="WIN 2,0,0,11"}catch(c){a=-1}}return a}function GetSwfVer(){var g=-1;if(navigator.plugins!=null&&navigator.plugins.length>0){if(navigator.plugins["Shockwave Flash 2.0"]||navigator.plugins["Shockwave Flash"]){var f=navigator.plugins["Shockwave Flash 2.0"]?" 2.0":"";var a=navigator.plugins["Shockwave Flash"+f].description;var e=a.split(" ");var c=e[2].split(".");var h=c[0];var b=c[1];var d=e[3];if(d==""){d=e[4]}if(d[0]=="d"){d=d.substring(1)}else{if(d[0]=="r"){d=d.substring(1);if(d.indexOf("d")>0){d=d.substring(0,d.indexOf("d"))}}else{if(d[0]=="b"){d=d.substring(1)}}}var g=h+"."+b+"."+d}}else{if(navigator.userAgent.toLowerCase().indexOf("webtv/2.6")!=-1){g=4}else{if(navigator.userAgent.toLowerCase().indexOf("webtv/2.5")!=-1){g=3}else{if(navigator.userAgent.toLowerCase().indexOf("webtv")!=-1){g=2}else{if(isIE&&isWin&&!isOpera){g=ControlVersion()}}}}}return g}function DetectFlashVer(f,d,c){versionStr=GetSwfVer();if(versionStr==-1){return false}else{if(versionStr!=0){if(isIE&&isWin&&!isOpera){tempArray=versionStr.split(" ");tempString=tempArray[1];versionArray=tempString.split(",")}else{versionArray=versionStr.split(".")}var e=versionArray[0];var a=versionArray[1];var b=versionArray[2];if(e>parseFloat(f)){return true}else{if(e==parseFloat(f)){if(a>parseFloat(d)){return true}else{if(a==parseFloat(d)){if(b>=parseFloat(c)){return true}}}}}return false}}}function AC_AddExtension(b,a){if(b.indexOf("?")!=-1){return b.replace(/\?/,a+"?")}else{return b+a}}function AC_Generateobj(e,d,a){var c="";if(isIE&&isWin&&!isOpera){c+="<object ";for(var b in e){c+=b+'="'+e[b]+'" '}c+=">";for(var b in d){c+='<param name="'+b+'" value="'+d[b]+'" /> '}c+="</object>"}else{c+="<embed ";for(var b in a){c+=b+'="'+a[b]+'" '}c+="> </embed>"}document.write(c)}function AC_FL_RunContent(){var a=AC_GetArgs(arguments,".swf","movie","clsid:d27cdb6e-ae6d-11cf-96b8-444553540000","application/x-shockwave-flash");AC_Generateobj(a.objAttrs,a.params,a.embedAttrs)}function AC_GetArgs(b,e,g,d,h){var a=new Object();a.embedAttrs=new Object();a.params=new Object();a.objAttrs=new Object();for(var c=0;c<b.length;c=c+2){var f=b[c].toLowerCase();switch(f){case"classid":break;case"pluginspage":a.embedAttrs[b[c]]=b[c+1];break;case"src":case"movie":b[c+1]=AC_AddExtension(b[c+1],e);a.embedAttrs.src=b[c+1];a.params[g]=b[c+1];break;case"onafterupdate":case"onbeforeupdate":case"onblur":case"oncellchange":case"onclick":case"ondblClick":case"ondrag":case"ondragend":case"ondragenter":case"ondragleave":case"ondragover":case"ondrop":case"onfinish":case"onfocus":case"onhelp":case"onmousedown":case"onmouseup":case"onmouseover":case"onmousemove":case"onmouseout":case"onkeypress":case"onkeydown":case"onkeyup":case"onload":case"onlosecapture":case"onpropertychange":case"onreadystatechange":case"onrowsdelete":case"onrowenter":case"onrowexit":case"onrowsinserted":case"onstart":case"onscroll":case"onbeforeeditfocus":case"onactivate":case"onbeforedeactivate":case"ondeactivate":case"type":case"codebase":a.objAttrs[b[c]]=b[c+1];break;case"id":case"width":case"height":case"align":case"vspace":case"hspace":case"class":case"title":case"accesskey":case"name":case"tabindex":a.embedAttrs[b[c]]=a.objAttrs[b[c]]=b[c+1];break;default:a.embedAttrs[b[c]]=a.params[b[c]]=b[c+1]}}a.objAttrs.classid=d;if(h){a.embedAttrs.type=h}return a};
\ No newline at end of file diff --git a/wqflask/wqflask/static/packages/cytoscape/js/min/cytoscape.min.js b/wqflask/wqflask/static/packages/cytoscape/js/min/cytoscape.min.js new file mode 100644 index 00000000..fb608c6d --- /dev/null +++ b/wqflask/wqflask/static/packages/cytoscape/js/min/cytoscape.min.js @@ -0,0 +1,62 @@ +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;t="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,t.cytoscape=e()}}(function(){var define,module,exports;return function e(t,r,n){function i(o,s){if(!r[o]){if(!t[o]){var l="function"==typeof require&&require;if(!s&&l)return l(o,!0);if(a)return a(o,!0);var u=new Error("Cannot find module '"+o+"'");throw u.code="MODULE_NOT_FOUND",u}var c=r[o]={exports:{}};t[o][0].call(c.exports,function(e){var r=t[o][1][e];return i(r?r:e)},c,c.exports,e,t,r,n)}return r[o].exports}for(var a="function"==typeof require&&require,o=0;o<n.length;o++)i(n[o]);return i}({1:[function(e,t,r){/*! + +Cytoscape.js 2.7.8 (MIT licensed) + +Copyright (c) The Cytoscape Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the “Software”), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ +"use strict"},{}],2:[function(e,t,r){"use strict";var n=e("./util"),i=e("./is"),a=e("./promise"),o=function(e,t,r){if(!(this instanceof o))return new o(e,t,r);var a=this._private=n.extend({duration:1e3},t,r);a.target=e,a.style=a.style||a.css,a.started=!1,a.playing=!1,a.hooked=!1,a.applying=!1,a.progress=0,a.completes=[],a.frames=[],a.complete&&i.fn(a.complete)&&a.completes.push(a.complete),this.length=1,this[0]=this},s=o.prototype;n.extend(s,{instanceString:function(){return"animation"},hook:function(){var e=this._private;if(!e.hooked){var t,r=e.target._private.animation;t=e.queue?r.queue:r.current,t.push(this),i.elementOrCollection(e.target)&&e.target.cy().addToAnimationPool(e.target),e.hooked=!0}return this},play:function(){var e=this._private;return 1===e.progress&&(e.progress=0),e.playing=!0,e.started=!1,e.stopped=!1,this.hook(),this},playing:function(){return this._private.playing},apply:function(){var e=this._private;return e.applying=!0,e.started=!1,e.stopped=!1,this.hook(),this},applying:function(){return this._private.applying},pause:function(){var e=this._private;return e.playing=!1,e.started=!1,this},stop:function(){var e=this._private;return e.playing=!1,e.started=!1,e.stopped=!0,this},rewind:function(){return this.progress(0)},fastforward:function(){return this.progress(1)},time:function(e){var t=this._private;return void 0===e?t.progress*t.duration:this.progress(e/t.duration)},progress:function(e){var t=this._private,r=t.playing;return void 0===e?t.progress:(r&&this.pause(),t.progress=e,t.started=!1,r&&this.play(),this)},completed:function(){return 1===this._private.progress},reverse:function(){var e=this._private,t=e.playing;t&&this.pause(),e.progress=1-e.progress,e.started=!1;var r=function(t,r){var n=e[t];e[t]=e[r],e[r]=n};r("zoom","startZoom"),r("pan","startPan"),r("position","startPosition");for(var n=0;n<e.style.length;n++){var i=e.style[n],a=i.name,o=e.startStyle[a];e.startStyle[a]=i,e.style[n]=o}return t&&this.play(),this},promise:function(e){var t,r=this._private;switch(e){case"frame":t=r.frames;break;default:case"complete":case"completed":t=r.completes}return new a(function(e,r){t.push(function(){e()})})}}),s.complete=s.completed,t.exports=o},{"./is":83,"./promise":86,"./util":100}],3:[function(e,t,r){"use strict";var n=e("../../is"),i={aStar:function(e){var t=this;e=e||{};var r=function(e,t,n,i){if(e==t)return i.push(a.getElementById(t)),i;if(t in n){var o=n[t],s=f[t];return i.push(a.getElementById(t)),i.push(a.getElementById(s)),r(e,o,n,i)}},i=function(e,t){if(0!==e.length){for(var r=0,n=t[e[0]],i=1;i<e.length;i++){var a=t[e[i]];n>a&&(n=a,r=i)}return r}},a=this._private.cy;if(null!=e&&null!=e.root){var o=n.string(e.root)?this.filter(e.root)[0]:e.root[0];if(null!=e.goal){var s=n.string(e.goal)?this.filter(e.goal)[0]:e.goal[0];if(null!=e.heuristic&&n.fn(e.heuristic))var l=e.heuristic;else var l=function(){return 0};if(null!=e.weight&&n.fn(e.weight))var u=e.weight;else var u=function(e){return 1};if(null!=e.directed)var c=e.directed;else var c=!1;var d=[],h=[o.id()],p={},f={},v={},g={};v[o.id()]=0,g[o.id()]=l(o);for(var y=this.edges().stdFilter(function(e){return!e.isLoop()}),m=this.nodes(),b=0;h.length>0;){var x=i(h,g),w=a.getElementById(h[x]);if(b++,w.id()==s.id()){var E=r(o.id(),s.id(),p,[]);return E.reverse(),{found:!0,distance:v[w.id()],path:t.spawn(E),steps:b}}d.push(w.id()),h.splice(x,1);var _=w.connectedEdges();c&&(_=_.stdFilter(function(e){return e.data("source")===w.id()})),_=_.intersect(y);for(var P=0;P<_.length;P++){var S=_[P],k=S.connectedNodes().stdFilter(function(e){return e.id()!==w.id()}).intersect(m);if(-1==d.indexOf(k.id())){var T=v[w.id()]+u.apply(S,[S]);-1!=h.indexOf(k.id())?T<v[k.id()]&&(v[k.id()]=T,g[k.id()]=T+l(k),p[k.id()]=w.id()):(v[k.id()]=T,g[k.id()]=T+l(k),h.push(k.id()),p[k.id()]=w.id(),f[k.id()]=S.id())}}}return{found:!1,distance:void 0,path:void 0,steps:b}}}}};t.exports=i},{"../../is":83}],4:[function(e,t,r){"use strict";var n=e("../../is"),i=e("../../util"),a={bellmanFord:function(e){var t=this;if(e=e||{},null!=e.weight&&n.fn(e.weight))var r=e.weight;else var r=function(e){return 1};if(null!=e.directed)var a=e.directed;else var a=!1;if(null!=e.root){if(n.string(e.root))var o=this.filter(e.root)[0];else var o=e.root[0];for(var s=this._private.cy,l=this.edges().stdFilter(function(e){return!e.isLoop()}),u=this.nodes(),c=u.length,d={},h=0;c>h;h++)d[u[h].id()]=h;for(var p=[],f=[],v=[],h=0;c>h;h++)u[h].id()===o.id()?p[h]=0:p[h]=1/0,f[h]=void 0;for(var g=!1,h=1;c>h;h++){g=!1;for(var y=0;y<l.length;y++){var m=d[l[y].source().id()],b=d[l[y].target().id()],x=r.apply(l[y],[l[y]]),w=p[m]+x;if(w<p[b]&&(p[b]=w,f[b]=m,v[b]=l[y],g=!0),!a){var w=p[b]+x;w<p[m]&&(p[m]=w,f[m]=b,v[m]=l[y],g=!0)}}if(!g)break}if(g)for(var y=0;y<l.length;y++){var m=d[l[y].source().id()],b=d[l[y].target().id()],x=r.apply(l[y],[l[y]]);if(p[m]+x<p[b])return i.error("Graph contains a negative weight cycle for Bellman-Ford"),{pathTo:void 0,distanceTo:void 0,hasNegativeWeightCycle:!0}}for(var E=[],h=0;c>h;h++)E.push(u[h].id());var _={distanceTo:function(e){if(n.string(e))var t=s.filter(e)[0].id();else var t=e.id();return p[d[t]]},pathTo:function(e){var r=function(e,t,r,n,i,a){for(;;){if(i.push(s.getElementById(n[r])),i.push(a[r]),t===r)return i;var o=e[r];if("undefined"==typeof o)return;r=o}};if(n.string(e))var i=s.filter(e)[0].id();else var i=e.id();var a=[],l=r(f,d[o.id()],d[i],E,a,v);return null!=l&&l.reverse(),t.spawn(l)},hasNegativeWeightCycle:!1};return _}}};t.exports=a},{"../../is":83,"../../util":100}],5:[function(e,t,r){"use strict";var n=e("../../is"),i=e("../../heap"),a={betweennessCentrality:function(e){e=e||{};var t,r;n.fn(e.weight)?(r=e.weight,t=!0):t=!1;for(var a,o=null!=e.directed?e.directed:!1,s=this._private.cy,l=this.nodes(),u={},c={},d={set:function(e,t){c[e]=t,t>a&&(a=t)},get:function(e){return c[e]}},h=0;h<l.length;h++){var p=l[h],f=p.id();o?u[f]=p.outgoers().nodes():u[f]=p.openNeighborhood().nodes(),d.set(f,0)}for(var v=0;v<l.length;v++){for(var g=l[v].id(),y=[],m={},b={},x={},w=new i(function(e,t){return x[e]-x[t]}),h=0;h<l.length;h++){var f=l[h].id();m[f]=[],b[f]=0,x[f]=1/0}for(b[g]=1,x[g]=0,w.push(g);!w.empty();){var p=w.pop();if(y.push(p),t)for(var E=0;E<u[p].length;E++){var _,P=u[p][E],S=s.getElementById(p);_=S.edgesTo(P).length>0?S.edgesTo(P)[0]:P.edgesTo(S)[0];var k=r.apply(_,[_]);P=P.id(),x[P]>x[p]+k&&(x[P]=x[p]+k,w.nodes.indexOf(P)<0?w.push(P):w.updateItem(P),b[P]=0,m[P]=[]),x[P]==x[p]+k&&(b[P]=b[P]+b[p],m[P].push(p))}else for(var E=0;E<u[p].length;E++){var P=u[p][E].id();x[P]==1/0&&(w.push(P),x[P]=x[p]+1),x[P]==x[p]+1&&(b[P]=b[P]+b[p],m[P].push(p))}}for(var T={},h=0;h<l.length;h++)T[l[h].id()]=0;for(;y.length>0;)for(var P=y.pop(),E=0;E<m[P].length;E++){var p=m[P][E];T[p]=T[p]+b[p]/b[P]*(1+T[P]),P!=l[v].id()&&d.set(P,d.get(P)+T[P])}}var D={betweenness:function(e){if(n.string(e))var e=s.filter(e).id();else var e=e.id();return d.get(e)},betweennessNormalized:function(e){if(n.string(e))var e=s.filter(e).id();else var e=e.id();return d.get(e)/a}};return D.betweennessNormalised=D.betweennessNormalized,D}};a.bc=a.betweennessCentrality,t.exports=a},{"../../heap":81,"../../is":83}],6:[function(e,t,r){"use strict";var n=e("../../is"),i=function(e){return e={bfs:e.bfs||!e.dfs,dfs:e.dfs||!e.bfs},function(t,r,i){var a,o,s;n.plainObject(t)&&!n.elementOrCollection(t)&&(a=t,t=a.roots||a.root,r=a.visit,i=a.directed,o=a.std,s=a.thisArg),i=2!==arguments.length||n.fn(r)?i:r,r=n.fn(r)?r:function(){};for(var l,u=this._private.cy,c=t=n.string(t)?this.filter(t):t,d=[],h=[],p={},f={},v={},g=0,y=this.nodes(),m=this.edges(),b=0;b<c.length;b++)c[b].isNode()&&(d.unshift(c[b]),e.bfs&&(v[c[b].id()]=!0,h.push(c[b])),f[c[b].id()]=0);for(;0!==d.length;){var c=e.bfs?d.shift():d.pop();if(e.dfs){if(v[c.id()])continue;v[c.id()]=!0,h.push(c)}var x,w=f[c.id()],E=p[c.id()],_=null==E?void 0:E.connectedNodes().not(c)[0];if(x=o?r.call(s,c,E,_,g++,w):r.call(c,g++,w,c,E,_),x===!0){l=c;break}if(x===!1)break;for(var P=c.connectedEdges(i?function(){return this.data("source")===c.id()}:void 0).intersect(m),b=0;b<P.length;b++){var S=P[b],k=S.connectedNodes(function(){return this.id()!==c.id()}).intersect(y);0===k.length||v[k.id()]||(k=k[0],d.push(k),e.bfs&&(v[k.id()]=!0,h.push(k)),p[k.id()]=S,f[k.id()]=f[c.id()]+1)}}for(var T=[],b=0;b<h.length;b++){var D=h[b],C=p[D.id()];C&&T.push(C),T.push(D)}return{path:u.collection(T,{unique:!0}),found:u.collection(l)}}},a={breadthFirstSearch:i({bfs:!0}),depthFirstSearch:i({dfs:!0})};a.bfs=a.breadthFirstSearch,a.dfs=a.depthFirstSearch,t.exports=a},{"../../is":83}],7:[function(e,t,r){"use strict";var n=e("../../is"),i={closenessCentralityNormalized:function(e){e=e||{};var t=this.cy(),r=e.harmonic;void 0===r&&(r=!0);for(var i={},a=0,o=this.nodes(),s=this.floydWarshall({weight:e.weight,directed:e.directed}),l=0;l<o.length;l++){for(var u=0,c=0;c<o.length;c++)if(l!=c){var d=s.distance(o[l],o[c]);u+=r?1/d:d}r||(u=1/u),u>a&&(a=u),i[o[l].id()]=u}return{closeness:function(e){if(n.string(e))var e=t.filter(e)[0].id();else var e=e.id();return i[e]/a}}},closenessCentrality:function(e){if(e=e||{},null!=e.root){if(n.string(e.root))var t=this.filter(e.root)[0];else var t=e.root[0];if(null!=e.weight&&n.fn(e.weight))var r=e.weight;else var r=function(){return 1};if(null!=e.directed&&n.bool(e.directed))var i=e.directed;else var i=!1;var a=e.harmonic;void 0===a&&(a=!0);for(var o=this.dijkstra({root:t,weight:r,directed:i}),s=0,l=this.nodes(),u=0;u<l.length;u++)if(l[u].id()!=t.id()){var c=o.distanceTo(l[u]);s+=a?1/c:c}return a?s:1/s}}};i.cc=i.closenessCentrality,i.ccn=i.closenessCentralityNormalised=i.closenessCentralityNormalized,t.exports=i},{"../../is":83}],8:[function(e,t,r){"use strict";var n=e("../../is"),i=e("../../util"),a={degreeCentralityNormalized:function(e){e=e||{};var t=this.cy();if(null!=e.directed)var r=e.directed;else var r=!1;var a=this.nodes(),o=a.length;if(r){for(var s={},l={},u=0,c=0,d=0;o>d;d++){var h=a[d],p=this.degreeCentrality(i.extend({},e,{root:h}));u<p.indegree&&(u=p.indegree),c<p.outdegree&&(c=p.outdegree),s[h.id()]=p.indegree,l[h.id()]=p.outdegree}return{indegree:function(e){if(n.string(e))var e=t.filter(e)[0].id();else var e=e.id();return s[e]/u},outdegree:function(e){if(n.string(e))var e=t.filter(e)[0].id();else var e=e.id();return l[e]/c}}}for(var f={},v=0,d=0;o>d;d++){var h=a[d],p=this.degreeCentrality(i.extend({},e,{root:h}));v<p.degree&&(v=p.degree),f[h.id()]=p.degree}return{degree:function(e){if(n.string(e))var e=t.filter(e)[0].id();else var e=e.id();return f[e]/v}}},degreeCentrality:function(e){e=e||{};var t=this;if(null!=e&&null!=e.root){var r=n.string(e.root)?this.filter(e.root)[0]:e.root[0];if(null!=e.weight&&n.fn(e.weight))var i=e.weight;else var i=function(e){return 1};if(null!=e.directed)var a=e.directed;else var a=!1;if(null!=e.alpha&&n.number(e.alpha))var o=e.alpha;else o=0;if(a){for(var s=r.connectedEdges('edge[target = "'+r.id()+'"]').intersection(t),l=r.connectedEdges('edge[source = "'+r.id()+'"]').intersection(t),u=s.length,c=l.length,d=0,h=0,p=0;p<s.length;p++){var f=s[p];d+=i.apply(f,[f])}for(var p=0;p<l.length;p++){var f=l[p];h+=i.apply(f,[f])}return{indegree:Math.pow(u,1-o)*Math.pow(d,o),outdegree:Math.pow(c,1-o)*Math.pow(h,o)}}for(var v=r.connectedEdges().intersection(t),g=v.length,y=0,p=0;p<v.length;p++){var f=v[p];y+=i.apply(f,[f])}return{degree:Math.pow(g,1-o)*Math.pow(y,o)}}}};a.dc=a.degreeCentrality,a.dcn=a.degreeCentralityNormalised=a.degreeCentralityNormalized,t.exports=a},{"../../is":83,"../../util":100}],9:[function(e,t,r){"use strict";var n=e("../../is"),i=e("../../heap"),a={dijkstra:function(e,t,r){var a;n.plainObject(e)&&!n.elementOrCollection(e)&&(a=e,e=a.root,t=a.weight,r=a.directed);var o=this._private.cy;t=n.fn(t)?t:function(){return 1};for(var s=n.string(e)?this.filter(e)[0]:e[0],l={},u={},c={},d=this.edges().filter(function(){return!this.isLoop()}),h=this.nodes(),p=function(e){return l[e.id()]},f=function(e,t){l[e.id()]=t,v.updateItem(e)},v=new i(function(e,t){return p(e)-p(t)}),g=0;g<h.length;g++){var y=h[g];l[y.id()]=y.same(s)?0:1/0,v.push(y)}for(var m=function(e,n){for(var i,a=(r?e.edgesTo(n):e.edgesWith(n)).intersect(d),o=1/0,s=0;s<a.length;s++){var l=a[s],u=t.apply(l,[l]);(o>u||!i)&&(o=u,i=l)}return{edge:i,dist:o}};v.size()>0;){var b=v.pop(),x=p(b),w=b.id();if(c[w]=x,x===Math.Infinite)break;for(var E=b.neighborhood().intersect(h),g=0;g<E.length;g++){var _=E[g],P=_.id(),S=m(b,_),k=x+S.dist;k<p(_)&&(f(_,k),u[P]={node:b,edge:S.edge})}}return{distanceTo:function(e){var t=n.string(e)?h.filter(e)[0]:e[0];return c[t.id()]},pathTo:function(e){var t=n.string(e)?h.filter(e)[0]:e[0],r=[],i=t;if(t.length>0)for(r.unshift(t);u[i.id()];){var a=u[i.id()];r.unshift(a.edge),r.unshift(a.node),i=a.node}return o.collection(r)}}}};t.exports=a},{"../../heap":81,"../../is":83}],10:[function(e,t,r){"use strict";var n=e("../../is"),i={floydWarshall:function(e){e=e||{};var t=this.cy();if(null!=e.weight&&n.fn(e.weight))var r=e.weight;else var r=function(e){return 1};if(null!=e.directed)var i=e.directed;else var i=!1;for(var a=this.edges().stdFilter(function(e){return!e.isLoop()}),o=this.nodes(),s=o.length,l={},u=0;s>u;u++)l[o[u].id()]=u;for(var c=[],u=0;s>u;u++){for(var d=new Array(s),h=0;s>h;h++)u==h?d[h]=0:d[h]=1/0;c.push(d)}var p=[],f=[],v=function(e){for(var t=0;s>t;t++){for(var r=new Array(s),n=0;s>n;n++)r[n]=void 0;e.push(r)}};v(p),v(f);for(var u=0;u<a.length;u++){var g=l[a[u].source().id()],y=l[a[u].target().id()],m=r.apply(a[u],[a[u]]);c[g][y]>m&&(c[g][y]=m,p[g][y]=y,f[g][y]=a[u])}if(!i)for(var u=0;u<a.length;u++){var g=l[a[u].target().id()],y=l[a[u].source().id()],m=r.apply(a[u],[a[u]]);c[g][y]>m&&(c[g][y]=m,p[g][y]=y,f[g][y]=a[u])}for(var b=0;s>b;b++)for(var u=0;s>u;u++)for(var h=0;s>h;h++)c[u][b]+c[b][h]<c[u][h]&&(c[u][h]=c[u][b]+c[b][h],p[u][h]=p[u][b]);for(var x=[],u=0;s>u;u++)x.push(o[u].id());var w={distance:function(e,r){if(n.string(e))var i=t.filter(e)[0].id();else var i=e.id();if(n.string(r))var a=t.filter(r)[0].id();else var a=r.id();return c[l[i]][l[a]]},path:function(e,r){var i=function(e,r,n,i,a){if(e===r)return t.getElementById(i[e]);if(void 0!==n[e][r]){for(var o=[t.getElementById(i[e])],s=e;e!==r;){s=e,e=n[e][r];var l=a[s][e];o.push(l),o.push(t.getElementById(i[e]))}return o}};if(n.string(e))var a=t.filter(e)[0].id();else var a=e.id();if(n.string(r))var o=t.filter(r)[0].id();else var o=r.id();var s=i(l[a],l[o],p,x,f);return t.collection(s)}};return w}};t.exports=i},{"../../is":83}],11:[function(e,t,r){"use strict";var n=e("../../util"),i={};[e("./bfs-dfs"),e("./dijkstra"),e("./kruskal"),e("./a-star"),e("./floyd-warshall"),e("./bellman-ford"),e("./kerger-stein"),e("./page-rank"),e("./degree-centrality"),e("./closeness-centrality"),e("./betweenness-centrality")].forEach(function(e){n.extend(i,e)}),t.exports=i},{"../../util":100,"./a-star":3,"./bellman-ford":4,"./betweenness-centrality":5,"./bfs-dfs":6,"./closeness-centrality":7,"./degree-centrality":8,"./dijkstra":9,"./floyd-warshall":10,"./kerger-stein":12,"./kruskal":13,"./page-rank":14}],12:[function(e,t,r){"use strict";var n=e("../../util"),i={kargerStein:function(e){var t=this;e=e||{};var r=function(e,t,r){for(var n=r[e],i=n[1],a=n[2],o=t[i],s=t[a],l=r.filter(function(e){return t[e[1]]===o&&t[e[2]]===s?!1:t[e[1]]!==s||t[e[2]]!==o}),u=0;u<l.length;u++){var c=l[u];c[1]===s?(l[u]=c.slice(0),l[u][1]=o):c[2]===s&&(l[u]=c.slice(0),l[u][2]=o)}for(var u=0;u<t.length;u++)t[u]===s&&(t[u]=o);return l},i=function(e,t,n,a){if(a>=n)return t;var o=Math.floor(Math.random()*t.length),s=r(o,e,t);return i(e,s,n-1,a)},a=this._private.cy,o=this.edges().stdFilter(function(e){return!e.isLoop()}),s=this.nodes(),l=s.length,u=o.length,c=Math.ceil(Math.pow(Math.log(l)/Math.LN2,2)),d=Math.floor(l/Math.sqrt(2));if(2>l)return void n.error("At least 2 nodes are required for Karger-Stein algorithm");for(var h={},p=0;l>p;p++)h[s[p].id()]=p;for(var f=[],p=0;u>p;p++){var v=o[p];f.push([p,h[v.source().id()],h[v.target().id()]])}for(var g,y=1/0,m=[],p=0;l>p;p++)m.push(p);for(var b=0;c>=b;b++){var x=m.slice(0),w=i(x,f,l,d),E=x.slice(0),_=i(x,w,d,2),P=i(E,w,d,2);_.length<=P.length&&_.length<y?(y=_.length,g=[_,x]):P.length<=_.length&&P.length<y&&(y=P.length,g=[P,E])}for(var S=g[0].map(function(e){return o[e[0]]}),k=[],T=[],D=g[1][0],p=0;p<g[1].length;p++){var C=g[1][p];C===D?k.push(s[p]):T.push(s[p])}var M={cut:t.spawn(a,S),partition1:t.spawn(k),partition2:t.spawn(T)};return M}};t.exports=i},{"../../util":100}],13:[function(e,t,r){"use strict";var n=e("../../is"),i={kruskal:function(e){function t(e){for(var t=0;t<a.length;t++){var r=a[t];if(r.anySame(e))return{eles:r,index:t}}}var r=this.cy();e=n.fn(e)?e:function(){return 1};for(var i=r.collection(r,[]),a=[],o=this.nodes(),s=0;s<o.length;s++)a.push(o[s].collection());for(var l=this.edges(),u=l.toArray().sort(function(t,r){var n=e.call(t,t),i=e.call(r,r);return n-i}),s=0;s<u.length;s++){var c=u[s],d=c.source()[0],h=c.target()[0],p=t(d),f=t(h);p.index!==f.index&&(i=i.add(c),a[p.index]=p.eles.add(f.eles),a.splice(f.index,1))}return o.add(i)}};t.exports=i},{"../../is":83}],14:[function(e,t,r){"use strict";var n=e("../../is"),i={pageRank:function(e){e=e||{};var t=function(e){for(var t=e.length,r=0,n=0;t>n;n++)r+=e[n];for(var n=0;t>n;n++)e[n]=e[n]/r};if(null!=e&&null!=e.dampingFactor)var r=e.dampingFactor;else var r=.8;if(null!=e&&null!=e.precision)var i=e.precision;else var i=1e-6;if(null!=e&&null!=e.iterations)var a=e.iterations;else var a=200;if(null!=e&&null!=e.weight&&n.fn(e.weight))var o=e.weight;else var o=function(e){return 1};for(var s=this._private.cy,l=this.edges().stdFilter(function(e){return!e.isLoop()}),u=this.nodes(),c=u.length,d=l.length,h={},p=0;c>p;p++)h[u[p].id()]=p;for(var f=[],v=[],g=(1-r)/c,p=0;c>p;p++){for(var y=[],m=0;c>m;m++)y.push(0);f.push(y),v.push(0)}for(var p=0;d>p;p++){var b=l[p],x=h[b.source().id()],w=h[b.target().id()],E=o.apply(b,[b]);f[w][x]+=E,v[x]+=E}for(var _=1/c+g,m=0;c>m;m++)if(0===v[m])for(var p=0;c>p;p++)f[p][m]=_;else for(var p=0;c>p;p++)f[p][m]=f[p][m]/v[m]+g;for(var P,S=[],k=[],p=0;c>p;p++)S.push(1),k.push(0);for(var T=0;a>T;T++){for(var D=k.slice(0),p=0;c>p;p++)for(var m=0;c>m;m++)D[p]+=f[p][m]*S[m];t(D),P=S,S=D;for(var C=0,p=0;c>p;p++)C+=Math.pow(P[p]-S[p],2);if(i>C)break}var M={rank:function(e){if(n.string(e))var t=s.filter(e)[0].id();else var t=e.id();return S[h[t]]}};return M}};t.exports=i},{"../../is":83}],15:[function(e,t,r){"use strict";var n=e("../define"),i={animate:n.animate(),animation:n.animation(),animated:n.animated(),clearQueue:n.clearQueue(),delay:n.delay(),delayAnimation:n.delayAnimation(),stop:n.stop()};t.exports=i},{"../define":44}],16:[function(e,t,r){"use strict";var n=e("../util"),i={classes:function(e){e=e.match(/\S+/g)||[];for(var t=this,r=[],i={},a=0;a<e.length;a++){var o=e[a];i[o]=!0}for(var s=0;s<t.length;s++){for(var l=t[s],u=l._private,c=u.classes,d=!1,a=0;a<e.length;a++){var o=e[a],h=c[o];if(!h){d=!0;break}}if(!d)for(var e=Object.keys(c),a=0;a<e.length;a++){var p=e[a],h=c[p],f=i[p];if(h&&!f){d=!0;break}}d&&(u.classes=n.copy(i),r.push(l))}return r.length>0&&this.spawn(r).updateStyle().trigger("class"),t},addClass:function(e){return this.toggleClass(e,!0)},hasClass:function(e){var t=this[0];return!(null==t||!t._private.classes[e])},toggleClass:function(e,t){for(var r=e.match(/\S+/g)||[],n=this,i=[],a=0,o=n.length;o>a;a++)for(var s=n[a],l=!1,u=0;u<r.length;u++){var c=r[u],d=s._private.classes,h=d[c],p=t||void 0===t&&!h;p?(d[c]=!0,h||l||(i.push(s),l=!0)):(d[c]=!1,h&&!l&&(i.push(s),l=!0))}return i.length>0&&this.spawn(i).updateStyle().trigger("class"),n},removeClass:function(e){return this.toggleClass(e,!1)},flashClass:function(e,t){var r=this;if(null==t)t=250;else if(0===t)return r;return r.addClass(e),setTimeout(function(){r.removeClass(e)},t),r}};t.exports=i},{"../util":100}],17:[function(e,t,r){"use strict";var n={allAre:function(e){return this.filter(e).length===this.length},is:function(e){return this.filter(e).length>0},some:function(e,t){for(var r=0;r<this.length;r++){var n=t?e.apply(t,[this[r],r,this]):e(this[r],r,this);if(n)return!0}return!1},every:function(e,t){for(var r=0;r<this.length;r++){var n=t?e.apply(t,[this[r],r,this]):e(this[r],r,this);if(!n)return!1}return!0},same:function(e){return e=this.cy().collection(e),this.length!==e.length?!1:this.intersect(e).length===this.length},anySame:function(e){return e=this.cy().collection(e),this.intersect(e).length>0},allAreNeighbors:function(e){return e=this.cy().collection(e),this.neighborhood().intersect(e).length===e.length}};n.allAreNeighbours=n.allAreNeighbors,t.exports=n},{}],18:[function(e,t,r){"use strict";var n={parent:function(e){for(var t=[],r=this._private.cy,n=0;n<this.length;n++){var i=this[n],a=r.getElementById(i._private.data.parent);a.size()>0&&t.push(a)}return this.spawn(t,{unique:!0}).filter(e)},parents:function(e){for(var t=[],r=this.parent();r.nonempty();){for(var n=0;n<r.length;n++){var i=r[n];t.push(i)}r=r.parent()}return this.spawn(t,{unique:!0}).filter(e)},commonAncestors:function(e){for(var t,r=0;r<this.length;r++){var n=this[r],i=n.parents();t=t||i,t=t.intersect(i)}return t.filter(e)},orphans:function(e){return this.stdFilter(function(e){return e.isNode()&&e.parent().empty()}).filter(e)},nonorphans:function(e){return this.stdFilter(function(e){return e.isNode()&&e.parent().nonempty()}).filter(e)},children:function(e){for(var t=[],r=0;r<this.length;r++){var n=this[r];t=t.concat(n._private.children)}return this.spawn(t,{unique:!0}).filter(e)},siblings:function(e){return this.parent().children().not(this).filter(e)},isParent:function(){var e=this[0];return e?0!==e._private.children.length:void 0},isChild:function(){var e=this[0];return e?void 0!==e._private.data.parent&&0!==e.parent().length:void 0},descendants:function(e){function t(e){for(var n=0;n<e.length;n++){var i=e[n];r.push(i),i.children().nonempty()&&t(i.children())}}var r=[];return t(this.children()),this.spawn(r,{unique:!0}).filter(e)}};n.ancestors=n.parents,t.exports=n},{}],19:[function(e,t,r){"use strict";var n,i,a=e("../define");n=i={data:a.data({field:"data",bindingEvent:"data",allowBinding:!0,allowSetting:!0,settingEvent:"data",settingTriggersEvent:!0,triggerFnName:"trigger",allowGetting:!0,immutableKeys:{id:!0,source:!0,target:!0,parent:!0},updateStyle:!0}),removeData:a.removeData({field:"data",event:"data",triggerFnName:"trigger",triggerEvent:!0,immutableKeys:{id:!0,source:!0,target:!0,parent:!0},updateStyle:!0}),scratch:a.data({field:"scratch",bindingEvent:"scratch",allowBinding:!0,allowSetting:!0,settingEvent:"scratch",settingTriggersEvent:!0,triggerFnName:"trigger",allowGetting:!0,updateStyle:!0}),removeScratch:a.removeData({field:"scratch",event:"scratch",triggerFnName:"trigger",triggerEvent:!0,updateStyle:!0}),rscratch:a.data({field:"rscratch",allowBinding:!1,allowSetting:!0,settingTriggersEvent:!1,allowGetting:!0}),removeRscratch:a.removeData({field:"rscratch",triggerEvent:!1}),id:function(){var e=this[0];return e?e._private.data.id:void 0}},n.attr=n.data,n.removeAttr=n.removeData,t.exports=i},{"../define":44}],20:[function(e,t,r){"use strict";function n(e){return function(t){var r=this;if(void 0===t&&(t=!0),0!==r.length&&r.isNode()&&!r.removed()){for(var n=0,i=r[0],a=i._private.edges,o=0;o<a.length;o++){var s=a[o];!t&&s.isLoop()||(n+=e(i,s))}return n}}}function i(e,t){return function(r){for(var n,i=this.nodes(),a=0;a<i.length;a++){var o=i[a],s=o[e](r);void 0===s||void 0!==n&&!t(s,n)||(n=s)}return n}}var a=e("../util"),o={};a.extend(o,{degree:n(function(e,t){return t.source().same(t.target())?2:1}),indegree:n(function(e,t){return t.target().same(e)?1:0}),outdegree:n(function(e,t){return t.source().same(e)?1:0})}),a.extend(o,{minDegree:i("degree",function(e,t){return t>e}),maxDegree:i("degree",function(e,t){return e>t}),minIndegree:i("indegree",function(e,t){return t>e}),maxIndegree:i("indegree",function(e,t){return e>t}),minOutdegree:i("outdegree",function(e,t){return t>e}),maxOutdegree:i("outdegree",function(e,t){return e>t})}),a.extend(o,{totalDegree:function(e){for(var t=0,r=this.nodes(),n=0;n<r.length;n++)t+=r[n].degree(e);return t}}),t.exports=o},{"../util":100}],21:[function(e,t,r){"use strict";var n,i,a=e("../define"),o=e("../is"),s=e("../util"),l=e("../math");n=i={position:a.data({field:"position",bindingEvent:"position",allowBinding:!0,allowSetting:!0,settingEvent:"position",settingTriggersEvent:!0,triggerFnName:"rtrigger",allowGetting:!0,validKeys:["x","y"],onSet:function(e){var t=e.updateCompoundBounds();t.rtrigger("position")},canSet:function(e){return!e.locked()&&!e.isParent()}}),silentPosition:a.data({field:"position",bindingEvent:"position",allowBinding:!1,allowSetting:!0,settingEvent:"position",settingTriggersEvent:!1,triggerFnName:"trigger",allowGetting:!0,validKeys:["x","y"],onSet:function(e){e.updateCompoundBounds()},canSet:function(e){return!e.locked()&&!e.isParent()}}),positions:function(e,t){if(o.plainObject(e))this.position(e);else if(o.fn(e)){for(var r=e,n=0;n<this.length;n++){var i=this[n],e=r.apply(i,[n,i]);if(e&&!i.locked()&&!i.isParent()){var a=i._private.position;a.x=e.x,a.y=e.y}}var s=this.updateCompoundBounds(),l=s.length>0?this.add(s):this;t?l.trigger("position"):l.rtrigger("position")}return this},silentPositions:function(e){return this.positions(e,!0)},renderedPosition:function(e,t){var r=this[0],n=this.cy(),i=n.zoom(),a=n.pan(),s=o.plainObject(e)?e:void 0,l=void 0!==s||void 0!==t&&o.string(e);if(r&&r.isNode()){if(!l){var u=r._private.position;return s={x:u.x*i+a.x,y:u.y*i+a.y},void 0===e?s:s[e]}for(var c=0;c<this.length;c++){var r=this[c];void 0!==t?r._private.position[e]=(t-a[e])/i:void 0!==s&&(r._private.position={x:(s.x-a.x)/i,y:(s.y-a.y)/i})}this.rtrigger("position")}else if(!l)return;return this},relativePosition:function(e,t){var r=this[0],n=this.cy(),i=o.plainObject(e)?e:void 0,a=void 0!==i||void 0!==t&&o.string(e),s=n.hasCompoundNodes();if(r&&r.isNode()){if(!a){var l=r._private.position,u=s?r.parent():null,c=u&&u.length>0,d=c;c&&(u=u[0]);var h=d?u._private.position:{x:0,y:0};return i={x:l.x-h.x,y:l.y-h.y},void 0===e?i:i[e]}for(var p=0;p<this.length;p++){var r=this[p],u=s?r.parent():null,c=u&&u.length>0,d=c;c&&(u=u[0]);var h=d?u._private.position:{x:0,y:0};void 0!==t?r._private.position[e]=t+h[e]:void 0!==i&&(r._private.position={x:i.x+h.x,y:i.y+h.y})}this.rtrigger("position")}else if(!a)return;return this},renderedBoundingBox:function(e){var t=this.boundingBox(e),r=this.cy(),n=r.zoom(),i=r.pan(),a=t.x1*n+i.x,o=t.x2*n+i.x,s=t.y1*n+i.y,l=t.y2*n+i.y;return{x1:a,x2:o,y1:s,y2:l,w:o-a,h:l-s}},updateCompoundBounds:function(){function e(e){if(e.isParent()){var t=e._private,n=e.children(),i="include"===e.pstyle("compound-sizing-wrt-labels").value,a=n.boundingBox({includeLabels:i,includeShadows:!1,includeOverlays:!1,useCache:!1}),o={top:e.pstyle("padding-top").pfValue,bottom:e.pstyle("padding-bottom").pfValue,left:e.pstyle("padding-left").pfValue,right:e.pstyle("padding-right").pfValue},s=t.position;t.autoWidth=a.w,s.x=(a.x1+a.x2-o.left+o.right)/2,t.autoHeight=a.h,s.y=(a.y1+a.y2-o.top+o.bottom)/2,r.push(e)}}var t=this.cy();if(!t.styleEnabled()||!t.hasCompoundNodes())return t.collection();for(var r=[],n=this;n.nonempty();){for(var i=0;i<n.length;i++){var a=n[i];e(a)}n=n.parent()}return this.spawn(r)}};var u=function(e){return e===1/0||e===-(1/0)?0:e},c=function(e,t,r,n,i){n-t!==0&&i-r!==0&&(e.x1=t<e.x1?t:e.x1,e.x2=n>e.x2?n:e.x2,e.y1=r<e.y1?r:e.y1,e.y2=i>e.y2?i:e.y2)},d=function(e,t){return c(e,t.x1,t.y1,t.x2,t.y2)},h=function(e,t,r){return s.getPrefixedProperty(e,t,r)},p=function(e,t,r,n){var i,a,o=t._private,s=o.rstyle,l=s.arrowWidth/2,u=t.pstyle(r+"-arrow-shape").value;"none"!==u&&("source"===r?(i=s.srcX,a=s.srcY):"target"===r?(i=s.tgtX,a=s.tgtY):(i=s.midX,a=s.midY),c(e,i-l,a-l,i+l,a+l))},f=function(e,t,r,n){var i;i=r?r+"-":"";var a=t._private,o=a.rstyle,s=t.pstyle(i+"label").strValue;if(s){var l,u,d,p,f=t.pstyle("text-halign"),v=t.pstyle("text-valign"),g=h(o,"labelWidth",r),y=h(o,"labelHeight",r),m=h(o,"labelX",r),b=h(o,"labelY",r),x=t.pstyle(i+"text-margin-x").pfValue,w=t.pstyle(i+"text-margin-y").pfValue,E=t.isEdge(),_=t.pstyle(i+"text-rotation"),P=t.pstyle("text-shadow-blur").pfValue/2,S=t.pstyle("text-shadow-offset-x").pfValue,k=t.pstyle("text-shadow-offset-y").pfValue,T=t.pstyle("text-shadow-opacity").value,D=t.pstyle("text-outline-width").pfValue,C=t.pstyle("text-border-width").pfValue,M=C/2,N=y,B=g,z=B/2,I=N/2;if(E)l=m-z,u=m+z,d=b-I,p=b+I;else{switch(f.value){case"left":l=m-B,u=m;break;case"center":l=m-z,u=m+z;break;case"right":l=m,u=m+B}switch(v.value){case"top":d=b-N,p=b;break;case"center":d=b-I,p=b+I;break;case"bottom":d=b,p=b+N}}var L=E&&"autorotate"===_.strValue,O=null!=_.pfValue&&0!==_.pfValue;if(L||O){var A=L?h(a.rstyle,"labelAngle",r):_.pfValue,R=Math.cos(A),q=Math.sin(A),V=function(e,t){return e-=m,t-=b,{x:e*R-t*q+m,y:e*q+t*R+b}},F=V(l,d),j=V(l,p),X=V(u,d),Y=V(u,p);l=Math.min(F.x,j.x,X.x,Y.x),u=Math.max(F.x,j.x,X.x,Y.x),d=Math.min(F.y,j.y,X.y,Y.y),p=Math.max(F.y,j.y,X.y,Y.y)}l+=x-Math.max(D,M),u+=x+Math.max(D,M),d+=w-Math.max(D,M),p+=w+Math.max(D,M),c(e,l,d,u,p),n.includeShadows&&T>0&&(l+=-P+S,u+=+P+S,d+=-P+k,p+=+P+k,c(e,l,d,u,p))}return e},v=function(e,t){var r,n,i,a,o,s,d=e._private.cy,h=d._private,v=h.styleEnabled,g={x1:1/0,y1:1/0,x2:-(1/0),y2:-(1/0)},y=e._private,m=v?e.pstyle("display").value:"element",b=e.isNode(),x=e.isEdge(),w="none"!==m;if(w){var E=0,_=0;v&&t.includeOverlays&&(E=e.pstyle("overlay-opacity").value,0!==E&&(_=e.pstyle("overlay-padding").value));var P=0,S=0;if(v&&(P=e.pstyle("width").pfValue,S=P/2),b&&t.includeNodes){var k=y.position;o=k.x,s=k.y;var P=e.outerWidth(),T=P/2,D=e.outerHeight(),C=D/2;r=o-T-_,n=o+T+_,i=s-C-_,a=s+C+_,c(g,r,i,n,a)}else if(x&&t.includeEdges){var M=y.rstyle||{};if(v&&(r=Math.min(M.srcX,M.midX,M.tgtX),n=Math.max(M.srcX,M.midX,M.tgtX),i=Math.min(M.srcY,M.midY,M.tgtY),a=Math.max(M.srcY,M.midY,M.tgtY),r-=S,n+=S,i-=S,a+=S,c(g,r,i,n,a)),v&&"haystack"===e.pstyle("curve-style").strValue){var N=M.haystackPts;if(r=N[0].x,i=N[0].y,n=N[1].x,a=N[1].y,r>n){var B=r;r=n,n=B}if(i>a){var B=i;i=a,a=B}c(g,r-S,i-S,n+S,a+S)}else{for(var z=M.bezierPts||M.linePts||[],I=0;I<z.length;I++){var L=z[I];r=L.x-S,n=L.x+S,i=L.y-S,a=L.y+S,c(g,r,i,n,a)}if(0===z.length){var O=y.source,A=O._private,R=A.position,q=y.target,V=q._private,F=V.position;if(r=R.x,n=F.x,i=R.y,a=F.y,r>n){var B=r;r=n,n=B}if(i>a){var B=i;i=a,a=B}r-=S,n+=S,i-=S,a+=S,c(g,r,i,n,a)}}}if(v){if(r=g.x1,n=g.x2,i=g.y1,a=g.y2,t.includeShadows&&e.pstyle("shadow-opacity").value>0){var j=e.pstyle("shadow-blur").pfValue/2,X=e.pstyle("shadow-offset-x").pfValue,Y=e.pstyle("shadow-offset-y").pfValue;c(g,r-j+X,i-j+Y,n+j+X,a+j+Y)}c(g,r-_,i-_,n+_,a+_)}v&&t.includeEdges&&x&&(p(g,e,"mid-source",t),p(g,e,"mid-target",t),p(g,e,"source",t),p(g,e,"target",t)),v&&t.includeLabels&&(f(g,e,null,t),x&&(f(g,e,"source",t),f(g,e,"target",t)))}return g.x1=u(g.x1),g.y1=u(g.y1),g.x2=u(g.x2),g.y2=u(g.y2),g.w=u(g.x2-g.x1),g.h=u(g.y2-g.y1),g.w>0&&g.h>0&&w&&l.expandBoundingBox(g,1),g},g=function(e){return e?"t":"f"},y=function(e){var t="";return t+=g(e.incudeNodes),t+=g(e.includeEdges),t+=g(e.includeLabels),t+=g(e.includeShadows),t+=g(e.includeOverlays)},m=function(e,t){var r,n=e._private,i=e.cy().headless(),a=t===b?x:y(t);return t.useCache&&!i&&n.bbCache&&n.bbCache[a]?r=n.bbCache[a]:(r=v(e,t),i||(n.bbCache=n.bbCache||{},n.bbCache[a]=r)),r},b={includeNodes:!0,includeEdges:!0,includeLabels:!0,includeShadows:!0,includeOverlays:!0,useCache:!0},x=y(b);i.boundingBox=function(e){if(1===this.length&&this[0]._private.bbCache&&(void 0===e||void 0===e.useCache||e.useCache===!0))return void 0===e&&(e=b),m(this[0],e);var t={x1:1/0,y1:1/0,x2:-(1/0),y2:-(1/0)};e=e||s.staticEmptyObject();var r={includeNodes:s["default"](e.includeNodes,b.includeNodes),includeEdges:s["default"](e.includeEdges,b.includeEdges),includeLabels:s["default"](e.includeLabels,b.includeLabels),includeShadows:s["default"](e.includeShadows,b.includeShadows),includeOverlays:s["default"](e.includeOverlays,b.includeOverlays),useCache:s["default"](e.useCache,b.useCache)},n=this,i=n.cy(),a=n.cy().renderer(),o=i.styleEnabled(); +o&&a.recalculateRenderedStyle(n,r.useCache);for(var l=0;l<n.length;l++){var c=n[l];o&&c.isEdge()&&"bezier"===c.pstyle("curve-style").strValue&&a.recalculateRenderedStyle(c.parallelEdges(),r.useCache),d(t,m(c,r))}return t.x1=u(t.x1),t.y1=u(t.y1),t.x2=u(t.x2),t.y2=u(t.y2),t.w=u(t.x2-t.x1),t.h=u(t.y2-t.y1),t};var w=function(e){e.uppercaseName=s.capitalize(e.name),e.autoName="auto"+e.uppercaseName,e.labelName="label"+e.uppercaseName,e.outerName="outer"+e.uppercaseName,e.uppercaseOuterName=s.capitalize(e.outerName),n[e.name]=function(){var t=this[0],r=t._private,n=r.cy,i=n._private.styleEnabled;if(t){if(!i)return 1;if(t.isParent())return r[e.autoName]||0;var a=t.pstyle(e.name);switch(a.strValue){case"label":return r.rstyle[e.labelName]||0;default:return a.pfValue}}},n["outer"+e.uppercaseName]=function(){var t=this[0],r=t._private,n=r.cy,i=n._private.styleEnabled;if(t){if(i){var a=t[e.name](),o=t.pstyle("border-width").pfValue,s=t.pstyle(e.paddings[0]).pfValue+t.pstyle(e.paddings[1]).pfValue;return a+o+s}return 1}},n["rendered"+e.uppercaseName]=function(){var t=this[0];if(t){var r=t[e.name]();return r*this.cy().zoom()}},n["rendered"+e.uppercaseOuterName]=function(){var t=this[0];if(t){var r=t[e.outerName]();return r*this.cy().zoom()}}};w({name:"width",paddings:["padding-left","padding-right"]}),w({name:"height",paddings:["padding-top","padding-bottom"]}),n.modelPosition=n.point=n.position,n.modelPositions=n.points=n.positions,n.renderedPoint=n.renderedPosition,n.relativePoint=n.relativePosition,n.boundingbox=n.boundingBox,n.renderedBoundingbox=n.renderedBoundingBox,t.exports=i},{"../define":44,"../is":83,"../math":85,"../util":100}],22:[function(e,t,r){"use strict";var n=e("../util"),i=e("../is"),a=function(e,t,r){var a=this;if(r=!(void 0!==r&&!r),void 0===e||void 0===t||!i.core(e))return void n.error("An element must have a core reference and parameters set");var o=t.group;if(null==o&&(o=t.data&&null!=t.data.source&&null!=t.data.target?"edges":"nodes"),"nodes"!==o&&"edges"!==o)return void n.error("An element must be of type `nodes` or `edges`; you specified `"+o+"`");if(this.length=1,this[0]=this,this._private={cy:e,single:!0,data:t.data||{},position:t.position||{},autoWidth:void 0,autoHeight:void 0,listeners:[],group:o,style:{},rstyle:{},styleCxts:[],removed:!0,selected:!!t.selected,selectable:void 0===t.selectable?!0:!!t.selectable,locked:!!t.locked,grabbed:!1,grabbable:void 0===t.grabbable?!0:!!t.grabbable,active:!1,classes:{},animation:{current:[],queue:[]},rscratch:{},scratch:t.scratch||{},edges:[],children:[],traversalCache:{}},t.renderedPosition){var s=t.renderedPosition,l=e.pan(),u=e.zoom();this._private.position={x:(s.x-l.x)/u,y:(s.y-l.y)/u}}if(i.string(t.classes))for(var c=t.classes.split(/\s+/),d=0,h=c.length;h>d;d++){var p=c[d];p&&""!==p&&(a._private.classes[p]=!0)}(t.style||t.css)&&e.style().applyBypass(this,t.style||t.css),(void 0===r||r)&&this.restore()};t.exports=a},{"../is":83,"../util":100}],23:[function(e,t,r){"use strict";var n=e("../define"),i={on:n.on(),one:n.on({unbindSelfOnTrigger:!0}),once:n.on({unbindAllBindersOnTrigger:!0}),off:n.off(),trigger:n.trigger(),rtrigger:function(e,t){return 0!==this.length?(this.cy().notify({type:e,eles:this}),this.trigger(e,t),this):void 0}};n.eventAliasesOn(i),t.exports=i},{"../define":44}],24:[function(e,t,r){"use strict";var n=e("../is"),i=e("../selector"),a={nodes:function(e){return this.filter(function(e,t){return t.isNode()}).filter(e)},edges:function(e){return this.filter(function(e,t){return t.isEdge()}).filter(e)},filter:function(e){if(void 0===e)return this;if(n.string(e)||n.elementOrCollection(e))return i(e).filter(this);if(n.fn(e)){for(var t=[],r=0;r<this.length;r++){var a=this[r];e.apply(a,[r,a])&&t.push(a)}return this.spawn(t)}return this.spawn()},not:function(e){if(e){n.string(e)&&(e=this.filter(e));for(var t=[],r=0;r<this.length;r++){var i=this[r],a=e._private.ids[i.id()];a||t.push(i)}return this.spawn(t)}return this},absoluteComplement:function(){var e=this._private.cy;return e.mutableElements().not(this)},intersect:function(e){if(n.string(e)){var t=e;return this.filter(t)}for(var r=[],i=this,a=e,o=this.length<e.length,s=o?a._private.ids:i._private.ids,l=o?i:a,u=0;u<l.length;u++){var c=l[u]._private.data.id,d=s[c];d&&r.push(d)}return this.spawn(r)},xor:function(e){var t=this._private.cy;n.string(e)&&(e=t.$(e));var r=[],i=this,a=e,o=function(e,t){for(var n=0;n<e.length;n++){var i=e[n],a=i._private.data.id,o=t._private.ids[a];o||r.push(i)}};return o(i,a),o(a,i),this.spawn(r)},diff:function(e){var t=this._private.cy;n.string(e)&&(e=t.$(e));var r=[],i=[],a=[],o=this,s=e,l=function(e,t,r){for(var n=0;n<e.length;n++){var i=e[n],o=i._private.data.id,s=t._private.ids[o];s?a.push(i):r.push(i)}};return l(o,s,r),l(s,o,i),{left:this.spawn(r,{unique:!0}),right:this.spawn(i,{unique:!0}),both:this.spawn(a,{unique:!0})}},add:function(e){var t=this._private.cy;if(!e)return this;if(n.string(e)){var r=e;e=t.mutableElements().filter(r)}for(var i=[],a=0;a<this.length;a++)i.push(this[a]);for(var a=0;a<e.length;a++){var o=!this._private.ids[e[a].id()];o&&i.push(e[a])}return this.spawn(i)},merge:function(e){var t=this._private,r=t.cy;if(!e)return this;if(e&&n.string(e)){var i=e;e=r.mutableElements().filter(i)}for(var a=0;a<e.length;a++){var o=e[a],s=o._private.data.id,l=!t.ids[s];if(l){var u=this.length++;this[u]=o,t.ids[s]=o,t.indexes[s]=u}else{var u=t.indexes[s];this[u]=o,t.ids[s]=o}}return this},unmergeOne:function(e){e=e[0];var t=this._private,r=e._private.data.id,n=t.indexes[r];if(null==n)return this;this[n]=void 0,t.ids[r]=void 0,t.indexes[r]=void 0;var i=n===this.length-1;if(this.length>1&&!i){var a=this.length-1,o=this[a],s=o._private.data.id;this[a]=void 0,this[n]=o,t.indexes[s]=n}return this.length--,this},unmerge:function(e){var t=this._private.cy;if(!e)return this;if(e&&n.string(e)){var r=e;e=t.mutableElements().filter(r)}for(var i=0;i<e.length;i++)this.unmergeOne(e[i]);return this},map:function(e,t){for(var r=[],n=this,i=0;i<n.length;i++){var a=n[i],o=t?e.apply(t,[a,i,n]):e(a,i,n);r.push(o)}return r},stdFilter:function(e,t){for(var r=[],n=this,i=0;i<n.length;i++){var a=n[i],o=t?e.apply(t,[a,i,n]):e(a,i,n);o&&r.push(a)}return this.spawn(r)},max:function(e,t){for(var r,n=-(1/0),i=this,a=0;a<i.length;a++){var o=i[a],s=t?e.apply(t,[o,a,i]):e(o,a,i);s>n&&(n=s,r=o)}return{value:n,ele:r}},min:function(e,t){for(var r,n=1/0,i=this,a=0;a<i.length;a++){var o=i[a],s=t?e.apply(t,[o,a,i]):e(o,a,i);n>s&&(n=s,r=o)}return{value:n,ele:r}}},o=a;o.u=o["|"]=o["+"]=o.union=o.or=o.add,o["\\"]=o["!"]=o["-"]=o.difference=o.relativeComplement=o.subtract=o.not,o.n=o["&"]=o["."]=o.and=o.intersection=o.intersect,o["^"]=o["(+)"]=o["(-)"]=o.symmetricDifference=o.symdiff=o.xor,o.fnFilter=o.filterFn=o.stdFilter,o.complement=o.abscomp=o.absoluteComplement,t.exports=a},{"../is":83,"../selector":87}],25:[function(e,t,r){"use strict";var n={isNode:function(){return"nodes"===this.group()},isEdge:function(){return"edges"===this.group()},isLoop:function(){return this.isEdge()&&this.source().id()===this.target().id()},isSimple:function(){return this.isEdge()&&this.source().id()!==this.target().id()},group:function(){var e=this[0];return e?e._private.group:void 0}};t.exports=n},{}],26:[function(e,t,r){"use strict";var n=e("../util"),i=e("../is"),a=e("./element"),o={generate:function(e,t,r){for(var i=null!=r?r:n.uuid();e.hasElementWithId(i);)i=n.uuid();return i}},s=function(e,t,r){if(void 0===e||!i.core(e))return void n.error("A collection must have a reference to the core");var s={},l={},u=!1;if(t){if(t.length>0&&i.plainObject(t[0])&&!i.element(t[0])){u=!0;for(var c=[],d={},h=0,p=t.length;p>h;h++){var f=t[h];null==f.data&&(f.data={});var v=f.data;if(null==v.id)v.id=o.generate(e,f);else if(e.hasElementWithId(v.id)||d[v.id])continue;var g=new a(e,f,!1);c.push(g),d[v.id]=!0}t=c}}else t=[];this.length=0;for(var h=0,p=t.length;p>h;h++){var y=t[h];if(y){var m=y._private.data.id;(!r||r.unique&&!s[m])&&(s[m]=y,l[m]=this.length,this[this.length]=y,this.length++)}}this._private={cy:e,ids:s,indexes:l},u&&this.restore()},l=a.prototype=s.prototype;l.instanceString=function(){return"collection"},l.spawn=function(e,t,r){return i.core(e)||(r=t,t=e,e=this.cy()),new s(e,t,r)},l.spawnSelf=function(){return this.spawn(this)},l.cy=function(){return this._private.cy},l.element=function(){return this[0]},l.collection=function(){return i.collection(this)?this:new s(this._private.cy,[this])},l.unique=function(){return new s(this._private.cy,this,{unique:!0})},l.hasElementWithId=function(e){return!!this._private.ids[e]},l.getElementById=function(e){var t=this._private.cy,r=this._private.ids[e];return r?r:new s(t)},l.poolIndex=function(){var e=this._private.cy,t=e._private.elements,r=this._private.data.id;return t._private.indexes[r]},l.json=function(e){var t=this.element(),r=this.cy();if(null==t&&e)return this;if(null!=t){var a=t._private;if(i.plainObject(e)){r.startBatch(),e.data&&t.data(e.data),e.position&&t.position(e.position);var o=function(r,n,i){var o=e[r];null!=o&&o!==a[r]&&(o?t[n]():t[i]())};return o("removed","remove","restore"),o("selected","select","unselect"),o("selectable","selectify","unselectify"),o("locked","lock","unlock"),o("grabbable","grabify","ungrabify"),null!=e.classes&&t.classes(e.classes),r.endBatch(),this}if(void 0===e){var s={data:n.copy(a.data),position:n.copy(a.position),group:a.group,removed:a.removed,selected:a.selected,selectable:a.selectable,locked:a.locked,grabbable:a.grabbable,classes:null};return s.classes=Object.keys(a.classes).filter(function(e){return a.classes[e]}).join(" "),s}}},l.jsons=function(){for(var e=[],t=0;t<this.length;t++){var r=this[t],n=r.json();e.push(n)}return e},l.clone=function(){for(var e=this.cy(),t=[],r=0;r<this.length;r++){var n=this[r],i=n.json(),o=new a(e,i,!1);t.push(o)}return new s(e,t)},l.copy=l.clone,l.restore=function(e){var t=this,r=t.cy(),a=r._private;void 0===e&&(e=!0);for(var l,u=[],c=[],d=0,h=t.length;h>d;d++){var p=t[d];p.removed()&&(p.isNode()?u.push(p):c.push(p))}l=u.concat(c);var d,f=function(){l.splice(d,1),d--};for(d=0;d<l.length;d++){var p=l[d],v=p._private,g=v.data;if(v.traversalCache=null,void 0===g.id)g.id=o.generate(r,p);else if(i.number(g.id))g.id=""+g.id;else{if(i.emptyString(g.id)||!i.string(g.id)){n.error("Can not create element with invalid string ID `"+g.id+"`"),f();continue}if(r.hasElementWithId(g.id)){n.error("Can not create second element with ID `"+g.id+"`"),f();continue}}var y=g.id;if(p.isNode()){var m=p,b=v.position;null==b.x&&(b.x=0),null==b.y&&(b.y=0)}if(p.isEdge()){for(var x=p,w=["source","target"],E=w.length,_=!1,P=0;E>P;P++){var S=w[P],k=g[S];i.number(k)&&(k=g[S]=""+g[S]),null==k||""===k?(n.error("Can not create edge `"+y+"` with unspecified "+S),_=!0):r.hasElementWithId(k)||(n.error("Can not create edge `"+y+"` with nonexistant "+S+" `"+k+"`"),_=!0)}if(_){f();continue}var T=r.getElementById(g.source),D=r.getElementById(g.target);T._private.edges.push(x),D._private.edges.push(x),x._private.source=T,x._private.target=D}v.ids={},v.ids[y]=p,v.indexes={},v.indexes[y]=p,v.removed=!1,r.addToPool(p)}for(var d=0;d<u.length;d++){var m=u[d],g=m._private.data;i.number(g.parent)&&(g.parent=""+g.parent);var C=g.parent,M=null!=C;if(M){var N=r.getElementById(C);if(N.empty())g.parent=void 0;else{for(var B=!1,z=N;!z.empty();){if(m.same(z)){B=!0,g.parent=void 0;break}z=z.parent()}B||(N[0]._private.children.push(m),m._private.parent=N[0],a.hasCompoundNodes=!0)}}}if(l.length>0){for(var I=new s(r,l),d=0;d<I.length;d++){var p=I[d];if(!p.isNode()){for(var L=p.parallelEdges(),P=0;P<L.length;P++)L[P]._private.traversalCache=null;p.source()[0]._private.traversalCache=null,p.target()[0]._private.traversalCache=null}}var O;O=a.hasCompoundNodes?I.add(I.connectedNodes()).add(I.parent()):I,O.updateStyle(e),e?I.rtrigger("add"):I.trigger("add")}return t},l.removed=function(){var e=this[0];return e&&e._private.removed},l.inside=function(){var e=this[0];return e&&!e._private.removed},l.remove=function(e){function t(e){for(var t=e._private.edges,r=0;r<t.length;r++)i(t[r])}function r(e){for(var t=e._private.children,r=0;r<t.length;r++)i(t[r])}function i(e){var n=h[e.id()];n||(h[e.id()]=!0,e.isNode()?(d.push(e),t(e),r(e)):d.unshift(e))}function a(e,t){var r=e._private.edges;n.removeFromArray(r,t),e._private.traversalCache=null}function o(e){for(var t=e.parallelEdges(),r=0;r<t.length;r++)t[r]._private.traversalCache=null}function l(e,t){t=t[0],e=e[0];var r=e._private.children,i=e.id();n.removeFromArray(r,t),y.ids[i]||(y.ids[i]=!0,y.push(e))}var u=this,c=[],d=[],h={},p=u._private.cy;void 0===e&&(e=!0);for(var f=0,v=u.length;v>f;f++){var g=u[f];i(g)}var y=[];y.ids={},p.removeFromPool(d);for(var f=0;f<d.length;f++){var g=d[f];if(g._private.removed=!0,c.push(g),g.isEdge()){var m=g.source()[0],b=g.target()[0];a(m,g),a(b,g),o(g)}else{var x=g.parent();0!==x.length&&l(x,g)}}var w=p._private.elements;p._private.hasCompoundNodes=!1;for(var f=0;f<w.length;f++){var g=w[f];if(g.isParent()){p._private.hasCompoundNodes=!0;break}}var E=new s(this.cy(),c);E.size()>0&&(e&&this.cy().notify({type:"remove",eles:E}),E.trigger("remove"));for(var f=0;f<y.length;f++){var g=y[f];g.removed()||g.updateStyle()}return new s(p,c)},l.move=function(e){var t=this._private.cy;if(void 0!==e.source||void 0!==e.target){var r=e.source,n=e.target,i=t.hasElementWithId(r),a=t.hasElementWithId(n);if(i||a){var o=this.jsons();this.remove();for(var s=0;s<o.length;s++){var l=o[s],u=this[s];"edges"===l.group&&(i&&(l.data.source=r),a&&(l.data.target=n),l.scratch=u._private.scratch)}return t.add(o)}}else if(void 0!==e.parent){var c=e.parent,d=null===c||t.hasElementWithId(c);if(d){var o=this.jsons(),h=this.descendants(),p=h.union(h.union(this).connectedEdges());this.remove();for(var s=0;s<this.length;s++){var l=o[s],u=this[s];"nodes"===l.group&&(l.data.parent=null===c?void 0:c,l.scratch=u._private.scratch)}return t.add(o).union(p.restore())}}return this},[e("./algorithms"),e("./animation"),e("./class"),e("./comparators"),e("./compounds"),e("./data"),e("./degree"),e("./dimensions"),e("./events"),e("./filter"),e("./group"),e("./index"),e("./iteration"),e("./layout"),e("./style"),e("./switch-functions"),e("./traversing")].forEach(function(e){n.extend(l,e)}),t.exports=s},{"../is":83,"../util":100,"./algorithms":11,"./animation":15,"./class":16,"./comparators":17,"./compounds":18,"./data":19,"./degree":20,"./dimensions":21,"./element":22,"./events":23,"./filter":24,"./group":25,"./index":26,"./iteration":27,"./layout":28,"./style":29,"./switch-functions":30,"./traversing":31}],27:[function(e,t,r){"use strict";var n=e("../is"),i=e("./zsort"),a={each:function(e){if(n.fn(e))for(var t=0;t<this.length;t++){var r=this[t],i=e.apply(r,[t,r]);if(i===!1)break}return this},forEach:function(e,t){if(n.fn(e))for(var r=0;r<this.length;r++){var i=this[r],a=t?e.apply(t,[i,r,this]):e(i,r,this);if(a===!1)break}return this},toArray:function(){for(var e=[],t=0;t<this.length;t++)e.push(this[t]);return e},slice:function(e,t){var r=[],n=this.length;null==t&&(t=n),null==e&&(e=0),0>e&&(e=n+e),0>t&&(t=n+t);for(var i=e;i>=0&&t>i&&n>i;i++)r.push(this[i]);return this.spawn(r)},size:function(){return this.length},eq:function(e){return this[e]||this.spawn()},first:function(){return this[0]||this.spawn()},last:function(){return this[this.length-1]||this.spawn()},empty:function(){return 0===this.length},nonempty:function(){return!this.empty()},sort:function(e){if(!n.fn(e))return this;var t=this.toArray().sort(e);return this.spawn(t)},sortByZIndex:function(){return this.sort(i)},zDepth:function(){var e=this[0];if(e){var t=e._private,r=t.group;if("nodes"===r){var n=t.data.parent?e.parents().size():0;return e.isParent()?n:Number.MAX_VALUE}var i=t.source,a=t.target,o=i.zDepth(),s=a.zDepth();return Math.max(o,s,0)}}};t.exports=a},{"../is":83,"./zsort":32}],28:[function(e,t,r){"use strict";var n=e("../is"),i=e("../util"),a=e("../promise"),o={layoutPositions:function(e,t,r){var i=this.nodes(),o=this.cy();if(e.trigger({type:"layoutstart",layout:e}),e.animations=[],t.animate){for(var s=0;s<i.length;s++){var l=i[s],u=r.call(l,s,l),c=l.position();n.number(c.x)&&n.number(c.y)||l.silentPosition({x:0,y:0});var d=l.animation({position:u,duration:t.animationDuration,easing:t.animationEasing});e.animations.push(d),d.play()}var h;o.on("step.*",h=function(){t.fit&&o.fit(t.eles,t.padding)}),e.one("layoutstop",function(){o.off("step.*",h)}),e.one("layoutready",t.ready),e.trigger({type:"layoutready",layout:e}),a.all(e.animations.map(function(e){return e.promise()})).then(function(){o.off("step.*",h),null!=t.zoom&&o.zoom(t.zoom),t.pan&&o.pan(t.pan),t.fit&&o.fit(t.eles,t.padding),e.one("layoutstop",t.stop),e.trigger({type:"layoutstop",layout:e})})}else i.positions(r),t.fit&&o.fit(t.eles,t.padding),null!=t.zoom&&o.zoom(t.zoom),t.pan&&o.pan(t.pan),e.one("layoutready",t.ready),e.trigger({type:"layoutready",layout:e}),e.one("layoutstop",t.stop),e.trigger({type:"layoutstop",layout:e});return this},layout:function(e){var t=this.cy();return t.layout(i.extend({},e,{eles:this})),this},makeLayout:function(e){var t=this.cy();return t.makeLayout(i.extend({},e,{eles:this}))}};o.createLayout=o.makeLayout,t.exports=o},{"../is":83,"../promise":86,"../util":100}],29:[function(e,t,r){"use strict";var n=e("../is"),i={updateStyle:function(e){var t=this._private.cy;if(!t.styleEnabled())return this;if(t._private.batchingStyle){var r=t._private.batchStyleEles;return r.merge(this),this}var n=t.style();e=!(!e&&void 0!==e),n.apply(this);var i=this.updateCompoundBounds(),a=i.length>0?this.add(i):this;return e?a.rtrigger("style"):a.trigger("style"),this},updateMappers:function(e){var t=this._private.cy,r=t.style();if(e=!(!e&&void 0!==e),!t.styleEnabled())return this;r.updateMappers(this);var n=this.updateCompoundBounds(),i=n.length>0?this.add(n):this;return e?i.rtrigger("style"):i.trigger("style"),this},parsedStyle:function(e){var t=this[0];if(t.cy().styleEnabled())return t?t._private.style[e]||t.cy().style().getDefaultProperty(e):void 0},renderedStyle:function(e){var t=this.cy();if(!t.styleEnabled())return this;var r=this[0];if(r){var n=r.cy().style().getRenderedStyle(r);return void 0===e?n:n[e]}},style:function(e,t){var r=this.cy();if(!r.styleEnabled())return this;var i=!1,a=r.style();if(n.plainObject(e)){var o=e;a.applyBypass(this,o,i);var s=this.updateCompoundBounds(),l=s.length>0?this.add(s):this;l.rtrigger("style")}else if(n.string(e)){if(void 0===t){var u=this[0];return u?a.getStylePropertyValue(u,e):void 0}a.applyBypass(this,e,t,i);var s=this.updateCompoundBounds(),l=s.length>0?this.add(s):this;l.rtrigger("style")}else if(void 0===e){var u=this[0];return u?a.getRawStyle(u):void 0}return this},removeStyle:function(e){var t=this.cy();if(!t.styleEnabled())return this;var r=!1,n=t.style(),i=this;if(void 0===e)for(var a=0;a<i.length;a++){var o=i[a];n.removeAllBypasses(o,r)}else{e=e.split(/\s+/);for(var a=0;a<i.length;a++){var o=i[a];n.removeBypasses(o,e,r)}}var s=this.updateCompoundBounds(),l=s.length>0?this.add(s):this;return l.rtrigger("style"),this},show:function(){return this.css("display","element"),this},hide:function(){return this.css("display","none"),this},visible:function(){var e=this.cy();if(!e.styleEnabled())return!0;var t=this[0],r=e.hasCompoundNodes();if(t){if("visible"!==t.pstyle("visibility").value||"element"!==t.pstyle("display").value)return!1;if("nodes"===t._private.group){if(!r)return!0;var n=t._private.data.parent?t.parents():null;if(n)for(var i=0;i<n.length;i++){var a=n[i],o=a.pstyle("visibility").value,s=a.pstyle("display").value;if("visible"!==o||"element"!==s)return!1}return!0}var l=t._private.source,u=t._private.target;return l.visible()&&u.visible()}},hidden:function(){var e=this[0];return e?!e.visible():void 0},effectiveOpacity:function(){var e=this.cy();if(!e.styleEnabled())return 1;var t=e.hasCompoundNodes(),r=this[0];if(r){var n=r._private,i=r.pstyle("opacity").value;if(!t)return i;var a=n.data.parent?r.parents():null;if(a)for(var o=0;o<a.length;o++){var s=a[o],l=s.pstyle("opacity").value;i=l*i}return i}},transparent:function(){var e=this.cy();if(!e.styleEnabled())return!1;var t=this[0],r=t.cy().hasCompoundNodes();return t?r?0===t.effectiveOpacity():0===t.pstyle("opacity").value:void 0},backgrounding:function(){var e=this.cy();if(!e.styleEnabled())return!1;var t=this[0];return!!t._private.backgrounding}};i.bypass=i.css=i.style,i.renderedCss=i.renderedStyle,i.removeBypass=i.removeCss=i.removeStyle,i.pstyle=i.parsedStyle,t.exports=i},{"../is":83}],30:[function(e,t,r){"use strict";function n(e){return function(){var t=arguments,r=[];if(2===t.length){var n=t[0],i=t[1];this.on(e.event,n,i)}else if(1===t.length){var i=t[0];this.on(e.event,i)}else if(0===t.length){for(var a=0;a<this.length;a++){var o=this[a],s=!e.ableField||o._private[e.ableField],l=o._private[e.field]!=e.value;if(e.overrideAble){var u=e.overrideAble(o);if(void 0!==u&&(s=u,!u))return this}s&&(o._private[e.field]=e.value,l&&r.push(o))}var c=this.spawn(r);c.updateStyle(),c.trigger(e.event)}return this}}function i(e){a[e.field]=function(){var t=this[0];if(t){if(e.overrideField){var r=e.overrideField(t);if(void 0!==r)return r}return t._private[e.field]}},a[e.on]=n({event:e.on,field:e.field,ableField:e.ableField,overrideAble:e.overrideAble,value:!0}),a[e.off]=n({event:e.off,field:e.field,ableField:e.ableField,overrideAble:e.overrideAble,value:!1})}var a={};i({field:"locked",overrideField:function(e){return e.cy().autolock()?!0:void 0},on:"lock",off:"unlock"}),i({field:"grabbable",overrideField:function(e){return e.cy().autoungrabify()?!1:void 0},on:"grabify",off:"ungrabify"}),i({field:"selected",ableField:"selectable",overrideAble:function(e){return e.cy().autounselectify()?!1:void 0},on:"select",off:"unselect"}),i({field:"selectable",overrideField:function(e){return e.cy().autounselectify()?!1:void 0},on:"selectify",off:"unselectify"}),a.deselect=a.unselect,a.grabbed=function(){var e=this[0];return e?e._private.grabbed:void 0},i({field:"active",on:"activate",off:"unactivate"}),a.inactive=function(){var e=this[0];return e?!e._private.active:void 0},t.exports=a},{}],31:[function(e,t,r){"use strict";function n(e){return function(t){for(var r=[],n=0;n<this.length;n++){var i=this[n],a=i._private[e.attr];a&&r.push(a)}return this.spawn(r,{unique:!0}).filter(t)}}function i(e){return function(t){var r=[],n=this._private.cy,i=e||{};s.string(t)&&(t=n.$(t));for(var a=this._private.ids,o=t._private.ids,l=0;l<t.length;l++)for(var u=t[l]._private.edges,c=0;c<u.length;c++){var d=u[c],h=d._private.data,p=a[h.source]&&o[h.target],f=o[h.source]&&a[h.target],v=p||f;if(v){if(i.thisIsSrc||i.thisIsTgt){if(i.thisIsSrc&&!p)continue;if(i.thisIsTgt&&!f)continue}r.push(d)}}return this.spawn(r,{unique:!0})}}function a(e){var t={codirected:!1};return e=o.extend({},t,e),function(t){for(var r=[],n=this.edges(),i=e,a=0;a<n.length;a++)for(var o=n[a],s=o._private,l=s.source,u=l._private.data.id,c=s.data.target,d=l._private.edges,h=0;h<d.length;h++){var p=d[h],f=p._private.data,v=f.target,g=f.source,y=v===c&&g===u,m=u===v&&c===g;(i.codirected&&y||!i.codirected&&(y||m))&&r.push(p)}return this.spawn(r,{unique:!0}).filter(t)}}var o=e("../util"),s=e("../is"),l={},u=function(e,t){return function(r,n,i,a){var o,l=r,u=this;if(null==l?o="null":s.elementOrCollection(l)&&1===l.length&&(o="#"+l.id()),1===u.length&&o){var c=u[0]._private,d=c.traversalCache=c.traversalCache||{},h=d[t]=d[t]||{},p=h[o];return p?p:h[o]=e.call(u,r,n,i,a)}return e.call(u,r,n,i,a)}},c=function(e){return function(t){for(var r=this,n=[],i=0;i<r.length;i++){var a=r[i];if(a.isNode()){for(var o=!1,s=a.connectedEdges(),l=0;l<s.length;l++){var u=s[l],c=u.source(),d=u.target();if(e.noIncomingEdges&&d===a&&c!==a||e.noOutgoingEdges&&c===a&&d!==a){o=!0;break}}o||n.push(a)}}return this.spawn(n,{unique:!0}).filter(t)}},d=function(e){return function(t){for(var r=this,n=[],i=0;i<r.length;i++){var a=r[i];if(a.isNode())for(var o=a.connectedEdges(),s=0;s<o.length;s++){var l=o[s],u=l.source(),c=l.target();e.outgoing&&u===a?(n.push(l),n.push(c)):e.incoming&&c===a&&(n.push(l),n.push(u))}}return this.spawn(n,{unique:!0}).filter(t)}},h=function(e){return function(t){for(var r=this,n=[],i={};;){var a=e.outgoing?r.outgoers():r.incomers();if(0===a.length)break;for(var o=!1,s=0;s<a.length;s++){var l=a[s],u=l.id();i[u]||(i[u]=!0,n.push(l),o=!0)}if(!o)break;r=a}return this.spawn(n,{unique:!0}).filter(t)}};o.extend(l,{roots:c({noIncomingEdges:!0}),leaves:c({noOutgoingEdges:!0}),outgoers:u(d({outgoing:!0}),"outgoers"),successors:h({outgoing:!0}),incomers:u(d({incoming:!0}),"incomers"),predecessors:h({incoming:!0})}),o.extend(l,{neighborhood:u(function(e){for(var t=[],r=this.nodes(),n=0;n<r.length;n++)for(var i=r[n],a=i.connectedEdges(),o=0;o<a.length;o++){var s=a[o],l=s.source(),u=s.target(),c=i===l?u:l;c.length>0&&t.push(c[0]),t.push(s[0])}return this.spawn(t,{unique:!0}).filter(e)},"neighborhood"),closedNeighborhood:function(e){return this.neighborhood().add(this).filter(e)},openNeighborhood:function(e){return this.neighborhood(e)}}),l.neighbourhood=l.neighborhood,l.closedNeighbourhood=l.closedNeighborhood,l.openNeighbourhood=l.openNeighborhood,o.extend(l,{source:u(function(e){var t,r=this[0];return r&&(t=r._private.source||r.cy().collection()),t&&e?t.filter(e):t},"source"),target:u(function(e){var t,r=this[0];return r&&(t=r._private.target||r.cy().collection()),t&&e?t.filter(e):t},"target"),sources:n({attr:"source"}),targets:n({attr:"target"})}),o.extend(l,{edgesWith:u(i(),"edgesWith",!0),edgesTo:u(i({thisIsSrc:!0}),"edgesTo",!0)}),o.extend(l,{connectedEdges:u(function(e){for(var t=[],r=this,n=0;n<r.length;n++){var i=r[n];if(i.isNode())for(var a=i._private.edges,o=0;o<a.length;o++){var s=a[o];t.push(s)}}return this.spawn(t,{unique:!0}).filter(e)},"connectedEdges"),connectedNodes:u(function(e){for(var t=[],r=this,n=0;n<r.length;n++){var i=r[n];i.isEdge()&&(t.push(i.source()[0]),t.push(i.target()[0]))}return this.spawn(t,{unique:!0}).filter(e)},"connectedNodes"),parallelEdges:u(a(),"parallelEdges"),codirectedEdges:u(a({codirected:!0}),"codirectedEdges")}),o.extend(l,{components:function(){var e=this,t=e.cy(),r=e.spawn(),n=e.nodes().spawnSelf(),i=[],a=function(e,t){r.merge(e),n.unmerge(e),t.merge(e)};if(n.empty())return e.spawn();do{var o=t.collection();i.push(o);var s=n[0];a(s,o),e.bfs({directed:!1,roots:s,visit:function(e,t,r,n,i){a(r,o)}})}while(n.length>0);return i.map(function(e){var t=e.connectedEdges().stdFilter(function(t){return e.anySame(t.source())&&e.anySame(t.target())});return e.union(t)})}}),t.exports=l},{"../is":83,"../util":100}],32:[function(e,t,r){"use strict";var n=function(e,t){var r=e.cy(),n=e.pstyle("z-index").value-t.pstyle("z-index").value,i=0,a=0,o=r.hasCompoundNodes(),s=e.isNode(),l=!s,u=t.isNode(),c=!u;o&&(i=e.zDepth(),a=t.zDepth());var d=i-a,h=0===d;return h?s&&c?1:l&&u?-1:0===n?e.poolIndex()-t.poolIndex():n:d};t.exports=n},{}],33:[function(e,t,r){"use strict";var n=e("../is"),i=e("../util"),a=e("../collection"),o=e("../collection/element"),s={add:function(e){var t,r=this;if(n.elementOrCollection(e)){var s=e;if(s._private.cy===r)t=s.restore();else{for(var l=[],u=0;u<s.length;u++){var c=s[u];l.push(c.json())}t=new a(r,l)}}else if(n.array(e)){var l=e;t=new a(r,l)}else if(n.plainObject(e)&&(n.array(e.nodes)||n.array(e.edges))){for(var d=e,l=[],h=["nodes","edges"],u=0,p=h.length;p>u;u++){var f=h[u],v=d[f];if(n.array(v))for(var g=0,y=v.length;y>g;g++){var m=i.extend({group:f},v[g]);l.push(m)}}t=new a(r,l)}else{var m=e;t=new o(r,m).collection()}return t},remove:function(e){if(n.elementOrCollection(e));else if(n.string(e)){var t=e;e=this.$(t)}return e.remove()},load:function(e,t,r){var a=this;a.notifications(!1);var o=a.mutableElements();o.length>0&&o.remove(),null!=e&&(n.plainObject(e)||n.array(e))&&a.add(e),a.one("layoutready",function(e){a.notifications(!0),a.trigger(e),a.notify({type:"load",eles:a.mutableElements()}),a.one("load",t),a.trigger("load")}).one("layoutstop",function(){a.one("done",r),a.trigger("done")});var s=i.extend({},a._private.options.layout);return s.eles=a.elements(),a.layout(s),this}};t.exports=s},{"../collection":26,"../collection/element":22,"../is":83,"../util":100}],34:[function(e,t,r){"use strict";var n=e("../define"),i=e("../util"),a=e("../is"),o={animate:n.animate(),animation:n.animation(),animated:n.animated(),clearQueue:n.clearQueue(),delay:n.delay(),delayAnimation:n.delayAnimation(),stop:n.stop(),addToAnimationPool:function(e){var t=this;t.styleEnabled()&&t._private.aniEles.merge(e)},stopAnimationLoop:function(){this._private.animationsRunning=!1},startAnimationLoop:function(){function e(){c._private.animationsRunning&&i.requestAnimationFrame(function(r){t(r),e()})}function t(e){function t(t,i){var s=t._private,l=s.animation.current,u=s.animation.queue,c=!1;if(0===l.length){var d=u.shift();d&&l.push(d)}for(var h=function(e){for(var t=e.length-1;t>=0;t--){var r=e[t];r()}e.splice(0,e.length)},p=l.length-1;p>=0;p--){var f=l[p],v=f._private;v.stopped?(l.splice(p,1),v.hooked=!1,v.playing=!1,v.started=!1,h(v.frames)):(v.playing||v.applying)&&(v.playing&&v.applying&&(v.applying=!1),v.started||r(t,f,e),n(t,f,e,i),a.fn(v.step)&&v.step.call(t,e),v.applying&&(v.applying=!1),h(v.frames),f.completed()&&(l.splice(p,1),v.hooked=!1,v.playing=!1,v.started=!1,h(v.completes)),c=!0)}return i||0!==l.length||0!==u.length||o.push(t),c}for(var i=c._private.aniEles,o=[],s=!1,l=0;l<i.length;l++){var u=i[l],d=t(u);s=s||d}var h=t(c,!0);if(s||h)if(i.length>0){var p=i.updateCompoundBounds().spawnSelf().merge(i);c.notify({type:"draw",eles:p})}else c.notify({type:"draw"});i.unmerge(o),c.trigger("step")}function r(e,t,r){var n=a.core(e),i=!n,o=e,s=c._private.style,l=t._private;if(i){var u=o._private.position;l.startPosition=l.startPosition||{x:u.x,y:u.y},l.startStyle=l.startStyle||s.getAnimationStartStyle(o,l.style)}if(n){var d=c._private.pan;l.startPan=l.startPan||{x:d.x,y:d.y},l.startZoom=null!=l.startZoom?l.startZoom:c._private.zoom}l.started=!0,l.startTime=r-l.progress*l.duration}function n(e,t,r,n){var i=c._private.style,s=!n,l=e._private,d=t._private,h=d.easing,f=d.startTime;if(!d.easingImpl)if(null==h)d.easingImpl=p.linear;else{var v;if(a.string(h)){var g=i.parse("transition-timing-function",h);v=g.value}else v=h;var y,m;a.string(v)?(y=v,m=[]):(y=v[1],m=v.slice(2).map(function(e){return+e})),m.length>0?("spring"===y&&m.push(d.duration),d.easingImpl=p[y].apply(null,m)):d.easingImpl=p[y]}var b,x=d.easingImpl;if(b=0===d.duration?1:(r-f)/d.duration,d.applying&&(b=d.progress),0>b?b=0:b>1&&(b=1),null==d.delay){var w=d.startPosition,E=d.position,_=l.position;E&&s&&(o(w.x,E.x)&&(_.x=u(w.x,E.x,b,x)),o(w.y,E.y)&&(_.y=u(w.y,E.y,b,x)),e.trigger("position"));var P=d.startPan,S=d.pan,k=l.pan,T=null!=S&&n;T&&(o(P.x,S.x)&&(k.x=u(P.x,S.x,b,x)),o(P.y,S.y)&&(k.y=u(P.y,S.y,b,x)),e.trigger("pan"));var D=d.startZoom,C=d.zoom,M=null!=C&&n;M&&(o(D,C)&&(l.zoom=u(D,C,b,x)),e.trigger("zoom")),(T||M)&&e.trigger("viewport");var N=d.style;if(N&&N.length>0&&s){for(var B=0;B<N.length;B++){var z=N[B],y=z.name,I=z,L=d.startStyle[y],O=u(L,I,b,x);i.overrideBypass(e,y,O)}e.trigger("style")}}return d.progress=b,b}function o(e,t){return null==e||null==t?!1:a.number(e)&&a.number(t)?!0:!(!e||!t)}function s(e,t,r){var n=1-r,i=r*r;return 3*n*n*r*e+3*n*i*t+i*r}function l(e,t){return function(r,n,i){return r+(n-r)*s(e,t,i)}}function u(e,t,r,n){0>r?r=0:r>1&&(r=1);var i,o;if(i=null!=e.pfValue||null!=e.value?null!=e.pfValue?e.pfValue:e.value:e,o=null!=t.pfValue||null!=t.value?null!=t.pfValue?t.pfValue:t.value:t,a.number(i)&&a.number(o))return n(i,o,r);if(a.array(i)&&a.array(o)){for(var s=[],l=0;l<o.length;l++){var u=i[l],c=o[l];if(null!=u&&null!=c){var d=n(u,c,r);e.roundValue&&(d=Math.round(d)),s.push(d)}else s.push(c)}return s}}var c=this;if(c._private.animationsRunning=!0,c.styleEnabled()){var d=c.renderer();d&&d.beforeRender?d.beforeRender(function(e,r){t(r)},d.beforeRenderPriorities.animations):e();/*! Runge-Kutta spring physics function generator. Adapted from Framer.js, copyright Koen Bok. MIT License: http://en.wikipedia.org/wiki/MIT_License */ +/* Given a tension, friction, and duration, a simulation at 60FPS will first run without a defined duration in order to calculate the full path. A second pass + then adjusts the time delta -- using the relation between actual time and duration -- to calculate the path for the duration-constrained animation. */ +var h=function(){function e(e){return-e.tension*e.x-e.friction*e.v}function t(t,r,n){var i={x:t.x+n.dx*r,v:t.v+n.dv*r,tension:t.tension,friction:t.friction};return{dx:i.v,dv:e(i)}}function r(r,n){var i={dx:r.v,dv:e(r)},a=t(r,.5*n,i),o=t(r,.5*n,a),s=t(r,n,o),l=1/6*(i.dx+2*(a.dx+o.dx)+s.dx),u=1/6*(i.dv+2*(a.dv+o.dv)+s.dv);return r.x=r.x+l*n,r.v=r.v+u*n,r}return function n(e,t,i){var a,o,s,l={x:-1,v:0,tension:null,friction:null},u=[0],c=0,d=1e-4,h=.016;for(e=parseFloat(e)||500,t=parseFloat(t)||20,i=i||null,l.tension=e,l.friction=t,a=null!==i,a?(c=n(e,t),o=c/i*h):o=h;;)if(s=r(s||l,o),u.push(1+s.x),c+=16,!(Math.abs(s.x)>d&&Math.abs(s.v)>d))break;return a?function(e){return u[e*(u.length-1)|0]}:c}}(),p={linear:function(e,t,r){return e+(t-e)*r},ease:l(.25,.1,.25,1),"ease-in":l(.42,0,1,1),"ease-out":l(0,0,.58,1),"ease-in-out":l(.42,0,.58,1),"ease-in-sine":l(.47,0,.745,.715),"ease-out-sine":l(.39,.575,.565,1),"ease-in-out-sine":l(.445,.05,.55,.95),"ease-in-quad":l(.55,.085,.68,.53),"ease-out-quad":l(.25,.46,.45,.94),"ease-in-out-quad":l(.455,.03,.515,.955),"ease-in-cubic":l(.55,.055,.675,.19),"ease-out-cubic":l(.215,.61,.355,1),"ease-in-out-cubic":l(.645,.045,.355,1),"ease-in-quart":l(.895,.03,.685,.22),"ease-out-quart":l(.165,.84,.44,1),"ease-in-out-quart":l(.77,0,.175,1),"ease-in-quint":l(.755,.05,.855,.06),"ease-out-quint":l(.23,1,.32,1),"ease-in-out-quint":l(.86,0,.07,1),"ease-in-expo":l(.95,.05,.795,.035),"ease-out-expo":l(.19,1,.22,1),"ease-in-out-expo":l(1,0,0,1),"ease-in-circ":l(.6,.04,.98,.335),"ease-out-circ":l(.075,.82,.165,1),"ease-in-out-circ":l(.785,.135,.15,.86),spring:function(e,t,r){if(0===r)return p.linear;var n=h(e,t,r);return function(e,t,r){return e+(t-e)*n(r)}},"cubic-bezier":function(e,t,r,n){return l(e,t,r,n)}}}}};t.exports=o},{"../define":44,"../is":83,"../util":100}],35:[function(e,t,r){"use strict";var n=e("../define"),i={on:n.on(),one:n.on({unbindSelfOnTrigger:!0}),once:n.on({unbindAllBindersOnTrigger:!0}),off:n.off(),trigger:n.trigger()};n.eventAliasesOn(i),t.exports=i},{"../define":44}],36:[function(e,t,r){"use strict";var n={png:function(e){var t=this._private.renderer;return e=e||{},t.png(e)},jpg:function(e){var t=this._private.renderer;return e=e||{},e.bg=e.bg||"#fff",t.jpg(e)}};n.jpeg=n.jpg,t.exports=n},{}],37:[function(e,t,r){"use strict";var n=e("../window"),i=e("../util"),a=e("../collection"),o=e("../is"),s=e("../promise"),l=e("../define"),u=function(e){var t=this;e=i.extend({},e);var r=e.container;r&&!o.htmlElement(r)&&o.htmlElement(r[0])&&(r=r[0]);var l=r?r._cyreg:null;l=l||{},l&&l.cy&&(l.cy.destroy(),l={});var u=l.readies=l.readies||[];r&&(r._cyreg=l),l.cy=t;var c=void 0!==n&&void 0!==r&&!e.headless,d=e;d.layout=i.extend({name:c?"grid":"null"},d.layout),d.renderer=i.extend({name:c?"canvas":"null"},d.renderer);var h=function(e,t,r){return void 0!==t?t:void 0!==r?r:e},p=this._private={container:r,ready:!1,initrender:!1,options:d,elements:new a(this),listeners:[],aniEles:new a(this),scratch:{},layout:null,renderer:null,notificationsEnabled:!0,minZoom:1e-50,maxZoom:1e50,zoomingEnabled:h(!0,d.zoomingEnabled),userZoomingEnabled:h(!0,d.userZoomingEnabled),panningEnabled:h(!0,d.panningEnabled),userPanningEnabled:h(!0,d.userPanningEnabled),boxSelectionEnabled:h(!0,d.boxSelectionEnabled),autolock:h(!1,d.autolock,d.autolockNodes),autoungrabify:h(!1,d.autoungrabify,d.autoungrabifyNodes),autounselectify:h(!1,d.autounselectify),styleEnabled:void 0===d.styleEnabled?c:d.styleEnabled,zoom:o.number(d.zoom)?d.zoom:1,pan:{x:o.plainObject(d.pan)&&o.number(d.pan.x)?d.pan.x:0,y:o.plainObject(d.pan)&&o.number(d.pan.y)?d.pan.y:0},animation:{current:[],queue:[]},hasCompoundNodes:!1},f=d.selectionType;void 0===f||"additive"!==f&&"single"!==f?p.selectionType="single":p.selectionType=f,o.number(d.minZoom)&&o.number(d.maxZoom)&&d.minZoom<d.maxZoom?(p.minZoom=d.minZoom,p.maxZoom=d.maxZoom):o.number(d.minZoom)&&void 0===d.maxZoom?p.minZoom=d.minZoom:o.number(d.maxZoom)&&void 0===d.minZoom&&(p.maxZoom=d.maxZoom);var v=function(e,t){var r=e.some(o.promise);return r?s.all(e).then(t):void t(e)};t.initRenderer(i.extend({hideEdgesOnViewport:d.hideEdgesOnViewport,textureOnViewport:d.textureOnViewport,wheelSensitivity:o.number(d.wheelSensitivity)&&d.wheelSensitivity>0?d.wheelSensitivity:1,motionBlur:void 0===d.motionBlur?!1:d.motionBlur,motionBlurOpacity:void 0===d.motionBlurOpacity?.05:d.motionBlurOpacity,pixelRatio:o.number(d.pixelRatio)&&d.pixelRatio>0?d.pixelRatio:void 0,desktopTapThreshold:void 0===d.desktopTapThreshold?4:d.desktopTapThreshold,touchTapThreshold:void 0===d.touchTapThreshold?8:d.touchTapThreshold},d.renderer)),v([d.style,d.elements],function(e){var r=e[0],n=e[1];p.styleEnabled&&t.setStyle(r),d.initrender&&(t.on("initrender",d.initrender),t.on("initrender",function(){p.initrender=!0})),t.load(n,function(){t.startAnimationLoop(),p.ready=!0,o.fn(d.ready)&&t.on("ready",d.ready);for(var e=0;e<u.length;e++){var r=u[e];t.on("ready",r)}l&&(l.readies=[]),t.trigger("ready")},d.done)})},c=u.prototype;i.extend(c,{instanceString:function(){return"core"},isReady:function(){return this._private.ready},ready:function(e){return this.isReady()?this.trigger("ready",[],e):this.on("ready",e),this},initrender:function(){return this._private.initrender},destroy:function(){var e=this;return e.stopAnimationLoop(),e.destroyRenderer(),e},hasElementWithId:function(e){return this._private.elements.hasElementWithId(e)},getElementById:function(e){return this._private.elements.getElementById(e)},selectionType:function(){return this._private.selectionType},hasCompoundNodes:function(){return this._private.hasCompoundNodes},headless:function(){return"null"===this._private.options.renderer.name},styleEnabled:function(){return this._private.styleEnabled},addToPool:function(e){return this._private.elements.merge(e),this},removeFromPool:function(e){return this._private.elements.unmerge(e),this},container:function(){return this._private.container},options:function(){return i.copy(this._private.options)},json:function(e){var t=this,r=t._private,n=t.mutableElements();if(o.plainObject(e)){if(t.startBatch(),e.elements){var a={},s=function(e,r){for(var n=0;n<e.length;n++){var o=e[n],s=o.data.id,l=t.getElementById(s);a[s]=!0,0!==l.length?l.json(o):r?t.add(i.extend({group:r},o)):t.add(o)}};if(o.array(e.elements))s(e.elements);else for(var l=["nodes","edges"],u=0;u<l.length;u++){var c=l[u],d=e.elements[c];o.array(d)&&s(d,c)}n.stdFilter(function(e){return!a[e.id()]}).remove()}e.style&&t.style(e.style),null!=e.zoom&&e.zoom!==r.zoom&&t.zoom(e.zoom),e.pan&&(e.pan.x===r.pan.x&&e.pan.y===r.pan.y||t.pan(e.pan));for(var h=["minZoom","maxZoom","zoomingEnabled","userZoomingEnabled","panningEnabled","userPanningEnabled","boxSelectionEnabled","autolock","autoungrabify","autounselectify"],u=0;u<h.length;u++){var p=h[u];null!=e[p]&&t[p](e[p])}return t.endBatch(),this}if(void 0===e){var f={};return f.elements={},n.forEach(function(e){var t=e.group();f.elements[t]||(f.elements[t]=[]),f.elements[t].push(e.json())}),this._private.styleEnabled&&(f.style=t.style().json()),f.zoomingEnabled=t._private.zoomingEnabled,f.userZoomingEnabled=t._private.userZoomingEnabled,f.zoom=t._private.zoom,f.minZoom=t._private.minZoom,f.maxZoom=t._private.maxZoom,f.panningEnabled=t._private.panningEnabled,f.userPanningEnabled=t._private.userPanningEnabled,f.pan=i.copy(t._private.pan),f.boxSelectionEnabled=t._private.boxSelectionEnabled,f.renderer=i.copy(t._private.options.renderer),f.hideEdgesOnViewport=t._private.options.hideEdgesOnViewport,f.textureOnViewport=t._private.options.textureOnViewport,f.wheelSensitivity=t._private.options.wheelSensitivity,f.motionBlur=t._private.options.motionBlur,f}},scratch:l.data({field:"scratch",bindingEvent:"scratch",allowBinding:!0,allowSetting:!0,settingEvent:"scratch",settingTriggersEvent:!0,triggerFnName:"trigger",allowGetting:!0}),removeScratch:l.removeData({field:"scratch",event:"scratch",triggerFnName:"trigger",triggerEvent:!0})}),[e("./add-remove"),e("./animation"),e("./events"),e("./export"),e("./layout"),e("./notification"),e("./renderer"),e("./search"),e("./style"),e("./viewport")].forEach(function(e){i.extend(c,e)}),t.exports=u},{"../collection":26,"../define":44,"../is":83,"../promise":86,"../util":100,"../window":107,"./add-remove":33,"./animation":34,"./events":35,"./export":36,"./layout":38,"./notification":39,"./renderer":40,"./search":41,"./style":42,"./viewport":43}],38:[function(e,t,r){"use strict";var n=e("../util"),i=e("../is"),a={layout:function(e){var t=this._private.prevLayout=null==e?this._private.prevLayout:this.makeLayout(e);return t.run(),this},makeLayout:function(e){var t=this;if(null==e)return void n.error("Layout options must be specified to make a layout");if(null==e.name)return void n.error("A `name` must be specified to make a layout");var r=e.name,a=t.extension("layout",r);if(null==a)return void n.error("Can not apply layout: No such layout `"+r+"` found; did you include its JS file?");var o;o=i.string(e.eles)?t.$(e.eles):null!=e.eles?e.eles:t.$();var s=new a(n.extend({},e,{cy:t,eles:o}));return s}};a.createLayout=a.makeLayout,t.exports=a},{"../is":83,"../util":100}],39:[function(e,t,r){"use strict";var n={notify:function(e){var t=this._private;if(t.batchingNotify){var r=t.batchNotifyEles,n=t.batchNotifyTypes;return e.eles&&r.merge(e.eles),void(n.ids[e.type]||(n.push(e.type),n.ids[e.type]=!0))}if(t.notificationsEnabled){var i=this.renderer();i.notify(e)}},notifications:function(e){var t=this._private;return void 0===e?t.notificationsEnabled:void(t.notificationsEnabled=!!e)},noNotifications:function(e){this.notifications(!1),e(),this.notifications(!0)},startBatch:function(){var e=this._private;return null==e.batchCount&&(e.batchCount=0),0===e.batchCount&&(e.batchingStyle=e.batchingNotify=!0,e.batchStyleEles=this.collection(),e.batchNotifyEles=this.collection(),e.batchNotifyTypes=[],e.batchNotifyTypes.ids={}),e.batchCount++,this},endBatch:function(){var e=this._private;return e.batchCount--,0===e.batchCount&&(e.batchingStyle=!1,e.batchStyleEles.updateStyle(),e.batchingNotify=!1,this.notify({type:e.batchNotifyTypes,eles:e.batchNotifyEles})),this},batch:function(e){return this.startBatch(),e(),this.endBatch(),this},batchData:function(e){var t=this;return this.batch(function(){for(var r=Object.keys(e),n=0;n<r.length;n++){var i=r[n],a=e[i],o=t.getElementById(i);o.data(a)}})}};t.exports=n},{}],40:[function(e,t,r){"use strict";var n=e("../util"),i={renderTo:function(e,t,r,n){var i=this._private.renderer;return i.renderTo(e,t,r,n),this},renderer:function(){return this._private.renderer},forceRender:function(){return this.notify({type:"draw"}),this},resize:function(){return this.invalidateSize(),this.notify({type:"resize"}),this.trigger("resize"),this},initRenderer:function(e){var t=this,r=t.extension("renderer",e.name);if(null==r)return void n.error("Can not initialise: No such renderer `%s` found; did you include its JS file?",e.name);var i=n.extend({},e,{cy:t});t._private.renderer=new r(i)},destroyRenderer:function(){var e=this;e.notify({type:"destroy"});var t=e.container();if(t)for(t._cyreg=null;t.childNodes.length>0;)t.removeChild(t.childNodes[0]);e._private.renderer=null},onRender:function(e){return this.on("render",e)},offRender:function(e){return this.off("render",e)}};i.invalidateDimensions=i.resize,t.exports=i},{"../util":100}],41:[function(e,t,r){"use strict";var n=e("../is"),i=e("../collection"),a={collection:function(e,t){return n.string(e)?this.$(e):n.elementOrCollection(e)?e.collection():n.array(e)?new i(this,e,t):new i(this)},nodes:function(e){var t=this.$(function(){return this.isNode()});return e?t.filter(e):t},edges:function(e){var t=this.$(function(){return this.isEdge()});return e?t.filter(e):t},$:function(e){var t=this._private.elements;return e?t.filter(e):t.spawnSelf()},mutableElements:function(){return this._private.elements}};a.elements=a.filter=a.$,t.exports=a},{"../collection":26,"../is":83}],42:[function(e,t,r){"use strict";var n=e("../is"),i=e("../style"),a={style:function(e){if(e){var t=this.setStyle(e);t.update()}return this._private.style},setStyle:function(e){var t=this._private;return n.stylesheet(e)?t.style=e.generateStyle(this):n.array(e)?t.style=i.fromJson(this,e):n.string(e)?t.style=i.fromString(this,e):t.style=i(this),t.style}};t.exports=a},{"../is":83,"../style":92}],43:[function(e,t,r){"use strict";var n=e("../is"),i={autolock:function(e){return void 0===e?this._private.autolock:(this._private.autolock=!!e,this)},autoungrabify:function(e){return void 0===e?this._private.autoungrabify:(this._private.autoungrabify=!!e,this)},autounselectify:function(e){return void 0===e?this._private.autounselectify:(this._private.autounselectify=!!e,this)},panningEnabled:function(e){return void 0===e?this._private.panningEnabled:(this._private.panningEnabled=!!e,this)},userPanningEnabled:function(e){return void 0===e?this._private.userPanningEnabled:(this._private.userPanningEnabled=!!e,this)},zoomingEnabled:function(e){return void 0===e?this._private.zoomingEnabled:(this._private.zoomingEnabled=!!e,this)},userZoomingEnabled:function(e){return void 0===e?this._private.userZoomingEnabled:(this._private.userZoomingEnabled=!!e,this)},boxSelectionEnabled:function(e){return void 0===e?this._private.boxSelectionEnabled:(this._private.boxSelectionEnabled=!!e,this)},pan:function(){var e,t,r,i,a,o=arguments,s=this._private.pan;switch(o.length){case 0:return s;case 1:if(n.string(o[0]))return e=o[0],s[e];if(n.plainObject(o[0])){if(!this._private.panningEnabled)return this;r=o[0],i=r.x,a=r.y,n.number(i)&&(s.x=i),n.number(a)&&(s.y=a),this.trigger("pan viewport")}break;case 2:if(!this._private.panningEnabled)return this;e=o[0],t=o[1],"x"!==e&&"y"!==e||!n.number(t)||(s[e]=t),this.trigger("pan viewport")}return this.notify({type:"viewport"}),this},panBy:function(e){var t,r,i,a,o,s=arguments,l=this._private.pan;if(!this._private.panningEnabled)return this;switch(s.length){case 1:n.plainObject(s[0])&&(i=s[0],a=i.x,o=i.y,n.number(a)&&(l.x+=a),n.number(o)&&(l.y+=o),this.trigger("pan viewport"));break;case 2:t=s[0],r=s[1],"x"!==t&&"y"!==t||!n.number(r)||(l[t]+=r),this.trigger("pan viewport")}return this.notify({type:"viewport"}),this},fit:function(e,t){var r=this.getFitViewport(e,t);if(r){var n=this._private;n.zoom=r.zoom,n.pan=r.pan,this.trigger("pan zoom viewport"),this.notify({type:"viewport"})}return this},getFitViewport:function(e,t){if(n.number(e)&&void 0===t&&(t=e,e=void 0),this._private.panningEnabled&&this._private.zoomingEnabled){var r;if(n.string(e)){var i=e;e=this.$(i)}else if(n.boundingBox(e)){var a=e;r={x1:a.x1,y1:a.y1,x2:a.x2,y2:a.y2},r.w=r.x2-r.x1,r.h=r.y2-r.y1}else n.elementOrCollection(e)||(e=this.mutableElements());r=r||e.boundingBox();var o,s=this.width(),l=this.height();if(t=n.number(t)?t:0,!isNaN(s)&&!isNaN(l)&&s>0&&l>0&&!isNaN(r.w)&&!isNaN(r.h)&&r.w>0&&r.h>0){o=Math.min((s-2*t)/r.w,(l-2*t)/r.h),o=o>this._private.maxZoom?this._private.maxZoom:o,o=o<this._private.minZoom?this._private.minZoom:o;var u={x:(s-o*(r.x1+r.x2))/2,y:(l-o*(r.y1+r.y2))/2};return{zoom:o,pan:u}}}},minZoom:function(e){return void 0===e?this._private.minZoom:(n.number(e)&&(this._private.minZoom=e),this)},maxZoom:function(e){return void 0===e?this._private.maxZoom:(n.number(e)&&(this._private.maxZoom=e),this)},zoom:function(e){var t,r;if(void 0===e)return this._private.zoom;if(n.number(e))r=e;else if(n.plainObject(e)){if(r=e.level,e.position){var i=e.position,a=this._private.pan,o=this._private.zoom;t={x:i.x*o+a.x,y:i.y*o+a.y}}else e.renderedPosition&&(t=e.renderedPosition);if(t&&!this._private.panningEnabled)return this}if(!this._private.zoomingEnabled)return this;if(!n.number(r)||t&&(!n.number(t.x)||!n.number(t.y)))return this;if(r=r>this._private.maxZoom?this._private.maxZoom:r,r=r<this._private.minZoom?this._private.minZoom:r,t){var s=this._private.pan,l=this._private.zoom,u=r,c={x:-u/l*(t.x-s.x)+t.x,y:-u/l*(t.y-s.y)+t.y};this._private.zoom=r,this._private.pan=c;var d=s.x!==c.x||s.y!==c.y;this.trigger(" zoom "+(d?" pan ":"")+" viewport ")}else this._private.zoom=r,this.trigger("zoom viewport");return this.notify({type:"viewport"}),this},viewport:function(e){var t=this._private,r=!0,i=!0,a=[],o=!1,s=!1;if(!e)return this;if(n.number(e.zoom)||(r=!1),n.plainObject(e.pan)||(i=!1),!r&&!i)return this;if(r){var l=e.zoom;l<t.minZoom||l>t.maxZoom||!t.zoomingEnabled?o=!0:(t.zoom=l,a.push("zoom"))}if(i&&(!o||!e.cancelOnFailedZoom)&&t.panningEnabled){var u=e.pan;n.number(u.x)&&(t.pan.x=u.x,s=!1),n.number(u.y)&&(t.pan.y=u.y,s=!1),s||a.push("pan")}return a.length>0&&(a.push("viewport"),this.trigger(a.join(" ")),this.notify({type:"viewport"})),this},center:function(e){var t=this.getCenterPan(e);return t&&(this._private.pan=t,this.trigger("pan viewport"),this.notify({type:"viewport"})),this},getCenterPan:function(e,t){if(this._private.panningEnabled){if(n.string(e)){var r=e;e=this.mutableElements().filter(r)}else n.elementOrCollection(e)||(e=this.mutableElements());var i=e.boundingBox(),a=this.width(),o=this.height();t=void 0===t?this._private.zoom:t;var s={x:(a-t*(i.x1+i.x2))/2,y:(o-t*(i.y1+i.y2))/2};return s}},reset:function(){return this._private.panningEnabled&&this._private.zoomingEnabled?(this.viewport({pan:{x:0,y:0},zoom:1}),this):this},invalidateSize:function(){this._private.sizeCache=null},size:function(){var e=this._private,t=e.container;return e.sizeCache=e.sizeCache||(t?{width:t.clientWidth,height:t.clientHeight}:{width:1,height:1})},width:function(){return this.size().width},height:function(){return this.size().height},extent:function(){var e=this._private.pan,t=this._private.zoom,r=this.renderedExtent(),n={x1:(r.x1-e.x)/t,x2:(r.x2-e.x)/t,y1:(r.y1-e.y)/t,y2:(r.y2-e.y)/t};return n.w=n.x2-n.x1,n.h=n.y2-n.y1,n},renderedExtent:function(){var e=this.width(),t=this.height();return{x1:0,y1:0,x2:e,y2:t,w:e,h:t}}};i.centre=i.center,i.autolockNodes=i.autolock,i.autoungrabifyNodes=i.autoungrabify,t.exports=i},{"../is":83}],44:[function(e,t,r){"use strict";var n=e("./util"),i=e("./is"),a=e("./selector"),o=e("./promise"),s=e("./event"),l=e("./animation"),u={data:function(e){var t={field:"data",bindingEvent:"data",allowBinding:!1,allowSetting:!1,allowGetting:!1,settingEvent:"data",settingTriggersEvent:!1,triggerFnName:"trigger",immutableKeys:{},updateStyle:!1,onSet:function(e){},canSet:function(e){return!0}};return e=n.extend({},t,e),function(t,r){var n=e,a=this,o=void 0!==a.length,s=o?a:[a],l=o?a[0]:a;if(i.string(t)){if(n.allowGetting&&void 0===r){var u;return l&&(u=l._private[n.field][t]),u}if(n.allowSetting&&void 0!==r){var c=!n.immutableKeys[t];if(c){for(var d=0,h=s.length;h>d;d++)n.canSet(s[d])&&(s[d]._private[n.field][t]=r);n.updateStyle&&a.updateStyle(),n.onSet(a),n.settingTriggersEvent&&a[n.triggerFnName](n.settingEvent)}}}else if(n.allowSetting&&i.plainObject(t)){for(var p,f,v=t,g=Object.keys(v),d=0;d<g.length;d++){p=g[d],f=v[p];var c=!n.immutableKeys[p];if(c)for(var y=0;y<s.length;y++){var m=s[y];n.canSet(m)&&(m._private[n.field][p]=f)}}n.updateStyle&&a.updateStyle(),n.onSet(a),n.settingTriggersEvent&&a[n.triggerFnName](n.settingEvent)}else if(n.allowBinding&&i.fn(t)){var b=t;a.on(n.bindingEvent,b)}else if(n.allowGetting&&void 0===t){var u;return l&&(u=l._private[n.field]),u}return a}},removeData:function(e){var t={field:"data",event:"data",triggerFnName:"trigger",triggerEvent:!1,immutableKeys:{}};return e=n.extend({},t,e),function(t){var r=e,n=this,a=void 0!==n.length,o=a?n:[n];if(i.string(t)){for(var s=t.split(/\s+/),l=s.length,u=0;l>u;u++){var c=s[u];if(!i.emptyString(c)){var d=!r.immutableKeys[c];if(d)for(var h=0,p=o.length;p>h;h++)o[h]._private[r.field][c]=void 0}}r.triggerEvent&&n[r.triggerFnName](r.event)}else if(void 0===t){for(var h=0,p=o.length;p>h;h++)for(var f=o[h]._private[r.field],s=Object.keys(f),u=0;u<s.length;u++){var c=s[u],v=!r.immutableKeys[c];v&&(f[c]=void 0)}r.triggerEvent&&n[r.triggerFnName](r.event)}return n}},event:{regex:/(\w+)(\.(?:\w+|\*))?/,universalNamespace:".*",optionalTypeRegex:/(\w+)?(\.(?:\w+|\*))?/,falseCallback:function(){return!1}},on:function(e){var t={unbindSelfOnTrigger:!1,unbindAllBindersOnTrigger:!1};return e=n.extend({},t,e),function(t,r,n,o){var s=this,l=void 0!==s.length,c=l?s:[s],d=i.string(t),h=e;if(i.plainObject(r)?(o=n,n=r,r=void 0):(i.fn(r)||r===!1)&&(o=r,n=void 0,r=void 0),(i.fn(n)||n===!1)&&(o=n,n=void 0),!i.fn(o)&&o!==!1&&d)return s;if(d){var p={};p[t]=o,t=p}for(var f=Object.keys(t),v=0;v<f.length;v++){var g=f[v];if(o=t[g],o===!1&&(o=u.event.falseCallback),i.fn(o)){g=g.split(/\s+/);for(var y=0;y<g.length;y++){var m=g[y];if(!i.emptyString(m)){var b=m.match(u.event.regex);if(b)for(var x=b[1],w=b[2]?b[2]:void 0,E={callback:o,data:n,delegated:!!r,selector:r,selObj:new a(r),type:x,namespace:w,unbindSelfOnTrigger:h.unbindSelfOnTrigger,unbindAllBindersOnTrigger:h.unbindAllBindersOnTrigger,binders:c},_=0;_<c.length;_++){var P=c[_]._private=c[_]._private||{};P.listeners=P.listeners||[],P.listeners.push(E)}}}}}return s}},eventAliasesOn:function(e){var t=e;t.addListener=t.listen=t.bind=t.on,t.removeListener=t.unlisten=t.unbind=t.off,t.emit=t.trigger,t.pon=t.promiseOn=function(e,t){var r=this,n=Array.prototype.slice.call(arguments,0);return new o(function(e,t){var i=function(t){r.off.apply(r,o),e(t)},a=n.concat([i]),o=a.concat([]);r.on.apply(r,a)})}},off:function(e){var t={};return e=n.extend({},t,e),function(e,t,r){var n=this,a=void 0!==n.length,o=a?n:[n],s=i.string(e);if(0===arguments.length){for(var l=0;l<o.length;l++)o[l]._private=o[l]._private||{},b.listeners=[];return n}if((i.fn(t)||t===!1)&&(r=t,t=void 0),s){var c={};c[e]=r,e=c}for(var d=Object.keys(e),h=0;h<d.length;h++){var p=d[h];r=e[p],r===!1&&(r=u.event.falseCallback),p=p.split(/\s+/);for(var f=0;f<p.length;f++){var v=p[f];if(!i.emptyString(v)){var g=v.match(u.event.optionalTypeRegex);if(g)for(var y=g[1]?g[1]:void 0,m=g[2]?g[2]:void 0,l=0;l<o.length;l++)for(var b=o[l]._private=o[l]._private||{},x=b.listeners=b.listeners||[],w=0;w<x.length;w++){var E=x[w],_=!m||m===E.namespace,P=!y||E.type===y,S=!r||r===E.callback,k=_&&P&&S;k&&(x.splice(w,1),w--)}}}}return n}},trigger:function(e){var t={};return e=n.extend({},t,e),function(t,r,n){var a=this,o=void 0!==a.length,l=o?a:[a],c=i.string(t),d=i.plainObject(t),h=i.event(t),p=this._private=this._private||{},f=p.cy||(i.core(this)?this:null),v=f?f.hasCompoundNodes():!1;if(c){var g=t.split(/\s+/);t=[];for(var y=0;y<g.length;y++){var m=g[y];if(!i.emptyString(m)){var b=m.match(u.event.regex),x=b[1],w=b[2]?b[2]:void 0;t.push({type:x,namespace:w})}}}else if(d){var E=t;t=[E]}r?i.array(r)||(r=[r]):r=[];for(var y=0;y<t.length;y++)for(var _=t[y],P=0;P<l.length;P++){var m,S=l[P],p=S._private=S._private||{},k=p.listeners=p.listeners||[],T=i.element(S),D=T||e.layout;if(h?(m=_,m.cyTarget=m.cyTarget||S,m.cy=m.cy||f):m=new s(_,{cyTarget:S,cy:f,namespace:_.namespace}),_.layout&&(m.layout=_.layout),e.layout&&(m.layout=S),m.cyPosition){var C=m.cyPosition,M=f.zoom(),N=f.pan();m.cyRenderedPosition={x:C.x*M+N.x,y:C.y*M+N.y}}n&&(k=[{namespace:m.namespace,type:m.type,callback:n}]);for(var B=0;B<k.length;B++){var z=k[B],I=!z.namespace||z.namespace===m.namespace||z.namespace===u.event.universalNamespace,L=z.type===m.type,O=z.delegated?S!==m.cyTarget&&i.element(m.cyTarget)&&z.selObj.matches(m.cyTarget):!0,A=I&&L&&O;if(A){var R=[m];if(R=R.concat(r),z.data?m.data=z.data:m.data=void 0,(z.unbindSelfOnTrigger||z.unbindAllBindersOnTrigger)&&(k.splice(B,1),B--),z.unbindAllBindersOnTrigger)for(var q=z.binders,V=0;V<q.length;V++){var F=q[V];if(F&&F!==S)for(var j=F._private.listeners,X=0;X<j.length;X++){var Y=j[X];Y===z&&(j.splice(X,1),X--)}}var W=z.delegated?m.cyTarget:S,$=z.callback.apply(W,R);($===!1||m.isPropagationStopped())&&(D=!1,$===!1&&(m.stopPropagation(),m.preventDefault()))}}if(D){var H=v?S._private.parent:null,U=null!=H&&0!==H.length;U?(H=H[0],H.trigger(m)):f.trigger(m)}}return a}},animated:function(e){var t={};return e=n.extend({},t,e),function(){var e=this,t=void 0!==e.length,r=t?e:[e],n=this._private.cy||this;if(!n.styleEnabled())return!1;var i=r[0];return i?i._private.animation.current.length>0:void 0}},clearQueue:function(e){var t={};return e=n.extend({},t,e),function(){var e=this,t=void 0!==e.length,r=t?e:[e],n=this._private.cy||this;if(!n.styleEnabled())return this;for(var i=0;i<r.length;i++){var a=r[i];a._private.animation.queue=[]}return this}},delay:function(e){var t={};return e=n.extend({},t,e),function(e,t){var r=this._private.cy||this;return r.styleEnabled()?this.animate({delay:e,duration:e,complete:t}):this}},delayAnimation:function(e){var t={};return e=n.extend({},t,e),function(e,t){var r=this._private.cy||this;return r.styleEnabled()?this.animation({delay:e,duration:e,complete:t}):this}},animation:function(e){var t={};return e=n.extend({},t,e),function(e,t){var r=this,i=void 0!==r.length,a=i?r:[r],o=this._private.cy||this,s=!i,u=!s;if(!o.styleEnabled())return this;var c=o.style();switch(e=n.extend({},e,t),void 0===e.duration&&(e.duration=400),e.duration){case"slow":e.duration=600;break;case"fast":e.duration=200}var d=0===Object.keys(e).length;if(d)return new l(a[0],e);if(u&&(e.style=c.getPropsList(e.style||e.css),e.css=void 0),e.renderedPosition&&u){var h=e.renderedPosition,p=o.pan(),f=o.zoom();e.position={x:(h.x-p.x)/f,y:(h.y-p.y)/f}}if(e.panBy&&s){var v=e.panBy,g=o.pan();e.pan={x:g.x+v.x,y:g.y+v.y}}var y=e.center||e.centre;if(y&&s){var m=o.getCenterPan(y.eles,e.zoom);m&&(e.pan=m)}if(e.fit&&s){var b=e.fit,x=o.getFitViewport(b.eles||b.boundingBox,b.padding);x&&(e.pan=x.pan,e.zoom=x.zoom)}return new l(a[0],e)}},animate:function(e){var t={};return e=n.extend({},t,e),function(e,t){var r=this,i=void 0!==r.length,a=i?r:[r],o=this._private.cy||this;if(!o.styleEnabled())return this;t&&(e=n.extend({},e,t));for(var s=0;s<a.length;s++){var l=a[s],u=l.animated()&&(void 0===e.queue||e.queue),c=l.animation(e,u?{queue:!0}:void 0);c.play()}return this}},stop:function(e){var t={};return e=n.extend({},t,e),function(e,t){var r=this,n=void 0!==r.length,i=n?r:[r],a=this._private.cy||this;if(!a.styleEnabled())return this;for(var o=0;o<i.length;o++){for(var s=i[o],l=s._private,u=l.animation.current,c=0;c<u.length;c++){var d=u[c],h=d._private;t&&(h.duration=0)}e&&(l.animation.queue=[]),t||(l.animation.current=[])}return a.notify({eles:this,type:"draw"}),this}}};t.exports=u},{"./animation":2,"./event":45,"./is":83,"./promise":86,"./selector":87,"./util":100}],45:[function(e,t,r){"use strict";function n(){return!1}function i(){return!0}/*! +Event object based on jQuery events, MIT license + +https://jquery.org/license/ +https://tldrlegal.com/license/mit-license +https://github.com/jquery/jquery/blob/master/src/event.js +*/ +var a=function(e,t){return this instanceof a?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented?i:n):this.type=e,t&&(this.type=void 0!==t.type?t.type:this.type,this.cy=t.cy,this.cyTarget=t.cyTarget,this.cyPosition=t.cyPosition,this.cyRenderedPosition=t.cyRenderedPosition,this.namespace=t.namespace,this.layout=t.layout,this.data=t.data,this.message=t.message),void(this.timeStamp=e&&e.timeStamp||Date.now())):new a(e,t)};a.prototype={instanceString:function(){return"event"},preventDefault:function(){this.isDefaultPrevented=i;var e=this.originalEvent;e&&e.preventDefault&&e.preventDefault()},stopPropagation:function(){this.isPropagationStopped=i;var e=this.originalEvent;e&&e.stopPropagation&&e.stopPropagation()},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=i,this.stopPropagation()},isDefaultPrevented:n,isPropagationStopped:n,isImmediatePropagationStopped:n},t.exports=a},{}],46:[function(e,t,r){"use strict";function n(e,t,r){var n=r,a=function(r){s.error("Can not register `"+t+"` for `"+e+"` since `"+r+"` already exists in the prototype and can not be overridden")};if("core"===e){if(c.prototype[t])return a(t);c.prototype[t]=r}else if("collection"===e){if(u.prototype[t])return a(t);u.prototype[t]=r}else if("layout"===e){for(var o=function(e){this.options=e,r.call(this,e),h.plainObject(this._private)||(this._private={}),this._private.cy=e.cy,this._private.listeners=[]},d=o.prototype=Object.create(r.prototype),f=[],v=0;v<f.length;v++){var g=f[v];d[g]=d[g]||function(){return this}}d.start&&!d.run?d.run=function(){return this.start(),this}:!d.start&&d.run&&(d.start=function(){return this.run(),this}),d.stop||(d.stop=function(){var e=this.options;if(e&&e.animate)for(var t=this.animations,r=0;r<t.length;r++)t[r].stop();return this.trigger("layoutstop"),this}),d.destroy||(d.destroy=function(){return this}),d.on=l.on({layout:!0}),d.one=l.on({layout:!0,unbindSelfOnTrigger:!0}),d.once=l.on({layout:!0,unbindAllBindersOnTrigger:!0}),d.off=l.off({layout:!0}),d.trigger=l.trigger({layout:!0}),l.eventAliasesOn(d),n=o}else if("renderer"===e&&"null"!==t&&"base"!==t){var y=i("renderer","base"),m=y.prototype,b=r,x=r.prototype,w=function(){y.apply(this,arguments),b.apply(this,arguments)},E=w.prototype;for(var _ in m){var P=m[_],S=null!=x[_];if(S)return a(_);E[_]=P}for(var _ in x)E[_]=x[_];m.clientFunctions.forEach(function(e){E[e]=E[e]||function(){s.error("Renderer does not implement `renderer."+e+"()` on its prototype")}}),n=w}return s.setMap({map:p,keys:[e,t],value:n})}function i(e,t){return s.getMap({map:p,keys:[e,t]})}function a(e,t,r,n,i){return s.setMap({map:f,keys:[e,t,r,n],value:i})}function o(e,t,r,n){return s.getMap({map:f,keys:[e,t,r,n]})}var s=e("./util"),l=e("./define"),u=e("./collection"),c=e("./core"),d=e("./extensions"),h=e("./is"),p={},f={},v=function(){return 2===arguments.length?i.apply(null,arguments):3===arguments.length?n.apply(null,arguments):4===arguments.length?o.apply(null,arguments):5===arguments.length?a.apply(null,arguments):void s.error("Invalid extension access syntax")};c.prototype.extension=v,d.forEach(function(e){e.extensions.forEach(function(t){n(e.type,t.name,t.impl)})}),t.exports=v},{"./collection":26,"./core":37,"./define":44,"./extensions":47,"./is":83,"./util":100}],47:[function(e,t,r){"use strict";t.exports=[{type:"layout",extensions:e("./layout")},{type:"renderer",extensions:e("./renderer")}]},{"./layout":53,"./renderer":78}],48:[function(e,t,r){"use strict";function n(e){this.options=i.extend({},s,e)}var i=e("../../util"),a=e("../../math"),o=e("../../is"),s={fit:!0,directed:!1,padding:30,circle:!1,spacingFactor:1.75,boundingBox:void 0,avoidOverlap:!0,roots:void 0,maximalAdjustments:0,animate:!1,animationDuration:500,animationEasing:void 0,ready:void 0,stop:void 0};n.prototype.run=function(){var e,t=this.options,r=t,n=t.cy,i=r.eles,s=i.nodes().not(":parent"),l=i,u=a.makeBoundingBox(r.boundingBox?r.boundingBox:{x1:0,y1:0,w:n.width(),h:n.height()});if(o.elementOrCollection(r.roots))e=r.roots;else if(o.array(r.roots)){for(var c=[],d=0;d<r.roots.length;d++){var h=r.roots[d],p=n.getElementById(h);c.push(p)}e=n.collection(c)}else if(o.string(r.roots))e=n.$(r.roots);else if(r.directed)e=s.roots();else{for(var f=[],v=s;v.length>0;){var g=n.collection();i.bfs({roots:v[0],visit:function(e,t,r,n,i){g=g.add(r)},directed:!1}),v=v.not(g),f.push(g)}e=n.collection();for(var d=0;d<f.length;d++){var y=f[d],m=y.maxDegree(!1),b=y.filter(function(){return this.degree(!1)===m});e=e.add(b)}}var x=[],w={},E={},_={},P={},S={};l.bfs({roots:e,directed:r.directed,visit:function(e,t,r,n,i){var a=this[0],o=a.id();if(x[t]||(x[t]=[]),x[t].push(a),w[o]=!0,E[o]=t,_[o]=i,P[o]=n,i){var s=i.id(),l=S[s]=S[s]||[];l.push(r)}}});for(var k=[],d=0;d<s.length;d++){var p=s[d];w[p.id()]||k.push(p)}for(var T=3*k.length,D=0;0!==k.length&&T>D;){for(var C=k.shift(),M=C.neighborhood().nodes(),N=!1,d=0;d<M.length;d++){var B=E[M[d].id()];if(void 0!==B){x[B].push(C),N=!0;break}}N||k.push(C),D++}for(;0!==k.length;){var C=k.shift(),N=!1;N||(0===x.length&&x.push([]),x[0].push(C))}var z=function(){for(var e=0;e<x.length;e++)for(var t=x[e],r=0;r<t.length;r++){var n=t[r];n._private.scratch.breadthfirst={depth:e,index:r}}};z();for(var I=function(e){for(var t,r=e.connectedEdges(function(){return this.data("target")===e.id()}),n=e._private.scratch.breadthfirst,i=0,a=0;a<r.length;a++){var o=r[a],s=o.source()[0],l=s._private.scratch.breadthfirst;n.depth<=l.depth&&i<l.depth&&(i=l.depth,t=s)}return t},L=0;L<r.maximalAdjustments;L++){for(var O=x.length,A=[],d=0;O>d;d++)for(var B=x[d],R=B.length,q=0;R>q;q++){var p=B[q],V=p._private.scratch.breadthfirst,F=I(p);F&&(V.intEle=F,A.push(p))}for(var d=0;d<A.length;d++){var p=A[d],V=p._private.scratch.breadthfirst,F=V.intEle,j=F._private.scratch.breadthfirst;x[V.depth].splice(V.index,1);for(var X=j.depth+1;X>x.length-1;)x.push([]);x[X].push(p),V.depth=X,V.index=x[X].length-1}z()}var Y=0;if(r.avoidOverlap){for(var d=0;d<s.length;d++){var W=s[d],$=W.boundingBox(),H=$.w,U=$.h;Y=Math.max(Y,H,U)}Y*=r.spacingFactor}for(var Z={},G=function(e){if(Z[e.id()])return Z[e.id()];for(var t=e._private.scratch.breadthfirst.depth,r=e.neighborhood().nodes().not(":parent"),n=0,i=0,a=0;a<r.length;a++){var o=r[a],s=o._private.scratch.breadthfirst,l=s.index,u=s.depth,c=x[u].length;(t>u||0===t)&&(n+=l/c,i++)}return i=Math.max(1,i),n/=i,0===i&&(n=void 0),Z[e.id()]=n,n},Q=function(e,t){var r=G(e),n=G(t);return r-n},K=0;3>K;K++){for(var d=0;d<x.length;d++)x[d]=x[d].sort(Q);z()}for(var J=0,d=0;d<x.length;d++)J=Math.max(x[d].length,J);for(var ee={x:u.x1+u.w/2,y:u.x1+u.h/2},te=function(e,t){var n=e._private.scratch.breadthfirst,i=n.depth,a=n.index,o=x[i].length,s=Math.max(u.w/(o+1),Y),l=Math.max(u.h/(x.length+1),Y),c=Math.min(u.w/2/x.length,u.h/2/x.length);if(c=Math.max(c,Y),r.circle){if(r.circle){var d=c*i+c-(x.length>0&&x[0].length<=3?c/2:0),h=2*Math.PI/x[i].length*a;return 0===i&&1===x[0].length&&(d=1),{x:ee.x+d*Math.cos(h),y:ee.y+d*Math.sin(h)}}return{x:ee.x+(a+1-(o+1)/2)*s,y:(i+1)*l}}var p={x:ee.x+(a+1-(o+1)/2)*s,y:(i+1)*l};return t?p:p},re={},d=x.length-1;d>=0;d--)for(var B=x[d],q=0;q<B.length;q++){var C=B[q];re[C.id()]=te(C,d===x.length-1)}return s.layoutPositions(this,r,function(){return re[this.id()]}),this},t.exports=n},{"../../is":83,"../../math":85,"../../util":100}],49:[function(e,t,r){"use strict";function n(e){this.options=i.extend({},s,e)}var i=e("../../util"),a=e("../../math"),o=e("../../is"),s={fit:!0,padding:30,boundingBox:void 0,avoidOverlap:!0,radius:void 0,startAngle:1.5*Math.PI,sweep:void 0,clockwise:!0,sort:void 0,animate:!1,animationDuration:500,animationEasing:void 0,ready:void 0,stop:void 0};n.prototype.run=function(){var e=this.options,t=e,r=e.cy,n=t.eles,i=void 0!==t.counterclockwise?!t.counterclockwise:t.clockwise,s=n.nodes().not(":parent");t.sort&&(s=s.sort(t.sort));for(var l,u=a.makeBoundingBox(t.boundingBox?t.boundingBox:{x1:0,y1:0,w:r.width(),h:r.height()}),c={x:u.x1+u.w/2,y:u.y1+u.h/2},d=void 0===t.sweep?2*Math.PI-2*Math.PI/s.length:t.sweep,h=d/Math.max(1,s.length-1),p=0,f=0;f<s.length;f++){var v=s[f],g=v.boundingBox(),y=g.w,m=g.h;p=Math.max(p,y,m)}if(l=o.number(t.radius)?t.radius:s.length<=1?0:Math.min(u.h,u.w)/2-p,s.length>1&&t.avoidOverlap){p*=1.75;var b=Math.cos(h)-Math.cos(0),x=Math.sin(h)-Math.sin(0),w=Math.sqrt(p*p/(b*b+x*x));l=Math.max(w,l)}var E=function(e,r){var n=t.startAngle+e*h*(i?1:-1),a=l*Math.cos(n),o=l*Math.sin(n),s={x:c.x+a,y:c.y+o};return s};return s.layoutPositions(this,t,E),this},t.exports=n},{"../../is":83,"../../math":85,"../../util":100}],50:[function(e,t,r){"use strict";function n(e){this.options=i.extend({},o,e)}var i=e("../../util"),a=e("../../math"),o={fit:!0,padding:30,startAngle:1.5*Math.PI,sweep:void 0,clockwise:!0,equidistant:!1,minNodeSpacing:10,boundingBox:void 0,avoidOverlap:!0,height:void 0,width:void 0,concentric:function(e){return e.degree()},levelWidth:function(e){return e.maxDegree()/4},animate:!1,animationDuration:500,animationEasing:void 0,ready:void 0,stop:void 0};n.prototype.run=function(){for(var e=this.options,t=e,r=void 0!==t.counterclockwise?!t.counterclockwise:t.clockwise,n=e.cy,i=t.eles,o=i.nodes().not(":parent"),s=a.makeBoundingBox(t.boundingBox?t.boundingBox:{x1:0,y1:0,w:n.width(),h:n.height()}),l={x:s.x1+s.w/2,y:s.y1+s.h/2},u=[],c=t.startAngle,d=0,h=0;h<o.length;h++){var p,f=o[h];p=t.concentric.apply(f,[f]),u.push({value:p,node:f}),f._private.scratch.concentric=p}o.updateStyle();for(var h=0;h<o.length;h++){var f=o[h],v=f.boundingBox();d=Math.max(d,v.w,v.h)}u.sort(function(e,t){return t.value-e.value});for(var g=t.levelWidth(o),y=[[]],m=y[0],h=0;h<u.length;h++){var b=u[h];if(m.length>0){var x=Math.abs(m[0].value-b.value);x>=g&&(m=[],y.push(m))}m.push(b)}var w=d+t.minNodeSpacing;if(!t.avoidOverlap){var E=y.length>0&&y[0].length>1,_=Math.min(s.w,s.h)/2-w,P=_/(y.length+E?1:0);w=Math.min(w,P)}for(var S=0,h=0;h<y.length;h++){var k=y[h],T=void 0===t.sweep?2*Math.PI-2*Math.PI/k.length:t.sweep,D=k.dTheta=T/Math.max(1,k.length-1);if(k.length>1&&t.avoidOverlap){var C=Math.cos(D)-Math.cos(0),M=Math.sin(D)-Math.sin(0),N=Math.sqrt(w*w/(C*C+M*M));S=Math.max(N,S)}k.r=S,S+=w}if(t.equidistant){for(var B=0,S=0,h=0;h<y.length;h++){var k=y[h],z=k.r-S;B=Math.max(B,z)}S=0;for(var h=0;h<y.length;h++){var k=y[h];0===h&&(S=k.r),k.r=S,S+=B}}for(var I={},h=0;h<y.length;h++)for(var k=y[h],D=k.dTheta,S=k.r,L=0;L<k.length;L++){var b=k[L],c=t.startAngle+(r?1:-1)*D*L,O={x:l.x+S*Math.cos(c),y:l.y+S*Math.sin(c)};I[b.node.id()]=O}return o.layoutPositions(this,t,function(){var e=this.id();return I[e]}),this},t.exports=n},{"../../math":85,"../../util":100}],51:[function(e,t,r){"use strict";function n(e){this.options=a.extend({},u,e),this.options.layout=this}var i,a=e("../../util"),o=e("../../math"),s=e("../../thread"),l=e("../../is"),u={ready:function(){},stop:function(){},animate:!0,animationThreshold:250,refresh:20,fit:!0,padding:30,boundingBox:void 0,componentSpacing:100,nodeRepulsion:function(e){return 4e5},nodeOverlap:10,idealEdgeLength:function(e){return 10},edgeElasticity:function(e){return 100},nestingFactor:5,gravity:80,numIter:1e3,initialTemp:200,coolingFactor:.95,minTemp:1,useMultitasking:!0};n.prototype.run=function(){var e=this.options,t=e.cy,r=this,n=this.thread;n&&!n.stopped()||(n=this.thread=s({disabled:!e.useMultitasking})),r.stopped=!1,r.trigger({type:"layoutstart",layout:r}),i=!0===e.debug;var o=c(t,r,e);i&&p(o),f(o,t);var l=Date.now(),u=!1,d=function(r){r=r||{},u&&!r.next||!r.force&&Date.now()-l<e.animationThreshold||(u=!0,a.requestAnimationFrame(function(){v(o,t,e),!0===e.fit&&t.fit(e.padding),u=!1,r.next&&r.next()}))};n.on("message",function(e){var t=e.message;o.layoutNodes=t,d()}),n.pass({layoutInfo:o,options:{animate:e.animate,refresh:e.refresh,componentSpacing:e.componentSpacing,nodeOverlap:e.nodeOverlap,nestingFactor:e.nestingFactor,gravity:e.gravity,numIter:e.numIter,initialTemp:e.initialTemp,coolingFactor:e.coolingFactor,minTemp:e.minTemp}}).run(function(e){var t,r=e.layoutInfo,n=e.options,i=!1,a=function(e,t,r){o(e,t),c(e,t),d(e,t),h(e,t),p(e,t)},o=function(e,t){for(var r=0;r<e.graphSet.length;r++)for(var n=e.graphSet[r],i=n.length,a=0;i>a;a++)for(var o=e.layoutNodes[e.idToIndex[n[a]]],l=a+1;i>l;l++){var u=e.layoutNodes[e.idToIndex[n[l]]];s(o,u,e,t)}},s=function(e,t,r,n){var i=e.cmptId,a=t.cmptId;if(i===a||r.isCompound){var o=t.positionX-e.positionX,s=t.positionY-e.positionY;if(0!==o||0!==s){var c=l(e,t,o,s);if(c>0)var d=n.nodeOverlap*c,h=Math.sqrt(o*o+s*s),p=d*o/h,f=d*s/h;else var v=u(e,o,s),g=u(t,-1*o,-1*s),y=g.x-v.x,m=g.y-v.y,b=y*y+m*m,h=Math.sqrt(b),d=(e.nodeRepulsion+t.nodeRepulsion)/b,p=d*y/h,f=d*m/h;e.isLocked||(e.offsetX-=p,e.offsetY-=f),t.isLocked||(t.offsetX+=p,t.offsetY+=f)}}},l=function(e,t,r,n){if(r>0)var i=e.maxX-t.minX;else var i=t.maxX-e.minX;if(n>0)var a=e.maxY-t.minY;else var a=t.maxY-e.minY;return i>=0&&a>=0?Math.sqrt(i*i+a*a):0},u=function(e,t,r){var n=e.positionX,i=e.positionY,a=e.height||1,o=e.width||1,s=r/t,l=a/o,u={};do{if(0===t&&r>0){u.x=n,u.y=i+a/2;break}if(0===t&&0>r){u.x=n,u.y=i+a/2;break}if(t>0&&s>=-1*l&&l>=s){u.x=n+o/2,u.y=i+o*r/2/t;break}if(0>t&&s>=-1*l&&l>=s){u.x=n-o/2,u.y=i-o*r/2/t;break}if(r>0&&(-1*l>=s||s>=l)){u.x=n+a*t/2/r,u.y=i+a/2;break}if(0>r&&(-1*l>=s||s>=l)){u.x=n-a*t/2/r,u.y=i-a/2;break}}while(!1);return u},c=function(e,t){for(var r=0;r<e.edgeSize;r++){var n=e.layoutEdges[r],i=e.idToIndex[n.sourceId],a=e.layoutNodes[i],o=e.idToIndex[n.targetId],s=e.layoutNodes[o],l=s.positionX-a.positionX,c=s.positionY-a.positionY;if(0===l&&0===c)return;var d=u(a,l,c),h=u(s,-1*l,-1*c),p=h.x-d.x,f=h.y-d.y,v=Math.sqrt(p*p+f*f),g=Math.pow(n.idealLength-v,2)/n.elasticity;if(0!==v)var y=g*p/v,m=g*f/v;else var y=0,m=0;a.isLocked||(a.offsetX+=y,a.offsetY+=m),s.isLocked||(s.offsetX-=y,s.offsetY-=m)}},d=function(e,t){for(var r=1,n=0;n<e.graphSet.length;n++){var i=e.graphSet[n],a=i.length;if(0===n)var o=e.clientHeight/2,s=e.clientWidth/2;else var l=e.layoutNodes[e.idToIndex[i[0]]],u=e.layoutNodes[e.idToIndex[l.parentId]],o=u.positionX,s=u.positionY;for(var c=0;a>c;c++){var d=e.layoutNodes[e.idToIndex[i[c]]];if(!d.isLocked){var h=o-d.positionX,p=s-d.positionY,f=Math.sqrt(h*h+p*p);if(f>r){var v=t.gravity*h/f,g=t.gravity*p/f;d.offsetX+=v,d.offsetY+=g}}}}},h=function(e,t){var r=[],n=0,i=-1;for(r.push.apply(r,e.graphSet[0]),i+=e.graphSet[0].length;i>=n;){var a=r[n++],o=e.idToIndex[a],s=e.layoutNodes[o],l=s.children;if(0<l.length&&!s.isLocked){for(var u=s.offsetX,c=s.offsetY,d=0;d<l.length;d++){var h=e.layoutNodes[e.idToIndex[l[d]]];h.offsetX+=u,h.offsetY+=c,r[++i]=l[d]}s.offsetX=0,s.offsetY=0}}},p=function(e,t){for(var r=0;r<e.nodeSize;r++){var n=e.layoutNodes[r];0<n.children.length&&(n.maxX=void 0,n.minX=void 0,n.maxY=void 0,n.minY=void 0)}for(var r=0;r<e.nodeSize;r++){var n=e.layoutNodes[r];if(!(0<n.children.length||n.isLocked)){var i=f(n.offsetX,n.offsetY,e.temperature);n.positionX+=i.x,n.positionY+=i.y,n.offsetX=0,n.offsetY=0,n.minX=n.positionX-n.width,n.maxX=n.positionX+n.width,n.minY=n.positionY-n.height,n.maxY=n.positionY+n.height,v(n,e)}}for(var r=0;r<e.nodeSize;r++){var n=e.layoutNodes[r];0<n.children.length&&!n.isLocked&&(n.positionX=(n.maxX+n.minX)/2,n.positionY=(n.maxY+n.minY)/2,n.width=n.maxX-n.minX,n.height=n.maxY-n.minY)}},f=function(e,t,r){var n=Math.sqrt(e*e+t*t);if(n>r)var i={x:r*e/n,y:r*t/n};else var i={x:e,y:t};return i},v=function(e,t){var r=e.parentId;if(null!=r){var n=t.layoutNodes[t.idToIndex[r]],i=!1;return(null==n.maxX||e.maxX+n.padRight>n.maxX)&&(n.maxX=e.maxX+n.padRight,i=!0),(null==n.minX||e.minX-n.padLeft<n.minX)&&(n.minX=e.minX-n.padLeft,i=!0),(null==n.maxY||e.maxY+n.padBottom>n.maxY)&&(n.maxY=e.maxY+n.padBottom,i=!0),(null==n.minY||e.minY-n.padTop<n.minY)&&(n.minY=e.minY-n.padTop,i=!0),i?v(n,t):void 0}},g=function(e,t){for(var n=r.layoutNodes,i=[],a=0;a<n.length;a++){var o=n[a],s=o.cmptId,l=i[s]=i[s]||[];l.push(o)}for(var u=0,a=0;a<i.length;a++){var c=i[a];if(c){c.x1=1/0,c.x2=-(1/0),c.y1=1/0,c.y2=-(1/0);for(var d=0;d<c.length;d++){var h=c[d];c.x1=Math.min(c.x1,h.positionX-h.width/2),c.x2=Math.max(c.x2,h.positionX+h.width/2),c.y1=Math.min(c.y1,h.positionY-h.height/2),c.y2=Math.max(c.y2,h.positionY+h.height/2)}c.w=c.x2-c.x1,c.h=c.y2-c.y1,u+=c.w*c.h}}i.sort(function(e,t){return t.w*t.h-e.w*e.h});for(var p=0,f=0,v=0,g=0,y=Math.sqrt(u)*r.clientWidth/r.clientHeight,a=0;a<i.length;a++){var c=i[a];if(c){for(var d=0;d<c.length;d++){var h=c[d];h.isLocked||(h.positionX+=p,h.positionY+=f)}p+=c.w+t.componentSpacing,v+=c.w+t.componentSpacing,g=Math.max(g,c.h),v>y&&(f+=g+t.componentSpacing,p=0,v=0,g=0)}}},y=function(e){return i?!1:(a(r,n,e),r.temperature=r.temperature*n.coolingFactor,!(r.temperature<n.minTemp))},m=0;do{for(var b=0;b<n.refresh&&m<n.numIter;){var t=y(m);if(!t)break;b++,m++}n.animate&&broadcast(r.layoutNodes)}while(t&&m+1<n.numIter);return g(r,n),r}).then(function(e){o.layoutNodes=e.layoutNodes,n.stop(),h()});var h=function(){d({force:!0,next:function(){r.one("layoutstop",e.stop),r.trigger({type:"layoutstop",layout:r})}})};return this},n.prototype.stop=function(){return this.stopped=!0,this.thread&&this.thread.stop(),this.trigger("layoutstop"),this},n.prototype.destroy=function(){return this.thread&&this.thread.stop(),this};var c=function(e,t,r){for(var n=r.eles.edges(),i=r.eles.nodes(),a={isCompound:e.hasCompoundNodes(),layoutNodes:[],idToIndex:{},nodeSize:i.size(),graphSet:[],indexToGraph:[],layoutEdges:[],edgeSize:n.size(),temperature:r.initialTemp,clientWidth:e.width(),clientHeight:e.width(),boundingBox:o.makeBoundingBox(r.boundingBox?r.boundingBox:{x1:0,y1:0,w:e.width(),h:e.height()})},s=r.eles.components(),u={},c=0;c<s.length;c++)for(var h=s[c],p=0;p<h.length;p++){var f=h[p];u[f.id()]=c}for(var c=0;c<a.nodeSize;c++){var v=i[c],g=v.boundingBox(),y={};y.isLocked=v.locked(),y.id=v.data("id"),y.parentId=v.data("parent"),y.cmptId=u[v.id()],y.children=[],y.positionX=v.position("x"),y.positionY=v.position("y"),y.offsetX=0,y.offsetY=0,y.height=g.w,y.width=g.h,y.maxX=y.positionX+y.width/2,y.minX=y.positionX-y.width/2,y.maxY=y.positionY+y.height/2,y.minY=y.positionY-y.height/2,y.padLeft=parseFloat(v.style("padding-left")),y.padRight=parseFloat(v.style("padding-right")),y.padTop=parseFloat(v.style("padding-top")),y.padBottom=parseFloat(v.style("padding-bottom")),y.nodeRepulsion=l.fn(r.nodeRepulsion)?r.nodeRepulsion.call(v,v):r.nodeRepulsion,a.layoutNodes.push(y),a.idToIndex[y.id]=c}for(var m=[],b=0,x=-1,w=[],c=0;c<a.nodeSize;c++){var v=a.layoutNodes[c],E=v.parentId;null!=E?a.layoutNodes[a.idToIndex[E]].children.push(v.id):(m[++x]=v.id,w.push(v.id))}for(a.graphSet.push(w);x>=b;){var _=m[b++],P=a.idToIndex[_],f=a.layoutNodes[P],S=f.children;if(S.length>0){a.graphSet.push(S);for(var c=0;c<S.length;c++)m[++x]=S[c]}}for(var c=0;c<a.graphSet.length;c++)for(var k=a.graphSet[c],p=0;p<k.length;p++){var T=a.idToIndex[k[p]];a.indexToGraph[T]=c}for(var c=0;c<a.edgeSize;c++){var D=n[c],C={};C.id=D.data("id"),C.sourceId=D.data("source"),C.targetId=D.data("target");var M=l.fn(r.idealEdgeLength)?r.idealEdgeLength.call(D,D):r.idealEdgeLength,N=l.fn(r.edgeElasticity)?r.edgeElasticity.call(D,D):r.edgeElasticity,B=a.idToIndex[C.sourceId],z=a.idToIndex[C.targetId],I=a.indexToGraph[B],L=a.indexToGraph[z];if(I!=L){for(var O=d(C.sourceId,C.targetId,a),A=a.graphSet[O],R=0,y=a.layoutNodes[B];-1===A.indexOf(y.id);)y=a.layoutNodes[a.idToIndex[y.parentId]],R++;for(y=a.layoutNodes[z];-1===A.indexOf(y.id);)y=a.layoutNodes[a.idToIndex[y.parentId]],R++;M*=R*r.nestingFactor}C.idealLength=M,C.elasticity=N,a.layoutEdges.push(C)}return a},d=function(e,t,r){var n=h(e,t,0,r);return 2>n.count?0:n.graph},h=function(e,t,r,n){var i=n.graphSet[r];if(-1<i.indexOf(e)&&-1<i.indexOf(t))return{count:2,graph:r};for(var a=0,o=0;o<i.length;o++){var s=i[o],l=n.idToIndex[s],u=n.layoutNodes[l].children;if(0!==u.length){var c=n.indexToGraph[n.idToIndex[u[0]]],d=h(e,t,c,n);if(0!==d.count){if(1!==d.count)return d;if(a++,2===a)break}}}return{count:a,graph:r}},p=function(e){if(i){console.debug("layoutNodes:");for(var t=0;t<e.nodeSize;t++){var r=e.layoutNodes[t],n="\nindex: "+t+"\nId: "+r.id+"\nChildren: "+r.children.toString()+"\nparentId: "+r.parentId+"\npositionX: "+r.positionX+"\npositionY: "+r.positionY+"\nOffsetX: "+r.offsetX+"\nOffsetY: "+r.offsetY+"\npadLeft: "+r.padLeft+"\npadRight: "+r.padRight+"\npadTop: "+r.padTop+"\npadBottom: "+r.padBottom;console.debug(n)}console.debug("idToIndex");for(var t in e.idToIndex)console.debug("Id: "+t+"\nIndex: "+e.idToIndex[t]);console.debug("Graph Set");for(var a=e.graphSet,t=0;t<a.length;t++)console.debug("Set : "+t+": "+a[t].toString());for(var n="IndexToGraph",t=0;t<e.indexToGraph.length;t++)n+="\nIndex : "+t+" Graph: "+e.indexToGraph[t];console.debug(n),n="Layout Edges";for(var t=0;t<e.layoutEdges.length;t++){var o=e.layoutEdges[t];n+="\nEdge Index: "+t+" ID: "+o.id+" SouceID: "+o.sourceId+" TargetId: "+o.targetId+" Ideal Length: "+o.idealLength}console.debug(n),n="nodeSize: "+e.nodeSize,n+="\nedgeSize: "+e.edgeSize,n+="\ntemperature: "+e.temperature,console.debug(n)}},f=function(e,t){for(var r=e.clientWidth,n=e.clientHeight,i=0;i<e.nodeSize;i++){var a=e.layoutNodes[i];0!==a.children.length||a.isLocked||(a.positionX=Math.random()*r,a.positionY=Math.random()*n)}},v=function(e,t,r){var n=r.layout,i=r.eles.nodes(),a=e.boundingBox,o={x1:1/0,x2:-(1/0),y1:1/0,y2:-(1/0)};r.boundingBox&&(i.forEach(function(t){var r=e.layoutNodes[e.idToIndex[t.data("id")]];o.x1=Math.min(o.x1,r.positionX),o.x2=Math.max(o.x2,r.positionX),o.y1=Math.min(o.y1,r.positionY),o.y2=Math.max(o.y2,r.positionY)}),o.w=o.x2-o.x1,o.h=o.y2-o.y1),i.positions(function(t,n){var i=e.layoutNodes[e.idToIndex[n.data("id")]];if(r.boundingBox){var s=(i.positionX-o.x1)/o.w,l=(i.positionY-o.y1)/o.h;return{x:a.x1+s*a.w,y:a.y1+l*a.h}}return{x:i.positionX,y:i.positionY}}),!0!==e.ready&&(e.ready=!0,n.one("layoutready",r.ready),n.trigger({type:"layoutready",layout:this}))};t.exports=n},{"../../is":83,"../../math":85,"../../thread":98,"../../util":100}],52:[function(e,t,r){"use strict";function n(e){this.options=i.extend({},o,e)}var i=e("../../util"),a=e("../../math"),o={fit:!0,padding:30,boundingBox:void 0,avoidOverlap:!0,avoidOverlapPadding:10,condense:!1,rows:void 0,cols:void 0,position:function(e){},sort:void 0,animate:!1,animationDuration:500,animationEasing:void 0,ready:void 0,stop:void 0};n.prototype.run=function(){var e=this.options,t=e,r=e.cy,n=t.eles,i=n.nodes().not(":parent");t.sort&&(i=i.sort(t.sort));var o=a.makeBoundingBox(t.boundingBox?t.boundingBox:{x1:0,y1:0,w:r.width(),h:r.height()});if(0===o.h||0===o.w)i.layoutPositions(this,t,function(){return{x:o.x1,y:o.y1}});else{var s=i.size(),l=Math.sqrt(s*o.h/o.w),u=Math.round(l),c=Math.round(o.w/o.h*l),d=function(e){if(null==e)return Math.min(u,c);var t=Math.min(u,c);t==u?u=e:c=e},h=function(e){if(null==e)return Math.max(u,c);var t=Math.max(u,c);t==u?u=e:c=e},p=t.rows,f=null!=t.cols?t.cols:t.columns;if(null!=p&&null!=f)u=p,c=f;else if(null!=p&&null==f)u=p,c=Math.ceil(s/u);else if(null==p&&null!=f)c=f,u=Math.ceil(s/c);else if(c*u>s){var v=d(),g=h();(v-1)*g>=s?d(v-1):(g-1)*v>=s&&h(g-1)}else for(;s>c*u;){var v=d(),g=h();(g+1)*v>=s?h(g+1):d(v+1)}var y=o.w/c,m=o.h/u;if(t.condense&&(y=0,m=0),t.avoidOverlap)for(var b=0;b<i.length;b++){var x=i[b],w=x._private.position;null!=w.x&&null!=w.y||(w.x=0,w.y=0);var E=x.boundingBox(),_=t.avoidOverlapPadding,P=E.w+_,S=E.h+_;y=Math.max(y,P),m=Math.max(m,S)}for(var k={},T=function(e,t){return!!k["c-"+e+"-"+t]},D=function(e,t){k["c-"+e+"-"+t]=!0},C=0,M=0,N=function(){M++,M>=c&&(M=0,C++)},B={},b=0;b<i.length;b++){var x=i[b],z=t.position(x);if(z&&(void 0!==z.row||void 0!==z.col)){var w={row:z.row,col:z.col};if(void 0===w.col)for(w.col=0;T(w.row,w.col);)w.col++;else if(void 0===w.row)for(w.row=0;T(w.row,w.col);)w.row++;B[x.id()]=w,D(w.row,w.col)}}var I=function(e,t){var r,n;if(t.locked()||t.isParent())return!1;var i=B[t.id()];if(i)r=i.col*y+y/2+o.x1,n=i.row*m+m/2+o.y1;else{for(;T(C,M);)N();r=M*y+y/2+o.x1,n=C*m+m/2+o.y1,D(C,M),N()}return{x:r,y:n}};i.layoutPositions(this,t,I)}return this},t.exports=n},{"../../math":85,"../../util":100}],53:[function(e,t,r){"use strict";t.exports=[{name:"breadthfirst",impl:e("./breadthfirst")},{name:"circle",impl:e("./circle")},{name:"concentric",impl:e("./concentric")},{name:"cose",impl:e("./cose")},{name:"grid",impl:e("./grid")},{name:"null",impl:e("./null")},{name:"preset",impl:e("./preset")},{name:"random",impl:e("./random")}]},{"./breadthfirst":48,"./circle":49,"./concentric":50,"./cose":51,"./grid":52,"./null":54,"./preset":55,"./random":56}],54:[function(e,t,r){"use strict";function n(e){this.options=i.extend({},a,e)}var i=e("../../util"),a={ready:function(){},stop:function(){}};n.prototype.run=function(){var e=this.options,t=e.eles,r=this;e.cy;return r.trigger("layoutstart"),t.nodes().positions(function(){return{x:0,y:0}}),r.one("layoutready",e.ready),r.trigger("layoutready"),r.one("layoutstop",e.stop),r.trigger("layoutstop"),this},n.prototype.stop=function(){return this},t.exports=n},{"../../util":100}],55:[function(e,t,r){"use strict";function n(e){this.options=i.extend({},o,e)}var i=e("../../util"),a=e("../../is"),o={positions:void 0,zoom:void 0,pan:void 0,fit:!0,padding:30,animate:!1,animationDuration:500,animationEasing:void 0,ready:void 0,stop:void 0};n.prototype.run=function(){function e(e){if(null==t.positions)return null;if(i)return t.positions.apply(e,[e]);var r=t.positions[e._private.data.id];return null==r?null:r}var t=this.options,r=t.eles,n=r.nodes(),i=a.fn(t.positions);return n.layoutPositions(this,t,function(t,r){var n=e(r);return r.locked()||null==n?!1:n}),this},t.exports=n},{"../../is":83,"../../util":100}],56:[function(e,t,r){"use strict";function n(e){this.options=i.extend({},o,e)}var i=e("../../util"),a=e("../../math"),o={fit:!0,padding:30,boundingBox:void 0,animate:!1,animationDuration:500,animationEasing:void 0,ready:void 0,stop:void 0};n.prototype.run=function(){var e=this.options,t=e.cy,r=e.eles,n=r.nodes().not(":parent"),i=a.makeBoundingBox(e.boundingBox?e.boundingBox:{x1:0,y1:0,w:t.width(),h:t.height()}),o=function(e,t){return{x:i.x1+Math.round(Math.random()*i.w),y:i.y1+Math.round(Math.random()*i.h)}};return n.layoutPositions(this,e,o),this},t.exports=n},{"../../math":85,"../../util":100}],57:[function(e,t,r){"use strict";var n=e("../../../math"),i=e("../../../is"),a=e("../../../util"),o={};o.arrowShapeWidth=.3,o.registerArrowShapes=function(){var e=this.arrowShapes={},t=this,r=function(e,t,r,n,i,a){var o=i.x-r/2-a,s=i.x+r/2+a,l=i.y-r/2-a,u=i.y+r/2+a,c=e>=o&&s>=e&&t>=l&&u>=t;return c},o=function(e,t,r,n,i){var a=e*Math.cos(n)-t*Math.sin(n),o=e*Math.sin(n)+t*Math.cos(n),s=a*r,l=o*r,u=s+i.x,c=l+i.y;return{x:u,y:c}},s=function(e,t,r,n){for(var i=[],a=0;a<e.length;a+=2){var s=e[a],l=e[a+1];i.push(o(s,l,t,r,n))}return i},l=function(e){for(var t=[],r=0;r<e.length;r++){var n=e[r];t.push(n.x,n.y)}return t},u=function(o,u){i.string(u)&&(u=e[u]),e[o]=a.extend({name:o,points:[-.15,-.3,.15,-.3,.15,.3,-.15,.3],collide:function(e,t,r,i,a,o){var u=l(s(this.points,r+2*o,i,a)),c=n.pointInsidePolygonPoints(e,t,u);return c},roughCollide:r,draw:function(e,r,n,i){var a=s(this.points,r,n,i);t.arrowShapeImpl("polygon")(e,a)},spacing:function(e){return 0},gap:function(e){return 2*e.pstyle("width").pfValue}},u)};u("none",{collide:a.falsify,roughCollide:a.falsify,draw:a.noop,spacing:a.zeroify,gap:a.zeroify}),u("triangle",{points:[-.15,-.3,0,0,.15,-.3]}),u("arrow","triangle"),u("triangle-backcurve",{points:e.triangle.points,controlPoint:[0,-.15],roughCollide:r,draw:function(e,r,n,i){var a=s(this.points,r,n,i),l=this.controlPoint,u=o(l[0],l[1],r,n,i);t.arrowShapeImpl(this.name)(e,a,u)},gap:function(e){return e.pstyle("width").pfValue}}),u("triangle-tee",{points:[-.15,-.3,0,0,.15,-.3,-.15,-.3],pointsTee:[-.15,-.4,-.15,-.5,.15,-.5,.15,-.4],collide:function(e,t,r,i,a,o){var u=l(s(this.points,r+2*o,i,a)),c=l(s(this.pointsTee,r+2*o,i,a)),d=n.pointInsidePolygonPoints(e,t,u)||n.pointInsidePolygonPoints(e,t,c);return d},draw:function(e,r,n,i){var a=s(this.points,r,n,i),o=s(this.pointsTee,r,n,i);t.arrowShapeImpl(this.name)(e,a,o)}}),u("vee",{points:[-.15,-.3,0,0,.15,-.3,0,-.15],gap:function(e){return e.pstyle("width").pfValue}}),u("circle",{radius:.15,collide:function(e,t,r,n,i,a){var o=i,s=Math.pow(o.x-e,2)+Math.pow(o.y-t,2)<=Math.pow((r+2*a)*this.radius,2);return s},draw:function(e,r,n,i){t.arrowShapeImpl(this.name)(e,i.x,i.y,this.radius*r)},spacing:function(e){return t.getArrowWidth(e.pstyle("width").pfValue)*this.radius}}),u("inhibitor",{points:[-.15,0,-.15,-.1,.15,-.1,.15,0],spacing:function(e){return 1},gap:function(e){return 1}}),u("tee","inhibitor"),u("square",{points:[-.15,0,.15,0,.15,-.3,-.15,-.3]}),u("diamond",{points:[-.15,-.15,0,-.3,.15,-.15,0,0],gap:function(e){return e.pstyle("width").pfValue}})},t.exports=o},{"../../../is":83,"../../../math":85,"../../../util":100}],58:[function(e,t,r){"use strict";function n(e,t,r){for(var n=function(e,t,r,n){return i.qbezierAt(e,t,r,n)},a=t._private,o=a.rstyle.bezierPts,s=0;s<e.bezierProjPcts.length;s++){var l=e.bezierProjPcts[s];o.push({x:n(r[0],r[2],r[4],l),y:n(r[1],r[3],r[5],l)})}}var i=e("../../../math"),a=e("../../../is"),o=e("../../../util"),s=e("../../../collection/zsort"),l={};l.registerCalculationListeners=function(){var e=this.cy,t=e.collection(),r=this,n=function(e,r){t.merge(e);for(var n=0;n<e.length;n++){var i=e[n],a=i._private,o=a.rstyle;o.clean=!1,a.bbCache=null;var s=o.dirtyEvents=o.dirtyEvents||{length:0};s[r.type]||(s[r.type]=!0,s.length++)}};r.binder(e).on("position.* style.* free.*","node",function(t){var r=t.cyTarget;if(n(r,t),n(r.connectedEdges(),t),e.hasCompoundNodes()){var i=r.parents();n(i,t),n(i.connectedEdges(),t)}}).on("add.* background.*","node",function(e){var t=e.cyTarget;n(t,e)}).on("add.* style.*","edge",function(e){var t=e.cyTarget;n(t,e),n(t.parallelEdges(),e)}).on("remove.*","edge",function(e){for(var t=e.cyTarget,r=t.parallelEdges(),i=0;i<r.length;i++){var a=r[i];a.removed()||n(a,e)}});var i=function(n){if(n){var i=r.onUpdateEleCalcsFns;if(i)for(var a=0;a<i.length;a++){var o=i[a];o(n,t)}r.recalculateRenderedStyle(t,!1);for(var a=0;a<t.length;a++)t[a]._private.rstyle.dirtyEvents=null;t=e.collection()}};r.beforeRender(i,r.beforeRenderPriorities.eleCalcs)},l.onUpdateEleCalcs=function(e){var t=this.onUpdateEleCalcsFns=this.onUpdateEleCalcsFns||[];t.push(e)},l.recalculateRenderedStyle=function(e,t){var r=[],n=[];void 0===t&&(t=!0);for(var i=0;i<e.length;i++){var a=e[i],o=a._private,s=o.rstyle;if(!(t&&s.clean||a.removed())){if("nodes"===o.group){var l=o.position;n.push(a),s.nodeX=l.x,s.nodeY=l.y,s.nodeW=a.pstyle("width").pfValue,s.nodeH=a.pstyle("height").pfValue}else r.push(a);s.clean=!0}}this.recalculateEdgeProjections(r),this.recalculateLabelProjections(n,r);for(var i=0;i<r.length;i++){var a=r[i],o=a._private,s=o.rstyle,u=o.rscratch;s.srcX=u.arrowStartX,s.srcY=u.arrowStartY,s.tgtX=u.arrowEndX,s.tgtY=u.arrowEndY,s.midX=u.midX,s.midY=u.midY,s.labelAngle=u.labelAngle,s.sourceLabelAngle=u.sourceLabelAngle,s.targetLabelAngle=u.targetLabelAngle}},l.projectIntoViewport=function(e,t){var r=this.findContainerClientCoords(),n=r[0],i=r[1],a=e-n,o=t-i;return a-=this.cy.pan().x,o-=this.cy.pan().y,a/=this.cy.zoom(),o/=this.cy.zoom(),[a,o]},l.findContainerClientCoords=function(){var e=this.container,t=this.containerBB=this.containerBB||e.getBoundingClientRect();return[t.left,t.top,t.right-t.left,t.bottom-t.top]},l.invalidateContainerClientCoordsCache=function(){this.containerBB=null},l.findNearestElement=function(e,t,r,n){return this.findNearestElements(e,t,r,n)[0]},l.findNearestElements=function(e,t,r,n){function a(e,t){if(e.isNode()){if(h)return;h=e,g.push(e)}if(e.isEdge()&&(null==t||E>t))if(d){if(d.pstyle("z-index").value===e.pstyle("z-index").value)for(var r=0;r<g.length;r++)if(g[r].isEdge()){g[r]=e,d=e,E=null!=t?t:E;break}}else g.push(e),d=e,E=null!=t?t:E}function s(n){var i=n._private;if("no"!==n.pstyle("events").strValue){var o=n.outerWidth()+2*x,s=n.outerHeight()+2*x,l=o/2,u=s/2,c=i.position;if(c.x-l<=e&&e<=c.x+l&&c.y-u<=t&&t<=c.y+u){ +var d=!r||n.visible()&&!n.transparent();if(r&&!d)return;var h=f.nodeShapes[p.getNodeShape(n)];h.checkPoint(e,t,0,o,s,c.x,c.y)&&a(n,0)}}}function l(n){var o=n._private;if("no"!==n.pstyle("events").strValue){var l,u,c=o.rscratch,d=n.pstyle("width").pfValue/2+b,h=d*d,v=2*d,y=o.source,x=o.target,w=!1,E=function(){if(void 0!==u)return u;if(!r)return u=!0,!0;var e=n.visible()&&!n.transparent();return e?(u=!0,!0):(u=!1,!1)};if("segments"===c.edgeType||"straight"===c.edgeType||"haystack"===c.edgeType)for(var _=c.allpts,P=0;P+3<_.length;P+=2)(w=i.inLineVicinity(e,t,_[P],_[P+1],_[P+2],_[P+3],v))&&E()&&h>(l=i.sqdistToFiniteLine(e,t,_[P],_[P+1],_[P+2],_[P+3]))&&a(n,l);else if("bezier"===c.edgeType||"multibezier"===c.edgeType||"self"===c.edgeType||"compound"===c.edgeType)for(var _=c.allpts,P=0;P+5<c.allpts.length;P+=4)(w=i.inBezierVicinity(e,t,_[P],_[P+1],_[P+2],_[P+3],_[P+4],_[P+5],v))&&E()&&h>(l=i.sqdistToQuadraticBezier(e,t,_[P],_[P+1],_[P+2],_[P+3],_[P+4],_[P+5]))&&a(n,l);if(w&&E())for(var y=y||o.source,x=x||o.target,S=n.pstyle("width").pfValue,k=p.getArrowWidth(S),T=[{name:"source",x:c.arrowStartX,y:c.arrowStartY,angle:c.srcArrowAngle},{name:"target",x:c.arrowEndX,y:c.arrowEndY,angle:c.tgtArrowAngle},{name:"mid-source",x:c.midX,y:c.midY,angle:c.midsrcArrowAngle},{name:"mid-target",x:c.midX,y:c.midY,angle:c.midtgtArrowAngle}],P=0;P<T.length;P++){var D=T[P],C=f.arrowShapes[n.pstyle(D.name+"-arrow-shape").value];if(C.roughCollide(e,t,k,D.angle,{x:D.x,y:D.y},b)&&C.collide(e,t,k,D.angle,{x:D.x,y:D.y},b)){a(n);break}}m&&g.length>0&&(s(y),s(x))}}function u(e,t,r){return o.getPrefixedProperty(e,t,r)}function c(r,n){var o,s=r._private,l=w;if(o=n?n+"-":"","no"!==r.pstyle("text-events").strValue){var c=r.pstyle(o+"text-rotation");if("autorotate"===c.strValue||c.pfValue){var d=s.rstyle,h=r.pstyle("text-border-width").pfValue,p=u(d,"labelWidth",n)+h/2+2*l,f=u(d,"labelHeight",n)+h/2+2*l,v=u(d,"labelX",n),g=u(d,"labelY",n),y=u(s.rscratch,"labelAngle",n),m=Math.cos(y),b=Math.sin(y),x=function(e,t){return e-=v,t-=g,{x:e*m-t*b+v,y:e*b+t*m+g}},E=v-p/2,_=v+p/2,P=g-f/2,S=g+f/2,k=x(E,P),T=x(E,S),D=x(_,P),C=x(_,S),M=[k.x,k.y,D.x,D.y,C.x,C.y,T.x,T.y];i.pointInsidePolygonPoints(e,t,M)&&a(r)}else{var N=r.boundingBox({includeLabels:!0,includeNodes:!1,includeEdges:!1});N.x1-=l,N.y1-=l,N.x2+=l,N.y2+=l,N.w=N.x2-N.x1,N.h=N.y2-N.y1,i.inBoundingBox(N,e,t)&&a(r)}}}for(var d,h,p=this,f=this,v=f.getCachedZSortedEles(),g=[],y=f.cy.zoom(),m=f.cy.hasCompoundNodes(),b=(n?24:8)/y,x=(n?8:2)/y,w=(n?8:2)/y,E=1/0,_=v.length-1;_>=0;_--){var P=v[_];P.isNode()?(s(P),c(P)):(l(P),c(P),c(P,"source"),c(P,"target"))}return g},l.getAllInBox=function(e,t,r,n){var a=this.getCachedZSortedEles(),o=a.nodes,s=a.edges,l=[],u=Math.min(e,r),c=Math.max(e,r),d=Math.min(t,n),h=Math.max(t,n);e=u,r=c,t=d,n=h;for(var p=i.makeBoundingBox({x1:e,y1:t,x2:r,y2:n}),f=0;f<o.length;f++){var v=o[f],g=v.boundingBox({includeNodes:!0,includeEdges:!1,includeLabels:!1,includeShadows:!1});i.boundingBoxesIntersect(p,g)&&l.push(o[f])}for(var y=0;y<s.length;y++){var m=s[y],b=m._private,x=b.rscratch;if((null==x.startX||null==x.startY||i.inBoundingBox(p,x.startX,x.startY))&&(null==x.endX||null==x.endY||i.inBoundingBox(p,x.endX,x.endY)))if("bezier"===x.edgeType||"multibezier"===x.edgeType||"self"===x.edgeType||"compound"===x.edgeType||"segments"===x.edgeType||"haystack"===x.edgeType){for(var w=b.rstyle.bezierPts||b.rstyle.linePts||b.rstyle.haystackPts,E=!0,f=0;f<w.length;f++)if(!i.pointInBoundingBox(p,w[f])){E=!1;break}E&&l.push(m)}else"haystack"!==x.edgeType&&"straight"!==x.edgeType||l.push(m)}return l},l.getNodeShape=function(e){var t=this,r=e.pstyle("shape").value;if(e.isParent())return"rectangle"===r||"roundrectangle"===r?r:"rectangle";if("polygon"===r){var n=e.pstyle("shape-polygon-points").value;return t.nodeShapes.makePolygon(n).name}return r},l.updateCachedZSortedEles=function(){this.getCachedZSortedEles(!0)},l.updateCachedGrabbedEles=function(){var e=this.cachedZSortedEles;e.drag=[],e.nondrag=[];for(var t,r=0;r<e.length;r++){var n=e[r],i=n._private.rscratch;i.isGrabTarget&&!n.isParent()?t=n:i.inDragLayer?e.drag.push(n):e.nondrag.push(n)}t&&e.drag.push(t)},l.getCachedZSortedEles=function(e){if(e||!this.cachedZSortedEles){var t=this.cy.mutableElements(),r=[];r.nodes=[],r.edges=[];for(var n=0;n<t.length;n++){var i=t[n];(i.animated()||i.visible()&&!i.transparent())&&(r.push(i),i.isNode()?r.nodes.push(i):r.edges.push(i))}r.sort(s),this.cachedZSortedEles=r,this.updateCachedGrabbedEles()}else r=this.cachedZSortedEles;return r},l.projectLines=function(e){var t=e._private,r=t.rscratch,i=r.edgeType;if(t.rstyle.bezierPts=null,t.rstyle.linePts=null,t.rstyle.haystackPts=null,"multibezier"===i||"bezier"===i||"self"===i||"compound"===i)for(var a=(t.rstyle.bezierPts=[],0);a+5<r.allpts.length;a+=4)n(this,e,r.allpts.slice(a,a+6));else if("segments"===i)for(var o=t.rstyle.linePts=[],a=0;a+1<r.allpts.length;a+=2)o.push({x:r.allpts[a],y:r.allpts[a+1]});else if("haystack"===i){var s=r.haystackPts;t.rstyle.haystackPts=[{x:s[0],y:s[1]},{x:s[2],y:s[3]}]}t.rstyle.arrowWidth=this.getArrowWidth(e.pstyle("width").pfValue)*this.arrowShapeWidth},l.projectBezier=l.projectLines,l.recalculateNodeLabelProjection=function(e){var t=e.pstyle("label").strValue;if(!a.emptyString(t)){var r,n,i=e._private,o=e.width(),s=e.height(),l=e.pstyle("padding-left").pfValue,u=e.pstyle("padding-right").pfValue,c=e.pstyle("padding-top").pfValue,d=e.pstyle("padding-bottom").pfValue,h=i.position,p=e.pstyle("text-halign").strValue,f=e.pstyle("text-valign").strValue,v=i.rscratch,g=i.rstyle;switch(p){case"left":r=h.x-o/2-l;break;case"right":r=h.x+o/2+u;break;default:r=h.x}switch(f){case"top":n=h.y-s/2-c;break;case"bottom":n=h.y+s/2+d;break;default:n=h.y}v.labelX=r,v.labelY=n,g.labelX=r,g.labelY=n,this.applyLabelDimensions(e)}},l.recalculateEdgeLabelProjections=function(e){var t,r=e._private,n=r.rscratch,a=this,s={mid:e.pstyle("label").strValue,source:e.pstyle("source-label").strValue,target:e.pstyle("target-label").strValue};if(s.mid||s.source||s.target){t={x:n.midX,y:n.midY};var l=function(e,t,n){o.setPrefixedProperty(r.rscratch,e,t,n),o.setPrefixedProperty(r.rstyle,e,t,n)};l("labelX",null,t.x),l("labelY",null,t.y);var u=function(){function e(e,t,r,n,a){var o=i.dist(t,r),s=e.segments[e.segments.length-1],l={p0:t,p1:r,t0:n,t1:a,startDist:s?s.startDist+s.length:0,length:o};e.segments.push(l),e.length+=o}if(u.cache)return u.cache;for(var t=[],o=0;o+5<n.allpts.length;o+=4){var s={x:n.allpts[o],y:n.allpts[o+1]},l={x:n.allpts[o+2],y:n.allpts[o+3]},c={x:n.allpts[o+4],y:n.allpts[o+5]};t.push({p0:s,p1:l,p2:c,startDist:0,length:0,segments:[]})}for(var d=r.rstyle.bezierPts,h=a.bezierProjPcts.length,o=0;o<t.length;o++){var p=t[o],f=t[o-1];f&&(p.startDist=f.startDist+f.length),e(p,p.p0,d[o*h],0,a.bezierProjPcts[0]);for(var v=0;h-1>v;v++)e(p,d[o*h+v],d[o*h+v+1],a.bezierProjPcts[v],a.bezierProjPcts[v+1]);e(p,d[o*h+h-1],p.p2,a.bezierProjPcts[h-1],1)}return u.cache=t},c=function(r){var a,o="source"===r;if(s[r]){var c=e.pstyle(r+"-text-offset").pfValue,d=function(e,t){var r=t.x-e.x,n=t.y-e.y;return Math.atan(n/r)},h=function(e,t,r,n){var a=i.bound(0,n-.001,1),o=i.bound(0,n+.001,1),s=i.qbezierPtAt(e,t,r,a),l=i.qbezierPtAt(e,t,r,o);return d(s,l)};switch(n.edgeType){case"self":case"compound":case"bezier":case"multibezier":for(var p,f=u(),v=0,g=0,y=0;y<f.length;y++){for(var m=f[o?y:f.length-1-y],b=0;b<m.segments.length;b++){var x=m.segments[o?b:m.segments.length-1-b],w=y===f.length-1&&b===m.segments.length-1;if(v=g,g+=x.length,g>=c||w){p={cp:m,segment:x};break}}if(p)break}var m=p.cp,x=p.segment,E=(c-v)/x.length,_=x.t1-x.t0,P=o?x.t0+_*E:x.t1-_*E;P=i.bound(0,P,1),t=i.qbezierPtAt(m.p0,m.p1,m.p2,P),a=h(m.p0,m.p1,m.p2,P,t);break;case"straight":case"segments":case"haystack":for(var S,k,T,D,C=0,M=n.allpts.length,y=0;M>y+3&&(o?(T={x:n.allpts[y],y:n.allpts[y+1]},D={x:n.allpts[y+2],y:n.allpts[y+3]}):(T={x:n.allpts[M-2-y],y:n.allpts[M-1-y]},D={x:n.allpts[M-4-y],y:n.allpts[M-3-y]}),S=i.dist(T,D),k=C,C+=S,!(C>=c));y+=2);var N=c-k,P=N/S;P=i.bound(0,P,1),t=i.lineAt(T,D,P),a=d(T,D)}l("labelX",r,t.x),l("labelY",r,t.y),l("labelAutoAngle",r,a)}};c("source"),c("target"),this.applyLabelDimensions(e)}},l.applyLabelDimensions=function(e){this.applyPrefixedLabelDimensions(e),e.isEdge()&&(this.applyPrefixedLabelDimensions(e,"source"),this.applyPrefixedLabelDimensions(e,"target"))},l.applyPrefixedLabelDimensions=function(e,t){var r=e._private,n=this.getLabelText(e,t),i=this.calculateLabelDimensions(e,n);o.setPrefixedProperty(r.rstyle,"labelWidth",t,i.width),o.setPrefixedProperty(r.rscratch,"labelWidth",t,i.width),o.setPrefixedProperty(r.rstyle,"labelHeight",t,i.height),o.setPrefixedProperty(r.rscratch,"labelHeight",t,i.height)},l.getLabelText=function(e,t){var r=e._private,n=t?t+"-":"",i=e.pstyle(n+"label").strValue,a=e.pstyle("text-transform").value,s=function(e,n){return n?(o.setPrefixedProperty(r.rscratch,e,t,n),n):o.getPrefixedProperty(r.rscratch,e,t)};if("none"==a||("uppercase"==a?i=i.toUpperCase():"lowercase"==a&&(i=i.toLowerCase())),"wrap"===e.pstyle("text-wrap").value){var l=s("labelKey");if(l&&s("labelWrapKey")===l)return s("labelWrapCachedText");for(var u=i.split("\n"),c=e.pstyle("text-max-width").pfValue,d=[],h=0;h<u.length;h++){var p=u[h],f=this.calculateLabelDimensions(e,p,"line="+p),v=f.width;if(v>c){for(var g=p.split(/\s+/),y="",m=0;m<g.length;m++){var b=g[m],x=0===y.length?b:y+" "+b,w=this.calculateLabelDimensions(e,x,"testLine="+x),E=w.width;c>=E?y+=b+" ":(d.push(y),y=b+" ")}y.match(/^\s+$/)||d.push(y)}else d.push(p)}s("labelWrapCachedLines",d),i=s("labelWrapCachedText",d.join("\n")),s("labelWrapKey",l)}return i},l.calculateLabelDimensions=function(e,t,r){var n=this,i=e._private.labelStyleKey+"$@$"+t;r&&(i+="$@$"+r);var a=n.labelDimCache||(n.labelDimCache={});if(a[i])return a[i];var o=1,s=e.pstyle("font-style").strValue,l=o*e.pstyle("font-size").pfValue+"px",u=e.pstyle("font-family").strValue,c=e.pstyle("font-weight").strValue,d=this.labelCalcDiv;d||(d=this.labelCalcDiv=document.createElement("div"),document.body.appendChild(d));var h=d.style;return h.fontFamily=u,h.fontStyle=s,h.fontSize=l,h.fontWeight=c,h.position="absolute",h.left="-9999px",h.top="-9999px",h.zIndex="-1",h.visibility="hidden",h.pointerEvents="none",h.padding="0",h.lineHeight="1","wrap"===e.pstyle("text-wrap").value?h.whiteSpace="pre":h.whiteSpace="normal",d.textContent=t,a[i]={width:Math.ceil(d.clientWidth/o),height:Math.ceil(d.clientHeight/o)},a[i]},l.recalculateLabelProjections=function(e,t){for(var r=0;r<e.length;r++)this.recalculateNodeLabelProjection(e[r]);for(var r=0;r<t.length;r++)this.recalculateEdgeLabelProjections(t[r])},l.recalculateEdgeProjections=function(e){this.findEdgeControlPoints(e)},l.findEdgeControlPoints=function(e){if(e&&0!==e.length){for(var t,r=this,n=r.cy,o=n.hasCompoundNodes(),s={},l=[],u=[],c=0;c<e.length;c++){var d=e[c],h=d._private,p=h.data,f=d.pstyle("curve-style").value,v="unbundled-bezier"===f||"segments"===f;if("none"!==d.pstyle("display").value)if("haystack"!==f){var g=p.source,y=p.target;t=g>y?y+"$-$"+g:g+"$-$"+y,v&&(t="unbundled$-$"+p.id),null==s[t]&&(s[t]=[],l.push(t)),s[t].push(d),v&&(s[t].hasUnbundled=!0)}else u.push(d)}for(var m,b,x,w,E,_,P,S,k,T,D,C,M,N,B=0;B<l.length;B++){t=l[B];var z=s[t];if(z.sort(function(e,t){return e.poolIndex()-t.poolIndex()}),m=z[0]._private.source,b=z[0]._private.target,!z.hasUnbundled&&m.id()>b.id()){var I=m;m=b,b=I}if(x=m._private,w=b._private,E=x.position,_=w.position,P=m.outerWidth(),S=m.outerHeight(),k=b.outerWidth(),T=b.outerHeight(),D=r.nodeShapes[this.getNodeShape(m)],C=r.nodeShapes[this.getNodeShape(b)],N=!1,z.length>1&&m!==b||z.hasUnbundled){var L=D.intersectLine(E.x,E.y,P,S,_.x,_.y,0),O=C.intersectLine(_.x,_.y,k,T,E.x,E.y,0),A={x1:L[0],x2:O[0],y1:L[1],y2:O[1]},R={x1:E.x,x2:_.x,y1:E.y,y2:_.y},q=O[1]-L[1],V=O[0]-L[0],F=Math.sqrt(V*V+q*q),j={x:V,y:q},X={x:j.x/F,y:j.y/F};M={x:-X.y,y:X.x},C.checkPoint(L[0],L[1],0,k,T,_.x,_.y)&&D.checkPoint(O[0],O[1],0,P,S,E.x,E.y)&&(M={},N=!0)}for(var d,Y,W,c=0;c<z.length;c++){d=z[c],Y=d._private,W=Y.rscratch;var $=W.lastEdgeIndex,H=c,U=W.lastNumEdges,Z=z.length,f=d.pstyle("curve-style").value,G=d.pstyle("control-point-distances"),Q=d.pstyle("control-point-weights"),K=G&&Q?Math.min(G.value.length,Q.value.length):1,J=d.pstyle("control-point-step-size").pfValue,ee=G?G.pfValue[0]:void 0,te=Q.value[0],v="unbundled-bezier"===f||"segments"===f,re=W.lastSrcCtlPtX,ne=E.x,ie=W.lastSrcCtlPtY,ae=E.y,oe=W.lastSrcCtlPtW,se=m.outerWidth(),le=W.lastSrcCtlPtH,ue=m.outerHeight(),ce=W.lastTgtCtlPtX,de=_.x,he=W.lastTgtCtlPtY,pe=_.y,fe=W.lastTgtCtlPtW,ve=b.outerWidth(),ge=W.lastTgtCtlPtH,ye=b.outerHeight(),me=W.lastW,be=d.pstyle("control-point-step-size").pfValue,xe=d.pstyle("edge-distances").value;if(N?W.badBezier=!0:W.badBezier=!1,re!==ne||ie!==ae||oe!==se||le!==ue||ce!==de||he!==pe||fe!==ve||ge!==ye||me!==be||!($===H&&U===Z||v)){if(W.lastSrcCtlPtX=ne,W.lastSrcCtlPtY=ae,W.lastSrcCtlPtW=se,W.lastSrcCtlPtH=ue,W.lastTgtCtlPtX=de,W.lastTgtCtlPtY=pe,W.lastTgtCtlPtW=ve,W.lastTgtCtlPtH=ye,W.lastEdgeIndex=H,W.lastNumEdges=Z,W.lastWidth=be,m===b){W.edgeType="self";var we=c,Ee=J;v&&(we=0,Ee=ee),W.ctrlpts=[E.x,E.y-(1+Math.pow(S,1.12)/100)*Ee*(we/3+1),E.x-(1+Math.pow(P,1.12)/100)*Ee*(we/3+1),E.y]}else if(o&&(m.isParent()||m.isChild()||b.isParent()||b.isChild())&&(m.parents().anySame(b)||b.parents().anySame(m))){W.edgeType="compound",W.badBezier=!1;var we=c,Ee=J;v&&(we=0,Ee=ee);var _e=50,Pe={x:E.x-P/2,y:E.y-S/2},Se={x:_.x-k/2,y:_.y-T/2},ke={x:Math.min(Pe.x,Se.x),y:Math.min(Pe.y,Se.y)},Te=.5,De=Math.max(Te,Math.log(.01*P)),Ce=Math.max(Te,Math.log(.01*k));W.ctrlpts=[ke.x,ke.y-(1+Math.pow(_e,1.12)/100)*Ee*(we/3+1)*De,ke.x-(1+Math.pow(_e,1.12)/100)*Ee*(we/3+1)*Ce,ke.y]}else if("segments"===f){W.edgeType="segments",W.segpts=[];for(var Me=d.pstyle("segment-weights").pfValue,Ne=d.pstyle("segment-distances").pfValue,Be=Math.min(Me.length,Ne.length),ze=0;Be>ze;ze++){var Ie=Me[ze],Le=Ne[ze],Oe=1-Ie,Ae=Ie,Re="node-position"===xe?R:A,qe={x:Re.x1*Oe+Re.x2*Ae,y:Re.y1*Oe+Re.y2*Ae};W.segpts.push(qe.x+M.x*Le,qe.y+M.y*Le)}}else if(z.length%2!==1||c!==Math.floor(z.length/2)||v){var Ve=v;W.edgeType=Ve?"multibezier":"bezier",W.ctrlpts=[];for(var Fe=0;K>Fe;Fe++){var je,Xe=(.5-z.length/2+c)*J,Ye=i.signum(Xe);Ve&&(ee=G?G.pfValue[Fe]:J,te=Q.value[Fe]),je=v?ee:void 0!==ee?Ye*ee:void 0;var We=void 0!==je?je:Xe,Oe=1-te,Ae=te,Re="node-position"===xe?R:A,qe={x:Re.x1*Oe+Re.x2*Ae,y:Re.y1*Oe+Re.y2*Ae};W.ctrlpts.push(qe.x+M.x*We,qe.y+M.y*We)}}else W.edgeType="straight";this.findEndpoints(d);var $e=!a.number(W.startX)||!a.number(W.startY),He=!a.number(W.arrowStartX)||!a.number(W.arrowStartY),Ue=!a.number(W.endX)||!a.number(W.endY),Ze=!a.number(W.arrowEndX)||!a.number(W.arrowEndY),Ge=3,Qe=this.getArrowWidth(d.pstyle("width").pfValue)*this.arrowShapeWidth,Ke=Ge*Qe;if("bezier"===W.edgeType){var Je=i.dist({x:W.ctrlpts[0],y:W.ctrlpts[1]},{x:W.startX,y:W.startY}),et=Ke>Je,tt=i.dist({x:W.ctrlpts[0],y:W.ctrlpts[1]},{x:W.endX,y:W.endY}),rt=Ke>tt,nt=!1;if($e||He||et){nt=!0;var it={x:W.ctrlpts[0]-E.x,y:W.ctrlpts[1]-E.y},at=Math.sqrt(it.x*it.x+it.y*it.y),ot={x:it.x/at,y:it.y/at},st=Math.max(P,S),lt={x:W.ctrlpts[0]+2*ot.x*st,y:W.ctrlpts[1]+2*ot.y*st},ut=D.intersectLine(E.x,E.y,P,S,lt.x,lt.y,0);et?(W.ctrlpts[0]=W.ctrlpts[0]+ot.x*(Ke-Je),W.ctrlpts[1]=W.ctrlpts[1]+ot.y*(Ke-Je)):(W.ctrlpts[0]=ut[0]+ot.x*Ke,W.ctrlpts[1]=ut[1]+ot.y*Ke)}if(Ue||Ze||rt){nt=!0;var it={x:W.ctrlpts[0]-_.x,y:W.ctrlpts[1]-_.y},at=Math.sqrt(it.x*it.x+it.y*it.y),ot={x:it.x/at,y:it.y/at},st=Math.max(P,S),lt={x:W.ctrlpts[0]+2*ot.x*st,y:W.ctrlpts[1]+2*ot.y*st},ct=C.intersectLine(_.x,_.y,k,T,lt.x,lt.y,0);rt?(W.ctrlpts[0]=W.ctrlpts[0]+ot.x*(Ke-tt),W.ctrlpts[1]=W.ctrlpts[1]+ot.y*(Ke-tt)):(W.ctrlpts[0]=ct[0]+ot.x*Ke,W.ctrlpts[1]=ct[1]+ot.y*Ke)}nt&&this.findEndpoints(d)}if("multibezier"===W.edgeType||"bezier"===W.edgeType||"self"===W.edgeType||"compound"===W.edgeType){W.allpts=[],W.allpts.push(W.startX,W.startY);for(var Fe=0;Fe+1<W.ctrlpts.length;Fe+=2)W.allpts.push(W.ctrlpts[Fe],W.ctrlpts[Fe+1]),Fe+3<W.ctrlpts.length&&W.allpts.push((W.ctrlpts[Fe]+W.ctrlpts[Fe+2])/2,(W.ctrlpts[Fe+1]+W.ctrlpts[Fe+3])/2);W.allpts.push(W.endX,W.endY);var dt,ht;W.ctrlpts.length/2%2===0?(dt=W.allpts.length/2-1,W.midX=W.allpts[dt],W.midY=W.allpts[dt+1]):(dt=W.allpts.length/2-3,ht=.5,W.midX=i.qbezierAt(W.allpts[dt],W.allpts[dt+2],W.allpts[dt+4],ht),W.midY=i.qbezierAt(W.allpts[dt+1],W.allpts[dt+3],W.allpts[dt+5],ht))}else if("straight"===W.edgeType)W.allpts=[W.startX,W.startY,W.endX,W.endY],W.midX=(W.startX+W.endX+W.arrowStartX+W.arrowEndX)/4,W.midY=(W.startY+W.endY+W.arrowStartY+W.arrowEndY)/4;else if("segments"===W.edgeType)if(W.allpts=[],W.allpts.push(W.startX,W.startY),W.allpts.push.apply(W.allpts,W.segpts),W.allpts.push(W.endX,W.endY),W.segpts.length%4===0){var pt=W.segpts.length/2,ft=pt-2;W.midX=(W.segpts[ft]+W.segpts[pt])/2,W.midY=(W.segpts[ft+1]+W.segpts[pt+1])/2}else{var ft=W.segpts.length/2-1;W.midX=W.segpts[ft],W.midY=W.segpts[ft+1]}this.projectLines(d),this.calculateArrowAngles(d),this.recalculateEdgeLabelProjections(d),this.calculateLabelAngles(d)}}}for(var c=0;c<u.length;c++){var d=u[c],h=d._private,vt=h.rscratch,W=vt;if(!vt.haystack){var gt=2*Math.random()*Math.PI;vt.source={x:Math.cos(gt),y:Math.sin(gt)};var gt=2*Math.random()*Math.PI;vt.target={x:Math.cos(gt),y:Math.sin(gt)}}var m=h.source,b=h.target,E=m._private.position,_=b._private.position,P=m.width(),k=b.width(),S=m.height(),T=b.height(),st=d.pstyle("haystack-radius").value,yt=st/2;W.haystackPts=W.allpts=[W.source.x*P*yt+E.x,W.source.y*S*yt+E.y,W.target.x*k*yt+_.x,W.target.y*T*yt+_.y],W.midX=(W.allpts[0]+W.allpts[2])/2,W.midY=(W.allpts[1]+W.allpts[3])/2,vt.edgeType="haystack",vt.haystack=!0,this.projectLines(d),this.calculateArrowAngles(d),this.recalculateEdgeLabelProjections(d),this.calculateLabelAngles(d)}return s}};var u=function(e,t){return Math.atan2(t,e)-Math.PI/2};l.calculateArrowAngles=function(e){var t,r,n,a,o,s,l=e._private.rscratch,c="haystack"===l.edgeType,d="multibezier"===l.edgeType,h="segments"===l.edgeType,p="compound"===l.edgeType,f="self"===l.edgeType,v=e._private.source._private.position,g=e._private.target._private.position;c?(n=l.haystackPts[0],a=l.haystackPts[1],o=l.haystackPts[2],s=l.haystackPts[3]):(n=l.arrowStartX,a=l.arrowStartY,o=l.arrowEndX,s=l.arrowEndY),t=v.x-n,r=v.y-a,l.srcArrowAngle=u(t,r);var y=l.midX,m=l.midY;if(c&&(y=(n+o)/2,m=(a+s)/2),t=o-n,r=s-a,f)t=-1,r=1;else if(h){var b=l.allpts;if(b.length/2%2===0){var x=b.length/2,w=x-2;t=b[x]-b[w],r=b[x+1]-b[w+1]}else{var x=b.length/2-1,w=x-2,E=x+2;t=b[x]-b[w],r=b[x+1]-b[w+1]}}else if(d||p){var _,P,S,k,b=l.allpts,T=l.ctrlpts;if(T.length/2%2===0){var D=b.length/2-1,C=D+2,M=C+2;_=i.qbezierAt(b[D],b[C],b[M],0),P=i.qbezierAt(b[D+1],b[C+1],b[M+1],0),S=i.qbezierAt(b[D],b[C],b[M],1e-4),k=i.qbezierAt(b[D+1],b[C+1],b[M+1],1e-4)}else{var C=b.length/2-1,D=C-2,M=C+2;_=i.qbezierAt(b[D],b[C],b[M],.4999),P=i.qbezierAt(b[D+1],b[C+1],b[M+1],.4999),S=i.qbezierAt(b[D],b[C],b[M],.5),k=i.qbezierAt(b[D+1],b[C+1],b[M+1],.5)}t=S-_,r=k-P}if(l.midtgtArrowAngle=u(t,r),l.midDispX=t,l.midDispY=r,t*=-1,r*=-1,h){var b=l.allpts;if(b.length/2%2===0);else{var x=b.length/2-1,E=x+2;t=-(b[E]-b[x]),r=-(b[E+1]-b[x+1])}}l.midsrcArrowAngle=u(t,r),t=g.x-o,r=g.y-s,l.tgtArrowAngle=u(t,r)},l.calculateLabelAngles=function(e){var t=e._private,r=t.rscratch,n=e.isEdge(),i=e.pstyle("text-rotation"),a=i.strValue;"none"===a?r.labelAngle=r.sourceLabelAngle=r.targetLabelAngle=0:n&&"autorotate"===a?(r.labelAngle=Math.atan(r.midDispY/r.midDispX),r.sourceLabelAngle=r.sourceLabelAutoAngle,r.targetLabelAngle=r.targetLabelAutoAngle):"autorotate"===a?r.labelAngle=r.sourceLabelAngle=r.targetLabelAngle=0:r.labelAngle=r.sourceLabelAngle=r.targetLabelAngle=i.pfValue},l.findEndpoints=function(e){var t,r,n,o=this,s=e.source()[0],l=e.target()[0],u=s._private,c=l._private,d=u.position,h=c.position,p=e.pstyle("target-arrow-shape").value,f=e.pstyle("source-arrow-shape").value,v=e._private.rscratch,g=v.edgeType,y="bezier"===g||"multibezier"===g||"self"===g||"compound"===g,m="bezier"!==g,b="straight"===g||"segments"===g,x="segments"===g,w=y||m||b;if(y){var E=[v.ctrlpts[0],v.ctrlpts[1]],_=m?[v.ctrlpts[v.ctrlpts.length-2],v.ctrlpts[v.ctrlpts.length-1]]:E;r=_,n=E}else if(b){var P=x?v.segpts.slice(0,2):[h.x,h.y],S=x?v.segpts.slice(v.segpts.length-2):[d.x,d.y];r=S,n=P}t=o.nodeShapes[this.getNodeShape(l)].intersectLine(h.x,h.y,l.outerWidth(),l.outerHeight(),r[0],r[1],0);var k=i.shortenIntersection(t,r,o.arrowShapes[p].spacing(e)),T=i.shortenIntersection(t,r,o.arrowShapes[p].gap(e));v.endX=T[0],v.endY=T[1],v.arrowEndX=k[0],v.arrowEndY=k[1],t=o.nodeShapes[this.getNodeShape(s)].intersectLine(d.x,d.y,s.outerWidth(),s.outerHeight(),n[0],n[1],0);var D=i.shortenIntersection(t,n,o.arrowShapes[f].spacing(e)),C=i.shortenIntersection(t,n,o.arrowShapes[f].gap(e));v.startX=C[0],v.startY=C[1],v.arrowStartX=D[0],v.arrowStartY=D[1],w&&(a.number(v.startX)&&a.number(v.startY)&&a.number(v.endX)&&a.number(v.endY)?v.badLine=!1:v.badLine=!0)},l.getArrowWidth=l.getArrowHeight=function(e){var t=this.arrowWidthCache=this.arrowWidthCache||{},r=t[e];return r?r:(r=Math.max(Math.pow(13.37*e,.9),29),t[e]=r,r)},t.exports=l},{"../../../collection/zsort":32,"../../../is":83,"../../../math":85,"../../../util":100}],59:[function(e,t,r){"use strict";var n={};n.getCachedImage=function(e,t){var r=this,n=r.imageCache=r.imageCache||{};if(n[e]&&n[e].image)return n[e].image;var i=n[e]=n[e]||{},a=i.image=new Image;return a.addEventListener("load",t),a.crossOrigin="Anonymous",a.src=e,a},t.exports=n},{}],60:[function(e,t,r){"use strict";var n=e("../../../is"),i=e("../../../util"),a=function(e){this.init(e)},o=a,s=o.prototype;s.clientFunctions=["redrawHint","render","renderTo","matchCanvasSize","nodeShapeImpl","arrowShapeImpl"],s.init=function(e){var t=this;t.options=e,t.cy=e.cy,t.container=e.cy.container(),t.selection=[void 0,void 0,void 0,void 0,0],t.bezierProjPcts=[.05,.225,.4,.5,.6,.775,.95],t.hoverData={down:null,last:null,downTime:null,triggerMode:null,dragging:!1,initialPan:[null,null],capture:!1},t.dragData={possibleDragElements:[]},t.touchData={start:null,capture:!1,startPosition:[null,null,null,null,null,null],singleTouchStartTime:null,singleTouchMoved:!0,now:[null,null,null,null,null,null],earlier:[null,null,null,null,null,null]},t.redraws=0,t.showFps=e.showFps,t.hideEdgesOnViewport=e.hideEdgesOnViewport,t.hideLabelsOnViewport=e.hideLabelsOnViewport,t.textureOnViewport=e.textureOnViewport,t.wheelSensitivity=e.wheelSensitivity,t.motionBlurEnabled=e.motionBlur,t.forcedPixelRatio=e.pixelRatio,t.motionBlur=e.motionBlur,t.motionBlurOpacity=e.motionBlurOpacity,t.motionBlurTransparency=1-t.motionBlurOpacity,t.motionBlurPxRatio=1,t.mbPxRBlurry=1,t.minMbLowQualFrames=4,t.fullQualityMb=!1,t.clearedForMotionBlur=[],t.desktopTapThreshold=e.desktopTapThreshold,t.desktopTapThreshold2=e.desktopTapThreshold*e.desktopTapThreshold,t.touchTapThreshold=e.touchTapThreshold,t.touchTapThreshold2=e.touchTapThreshold*e.touchTapThreshold,t.tapholdDuration=500,t.bindings=[],t.beforeRenderCallbacks=[],t.beforeRenderPriorities={animations:400,eleCalcs:300,eleTxrDeq:200,lyrTxrDeq:100},t.registerNodeShapes(),t.registerArrowShapes(),t.registerCalculationListeners(),t.load()},s.notify=function(e){var t,r=this;t=n.array(e.type)?e.type:[e.type];for(var i={},a=0;a<t.length;a++){var o=t[a];i[o]=!0}return i.destroy?void r.destroy():((i.add||i.remove||i.load||i.style)&&r.updateCachedZSortedEles(),i.viewport&&r.redrawHint("select",!0),(i.load||i.resize)&&(r.invalidateContainerClientCoordsCache(),r.matchCanvasSize(r.container)),r.redrawHint("eles",!0),r.redrawHint("drag",!0),this.startRenderLoop(),void this.redraw())},s.destroy=function(){var e=this;e.destroyed=!0,e.cy.stopAnimationLoop();for(var t=0;t<e.bindings.length;t++){var r=e.bindings[t],n=r,i=n.target;(i.off||i.removeEventListener).apply(i,n.args)}if(e.bindings=[],e.beforeRenderCallbacks=[],e.onUpdateEleCalcsFns=[],e.removeObserver&&e.removeObserver.disconnect(),e.styleObserver&&e.styleObserver.disconnect(),e.labelCalcDiv)try{document.body.removeChild(e.labelCalcDiv)}catch(a){}},[e("./arrow-shapes"),e("./coord-ele-math"),e("./images"),e("./load-listeners"),e("./node-shapes"),e("./redraw")].forEach(function(e){i.extend(s,e)}),t.exports=o},{"../../../is":83,"../../../util":100,"./arrow-shapes":57,"./coord-ele-math":58,"./images":59,"./load-listeners":61,"./node-shapes":62,"./redraw":63}],61:[function(e,t,r){"use strict";var n=e("../../../is"),i=e("../../../util"),a=e("../../../math"),o=e("../../../event"),s={};s.registerBinding=function(e,t,r,n){var i=Array.prototype.slice.apply(arguments,[1]),a=this.binder(e);return a.on.apply(a,i)},s.binder=function(e){var t=this,r=function(){var r=arguments;return t.bindings.push({target:e,args:r}),(e.addEventListener||e.on).apply(e,r),this};return{on:r,addEventListener:r,addListener:r,bind:r}},s.nodeIsDraggable=function(e){return e&&e.isNode()&&!e.locked()&&e.grabbable()},s.nodeIsGrabbable=function(e){return this.nodeIsDraggable(e)&&0!==e.pstyle("opacity").value&&"visible"===e.pstyle("visibility").value&&"element"===e.pstyle("display").value},s.load=function(){var e=this,t=function(t,r,n,a){null==t&&(t=e.cy);for(var s=0;s<r.length;s++){var l=r[s],u=new o(n,i.extend({type:l},a));t.trigger(u)}},r=function(e){return e.shiftKey||e.metaKey||e.ctrlKey},s=function(t,r){var n=!0;if(e.cy.hasCompoundNodes()&&t&&t.isEdge())for(var i=0;r&&i<r.length;i++){var t=r[i];if(t.isNode()&&t.isParent()){n=!1;break}}else n=!0;return n},l=function(t){var r;if(t.addToList&&e.cy.hasCompoundNodes()){if(!t.addToList.hasId){t.addToList.hasId={};for(var n=0;n<t.addToList.length;n++){var i=t.addToList[n];t.addToList.hasId[i.id()]=!0}}r=t.addToList.hasId}return r||{}},u=function(e){e[0]._private.grabbed=!0},c=function(e){e[0]._private.grabbed=!1},d=function(e){e[0]._private.rscratch.inDragLayer=!0},h=function(e){e[0]._private.rscratch.inDragLayer=!1},p=function(e){e[0]._private.rscratch.isGrabTarget=!0},f=function(e){e[0]._private.rscratch.isGrabTarget=!1},v=function(e,t){var r=l(t);r[e.id()]||(t.addToList.push(e),r[e.id()]=!0,u(e))},g=function(e,t){if(e.cy().hasCompoundNodes()&&(null!=t.inDragLayer||null!=t.addToList)){var r=e.descendants();t.inDragLayer&&(r.forEach(d),r.connectedEdges().forEach(d)),t.addToList&&r.forEach(function(e){v(e,t)})}},y=function(t,r){r=r||{};var n=t.cy().hasCompoundNodes();r.inDragLayer&&(t.forEach(d),t.neighborhood().stdFilter(function(e){return!n||e.isEdge()}).forEach(d)),r.addToList&&t.forEach(function(e){v(e,r)}),g(t,r),x(t,{inDragLayer:r.inDragLayer}),e.updateCachedGrabbedEles()},m=y,b=function(t){t&&(t.hasId={},e.getCachedZSortedEles().forEach(function(e){c(e),h(e),f(e)}),e.updateCachedGrabbedEles())},x=function(e,t){if((null!=t.inDragLayer||null!=t.addToList)&&e.cy().hasCompoundNodes()){var r=e.ancestors().orphans();if(!r.same(e)){var n=r.descendants().spawnSelf().merge(r).unmerge(e).unmerge(e.descendants()),i=n.connectedEdges();t.inDragLayer&&(i.forEach(d),n.forEach(d)),t.addToList&&n.forEach(function(e){v(e,t)})}}},w="undefined"!=typeof MutationObserver;w?(e.removeObserver=new MutationObserver(function(t){for(var r=0;r<t.length;r++){var n=t[r],i=n.removedNodes;if(i)for(var a=0;a<i.length;a++){var o=i[a];if(o===e.container){e.destroy();break}}}}),e.container.parentNode&&e.removeObserver.observe(e.container.parentNode,{childList:!0})):e.registerBinding(e.container,"DOMNodeRemoved",function(t){e.destroy()});var E=i.debounce(function(){e.cy.invalidateSize(),e.invalidateContainerClientCoordsCache(),e.matchCanvasSize(e.container),e.redrawHint("eles",!0),e.redrawHint("drag",!0),e.redraw()},100);w&&(e.styleObserver=new MutationObserver(E),e.styleObserver.observe(e.container,{attributes:!0})),e.registerBinding(window,"resize",E);for(var _=function(t){e.registerBinding(t,"scroll",function(t){e.invalidateContainerClientCoordsCache()})},P=e.cy.container();_(P),P.parentNode;)P=P.parentNode;e.registerBinding(e.container,"contextmenu",function(e){e.preventDefault()});var S=function(){return 0!==e.selection[4]};e.registerBinding(e.container,"mousedown",function(r){r.preventDefault(),e.hoverData.capture=!0,e.hoverData.which=r.which;var n=e.cy,i=[r.clientX,r.clientY],a=e.projectIntoViewport(i[0],i[1]),s=e.selection,l=e.findNearestElements(a[0],a[1],!0,!1),u=l[0],c=e.dragData.possibleDragElements;e.hoverData.mdownPos=a,e.hoverData.mdownGPos=i;var d=function(){e.hoverData.tapholdCancelled=!1,clearTimeout(e.hoverData.tapholdTimeout),e.hoverData.tapholdTimeout=setTimeout(function(){if(!e.hoverData.tapholdCancelled){var t=e.hoverData.down;t?t.trigger(new o(r,{type:"taphold",cyPosition:{x:a[0],y:a[1]}})):n.trigger(new o(r,{type:"taphold",cyPosition:{x:a[0],y:a[1]}}))}},e.tapholdDuration)};if(3==r.which){e.hoverData.cxtStarted=!0;var h=new o(r,{type:"cxttapstart",cyPosition:{x:a[0],y:a[1]}});u?(u.activate(),u.trigger(h),e.hoverData.down=u):n.trigger(h),e.hoverData.downTime=(new Date).getTime(),e.hoverData.cxtDragged=!1}else if(1==r.which){if(u&&u.activate(),null!=u&&e.nodeIsGrabbable(u)){var f=new o(r,{type:"grab",cyPosition:{x:a[0],y:a[1]}});if(p(u),u.selected()){if(u.selected()){c=e.dragData.possibleDragElements=[];var v=n.$(function(){return this.isNode()&&this.selected()&&e.nodeIsGrabbable(this)});y(v,{addToList:c}),u.trigger(f)}}else c=e.dragData.possibleDragElements=[],m(u,{addToList:c}),u.trigger(f);e.redrawHint("eles",!0),e.redrawHint("drag",!0)}e.hoverData.down=u,e.hoverData.downs=l,e.hoverData.downTime=(new Date).getTime(),t(u,["mousedown","tapstart","vmousedown"],r,{cyPosition:{x:a[0],y:a[1]}}),null==u?(s[4]=1,e.data.bgActivePosistion={x:a[0],y:a[1]},e.redrawHint("select",!0),e.redraw()):u.isEdge()&&(s[4]=1),d()}s[0]=s[2]=a[0],s[1]=s[3]=a[1]},!1),e.registerBinding(window,"mousemove",function(i){var l=!1,u=e.hoverData.capture;if(!u){var c=e.findContainerClientCoords();if(!(i.clientX>c[0]&&i.clientX<c[0]+e.canvasWidth&&i.clientY>c[1]&&i.clientY<c[1]+e.canvasHeight))return;for(var d=e.container,h=i.target,p=h.parentNode,f=!1;p;){if(p===d){f=!0;break}p=p.parentNode}if(!f)return}var v=e.cy,g=v.zoom(),m=[i.clientX,i.clientY],b=e.projectIntoViewport(m[0],m[1]),x=e.hoverData.mdownPos,w=e.hoverData.mdownGPos,E=e.selection,_=null;e.hoverData.draggingEles||e.hoverData.dragging||e.hoverData.selecting||(_=e.findNearestElement(b[0],b[1],!0,!1));var P,S=e.hoverData.last,k=e.hoverData.down,T=[b[0]-E[2],b[1]-E[3]],D=e.dragData.possibleDragElements;if(w){var C=m[0]-w[0],M=C*C,N=m[1]-w[1],B=N*N,z=M+B;P=z>=e.desktopTapThreshold2}var I=r(i);P&&(e.hoverData.tapholdCancelled=!0);var L=function(){var t=e.hoverData.dragDelta=e.hoverData.dragDelta||[];0===t.length?(t.push(T[0]),t.push(T[1])):(t[0]+=T[0],t[1]+=T[1])};if(l=!0,t(_,["mousemove","vmousemove","tapdrag"],i,{cyPosition:{x:b[0],y:b[1]}}),3===e.hoverData.which){if(P){var O=new o(i,{type:"cxtdrag",cyPosition:{x:b[0],y:b[1]}});k?k.trigger(O):v.trigger(O),e.hoverData.cxtDragged=!0,e.hoverData.cxtOver&&_===e.hoverData.cxtOver||(e.hoverData.cxtOver&&e.hoverData.cxtOver.trigger(new o(i,{type:"cxtdragout",cyPosition:{x:b[0],y:b[1]}})),e.hoverData.cxtOver=_,_&&_.trigger(new o(i,{type:"cxtdragover",cyPosition:{x:b[0],y:b[1]}})))}}else if(e.hoverData.dragging){if(l=!0,v.panningEnabled()&&v.userPanningEnabled()){var A;if(e.hoverData.justStartedPan){var R=e.hoverData.mdownPos;A={x:(b[0]-R[0])*g,y:(b[1]-R[1])*g},e.hoverData.justStartedPan=!1}else A={x:T[0]*g,y:T[1]*g};v.panBy(A),e.hoverData.dragged=!0}b=e.projectIntoViewport(i.clientX,i.clientY)}else if(1!=E[4]||null!=k&&!k.isEdge()){if(k&&k.isEdge()&&k.active()&&k.unactivate(),k&&k.grabbed()||_==S||(S&&t(S,["mouseout","tapdragout"],i,{cyPosition:{x:b[0],y:b[1]}}),_&&t(_,["mouseover","tapdragover"],i,{cyPosition:{x:b[0],y:b[1]}}),e.hoverData.last=_),k&&e.nodeIsDraggable(k))if(P){var q=!e.dragData.didDrag;q&&e.redrawHint("eles",!0),e.dragData.didDrag=!0;var V=[];e.hoverData.draggingEles||y(v.collection(D),{inDragLayer:!0});for(var F=0;F<D.length;F++){var j=D[F];if(e.nodeIsDraggable(j)&&j.grabbed()){var X=j._private.position;if(V.push(j),n.number(T[0])&&n.number(T[1])){var Y=!j.isParent(); +if(Y&&(X.x+=T[0],X.y+=T[1]),q){var W=e.hoverData.dragDelta;Y&&W&&n.number(W[0])&&n.number(W[1])&&(X.x+=W[0],X.y+=W[1])}}}}e.hoverData.draggingEles=!0;var $=v.collection(V);$.updateCompoundBounds(),$.trigger("position drag"),e.redrawHint("drag",!0),e.redraw()}else L();l=!0}else if(P){if(e.hoverData.dragging||!v.boxSelectionEnabled()||!I&&v.panningEnabled()&&v.userPanningEnabled()){if(!e.hoverData.selecting&&v.panningEnabled()&&v.userPanningEnabled()){var H=s(k,e.hoverData.downs);H&&(e.hoverData.dragging=!0,e.hoverData.justStartedPan=!0,E[4]=0,e.data.bgActivePosistion=a.array2point(x),e.redrawHint("select",!0),e.redraw())}}else e.data.bgActivePosistion=void 0,e.hoverData.selecting||v.trigger("boxstart"),e.hoverData.selecting=!0,e.redrawHint("select",!0),e.redraw();k&&k.isEdge()&&k.active()&&k.unactivate()}return E[2]=b[0],E[3]=b[1],l?(i.stopPropagation&&i.stopPropagation(),i.preventDefault&&i.preventDefault(),!1):void 0},!1),e.registerBinding(window,"mouseup",function(n){var i=e.hoverData.capture;if(i){e.hoverData.capture=!1;var a=e.cy,s=e.projectIntoViewport(n.clientX,n.clientY),l=e.selection,u=e.findNearestElement(s[0],s[1],!0,!1),c=e.dragData.possibleDragElements,d=e.hoverData.down,h=r(n);if(e.data.bgActivePosistion&&(e.redrawHint("select",!0),e.redraw()),e.hoverData.tapholdCancelled=!0,e.data.bgActivePosistion=void 0,d&&d.unactivate(),3===e.hoverData.which){var p=new o(n,{type:"cxttapend",cyPosition:{x:s[0],y:s[1]}});if(d?d.trigger(p):a.trigger(p),!e.hoverData.cxtDragged){var f=new o(n,{type:"cxttap",cyPosition:{x:s[0],y:s[1]}});d?d.trigger(f):a.trigger(f)}e.hoverData.cxtDragged=!1,e.hoverData.which=null}else if(1===e.hoverData.which){if(null!=d||e.dragData.didDrag||e.hoverData.selecting||e.hoverData.dragged||r(n)||(a.$(function(){return this.selected()}).unselect(),c.length>0&&e.redrawHint("eles",!0),e.dragData.possibleDragElements=c=[]),t(u,["mouseup","tapend","vmouseup"],n,{cyPosition:{x:s[0],y:s[1]}}),e.dragData.didDrag||e.hoverData.dragged||e.hoverData.selecting||t(d,["click","tap","vclick"],n,{cyPosition:{x:s[0],y:s[1]}}),u!=d||e.dragData.didDrag||e.hoverData.selecting||null!=u&&u._private.selectable&&(e.hoverData.dragging||("additive"===a.selectionType()||h?u.selected()?u.unselect():u.select():h||(a.$(":selected").unmerge(u).unselect(),u.select())),e.redrawHint("eles",!0)),e.hoverData.selecting){var v=a.collection(e.getAllInBox(l[0],l[1],l[2],l[3]));e.redrawHint("select",!0),v.length>0&&e.redrawHint("eles",!0),a.trigger("boxend");var g=function(e){return e.selectable()&&!e.selected()};"additive"===a.selectionType()?v.trigger("box").stdFilter(g).select().trigger("boxselect"):(h||a.$(":selected").unmerge(v).unselect(),v.trigger("box").stdFilter(g).select().trigger("boxselect")),e.redraw()}if(e.hoverData.dragging&&(e.hoverData.dragging=!1,e.redrawHint("select",!0),e.redrawHint("eles",!0),e.redraw()),!l[4]){e.redrawHint("drag",!0),e.redrawHint("eles",!0);var y=d&&d.grabbed();b(c),y&&d.trigger("free")}}l[4]=0,e.hoverData.down=null,e.hoverData.cxtStarted=!1,e.hoverData.draggingEles=!1,e.hoverData.selecting=!1,e.dragData.didDrag=!1,e.hoverData.dragged=!1,e.hoverData.dragDelta=[],e.hoverData.mdownPos=null,e.hoverData.mdownGPos=null}},!1);var k=function(t){if(!e.scrollingPage){var r=e.cy,n=e.projectIntoViewport(t.clientX,t.clientY),i=[n[0]*r.zoom()+r.pan().x,n[1]*r.zoom()+r.pan().y];if(e.hoverData.draggingEles||e.hoverData.dragging||e.hoverData.cxtStarted||S())return void t.preventDefault();if(r.panningEnabled()&&r.userPanningEnabled()&&r.zoomingEnabled()&&r.userZoomingEnabled()){t.preventDefault(),e.data.wheelZooming=!0,clearTimeout(e.data.wheelTimeout),e.data.wheelTimeout=setTimeout(function(){e.data.wheelZooming=!1,e.redrawHint("eles",!0),e.redraw()},150);var a=t.deltaY/-250||t.wheelDeltaY/1e3||t.wheelDelta/1e3;a*=e.wheelSensitivity;var o=1===t.deltaMode;o&&(a*=33),r.zoom({level:r.zoom()*Math.pow(10,a),renderedPosition:{x:i[0],y:i[1]}})}}};e.registerBinding(e.container,"wheel",k,!0),e.registerBinding(window,"scroll",function(t){e.scrollingPage=!0,clearTimeout(e.scrollingPageTimeout),e.scrollingPageTimeout=setTimeout(function(){e.scrollingPage=!1},250)},!0),e.registerBinding(e.container,"mouseout",function(t){var r=e.projectIntoViewport(t.clientX,t.clientY);e.cy.trigger(new o(t,{type:"mouseout",cyPosition:{x:r[0],y:r[1]}}))},!1),e.registerBinding(e.container,"mouseover",function(t){var r=e.projectIntoViewport(t.clientX,t.clientY);e.cy.trigger(new o(t,{type:"mouseover",cyPosition:{x:r[0],y:r[1]}}))},!1);var T,D,C,M,N,B,z,I,L,O,A,R,q,V,F=function(e,t,r,n){return Math.sqrt((r-e)*(r-e)+(n-t)*(n-t))},j=function(e,t,r,n){return(r-e)*(r-e)+(n-t)*(n-t)};e.registerBinding(e.container,"touchstart",V=function(r){e.touchData.capture=!0,e.data.bgActivePosistion=void 0;var n=e.cy,i=e.touchData.now,a=e.touchData.earlier;if(r.touches[0]){var s=e.projectIntoViewport(r.touches[0].clientX,r.touches[0].clientY);i[0]=s[0],i[1]=s[1]}if(r.touches[1]){var s=e.projectIntoViewport(r.touches[1].clientX,r.touches[1].clientY);i[2]=s[0],i[3]=s[1]}if(r.touches[2]){var s=e.projectIntoViewport(r.touches[2].clientX,r.touches[2].clientY);i[4]=s[0],i[5]=s[1]}if(r.touches[1]){b(e.dragData.touchDragEles);var l=e.findContainerClientCoords();L=l[0],O=l[1],A=l[2],R=l[3],T=r.touches[0].clientX-L,D=r.touches[0].clientY-O,C=r.touches[1].clientX-L,M=r.touches[1].clientY-O,q=T>=0&&A>=T&&C>=0&&A>=C&&D>=0&&R>=D&&M>=0&&R>=M;var u=n.pan(),c=n.zoom();N=F(T,D,C,M),B=j(T,D,C,M),z=[(T+C)/2,(D+M)/2],I=[(z[0]-u.x)/c,(z[1]-u.y)/c];var d=200,h=d*d;if(h>B&&!r.touches[2]){var f=e.findNearestElement(i[0],i[1],!0,!0),v=e.findNearestElement(i[2],i[3],!0,!0);return f&&f.isNode()?(f.activate().trigger(new o(r,{type:"cxttapstart",cyPosition:{x:i[0],y:i[1]}})),e.touchData.start=f):v&&v.isNode()?(v.activate().trigger(new o(r,{type:"cxttapstart",cyPosition:{x:i[0],y:i[1]}})),e.touchData.start=v):(n.trigger(new o(r,{type:"cxttapstart",cyPosition:{x:i[0],y:i[1]}})),e.touchData.start=null),e.touchData.start&&(e.touchData.start._private.grabbed=!1),e.touchData.cxt=!0,e.touchData.cxtDragged=!1,e.data.bgActivePosistion=void 0,void e.redraw()}}if(r.touches[2]);else if(r.touches[1]);else if(r.touches[0]){var g=e.findNearestElements(i[0],i[1],!0,!0),x=g[0];if(null!=x&&(x.activate(),e.touchData.start=x,e.touchData.starts=g,e.nodeIsGrabbable(x))){var w=e.dragData.touchDragEles=[];if(e.redrawHint("eles",!0),e.redrawHint("drag",!0),x.selected()){var E=n.$(function(){return this.selected()&&e.nodeIsGrabbable(this)});y(E,{addToList:w})}else m(x,{addToList:w});p(x),x.trigger(new o(r,{type:"grab",cyPosition:{x:i[0],y:i[1]}}))}t(x,["touchstart","tapstart","vmousedown"],r,{cyPosition:{x:i[0],y:i[1]}}),null==x&&(e.data.bgActivePosistion={x:s[0],y:s[1]},e.redrawHint("select",!0),e.redraw()),e.touchData.startPosition=[];for(var _=0;_<i.length;_++)a[_]=i[_],e.touchData.startPosition[_]=i[_];e.touchData.startGPosition=[r.touches[0].clientX,r.touches[0].clientY],e.touchData.singleTouchMoved=!1,e.touchData.singleTouchStartTime=+new Date,clearTimeout(e.touchData.tapholdTimeout),e.touchData.tapholdTimeout=setTimeout(function(){e.touchData.singleTouchMoved!==!1||e.pinching||e.touchData.selecting||(t(e.touchData.start,["taphold"],r,{cyPosition:{x:i[0],y:i[1]}}),e.touchData.start||n.$(":selected").unselect())},e.tapholdDuration)}},!1);var X;e.registerBinding(window,"touchmove",X=function(r){var i=e.selection,l=e.touchData.capture,u=e.cy,c=e.touchData.now,d=e.touchData.earlier,h=u.zoom();if(r.touches[0]){var p=e.projectIntoViewport(r.touches[0].clientX,r.touches[0].clientY);c[0]=p[0],c[1]=p[1]}if(r.touches[1]){var p=e.projectIntoViewport(r.touches[1].clientX,r.touches[1].clientY);c[2]=p[0],c[3]=p[1]}if(r.touches[2]){var p=e.projectIntoViewport(r.touches[2].clientX,r.touches[2].clientY);c[4]=p[0],c[5]=p[1]}var f;if(l&&r.touches[0]){for(var v=[],g=0;g<c.length;g++)v[g]=c[g]-d[g];var m=e.touchData.startGPosition,x=r.touches[0].clientX-m[0],w=x*x,E=r.touches[0].clientY-m[1],_=E*E,P=w+_;f=P>=e.touchTapThreshold2}if(l&&e.touchData.cxt){r.preventDefault();var S=r.touches[0].clientX-L,k=r.touches[0].clientY-O,z=r.touches[1].clientX-L,A=r.touches[1].clientY-O,R=j(S,k,z,A),V=R/B,X=150,Y=X*X,W=1.5,$=W*W;if(V>=$||R>=Y){e.touchData.cxt=!1,e.touchData.start&&(e.touchData.start.unactivate(),e.touchData.start=null),e.data.bgActivePosistion=void 0,e.redrawHint("select",!0);var H=new o(r,{type:"cxttapend",cyPosition:{x:c[0],y:c[1]}});e.touchData.start?e.touchData.start.trigger(H):u.trigger(H)}}if(l&&e.touchData.cxt){var H=new o(r,{type:"cxtdrag",cyPosition:{x:c[0],y:c[1]}});e.data.bgActivePosistion=void 0,e.redrawHint("select",!0),e.touchData.start?e.touchData.start.trigger(H):u.trigger(H),e.touchData.start&&(e.touchData.start._private.grabbed=!1),e.touchData.cxtDragged=!0;var U=e.findNearestElement(c[0],c[1],!0,!0);e.touchData.cxtOver&&U===e.touchData.cxtOver||(e.touchData.cxtOver&&e.touchData.cxtOver.trigger(new o(r,{type:"cxtdragout",cyPosition:{x:c[0],y:c[1]}})),e.touchData.cxtOver=U,U&&U.trigger(new o(r,{type:"cxtdragover",cyPosition:{x:c[0],y:c[1]}})))}else if(l&&r.touches[2]&&u.boxSelectionEnabled())r.preventDefault(),e.data.bgActivePosistion=void 0,this.lastThreeTouch=+new Date,e.touchData.selecting||u.trigger("boxstart"),e.touchData.selecting=!0,e.redrawHint("select",!0),i&&0!==i.length&&void 0!==i[0]?(i[2]=(c[0]+c[2]+c[4])/3,i[3]=(c[1]+c[3]+c[5])/3):(i[0]=(c[0]+c[2]+c[4])/3,i[1]=(c[1]+c[3]+c[5])/3,i[2]=(c[0]+c[2]+c[4])/3+1,i[3]=(c[1]+c[3]+c[5])/3+1),i[4]=1,e.touchData.selecting=!0,e.redraw();else if(l&&r.touches[1]&&u.zoomingEnabled()&&u.panningEnabled()&&u.userZoomingEnabled()&&u.userPanningEnabled()){r.preventDefault(),e.data.bgActivePosistion=void 0,e.redrawHint("select",!0);var Z=e.dragData.touchDragEles;if(Z){e.redrawHint("drag",!0);for(var G=0;G<Z.length;G++)Z[G]._private.grabbed=!1,Z[G]._private.rscratch.inDragLayer=!1}var S=r.touches[0].clientX-L,k=r.touches[0].clientY-O,z=r.touches[1].clientX-L,A=r.touches[1].clientY-O,Q=F(S,k,z,A),K=Q/N;if(1!=K&&q){var J=S-T,ee=k-D,te=z-C,re=A-M,ne=(J+te)/2,ie=(ee+re)/2,ae=u.zoom(),oe=ae*K,se=u.pan(),le=I[0]*ae+se.x,ue=I[1]*ae+se.y,ce={x:-oe/ae*(le-se.x-ne)+le,y:-oe/ae*(ue-se.y-ie)+ue};if(e.touchData.start){var Z=e.dragData.touchDragEles;b(Z),e.redrawHint("drag",!0),e.redrawHint("eles",!0),e.touchData.start.trigger("free").unactivate()}u.viewport({zoom:oe,pan:ce,cancelOnFailedZoom:!0}),N=Q,T=S,D=k,C=z,M=A,e.pinching=!0}if(r.touches[0]){var p=e.projectIntoViewport(r.touches[0].clientX,r.touches[0].clientY);c[0]=p[0],c[1]=p[1]}if(r.touches[1]){var p=e.projectIntoViewport(r.touches[1].clientX,r.touches[1].clientY);c[2]=p[0],c[3]=p[1]}if(r.touches[2]){var p=e.projectIntoViewport(r.touches[2].clientX,r.touches[2].clientY);c[4]=p[0],c[5]=p[1]}}else if(r.touches[0]){var U,de=e.touchData.start,he=e.touchData.last;if(e.hoverData.draggingEles||e.swipePanning||(U=e.findNearestElement(c[0],c[1],!0,!0)),l&&null!=de&&r.preventDefault(),l&&null!=de&&e.nodeIsDraggable(de))if(f){var Z=e.dragData.touchDragEles,pe=!e.dragData.didDrag;pe&&y(u.collection(Z),{inDragLayer:!0});for(var fe=0;fe<Z.length;fe++){var ve=Z[fe];if(e.nodeIsDraggable(ve)&&ve.grabbed()){e.dragData.didDrag=!0;var ge=ve._private.position,ye=!ve.isParent();if(ye&&n.number(v[0])&&n.number(v[1])&&(ge.x+=v[0],ge.y+=v[1]),pe){e.redrawHint("eles",!0);var me=e.touchData.dragDelta;ye&&me&&n.number(me[0])&&n.number(me[1])&&(ge.x+=me[0],ge.y+=me[1])}}}var be=u.collection(Z);be.updateCompoundBounds(),be.trigger("position drag"),e.hoverData.draggingEles=!0,e.redrawHint("drag",!0),e.touchData.startPosition[0]==d[0]&&e.touchData.startPosition[1]==d[1]&&e.redrawHint("eles",!0),e.redraw()}else{var me=e.touchData.dragDelta=e.touchData.dragDelta||[];0===me.length?(me.push(v[0]),me.push(v[1])):(me[0]+=v[0],me[1]+=v[1])}if(t(de||U,["touchmove","tapdrag","vmousemove"],r,{cyPosition:{x:c[0],y:c[1]}}),de&&de.grabbed()||U==he||(he&&he.trigger(new o(r,{type:"tapdragout",cyPosition:{x:c[0],y:c[1]}})),U&&U.trigger(new o(r,{type:"tapdragover",cyPosition:{x:c[0],y:c[1]}}))),e.touchData.last=U,l)for(var G=0;G<c.length;G++)c[G]&&e.touchData.startPosition[G]&&f&&(e.touchData.singleTouchMoved=!0);if(l&&(null==de||de.isEdge())&&u.panningEnabled()&&u.userPanningEnabled()){var xe=s(de,e.touchData.starts);xe&&(r.preventDefault(),e.swipePanning?u.panBy({x:v[0]*h,y:v[1]*h}):f&&(e.swipePanning=!0,u.panBy({x:x*h,y:E*h}),de&&(de.unactivate(),e.data.bgActivePosistion||(e.data.bgActivePosistion=a.array2point(e.touchData.startPosition)),e.redrawHint("select",!0),e.touchData.start=null)));var p=e.projectIntoViewport(r.touches[0].clientX,r.touches[0].clientY);c[0]=p[0],c[1]=p[1]}}for(var g=0;g<c.length;g++)d[g]=c[g]},!1);var Y;e.registerBinding(window,"touchcancel",Y=function(t){var r=e.touchData.start;e.touchData.capture=!1,r&&r.unactivate()});var W;if(e.registerBinding(window,"touchend",W=function(r){var n=e.touchData.start,i=e.touchData.capture;if(i){e.touchData.capture=!1,r.preventDefault();var a=e.selection;e.swipePanning=!1,e.hoverData.draggingEles=!1;var s=e.cy,l=s.zoom(),u=e.touchData.now,c=e.touchData.earlier;if(r.touches[0]){var d=e.projectIntoViewport(r.touches[0].clientX,r.touches[0].clientY);u[0]=d[0],u[1]=d[1]}if(r.touches[1]){var d=e.projectIntoViewport(r.touches[1].clientX,r.touches[1].clientY);u[2]=d[0],u[3]=d[1]}if(r.touches[2]){var d=e.projectIntoViewport(r.touches[2].clientX,r.touches[2].clientY);u[4]=d[0],u[5]=d[1]}n&&n.unactivate();var h;if(e.touchData.cxt){if(h=new o(r,{type:"cxttapend",cyPosition:{x:u[0],y:u[1]}}),n?n.trigger(h):s.trigger(h),!e.touchData.cxtDragged){var p=new o(r,{type:"cxttap",cyPosition:{x:u[0],y:u[1]}});n?n.trigger(p):s.trigger(p)}return e.touchData.start&&(e.touchData.start._private.grabbed=!1),e.touchData.cxt=!1,e.touchData.start=null,void e.redraw()}if(!r.touches[2]&&s.boxSelectionEnabled()&&e.touchData.selecting){e.touchData.selecting=!1;var f=s.collection(e.getAllInBox(a[0],a[1],a[2],a[3]));a[0]=void 0,a[1]=void 0,a[2]=void 0,a[3]=void 0,a[4]=0,e.redrawHint("select",!0),s.trigger("boxend");var v=function(e){return e.selectable()&&!e.selected()};f.trigger("box").stdFilter(v).select().trigger("boxselect"),f.nonempty()&&e.redrawHint("eles",!0),e.redraw()}if(null!=n&&n.unactivate(),r.touches[2])e.data.bgActivePosistion=void 0,e.redrawHint("select",!0);else if(r.touches[1]);else if(r.touches[0]);else if(!r.touches[0]){e.data.bgActivePosistion=void 0,e.redrawHint("select",!0);var g=e.dragData.touchDragEles;if(null!=n){var y=n._private.grabbed;b(g),e.redrawHint("drag",!0),e.redrawHint("eles",!0),y&&n.trigger("free"),t(n,["touchend","tapend","vmouseup","tapdragout"],r,{cyPosition:{x:u[0],y:u[1]}}),n.unactivate(),e.touchData.start=null}else{var m=e.findNearestElement(u[0],u[1],!0,!0);t(m,["touchend","tapend","vmouseup","tapdragout"],r,{cyPosition:{x:u[0],y:u[1]}})}var x=e.touchData.startPosition[0]-u[0],w=x*x,E=e.touchData.startPosition[1]-u[1],_=E*E,P=w+_,S=P*l*l;null!=n&&!e.dragData.didDrag&&n._private.selectable&&S<e.touchTapThreshold2&&!e.pinching&&("single"===s.selectionType()?(s.$(":selected").unmerge(n).unselect(),n.select()):n.selected()?n.unselect():n.select(),e.redrawHint("eles",!0)),e.touchData.singleTouchMoved||t(n,["tap","vclick"],r,{cyPosition:{x:u[0],y:u[1]}}),e.touchData.singleTouchMoved=!0}for(var k=0;k<u.length;k++)c[k]=u[k];e.dragData.didDrag=!1,0===r.touches.length&&(e.touchData.dragDelta=[],e.touchData.startPosition=null,e.touchData.startGPosition=null),r.touches.length<2&&(e.pinching=!1,e.redrawHint("eles",!0),e.redraw())}},!1),"undefined"==typeof TouchEvent){var $=[],H=function(e){return{clientX:e.clientX,clientY:e.clientY,force:1,identifier:e.pointerId,pageX:e.pageX,pageY:e.pageY,radiusX:e.width/2,radiusY:e.height/2,screenX:e.screenX,screenY:e.screenY,target:e.target}},U=function(e){return{event:e,touch:H(e)}},Z=function(e){$.push(U(e))},G=function(e){for(var t=0;t<$.length;t++){var r=$[t];if(r.event.pointerId===e.pointerId)return void $.splice(t,1)}},Q=function(e){var t=$.filter(function(t){return t.event.pointerId===e.pointerId})[0];t.event=e,t.touch=H(e)},K=function(e){e.touches=$.map(function(e){return e.touch})};e.registerBinding(e.container,"pointerdown",function(e){"mouse"!==e.pointerType&&(e.preventDefault(),Z(e),K(e),V(e))}),e.registerBinding(e.container,"pointerup",function(e){"mouse"!==e.pointerType&&(G(e),K(e),W(e))}),e.registerBinding(e.container,"pointercancel",function(e){"mouse"!==e.pointerType&&(G(e),K(e),Y(e))}),e.registerBinding(e.container,"pointermove",function(e){"mouse"!==e.pointerType&&(e.preventDefault(),Q(e),K(e),X(e))})}},t.exports=s},{"../../../event":45,"../../../is":83,"../../../math":85,"../../../util":100}],62:[function(e,t,r){"use strict";var n=e("../../../math"),i={};i.generatePolygon=function(e,t){return this.nodeShapes[e]={renderer:this,name:e,points:t,draw:function(e,t,r,n,i){this.renderer.nodeShapeImpl("polygon",e,t,r,n,i,this.points)},intersectLine:function(e,t,r,i,a,o,s){return n.polygonIntersectLine(a,o,this.points,e,t,r/2,i/2,s)},checkPoint:function(e,t,r,i,a,o,s){return n.pointInsidePolygon(e,t,this.points,o,s,i,a,[0,-1],r)}}},i.generateEllipse=function(){return this.nodeShapes.ellipse={renderer:this,name:"ellipse",draw:function(e,t,r,n,i){this.renderer.nodeShapeImpl(this.name,e,t,r,n,i)},intersectLine:function(e,t,r,i,a,o,s){return n.intersectLineEllipse(a,o,e,t,r/2+s,i/2+s)},checkPoint:function(e,t,r,n,i,a,o){return e-=a,t-=o,e/=n/2+r,t/=i/2+r,1>=e*e+t*t}}},i.generateRoundRectangle=function(){return this.nodeShapes.roundrectangle={renderer:this,name:"roundrectangle",points:n.generateUnitNgonPointsFitToSquare(4,0),draw:function(e,t,r,n,i){this.renderer.nodeShapeImpl(this.name,e,t,r,n,i)},intersectLine:function(e,t,r,i,a,o,s){return n.roundRectangleIntersectLine(a,o,e,t,r,i,s)},checkPoint:function(e,t,r,i,a,o,s){var l=n.getRoundRectangleRadius(i,a);if(n.pointInsidePolygon(e,t,this.points,o,s,i,a-2*l,[0,-1],r))return!0;if(n.pointInsidePolygon(e,t,this.points,o,s,i-2*l,a,[0,-1],r))return!0;var u=function(e,t,r,n,i,a,o){return e-=r,t-=n,e/=i/2+o,t/=a/2+o,1>=e*e+t*t};return u(e,t,o-i/2+l,s-a/2+l,2*l,2*l,r)?!0:u(e,t,o+i/2-l,s-a/2+l,2*l,2*l,r)?!0:u(e,t,o+i/2-l,s+a/2-l,2*l,2*l,r)?!0:!!u(e,t,o-i/2+l,s+a/2-l,2*l,2*l,r)}}},i.registerNodeShapes=function(){var e=this.nodeShapes={},t=this;this.generateEllipse(),this.generatePolygon("triangle",n.generateUnitNgonPointsFitToSquare(3,0)),this.generatePolygon("rectangle",n.generateUnitNgonPointsFitToSquare(4,0)),e.square=e.rectangle,this.generateRoundRectangle(),this.generatePolygon("diamond",[0,1,1,0,0,-1,-1,0]),this.generatePolygon("pentagon",n.generateUnitNgonPointsFitToSquare(5,0)),this.generatePolygon("hexagon",n.generateUnitNgonPointsFitToSquare(6,0)),this.generatePolygon("heptagon",n.generateUnitNgonPointsFitToSquare(7,0)),this.generatePolygon("octagon",n.generateUnitNgonPointsFitToSquare(8,0));var r=new Array(20),i=n.generateUnitNgonPoints(5,0),a=n.generateUnitNgonPoints(5,Math.PI/5),o=.5*(3-Math.sqrt(5));o*=1.57;for(var s=0;s<a.length/2;s++)a[2*s]*=o,a[2*s+1]*=o;for(var s=0;5>s;s++)r[4*s]=i[2*s],r[4*s+1]=i[2*s+1],r[4*s+2]=a[2*s],r[4*s+3]=a[2*s+1];r=n.fitPolygonToSquare(r),this.generatePolygon("star",r),this.generatePolygon("vee",[-1,-1,0,-.333,1,-1,0,1]),this.generatePolygon("rhomboid",[-1,-1,.333,-1,1,1,-.333,1]),e.makePolygon=function(e){var r,n=e.join("$"),i="polygon-"+n;return(r=this[i])?r:t.generatePolygon(i,e)}},t.exports=i},{"../../../math":85}],63:[function(e,t,r){"use strict";var n=e("../../../util"),i={};i.timeToRender=function(){return this.redrawTotalTime/this.redrawCount},i.redraw=function(e){e=e||n.staticEmptyObject();var t=this;void 0===t.averageRedrawTime&&(t.averageRedrawTime=0),void 0===t.lastRedrawTime&&(t.lastRedrawTime=0),void 0===t.lastDrawTime&&(t.lastDrawTime=0),t.requestedFrame=!0,t.renderOptions=e},i.beforeRender=function(e,t){t=t||0;var r=this.beforeRenderCallbacks;r.push({fn:e,priority:t}),r.sort(function(e,t){return t.priority-e.priority})};var a=function(e,t,r){for(var n=e.beforeRenderCallbacks,i=0;i<n.length;i++)n[i].fn(t,r)};i.startRenderLoop=function(){var e=this;if(!e.renderLoopStarted){e.renderLoopStarted=!0;var t=function(r){if(!e.destroyed){if(e.requestedFrame&&!e.skipFrame){a(e,!0,r);var i=n.performanceNow();e.render(e.renderOptions);var o=e.lastDrawTime=n.performanceNow();void 0===e.averageRedrawTime&&(e.averageRedrawTime=o-i),void 0===e.redrawCount&&(e.redrawCount=0),e.redrawCount++,void 0===e.redrawTotalTime&&(e.redrawTotalTime=0);var s=o-i;e.redrawTotalTime+=s,e.lastRedrawTime=s,e.averageRedrawTime=e.averageRedrawTime/2+s/2,e.requestedFrame=!1}else a(e,!1,r);e.skipFrame=!1,n.requestAnimationFrame(t)}};n.requestAnimationFrame(t)}},t.exports=i},{"../../../util":100}],64:[function(e,t,r){"use strict";var n,i={};i.arrowShapeImpl=function(e){return(n||(n={polygon:function(e,t){for(var r=0;r<t.length;r++){var n=t[r];e.lineTo(n.x,n.y)}},"triangle-backcurve":function(e,t,r){for(var n,i=0;i<t.length;i++){var a=t[i];0===i&&(n=a),e.lineTo(a.x,a.y)}e.quadraticCurveTo(r.x,r.y,n.x,n.y)},"triangle-tee":function(e,t,r){e.beginPath&&e.beginPath();for(var n=t,i=0;i<n.length;i++){var a=n[i];e.lineTo(a.x,a.y)}e.closePath&&e.closePath(),e.beginPath&&e.beginPath();var o=r,s=r[0];e.moveTo(s.x,s.y);for(var i=0;i<o.length;i++){var a=o[i];e.lineTo(a.x,a.y)}e.closePath&&e.closePath()},circle:function(e,t,r,n){e.arc(t,r,n,0,2*Math.PI,!1)}}))[e]},t.exports=i},{}],65:[function(e,t,r){"use strict";var n={};n.drawEdge=function(e,t,r,n,i){var a=t._private.rscratch,o=this.usePaths();if(!(a.badLine||isNaN(a.allpts[0])||t.pstyle("width").pfValue<=0)){var s;r&&(s=r,e.translate(-s.x1,-s.y1));var l=t.pstyle("overlay-padding").pfValue,u=t.pstyle("overlay-opacity").value,c=t.pstyle("overlay-color").value;if(i){if(0===u)return;this.strokeStyle(e,c[0],c[1],c[2],u),e.lineCap="round","self"!=a.edgeType||o||(e.lineCap="butt")}else{var d=t.pstyle("line-color").value;this.strokeStyle(e,d[0],d[1],d[2],t.pstyle("opacity").value),e.lineCap="butt"}e.lineJoin="round";var h=t.pstyle("width").pfValue+(i?2*l:0),p=i?"solid":t.pstyle("line-style").value;e.lineWidth=h;var f=t.pstyle("shadow-blur").pfValue,v=t.pstyle("shadow-opacity").value,g=t.pstyle("shadow-color").value,y=t.pstyle("shadow-offset-x").pfValue,m=t.pstyle("shadow-offset-y").pfValue;this.shadowStyle(e,g,i?0:v,f,y,m),this.drawEdgePath(t,e,a.allpts,p,h),this.drawArrowheads(e,t,i),this.shadowStyle(e,"transparent",0),i||this.drawEdge(e,t,!1,n,!0),this.drawElementText(e,t,n),r&&e.translate(s.x1,s.y1)}},n.drawEdgePath=function(e,t,r,n,i){var a,o=e._private.rscratch,s=t,l=!1,u=this.usePaths();if(u){var c=r.join("$"),d=o.pathCacheKey&&o.pathCacheKey===c;d?(a=t=o.pathCache,l=!0):(a=t=new Path2D,o.pathCacheKey=c,o.pathCache=a)}if(s.setLineDash)switch(n){case"dotted":s.setLineDash([1,1]);break;case"dashed":s.setLineDash([6,3]);break;case"solid":s.setLineDash([])}if(!l&&!o.badLine)switch(t.beginPath&&t.beginPath(),t.moveTo(r[0],r[1]),o.edgeType){case"bezier":case"self":case"compound":case"multibezier":for(var h=2;h+3<r.length;h+=4)t.quadraticCurveTo(r[h],r[h+1],r[h+2],r[h+3]);break;case"straight":case"segments":case"haystack":for(var h=2;h+1<r.length;h+=2)t.lineTo(r[h],r[h+1])}t=s,u?t.stroke(a):t.stroke(),t.setLineDash&&t.setLineDash([])},n.drawArrowheads=function(e,t,r){if(!r){var n=t._private.rscratch,i="haystack"===n.edgeType;i||this.drawArrowhead(e,t,"source",n.arrowStartX,n.arrowStartY,n.srcArrowAngle),this.drawArrowhead(e,t,"mid-target",n.midX,n.midY,n.midtgtArrowAngle),this.drawArrowhead(e,t,"mid-source",n.midX,n.midY,n.midsrcArrowAngle),i||this.drawArrowhead(e,t,"target",n.arrowEndX,n.arrowEndY,n.tgtArrowAngle)}},n.drawArrowhead=function(e,t,r,n,i,a){if(!(isNaN(n)||null==n||isNaN(i)||null==i||isNaN(a)||null==a)){var o=this,s=t.pstyle(r+"-arrow-shape").value;if("none"!==s){var l=e.globalCompositeOperation,u="hollow"===t.pstyle(r+"-arrow-fill").value?"both":"filled",c=t.pstyle(r+"-arrow-fill").value,d=t.pstyle("opacity").value;"half-triangle-overshot"===s&&(c="hollow",u="hollow"),1===d&&"hollow"!==c||(e.globalCompositeOperation="destination-out",o.fillStyle(e,255,255,255,1),o.strokeStyle(e,255,255,255,1),o.drawArrowShape(t,r,e,u,t.pstyle("width").pfValue,t.pstyle(r+"-arrow-shape").value,n,i,a),e.globalCompositeOperation=l);var h=t.pstyle(r+"-arrow-color").value;o.fillStyle(e,h[0],h[1],h[2],d),o.strokeStyle(e,h[0],h[1],h[2],d),o.drawArrowShape(t,r,e,c,t.pstyle("width").pfValue,t.pstyle(r+"-arrow-shape").value,n,i,a)}}},n.drawArrowShape=function(e,t,r,n,i,a,o,s,l){var u,c=this,d=this.usePaths(),h=e._private.rscratch,p=!1,f=r,v={x:o,y:s},g=this.getArrowWidth(i),y=c.arrowShapes[a];if(d){var m=g+"$"+a+"$"+l+"$"+o+"$"+s;h.arrowPathCacheKey=h.arrowPathCacheKey||{},h.arrowPathCache=h.arrowPathCache||{};var b=h.arrowPathCacheKey[t]===m;b?(u=r=h.arrowPathCache[t],p=!0):(u=r=new Path2D,h.arrowPathCacheKey[t]=m,h.arrowPathCache[t]=u)}r.beginPath&&r.beginPath(),p||y.draw(r,g,l,v),!y.leavePathOpen&&r.closePath&&r.closePath(),r=f,"filled"!==n&&"both"!==n||(d?r.fill(u):r.fill()),"hollow"!==n&&"both"!==n||(r.lineWidth=y.matchEdgeWidth?i:1,r.lineJoin="miter",d?r.stroke(u):r.stroke())},t.exports=n},{}],66:[function(e,t,r){"use strict";var n=e("../../../math"),i={};i.drawElement=function(e,t,r,n){var i=this;t.isNode()?i.drawNode(e,t,r,n):i.drawEdge(e,t,r,n)},i.drawCachedElement=function(e,t,r,i){var a=this,o=t.boundingBox();if(!i||n.boundingBoxesIntersect(o,i)){var s=a.data.eleTxrCache.getElement(t,o,r);s?e.drawImage(s.texture.canvas,s.x,0,s.width,s.height,o.x1,o.y1,o.w,o.h):a.drawElement(e,t)}},i.drawElements=function(e,t){for(var r=this,n=0;n<t.length;n++){var i=t[n];r.drawElement(e,i)}},i.drawCachedElements=function(e,t,r,n){for(var i=this,a=0;a<t.length;a++){var o=t[a];i.drawCachedElement(e,o,r,n)}},i.drawCachedNodes=function(e,t,r,n){for(var i=this,a=0;a<t.length;a++){var o=t[a];o.isNode()&&i.drawCachedElement(e,o,r,n)}},i.drawLayeredElements=function(e,t,r,n){var i=this,a=i.data.lyrTxrCache.getLayers(t,r);if(a)for(var o=0;o<a.length;o++){var s=a[o],l=s.bb;e.drawImage(s.canvas,l.x1,l.y1,l.w,l.h)}else i.drawCachedElements(e,t,r,n)},t.exports=i},{"../../../math":85}],67:[function(e,t,r){"use strict";var n={};n.safeDrawImage=function(e,t,r,n,i,a,o,s,l,u){var c=this;try{e.drawImage(t,r,n,i,a,o,s,l,u)}catch(d){c.redrawHint("eles",!0),c.redrawHint("drag",!0),c.drawingImage=!0,c.redraw()}},n.drawInscribedImage=function(e,t,r){var n=this,i=r._private.position.x,a=r._private.position.y,o=r.pstyle("background-fit").value,s=r.pstyle("background-position-x"),l=r.pstyle("background-position-y"),u=r.pstyle("background-repeat").value,c=r.width(),d=r.height(),h=r._private.rscratch,p=r.pstyle("background-clip").value,f="node"===p,v=r.pstyle("background-image-opacity").value,g=t.width||t.cachedW,y=t.height||t.cachedH;null!=g&&null!=y||(document.body.appendChild(t),g=t.cachedW=t.width||t.offsetWidth,y=t.cachedH=t.height||t.offsetHeight,document.body.removeChild(t));var m=g,b=y,x=r.pstyle("background-width");"auto"!==x.value&&(m="%"===x.units?x.value/100*c:x.pfValue);var w=r.pstyle("background-height");if("auto"!==w.value&&(b="%"===w.units?w.value/100*d:w.pfValue),0!==m&&0!==b){if("contain"===o){var E=Math.min(c/m,d/b);m*=E,b*=E}else if("cover"===o){var E=Math.max(c/m,d/b);m*=E,b*=E}var _=i-c/2;_+="%"===s.units?(c-m)*s.value/100:s.pfValue;var P=a-d/2;P+="%"===l.units?(d-b)*l.value/100:l.pfValue,h.pathCache&&(_-=i,P-=a,i=0,a=0);var S=e.globalAlpha;if(e.globalAlpha=v,"no-repeat"===u)f&&(e.save(),h.pathCache?e.clip(h.pathCache):(n.nodeShapes[n.getNodeShape(r)].draw(e,i,a,c,d),e.clip())),n.safeDrawImage(e,t,0,0,g,y,_,P,m,b),f&&e.restore();else{var k=e.createPattern(t,u);e.fillStyle=k,n.nodeShapes[n.getNodeShape(r)].draw(e,i,a,c,d),e.translate(_,P),e.fill(),e.translate(-_,-P)}e.globalAlpha=S}},t.exports=n},{}],68:[function(e,t,r){"use strict";function n(e,t,r,n,i,a){var a=a||5;e.beginPath(),e.moveTo(t+a,r),e.lineTo(t+n-a,r),e.quadraticCurveTo(t+n,r,t+n,r+a),e.lineTo(t+n,r+i-a),e.quadraticCurveTo(t+n,r+i,t+n-a,r+i),e.lineTo(t+a,r+i),e.quadraticCurveTo(t,r+i,t,r+i-a),e.lineTo(t,r+a),e.quadraticCurveTo(t,r,t+a,r),e.closePath(),e.fill()}var i=e("../../../util"),a=e("../../../math"),o={};o.eleTextBiggerThanMin=function(e,t){if(!t){var r=e.cy().zoom(),n=this.getPixelRatio(),i=Math.ceil(a.log2(r*n));t=Math.pow(2,i)}var o=e.pstyle("font-size").pfValue*t,s=e.pstyle("min-zoomed-font-size").pfValue;return!(s>o)},o.drawElementText=function(e,t,r){var n=this;if(void 0===r){if(!n.eleTextBiggerThanMin(t))return}else if(!r)return;if(t.isNode()){var i=t.pstyle("label");if(!i||!i.value)return;var a=t.pstyle("text-halign").strValue;t.pstyle("text-valign").strValue;switch(a){case"left":e.textAlign="right";break;case"right":e.textAlign="left";break;default:e.textAlign="center"}e.textBaseline="bottom"}else{var i=t.pstyle("label"),o=t.pstyle("source-label"),s=t.pstyle("target-label");if(!(i&&i.value||o&&o.value||s&&s.value))return;e.textAlign="center",e.textBaseline="bottom"}n.drawText(e,t),t.isEdge()&&(n.drawText(e,t,"source"),n.drawText(e,t,"target"))},o.drawNodeText=o.drawEdgeText=o.drawElementText,o.getFontCache=function(e){var t;this.fontCaches=this.fontCaches||[];for(var r=0;r<this.fontCaches.length;r++)if(t=this.fontCaches[r],t.context===e)return t;return t={context:e},this.fontCaches.push(t),t},o.setupTextStyle=function(e,t){var r=t.effectiveOpacity(),n=t.pstyle("font-style").strValue,i=t.pstyle("font-size").pfValue+"px",a=t.pstyle("font-family").strValue,o=t.pstyle("font-weight").strValue,s=t.pstyle("text-opacity").value*t.pstyle("opacity").value*r,l=t.pstyle("text-outline-opacity").value*s,u=t.pstyle("color").value,c=t.pstyle("text-outline-color").value,d=t.pstyle("text-shadow-blur").pfValue,h=t.pstyle("text-shadow-opacity").value,p=t.pstyle("text-shadow-color").value,f=t.pstyle("text-shadow-offset-x").pfValue,v=t.pstyle("text-shadow-offset-y").pfValue,g=t._private.fontKey,y=this.getFontCache(e);y.key!==g&&(e.font=n+" "+o+" "+i+" "+a,y.key=g),e.lineJoin="round",this.fillStyle(e,u[0],u[1],u[2],s),this.strokeStyle(e,c[0],c[1],c[2],l),this.shadowStyle(e,p,h,d,f,v)},o.drawText=function(e,t,r){var a=t._private,o=a.rscratch,s=t.effectiveOpacity();if(0!==s&&0!==t.pstyle("text-opacity").value){var l=i.getPrefixedProperty(o,"labelX",r),u=i.getPrefixedProperty(o,"labelY",r),c=this.getLabelText(t,r);if(null!=c&&""!==c&&!isNaN(l)&&!isNaN(u)){this.setupTextStyle(e,t);var d=r?r+"-":"",h=i.getPrefixedProperty(o,"labelWidth",r),p=i.getPrefixedProperty(o,"labelHeight",r),f=i.getPrefixedProperty(o,"labelAngle",r),v=t.pstyle(d+"text-margin-x").pfValue,g=t.pstyle(d+"text-margin-y").pfValue,y=t.isEdge(),m=t.isNode(),b=t.pstyle("text-halign").value,x=t.pstyle("text-valign").value;y&&(b="center",x="center"),l+=v,u+=g;var w,E=t.pstyle("text-rotation");if(w="autorotate"===E.strValue?y?f:0:"none"===E.strValue?0:E.pfValue,0!==w){var _=l,P=u;e.translate(_,P),e.rotate(w),l=0,u=0}if(m){var S=t.pstyle("padding-left").pfValue,k=t.pstyle("padding-right").pfValue,T=t.pstyle("padding-top").pfValue,D=t.pstyle("padding-bottom").pfValue;l+=S/2,l-=k/2,u+=T/2,u-=D/2}switch(x){case"top":break;case"center":u+=p/2;break;case"bottom":u+=p}var C=t.pstyle("text-background-opacity").value,M=t.pstyle("text-border-opacity").value,N=t.pstyle("text-border-width").pfValue;if(C>0||N>0&&M>0){var B=l;switch(b){case"left":B-=h;break;case"center":B-=h/2;break;case"right":}var z=u;switch(x){case"top":z-=p;break;case"center":z-=p/2;break;case"bottom":}if(C>0){var I=e.fillStyle,L=t.pstyle("text-background-color").value;e.fillStyle="rgba("+L[0]+","+L[1]+","+L[2]+","+C*s+")";var O=t.pstyle("text-background-shape").strValue;"roundrectangle"==O?n(e,B,z,h,p,2):e.fillRect(B,z,h,p),e.fillStyle=I}if(N>0&&M>0){var A=e.strokeStyle,R=e.lineWidth,q=t.pstyle("text-border-color").value,V=t.pstyle("text-border-style").value;if(e.strokeStyle="rgba("+q[0]+","+q[1]+","+q[2]+","+M*s+")",e.lineWidth=N,e.setLineDash)switch(V){case"dotted":e.setLineDash([1,1]);break;case"dashed":e.setLineDash([4,2]);break;case"double":e.lineWidth=N/4,e.setLineDash([]);break;case"solid":e.setLineDash([])}if(e.strokeRect(B,z,h,p),"double"===V){var F=N/2;e.strokeRect(B+F,z+F,h-2*F,p-2*F)}e.setLineDash&&e.setLineDash([]), +e.lineWidth=R,e.strokeStyle=A}}var j=2*t.pstyle("text-outline-width").pfValue;if(j>0&&(e.lineWidth=j),"wrap"===t.pstyle("text-wrap").value){var X=o.labelWrapCachedLines,Y=p/X.length;switch(x){case"top":u-=(X.length-1)*Y;break;case"bottom":break;default:case"center":u-=(X.length-1)*Y/2}for(var W=0;W<X.length;W++)j>0&&e.strokeText(X[W],l,u),e.fillText(X[W],l,u),u+=Y}else j>0&&e.strokeText(c,l,u),e.fillText(c,l,u);0!==w&&(e.rotate(-w),e.translate(-_,-P)),this.shadowStyle(e,"transparent",0)}}},t.exports=o},{"../../../math":85,"../../../util":100}],69:[function(e,t,r){"use strict";var n=e("../../../is"),i={};i.drawNode=function(e,t,r,i){var a,o,s=this,l=t._private.rscratch,u=t._private,c=c||u.position;if(n.number(c.x)&&n.number(c.y)){var d,h=this.usePaths(),p=!1,f=t.effectiveOpacity();if(0!==f){a=t.width()+t.pstyle("padding-left").pfValue+t.pstyle("padding-right").pfValue,o=t.height()+t.pstyle("padding-top").pfValue+t.pstyle("padding-bottom").pfValue,e.lineWidth=t.pstyle("border-width").pfValue;var v;r&&(v=r,e.translate(-v.x1,-v.y1));var g,y=t.pstyle("background-image"),m=y.value[2]||y.value[1];if(void 0!==m){g=this.getCachedImage(m,function(){t.trigger("background"),s.redrawHint("eles",!0),s.redrawHint("drag",!0),s.drawingImage=!0,s.redraw()});var b=u.backgrounding;u.backgrounding=!g.complete,b!==u.backgrounding&&t.updateStyle(!1)}var x=t.pstyle("background-color").value,w=t.pstyle("border-color").value,E=t.pstyle("border-style").value;this.fillStyle(e,x[0],x[1],x[2],t.pstyle("background-opacity").value*f),this.strokeStyle(e,w[0],w[1],w[2],t.pstyle("border-opacity").value*f);var _=t.pstyle("shadow-blur").pfValue,P=t.pstyle("shadow-opacity").value,S=t.pstyle("shadow-color").value,k=t.pstyle("shadow-offset-x").pfValue,T=t.pstyle("shadow-offset-y").pfValue;if(this.shadowStyle(e,S,P,_,k,T),e.lineJoin="miter",e.setLineDash)switch(E){case"dotted":e.setLineDash([1,1]);break;case"dashed":e.setLineDash([4,2]);break;case"solid":case"double":e.setLineDash([])}var D=t.pstyle("shape").strValue,C=t.pstyle("shape-polygon-points").pfValue;if(h){var M=D+"$"+a+"$"+o+("polygon"===D?"$"+C.join("$"):"");e.translate(c.x,c.y),l.pathCacheKey===M?(d=l.pathCache,p=!0):(d=new Path2D,l.pathCacheKey=M,l.pathCache=d)}if(!p){var N=c;h&&(N={x:0,y:0}),s.nodeShapes[this.getNodeShape(t)].draw(d||e,N.x,N.y,a,o)}h?e.fill(d):e.fill(),this.shadowStyle(e,"transparent",0),void 0!==m&&g.complete&&this.drawInscribedImage(e,g,t);var B=t.pstyle("background-blacken").value,z=t.pstyle("border-width").pfValue;if(this.hasPie(t)&&(this.drawPie(e,t,f),0===B&&0===z||h||s.nodeShapes[this.getNodeShape(t)].draw(e,c.x,c.y,a,o)),B>0?(this.fillStyle(e,0,0,0,B),h?e.fill(d):e.fill()):0>B&&(this.fillStyle(e,255,255,255,-B),h?e.fill(d):e.fill()),z>0&&(h?e.stroke(d):e.stroke(),"double"===E)){e.lineWidth=t.pstyle("border-width").pfValue/3;var I=e.globalCompositeOperation;e.globalCompositeOperation="destination-out",h?e.stroke(d):e.stroke(),e.globalCompositeOperation=I}h&&e.translate(-c.x,-c.y),e.setLineDash&&e.setLineDash([]),s.drawElementText(e,t,i);var L=t.pstyle("overlay-padding").pfValue,O=t.pstyle("overlay-opacity").value,A=t.pstyle("overlay-color").value;O>0&&(this.fillStyle(e,A[0],A[1],A[2],O),s.nodeShapes.roundrectangle.draw(e,t._private.position.x,t._private.position.y,a+2*L,o+2*L),e.fill()),r&&e.translate(v.x1,v.y1)}}},i.hasPie=function(e){return e=e[0],e._private.hasPie},i.drawPie=function(e,t,r,n){t=t[0];var i=t._private,a=t.cy().style(),o=t.pstyle("pie-size"),s=t.width(),l=t.height(),n=n||i.position,u=n.x,c=n.y,d=Math.min(s,l)/2,h=0,p=this.usePaths();p&&(u=0,c=0),"%"===o.units?d=d*o.value/100:void 0!==o.pfValue&&(d=o.pfValue/2);for(var f=1;f<=a.pieBackgroundN;f++){var v=t.pstyle("pie-"+f+"-background-size").value,g=t.pstyle("pie-"+f+"-background-color").value,y=t.pstyle("pie-"+f+"-background-opacity").value*r,m=v/100;m+h>1&&(m=1-h);var b=1.5*Math.PI+2*Math.PI*h,x=2*Math.PI*m,w=b+x;0===v||h>=1||h+m>1||(e.beginPath(),e.moveTo(u,c),e.arc(u,c,d,b,w),e.closePath(),this.fillStyle(e,g[0],g[1],g[2],y),e.fill(),h+=m)}},t.exports=i},{"../../../is":83}],70:[function(e,t,r){"use strict";var n={},i=e("../../../util"),a=100;n.getPixelRatio=function(){var e=this.data.contexts[0];if(null!=this.forcedPixelRatio)return this.forcedPixelRatio;var t=e.backingStorePixelRatio||e.webkitBackingStorePixelRatio||e.mozBackingStorePixelRatio||e.msBackingStorePixelRatio||e.oBackingStorePixelRatio||e.backingStorePixelRatio||1;return(window.devicePixelRatio||1)/t},n.paintCache=function(e){for(var t,r=this.paintCaches=this.paintCaches||[],n=!0,i=0;i<r.length;i++)if(t=r[i],t.context===e){n=!1;break}return n&&(t={context:e},r.push(t)),t},n.fillStyle=function(e,t,r,n,i){e.fillStyle="rgba("+t+","+r+","+n+","+i+")"},n.strokeStyle=function(e,t,r,n,i){e.strokeStyle="rgba("+t+","+r+","+n+","+i+")"},n.shadowStyle=function(e,t,r,n,i,a){var o=this.cy.zoom();r>0?(e.shadowBlur=n*o,e.shadowColor="rgba("+t[0]+","+t[1]+","+t[2]+","+r+")",e.shadowOffsetX=i*o,e.shadowOffsetY=a*o):(e.shadowBlur=0,e.shadowColor="transparent",e.shadowOffsetX=0,e.shadowOffsetY=0)},n.matchCanvasSize=function(e){var t=this,r=t.data,n=e.clientWidth,i=e.clientHeight,a=t.getPixelRatio(),o=t.motionBlurPxRatio;e!==t.data.bufferCanvases[t.MOTIONBLUR_BUFFER_NODE]&&e!==t.data.bufferCanvases[t.MOTIONBLUR_BUFFER_DRAG]||(a=o);var s,l=n*a,u=i*a;if(l!==t.canvasWidth||u!==t.canvasHeight){t.fontCaches=null;var c=r.canvasContainer;c.style.width=n+"px",c.style.height=i+"px";for(var d=0;d<t.CANVAS_LAYERS;d++)s=r.canvases[d],s.width===l&&s.height===u||(s.width=l,s.height=u,s.style.width=n+"px",s.style.height=i+"px");for(var d=0;d<t.BUFFER_COUNT;d++)s=r.bufferCanvases[d],s.width===l&&s.height===u||(s.width=l,s.height=u,s.style.width=n+"px",s.style.height=i+"px");t.textureMult=1,1>=a&&(s=r.bufferCanvases[t.TEXTURE_BUFFER],t.textureMult=2,s.width=l*t.textureMult,s.height=u*t.textureMult),t.canvasWidth=l,t.canvasHeight=u}},n.renderTo=function(e,t,r,n){this.render({forcedContext:e,forcedZoom:t,forcedPan:r,drawAllLayers:!0,forcedPxRatio:n})},n.render=function(e){function t(e,t,r,n,i){var a=e.globalCompositeOperation;e.globalCompositeOperation="destination-out",c.fillStyle(e,255,255,255,c.motionBlurTransparency),e.fillRect(t,r,n,i),e.globalCompositeOperation=a}function r(e,r){var i,a,s,d;c.clearingMotionBlur||e!==p.bufferContexts[c.MOTIONBLUR_BUFFER_NODE]&&e!==p.bufferContexts[c.MOTIONBLUR_BUFFER_DRAG]?(i=k,a=P,s=c.canvasWidth,d=c.canvasHeight):(i={x:S.x*y,y:S.y*y},a=_*y,s=c.canvasWidth*y,d=c.canvasHeight*y),e.setTransform(1,0,0,1,0,0),"motionBlur"===r?t(e,0,0,s,d):n||void 0!==r&&!r||e.clearRect(0,0,s,d),o||(e.translate(i.x,i.y),e.scale(a,a)),u&&e.translate(u.x,u.y),l&&e.scale(l,l)}e=e||i.staticEmptyObject();var n=e.forcedContext,o=e.drawAllLayers,s=e.drawOnlyNodeLayer,l=e.forcedZoom,u=e.forcedPan,c=this,d=void 0===e.forcedPxRatio?this.getPixelRatio():e.forcedPxRatio,h=c.cy,p=c.data,f=p.canvasNeedsRedraw,v=c.textureOnViewport&&!n&&(c.pinching||c.hoverData.dragging||c.swipePanning||c.data.wheelZooming),g=void 0!==e.motionBlur?e.motionBlur:c.motionBlur,y=c.motionBlurPxRatio,m=h.hasCompoundNodes(),b=c.hoverData.draggingEles,x=!(!c.hoverData.selecting&&!c.touchData.selecting);g=g&&!n&&c.motionBlurEnabled&&!x;var w=g;n||(c.prevPxRatio!==d&&(c.invalidateContainerClientCoordsCache(),c.matchCanvasSize(c.container),c.redrawHint("eles",!0),c.redrawHint("drag",!0)),c.prevPxRatio=d),!n&&c.motionBlurTimeout&&clearTimeout(c.motionBlurTimeout),g&&(null==c.mbFrames&&(c.mbFrames=0),c.drawingImage||c.mbFrames++,c.mbFrames<3&&(w=!1),c.mbFrames>c.minMbLowQualFrames&&(c.motionBlurPxRatio=c.mbPxRBlurry)),c.clearingMotionBlur&&(c.motionBlurPxRatio=1),c.textureDrawLastFrame&&!v&&(f[c.NODE]=!0,f[c.SELECT_BOX]=!0);var E=h.style()._private.coreStyle,_=h.zoom(),P=void 0!==l?l:_,S=h.pan(),k={x:S.x,y:S.y},T={zoom:_,pan:{x:S.x,y:S.y}},D=c.prevViewport,C=void 0===D||T.zoom!==D.zoom||T.pan.x!==D.pan.x||T.pan.y!==D.pan.y;C||b&&!m||(c.motionBlurPxRatio=1),u&&(k=u),P*=d,k.x*=d,k.y*=d;var M=c.getCachedZSortedEles();if(v||(c.textureDrawLastFrame=!1),v){c.textureDrawLastFrame=!0;var N;if(!c.textureCache){c.textureCache={},N=c.textureCache.bb=h.mutableElements().boundingBox(),c.textureCache.texture=c.data.bufferCanvases[c.TEXTURE_BUFFER];var B=c.data.bufferContexts[c.TEXTURE_BUFFER];B.setTransform(1,0,0,1,0,0),B.clearRect(0,0,c.canvasWidth*c.textureMult,c.canvasHeight*c.textureMult),c.render({forcedContext:B,drawOnlyNodeLayer:!0,forcedPxRatio:d*c.textureMult});var T=c.textureCache.viewport={zoom:h.zoom(),pan:h.pan(),width:c.canvasWidth,height:c.canvasHeight};T.mpan={x:(0-T.pan.x)/T.zoom,y:(0-T.pan.y)/T.zoom}}f[c.DRAG]=!1,f[c.NODE]=!1;var z=p.contexts[c.NODE],I=c.textureCache.texture,T=c.textureCache.viewport;N=c.textureCache.bb,z.setTransform(1,0,0,1,0,0),g?t(z,0,0,T.width,T.height):z.clearRect(0,0,T.width,T.height);var L=E["outside-texture-bg-color"].value,O=E["outside-texture-bg-opacity"].value;c.fillStyle(z,L[0],L[1],L[2],O),z.fillRect(0,0,T.width,T.height);var _=h.zoom();r(z,!1),z.clearRect(T.mpan.x,T.mpan.y,T.width/T.zoom/d,T.height/T.zoom/d),z.drawImage(I,T.mpan.x,T.mpan.y,T.width/T.zoom/d,T.height/T.zoom/d)}else c.textureOnViewport&&!n&&(c.textureCache=null);var A=h.extent(),R=c.pinching||c.hoverData.dragging||c.swipePanning||c.data.wheelZooming||c.hoverData.draggingEles,q=c.hideEdgesOnViewport&&R,V=[];if(V[c.NODE]=!f[c.NODE]&&g&&!c.clearedForMotionBlur[c.NODE]||c.clearingMotionBlur,V[c.NODE]&&(c.clearedForMotionBlur[c.NODE]=!0),V[c.DRAG]=!f[c.DRAG]&&g&&!c.clearedForMotionBlur[c.DRAG]||c.clearingMotionBlur,V[c.DRAG]&&(c.clearedForMotionBlur[c.DRAG]=!0),f[c.NODE]||o||s||V[c.NODE]){var F=g&&!V[c.NODE]&&1!==y,z=n||(F?c.data.bufferContexts[c.MOTIONBLUR_BUFFER_NODE]:p.contexts[c.NODE]),j=g&&!F?"motionBlur":void 0;r(z,j),q?c.drawCachedNodes(z,M.nondrag,d,A):c.drawLayeredElements(z,M.nondrag,d,A),o||g||(f[c.NODE]=!1)}if(!s&&(f[c.DRAG]||o||V[c.DRAG])){var F=g&&!V[c.DRAG]&&1!==y,z=n||(F?c.data.bufferContexts[c.MOTIONBLUR_BUFFER_DRAG]:p.contexts[c.DRAG]);r(z,g&&!F?"motionBlur":void 0),q?c.drawCachedNodes(z,M.drag,d,A):c.drawCachedElements(z,M.drag,d,A),o||g||(f[c.DRAG]=!1)}if(c.showFps||!s&&f[c.SELECT_BOX]&&!o){var z=n||p.contexts[c.SELECT_BOX];if(r(z),1==c.selection[4]&&(c.hoverData.selecting||c.touchData.selecting)){var _=c.cy.zoom(),X=E["selection-box-border-width"].value/_;z.lineWidth=X,z.fillStyle="rgba("+E["selection-box-color"].value[0]+","+E["selection-box-color"].value[1]+","+E["selection-box-color"].value[2]+","+E["selection-box-opacity"].value+")",z.fillRect(c.selection[0],c.selection[1],c.selection[2]-c.selection[0],c.selection[3]-c.selection[1]),X>0&&(z.strokeStyle="rgba("+E["selection-box-border-color"].value[0]+","+E["selection-box-border-color"].value[1]+","+E["selection-box-border-color"].value[2]+","+E["selection-box-opacity"].value+")",z.strokeRect(c.selection[0],c.selection[1],c.selection[2]-c.selection[0],c.selection[3]-c.selection[1]))}if(p.bgActivePosistion&&!c.hoverData.selecting){var _=c.cy.zoom(),Y=p.bgActivePosistion;z.fillStyle="rgba("+E["active-bg-color"].value[0]+","+E["active-bg-color"].value[1]+","+E["active-bg-color"].value[2]+","+E["active-bg-opacity"].value+")",z.beginPath(),z.arc(Y.x,Y.y,E["active-bg-size"].pfValue/_,0,2*Math.PI),z.fill()}var W=c.lastRedrawTime;if(c.showFps&&W){W=Math.round(W);var $=Math.round(1e3/W);z.setTransform(1,0,0,1,0,0),z.fillStyle="rgba(255, 0, 0, 0.75)",z.strokeStyle="rgba(255, 0, 0, 0.75)",z.lineWidth=1,z.fillText("1 frame = "+W+" ms = "+$+" fps",0,20);var H=60;z.strokeRect(0,30,250,20),z.fillRect(0,30,250*Math.min($/H,1),20)}o||(f[c.SELECT_BOX]=!1)}if(g&&1!==y){var U=p.contexts[c.NODE],Z=c.data.bufferCanvases[c.MOTIONBLUR_BUFFER_NODE],G=p.contexts[c.DRAG],Q=c.data.bufferCanvases[c.MOTIONBLUR_BUFFER_DRAG],K=function(e,r,n){e.setTransform(1,0,0,1,0,0),n||!w?e.clearRect(0,0,c.canvasWidth,c.canvasHeight):t(e,0,0,c.canvasWidth,c.canvasHeight);var i=y;e.drawImage(r,0,0,c.canvasWidth*i,c.canvasHeight*i,0,0,c.canvasWidth,c.canvasHeight)};(f[c.NODE]||V[c.NODE])&&(K(U,Z,V[c.NODE]),f[c.NODE]=!1),(f[c.DRAG]||V[c.DRAG])&&(K(G,Q,V[c.DRAG]),f[c.DRAG]=!1)}c.prevViewport=T,c.clearingMotionBlur&&(c.clearingMotionBlur=!1,c.motionBlurCleared=!0,c.motionBlur=!0),g&&(c.motionBlurTimeout=setTimeout(function(){c.motionBlurTimeout=null,c.clearedForMotionBlur[c.NODE]=!1,c.clearedForMotionBlur[c.DRAG]=!1,c.motionBlur=!1,c.clearingMotionBlur=!v,c.mbFrames=0,f[c.NODE]=!0,f[c.DRAG]=!0,c.redraw()},a)),c.drawingImage=!1,n||c.initrender||(c.initrender=!0,h.trigger("initrender")),n||h.trigger("render")},t.exports=n},{"../../../util":100}],71:[function(e,t,r){"use strict";var n=e("../../../math"),i={};i.drawPolygonPath=function(e,t,r,n,i,a){var o=n/2,s=i/2;e.beginPath&&e.beginPath(),e.moveTo(t+o*a[0],r+s*a[1]);for(var l=1;l<a.length/2;l++)e.lineTo(t+o*a[2*l],r+s*a[2*l+1]);e.closePath()},i.drawRoundRectanglePath=function(e,t,r,i,a){var o=i/2,s=a/2,l=n.getRoundRectangleRadius(i,a);e.beginPath&&e.beginPath(),e.moveTo(t,r-s),e.arcTo(t+o,r-s,t+o,r,l),e.arcTo(t+o,r+s,t,r+s,l),e.arcTo(t-o,r+s,t-o,r,l),e.arcTo(t-o,r-s,t,r-s,l),e.lineTo(t,r-s),e.closePath()};for(var a=Math.sin(0),o=Math.cos(0),s={},l={},u=Math.PI/40,c=0*Math.PI;c<2*Math.PI;c+=u)s[c]=Math.sin(c),l[c]=Math.cos(c);i.drawEllipsePath=function(e,t,r,n,i){if(e.beginPath&&e.beginPath(),e.ellipse)e.ellipse(t,r,n/2,i/2,0,0,2*Math.PI);else for(var c,d,h=n/2,p=i/2,f=0*Math.PI;f<2*Math.PI;f+=u)c=t-h*s[f]*a+h*l[f]*o,d=r+p*l[f]*a+p*s[f]*o,0===f?e.moveTo(c,d):e.lineTo(c,d);e.closePath()},t.exports=i},{"../../../math":85}],72:[function(e,t,r){"use strict";var n=e("../../../math"),i=e("../../../util"),a=e("../../../heap"),o=e("./texture-cache-defs"),s=25,l=50,u=-4,c=2,d=3.99,h=8,p=1024,f=1024,v=1024,g=.5,y=.8,m=10,b=!1,x=!1,w=.15,E=.1,_=.9,P=.9,S=100,k=1,T={dequeue:"dequeue",downscale:"downscale",highQuality:"highQuality"},D=function(e){var t=this;t.renderer=e,t.onDequeues=[],t.setupDequeueing()},C=D.prototype;C.reasons=T,C.getTextureQueue=function(e){var t=this;return t.eleImgCaches=t.eleImgCaches||{},t.eleImgCaches[e]=t.eleImgCaches[e]||[]},C.getRetiredTextureQueue=function(e){var t=this,r=t.eleImgCaches.retired=t.eleImgCaches.retired||{},n=r[e]=r[e]||[];return n},C.getElementQueue=function(){var e=this,t=e.eleCacheQueue=e.eleCacheQueue||new a(function(e,t){return t.reqs-e.reqs});return t},C.getElementIdToQueue=function(){var e=this,t=e.eleIdToCacheQueue=e.eleIdToCacheQueue||{};return t},C.getElement=function(e,t,r,i,a){var o=this,p=this.renderer,g=e._private.rscratch,y=p.cy.zoom();if(null==i&&(i=Math.ceil(n.log2(y*r))),u>i)i=u;else if(y>=d||i>c)return null;var m=Math.pow(2,i),w=t.h*m,E=t.w*m,_=g.imgCaches=g.imgCaches||{},P=_[i];if(P)return P;var S;if(S=s>=w?s:l>=w?l:Math.ceil(w/l)*l,w>v||E>f||!b&&e.isEdge()||!x&&e.isParent())return null;var k=o.getTextureQueue(S),D=k[k.length-2],C=function(){return o.recycleTexture(S,E)||o.addTexture(S,E)};D||(D=k[k.length-1]),D||(D=C()),D.width-D.usedWidth<E&&(D=C());for(var M,N=p.eleTextBiggerThanMin(e,m),B=function(e){return e&&e.scaledLabelShown===N},z=a&&a===T.dequeue,I=a&&a===T.highQuality,L=a&&a===T.downscale,O=i+1;c>=O;O++){var A=_[O];if(A){M=A;break}}var R=M&&M.level===i+1?M:null,q=function(){D.context.drawImage(R.texture.canvas,R.x,0,R.width,R.height,D.usedWidth,0,E,w)};if(B(R))q();else if(B(M)){if(!I)return o.queueElement(e,t,M.level-1),M;for(var O=M.level;O>i;O--)R=o.getElement(e,t,r,O,T.downscale);q()}else{var V;if(!z&&!I&&!L)for(var O=i-1;O>=u;O--){var A=_[O];if(A){V=A;break}}if(B(V))return o.queueElement(e,t,i),V;D.context.translate(D.usedWidth,0),D.context.scale(m,m),p.drawElement(D.context,e,t,N),D.context.scale(1/m,1/m),D.context.translate(-D.usedWidth,0)}return P=_[i]={ele:e,x:D.usedWidth,texture:D,level:i,scale:m,width:E,height:w,scaledLabelShown:N},D.usedWidth+=Math.ceil(E+h),D.eleCaches.push(P),o.checkTextureFullness(D),P},C.invalidateElement=function(e){var t=this,r=e._private.rscratch.imgCaches;if(r)for(var n=u;c>=n;n++){var a=r[n];if(a){var o=a.texture;o.invalidatedWidth+=a.width,r[n]=null,i.removeFromArray(o.eleCaches,a),t.checkTextureUtility(o)}}},C.checkTextureUtility=function(e){e.invalidatedWidth>=g*e.width&&this.retireTexture(e)},C.checkTextureFullness=function(e){var t=this,r=t.getTextureQueue(e.height);e.usedWidth/e.width>y&&e.fullnessChecks>=m?i.removeFromArray(r,e):e.fullnessChecks++},C.retireTexture=function(e){var t=this,r=e.height,n=t.getTextureQueue(r);i.removeFromArray(n,e),e.retired=!0;for(var a=e.eleCaches,o=0;o<a.length;o++){var s=a[o],l=s.ele,u=s.level,c=l._private.rscratch.imgCaches;c&&(c[u]=null)}i.clearArray(a);var d=t.getRetiredTextureQueue(r);d.push(e)},C.addTexture=function(e,t){var r=this,n=r.getTextureQueue(e),i={};return n.push(i),i.eleCaches=[],i.height=e,i.width=Math.max(p,t),i.usedWidth=0,i.invalidatedWidth=0,i.fullnessChecks=0,i.canvas=document.createElement("canvas"),i.canvas.width=i.width,i.canvas.height=i.height,i.context=i.canvas.getContext("2d"),i},C.recycleTexture=function(e,t){for(var r=this,n=r.getTextureQueue(e),a=r.getRetiredTextureQueue(e),o=0;o<a.length;o++){var s=a[o];if(s.width>=t)return s.retired=!1,s.usedWidth=0,s.invalidatedWidth=0,s.fullnessChecks=0,i.clearArray(s.eleCaches),s.context.clearRect(0,0,s.width,s.height),i.removeFromArray(a,s),n.push(s),s}},C.queueElement=function(e,t,r){var i=this,a=i.getElementQueue(),o=i.getElementIdToQueue(),s=e.id(),l=o[s];if(l)l.level=Math.max(l.level,r),l.reqs++,a.updateItem(l);else{var u={ele:e,bb:t,position:n.copyPosition(e.position()),level:r,reqs:1};e.isEdge()&&(u.positions={source:n.copyPosition(e.source().position()),target:n.copyPosition(e.target().position())}),a.push(u),o[s]=u}},C.dequeue=function(e,t){for(var r=this,i=r.getElementQueue(),a=r.getElementIdToQueue(),o=[],s=0;k>s&&i.size()>0;s++){var l=i.pop();a[l.ele.id()]=null,o.push(l);var u,c=l.ele;u=(!c.isEdge()||n.arePositionsSame(c.source().position(),l.positions.source)&&n.arePositionsSame(c.target().position(),l.positions.target))&&n.arePositionsSame(c.position(),l.position)?l.bb:c.boundingBox(),r.getElement(l.ele,u,e,l.level,T.dequeue)}return o},C.onDequeue=function(e){this.onDequeues.push(e)},C.offDequeue=function(e){i.removeFromArray(this.onDequeues,e)},C.setupDequeueing=o.setupDequeueing({deqRedrawThreshold:S,deqCost:w,deqAvgCost:E,deqNoDrawCost:_,deqFastCost:P,deq:function(e,t,r){return e.dequeue(t,r)},onDeqd:function(e,t){for(var r=0;r<e.onDequeues.length;r++){var n=e.onDequeues[r];n(t)}},shouldRedraw:function(e,t,r,i){for(var a=0;a<t.length;a++){var o=t[a].bb;if(n.boundingBoxesIntersect(o,i))return!0}return!1},priority:function(e){return e.renderer.beforeRenderPriorities.eleTxrDeq}}),t.exports=D},{"../../../heap":81,"../../../math":85,"../../../util":100,"./texture-cache-defs":77}],73:[function(e,t,r){"use strict";var n=e("../../../is"),i={};i.createBuffer=function(e,t){var r=document.createElement("canvas");return r.width=e,r.height=t,[r,r.getContext("2d")]},i.bufferCanvasImage=function(e){var t=this.cy,r=t.mutableElements(),i=r.boundingBox(),a=e.full?Math.ceil(i.w):this.container.clientWidth,o=e.full?Math.ceil(i.h):this.container.clientHeight,s=n.number(e.maxWidth)||n.number(e.maxHeight),l=this.getPixelRatio(),u=1;if(void 0!==e.scale)a*=e.scale,o*=e.scale,u=e.scale;else if(s){var c=1/0,d=1/0;n.number(e.maxWidth)&&(c=u*e.maxWidth/a),n.number(e.maxHeight)&&(d=u*e.maxHeight/o),u=Math.min(c,d),a*=u,o*=u}s||(a*=l,o*=l,u*=l);var h=document.createElement("canvas");h.width=a,h.height=o,h.style.width=a+"px",h.style.height=o+"px";var p=h.getContext("2d");if(a>0&&o>0){p.clearRect(0,0,a,o),e.bg&&(p.fillStyle=e.bg,p.rect(0,0,a,o),p.fill()),p.globalCompositeOperation="source-over";var f=this.getCachedZSortedEles();if(e.full)p.translate(-i.x1*u,-i.y1*u),p.scale(u,u),this.drawElements(p,f);else{var v=t.pan(),g={x:v.x*u,y:v.y*u};u*=t.zoom(),p.translate(g.x,g.y),p.scale(u,u),this.drawElements(p,f)}}return h},i.png=function(e){return this.bufferCanvasImage(e).toDataURL("image/png")},i.jpg=function(e){return this.bufferCanvasImage(e).toDataURL("image/jpeg")},t.exports=i},{"../../../is":83}],74:[function(e,t,r){"use strict";function n(e){var t=this;t.data={canvases:new Array(u.CANVAS_LAYERS),contexts:new Array(u.CANVAS_LAYERS),canvasNeedsRedraw:new Array(u.CANVAS_LAYERS),bufferCanvases:new Array(u.BUFFER_COUNT),bufferContexts:new Array(u.CANVAS_LAYERS)},t.data.canvasContainer=document.createElement("div");var r=t.data.canvasContainer.style;t.data.canvasContainer.setAttribute("style","-webkit-tap-highlight-color: rgba(0,0,0,0);"),r.position="relative",r.zIndex="0",r.overflow="hidden";var n=e.cy.container();n.appendChild(t.data.canvasContainer),n.setAttribute("style",(n.getAttribute("style")||"")+"-webkit-tap-highlight-color: rgba(0,0,0,0);");for(var i=0;i<u.CANVAS_LAYERS;i++){var l=t.data.canvases[i]=document.createElement("canvas");t.data.contexts[i]=l.getContext("2d"),l.setAttribute("style","-webkit-user-select: none; -moz-user-select: -moz-none; user-select: none; -webkit-tap-highlight-color: rgba(0,0,0,0); outline-style: none;"+(a.ms()?" -ms-touch-action: none; touch-action: none; ":"")),l.style.position="absolute",l.setAttribute("data-id","layer"+i),l.style.zIndex=String(u.CANVAS_LAYERS-i),t.data.canvasContainer.appendChild(l),t.data.canvasNeedsRedraw[i]=!1}t.data.topCanvas=t.data.canvases[0],t.data.canvases[u.NODE].setAttribute("data-id","layer"+u.NODE+"-node"),t.data.canvases[u.SELECT_BOX].setAttribute("data-id","layer"+u.SELECT_BOX+"-selectbox"),t.data.canvases[u.DRAG].setAttribute("data-id","layer"+u.DRAG+"-drag");for(var i=0;i<u.BUFFER_COUNT;i++)t.data.bufferCanvases[i]=document.createElement("canvas"),t.data.bufferContexts[i]=t.data.bufferCanvases[i].getContext("2d"),t.data.bufferCanvases[i].style.position="absolute",t.data.bufferCanvases[i].setAttribute("data-id","buffer"+i),t.data.bufferCanvases[i].style.zIndex=String(-i-1),t.data.bufferCanvases[i].style.visibility="hidden";t.pathsEnabled=!0,t.data.eleTxrCache=new o(t),t.data.lyrTxrCache=new s(t,t.data.eleTxrCache),t.onUpdateEleCalcs(function(e,r){for(var n=0;n<r.length;n++){var i=r[n],a=i._private.rstyle,o=a.dirtyEvents;i.isNode()&&o&&1===o.length&&o.position||t.data.eleTxrCache.invalidateElement(i)}r.length>0&&t.data.lyrTxrCache.invalidateElements(r)})}var i=e("../../../util"),a=e("../../../is"),o=e("./ele-texture-cache"),s=e("./layered-texture-cache"),l=n,u=n.prototype;u.CANVAS_LAYERS=3,u.SELECT_BOX=0,u.DRAG=1,u.NODE=2,u.BUFFER_COUNT=3,u.TEXTURE_BUFFER=0,u.MOTIONBLUR_BUFFER_NODE=1,u.MOTIONBLUR_BUFFER_DRAG=2,u.redrawHint=function(e,t){var r=this;switch(e){case"eles":r.data.canvasNeedsRedraw[u.NODE]=t;break;case"drag":r.data.canvasNeedsRedraw[u.DRAG]=t;break;case"select":r.data.canvasNeedsRedraw[u.SELECT_BOX]=t}};var c="undefined"!=typeof Path2D;u.path2dEnabled=function(e){return void 0===e?this.pathsEnabled:void(this.pathsEnabled=!!e)},u.usePaths=function(){return c&&this.pathsEnabled},[e("./arrow-shapes"),e("./drawing-elements"),e("./drawing-edges"),e("./drawing-images"),e("./drawing-label-text"),e("./drawing-nodes"),e("./drawing-redraw"),e("./drawing-shapes"),e("./export-image"),e("./node-shapes")].forEach(function(e){i.extend(u,e)}),t.exports=l},{"../../../is":83,"../../../util":100,"./arrow-shapes":64,"./drawing-edges":65,"./drawing-elements":66,"./drawing-images":67,"./drawing-label-text":68,"./drawing-nodes":69,"./drawing-redraw":70,"./drawing-shapes":71,"./ele-texture-cache":72,"./export-image":73,"./layered-texture-cache":75,"./node-shapes":76}],75:[function(e,t,r){"use strict";function n(e,t){null!=e.imageSmoothingEnabled?e.imageSmoothingEnabled=t:(e.webkitImageSmoothingEnabled=t,e.mozImageSmoothingEnabled=t,e.msImageSmoothingEnabled=t)}var i=e("../../../util"),a=e("../../../math"),o=e("../../../heap"),s=e("../../../is"),l=e("./texture-cache-defs"),u=1,c=-4,d=2,h=3.99,p=50,f=50,v=!0,g=.15,y=.1,m=.9,b=.9,x=1,w=250,E=16e6,_=!0,P=!0,S=!0,k=function(e,t){var r=this,n=r.renderer=e;r.layersByLevel={},r.firstGet=!0,r.lastInvalidationTime=i.performanceNow()-2*w,r.skipping=!1,n.beforeRender(function(e,t){t-r.lastInvalidationTime<=w?r.skipping=!0:r.skipping=!1});var a=function(e,t){return t.reqs-e.reqs};r.layersQueue=new o(a),r.eleTxrCache=t,r.setupEleCacheInvalidation(),r.setupDequeueing()},T=k.prototype,D=0,C=Math.pow(2,53)-1;T.makeLayer=function(e,t){var r=Math.pow(2,t),n=Math.ceil(e.w*r),i=Math.ceil(e.h*r),a=document.createElement("canvas");a.width=n,a.height=i;var o={id:D=++D%C,bb:e,level:t,width:n,height:i,canvas:a,context:a.getContext("2d"),eles:[],elesQueue:[],reqs:0},s=o.context,l=-o.bb.x1,u=-o.bb.y1;return s.scale(r,r),s.translate(l,u),o},T.getLayers=function(e,t,r){var n=this,o=n.renderer,s=o.cy,l=s.zoom(),p=n.firstGet;if(n.firstGet=!1,null==r)if(r=Math.ceil(a.log2(l*t)),c>r)r=c;else if(l>=h||r>d)return null;n.validateLayersElesOrdering(r,e);var f,v,g=n.layersByLevel,y=Math.pow(2,r),m=g[r]=g[r]||[],b=n.levelIsComplete(r,e),x=function(){var t=function(t){return n.validateLayersElesOrdering(t,e),n.levelIsComplete(t,e)?(v=g[t],!0):void 0},a=function(e){if(!v)for(var n=r+e;n>=c&&d>=n&&!t(n);n+=e);};a(1),a(-1);for(var o=m.length-1;o>=0;o--){var s=m[o];s.invalid&&i.removeFromArray(m,s)}};if(b)return m;x();var w=function(){if(!f){f=a.makeBoundingBox();for(var t=0;t<e.length;t++)a.updateBoundingBox(f,e[t].boundingBox())}return f},P=function(e){e=e||{};var t=e.after;w();var i=f.w*y*(f.h*y);if(i>E)return null;var a=n.makeLayer(f,r);if(null!=t){var o=m.indexOf(t)+1;m.splice(o,0,a)}else(void 0===e.insert||e.insert)&&m.unshift(a);return a};if(n.skipping&&!p)return null;for(var S=null,k=e.length/u,T=_&&!p,D=0;D<e.length;D++){var C=e[D],M=C._private.rscratch,N=M.imgLayerCaches=M.imgLayerCaches||{},B=N[r];if(B)S=B;else{if((!S||S.eles.length>=k||u>1&&!a.boundingBoxInBoundingBox(S.bb,C.boundingBox()))&&(S=P({insert:!0,after:S}),!S))return null;v||T?n.queueLayer(S,C):n.drawEleInLayer(S,C,r,t),S.eles.push(C),N[r]=S}}return v?v:T?null:m},T.getEleLevelForLayerLevel=function(e,t){return e},T.drawEleInLayer=function(e,t,r,i){var a=this,o=this.renderer,s=e.context,l=t.boundingBox(),u=a.eleTxrCache,c=P?u.reasons.highQuality:void 0;r=a.getEleLevelForLayerLevel(r,i);var d=S?u.getElement(t,l,null,r,c):null;d?(v&&n(s,!1),s.drawImage(d.texture.canvas,d.x,0,d.width,d.height,l.x1,l.y1,l.w,l.h),v&&n(s,!0)):o.drawElement(s,t)},T.levelIsComplete=function(e,t){var r=this,n=r.layersByLevel[e];if(!n||0===n.length)return!1;for(var i=0,a=0;a<n.length;a++){var o=n[a];if(o.reqs>0)return!1;if(o.invalid)return!1;i+=o.eles.length}return i===t.length},T.validateLayersElesOrdering=function(e,t){var r=this.layersByLevel[e];if(r)for(var n=0;n<r.length;n++){for(var i=r[n],a=-1,o=0;o<t.length;o++)if(i.eles[0]===t[o]){a=o;break}if(0>a)this.invalidateLayer(i);else for(var s=a,o=0;o<i.eles.length;o++)if(i.eles[o]!==t[s+o]){this.invalidateLayer(i);break}}},T.updateElementsInLayers=function(e,t){for(var r=this,n=s.element(e[0]),i=0;i<e.length;i++)for(var a=n?null:e[i],o=n?e[i]:e[i].ele,l=o._private.rscratch,u=l.imgLayerCaches=l.imgLayerCaches||{},h=c;d>=h;h++){var p=u[h];p&&(a&&r.getEleLevelForLayerLevel(p.level)!==a.level||t(p,o,a))}},T.haveLayers=function(){for(var e=this,t=!1,r=c;d>=r;r++){var n=e.layersByLevel[r];if(n&&n.length>0){t=!0;break}}return t},T.invalidateElements=function(e){var t=this;t.lastInvalidationTime=i.performanceNow(),0!==e.length&&t.haveLayers()&&t.updateElementsInLayers(e,function(e,r,n){t.invalidateLayer(e)})},T.invalidateLayer=function(e){if(this.lastInvalidationTime=i.performanceNow(),!e.invalid){var t=e.level,r=e.eles,n=this.layersByLevel[t];i.removeFromArray(n,e),e.elesQueue=[],e.invalid=!0,e.replacement&&(e.replacement.invalid=!0);for(var a=0;a<r.length;a++){var o=r[a]._private.rscratch.imgLayerCaches;o&&(o[t]=null)}}},T.refineElementTextures=function(e){var t=this;t.updateElementsInLayers(e,function(e,r,n){var i=e.replacement;if(i||(i=e.replacement=t.makeLayer(e.bb,e.level),i.replaces=e,i.eles=e.eles),!i.reqs)for(var a=0;a<i.eles.length;a++)t.queueLayer(i,i.eles[a])})},T.setupEleCacheInvalidation=function(){var e=this,t=[];if(S){var r=i.debounce(function(){e.refineElementTextures(t),t=[]},f);e.eleTxrCache.onDequeue(function(e){for(var n=0;n<e.length;n++)t.push(e[n]);r()})}},T.queueLayer=function(e,t){var r=this,n=r.layersQueue,i=e.elesQueue,a=i.hasId=i.hasId||{};if(!e.replacement){if(t){if(a[t.id()])return;i.push(t),a[t.id()]=!0}e.reqs?(e.reqs++,n.updateItem(e)):(e.reqs=1,n.push(e))}},T.dequeue=function(e){for(var t=this,r=t.layersQueue,n=[],i=0;x>i&&0!==r.size();){var a=r.peek();if(a.replacement)r.pop();else if(a.replaces&&a!==a.replaces.replacement)r.pop();else if(a.invalid)r.pop();else{var o=a.elesQueue.shift();o&&(t.drawEleInLayer(a,o,a.level,e),i++),0===n.length&&n.push(!0),0===a.elesQueue.length&&(r.pop(),a.reqs=0,a.replaces&&t.applyLayerReplacement(a),t.requestRedraw())}}return n},T.applyLayerReplacement=function(e){var t=this,r=t.layersByLevel[e.level],n=e.replaces,i=r.indexOf(n);if(!(0>i||n.invalid)){r[i]=e;for(var a=0;a<e.eles.length;a++){var o=e.eles[a]._private,s=o.imgLayerCaches=o.imgLayerCaches||{};s&&(s[e.level]=e)}t.requestRedraw()}},T.requestRedraw=i.debounce(function(){var e=this.renderer;e.redrawHint("eles",!0),e.redrawHint("drag",!0),e.redraw()},100),T.setupDequeueing=l.setupDequeueing({deqRedrawThreshold:p,deqCost:g,deqAvgCost:y,deqNoDrawCost:m,deqFastCost:b,deq:function(e,t){return e.dequeue(t)},onDeqd:i.noop,shouldRedraw:i.trueify,priority:function(e){return e.renderer.beforeRenderPriorities.lyrTxrDeq}}),t.exports=k},{"../../../heap":81,"../../../is":83,"../../../math":85,"../../../util":100,"./texture-cache-defs":77}],76:[function(e,t,r){"use strict";var n={};n.nodeShapeImpl=function(e,t,r,n,i,a,o){switch(e){case"ellipse":return this.drawEllipsePath(t,r,n,i,a);case"polygon":return this.drawPolygonPath(t,r,n,i,a,o);case"roundrectangle":return this.drawRoundRectanglePath(t,r,n,i,a)}},t.exports=n},{}],77:[function(e,t,r){"use strict";var n=e("../../../util"),i=1e3/60;t.exports={setupDequeueing:function(e){return function(){var t=this,r=this.renderer;if(!t.dequeueingSetup){t.dequeueingSetup=!0;var a=n.debounce(function(){r.redrawHint("eles",!0),r.redrawHint("drag",!0),r.redraw()},e.deqRedrawThreshold),o=function(o,s){for(var l=n.performanceNow(),u=r.averageRedrawTime,c=r.lastRedrawTime,d=[],h=r.cy.extent(),p=r.getPixelRatio();;){var f=n.performanceNow(),v=f-l,g=f-s;if(i>c){var y=i-(o?u:0);if(g>=e.deqFastCost*y)break}else if(o){if(v>=e.deqCost*c||v>=e.deqAvgCost*u)break}else if(g>=e.deqNoDrawCost*i)break;var m=e.deq(t,p,h);if(!(m.length>0))break;for(var b=0;b<m.length;b++)d.push(m[b])}d.length>0&&(e.onDeqd(t,d),!o&&e.shouldRedraw(t,d,p,h)&&a())},s=e.priority||n.noop;r.beforeRender(o,s(t))}}}}},{"../../../util":100}],78:[function(e,t,r){"use strict";t.exports=[{name:"null",impl:e("./null")},{name:"base",impl:e("./base")},{name:"canvas",impl:e("./canvas")}]},{"./base":60,"./canvas":74,"./null":79}],79:[function(e,t,r){"use strict";function n(e){this.options=e,this.notifications=0}var i=function(){};n.prototype={recalculateRenderedStyle:i,notify:function(){this.notifications++},init:i},t.exports=n},{}],80:[function(e,t,r){/*! Weaver licensed under MIT (https://tldrlegal.com/license/mit-license), copyright Max Franz */ +"use strict";var n=e("./is"),i=e("./util"),a=e("./thread"),o=e("./promise"),s=e("./define"),l=function(t){if(!(this instanceof l))return new l(t);this._private={pass:[]};var r=4;if(n.number(t),"undefined"!=typeof navigator&&null!=navigator.hardwareConcurrency)t=navigator.hardwareConcurrency;else try{t=e("os").cpus().length}catch(i){t=r}for(var o=0;t>o;o++)this[o]=new a;this.length=t},u=l.prototype;i.extend(u,{instanceString:function(){return"fabric"},require:function(e,t){for(var r=0;r<this.length;r++){var n=this[r];n.require(e,t)}return this},random:function(){var e=Math.round((this.length-1)*Math.random()),t=this[e];return t},run:function(e){var t=this._private.pass.shift();return this.random().pass(t).run(e)},message:function(e){return this.random().message(e)},broadcast:function(e){for(var t=0;t<this.length;t++){var r=this[t];r.message(e)}return this},stop:function(){for(var e=0;e<this.length;e++){var t=this[e];t.stop()}return this},pass:function(e){var t=this._private.pass;if(!n.array(e))throw"Only arrays may be used with fabric.pass()";return t.push(e),this},spreadSize:function(){var e=Math.ceil(this._private.pass[0].length/this.length);return e=Math.max(1,e)},spread:function(e){for(var t=this,r=t._private,n=t.spreadSize(),i=r.pass.shift().concat([]),a=[],s=0;s<this.length;s++){var l=this[s],u=i.splice(0,n),c=l.pass(u).run(e);a.push(c);var d=0===i.length;if(d)break}return o.all(a).then(function(e){for(var t=[],r=0,n=0;n<e.length;n++)for(var i=e[n],a=0;a<i.length;a++){var o=i[a];t[r++]=o}return t})},map:function(e){var t=this;return t.require(e,"_$_$_fabmap"),t.spread(function(e){var t=[],r=resolve;resolve=function(e){t.push(e)};for(var n=0;n<e.length;n++){var i=t.length,a=_$_$_fabmap(e[n]),o=i===t.length;o&&t.push(a)}return resolve=r,t})},filter:function(e){var t=this._private,r=t.pass[0];return this.map(e).then(function(e){for(var t=[],n=0;n<r.length;n++){var i=r[n],a=e[n];a&&t.push(i)}return t})},sort:function(e){var t=this,r=this._private.pass[0].length,n=this.spreadSize();return e=e||function(e,t){return t>e?-1:e>t?1:0},t.require(e,"_$_$_cmp"),t.spread(function(e){var t=e.sort(_$_$_cmp);resolve(t)}).then(function(t){for(var i=function(n,i,a){i=Math.min(i,r),a=Math.min(a,r);for(var o=n,s=i,l=[],u=o;a>u;u++){var c=t[n],d=t[i];s>n&&(i>=a||e(c,d)<=0)?(l.push(c),n++):(l.push(d),i++)}for(var u=0;u<l.length;u++){var h=o+u;t[h]=l[u]}},a=n;r>a;a*=2)for(var o=0;r>o;o+=2*a)i(o,o+a,o+2*a);return t})}});var c=function(e){return e=e||{},function(t,r){var n=this._private.pass.shift();return this.random().pass(n)[e.threadFn](t,r)}};i.extend(u,{randomMap:c({threadFn:"map"}),reduce:c({threadFn:"reduce"}),reduceRight:c({threadFn:"reduceRight"})});var d=u;d.promise=d.run,d.terminate=d.halt=d.stop,d.include=d.require,i.extend(u,{on:s.on(),one:s.on({unbindSelfOnTrigger:!0}),off:s.off(),trigger:s.trigger()}),s.eventAliasesOn(u),t.exports=l},{"./define":44,"./is":83,"./promise":86,"./thread":98,"./util":100,os:void 0}],81:[function(e,t,r){/*! +Ported by Xueqiao Xu <xueqiaoxu@gmail.com>; + +PSF LICENSE AGREEMENT FOR PYTHON 2.7.2 + +1. This LICENSE AGREEMENT is between the Python Software Foundation (“PSF”), and the Individual or Organization (“Licensee”) accessing and otherwise using Python 2.7.2 software in source or binary form and its associated documentation. +2. Subject to the terms and conditions of this License Agreement, PSF hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use Python 2.7.2 alone or in any derivative version, provided, however, that PSF’s License Agreement and PSF’s notice of copyright, i.e., “Copyright © 2001-2012 Python Software Foundation; All Rights Reserved” are retained in Python 2.7.2 alone or in any derivative version prepared by Licensee. +3. In the event Licensee prepares a derivative work that is based on or incorporates Python 2.7.2 or any part thereof, and wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in any such work a brief summary of the changes made to Python 2.7.2. +4. PSF is making Python 2.7.2 available to Licensee on an “AS IS” basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 2.7.2 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. +5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 2.7.2 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.7.2, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. +6. This License Agreement will automatically terminate upon a material breach of its terms and conditions. +7. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between PSF and Licensee. This License Agreement does not grant permission to use PSF trademarks or trade name in a trademark sense to endorse or promote products or services of Licensee, or any third party. +8. By copying, installing or otherwise using Python 2.7.2, Licensee agrees to be bound by the terms and conditions of this License Agreement. +*/ +"use strict";(function(){var e,n,i,a,o,s,l,u,c,d,h,p,f,v,g;i=Math.floor,d=Math.min,n=function(e,t){return t>e?-1:e>t?1:0},c=function(e,t,r,a,o){var s;if(null==r&&(r=0),null==o&&(o=n),0>r)throw new Error("lo must be non-negative");for(null==a&&(a=e.length);a>r;)s=i((r+a)/2),o(t,e[s])<0?a=s:r=s+1;return[].splice.apply(e,[r,r-r].concat(t)),t},s=function(e,t,r){return null==r&&(r=n),e.push(t),v(e,0,e.length-1,r)},o=function(e,t){var r,i;return null==t&&(t=n),r=e.pop(),e.length?(i=e[0],e[0]=r,g(e,0,t)):i=r,i},u=function(e,t,r){var i;return null==r&&(r=n),i=e[0],e[0]=t,g(e,0,r),i},l=function(e,t,r){var i;return null==r&&(r=n),e.length&&r(e[0],t)<0&&(i=[e[0],t],t=i[0],e[0]=i[1],g(e,0,r)),t},a=function(e,t){var r,a,o,s,l,u;for(null==t&&(t=n),s=function(){u=[];for(var t=0,r=i(e.length/2);r>=0?r>t:t>r;r>=0?t++:t--)u.push(t);return u}.apply(this).reverse(),l=[],a=0,o=s.length;o>a;a++)r=s[a],l.push(g(e,r,t));return l},f=function(e,t,r){var i;return null==r&&(r=n),i=e.indexOf(t),-1!==i?(v(e,0,i,r),g(e,i,r)):void 0},h=function(e,t,r){var i,o,s,u,c;if(null==r&&(r=n),o=e.slice(0,t),!o.length)return o;for(a(o,r),c=e.slice(t),s=0,u=c.length;u>s;s++)i=c[s],l(o,i,r);return o.sort(r).reverse()},p=function(e,t,r){var i,s,l,u,h,p,f,v,g,y;if(null==r&&(r=n),10*t<=e.length){if(u=e.slice(0,t).sort(r),!u.length)return u;for(l=u[u.length-1],v=e.slice(t),h=0,f=v.length;f>h;h++)i=v[h],r(i,l)<0&&(c(u,i,0,null,r),u.pop(),l=u[u.length-1]);return u}for(a(e,r),y=[],s=p=0,g=d(t,e.length);g>=0?g>p:p>g;s=g>=0?++p:--p)y.push(o(e,r));return y},v=function(e,t,r,i){var a,o,s;for(null==i&&(i=n),a=e[r];r>t&&(s=r-1>>1,o=e[s],i(a,o)<0);)e[r]=o,r=s;return e[r]=a},g=function(e,t,r){var i,a,o,s,l;for(null==r&&(r=n),a=e.length,l=t,o=e[t],i=2*t+1;a>i;)s=i+1,a>s&&!(r(e[i],e[s])<0)&&(i=s),e[t]=e[i],t=i,i=2*t+1;return e[t]=o,v(e,l,t,r)},e=function(){function e(e){this.cmp=null!=e?e:n,this.nodes=[]}return e.push=s,e.pop=o,e.replace=u,e.pushpop=l,e.heapify=a,e.updateItem=f,e.nlargest=h,e.nsmallest=p,e.prototype.push=function(e){return s(this.nodes,e,this.cmp)},e.prototype.pop=function(){return o(this.nodes,this.cmp)},e.prototype.peek=function(){return this.nodes[0]},e.prototype.contains=function(e){return-1!==this.nodes.indexOf(e)},e.prototype.replace=function(e){return u(this.nodes,e,this.cmp)},e.prototype.pushpop=function(e){return l(this.nodes,e,this.cmp)},e.prototype.heapify=function(){return a(this.nodes,this.cmp)},e.prototype.updateItem=function(e){return f(this.nodes,e,this.cmp)},e.prototype.clear=function(){return this.nodes=[]},e.prototype.empty=function(){return 0===this.nodes.length},e.prototype.size=function(){return this.nodes.length},e.prototype.clone=function(){var t;return t=new e,t.nodes=this.nodes.slice(0),t},e.prototype.toArray=function(){return this.nodes.slice(0)},e.prototype.insert=e.prototype.push,e.prototype.top=e.prototype.peek,e.prototype.front=e.prototype.peek,e.prototype.has=e.prototype.contains,e.prototype.copy=e.prototype.clone,e}(),function(e,n){return"function"==typeof define&&define.amd?define([],n):"object"==typeof r?t.exports=n():e.Heap=n()}(this,function(){return e})}).call(this)},{}],82:[function(e,t,r){"use strict";e("./-preamble");var n=e("./window"),i=e("./is"),a=e("./core"),o=e("./extension"),s=e("./jquery-plugin"),l=e("./stylesheet"),u=e("./thread"),c=e("./fabric"),d=function(e){return void 0===e&&(e={}),i.plainObject(e)?new a(e):i.string(e)?o.apply(o,arguments):void 0};d.version=e("./version.json"),n&&n.jQuery&&s(n.jQuery,d),d.registerJquery=function(e){s(e,d)},d.stylesheet=d.Stylesheet=l,d.thread=d.Thread=u,d.fabric=d.Fabric=c,t.exports=d},{"./-preamble":1,"./core":37,"./extension":46,"./fabric":80,"./is":83,"./jquery-plugin":84,"./stylesheet":97,"./thread":98,"./version.json":106,"./window":107}],83:[function(e,t,r){"use strict";var n=e("./window"),i=n?n.navigator:null,a=n?n.document:null,o="string",s=typeof{},l="function",u=typeof HTMLElement,c=function(e){return e&&e.instanceString&&d.fn(e.instanceString)?e.instanceString():null},d={defined:function(e){return null!=e},string:function(e){return null!=e&&typeof e==o},fn:function(e){return null!=e&&typeof e===l},array:function(e){return Array.isArray?Array.isArray(e):null!=e&&e instanceof Array},plainObject:function(e){return null!=e&&typeof e===s&&!d.array(e)&&e.constructor===Object},object:function(e){return null!=e&&typeof e===s},number:function(e){return null!=e&&"number"==typeof e&&!isNaN(e)},integer:function(e){return d.number(e)&&Math.floor(e)===e},bool:function(e){return null!=e&&typeof e==typeof!0},htmlElement:function(e){return"undefined"===u?void 0:null!=e&&e instanceof HTMLElement},elementOrCollection:function(e){return d.element(e)||d.collection(e)},element:function(e){return"collection"===c(e)&&e._private.single},collection:function(e){return"collection"===c(e)&&!e._private.single},core:function(e){return"core"===c(e)},style:function(e){return"style"===c(e)},stylesheet:function(e){return"stylesheet"===c(e)},event:function(e){return"event"===c(e)},thread:function(e){return"thread"===c(e)},fabric:function(e){return"fabric"===c(e)},emptyString:function(e){return void 0===e||null===e?!0:!(""!==e&&!e.match(/^\s+$/))},nonemptyString:function(e){return!(!e||!d.string(e)||""===e||e.match(/^\s+$/))},domElement:function(e){return"undefined"==typeof HTMLElement?!1:e instanceof HTMLElement},boundingBox:function(e){return d.plainObject(e)&&d.number(e.x1)&&d.number(e.x2)&&d.number(e.y1)&&d.number(e.y2)},promise:function(e){return d.object(e)&&d.fn(e.then)},touch:function(){return n&&("ontouchstart"in n||n.DocumentTouch&&a instanceof DocumentTouch)},gecko:function(){return n&&("undefined"!=typeof InstallTrigger||"MozAppearance"in a.documentElement.style)},webkit:function(){return n&&("undefined"!=typeof webkitURL||"WebkitAppearance"in a.documentElement.style)},chromium:function(){return n&&"undefined"!=typeof chrome},khtml:function(){return i&&i.vendor.match(/kde/i)},khtmlEtc:function(){return d.khtml()||d.webkit()||d.chromium()},ms:function(){return i&&i.userAgent.match(/msie|trident|edge/i)},windows:function(){return i&&i.appVersion.match(/Win/i)},mac:function(){return i&&i.appVersion.match(/Mac/i)},linux:function(){return i&&i.appVersion.match(/Linux/i)},unix:function(){return i&&i.appVersion.match(/X11/i)}};t.exports=d},{"./window":107}],84:[function(e,t,r){"use strict";var n=e("./is"),i=function(e){var t=e[0]._cyreg=e[0]._cyreg||{};return t},a=function(e,t){e&&(e.fn.cytoscape||(e.fn.cytoscape=function(r){var a=e(this);if("get"===r)return i(a).cy;if(n.fn(r)){var o=r,s=i(a).cy;if(s&&s.isReady())s.trigger("ready",[],o);else{var l=i(a),u=l.readies=l.readies||[];u.push(o)}}else if(n.plainObject(r))return a.each(function(){var n=e.extend({},r,{container:e(this)[0]});t(n)})},e.cytoscape=t,null==e.fn.cy&&null==e.cy&&(e.fn.cy=e.fn.cytoscape,e.cy=e.cytoscape)))};t.exports=a},{"./is":83}],85:[function(e,t,r){"use strict";var n={};n.arePositionsSame=function(e,t){return e.x===t.x&&e.y===t.y},n.copyPosition=function(e){return{x:e.x,y:e.y}},n.array2point=function(e){return{x:e[0],y:e[1]}},n.deg2rad=function(e){return Math.PI*e/180},n.log2=Math.log2||function(e){return Math.log(e)/Math.log(2)},n.signum=function(e){return e>0?1:0>e?-1:0},n.dist=function(e,t){return Math.sqrt(n.sqdist(e,t))},n.sqdist=function(e,t){var r=t.x-e.x,n=t.y-e.y;return r*r+n*n},n.qbezierAt=function(e,t,r,n){return(1-n)*(1-n)*e+2*(1-n)*n*t+n*n*r},n.qbezierPtAt=function(e,t,r,i){return{x:n.qbezierAt(e.x,t.x,r.x,i),y:n.qbezierAt(e.y,t.y,r.y,i)}},n.lineAt=function(e,t,r,i){var a={x:t.x-e.x,y:t.y-e.y},o=n.dist(e,t),s={x:a.x/o,y:a.y/o};r=null==r?0:r;var i=null!=i?i:r*o;return{x:e.x+s.x*i,y:e.y+s.y*i}},n.lineAtDist=function(e,t,r){return n.lineAt(e,t,void 0,r)},n.triangleAngle=function(e,t,r){var i=n.dist(t,r),a=n.dist(e,r),o=n.dist(e,t);return Math.acos((i*i+a*a-o*o)/(2*i*a))},n.bound=function(e,t,r){return Math.max(e,Math.min(r,t))},n.makeBoundingBox=function(e){if(null==e)return{x1:1/0,y1:1/0,x2:-(1/0),y2:-(1/0),w:0,h:0};if(null!=e.x1&&null!=e.y1){if(null!=e.x2&&null!=e.y2&&e.x2>=e.x1&&e.y2>=e.y1)return{x1:e.x1,y1:e.y1,x2:e.x2,y2:e.y2,w:e.x2-e.x1,h:e.y2-e.y1};if(null!=e.w&&null!=e.h&&e.w>=0&&e.h>=0)return{x1:e.x1,y1:e.y1,x2:e.x1+e.w,y2:e.y1+e.h,w:e.w,h:e.h}}},n.updateBoundingBox=function(e,t){e.x1=Math.min(e.x1,t.x1),e.x2=Math.max(e.x2,t.x2),e.w=e.x2-e.x1,e.y1=Math.min(e.y1,t.y1),e.y2=Math.max(e.y2,t.y2),e.h=e.y2-e.y1},n.expandBoundingBox=function(e,t){return e.x1-=t,e.x2+=t,e.y1-=t,e.y2+=t,e.w=e.x2-e.x1,e.h=e.y2-e.y1,e},n.boundingBoxesIntersect=function(e,t){return e.x1>t.x2?!1:t.x1>e.x2?!1:e.x2<t.x1?!1:t.x2<e.x1?!1:e.y2<t.y1?!1:t.y2<e.y1?!1:e.y1>t.y2?!1:!(t.y1>e.y2)},n.inBoundingBox=function(e,t,r){return e.x1<=t&&t<=e.x2&&e.y1<=r&&r<=e.y2},n.pointInBoundingBox=function(e,t){return this.inBoundingBox(e,t.x,t.y)},n.boundingBoxInBoundingBox=function(e,t){return n.inBoundingBox(e,t.x1,t.y1)&&n.inBoundingBox(e,t.x2,t.y2)},n.roundRectangleIntersectLine=function(e,t,r,n,i,a,o){var s,l=this.getRoundRectangleRadius(i,a),u=i/2,c=a/2,d=r-u+l-o,h=n-c-o,p=r+u-l+o,f=h;if(s=this.finiteLinesIntersect(e,t,r,n,d,h,p,f,!1),s.length>0)return s;var v=r+u+o,g=n-c+l-o,y=v,m=n+c-l+o;if(s=this.finiteLinesIntersect(e,t,r,n,v,g,y,m,!1),s.length>0)return s;var b=r-u+l-o,x=n+c+o,w=r+u-l+o,E=x;if(s=this.finiteLinesIntersect(e,t,r,n,b,x,w,E,!1),s.length>0)return s;var _=r-u-o,P=n-c+l-o,S=_,k=n+c-l+o;if(s=this.finiteLinesIntersect(e,t,r,n,_,P,S,k,!1),s.length>0)return s;var T,D=r-u+l,C=n-c+l;if(T=this.intersectLineCircle(e,t,r,n,D,C,l+o),T.length>0&&T[0]<=D&&T[1]<=C)return[T[0],T[1]];var M=r+u-l,N=n-c+l;if(T=this.intersectLineCircle(e,t,r,n,M,N,l+o),T.length>0&&T[0]>=M&&T[1]<=N)return[T[0],T[1]];var B=r+u-l,z=n+c-l;if(T=this.intersectLineCircle(e,t,r,n,B,z,l+o),T.length>0&&T[0]>=B&&T[1]>=z)return[T[0],T[1]];var I=r-u+l,L=n+c-l;return T=this.intersectLineCircle(e,t,r,n,I,L,l+o),T.length>0&&T[0]<=I&&T[1]>=L?[T[0],T[1]]:[]},n.inLineVicinity=function(e,t,r,n,i,a,o){var s=o,l=Math.min(r,i),u=Math.max(r,i),c=Math.min(n,a),d=Math.max(n,a);return e>=l-s&&u+s>=e&&t>=c-s&&d+s>=t},n.inBezierVicinity=function(e,t,r,n,i,a,o,s,l){var u={x1:Math.min(r,o,i)-l,x2:Math.max(r,o,i)+l,y1:Math.min(n,s,a)-l,y2:Math.max(n,s,a)+l};return!(e<u.x1||e>u.x2||t<u.y1||t>u.y2)},n.solveCubic=function(e,t,r,n,i){t/=e,r/=e,n/=e;var a,o,s,l,u,c,d,h;return o=(3*r-t*t)/9,s=-(27*n)+t*(9*r-2*(t*t)),s/=54,a=o*o*o+s*s,i[1]=0,d=t/3,a>0?(u=s+Math.sqrt(a),u=0>u?-Math.pow(-u,1/3):Math.pow(u,1/3),c=s-Math.sqrt(a),c=0>c?-Math.pow(-c,1/3):Math.pow(c,1/3),i[0]=-d+u+c,d+=(u+c)/2,i[4]=i[2]=-d,d=Math.sqrt(3)*(-c+u)/2,i[3]=d,void(i[5]=-d)):(i[5]=i[3]=0,0===a?(h=0>s?-Math.pow(-s,1/3):Math.pow(s,1/3),i[0]=-d+2*h,void(i[4]=i[2]=-(h+d))):(o=-o,l=o*o*o,l=Math.acos(s/Math.sqrt(l)),h=2*Math.sqrt(o),i[0]=-d+h*Math.cos(l/3),i[2]=-d+h*Math.cos((l+2*Math.PI)/3),void(i[4]=-d+h*Math.cos((l+4*Math.PI)/3))))},n.sqdistToQuadraticBezier=function(e,t,r,n,i,a,o,s){var l=1*r*r-4*r*i+2*r*o+4*i*i-4*i*o+o*o+n*n-4*n*a+2*n*s+4*a*a-4*a*s+s*s,u=9*r*i-3*r*r-3*r*o-6*i*i+3*i*o+9*n*a-3*n*n-3*n*s-6*a*a+3*a*s,c=3*r*r-6*r*i+r*o-r*e+2*i*i+2*i*e-o*e+3*n*n-6*n*a+n*s-n*t+2*a*a+2*a*t-s*t,d=1*r*i-r*r+r*e-i*e+n*a-n*n+n*t-a*t,h=[];this.solveCubic(l,u,c,d,h);for(var p=1e-7,f=[],v=0;6>v;v+=2)Math.abs(h[v+1])<p&&h[v]>=0&&h[v]<=1&&f.push(h[v]);f.push(1),f.push(0);for(var g,y,m,b,x=-1,w=0;w<f.length;w++)y=Math.pow(1-f[w],2)*r+2*(1-f[w])*f[w]*i+f[w]*f[w]*o,m=Math.pow(1-f[w],2)*n+2*(1-f[w])*f[w]*a+f[w]*f[w]*s,b=Math.pow(y-e,2)+Math.pow(m-t,2),x>=0?x>b&&(x=b,g=f[w]):(x=b,g=f[w]);return x},n.sqdistToFiniteLine=function(e,t,r,n,i,a){var o=[e-r,t-n],s=[i-r,a-n],l=s[0]*s[0]+s[1]*s[1],u=o[0]*o[0]+o[1]*o[1],c=o[0]*s[0]+o[1]*s[1],d=c*c/l;return 0>c?u:d>l?(e-i)*(e-i)+(t-a)*(t-a):u-d},n.pointInsidePolygonPoints=function(e,t,r){for(var n,i,a,o,s,l=0,u=0,c=0;c<r.length/2;c++)if(n=r[2*c],i=r[2*c+1],c+1<r.length/2?(a=r[2*(c+1)],o=r[2*(c+1)+1]):(a=r[2*(c+1-r.length/2)],o=r[2*(c+1-r.length/2)+1]),n==e&&a==e);else{if(!(n>=e&&e>=a||e>=n&&a>=e))continue;s=(e-n)/(a-n)*(o-i)+i,s>t&&l++,t>s&&u++}return l%2!==0},n.pointInsidePolygon=function(e,t,r,i,a,o,s,l,u){var c,d=new Array(r.length);null!=l[0]?(c=Math.atan(l[1]/l[0]),l[0]<0?c+=Math.PI/2:c=-c-Math.PI/2):c=l;for(var h=Math.cos(-c),p=Math.sin(-c),f=0;f<d.length/2;f++)d[2*f]=o/2*(r[2*f]*h-r[2*f+1]*p),d[2*f+1]=s/2*(r[2*f+1]*h+r[2*f]*p),d[2*f]+=i,d[2*f+1]+=a;var v;if(u>0){var g=this.expandPolygon(d,-u);v=this.joinLines(g)}else v=d;return n.pointInsidePolygonPoints(e,t,v)},n.joinLines=function(e){for(var t,r,n,i,a,o,s,l,u=new Array(e.length/2),c=0;c<e.length/4;c++){t=e[4*c],r=e[4*c+1],n=e[4*c+2],i=e[4*c+3],c<e.length/4-1?(a=e[4*(c+1)],o=e[4*(c+1)+1],s=e[4*(c+1)+2],l=e[4*(c+1)+3]):(a=e[0],o=e[1],s=e[2],l=e[3]);var d=this.finiteLinesIntersect(t,r,n,i,a,o,s,l,!0);u[2*c]=d[0],u[2*c+1]=d[1]}return u},n.expandPolygon=function(e,t){for(var r,n,i,a,o=new Array(2*e.length),s=0;s<e.length/2;s++){r=e[2*s],n=e[2*s+1],s<e.length/2-1?(i=e[2*(s+1)],a=e[2*(s+1)+1]):(i=e[0],a=e[1]);var l=a-n,u=-(i-r),c=Math.sqrt(l*l+u*u),d=l/c,h=u/c;o[4*s]=r+d*t,o[4*s+1]=n+h*t,o[4*s+2]=i+d*t,o[4*s+3]=a+h*t}return o},n.intersectLineEllipse=function(e,t,r,n,i,a){var o=r-e,s=n-t;o/=i,s/=a;var l=Math.sqrt(o*o+s*s),u=l-1;if(0>u)return[];var c=u/l;return[(r-e)*c+e,(n-t)*c+t]},n.intersectLineCircle=function(e,t,r,n,i,a,o){var s=[r-e,n-t],l=[i,a],u=[e-i,t-a],c=s[0]*s[0]+s[1]*s[1],d=2*(u[0]*s[0]+u[1]*s[1]),l=u[0]*u[0]+u[1]*u[1]-o*o,h=d*d-4*c*l;if(0>h)return[];var p=(-d+Math.sqrt(h))/(2*c),f=(-d-Math.sqrt(h))/(2*c),v=Math.min(p,f),g=Math.max(p,f),y=[];if(v>=0&&1>=v&&y.push(v),g>=0&&1>=g&&y.push(g),0===y.length)return[];var m=y[0]*s[0]+e,b=y[0]*s[1]+t;if(y.length>1){if(y[0]==y[1])return[m,b];var x=y[1]*s[0]+e,w=y[1]*s[1]+t;return[m,b,x,w]}return[m,b]},n.findCircleNearPoint=function(e,t,r,n,i){var a=n-e,o=i-t,s=Math.sqrt(a*a+o*o),l=a/s,u=o/s;return[e+l*r,t+u*r]},n.findMaxSqDistanceToOrigin=function(e){for(var t,r=1e-6,n=0;n<e.length/2;n++)t=e[2*n]*e[2*n]+e[2*n+1]*e[2*n+1],t>r&&(r=t);return r},n.midOfThree=function(e,t,r){return e>=t&&r>=e||e>=r&&t>=e?e:t>=e&&r>=t||t>=r&&e>=t?t:r},n.finiteLinesIntersect=function(e,t,r,n,i,a,o,s,l){var u=e-i,c=r-e,d=o-i,h=t-a,p=n-t,f=s-a,v=d*h-f*u,g=c*h-p*u,y=f*c-d*p;if(0!==y){var m=v/y,b=g/y,x=.001,w=0-x,E=1+x;return m>=w&&E>=m&&b>=w&&E>=b?[e+m*c,t+m*p]:l?[e+m*c,t+m*p]:[]}return 0===v||0===g?this.midOfThree(e,r,o)===o?[o,s]:this.midOfThree(e,r,i)===i?[i,a]:this.midOfThree(i,o,r)===r?[r,n]:[]:[]},n.polygonIntersectLine=function(e,t,r,i,a,o,s,l){for(var u,c=[],d=new Array(r.length),h=0;h<d.length/2;h++)d[2*h]=r[2*h]*o+i,d[2*h+1]=r[2*h+1]*s+a;var p;if(l>0){var f=n.expandPolygon(d,-l);p=n.joinLines(f)}else p=d;for(var v,g,y,m,h=0;h<p.length/2;h++)v=p[2*h],g=p[2*h+1],h<p.length/2-1?(y=p[2*(h+1)],m=p[2*(h+1)+1]):(y=p[0],m=p[1]),u=this.finiteLinesIntersect(e,t,i,a,v,g,y,m),0!==u.length&&c.push(u[0],u[1]);return c},n.shortenIntersection=function(e,t,r){var n=[e[0]-t[0],e[1]-t[1]],i=Math.sqrt(n[0]*n[0]+n[1]*n[1]),a=(i-r)/i;return 0>a&&(a=1e-5),[t[0]+a*n[0],t[1]+a*n[1]]},n.generateUnitNgonPointsFitToSquare=function(e,t){var r=n.generateUnitNgonPoints(e,t);return r=n.fitPolygonToSquare(r)},n.fitPolygonToSquare=function(e){for(var t,r,n=e.length/2,i=1/0,a=1/0,o=-(1/0),s=-(1/0),l=0;n>l;l++)t=e[2*l],r=e[2*l+1],i=Math.min(i,t),o=Math.max(o,t),a=Math.min(a,r),s=Math.max(s,r);for(var u=2/(o-i),c=2/(s-a),l=0;n>l;l++)t=e[2*l]=e[2*l]*u,r=e[2*l+1]=e[2*l+1]*c,i=Math.min(i,t),o=Math.max(o,t),a=Math.min(a,r),s=Math.max(s,r);if(-1>a)for(var l=0;n>l;l++)r=e[2*l+1]=e[2*l+1]+(-1-a);return e},n.generateUnitNgonPoints=function(e,t){var r=1/e*2*Math.PI,n=e%2===0?Math.PI/2+r/2:Math.PI/2;n+=t;for(var i,a,o,s=new Array(2*e),l=0;e>l;l++)i=l*r+n,a=s[2*l]=Math.cos(i),o=s[2*l+1]=Math.sin(-i);return s},n.getRoundRectangleRadius=function(e,t){return Math.min(e/4,t/4,8)},t.exports=n},{}],86:[function(e,t,r){/*! +Embeddable Minimum Strictly-Compliant Promises/A+ 1.1.1 Thenable +Copyright (c) 2013-2014 Ralf S. Engelschall (http://engelschall.com) +Licensed under The MIT License (http://opensource.org/licenses/MIT) +*/ +"use strict";var n=0,i=1,a=2,o=function(e){return this instanceof o?(this.id="Thenable/1.0.7",this.state=n,this.fulfillValue=void 0,this.rejectReason=void 0,this.onFulfilled=[],this.onRejected=[],this.proxy={then:this.then.bind(this)},void("function"==typeof e&&e.call(this,this.fulfill.bind(this),this.reject.bind(this)))):new o(e)};o.prototype={fulfill:function(e){return s(this,i,"fulfillValue",e)},reject:function(e){return s(this,a,"rejectReason",e)},then:function(e,t){var r=this,n=new o;return r.onFulfilled.push(c(e,n,"fulfill")),r.onRejected.push(c(t,n,"reject")),l(r),n.proxy}};var s=function(e,t,r,i){return e.state===n&&(e.state=t,e[r]=i,l(e)),e},l=function(e){e.state===i?u(e,"onFulfilled",e.fulfillValue):e.state===a&&u(e,"onRejected",e.rejectReason)},u=function(e,t,r){if(0!==e[t].length){var n=e[t];e[t]=[];var i=function(){for(var e=0;e<n.length;e++)n[e](r)};"function"==typeof setImmediate?setImmediate(i):setTimeout(i,0)}},c=function(e,t,r){return function(n){if("function"!=typeof e)t[r].call(t,n);else{var i;try{i=e(n)}catch(a){return void t.reject(a)}d(t,i)}}},d=function(e,t){if(e===t||e.proxy===t)return void e.reject(new TypeError("cannot resolve promise with itself"));var r;if("object"==typeof t&&null!==t||"function"==typeof t)try{r=t.then}catch(n){return void e.reject(n)}if("function"!=typeof r)e.fulfill(t);else{var i=!1;try{r.call(t,function(r){i||(i=!0,r===t?e.reject(new TypeError("circular thenable chain")):d(e,r))},function(t){i||(i=!0,e.reject(t))})}catch(n){i||e.reject(n)}}};o.all=function(e){return new o(function(t,r){for(var n=new Array(e.length),i=0,a=function(r,a){n[r]=a,i++,i===e.length&&t(n)},o=0;o<e.length;o++)!function(t){var n=e[t],i=null!=n&&null!=n.then;if(i)n.then(function(e){a(t,e)},function(e){r(e)});else{var o=n;a(t,o)}}(o)})},o.resolve=function(e){return new o(function(t,r){t(e)})},o.reject=function(e){return new o(function(t,r){r(e)})},t.exports="undefined"!=typeof Promise?Promise:o},{}],87:[function(e,t,r){"use strict";var n=e("./is"),i=e("./util"),a=function(e){if(!(this instanceof a))return new a(e);var t=this;t._private={selectorText:null,invalid:!0};var r=function(){return{classes:[],colonSelectors:[],data:[],group:null,ids:[],meta:[],collection:null,filter:null,parent:null,ancestor:null,subject:null,child:null,descendant:null}};if(!e||n.string(e)&&e.match(/^\s*$/))t.length=0;else if("*"===e||"edge"===e||"node"===e)t[0]=r(),t[0].group="*"===e?e:e+"s",t[0].groupOnly=!0,t._private.invalid=!1,t._private.selectorText=e,t.length=1;else if(n.elementOrCollection(e)){var o=e.collection();t[0]=r(),t[0].collection=o,t.length=1}else if(n.fn(e))t[0]=r(),t[0].filter=e,t.length=1;else{if(!n.string(e))return void i.error("A selector must be created from a string; found "+e);var s=null,l={metaChar:"[\\!\\\"\\#\\$\\%\\&\\'\\(\\)\\*\\+\\,\\.\\/\\:\\;\\<\\=\\>\\?\\@\\[\\]\\^\\`\\{\\|\\}\\~]",comparatorOp:"=|\\!=|>|>=|<|<=|\\$=|\\^=|\\*=",boolOp:"\\?|\\!|\\^",string:'"(?:\\\\"|[^"])+"|'+"'(?:\\\\'|[^'])+'",number:i.regex.number,meta:"degree|indegree|outdegree",separator:"\\s*,\\s*",descendant:"\\s+",child:"\\s+>\\s+",subject:"\\$"};l.variable="(?:[\\w-]|(?:\\\\"+l.metaChar+"))+",l.value=l.string+"|"+l.number,l.className=l.variable,l.id=l.variable;for(var u=function(e){return e.replace(new RegExp("\\\\("+l.metaChar+")","g"),function(e,t,r,n){return t})},c=l.comparatorOp.split("|"),d=0;d<c.length;d++){var h=c[d];l.comparatorOp+="|@"+h}for(var c=l.comparatorOp.split("|"),d=0;d<c.length;d++){var h=c[d];h.indexOf("!")>=0||"="!==h&&(l.comparatorOp+="|\\!"+h)}var p=[{name:"group",query:!0,regex:"(node|edge|\\*)",populate:function(e){this.group="*"===e?e:e+"s"}},{name:"state",query:!0,regex:"(:selected|:unselected|:locked|:unlocked|:visible|:hidden|:transparent|:grabbed|:free|:removed|:inside|:grabbable|:ungrabbable|:animated|:unanimated|:selectable|:unselectable|:orphan|:nonorphan|:parent|:child|:loop|:simple|:active|:inactive|:touch|:backgrounding|:nonbackgrounding)",populate:function(e){this.colonSelectors.push(e)}},{name:"id",query:!0,regex:"\\#("+l.id+")",populate:function(e){this.ids.push(u(e))}},{name:"className",query:!0,regex:"\\.("+l.className+")",populate:function(e){this.classes.push(u(e))}},{name:"dataExists",query:!0,regex:"\\[\\s*("+l.variable+")\\s*\\]",populate:function(e){this.data.push({field:u(e)})}},{name:"dataCompare",query:!0,regex:"\\[\\s*("+l.variable+")\\s*("+l.comparatorOp+")\\s*("+l.value+")\\s*\\]",populate:function(e,t,r){var n=null!=new RegExp("^"+l.string+"$").exec(r);r=n?r.substring(1,r.length-1):parseFloat(r),this.data.push({field:u(e),operator:t,value:r})}},{name:"dataBool",query:!0,regex:"\\[\\s*("+l.boolOp+")\\s*("+l.variable+")\\s*\\]",populate:function(e,t){this.data.push({field:u(t),operator:e})}},{name:"metaCompare",query:!0,regex:"\\[\\[\\s*("+l.meta+")\\s*("+l.comparatorOp+")\\s*("+l.number+")\\s*\\]\\]",populate:function(e,t,r){this.meta.push({field:u(e),operator:t,value:parseFloat(r)})}},{name:"nextQuery",separator:!0,regex:l.separator,populate:function(){t[++d]=r(),s=null}},{name:"child",separator:!0,regex:l.child,populate:function(){var e=r();e.parent=this,e.subject=s,t[d]=e}},{name:"descendant",separator:!0,regex:l.descendant,populate:function(){var e=r();e.ancestor=this,e.subject=s,t[d]=e}},{name:"subject",modifier:!0,regex:l.subject,populate:function(){return null!=s&&this.subject!=this?(i.error("Redefinition of subject in selector `"+e+"`"),!1):(s=this,void(this.subject=this))}}];t._private.selectorText=e;var f=e,d=0,v=function(e){for(var t,r,i,a=0;a<p.length;a++){var o=p[a],s=o.name;if(!n.fn(e)||e(s,o)){var l=f.match(new RegExp("^"+o.regex));if(null!=l){r=l,t=o,i=s;var u=l[0];f=f.substring(u.length);break}}}return{expr:t,match:r,name:i}},g=function(){var e=f.match(/^\s+/);if(e){var t=e[0];f=f.substring(t.length)}};for(t[0]=r(),g();;){var y=v();if(null==y.expr)return void i.error("The selector `"+e+"`is invalid");for(var m=[],b=1;b<y.match.length;b++)m.push(y.match[b]);var x=y.expr.populate.apply(t[d],m);if(x===!1)return;if(f.match(/^\s*$/))break}t.length=d+1;for(var b=0;b<t.length;b++){var w=t[b];if(null!=w.subject){for(;w.subject!=w;)if(null!=w.parent){var E=w.parent,_=w;_.parent=null,E.child=_,w=E}else{if(null==w.ancestor){i.error("When adjusting references for the selector `"+w+"`, neither parent nor ancestor was found");break}var P=w.ancestor,S=w;S.ancestor=null,P.descendant=S,w=P}t[b]=w.subject}}}t._private.invalid=!1},o=a.prototype;o.size=function(){return this.length},o.eq=function(e){return this[e]};var s=function(e,t){var r=t._private;if(e.groupOnly)return"*"===e.group||e.group===r.group;if(null!=e.group&&"*"!=e.group&&e.group!=r.group)return!1;for(var i=t.cy(),a=!0,o=0;o<e.colonSelectors.length;o++){var l=e.colonSelectors[o];switch(l){case":selected":a=t.selected();break;case":unselected":a=!t.selected();break;case":selectable":a=t.selectable();break;case":unselectable":a=!t.selectable();break;case":locked":a=t.locked();break;case":unlocked":a=!t.locked();break;case":visible":a=t.visible();break;case":hidden":a=!t.visible();break;case":transparent":a=t.transparent();break;case":grabbed":a=t.grabbed();break;case":free":a=!t.grabbed();break;case":removed":a=t.removed();break;case":inside":a=!t.removed();break;case":grabbable":a=t.grabbable();break;case":ungrabbable":a=!t.grabbable();break;case":animated":a=t.animated();break;case":unanimated":a=!t.animated();break;case":parent":a=t.isNode()&&t.children().nonempty();break;case":child":case":nonorphan":a=t.isNode()&&t.parent().nonempty();break;case":orphan":a=t.isNode()&&t.parent().empty();break;case":loop":a=t.isEdge()&&t.data("source")===t.data("target");break;case":simple":a=t.isEdge()&&t.data("source")!==t.data("target");break;case":active":a=t.active();break;case":inactive":a=!t.active();break;case":touch":a=n.touch();break;case":backgrounding":a=t.backgrounding();break;case":nonbackgrounding":a=!t.backgrounding()}if(!a)break}if(!a)return!1;for(var u=!0,o=0;o<e.ids.length;o++){var c=e.ids[o],d=r.data.id;if(u=u&&c==d,!u)break}if(!u)return!1;for(var h=!0,o=0;o<e.classes.length;o++){var p=e.classes[o];if(h=h&&t.hasClass(p),!h)break}if(!h)return!1;var f=function(t){for(var r=!0,i=0;i<e[t.name].length;i++){var a,o=e[t.name][i],s=o.operator,l=o.value,u=o.field;if(null!=s&&null!=l){var c=t.fieldValue(u),d=n.string(c)||n.number(c)?""+c:"",h=""+l,p=!1;s.indexOf("@")>=0&&(d=d.toLowerCase(),h=h.toLowerCase(),s=s.replace("@",""),p=!0);var f=!1;s.indexOf("!")>=0&&(s=s.replace("!",""),f=!0),p&&(l=h.toLowerCase(),c=d.toLowerCase());var v=!1;switch(s){case"*=":a=d.indexOf(h)>=0;break;case"$=":a=d.indexOf(h,d.length-h.length)>=0;break;case"^=":a=0===d.indexOf(h);break;case"=":a=c===l;break;case">":v=!0,a=c>l;break;case">=":v=!0,a=c>=l;break;case"<":v=!0,a=l>c;break;case"<=":v=!0,a=l>=c;break;default:a=!1}!f||null==c&&v||(a=!a)}else if(null!=s)switch(s){case"?":a=t.fieldTruthy(u);break;case"!":a=!t.fieldTruthy(u);break;case"^":a=t.fieldUndefined(u)}else a=!t.fieldUndefined(u);if(!a){r=!1;break}}return r},v=f({name:"data",fieldValue:function(e){return r.data[e]},fieldUndefined:function(e){return void 0===r.data[e]},fieldTruthy:function(e){return!!r.data[e]}});if(!v)return!1;var g=f({name:"meta",fieldValue:function(e){return t[e]()},fieldUndefined:function(e){return null==t[e]()},fieldTruthy:function(e){return!!t[e]()}});if(!g)return!1;if(null!=e.collection){var y=e.collection.hasElementWithId(t.id());if(!y)return!1}if(null!=e.filter&&0===t.collection().filter(e.filter).size())return!1;var m=function(e,t){if(null!=e){var r=!1;if(!i.hasCompoundNodes())return!1;t=t();for(var n=0;n<t.length;n++)if(s(e,t[n])){r=!0;break}return r}return!0};return m(e.parent,function(){return t.parent()})&&m(e.ancestor,function(){return t.parents()})&&m(e.child,function(){return t.children()})?!!m(e.descendant,function(){return t.descendants()}):!1};o.filter=function(e){var t=this,r=e.cy();if(t._private.invalid)return r.collection();var n=function(e,r){for(var n=0;n<t.length;n++){var i=t[n];if(s(i,r))return!0}return!1};null==t._private.selectorText&&(n=function(){return!0});var i=e.filter(n);return i},o.matches=function(e){var t=this;if(t._private.invalid)return!1;for(var r=0;r<t.length;r++){var n=t[r];if(s(n,e))return!0}return!1},o.toString=o.selector=function(){for(var e="",t=function(e,t){return n.string(e)?t?'"'+e+'"':e:""},r=function(e){var n="";e.subject===e&&(n+="$");var a=t(e.group);n+=a.substring(0,a.length-1);for(var o=0;o<e.data.length;o++){var s=e.data[o];n+=s.value?"["+s.field+t(s.operator)+t(s.value,!0)+"]":"["+t(s.operator)+s.field+"]"}for(var o=0;o<e.meta.length;o++){var l=e.meta[o];n+="[["+l.field+t(l.operator)+t(l.value,!0)+"]]"}for(var o=0;o<e.colonSelectors.length;o++){var u=e.colonSelectors[i];n+=u}for(var o=0;o<e.ids.length;o++){var u="#"+e.ids[i];n+=u}for(var o=0;o<e.classes.length;o++){var u="."+e.classes[o];n+=u}return null!=e.parent&&(n=r(e.parent)+" > "+n),null!=e.ancestor&&(n=r(e.ancestor)+" "+n),null!=e.child&&(n+=" > "+r(e.child)),null!=e.descendant&&(n+=" "+r(e.descendant)),n},i=0;i<this.length;i++){var a=this[i];e+=r(a),this.length>1&&i<this.length-1&&(e+=", ")}return e},t.exports=a},{"./is":83,"./util":100}],88:[function(e,t,r){"use strict";var n=e("../util"),i=e("../is"),a={};a.apply=function(e){var t=this,r=t._private;r.newStyle&&(r.contextStyles={},r.propDiffs={},t.cleanElements(e,!0));for(var n=0;n<e.length;n++){var i=e[n],a=t.getContextMeta(i),o=t.getContextStyle(a),s=t.applyContextStyle(a,o,i);t.updateTransitions(i,s.diffProps),t.updateStyleHints(i)}r.newStyle=!1},a.getPropertiesDiff=function(e,t){var r=this,n=r._private.propDiffs=r._private.propDiffs||{},i=e+"-"+t,a=n[i];if(a)return a;for(var o=[],s={},l=0;l<r.length;l++){var u=r[l],c="t"===e[l],d="t"===t[l],h=c!==d,p=u.mappedProperties.length>0;if(h||p){var f;h&&p?f=u.properties:h?f=u.properties:p&&(f=u.mappedProperties);for(var v=0;v<f.length;v++){for(var g=f[v],y=g.name,m=!1,b=l+1;b<r.length;b++){var x=r[b],w="t"===t[b];if(w&&(m=null!=x.properties[g.name]))break}s[y]||m||(s[y]=!0,o.push(y))}}}return n[i]=o,o},a.getContextMeta=function(e){var t,r=this,n="",i=e._private.styleCxtKey||"";r._private.newStyle&&(i="");for(var a=0;a<r.length;a++){var o=r[a],s=o.selector&&o.selector.matches(e);n+=s?"t":"f"}return t=r.getPropertiesDiff(i,n),e._private.styleCxtKey=n,{key:n,diffPropNames:t}},a.getContextStyle=function(e){var t=e.key,r=this,n=this._private.contextStyles=this._private.contextStyles||{};if(n[t])return n[t];for(var i={_private:{key:t}},a=0;a<r.length;a++){var o=r[a],s="t"===t[a];if(s)for(var l=0;l<o.properties.length;l++){var u=o.properties[l],c=i[u.name]=u;c.context=o}}return n[t]=i,i},a.applyContextStyle=function(e,t,r){for(var n=this,i=e.diffPropNames,a={},o=0;o<i.length;o++){var s=i[o],l=t[s],u=r.pstyle(s);if(l||(l=u.bypass?{name:s,deleteBypassed:!0}:{name:s,"delete":!0}),u!==l){var c=a[s]={prev:u};n.applyParsedProperty(r,l),c.next=r.pstyle(s),c.next&&c.next.bypass&&(c.next=c.next.bypassed)}}return{diffProps:a}},a.updateStyleHints=function(e){var t=e._private,r=this;if(!e.removed()){var n=!1;if("nodes"===t.group)for(var i=1;i<=r.pieBackgroundN;i++){var a=e.pstyle("pie-"+i+"-background-size").value;if(a>0){n=!0;break}}t.hasPie=n;var o=e.pstyle("text-transform").strValue,s=e.pstyle("label").strValue,l=e.pstyle("source-label").strValue,u=e.pstyle("target-label").strValue,c=e.pstyle("font-style").strValue,a=e.pstyle("font-size").pfValue+"px",d=e.pstyle("font-family").strValue,h=e.pstyle("font-weight").strValue,p=e.pstyle("text-valign").strValue,f=e.pstyle("text-valign").strValue,v=e.pstyle("text-outline-width").pfValue,g=e.pstyle("text-wrap").strValue,y=e.pstyle("text-max-width").pfValue,m=c+"$"+a+"$"+d+"$"+h+"$"+o+"$"+p+"$"+f+"$"+v+"$"+g+"$"+y;t.labelStyleKey=m,t.sourceLabelKey=m+"$"+l,t.targetLabelKey=m+"$"+u,t.labelKey=m+"$"+s,t.fontKey=c+"$"+h+"$"+a+"$"+d,t.styleKey=Date.now()}},a.applyParsedProperty=function(e,t){var r,a,o=this,s=t,l=e._private.style,u=o.types,c=o.properties[s.name].type,d=s.bypass,h=l[s.name],p=h&&h.bypass,f=e._private;if("curve-style"===t.name&&"haystack"===t.value&&e.isEdge()&&(e.isLoop()||e.source().isParent()||e.target().isParent())&&(s=t=this.parse(t.name,"bezier",d)),s["delete"])return l[s.name]=void 0,!0;if(s.deleteBypassed)return h?h.bypass?(h.bypassed=void 0,!0):!1:!0;if(s.deleteBypass)return h?h.bypass?(l[s.name]=h.bypassed,!0):!1:!0;var v=function(){n.error("Do not assign mappings to elements without corresponding data (e.g. ele `"+e.id()+"` for property `"+s.name+"` with data field `"+s.field+"`); try a `["+s.field+"]` selector to limit scope to elements with `"+s.field+"` defined")};switch(s.mapped){case u.mapData:case u.mapLayoutData:case u.mapScratch:var r,g=s.mapped===u.mapLayoutData,y=s.mapped===u.mapScratch,m=s.field.split(".");r=y||g?f.scratch:f.data;for(var b=0;b<m.length&&r;b++){var x=m[b];r=r[x]}var w;if(w=i.number(r)?(r-s.fieldMin)/(s.fieldMax-s.fieldMin):0,0>w?w=0:w>1&&(w=1),c.color){var E=s.valueMin[0],_=s.valueMax[0],P=s.valueMin[1],S=s.valueMax[1],k=s.valueMin[2],T=s.valueMax[2],D=null==s.valueMin[3]?1:s.valueMin[3],C=null==s.valueMax[3]?1:s.valueMax[3],M=[Math.round(E+(_-E)*w),Math.round(P+(S-P)*w),Math.round(k+(T-k)*w),Math.round(D+(C-D)*w)];a={bypass:s.bypass,name:s.name,value:M,strValue:"rgb("+M[0]+", "+M[1]+", "+M[2]+")"}}else{if(!c.number)return!1;var N=s.valueMin+(s.valueMax-s.valueMin)*w;a=this.parse(s.name,N,s.bypass,!0)}a||(a=this.parse(s.name,h.strValue,s.bypass,!0)),a||v(),a.mapping=s,s=a;break;case u.data:case u.layoutData:case u.scratch:var r,g=s.mapped===u.layoutData,y=s.mapped===u.scratch,m=s.field.split(".");if(r=y||g?f.scratch:f.data)for(var b=0;b<m.length;b++){var x=m[b];r=r[x]}if(a=this.parse(s.name,r,s.bypass,!0),!a){var B=h?h.strValue:"";a=this.parse(s.name,B,s.bypass,!0)}a||v(),a.mapping=s,s=a;break;case u.fn:var z=s.value,I=z(e);a=this.parse(s.name,I,s.bypass,!0),a.mapping=s,s=a;break;case void 0:break;default:return!1}return d?(p?s.bypassed=h.bypassed:s.bypassed=h,l[s.name]=s):p?h.bypassed=s:l[s.name]=s,!0},a.cleanElements=function(e,t){for(var r=this,n=r.properties,i=0;i<e.length;i++){var a=e[i];if(t)for(var o=a._private.style,s=0;s<n.length;s++){var l=n[s],u=o[l.name];u&&(u.bypass?u.bypassed=null:o[l.name]=null)}else a._private.style={}}},a.update=function(){var e=this._private.cy,t=e.mutableElements();t.updateStyle()},a.updateMappers=function(e){for(var t=this,r=0;r<e.length;r++){for(var n=e[r],i=n._private.style,a=0;a<t.properties.length;a++){var o=t.properties[a],s=i[o.name];if(s&&s.mapping){var l=s.mapping;this.applyParsedProperty(n,l)}}this.updateStyleHints(n)}},a.updateTransitions=function(e,t,r){var n=this,a=e._private,o=e.pstyle("transition-property").value,s=e.pstyle("transition-duration").pfValue,l=e.pstyle("transition-delay").pfValue;if(o.length>0&&s>0){for(var u={},c=!1,d=0;d<o.length;d++){var h=o[d],p=e.pstyle(h),f=t[h];if(f){var v,g=f.prev,y=g,m=null!=f.next?f.next:p,b=!1,x=1e-6;y&&(i.number(y.pfValue)&&i.number(m.pfValue)?(b=m.pfValue-y.pfValue,v=y.pfValue+x*b):i.number(y.value)&&i.number(m.value)?(b=m.value-y.value,v=y.value+x*b):i.array(y.value)&&i.array(m.value)&&(b=y.value[0]!==m.value[0]||y.value[1]!==m.value[1]||y.value[2]!==m.value[2],v=y.strValue),b&&(u[h]=m.strValue,this.applyBypass(e,h,v),c=!0))}}if(!c)return;a.transitioning=!0,e.stop(),l>0&&e.delay(l),e.animate({css:u},{duration:s,easing:e.pstyle("transition-timing-function").value,queue:!1,complete:function(){r||n.removeBypasses(e,o),a.transitioning=!1}})}else a.transitioning&&(e.stop(),this.removeBypasses(e,o),a.transitioning=!1)},t.exports=a},{"../is":83,"../util":100}],89:[function(e,t,r){"use strict";var n=e("../is"),i=e("../util"),a={};a.applyBypass=function(e,t,r,a){var o=this,s=[],l=!0;if("*"===t||"**"===t){if(void 0!==r)for(var u=0;u<o.properties.length;u++){var c=o.properties[u],t=c.name,d=this.parse(t,r,!0);d&&s.push(d)}}else if(n.string(t)){var d=this.parse(t,r,!0);d&&s.push(d)}else{if(!n.plainObject(t))return!1;var h=t;a=r;for(var u=0;u<o.properties.length;u++){var c=o.properties[u],t=c.name,r=h[t];if(void 0===r&&(r=h[i.dash2camel(t)]),void 0!==r){var d=this.parse(t,r,!0);d&&s.push(d)}}}if(0===s.length)return!1;for(var p=!1,u=0;u<e.length;u++){for(var f,v=e[u],g={},y=0;y<s.length;y++){var c=s[y];if(a){var m=v.pstyle(c.name);f=g[c.name]={prev:m}}p=this.applyParsedProperty(v,c)||p,a&&(f.next=v.pstyle(c.name))}p&&this.updateStyleHints(v),a&&this.updateTransitions(v,g,l)}return p},a.overrideBypass=function(e,t,r){t=i.camel2dash(t);for(var n=0;n<e.length;n++){var a=e[n],o=a._private.style[t],s=this.properties[t].type,l=s.color,u=s.mutiple;o&&o.bypass?(o.value=r,null!=o.pfValue&&(o.pfValue=r),l?o.strValue="rgb("+r.join(",")+")":u?o.strValue=r.join(" "):o.strValue=""+r):this.applyBypass(a,t,r)}},a.removeAllBypasses=function(e,t){return this.removeBypasses(e,this.propertyNames,t)},a.removeBypasses=function(e,t,r){for(var n=!0,i=0;i<e.length;i++){for(var a=e[i],o={},s=0;s<t.length;s++){var l=t[s],u=this.properties[l],c=a.pstyle(u.name);if(c&&c.bypass){var d="",h=this.parse(l,d,!0),p=o[u.name]={prev:c};this.applyParsedProperty(a,h),p.next=a.pstyle(u.name)}}this.updateStyleHints(a),r&&this.updateTransitions(a,o,n)}},t.exports=a},{"../is":83,"../util":100}],90:[function(e,t,r){"use strict";var n=e("../window"),i={};i.getEmSizeInPixels=function(){var e=this.containerCss("font-size");return null!=e?parseFloat(e):1},i.containerCss=function(e){var t=this._private.cy,r=t.container();return n&&r&&n.getComputedStyle?n.getComputedStyle(r).getPropertyValue(e):void 0},t.exports=i},{"../window":107}],91:[function(e,t,r){"use strict";var n=e("../util"),i=e("../is"),a={};a.getRenderedStyle=function(e){return this.getRawStyle(e,!0)},a.getRawStyle=function(e,t){var r=this,e=e[0];if(e){for(var i={},a=0;a<r.properties.length;a++){var o=r.properties[a],s=r.getStylePropertyValue(e,o.name,t);s&&(i[o.name]=s,i[n.dash2camel(o.name)]=s)}return i}},a.getStylePropertyValue=function(e,t,r){var n=this,e=e[0];if(e){var i=n.properties[t],a=i.type,o=e.pstyle(i.name),s=e.cy().zoom();if(o){var l=o.units?a.implicitUnits||"px":null,u=l?[].concat(o.pfValue).map(function(e){return e*(r?s:1)+l}).join(" "):o.strValue;return u}}},a.getAnimationStartStyle=function(e,t){for(var r={},n=0;n<t.length;n++){var a=t[n],o=a.name,s=e.pstyle(o);void 0!==s&&(s=i.plainObject(s)?this.parse(o,s.strValue):this.parse(o,s)),s&&(r[o]=s)}return r},a.getPropsList=function(e){var t=this,r=[],i=e,a=t.properties;if(i)for(var o=Object.keys(i),s=0;s<o.length;s++){var l=o[s],u=i[l],c=a[l]||a[n.camel2dash(l)],d=this.parse(c.name,u);r.push(d)}return r},t.exports=a},{"../is":83,"../util":100}],92:[function(e,t,r){"use strict";var n=e("../is"),i=e("../util"),a=e("../selector"),o=function(e){return this instanceof o?n.core(e)?(this._private={cy:e,coreStyle:{}},this.length=0,void this.resetToDefault()):void i.error("A style must have a core reference"):new o(e)},s=o.prototype;s.instanceString=function(){return"style"},s.clear=function(){for(var e=0;e<this.length;e++)this[e]=void 0;this.length=0;var t=this._private;return t.newStyle=!0,this},s.resetToDefault=function(){return this.clear(),this.addDefaultStylesheet(),this},s.core=function(){return this._private.coreStyle},s.selector=function(e){var t="core"===e?null:new a(e),r=this.length++;return this[r]={selector:t,properties:[],mappedProperties:[],index:r},this},s.css=function(){var e=this,t=arguments;switch(t.length){case 1:for(var r=t[0],n=0;n<e.properties.length;n++){var a=e.properties[n],o=r[a.name];void 0===o&&(o=r[i.dash2camel(a.name)]),void 0!==o&&this.cssRule(a.name,o)}break;case 2:this.cssRule(t[0],t[1])}return this},s.style=s.css,s.cssRule=function(e,t){var r=this.parse(e,t);if(r){var n=this.length-1;this[n].properties.push(r),this[n].properties[r.name]=r,r.name.match(/pie-(\d+)-background-size/)&&r.value&&(this._private.hasPie=!0),r.mapped&&this[n].mappedProperties.push(r);var i=!this[n].selector;i&&(this._private.coreStyle[r.name]=r)}return this},o.fromJson=function(e,t){var r=new o(e);return r.fromJson(t),r},o.fromString=function(e,t){return new o(e).fromString(t)},[e("./apply"),e("./bypass"),e("./container"),e("./get-for-ele"),e("./json"),e("./string-sheet"),e("./properties"),e("./parse")].forEach(function(e){i.extend(s,e)}),o.types=s.types,o.properties=s.properties,t.exports=o},{"../is":83,"../selector":87,"../util":100,"./apply":88,"./bypass":89,"./container":90,"./get-for-ele":91,"./json":93,"./parse":94,"./properties":95,"./string-sheet":96}],93:[function(e,t,r){"use strict";var n={};n.applyFromJson=function(e){for(var t=this,r=0;r<e.length;r++){var n=e[r],i=n.selector,a=n.style||n.css,o=Object.keys(a);t.selector(i);for(var s=0;s<o.length;s++){var l=o[s],u=a[l];t.css(l,u)}}return t},n.fromJson=function(e){var t=this;return t.resetToDefault(),t.applyFromJson(e),t},n.json=function(){for(var e=[],t=this.defaultLength;t<this.length;t++){for(var r=this[t],n=r.selector,i=r.properties,a={},o=0;o<i.length;o++){var s=i[o];a[s.name]=s.strValue}e.push({selector:n?n.toString():"core",style:a})}return e},t.exports=n},{}],94:[function(e,t,r){"use strict";var n=e("../util"),i=e("../is"),a=e("../math"),o={};o.parse=function(e,t,r,a){var o=this;if(i.fn(t))return o.parseImpl(e,t,r,a);var s,l=[e,t,r,a].join("$"),u=o.propCache=o.propCache||{};return(s=u[l])||(s=u[l]=o.parseImpl(e,t,r,a)),s=n.copy(s),s&&(s.value=n.copy(s.value)),s};var s=function(e,t,r,o){var s=this;e=n.camel2dash(e);var l=s.properties[e],u=t,c=s.types;if(!l)return null;if(void 0===t||null===t)return null;l.alias&&(l=l.pointsTo,e=l.name);var d=i.string(t);d&&(t=t.trim());var h=l.type;if(!h)return null;if(r&&(""===t||null===t))return{name:e,value:t,bypass:!0,deleteBypass:!0};if(i.fn(t))return{name:e,value:t,strValue:"fn",mapped:c.fn,bypass:r};var p,f,v,g,y,m;if(!d||o);else{if((p=new RegExp(c.data.regex).exec(t))||(v=new RegExp(c.layoutData.regex).exec(t))||(y=new RegExp(c.scratch.regex).exec(t))){if(r)return!1;var b;return b=p?c.data:v?c.layoutData:c.scratch,p=p||v||y,{name:e,value:p,strValue:""+t,mapped:b,field:p[1],bypass:r}}if((f=new RegExp(c.mapData.regex).exec(t))||(g=new RegExp(c.mapLayoutData.regex).exec(t))||(m=new RegExp(c.mapScratch.regex).exec(t))){if(r)return!1;if(h.multiple)return!1;var b;if(b=f?c.mapData:g?c.mapLayoutData:c.mapScratch,f=f||g||m,!h.color&&!h.number)return!1;var x=this.parse(e,f[4]);if(!x||x.mapped)return!1;var w=this.parse(e,f[5]);if(!w||w.mapped)return!1;if(x.value===w.value)return!1;if(h.color){var E=x.value,_=w.value,P=!(E[0]!==_[0]||E[1]!==_[1]||E[2]!==_[2]||E[3]!==_[3]&&(null!=E[3]&&1!==E[3]||null!=_[3]&&1!==_[3]));if(P)return!1}return{name:e,value:f,strValue:""+t,mapped:b,field:f[1],fieldMin:parseFloat(f[2]),fieldMax:parseFloat(f[3]),valueMin:x.value,valueMax:w.value,bypass:r}}}if(h.multiple&&"multiple"!==o){var S;if(S=d?t.split(/\s+/):i.array(t)?t:[t],h.evenMultiple&&S.length%2!==0)return null;var k=S.map(function(t){var n=s.parse(e,t,r,"multiple");return null!=n.pfValue?n.pfValue:n.value});return{name:e,value:k,pfValue:k,strValue:k.join(" "),bypass:r,units:h.number&&!h.unitless?h.implicitUnits||"px":void 0}}var T=function(){for(var n=0;n<h.enums.length;n++){var i=h.enums[n];if(i===t)return{name:e,value:t,strValue:""+t,bypass:r}}return null};if(h.number){var D,C="px";if(h.units&&(D=h.units),h.implicitUnits&&(C=h.implicitUnits),!h.unitless)if(d){var M="px|em"+(h.allowPercent?"|\\%":"");D&&(M=D);var N=t.match("^("+n.regex.number+")("+M+")?$");N&&(t=N[1],D=N[2]||C)}else D&&!h.implicitUnits||(D=C);if(t=parseFloat(t),isNaN(t)&&void 0===h.enums)return null;if(isNaN(t)&&void 0!==h.enums)return t=u,T();if(h.integer&&!i.integer(t))return null;if(void 0!==h.min&&t<h.min||void 0!==h.max&&t>h.max)return null;var B={name:e,value:t,strValue:""+t+(D?D:""),units:D,bypass:r};return h.unitless||"px"!==D&&"em"!==D?B.pfValue=t:B.pfValue="px"!==D&&D?this.getEmSizeInPixels()*t:t,"ms"!==D&&"s"!==D||(B.pfValue="ms"===D?t:1e3*t),"deg"!==D&&"rad"!==D||(B.pfValue="rad"===D?t:a.deg2rad(t)),B}if(h.propList){var z=[],I=""+t;if("none"===I);else{for(var L=I.split(","),O=0;O<L.length;O++){var A=L[O].trim();s.properties[A]&&z.push(A)}if(0===z.length)return null}return{name:e,value:z,strValue:0===z.length?"none":z.join(", "),bypass:r}}if(h.color){var R=n.color2tuple(t);return R?{name:e,value:R,strValue:""+t,bypass:r,roundValue:!0}:null}if(h.regex||h.regexes){if(h.enums){var q=T();if(q)return q}for(var V=h.regexes?h.regexes:[h.regex],O=0;O<V.length;O++){var F=new RegExp(V[O]),j=F.exec(t);if(j)return{name:e,value:j,strValue:""+t,bypass:r}}return null}return h.string?{name:e,value:t,strValue:""+t,bypass:r}:h.enums?T():null};o.parseImpl=s,t.exports=o},{"../is":83,"../math":85,"../util":100}],95:[function(e,t,r){"use strict";var n=e("../util"),i={};!function(){var e=n.regex.number,t=n.regex.rgbaNoBackRefs,r=n.regex.hslaNoBackRefs,a=n.regex.hex3,o=n.regex.hex6,s=function(e){return"^"+e+"\\s*\\(\\s*([\\w\\.]+)\\s*\\)$"},l=function(n){var i=e+"|\\w+|"+t+"|"+r+"|"+a+"|"+o;return"^"+n+"\\s*\\(([\\w\\.]+)\\s*\\,\\s*("+e+")\\s*\\,\\s*("+e+")\\s*,\\s*("+i+")\\s*\\,\\s*("+i+")\\)$"};i.types={time:{number:!0,min:0,units:"s|ms",implicitUnits:"ms"},percent:{number:!0,min:0,max:100,units:"%",implicitUnits:"%"},zeroOneNumber:{number:!0,min:0,max:1,unitless:!0},nOneOneNumber:{number:!0,min:-1,max:1,unitless:!0},nonNegativeInt:{number:!0,min:0,integer:!0,unitless:!0},position:{enums:["parent","origin"]},nodeSize:{number:!0,min:0,enums:["label"]},number:{number:!0,unitless:!0},numbers:{number:!0,unitless:!0,multiple:!0},size:{number:!0,min:0},bidirectionalSize:{number:!0},bidirectionalSizes:{number:!0,multiple:!0},bgSize:{number:!0,min:0,allowPercent:!0},bgWH:{number:!0,min:0,allowPercent:!0,enums:["auto"]},bgPos:{number:!0,allowPercent:!0},bgRepeat:{enums:["repeat","repeat-x","repeat-y","no-repeat"]},bgFit:{enums:["none","contain","cover"]},bgClip:{enums:["none","node"]},color:{color:!0},bool:{enums:["yes","no"]},lineStyle:{enums:["solid","dotted","dashed"]},borderStyle:{enums:["solid","dotted","dashed","double"]},curveStyle:{enums:["bezier","unbundled-bezier","haystack","segments"]},fontFamily:{regex:'^([\\w- \\"]+(?:\\s*,\\s*[\\w- \\"]+)*)$'},fontVariant:{enums:["small-caps","normal"]},fontStyle:{enums:["italic","normal","oblique"]},fontWeight:{enums:["normal","bold","bolder","lighter","100","200","300","400","500","600","800","900",100,200,300,400,500,600,700,800,900]},textDecoration:{enums:["none","underline","overline","line-through"]},textTransform:{enums:["none","uppercase","lowercase"]},textWrap:{enums:["none","wrap"]},textBackgroundShape:{enums:["rectangle","roundrectangle"]},nodeShape:{enums:["rectangle","roundrectangle","ellipse","triangle","square","pentagon","hexagon","heptagon","octagon","star","diamond","vee","rhomboid","polygon"]},compoundIncludeLabels:{enums:["include","exclude"]},arrowShape:{enums:["tee","triangle","triangle-tee","triangle-backcurve","half-triangle-overshot","vee","square","circle","diamond","none"]},arrowFill:{enums:["filled","hollow"]},display:{enums:["element","none"]},visibility:{enums:["hidden","visible"]},valign:{enums:["top","center","bottom"]},halign:{enums:["left","center","right"]},text:{string:!0},data:{mapping:!0,regex:s("data")},layoutData:{mapping:!0,regex:s("layoutData")},scratch:{mapping:!0,regex:s("scratch")},mapData:{mapping:!0,regex:l("mapData")},mapLayoutData:{mapping:!0,regex:l("mapLayoutData")},mapScratch:{mapping:!0,regex:l("mapScratch")},fn:{mapping:!0,fn:!0},url:{regex:"^url\\s*\\(\\s*([^\\s]+)\\s*\\s*\\)|none|(.+)$"},propList:{propList:!0},angle:{number:!0,units:"deg|rad",implicitUnits:"rad"},textRotation:{number:!0,units:"deg|rad",implicitUnits:"rad",enums:["none","autorotate"]},polygonPointList:{number:!0,multiple:!0,evenMultiple:!0,min:-1,max:1,unitless:!0},edgeDistances:{enums:["intersection","node-position"]},easing:{regexes:["^(spring)\\s*\\(\\s*("+e+")\\s*,\\s*("+e+")\\s*\\)$","^(cubic-bezier)\\s*\\(\\s*("+e+")\\s*,\\s*("+e+")\\s*,\\s*("+e+")\\s*,\\s*("+e+")\\s*\\)$"],enums:["linear","ease","ease-in","ease-out","ease-in-out","ease-in-sine","ease-out-sine","ease-in-out-sine","ease-in-quad","ease-out-quad","ease-in-out-quad","ease-in-cubic","ease-out-cubic","ease-in-out-cubic","ease-in-quart","ease-out-quart","ease-in-out-quart","ease-in-quint","ease-out-quint","ease-in-out-quint","ease-in-expo","ease-out-expo","ease-in-out-expo","ease-in-circ","ease-out-circ","ease-in-out-circ"]}};var u=i.types,c=i.properties=[{name:"label",type:u.text},{name:"text-rotation",type:u.textRotation},{name:"text-margin-x",type:u.bidirectionalSize},{name:"text-margin-y",type:u.bidirectionalSize},{name:"source-label",type:u.text},{name:"source-text-rotation",type:u.textRotation},{name:"source-text-margin-x",type:u.bidirectionalSize},{name:"source-text-margin-y",type:u.bidirectionalSize},{name:"source-text-offset",type:u.size},{name:"target-label",type:u.text},{name:"target-text-rotation",type:u.textRotation},{name:"target-text-margin-x",type:u.bidirectionalSize},{name:"target-text-margin-y",type:u.bidirectionalSize},{name:"target-text-offset",type:u.size},{name:"text-valign",type:u.valign},{name:"text-halign",type:u.halign},{name:"color",type:u.color},{name:"text-outline-color",type:u.color},{name:"text-outline-width",type:u.size},{name:"text-outline-opacity",type:u.zeroOneNumber},{name:"text-opacity",type:u.zeroOneNumber},{name:"text-background-color",type:u.color},{name:"text-background-margin",type:u.size},{name:"text-background-opacity",type:u.zeroOneNumber},{name:"text-border-opacity",type:u.zeroOneNumber},{name:"text-border-color",type:u.color},{name:"text-border-width",type:u.size},{name:"text-border-style",type:u.borderStyle},{name:"text-background-shape",type:u.textBackgroundShape},{name:"text-transform",type:u.textTransform},{name:"text-wrap",type:u.textWrap},{name:"text-max-width",type:u.size},{name:"text-events",type:u.bool},{name:"font-family",type:u.fontFamily},{name:"font-style",type:u.fontStyle},{name:"font-weight",type:u.fontWeight},{name:"font-size",type:u.size},{name:"min-zoomed-font-size",type:u.size},{name:"events",type:u.bool},{name:"display",type:u.display},{name:"visibility", +type:u.visibility},{name:"opacity",type:u.zeroOneNumber},{name:"z-index",type:u.nonNegativeInt},{name:"overlay-padding",type:u.size},{name:"overlay-color",type:u.color},{name:"overlay-opacity",type:u.zeroOneNumber},{name:"shadow-blur",type:u.size},{name:"shadow-color",type:u.color},{name:"shadow-opacity",type:u.zeroOneNumber},{name:"shadow-offset-x",type:u.bidirectionalSize},{name:"shadow-offset-y",type:u.bidirectionalSize},{name:"text-shadow-blur",type:u.size},{name:"text-shadow-color",type:u.color},{name:"text-shadow-opacity",type:u.zeroOneNumber},{name:"text-shadow-offset-x",type:u.bidirectionalSize},{name:"text-shadow-offset-y",type:u.bidirectionalSize},{name:"transition-property",type:u.propList},{name:"transition-duration",type:u.time},{name:"transition-delay",type:u.time},{name:"transition-timing-function",type:u.easing},{name:"height",type:u.nodeSize},{name:"width",type:u.nodeSize},{name:"shape",type:u.nodeShape},{name:"shape-polygon-points",type:u.polygonPointList},{name:"background-color",type:u.color},{name:"background-opacity",type:u.zeroOneNumber},{name:"background-blacken",type:u.nOneOneNumber},{name:"padding-left",type:u.size},{name:"padding-right",type:u.size},{name:"padding-top",type:u.size},{name:"padding-bottom",type:u.size},{name:"border-color",type:u.color},{name:"border-opacity",type:u.zeroOneNumber},{name:"border-width",type:u.size},{name:"border-style",type:u.borderStyle},{name:"background-image",type:u.url},{name:"background-image-opacity",type:u.zeroOneNumber},{name:"background-position-x",type:u.bgPos},{name:"background-position-y",type:u.bgPos},{name:"background-repeat",type:u.bgRepeat},{name:"background-fit",type:u.bgFit},{name:"background-clip",type:u.bgClip},{name:"background-width",type:u.bgWH},{name:"background-height",type:u.bgWH},{name:"position",type:u.position},{name:"compound-sizing-wrt-labels",type:u.compoundIncludeLabels},{name:"line-style",type:u.lineStyle},{name:"line-color",type:u.color},{name:"curve-style",type:u.curveStyle},{name:"haystack-radius",type:u.zeroOneNumber},{name:"control-point-step-size",type:u.size},{name:"control-point-distances",type:u.bidirectionalSizes},{name:"control-point-weights",type:u.numbers},{name:"segment-distances",type:u.bidirectionalSizes},{name:"segment-weights",type:u.numbers},{name:"edge-distances",type:u.edgeDistances},{name:"selection-box-color",type:u.color},{name:"selection-box-opacity",type:u.zeroOneNumber},{name:"selection-box-border-color",type:u.color},{name:"selection-box-border-width",type:u.size},{name:"active-bg-color",type:u.color},{name:"active-bg-opacity",type:u.zeroOneNumber},{name:"active-bg-size",type:u.size},{name:"outside-texture-bg-color",type:u.color},{name:"outside-texture-bg-opacity",type:u.zeroOneNumber}],d=i.aliases=[{name:"content",pointsTo:"label"},{name:"control-point-distance",pointsTo:"control-point-distances"},{name:"control-point-weight",pointsTo:"control-point-weights"},{name:"edge-text-rotation",pointsTo:"text-rotation"}];i.pieBackgroundN=16,c.push({name:"pie-size",type:u.bgSize});for(var h=1;h<=i.pieBackgroundN;h++)c.push({name:"pie-"+h+"-background-color",type:u.color}),c.push({name:"pie-"+h+"-background-size",type:u.percent}),c.push({name:"pie-"+h+"-background-opacity",type:u.zeroOneNumber});var p=i.arrowPrefixes=["source","mid-source","target","mid-target"];[{name:"arrow-shape",type:u.arrowShape},{name:"arrow-color",type:u.color},{name:"arrow-fill",type:u.arrowFill}].forEach(function(e){p.forEach(function(t){var r=t+"-"+e.name,n=e.type;c.push({name:r,type:n})})},{}),i.propertyNames=c.map(function(e){return e.name});for(var h=0;h<c.length;h++){var f=c[h];c[f.name]=f}for(var h=0;h<d.length;h++){var v=d[h],g=c[v.pointsTo],y={name:v.name,alias:!0,pointsTo:g};c.push(y),c[v.name]=y}}(),i.getDefaultProperty=function(e){return this.getDefaultProperties()[e]},i.getDefaultProperties=n.memoize(function(){for(var e=n.extend({events:"yes","text-events":"no","text-valign":"top","text-halign":"center",color:"#000","text-outline-color":"#000","text-outline-width":0,"text-outline-opacity":1,"text-opacity":1,"text-decoration":"none","text-transform":"none","text-wrap":"none","text-max-width":9999,"text-background-color":"#000","text-background-opacity":0,"text-background-margin":0,"text-border-opacity":0,"text-border-width":0,"text-border-style":"solid","text-border-color":"#000","text-background-shape":"rectangle","font-family":"Helvetica Neue, Helvetica, sans-serif","font-style":"normal","font-weight":"normal","font-size":16,"min-zoomed-font-size":0,"text-rotation":"none","source-text-rotation":"none","target-text-rotation":"none",visibility:"visible",display:"element",opacity:1,"z-index":0,label:"","text-margin-x":0,"text-margin-y":0,"source-label":"","source-text-offset":0,"source-text-margin-x":0,"source-text-margin-y":0,"target-label":"","target-text-offset":0,"target-text-margin-x":0,"target-text-margin-y":0,"overlay-opacity":0,"overlay-color":"#000","overlay-padding":10,"shadow-opacity":0,"shadow-color":"#000","shadow-blur":10,"shadow-offset-x":0,"shadow-offset-y":0,"text-shadow-opacity":0,"text-shadow-color":"#000","text-shadow-blur":5,"text-shadow-offset-x":0,"text-shadow-offset-y":0,"transition-property":"none","transition-duration":0,"transition-delay":0,"transition-timing-function":"linear","background-blacken":0,"background-color":"#999","background-opacity":1,"background-image":"none","background-image-opacity":1,"background-position-x":"50%","background-position-y":"50%","background-repeat":"no-repeat","background-fit":"none","background-clip":"node","background-width":"auto","background-height":"auto","border-color":"#000","border-opacity":1,"border-width":0,"border-style":"solid",height:30,width:30,shape:"ellipse","shape-polygon-points":"-1, -1, 1, -1, 1, 1, -1, 1","padding-top":0,"padding-bottom":0,"padding-left":0,"padding-right":0,position:"origin","compound-sizing-wrt-labels":"include"},{"pie-size":"100%"},[{name:"pie-{{i}}-background-color",value:"black"},{name:"pie-{{i}}-background-size",value:"0%"},{name:"pie-{{i}}-background-opacity",value:1}].reduce(function(e,t){for(var r=1;r<=i.pieBackgroundN;r++){var n=t.name.replace("{{i}}",r),a=t.value;e[n]=a}return e},{}),{"line-style":"solid","line-color":"#999","control-point-step-size":40,"control-point-weights":.5,"segment-weights":.5,"segment-distances":20,"edge-distances":"intersection","curve-style":"bezier","haystack-radius":0},[{name:"arrow-shape",value:"none"},{name:"arrow-color",value:"#999"},{name:"arrow-fill",value:"filled"}].reduce(function(e,t){return i.arrowPrefixes.forEach(function(r){var n=r+"-"+t.name,i=t.value;e[n]=i}),e},{})),t={},r=0;r<this.properties.length;r++){var a=this.properties[r];if(!a.pointsTo){var o=a.name,s=e[o],l=this.parse(o,s);t[o]=l}}return t}),i.addDefaultStylesheet=function(){this.selector("$node > node").css({shape:"rectangle","padding-top":10,"padding-right":10,"padding-left":10,"padding-bottom":10,"background-color":"#eee","border-color":"#ccc","border-width":1}).selector("edge").css({width:3,"curve-style":"haystack"}).selector(":selected").css({"background-color":"#0169D9","line-color":"#0169D9","source-arrow-color":"#0169D9","target-arrow-color":"#0169D9","mid-source-arrow-color":"#0169D9","mid-target-arrow-color":"#0169D9"}).selector("node:parent:selected").css({"background-color":"#CCE1F9","border-color":"#aec8e5"}).selector(":active").css({"overlay-color":"black","overlay-padding":10,"overlay-opacity":.25}).selector("core").css({"selection-box-color":"#ddd","selection-box-opacity":.65,"selection-box-border-color":"#aaa","selection-box-border-width":1,"active-bg-color":"black","active-bg-opacity":.15,"active-bg-size":30,"outside-texture-bg-color":"#000","outside-texture-bg-opacity":.125}),this.defaultLength=this.length},t.exports=i},{"../util":100}],96:[function(e,t,r){"use strict";var n=e("../util"),i=e("../selector"),a={};a.applyFromString=function(e){function t(){c=c.length>a.length?c.substr(a.length):""}function r(){o=o.length>s.length?o.substr(s.length):""}var a,o,s,l=this,u=this,c=""+e;for(c=c.replace(/[\/][*](\s|.)+?[*][\/]/g,"");;){var d=c.match(/^\s*$/);if(d)break;var h=c.match(/^\s*((?:.|\s)+?)\s*\{((?:.|\s)+?)\}/);if(!h){n.error("Halting stylesheet parsing: String stylesheet contains more to parse but no selector and block found in: "+c);break}a=h[0];var p=h[1];if("core"!==p){var f=new i(p);if(f._private.invalid){n.error("Skipping parsing of block: Invalid selector found in string stylesheet: "+p),t();continue}}var v=h[2],g=!1;o=v;for(var y=[];;){var d=o.match(/^\s*$/);if(d)break;var m=o.match(/^\s*(.+?)\s*:\s*(.+?)\s*;/);if(!m){n.error("Skipping parsing of block: Invalid formatting of style property and value definitions found in:"+v),g=!0;break}s=m[0];var b=m[1],x=m[2],w=l.properties[b];if(w){var E=u.parse(b,x);E?(y.push({name:b,val:x}),r()):(n.error("Skipping property: Invalid property definition in: "+s),r())}else n.error("Skipping property: Invalid property name in: "+s),r()}if(g){t();break}u.selector(p);for(var _=0;_<y.length;_++){var w=y[_];u.css(w.name,w.val)}t()}return u},a.fromString=function(e){var t=this;return t.resetToDefault(),t.applyFromString(e),t},t.exports=a},{"../selector":87,"../util":100}],97:[function(e,t,r){"use strict";var n=e("./is"),i=e("./util"),a=e("./style"),o=function(){return this instanceof o?void(this.length=0):new o},s=o.prototype;s.instanceString=function(){return"stylesheet"},s.selector=function(e){var t=this.length++;return this[t]={selector:e,properties:[]},this},s.css=function(e,t){var r=this.length-1;if(n.string(e))this[r].properties.push({name:e,value:t});else if(n.plainObject(e))for(var o=e,s=0;s<a.properties.length;s++){var l=a.properties[s],u=o[l.name];if(void 0===u&&(u=o[i.dash2camel(l.name)]),void 0!==u){var e=l.name,t=u;this[r].properties.push({name:e,value:t})}}return this},s.style=s.css,s.generateStyle=function(e){for(var t=new a(e),r=0;r<this.length;r++){var n=this[r],i=n.selector,o=n.properties;t.selector(i);for(var s=0;s<o.length;s++){var l=o[s];t.css(l.name,l.value)}}return t},t.exports=o},{"./is":83,"./style":92,"./util":100}],98:[function(_dereq_,module,exports){/*! Weaver licensed under MIT (https://tldrlegal.com/license/mit-license), copyright Max Franz */ +"use strict";var window=_dereq_("./window"),util=_dereq_("./util"),Promise=_dereq_("./promise"),Event=_dereq_("./event"),define=_dereq_("./define"),is=_dereq_("./is"),Thread=function(e){if(!(this instanceof Thread))return new Thread(e);var t=this._private={requires:[],files:[],queue:null,pass:[],disabled:!1};is.plainObject(e)&&null!=e.disabled&&(t.disabled=!!e.disabled)},thdfn=Thread.prototype,stringifyFieldVal=function(e){var t=is.fn(e)?e.toString():"JSON.parse('"+JSON.stringify(e)+"')";return t},fnAsRequire=function(e){var t,r;is.object(e)&&e.fn?(t=fnAs(e.fn,e.name),r=e.name,e=e.fn):is.fn(e)?(t=e.toString(),r=e.name):is.string(e)?t=e:is.object(e)&&(t=e.proto?"":e.name+" = {};",r=e.name,e=e.obj),t+="\n";var n=function(e,r){if(e.prototype){var n=!1;for(var i in e.prototype){n=!0;break}n&&(t+=fnAsRequire({name:r,obj:e,proto:!0},e))}};if(e.prototype&&null!=r)for(var i in e.prototype){var a="",o=e.prototype[i],s=stringifyFieldVal(o),l=r+".prototype."+i;a+=l+" = "+s+";\n",a&&(t+=a),n(o,l)}if(!is.string(e))for(var i in e){var u="";if(e.hasOwnProperty(i)){var o=e[i],s=stringifyFieldVal(o),l=r+'["'+i+'"]';u+=l+" = "+s+";\n"}u&&(t+=u),n(o,l)}return t},isPathStr=function(e){return is.string(e)&&e.match(/\.js$/)};util.extend(thdfn,{instanceString:function(){return"thread"},require:function(e,t){var r=this._private.requires;if(isPathStr(e))return this._private.files.push(e),this;if(t)e=is.fn(e)?{name:t,fn:e}:{name:t,obj:e};else if(is.fn(e)){if(!e.name)throw'The function name could not be automatically determined. Use thread.require( someFunction, "someFunction" )';e={name:e.name,fn:e}}return r.push(e),this},pass:function(e){return this._private.pass.push(e),this},run:function(fn,pass){var self=this,_p=this._private;if(pass=pass||_p.pass.shift(),_p.stopped)throw"Attempted to run a stopped thread! Start a new thread or do not stop the existing thread and reuse it.";if(_p.running)return _p.queue=_p.queue.then(function(){return self.run(fn,pass)});var useWW=null!=window&&!_p.disabled,useNode=!window&&"undefined"!=typeof module&&!_p.disabled;self.trigger("run");var runP=new Promise(function(resolve,reject){_p.running=!0;var threadTechAlreadyExists=_p.ran,fnImplStr=is.string(fn)?fn:fn.toString(),fnStr="\n"+_p.requires.map(function(e){return fnAsRequire(e)}).concat(_p.files.map(function(e){if(useWW){var t=function(e){return e.match(/^\.\//)||e.match(/^\.\./)?window.location.origin+window.location.pathname+e:e.match(/^\//)?window.location.origin+"/"+e:e};return'importScripts("'+t(e)+'");'}if(useNode)return'eval( require("fs").readFileSync("'+e+'", { encoding: "utf8" }) );';throw"External file `"+e+"` can not be required without any threading technology."})).concat(["( function(){","var ret = ("+fnImplStr+")("+JSON.stringify(pass)+");","if( ret !== undefined ){ resolve(ret); }","} )()\n"]).join("\n");if(_p.requires=[],_p.files=[],useWW){var fnBlob,fnUrl;if(!threadTechAlreadyExists){var fnPre=fnStr+"";fnStr=["function _ref_(o){ return eval(o); };","function broadcast(m){ return message(m); };","function message(m){ postMessage(m); };","function listen(fn){",' self.addEventListener("message", function(m){ ',' if( typeof m === "object" && (m.data.$$eval || m.data === "$$start") ){'," } else { "," fn( m.data );"," }"," });","};",'self.addEventListener("message", function(m){ if( m.data.$$eval ){ eval( m.data.$$eval ); } });',"function resolve(v){ postMessage({ $$resolve: v }); };","function reject(v){ postMessage({ $$reject: v }); };"].join("\n"),fnStr+=fnPre,fnBlob=new Blob([fnStr],{type:"application/javascript"}),fnUrl=window.URL.createObjectURL(fnBlob)}var ww=_p.webworker=_p.webworker||new Worker(fnUrl);threadTechAlreadyExists&&ww.postMessage({$$eval:fnStr});var cb;ww.addEventListener("message",cb=function(e){var t=is.object(e)&&is.object(e.data);t&&"$$resolve"in e.data?(ww.removeEventListener("message",cb),resolve(e.data.$$resolve)):t&&"$$reject"in e.data?(ww.removeEventListener("message",cb),reject(e.data.$$reject)):self.trigger(new Event(e,{type:"message",message:e.data}))},!1),threadTechAlreadyExists||ww.postMessage("$$start")}else if(useNode){_p.child||(_p.child=_dereq_("child_process").fork(_dereq_("path").join(__dirname,"thread-node-fork")));var child=_p.child,cb;child.on("message",cb=function(e){is.object(e)&&"$$resolve"in e?(child.removeListener("message",cb),resolve(e.$$resolve)):is.object(e)&&"$$reject"in e?(child.removeListener("message",cb),reject(e.$$reject)):self.trigger(new Event({},{type:"message",message:e}))}),child.send({$$eval:fnStr})}else{var promiseResolve=resolve,promiseReject=reject,timer=_p.timer=_p.timer||{listeners:[],exec:function(){fnStr=["function _ref_(o){ return eval(o); };","function broadcast(m){ return message(m); };",'function message(m){ self.trigger( new Event({}, { type: "message", message: m }) ); };',"function listen(fn){ timer.listeners.push( fn ); };","function resolve(v){ promiseResolve(v); };","function reject(v){ promiseReject(v); };"].join("\n")+fnStr,eval(fnStr)},message:function(e){for(var t=timer.listeners,r=0;r<t.length;r++){var n=t[r];n(e)}}};timer.exec()}}).then(function(e){return _p.running=!1,_p.ran=!0,self.trigger("ran"),e});return null==_p.queue&&(_p.queue=runP),runP},message:function(e){var t=this._private;return t.webworker&&t.webworker.postMessage(e),t.child&&t.child.send(e),t.timer&&t.timer.message(e),this},stop:function(){var e=this._private;return e.webworker&&e.webworker.terminate(),e.child&&e.child.kill(),e.timer,e.stopped=!0,this.trigger("stop")},stopped:function(){return this._private.stopped}});var fnAs=function(e,t){var r=e.toString();return r=r.replace(/function\s*?\S*?\s*?\(/,"function "+t+"(")},defineFnal=function(e){return e=e||{},function(t,r){var n=fnAs(t,"_$_$_"+e.name);return this.require(n),this.run(["function( data ){"," var origResolve = resolve;"," var res = [];"," "," resolve = function( val ){"," res.push( val );"," };"," "," var ret = data."+e.name+"( _$_$_"+e.name+(arguments.length>1?", "+JSON.stringify(r):"")+" );"," "," resolve = origResolve;"," resolve( res.length > 0 ? res : ret );","}"].join("\n"))}};util.extend(thdfn,{reduce:defineFnal({name:"reduce"}),reduceRight:defineFnal({name:"reduceRight"}),map:defineFnal({name:"map"})});var fn=thdfn;fn.promise=fn.run,fn.terminate=fn.halt=fn.stop,fn.include=fn.require,util.extend(thdfn,{on:define.on(),one:define.on({unbindSelfOnTrigger:!0}),off:define.off(),trigger:define.trigger()}),define.eventAliasesOn(thdfn),module.exports=Thread},{"./define":44,"./event":45,"./is":83,"./promise":86,"./util":100,"./window":107,child_process:void 0,path:void 0}],99:[function(e,t,r){"use strict";var n=e("../is");t.exports={hex2tuple:function(e){if((4===e.length||7===e.length)&&"#"===e[0]){var t,r,n,i=4===e.length,a=16;return i?(t=parseInt(e[1]+e[1],a),r=parseInt(e[2]+e[2],a),n=parseInt(e[3]+e[3],a)):(t=parseInt(e[1]+e[2],a),r=parseInt(e[3]+e[4],a),n=parseInt(e[5]+e[6],a)),[t,r,n]}},hsl2tuple:function(e){function t(e,t,r){return 0>r&&(r+=1),r>1&&(r-=1),1/6>r?e+6*(t-e)*r:.5>r?t:2/3>r?e+(t-e)*(2/3-r)*6:e}var r,n,i,a,o,s,l,u,c=new RegExp("^"+this.regex.hsla+"$").exec(e);if(c){if(n=parseInt(c[1]),0>n?n=(360- -1*n%360)%360:n>360&&(n%=360),n/=360,i=parseFloat(c[2]),0>i||i>100)return;if(i/=100,a=parseFloat(c[3]),0>a||a>100)return;if(a/=100,o=c[4],void 0!==o&&(o=parseFloat(o),0>o||o>1))return;if(0===i)s=l=u=Math.round(255*a);else{var d=.5>a?a*(1+i):a+i-a*i,h=2*a-d;s=Math.round(255*t(h,d,n+1/3)),l=Math.round(255*t(h,d,n)),u=Math.round(255*t(h,d,n-1/3))}r=[s,l,u,o]}return r},rgb2tuple:function(e){var t,r=new RegExp("^"+this.regex.rgba+"$").exec(e);if(r){t=[];for(var n=[],i=1;3>=i;i++){var a=r[i];if("%"===a[a.length-1]&&(n[i]=!0),a=parseFloat(a),n[i]&&(a=a/100*255),0>a||a>255)return;t.push(Math.floor(a))}var o=n[1]||n[2]||n[3],s=n[1]&&n[2]&&n[3];if(o&&!s)return;var l=r[4];if(void 0!==l){if(l=parseFloat(l),0>l||l>1)return;t.push(l)}}return t},colorname2tuple:function(e){return this.colors[e.toLowerCase()]},color2tuple:function(e){return(n.array(e)?e:null)||this.colorname2tuple(e)||this.hex2tuple(e)||this.rgb2tuple(e)||this.hsl2tuple(e)},colors:{transparent:[0,0,0,0],aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],grey:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]}}},{"../is":83}],100:[function(e,t,r){"use strict";var n=e("../is"),i=e("../math"),a={trueify:function(){return!0},falsify:function(){return!1},zeroify:function(){return 0},noop:function(){},error:function(e){console.error?(console.error.apply(console,arguments),console.trace&&console.trace()):(console.log.apply(console,arguments),console.trace&&console.trace())},clone:function(e){return this.extend({},e)},copy:function(e){return null==e?e:n.array(e)?e.slice():n.plainObject(e)?this.clone(e):e},uuid:function(e,t){for(t=e="";e++<36;t+=51*e&52?(15^e?8^Math.random()*(20^e?16:4):4).toString(16):"-");return t}};a.makeBoundingBox=i.makeBoundingBox.bind(i),a._staticEmptyObject={},a.staticEmptyObject=function(){return a._staticEmptyObject},a.extend=null!=Object.assign?Object.assign:function(e){for(var t=arguments,r=1;r<t.length;r++){var n=t[r];if(n)for(var i=Object.keys(n),a=0;a<i.length;a++){var o=i[a];e[o]=n[o]}}return e},a["default"]=function(e,t){return void 0===e?t:e},a.removeFromArray=function(e,t,r){for(var n=e.length;n>=0&&(e[n]!==t||(e.splice(n,1),r));n--);},a.clearArray=function(e){e.splice(0,e.length)},a.getPrefixedProperty=function(e,t,r){return r&&(t=this.prependCamel(r,t)),e[t]},a.setPrefixedProperty=function(e,t,r,n){r&&(t=this.prependCamel(r,t)),e[t]=n},[e("./colors"),e("./maps"),{memoize:e("./memoize")},e("./regex"),e("./strings"),e("./timing")].forEach(function(e){a.extend(a,e)}),t.exports=a},{"../is":83,"../math":85,"./colors":99,"./maps":101,"./memoize":102,"./regex":103,"./strings":104,"./timing":105}],101:[function(e,t,r){"use strict";var n=e("../is");t.exports={mapEmpty:function(e){var t=!0;return null!=e?0===Object.keys(e).length:t},pushMap:function(e){var t=this.getMap(e);null==t?this.setMap(this.extend({},e,{value:[e.value]})):t.push(e.value)},setMap:function(e){for(var t,r=e.map,i=e.keys,a=i.length,o=0;a>o;o++){var t=i[o];n.plainObject(t)&&this.error("Tried to set map with object key"),o<i.length-1?(null==r[t]&&(r[t]={}),r=r[t]):r[t]=e.value}},getMap:function(e){for(var t=e.map,r=e.keys,i=r.length,a=0;i>a;a++){var o=r[a];if(n.plainObject(o)&&this.error("Tried to get map with object key"),t=t[o],null==t)return t}return t},deleteMap:function(e){for(var t=e.map,r=e.keys,i=r.length,a=e.keepChildren,o=0;i>o;o++){var s=r[o];n.plainObject(s)&&this.error("Tried to delete map with object key");var l=o===e.keys.length-1;if(l)if(a)for(var u=Object.keys(t),c=0;c<u.length;c++){var d=u[c];a[d]||(t[d]=void 0)}else t[s]=void 0;else t=t[s]}}}},{"../is":83}],102:[function(e,t,r){"use strict";t.exports=function(e,t){t||(t=function(){if(1===arguments.length)return arguments[0];if(0===arguments.length)return"undefined";for(var e=[],t=0;t<arguments.length;t++)e.push(arguments[t]);return e.join("$")});var r=function(){var n,i=this,a=arguments,o=t.apply(i,a),s=r.cache;return(n=s[o])||(n=s[o]=e.apply(i,a)),n};return r.cache={},r}},{}],103:[function(e,t,r){"use strict";var n="(?:[-+]?(?:(?:\\d+|\\d*\\.\\d+)(?:[Ee][+-]?\\d+)?))",i="rgb[a]?\\(("+n+"[%]?)\\s*,\\s*("+n+"[%]?)\\s*,\\s*("+n+"[%]?)(?:\\s*,\\s*("+n+"))?\\)",a="rgb[a]?\\((?:"+n+"[%]?)\\s*,\\s*(?:"+n+"[%]?)\\s*,\\s*(?:"+n+"[%]?)(?:\\s*,\\s*(?:"+n+"))?\\)",o="hsl[a]?\\(("+n+")\\s*,\\s*("+n+"[%])\\s*,\\s*("+n+"[%])(?:\\s*,\\s*("+n+"))?\\)",s="hsl[a]?\\((?:"+n+")\\s*,\\s*(?:"+n+"[%])\\s*,\\s*(?:"+n+"[%])(?:\\s*,\\s*(?:"+n+"))?\\)",l="\\#[0-9a-fA-F]{3}",u="\\#[0-9a-fA-F]{6}";t.exports={regex:{number:n,rgba:i,rgbaNoBackRefs:a,hsla:o,hslaNoBackRefs:s,hex3:l,hex6:u}}},{}],104:[function(e,t,r){"use strict";var n=e("./memoize"),i=e("../is");t.exports={camel2dash:n(function(e){return e.replace(/([A-Z])/g,function(e){return"-"+e.toLowerCase()})}),dash2camel:n(function(e){return e.replace(/(-\w)/g,function(e){return e[1].toUpperCase()})}),prependCamel:n(function(e,t){return e+t[0].toUpperCase()+t.substring(1)},function(e,t){return e+"$"+t}),capitalize:function(e){return i.emptyString(e)?e:e.charAt(0).toUpperCase()+e.substring(1)}}},{"../is":83,"./memoize":102}],105:[function(e,t,r){"use strict";var n=e("../window"),i=e("../is"),a=n?n.performance:null,o={},s=n?n.requestAnimationFrame||n.mozRequestAnimationFrame||n.webkitRequestAnimationFrame||n.msRequestAnimationFrame:null;s=s||function(e){e&&setTimeout(function(){e(l())},1e3/60)},o.requestAnimationFrame=function(e){s(e)};var l=a&&a.now?function(){return a.now()}:function(){return Date.now()};o.performanceNow=l,o.throttle=function(e,t,r){var n=!0,a=!0;return r===!1?n=!1:i.plainObject(r)&&(n="leading"in r?r.leading:n,a="trailing"in r?r.trailing:a),r=r||{},r.leading=n,r.maxWait=t,r.trailing=a,o.debounce(e,t,r)},o.now=function(){return Date.now()},o.debounce=function(e,t,r){var n,a,o,s,l,u,c,d=this,h=0,p=!1,f=!0;if(i.fn(e)){if(t=Math.max(0,t)||0,r===!0){var v=!0;f=!1}else i.plainObject(r)&&(v=r.leading,p="maxWait"in r&&(Math.max(t,r.maxWait)||0),f="trailing"in r?r.trailing:f);var g=function(){var r=t-(d.now()-s);if(0>=r){a&&clearTimeout(a);var i=c;a=u=c=void 0,i&&(h=d.now(),o=e.apply(l,n),u||a||(n=l=null))}else u=setTimeout(g,r)},y=function(){u&&clearTimeout(u),a=u=c=void 0,(f||p!==t)&&(h=d.now(),o=e.apply(l,n),u||a||(n=l=null))};return function(){if(n=arguments,s=d.now(),l=this,c=f&&(u||!v),p===!1)var r=v&&!u;else{a||v||(h=s);var i=p-(s-h),m=0>=i;m?(a&&(a=clearTimeout(a)),h=s,o=e.apply(l,n)):a||(a=setTimeout(y,i))}return m&&u?u=clearTimeout(u):u||t===p||(u=setTimeout(g,t)),r&&(m=!0,o=e.apply(l,n)),!m||u||a||(n=l=null),o}}},t.exports=o},{"../is":83,"../window":107}],106:[function(e,t,r){t.exports="2.7.8"},{}],107:[function(e,t,r){t.exports="undefined"==typeof window?null:window},{}]},{},[82])(82)});
\ No newline at end of file diff --git a/wqflask/wqflask/static/packages/cytoscape/js/min/json2.min.js b/wqflask/wqflask/static/packages/cytoscape/js/min/json2.min.js new file mode 100644 index 00000000..273eca0f --- /dev/null +++ b/wqflask/wqflask/static/packages/cytoscape/js/min/json2.min.js @@ -0,0 +1 @@ +if(!this.JSON){this.JSON={}}(function(){function f(n){return n<10?"0"+n:n}if(typeof Date.prototype.toJSON!=="function"){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf()}}var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==="string"?c:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+string+'"'}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==="object"&&typeof value.toJSON==="function"){value=value.toJSON(key)}if(typeof rep==="function"){value=rep.call(holder,key,value)}switch(typeof value){case"string":return quote(value);case"number":return isFinite(value)?String(value):"null";case"boolean":case"null":return String(value);case"object":if(!value){return"null"}gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==="[object Array]"){length=value.length;for(i=0;i<length;i+=1){partial[i]=str(i,value)||"null"}v=partial.length===0?"[]":gap?"[\n"+gap+partial.join(",\n"+gap)+"\n"+mind+"]":"["+partial.join(",")+"]";gap=mind;return v}if(rep&&typeof rep==="object"){length=rep.length;for(i=0;i<length;i+=1){k=rep[i];if(typeof k==="string"){v=str(k,value);if(v){partial.push(quote(k)+(gap?": ":":")+v)}}}}else{for(k in value){if(Object.hasOwnProperty.call(value,k)){v=str(k,value);if(v){partial.push(quote(k)+(gap?": ":":")+v)}}}}v=partial.length===0?"{}":gap?"{\n"+gap+partial.join(",\n"+gap)+"\n"+mind+"}":"{"+partial.join(",")+"}";gap=mind;return v}}if(typeof JSON.stringify!=="function"){JSON.stringify=function(value,replacer,space){var i;gap="";indent="";if(typeof space==="number"){for(i=0;i<space;i+=1){indent+=" "}}else{if(typeof space==="string"){indent=space}}rep=replacer;if(replacer&&typeof replacer!=="function"&&(typeof replacer!=="object"||typeof replacer.length!=="number")){throw new Error("JSON.stringify")}return str("",{"":value})}}if(typeof JSON.parse!=="function"){JSON.parse=function(text,reviver){var j;function walk(holder,key){var k,v,value=holder[key];if(value&&typeof value==="object"){for(k in value){if(Object.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v}else{delete value[k]}}}}return reviver.call(holder,key,value)}cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})}if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))){j=eval("("+text+")");return typeof reviver==="function"?walk({"":j},""):j}throw new SyntaxError("JSON.parse")}}}());
\ No newline at end of file diff --git a/wqflask/wqflask/static/packages/cytoscape/js/src/AC_OETags.js b/wqflask/wqflask/static/packages/cytoscape/js/src/AC_OETags.js new file mode 100644 index 00000000..de66406e --- /dev/null +++ b/wqflask/wqflask/static/packages/cytoscape/js/src/AC_OETags.js @@ -0,0 +1,278 @@ +// Flash Player Version Detection - Rev 1.6 +// Detect Client Browser type +// Copyright(c) 2005-2006 Adobe Macromedia Software, LLC. All rights reserved. +var isIE = (navigator.appVersion.indexOf("MSIE") != -1) ? true : false; +var isWin = (navigator.appVersion.toLowerCase().indexOf("win") != -1) ? true : false; +var isOpera = (navigator.userAgent.indexOf("Opera") != -1) ? true : false; + +function ControlVersion() +{ + var version; + var axo; + var e; + + // NOTE : new ActiveXObject(strFoo) throws an exception if strFoo isn't in the registry + + try { + // version will be set for 7.X or greater players + axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7"); + version = axo.GetVariable("$version"); + } catch (e) { + } + + if (!version) + { + try { + // version will be set for 6.X players only + axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6"); + + // installed player is some revision of 6.0 + // GetVariable("$version") crashes for versions 6.0.22 through 6.0.29, + // so we have to be careful. + + // default to the first public version + version = "WIN 6,0,21,0"; + + // throws if AllowScripAccess does not exist (introduced in 6.0r47) + axo.AllowScriptAccess = "always"; + + // safe to call for 6.0r47 or greater + version = axo.GetVariable("$version"); + + } catch (e) { + } + } + + if (!version) + { + try { + // version will be set for 4.X or 5.X player + axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.3"); + version = axo.GetVariable("$version"); + } catch (e) { + } + } + + if (!version) + { + try { + // version will be set for 3.X player + axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.3"); + version = "WIN 3,0,18,0"; + } catch (e) { + } + } + + if (!version) + { + try { + // version will be set for 2.X player + axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash"); + version = "WIN 2,0,0,11"; + } catch (e) { + version = -1; + } + } + + return version; +} + +// JavaScript helper required to detect Flash Player PlugIn version information +function GetSwfVer(){ + // NS/Opera version >= 3 check for Flash plugin in plugin array + var flashVer = -1; + + if (navigator.plugins != null && navigator.plugins.length > 0) { + if (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]) { + var swVer2 = navigator.plugins["Shockwave Flash 2.0"] ? " 2.0" : ""; + var flashDescription = navigator.plugins["Shockwave Flash" + swVer2].description; + var descArray = flashDescription.split(" "); + var tempArrayMajor = descArray[2].split("."); + var versionMajor = tempArrayMajor[0]; + var versionMinor = tempArrayMajor[1]; + var versionRevision = descArray[3]; + if (versionRevision == "") { + versionRevision = descArray[4]; + } + if (versionRevision[0] == "d") { + versionRevision = versionRevision.substring(1); + } else if (versionRevision[0] == "r") { + versionRevision = versionRevision.substring(1); + if (versionRevision.indexOf("d") > 0) { + versionRevision = versionRevision.substring(0, versionRevision.indexOf("d")); + } + } else if (versionRevision[0] == "b") { + versionRevision = versionRevision.substring(1); + } + var flashVer = versionMajor + "." + versionMinor + "." + versionRevision; + } + } + // MSN/WebTV 2.6 supports Flash 4 + else if (navigator.userAgent.toLowerCase().indexOf("webtv/2.6") != -1) flashVer = 4; + // WebTV 2.5 supports Flash 3 + else if (navigator.userAgent.toLowerCase().indexOf("webtv/2.5") != -1) flashVer = 3; + // older WebTV supports Flash 2 + else if (navigator.userAgent.toLowerCase().indexOf("webtv") != -1) flashVer = 2; + else if ( isIE && isWin && !isOpera ) { + flashVer = ControlVersion(); + } + return flashVer; +} + +// When called with reqMajorVer, reqMinorVer, reqRevision returns true if that version or greater is available +function DetectFlashVer(reqMajorVer, reqMinorVer, reqRevision) +{ + versionStr = GetSwfVer(); + if (versionStr == -1 ) { + return false; + } else if (versionStr != 0) { + if(isIE && isWin && !isOpera) { + // Given "WIN 2,0,0,11" + tempArray = versionStr.split(" "); // ["WIN", "2,0,0,11"] + tempString = tempArray[1]; // "2,0,0,11" + versionArray = tempString.split(","); // ['2', '0', '0', '11'] + } else { + versionArray = versionStr.split("."); + } + var versionMajor = versionArray[0]; + var versionMinor = versionArray[1]; + var versionRevision = versionArray[2]; + + // is the major.revision >= requested major.revision AND the minor version >= requested minor + if (versionMajor > parseFloat(reqMajorVer)) { + return true; + } else if (versionMajor == parseFloat(reqMajorVer)) { + if (versionMinor > parseFloat(reqMinorVer)) + return true; + else if (versionMinor == parseFloat(reqMinorVer)) { + if (versionRevision >= parseFloat(reqRevision)) + return true; + } + } + return false; + } +} + +function AC_AddExtension(src, ext) +{ + if (src.indexOf('?') != -1) + return src.replace(/\?/, ext+'?'); + else + return src + ext; +} + +function AC_Generateobj(objAttrs, params, embedAttrs) +{ + var str = ''; + if (isIE && isWin && !isOpera) + { + str += '<object '; + for (var i in objAttrs) + str += i + '="' + objAttrs[i] + '" '; + str += '>'; + for (var i in params) + str += '<param name="' + i + '" value="' + params[i] + '" /> '; + str += '</object>'; + } else { + str += '<embed '; + for (var i in embedAttrs) + str += i + '="' + embedAttrs[i] + '" '; + str += '> </embed>'; + } + + document.write(str); +} + +function AC_FL_RunContent(){ + var ret = + AC_GetArgs + ( arguments, ".swf", "movie", "clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" + , "application/x-shockwave-flash" + ); + AC_Generateobj(ret.objAttrs, ret.params, ret.embedAttrs); +} + +function AC_GetArgs(args, ext, srcParamName, classid, mimeType){ + var ret = new Object(); + ret.embedAttrs = new Object(); + ret.params = new Object(); + ret.objAttrs = new Object(); + for (var i=0; i < args.length; i=i+2){ + var currArg = args[i].toLowerCase(); + + switch (currArg){ + case "classid": + break; + case "pluginspage": + ret.embedAttrs[args[i]] = args[i+1]; + break; + case "src": + case "movie": + args[i+1] = AC_AddExtension(args[i+1], ext); + ret.embedAttrs["src"] = args[i+1]; + ret.params[srcParamName] = args[i+1]; + break; + case "onafterupdate": + case "onbeforeupdate": + case "onblur": + case "oncellchange": + case "onclick": + case "ondblClick": + case "ondrag": + case "ondragend": + case "ondragenter": + case "ondragleave": + case "ondragover": + case "ondrop": + case "onfinish": + case "onfocus": + case "onhelp": + case "onmousedown": + case "onmouseup": + case "onmouseover": + case "onmousemove": + case "onmouseout": + case "onkeypress": + case "onkeydown": + case "onkeyup": + case "onload": + case "onlosecapture": + case "onpropertychange": + case "onreadystatechange": + case "onrowsdelete": + case "onrowenter": + case "onrowexit": + case "onrowsinserted": + case "onstart": + case "onscroll": + case "onbeforeeditfocus": + case "onactivate": + case "onbeforedeactivate": + case "ondeactivate": + case "type": + case "codebase": + ret.objAttrs[args[i]] = args[i+1]; + break; + case "id": + case "width": + case "height": + case "align": + case "vspace": + case "hspace": + case "class": + case "title": + case "accesskey": + case "name": + case "tabindex": + ret.embedAttrs[args[i]] = ret.objAttrs[args[i]] = args[i+1]; + break; + default: + ret.embedAttrs[args[i]] = ret.params[args[i]] = args[i+1]; + } + } + ret.objAttrs["classid"] = classid; + if (mimeType) ret.embedAttrs["type"] = mimeType; + return ret; +} + + diff --git a/wqflask/wqflask/static/packages/cytoscape/js/src/cytoscape-panzoom.js b/wqflask/wqflask/static/packages/cytoscape/js/src/cytoscape-panzoom.js new file mode 100644 index 00000000..3024cda5 --- /dev/null +++ b/wqflask/wqflask/static/packages/cytoscape/js/src/cytoscape-panzoom.js @@ -0,0 +1,594 @@ +/*!
+Copyright (c) The Cytoscape Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the “Software”), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+;(function(){ 'use strict';
+
+ // registers the extension on a cytoscape lib ref
+ var register = function( cytoscape, $ ){
+ if( !cytoscape ){ return; } // can't register if cytoscape unspecified
+
+ $.fn.cyPanzoom = $.fn.cytoscapePanzoom = function( options ){
+ panzoom.apply( this, [ options, $ ] );
+
+ return this; // chainability
+ };
+
+ // if you want a core extension
+ cytoscape('core', 'panzoom', function( options ){ // could use options object, but args are up to you
+ var cy = this;
+
+ panzoom.apply( cy.container(), [ options, $ ] );
+
+ return this; // chainability
+ });
+
+ };
+
+ var defaults = {
+ zoomFactor: 0.05, // zoom factor per zoom tick
+ zoomDelay: 45, // how many ms between zoom ticks
+ minZoom: 0.1, // min zoom level
+ maxZoom: 10, // max zoom level
+ fitPadding: 50, // padding when fitting
+ panSpeed: 10, // how many ms in between pan ticks
+ panDistance: 10, // max pan distance per tick
+ panDragAreaSize: 75, // the length of the pan drag box in which the vector for panning is calculated (bigger = finer control of pan speed and direction)
+ panMinPercentSpeed: 0.25, // the slowest speed we can pan by (as a percent of panSpeed)
+ panInactiveArea: 8, // radius of inactive area in pan drag box
+ panIndicatorMinOpacity: 0.5, // min opacity of pan indicator (the draggable nib); scales from this to 1.0
+ zoomOnly: false, // a minimal version of the ui only with zooming (useful on systems with bad mousewheel resolution)
+ fitSelector: undefined, // selector of elements to fit
+ animateOnFit: function(){ // whether to animate on fit
+ return false;
+ },
+ fitAnimationDuration: 1000, // duration of animation on fit
+
+ // icon class names
+ sliderHandleIcon: 'fa fa-minus',
+ zoomInIcon: 'fa fa-plus',
+ zoomOutIcon: 'fa fa-minus',
+ resetIcon: 'fa fa-expand'
+ };
+
+ var panzoom = function( params, $ ){
+ var options = $.extend(true, {}, defaults, params);
+ var fn = params;
+
+ var functions = {
+ destroy: function(){
+ var $this = $(this);
+ var $pz = $this.find(".cy-panzoom");
+
+ $pz.data('winbdgs').forEach(function( l ){
+ $(window).unbind( l.evt, l.fn );
+ });
+
+ $pz.data('cybdgs').forEach(function( l ){
+ $this.cytoscape('get').off( l.evt, l.fn );
+ });
+
+ $pz.remove();
+ },
+
+ init: function(){
+ var browserIsMobile = 'ontouchstart' in window;
+
+ return $(this).each(function(){
+ var $container = $(this);
+
+ var winbdgs = [];
+ var $win = $(window);
+
+ var windowBind = function( evt, fn ){
+ winbdgs.push({ evt: evt, fn: fn });
+
+ $win.bind( evt, fn );
+ };
+
+ var windowUnbind = function( evt, fn ){
+ for( var i = 0; i < winbdgs.length; i++ ){
+ var l = winbdgs[i];
+
+ if( l.evt === evt && l.fn === fn ){
+ winbdgs.splice( i, 1 );
+ break;
+ }
+ }
+
+ $win.unbind( evt, fn );
+ };
+
+ var cybdgs = [];
+ var cy = $container.cytoscape('get');
+
+ var cyOn = function( evt, fn ){
+ cybdgs.push({ evt: evt, fn: fn });
+
+ cy.on( evt, fn );
+ };
+
+ var cyOff = function( evt, fn ){
+ for( var i = 0; i < cybdgs.length; i++ ){
+ var l = cybdgs[i];
+
+ if( l.evt === evt && l.fn === fn ){
+ cybdgs.splice( i, 1 );
+ break;
+ }
+ }
+
+ cy.off( evt, fn );
+ };
+
+ var $panzoom = $('<div class="cy-panzoom"></div>');
+ $container.prepend( $panzoom );
+
+ $panzoom.css('position', 'absolute'); // must be absolute regardless of stylesheet
+
+ $panzoom.data('winbdgs', winbdgs);
+ $panzoom.data('cybdgs', cybdgs);
+
+ if( options.zoomOnly ){
+ $panzoom.addClass("cy-panzoom-zoom-only");
+ }
+
+ // add base html elements
+ /////////////////////////
+
+ var $zoomIn = $('<div class="cy-panzoom-zoom-in cy-panzoom-zoom-button"><span class="icon '+ options.zoomInIcon +'"></span></div>');
+ $panzoom.append( $zoomIn );
+
+ var $zoomOut = $('<div class="cy-panzoom-zoom-out cy-panzoom-zoom-button"><span class="icon ' + options.zoomOutIcon + '"></span></div>');
+ $panzoom.append( $zoomOut );
+
+ var $reset = $('<div class="cy-panzoom-reset cy-panzoom-zoom-button"><span class="icon ' + options.resetIcon + '"></span></div>');
+ $panzoom.append( $reset );
+
+ var $slider = $('<div class="cy-panzoom-slider"></div>');
+ $panzoom.append( $slider );
+
+ $slider.append('<div class="cy-panzoom-slider-background"></div>');
+
+ var $sliderHandle = $('<div class="cy-panzoom-slider-handle"><span class="icon ' + options.sliderHandleIcon + '"></span></div>');
+ $slider.append( $sliderHandle );
+
+ var $noZoomTick = $('<div class="cy-panzoom-no-zoom-tick"></div>');
+ $slider.append( $noZoomTick );
+
+ var $panner = $('<div class="cy-panzoom-panner"></div>');
+ $panzoom.append( $panner );
+
+ var $pHandle = $('<div class="cy-panzoom-panner-handle"></div>');
+ $panner.append( $pHandle );
+
+ var $pUp = $('<div class="cy-panzoom-pan-up cy-panzoom-pan-button"></div>');
+ var $pDown = $('<div class="cy-panzoom-pan-down cy-panzoom-pan-button"></div>');
+ var $pLeft = $('<div class="cy-panzoom-pan-left cy-panzoom-pan-button"></div>');
+ var $pRight = $('<div class="cy-panzoom-pan-right cy-panzoom-pan-button"></div>');
+ $panner.append( $pUp ).append( $pDown ).append( $pLeft ).append( $pRight );
+
+ var $pIndicator = $('<div class="cy-panzoom-pan-indicator"></div>');
+ $panner.append( $pIndicator );
+
+ // functions for calculating panning
+ ////////////////////////////////////
+
+ function handle2pan(e){
+ var v = {
+ x: e.originalEvent.pageX - $panner.offset().left - $panner.width()/2,
+ y: e.originalEvent.pageY - $panner.offset().top - $panner.height()/2
+ }
+
+ var r = options.panDragAreaSize;
+ var d = Math.sqrt( v.x*v.x + v.y*v.y );
+ var percent = Math.min( d/r, 1 );
+
+ if( d < options.panInactiveArea ){
+ return {
+ x: NaN,
+ y: NaN
+ };
+ }
+
+ v = {
+ x: v.x/d,
+ y: v.y/d
+ };
+
+ percent = Math.max( options.panMinPercentSpeed, percent );
+
+ var vnorm = {
+ x: -1 * v.x * (percent * options.panDistance),
+ y: -1 * v.y * (percent * options.panDistance)
+ };
+
+ return vnorm;
+ }
+
+ function donePanning(){
+ clearInterval(panInterval);
+ windowUnbind("mousemove", handler);
+
+ $pIndicator.hide();
+ }
+
+ function positionIndicator(pan){
+ var v = pan;
+ var d = Math.sqrt( v.x*v.x + v.y*v.y );
+ var vnorm = {
+ x: -1 * v.x/d,
+ y: -1 * v.y/d
+ };
+
+ var w = $panner.width();
+ var h = $panner.height();
+ var percent = d/options.panDistance;
+ var opacity = Math.max( options.panIndicatorMinOpacity, percent );
+ var color = 255 - Math.round( opacity * 255 );
+
+ $pIndicator.show().css({
+ left: w/2 * vnorm.x + w/2,
+ top: h/2 * vnorm.y + h/2,
+ background: "rgb(" + color + ", " + color + ", " + color + ")"
+ });
+ }
+
+ function calculateZoomCenterPoint(){
+ var cy = $container.cytoscape("get");
+ var pan = cy.pan();
+ var zoom = cy.zoom();
+
+ zx = $container.width()/2;
+ zy = $container.height()/2;
+ }
+
+ var zooming = false;
+ function startZooming(){
+ zooming = true;
+
+ calculateZoomCenterPoint();
+ }
+
+
+ function endZooming(){
+ zooming = false;
+ }
+
+ var zx, zy;
+ function zoomTo(level){
+ var cy = $container.cytoscape("get");
+
+ if( !zooming ){ // for non-continuous zooming (e.g. click slider at pt)
+ calculateZoomCenterPoint();
+ }
+
+ cy.zoom({
+ level: level,
+ renderedPosition: { x: zx, y: zy }
+ });
+ }
+
+ var panInterval;
+
+ var handler = function(e){
+ e.stopPropagation(); // don't trigger dragging of panzoom
+ e.preventDefault(); // don't cause text selection
+ clearInterval(panInterval);
+
+ var pan = handle2pan(e);
+
+ if( isNaN(pan.x) || isNaN(pan.y) ){
+ $pIndicator.hide();
+ return;
+ }
+
+ positionIndicator(pan);
+ panInterval = setInterval(function(){
+ $container.cytoscape("get").panBy(pan);
+ }, options.panSpeed);
+ };
+
+ $pHandle.bind("mousedown", function(e){
+ // handle click of icon
+ handler(e);
+
+ // update on mousemove
+ windowBind("mousemove", handler);
+ });
+
+ $pHandle.bind("mouseup", function(){
+ donePanning();
+ });
+
+ windowBind("mouseup blur", function(){
+ donePanning();
+ });
+
+
+
+ // set up slider behaviour
+ //////////////////////////
+
+ $slider.bind('mousedown', function(){
+ return false; // so we don't pan close to the slider handle
+ });
+
+ var sliderVal;
+ var sliding = false;
+ var sliderPadding = 2;
+
+ function setSliderFromMouse(evt, handleOffset){
+ if( handleOffset === undefined ){
+ handleOffset = 0;
+ }
+
+ var padding = sliderPadding;
+ var min = 0 + padding;
+ var max = $slider.height() - $sliderHandle.height() - 2*padding;
+ var top = evt.pageY - $slider.offset().top - handleOffset;
+
+ // constrain to slider bounds
+ if( top < min ){ top = min }
+ if( top > max ){ top = max }
+
+ var percent = 1 - (top - min) / ( max - min );
+
+ // move the handle
+ $sliderHandle.css('top', top);
+
+ var zmin = options.minZoom;
+ var zmax = options.maxZoom;
+
+ // assume (zoom = zmax ^ p) where p ranges on (x, 1) with x negative
+ var x = Math.log(zmin) / Math.log(zmax);
+ var p = (1 - x)*percent + x;
+
+ // change the zoom level
+ var z = Math.pow( zmax, p );
+
+ // bound the zoom value in case of floating pt rounding error
+ if( z < zmin ){
+ z = zmin;
+ } else if( z > zmax ){
+ z = zmax;
+ }
+
+ zoomTo( z );
+ }
+
+ var sliderMdownHandler, sliderMmoveHandler;
+ $sliderHandle.bind('mousedown', sliderMdownHandler = function( mdEvt ){
+ var handleOffset = mdEvt.target === $sliderHandle[0] ? mdEvt.offsetY : 0;
+ sliding = true;
+
+ startZooming();
+ $sliderHandle.addClass("active");
+
+ var lastMove = 0;
+ windowBind('mousemove', sliderMmoveHandler = function( mmEvt ){
+ var now = +new Date;
+
+ // throttle the zooms every 10 ms so we don't call zoom too often and cause lag
+ if( now > lastMove + 10 ){
+ lastMove = now;
+ } else {
+ return false;
+ }
+
+ setSliderFromMouse(mmEvt, handleOffset);
+
+ return false;
+ });
+
+ // unbind when
+ windowBind('mouseup', function(){
+ windowUnbind('mousemove', sliderMmoveHandler);
+ sliding = false;
+
+ $sliderHandle.removeClass("active");
+ endZooming();
+ });
+
+ return false;
+ });
+
+ $slider.bind('mousedown', function(e){
+ if( e.target !== $sliderHandle[0] ){
+ sliderMdownHandler(e);
+ setSliderFromMouse(e);
+ }
+ });
+
+ function positionSliderFromZoom(){
+ var cy = $container.cytoscape("get");
+ var z = cy.zoom();
+ var zmin = options.minZoom;
+ var zmax = options.maxZoom;
+
+ // assume (zoom = zmax ^ p) where p ranges on (x, 1) with x negative
+ var x = Math.log(zmin) / Math.log(zmax);
+ var p = Math.log(z) / Math.log(zmax);
+ var percent = 1 - (p - x) / (1 - x); // the 1- bit at the front b/c up is in the -ve y direction
+
+ var min = sliderPadding;
+ var max = $slider.height() - $sliderHandle.height() - 2*sliderPadding;
+ var top = percent * ( max - min );
+
+ // constrain to slider bounds
+ if( top < min ){ top = min }
+ if( top > max ){ top = max }
+
+ // move the handle
+ $sliderHandle.css('top', top);
+ }
+
+ positionSliderFromZoom();
+
+ cyOn('zoom', function(){
+ if( !sliding ){
+ positionSliderFromZoom();
+ }
+ });
+
+ // set the position of the zoom=1 tick
+ (function(){
+ var z = 1;
+ var zmin = options.minZoom;
+ var zmax = options.maxZoom;
+
+ // assume (zoom = zmax ^ p) where p ranges on (x, 1) with x negative
+ var x = Math.log(zmin) / Math.log(zmax);
+ var p = Math.log(z) / Math.log(zmax);
+ var percent = 1 - (p - x) / (1 - x); // the 1- bit at the front b/c up is in the -ve y direction
+
+ if( percent > 1 || percent < 0 ){
+ $noZoomTick.hide();
+ return;
+ }
+
+ var min = sliderPadding;
+ var max = $slider.height() - $sliderHandle.height() - 2*sliderPadding;
+ var top = percent * ( max - min );
+
+ // constrain to slider bounds
+ if( top < min ){ top = min }
+ if( top > max ){ top = max }
+
+ $noZoomTick.css('top', top);
+ })();
+
+ // set up zoom in/out buttons
+ /////////////////////////////
+
+ function bindButton($button, factor){
+ var zoomInterval;
+
+ $button.bind("mousedown", function(e){
+ e.preventDefault();
+ e.stopPropagation();
+
+ if( e.button != 0 ){
+ return;
+ }
+
+ var cy = $container.cytoscape("get");
+ var doZoom = function(){
+ var zoom = cy.zoom();
+ var lvl = cy.zoom() * factor;
+
+ if( lvl < options.minZoom ){
+ lvl = options.minZoom;
+ }
+
+ if( lvl > options.maxZoom ){
+ lvl = options.maxZoom;
+ }
+
+ if( (lvl == options.maxZoom && zoom == options.maxZoom) ||
+ (lvl == options.minZoom && zoom == options.minZoom)
+ ){
+ return;
+ }
+
+ zoomTo(lvl);
+ };
+
+ startZooming();
+ doZoom();
+ zoomInterval = setInterval(doZoom, options.zoomDelay);
+
+ return false;
+ });
+
+ windowBind("mouseup blur", function(){
+ clearInterval(zoomInterval);
+ endZooming();
+ });
+ }
+
+ bindButton( $zoomIn, (1 + options.zoomFactor) );
+ bindButton( $zoomOut, (1 - options.zoomFactor) );
+
+ $reset.bind("mousedown", function(e){
+ if( e.button != 0 ){
+ return;
+ }
+
+ var cy = $container.cytoscape("get");
+ var elesToFit = options.fitSelector?cy.elements(options.fitSelector):cy.elements();
+
+ if( elesToFit.size() === 0 ){
+ cy.reset();
+ } else {
+ var animateOnFit = typeof options.animateOnFit === 'function' ? options.animateOnFit.call() : options.animateOnFit;
+ if(animateOnFit){
+ cy.animate({
+ fit: {
+ eles: elesToFit,
+ padding: options.fitPadding
+ }
+ }, {
+ duration: options.fitAnimationDuration
+ });
+ }
+ else{
+ cy.fit( elesToFit, options.fitPadding );
+ }
+
+ }
+
+ return false;
+ });
+
+
+
+ });
+ }
+ };
+
+ if( functions[fn] ){
+ return functions[fn].apply(this, Array.prototype.slice.call( arguments, 1 ));
+ } else if( typeof fn == 'object' || !fn ) {
+ return functions.init.apply( this, arguments );
+ } else {
+ $.error("No such function `"+ fn +"` for jquery.cytoscapePanzoom");
+ }
+
+ return $(this);
+ };
+
+
+ if( typeof module !== 'undefined' && module.exports ){ // expose as a commonjs module
+ module.exports = register;
+ }
+
+ if( typeof define !== 'undefined' && define.amd ){ // expose as an amd/requirejs module
+ define('cytoscape-panzoom', function(){
+ return register;
+ });
+ }
+
+ if( typeof cytoscape !== 'undefined' && typeof jQuery !== 'undefined' ){ // expose to global cytoscape (i.e. window.cytoscape)
+ register( cytoscape, jQuery );
+ }
+
+})();
diff --git a/wqflask/wqflask/static/packages/cytoscape/js/src/cytoscape-qtip.js b/wqflask/wqflask/static/packages/cytoscape/js/src/cytoscape-qtip.js new file mode 100644 index 00000000..9527279c --- /dev/null +++ b/wqflask/wqflask/static/packages/cytoscape/js/src/cytoscape-qtip.js @@ -0,0 +1,398 @@ +/*!
+Copyright (c) The Cytoscape Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the “Software”), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+;(function( $, $$ ){ 'use strict';
+
+ var isObject = function(o){
+ return o != null && typeof o === 'object';
+ };
+
+ var isFunction = function(o){
+ return o != null && typeof o === 'function';
+ };
+
+ var isNumber = function(o){
+ return o != null && typeof o === 'number';
+ };
+
+ var isString = function(o){
+ return o != null && typeof o === 'string';
+ };
+
+ var isUndef = function(o){
+ return o === undefined;
+ };
+
+ var wrap = function(obj, target) {
+ if( isFunction(obj) ) {
+ return function(event, api){
+ return obj.apply( target, [event, api] );
+ };
+ } else {
+ return obj;
+ }
+ };
+
+ var throttle = function(func, wait, options) {
+ var leading = true,
+ trailing = true;
+
+ if (options === false) {
+ leading = false;
+ } else if (isObject(options)) {
+ leading = 'leading' in options ? options.leading : leading;
+ trailing = 'trailing' in options ? options.trailing : trailing;
+ }
+ options = options || {};
+ options.leading = leading;
+ options.maxWait = wait;
+ options.trailing = trailing;
+
+ return debounce(func, wait, options);
+ };
+
+ var debounce = function(func, wait, options) { // ported lodash debounce function
+ var args,
+ maxTimeoutId,
+ result,
+ stamp,
+ thisArg,
+ timeoutId,
+ trailingCall,
+ lastCalled = 0,
+ maxWait = false,
+ trailing = true;
+
+ if (!isFunction(func)) {
+ return;
+ }
+ wait = Math.max(0, wait) || 0;
+ if (options === true) {
+ var leading = true;
+ trailing = false;
+ } else if (isObject(options)) {
+ leading = options.leading;
+ maxWait = 'maxWait' in options && (Math.max(wait, options.maxWait) || 0);
+ trailing = 'trailing' in options ? options.trailing : trailing;
+ }
+ var delayed = function() {
+ var remaining = wait - (Date.now() - stamp);
+ if (remaining <= 0) {
+ if (maxTimeoutId) {
+ clearTimeout(maxTimeoutId);
+ }
+ var isCalled = trailingCall;
+ maxTimeoutId = timeoutId = trailingCall = undefined;
+ if (isCalled) {
+ lastCalled = Date.now();
+ result = func.apply(thisArg, args);
+ if (!timeoutId && !maxTimeoutId) {
+ args = thisArg = null;
+ }
+ }
+ } else {
+ timeoutId = setTimeout(delayed, remaining);
+ }
+ };
+
+ var maxDelayed = function() {
+ if (timeoutId) {
+ clearTimeout(timeoutId);
+ }
+ maxTimeoutId = timeoutId = trailingCall = undefined;
+ if (trailing || (maxWait !== wait)) {
+ lastCalled = Date.now();
+ result = func.apply(thisArg, args);
+ if (!timeoutId && !maxTimeoutId) {
+ args = thisArg = null;
+ }
+ }
+ };
+
+ return function() {
+ args = arguments;
+ stamp = Date.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;
+
+ 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 = null;
+ }
+ return result;
+ };
+ };
+
+ function register( $$, $ ){
+
+ // use a single dummy dom ele as target for every qtip
+ var $qtipContainer = $('<div></div>');
+ var viewportDebounceRate = 250;
+
+ function generateOpts( target, passedOpts ){
+ var qtip = target.scratch().qtip;
+ var opts = $.extend( {}, passedOpts );
+
+ if( !opts.id ){
+ opts.id = 'cy-qtip-target-' + ( Date.now() + Math.round( Math.random() * 10000) );
+ }
+
+ if( !qtip.$domEle ){
+ qtip.$domEle = $qtipContainer;
+ }
+
+ // qtip should be positioned relative to cy dom container
+ opts.position = opts.position || {};
+ opts.position.container = opts.position.container || $( document.body );
+ opts.position.viewport = opts.position.viewport || $( document.body );
+ opts.position.target = [0, 0];
+ opts.position.my = opts.position.my || 'top center';
+ opts.position.at = opts.position.at || 'bottom center';
+
+ // adjust
+ var adjust = opts.position.adjust = opts.position.adjust || {};
+ adjust.method = adjust.method || 'flip';
+ adjust.mouse = false;
+
+ if( isUndef(adjust.cyAdjustToEleBB) ){
+ adjust.cyAdjustToEleBB = true;
+ }
+
+ // default show event
+ opts.show = opts.show || {};
+
+ if( isUndef(opts.show.event) ){
+ opts.show.event = 'tap';
+ }
+
+ // default hide event
+ opts.hide = opts.hide || {};
+ opts.hide.cyViewport = opts.hide.cyViewport === undefined ? true : opts.hide.cyViewport;
+
+ if( isUndef(opts.hide.event) ){
+ opts.hide.event = 'unfocus';
+ }
+
+ // so multiple qtips can exist at once (only works on recent qtip2 versions)
+ opts.overwrite = false;
+
+ if( opts.content ){
+ if ( isFunction(opts.content) || isString(opts.content) ){
+ opts.content = wrap( opts.content, target );
+ } else {
+ opts.content = {
+ text: wrap( opts.content.text, target ),
+ title: wrap( opts.content.title, target )
+ };
+ }
+ }
+
+ return opts;
+ }
+
+ $$('collection', 'qtip', function( passedOpts ){
+ var eles = this;
+ var cy = this.cy();
+ var container = cy.container();
+
+ if( passedOpts === 'api' ){
+ return this.scratch().qtip.api;
+ }
+
+ eles.each(function(i, ele){
+ var scratch = ele.scratch();
+ var qtip = scratch.qtip = scratch.qtip || {};
+ var opts = generateOpts( ele, passedOpts );
+ var adjNums = opts.position.adjust;
+
+
+ qtip.$domEle.qtip( opts );
+ var qtipApi = qtip.api = qtip.$domEle.qtip('api'); // save api ref
+ qtip.$domEle.removeData('qtip'); // remove qtip dom/api ref to be safe
+
+ var updatePosition = function(e){
+ var cOff = container.getBoundingClientRect();
+ var pos = ele.renderedPosition() || ( e ? e.cyRenderedPosition : undefined );
+ if( !pos || pos.x == null || isNaN(pos.x) ){ return; }
+
+ if( opts.position.adjust.cyAdjustToEleBB && ele.isNode() ){
+ var my = opts.position.my.toLowerCase();
+ var at = opts.position.at.toLowerCase();
+ var z = cy.zoom();
+ var w = ele.outerWidth() * z;
+ var h = ele.outerHeight() * z;
+
+ if( at.match('top') ){
+ pos.y -= h/2;
+ } else if( at.match('bottom') ){
+ pos.y += h/2;
+ }
+
+ if( at.match('left') ){
+ pos.x -= w/2;
+ } else if( at.match('right') ){
+ pos.x += w/2;
+ }
+
+ if( isNumber(adjNums.x) ){
+ pos.x += adjNums.x;
+ }
+
+ if( isNumber(adjNums.y) ){
+ pos.y += adjNums.y;
+ }
+ }
+
+ qtipApi.set('position.adjust.x', cOff.left + pos.x + window.pageXOffset);
+ qtipApi.set('position.adjust.y', cOff.top + pos.y + window.pageYOffset);
+ };
+ updatePosition();
+
+ ele.on( opts.show.event, function(e){
+ updatePosition(e);
+
+ qtipApi.show();
+ } );
+
+ ele.on( opts.hide.event, function(e){
+ qtipApi.hide();
+ } );
+
+ if( opts.hide.cyViewport ){
+ cy.on('viewport', debounce(function(){
+ qtipApi.hide();
+ }, viewportDebounceRate, { leading: true }) );
+ }
+
+ if( opts.position.adjust.cyViewport ){
+ cy.on('pan zoom', debounce(function(e){
+ updatePosition(e);
+
+ qtipApi.reposition();
+ }, viewportDebounceRate, { trailing: true }) );
+ }
+
+ });
+
+ return this; // chainability
+
+ });
+
+ $$('core', 'qtip', function( passedOpts ){
+ var cy = this;
+ var container = cy.container();
+
+ if( passedOpts === 'api' ){
+ return this.scratch().qtip.api;
+ }
+
+ var scratch = cy.scratch();
+ var qtip = scratch.qtip = scratch.qtip || {};
+ var opts = generateOpts( cy, passedOpts );
+
+
+ qtip.$domEle.qtip( opts );
+ var qtipApi = qtip.api = qtip.$domEle.qtip('api'); // save api ref
+ qtip.$domEle.removeData('qtip'); // remove qtip dom/api ref to be safe
+
+ var updatePosition = function(e){
+ var cOff = container.getBoundingClientRect();
+ var pos = e.cyRenderedPosition;
+ if( !pos || pos.x == null || isNaN(pos.x) ){ return; }
+
+ qtipApi.set('position.adjust.x', cOff.left + pos.x + window.pageXOffset);
+ qtipApi.set('position.adjust.y', cOff.top + pos.y + window.pageYOffset);
+ };
+
+ cy.on( opts.show.event, function(e){
+ if( !opts.show.cyBgOnly || (opts.show.cyBgOnly && e.cyTarget === cy) ){
+ updatePosition(e);
+
+ qtipApi.show();
+ }
+ } );
+
+ cy.on( opts.hide.event, function(e){
+ if( !opts.hide.cyBgOnly || (opts.hide.cyBgOnly && e.cyTarget === cy) ){
+ qtipApi.hide();
+ }
+ } );
+
+ if( opts.hide.cyViewport ){
+ cy.on('viewport', debounce(function(){
+ qtipApi.hide();
+ }, viewportDebounceRate, { leading: true }) );
+ }
+
+ return this; // chainability
+
+ });
+
+ }
+
+ if( typeof module !== 'undefined' && module.exports ){ // expose as a commonjs module
+ module.exports = register;
+ }
+
+ if( typeof define !== 'undefined' && define.amd ){ // expose as an amd/requirejs module
+ define('cytoscape-qtip', function(){
+ return register;
+ });
+ }
+
+ if( $ && $$ ){
+ register( $$, $ );
+ }
+
+})(
+ typeof jQuery !== 'undefined' ? jQuery : null,
+ typeof cytoscape !== 'undefined' ? cytoscape : null
+);
diff --git a/wqflask/wqflask/static/packages/cytoscape/js/src/cytoscape.js b/wqflask/wqflask/static/packages/cytoscape/js/src/cytoscape.js new file mode 100644 index 00000000..8267b7f2 --- /dev/null +++ b/wqflask/wqflask/static/packages/cytoscape/js/src/cytoscape.js @@ -0,0 +1,26998 @@ +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.cytoscape = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){ + +/*! + +Cytoscape.js 2.7.8 (MIT licensed) + +Copyright (c) The Cytoscape Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the “Software”), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +'use strict'; + +},{}],2:[function(_dereq_,module,exports){ +'use strict'; + +var util = _dereq_( './util' ); +var is = _dereq_( './is' ); +var Promise = _dereq_( './promise' ); + +var Animation = function( target, opts, opts2 ){ + if( !(this instanceof Animation) ){ + return new Animation( target, opts, opts2 ); + } + + var _p = this._private = util.extend( { + duration: 1000 + }, opts, opts2 ); + + _p.target = target; + _p.style = _p.style || _p.css; + _p.started = false; + _p.playing = false; + _p.hooked = false; + _p.applying = false; + _p.progress = 0; + _p.completes = []; + _p.frames = []; + + if( _p.complete && is.fn( _p.complete ) ){ + _p.completes.push( _p.complete ); + } + + // for future timeline/animations impl + this.length = 1; + this[0] = this; +}; + +var anifn = Animation.prototype; + +util.extend( anifn, { + + instanceString: function(){ return 'animation'; }, + + hook: function(){ + var _p = this._private; + + if( !_p.hooked ){ + // add to target's animation queue + var q; + var tAni = _p.target._private.animation; + if( _p.queue ){ + q = tAni.queue; + } else { + q = tAni.current; + } + q.push( this ); + + // add to the animation loop pool + if( is.elementOrCollection( _p.target ) ){ + _p.target.cy().addToAnimationPool( _p.target ); + } + + _p.hooked = true; + } + + return this; + }, + + play: function(){ + var _p = this._private; + + // autorewind + if( _p.progress === 1 ){ + _p.progress = 0; + } + + _p.playing = true; + _p.started = false; // needs to be started by animation loop + _p.stopped = false; + + this.hook(); + + // the animation loop will start the animation... + + return this; + }, + + playing: function(){ + return this._private.playing; + }, + + apply: function(){ + var _p = this._private; + + _p.applying = true; + _p.started = false; // needs to be started by animation loop + _p.stopped = false; + + this.hook(); + + // the animation loop will apply the animation at this progress + + return this; + }, + + applying: function(){ + return this._private.applying; + }, + + pause: function(){ + var _p = this._private; + + _p.playing = false; + _p.started = false; + + return this; + }, + + stop: function(){ + var _p = this._private; + + _p.playing = false; + _p.started = false; + _p.stopped = true; // to be removed from animation queues + + return this; + }, + + rewind: function(){ + return this.progress( 0 ); + }, + + fastforward: function(){ + return this.progress( 1 ); + }, + + time: function( t ){ + var _p = this._private; + + if( t === undefined ){ + return _p.progress * _p.duration; + } else { + return this.progress( t / _p.duration ); + } + }, + + progress: function( p ){ + var _p = this._private; + var wasPlaying = _p.playing; + + if( p === undefined ){ + return _p.progress; + } else { + if( wasPlaying ){ + this.pause(); + } + + _p.progress = p; + _p.started = false; + + if( wasPlaying ){ + this.play(); + } + } + + return this; + }, + + completed: function(){ + return this._private.progress === 1; + }, + + reverse: function(){ + var _p = this._private; + var wasPlaying = _p.playing; + + if( wasPlaying ){ + this.pause(); + } + + _p.progress = 1 - _p.progress; + _p.started = false; + + var swap = function( a, b ){ + var _pa = _p[ a ]; + + _p[ a ] = _p[ b ]; + _p[ b ] = _pa; + }; + + swap( 'zoom', 'startZoom' ); + swap( 'pan', 'startPan' ); + swap( 'position', 'startPosition' ); + + // swap styles + for( var i = 0; i < _p.style.length; i++ ){ + var prop = _p.style[ i ]; + var name = prop.name; + var startStyleProp = _p.startStyle[ name ]; + + _p.startStyle[ name ] = prop; + _p.style[ i ] = startStyleProp; + } + + if( wasPlaying ){ + this.play(); + } + + return this; + }, + + promise: function( type ){ + var _p = this._private; + + var arr; + + switch( type ){ + case 'frame': + arr = _p.frames; + break; + default: + case 'complete': + case 'completed': + arr = _p.completes; + } + + return new Promise( function( resolve, reject ){ + arr.push( function(){ + resolve(); + } ); + } ); + } + +} ); + +anifn.complete = anifn.completed; + +module.exports = Animation; + +},{"./is":83,"./promise":86,"./util":100}],3:[function(_dereq_,module,exports){ +'use strict'; + +var is = _dereq_( '../../is' ); + +var elesfn = ({ + + // Implemented from pseudocode from wikipedia + aStar: function( options ){ + var eles = this; + + options = options || {}; + + // Reconstructs the path from Start to End, acumulating the result in pathAcum + var reconstructPath = function( start, end, cameFromMap, pathAcum ){ + // Base case + if( start == end ){ + pathAcum.push( cy.getElementById( end ) ); + return pathAcum; + } + + if( end in cameFromMap ){ + // We know which node is before the last one + var previous = cameFromMap[ end ]; + var previousEdge = cameFromEdge[ end ]; + + pathAcum.push( cy.getElementById( end ) ); + pathAcum.push( cy.getElementById( previousEdge ) ); + + + return reconstructPath( start, + previous, + cameFromMap, + pathAcum ); + } + + // We should not reach here! + return undefined; + }; + + // Returns the index of the element in openSet which has minimum fScore + var findMin = function( openSet, fScore ){ + if( openSet.length === 0 ){ + // Should never be the case + return undefined; + } + var minPos = 0; + var tempScore = fScore[ openSet[0] ]; + for( var i = 1; i < openSet.length; i++ ){ + var s = fScore[ openSet[ i ] ]; + if( s < tempScore ){ + tempScore = s; + minPos = i; + } + } + return minPos; + }; + + var cy = this._private.cy; + + // root - mandatory! + if( options != null && options.root != null ){ + var source = is.string( options.root ) ? + // use it as a selector, e.g. "#rootID + this.filter( options.root )[0] : + options.root[0]; + } else { + return undefined; + } + + // goal - mandatory! + if( options.goal != null ){ + var target = is.string( options.goal ) ? + // use it as a selector, e.g. "#goalID + this.filter( options.goal )[0] : + options.goal[0]; + } else { + return undefined; + } + + // Heuristic function - optional + if( options.heuristic != null && is.fn( options.heuristic ) ){ + var heuristic = options.heuristic; + } else { + var heuristic = function(){ return 0; }; // use constant if unspecified + } + + // Weight function - optional + if( options.weight != null && is.fn( options.weight ) ){ + var weightFn = options.weight; + } else { + // If not specified, assume each edge has equal weight (1) + var weightFn = function( e ){return 1;}; + } + + // directed - optional + if( options.directed != null ){ + var directed = options.directed; + } else { + var directed = false; + } + + var closedSet = []; + var openSet = [ source.id() ]; + var cameFrom = {}; + var cameFromEdge = {}; + var gScore = {}; + var fScore = {}; + + gScore[ source.id() ] = 0; + fScore[ source.id() ] = heuristic( source ); + + var edges = this.edges().stdFilter( function( e ){ return !e.isLoop(); } ); + var nodes = this.nodes(); + + // Counter + var steps = 0; + + // Main loop + while( openSet.length > 0 ){ + var minPos = findMin( openSet, fScore ); + var cMin = cy.getElementById( openSet[ minPos ] ); + steps++; + + // If we've found our goal, then we are done + if( cMin.id() == target.id() ){ + var rPath = reconstructPath( source.id(), target.id(), cameFrom, [] ); + rPath.reverse(); + return { + found: true, + distance: gScore[ cMin.id() ], + path: eles.spawn( rPath ), + steps: steps + }; + } + + // Add cMin to processed nodes + closedSet.push( cMin.id() ); + // Remove cMin from boundary nodes + openSet.splice( minPos, 1 ); + + // Update scores for neighbors of cMin + // Take into account if graph is directed or not + var vwEdges = cMin.connectedEdges(); + if( directed ){ vwEdges = vwEdges.stdFilter( function( ele ){ return ele.data( 'source' ) === cMin.id(); } ); } + vwEdges = vwEdges.intersect( edges ); + + for( var i = 0; i < vwEdges.length; i++ ){ + var e = vwEdges[ i ]; + var w = e.connectedNodes().stdFilter( function( n ){ return n.id() !== cMin.id(); } ).intersect( nodes ); + + // if node is in closedSet, ignore it + if( closedSet.indexOf( w.id() ) != -1 ){ + continue; + } + + // New tentative score for node w + var tempScore = gScore[ cMin.id() ] + weightFn.apply( e, [ e ] ); + + // Update gScore for node w if: + // w not present in openSet + // OR + // tentative gScore is less than previous value + + // w not in openSet + if( openSet.indexOf( w.id() ) == -1 ){ + gScore[ w.id() ] = tempScore; + fScore[ w.id() ] = tempScore + heuristic( w ); + openSet.push( w.id() ); // Add node to openSet + cameFrom[ w.id() ] = cMin.id(); + cameFromEdge[ w.id() ] = e.id(); + continue; + } + // w already in openSet, but with greater gScore + if( tempScore < gScore[ w.id() ] ){ + gScore[ w.id() ] = tempScore; + fScore[ w.id() ] = tempScore + heuristic( w ); + cameFrom[ w.id() ] = cMin.id(); + } + + } // End of neighbors update + + } // End of main loop + + // If we've reached here, then we've not reached our goal + return { + found: false, + distance: undefined, + path: undefined, + steps: steps + }; + } + +}); // elesfn + + +module.exports = elesfn; + +},{"../../is":83}],4:[function(_dereq_,module,exports){ +'use strict'; + +var is = _dereq_( '../../is' ); +var util = _dereq_( '../../util' ); + +var elesfn = ({ + + // Implemented from pseudocode from wikipedia + bellmanFord: function( options ){ + var eles = this; + + options = options || {}; + + // Weight function - optional + if( options.weight != null && is.fn( options.weight ) ){ + var weightFn = options.weight; + } else { + // If not specified, assume each edge has equal weight (1) + var weightFn = function( e ){return 1;}; + } + + // directed - optional + if( options.directed != null ){ + var directed = options.directed; + } else { + var directed = false; + } + + // root - mandatory! + if( options.root != null ){ + if( is.string( options.root ) ){ + // use it as a selector, e.g. "#rootID + var source = this.filter( options.root )[0]; + } else { + var source = options.root[0]; + } + } else { + return undefined; + } + + var cy = this._private.cy; + var edges = this.edges().stdFilter( function( e ){ return !e.isLoop(); } ); + var nodes = this.nodes(); + var numNodes = nodes.length; + + // mapping: node id -> position in nodes array + var id2position = {}; + for( var i = 0; i < numNodes; i++ ){ + id2position[ nodes[ i ].id() ] = i; + } + + // Initializations + var cost = []; + var predecessor = []; + var predEdge = []; + + for( var i = 0; i < numNodes; i++ ){ + if( nodes[ i ].id() === source.id() ){ + cost[ i ] = 0; + } else { + cost[ i ] = Infinity; + } + predecessor[ i ] = undefined; + } + + // Edges relaxation + var flag = false; + for( var i = 1; i < numNodes; i++ ){ + flag = false; + for( var e = 0; e < edges.length; e++ ){ + var sourceIndex = id2position[ edges[ e ].source().id() ]; + var targetIndex = id2position[ edges[ e ].target().id() ]; + var weight = weightFn.apply( edges[ e ], [ edges[ e ] ] ); + + var temp = cost[ sourceIndex ] + weight; + if( temp < cost[ targetIndex ] ){ + cost[ targetIndex ] = temp; + predecessor[ targetIndex ] = sourceIndex; + predEdge[ targetIndex ] = edges[ e ]; + flag = true; + } + + // If undirected graph, we need to take into account the 'reverse' edge + if( !directed ){ + var temp = cost[ targetIndex ] + weight; + if( temp < cost[ sourceIndex ] ){ + cost[ sourceIndex ] = temp; + predecessor[ sourceIndex ] = targetIndex; + predEdge[ sourceIndex ] = edges[ e ]; + flag = true; + } + } + } + + if( !flag ){ + break; + } + } + + if( flag ){ + // Check for negative weight cycles + for( var e = 0; e < edges.length; e++ ){ + var sourceIndex = id2position[ edges[ e ].source().id() ]; + var targetIndex = id2position[ edges[ e ].target().id() ]; + var weight = weightFn.apply( edges[ e ], [ edges[ e ] ] ); + + if( cost[ sourceIndex ] + weight < cost[ targetIndex ] ){ + util.error( 'Graph contains a negative weight cycle for Bellman-Ford' ); + return { pathTo: undefined, + distanceTo: undefined, + hasNegativeWeightCycle: true}; + } + } + } + + // Build result object + var position2id = []; + for( var i = 0; i < numNodes; i++ ){ + position2id.push( nodes[ i ].id() ); + } + + + var res = { + distanceTo: function( to ){ + if( is.string( to ) ){ + // to is a selector string + var toId = (cy.filter( to )[0]).id(); + } else { + // to is a node + var toId = to.id(); + } + + return cost[ id2position[ toId ] ]; + }, + + pathTo: function( to ){ + + var reconstructPathAux = function( predecessor, fromPos, toPos, position2id, acumPath, predEdge ){ + for( ;; ){ + // Add toId to path + acumPath.push( cy.getElementById( position2id[ toPos ] ) ); + acumPath.push( predEdge[ toPos ] ); + + if( fromPos === toPos ){ + // reached starting node + return acumPath; + } + + // If no path exists, discart acumulated path and return undefined + var predPos = predecessor[ toPos ]; + if( typeof predPos === 'undefined' ){ + return undefined; + } + + toPos = predPos; + } + + }; + + if( is.string( to ) ){ + // to is a selector string + var toId = (cy.filter( to )[0]).id(); + } else { + // to is a node + var toId = to.id(); + } + var path = []; + + // This returns a reversed path + var res = reconstructPathAux( predecessor, + id2position[ source.id() ], + id2position[ toId ], + position2id, + path, + predEdge ); + + // Get it in the correct order and return it + if( res != null ){ + res.reverse(); + } + + return eles.spawn( res ); + }, + + hasNegativeWeightCycle: false + }; + + return res; + + } // bellmanFord + +}); // elesfn + +module.exports = elesfn; + +},{"../../is":83,"../../util":100}],5:[function(_dereq_,module,exports){ +'use strict'; + +var is = _dereq_( '../../is' ); +var Heap = _dereq_( '../../heap' ); + +var elesfn = ({ + + // Implemented from the algorithm in the paper "On Variants of Shortest-Path Betweenness Centrality and their Generic Computation" by Ulrik Brandes + betweennessCentrality: function( options ){ + options = options || {}; + + // Weight - optional + var weighted, weightFn; + if( is.fn( options.weight ) ){ + weightFn = options.weight; + weighted = true; + } else { + weighted = false; + } + + // Directed - default false + var directed = options.directed != null ? options.directed : false; + + var cy = this._private.cy; + + // starting + var V = this.nodes(); + var A = {}; + var _C = {}; + var max; + var C = { + set: function( key, val ){ + _C[ key ] = val; + + if( val > max ){ max = val; } + }, + + get: function( key ){ return _C[ key ]; } + }; + + // A contains the neighborhoods of every node + for( var i = 0; i < V.length; i++ ){ + var v = V[ i ]; + var vid = v.id(); + + if( directed ){ + A[ vid ] = v.outgoers().nodes(); // get outgoers of every node + } else { + A[ vid ] = v.openNeighborhood().nodes(); // get neighbors of every node + } + + C.set( vid, 0 ); + } + + for( var s = 0; s < V.length; s++ ){ + var sid = V[s].id(); + var S = []; // stack + var P = {}; + var g = {}; + var d = {}; + var Q = new Heap(function( a, b ){ + return d[a] - d[b]; + }); // queue + + // init dictionaries + for( var i = 0; i < V.length; i++ ){ + var vid = V[ i ].id(); + + P[ vid ] = []; + g[ vid ] = 0; + d[ vid ] = Infinity; + } + + g[ sid ] = 1; // sigma + d[ sid ] = 0; // distance to s + + Q.push( sid ); + + while( !Q.empty() ){ + var v = Q.pop(); + + S.push( v ); + + if( weighted ){ + for( var j = 0; j < A[v].length; j++ ){ + var w = A[v][j]; + var vEle = cy.getElementById( v ); + + var edge; + if( vEle.edgesTo( w ).length > 0 ){ + edge = vEle.edgesTo( w )[0]; + } else { + edge = w.edgesTo( vEle )[0]; + } + + var edgeWeight = weightFn.apply( edge, [ edge ] ); + + w = w.id(); + + if( d[w] > d[v] + edgeWeight ){ + d[w] = d[v] + edgeWeight; + + if( Q.nodes.indexOf( w ) < 0 ){ //if w is not in Q + Q.push( w ); + } else { // update position if w is in Q + Q.updateItem( w ); + } + + g[w] = 0; + P[w] = []; + } + + if( d[w] == d[v] + edgeWeight ){ + g[w] = g[w] + g[v]; + P[w].push( v ); + } + } + } else { + for( var j = 0; j < A[v].length; j++ ){ + var w = A[v][j].id(); + + if( d[w] == Infinity ){ + Q.push( w ); + + d[w] = d[v] + 1; + } + + if( d[w] == d[v] + 1 ){ + g[w] = g[w] + g[v]; + P[w].push( v ); + } + } + } + } + + var e = {}; + for( var i = 0; i < V.length; i++ ){ + e[ V[ i ].id() ] = 0; + } + + while( S.length > 0 ){ + var w = S.pop(); + + for( var j = 0; j < P[w].length; j++ ){ + var v = P[w][j]; + + e[v] = e[v] + (g[v] / g[w]) * (1 + e[w]); + + if( w != V[s].id() ){ + C.set( w, C.get( w ) + e[w] ); + } + } + } + } + + var ret = { + betweenness: function( node ){ + if( is.string( node ) ){ + var node = cy.filter( node ).id(); + } else { + var node = node.id(); + } + + return C.get( node ); + }, + + betweennessNormalized: function( node ){ + if( is.string( node ) ){ + var node = cy.filter( node ).id(); + } else { + var node = node.id(); + } + + return C.get( node ) / max; + } + }; + + // alias + ret.betweennessNormalised = ret.betweennessNormalized; + + return ret; + } // betweennessCentrality + +}); // elesfn + +// nice, short mathemathical alias +elesfn.bc = elesfn.betweennessCentrality; + +module.exports = elesfn; + +},{"../../heap":81,"../../is":83}],6:[function(_dereq_,module,exports){ +'use strict'; + +var is = _dereq_( '../../is' ); + +var defineSearch = function( params ){ + params = { + bfs: params.bfs || !params.dfs, + dfs: params.dfs || !params.bfs + }; + + // from pseudocode on wikipedia + return function searchFn( roots, fn, directed ){ + var options; + var std; + var thisArg; + if( is.plainObject( roots ) && !is.elementOrCollection( roots ) ){ + options = roots; + roots = options.roots || options.root; + fn = options.visit; + directed = options.directed; + std = options.std; + thisArg = options.thisArg; + } + + directed = arguments.length === 2 && !is.fn( fn ) ? fn : directed; + fn = is.fn( fn ) ? fn : function(){}; + + var cy = this._private.cy; + var v = roots = is.string( roots ) ? this.filter( roots ) : roots; + var Q = []; + var connectedNodes = []; + var connectedBy = {}; + var id2depth = {}; + var V = {}; + var j = 0; + var found; + var nodes = this.nodes(); + var edges = this.edges(); + + // enqueue v + for( var i = 0; i < v.length; i++ ){ + if( v[ i ].isNode() ){ + Q.unshift( v[ i ] ); + + if( params.bfs ){ + V[ v[ i ].id() ] = true; + + connectedNodes.push( v[ i ] ); + } + + id2depth[ v[ i ].id() ] = 0; + } + } + + while( Q.length !== 0 ){ + var v = params.bfs ? Q.shift() : Q.pop(); + + if( params.dfs ){ + if( V[ v.id() ] ){ continue; } + + V[ v.id() ] = true; + + connectedNodes.push( v ); + } + + var depth = id2depth[ v.id() ]; + var prevEdge = connectedBy[ v.id() ]; + var prevNode = prevEdge == null ? undefined : prevEdge.connectedNodes().not( v )[0]; + var ret; + + if( std ){ + ret = fn.call( thisArg, v, prevEdge, prevNode, j++, depth ); + } else { + ret = fn.call( v, j++, depth, v, prevEdge, prevNode ); + } + + if( ret === true ){ + found = v; + break; + } + + if( ret === false ){ + break; + } + + var vwEdges = v.connectedEdges( directed ? function(){ return this.data( 'source' ) === v.id(); } : undefined ).intersect( edges ); + for( var i = 0; i < vwEdges.length; i++ ){ + var e = vwEdges[ i ]; + var w = e.connectedNodes( function(){ return this.id() !== v.id(); } ).intersect( nodes ); + + if( w.length !== 0 && !V[ w.id() ] ){ + w = w[0]; + + Q.push( w ); + + if( params.bfs ){ + V[ w.id() ] = true; + + connectedNodes.push( w ); + } + + connectedBy[ w.id() ] = e; + + id2depth[ w.id() ] = id2depth[ v.id() ] + 1; + } + } + + } + + var connectedEles = []; + + for( var i = 0; i < connectedNodes.length; i++ ){ + var node = connectedNodes[ i ]; + var edge = connectedBy[ node.id() ]; + + if( edge ){ + connectedEles.push( edge ); + } + + connectedEles.push( node ); + } + + return { + path: cy.collection( connectedEles, { unique: true } ), + found: cy.collection( found ) + }; + }; +}; + +// search, spanning trees, etc +var elesfn = ({ + breadthFirstSearch: defineSearch( { bfs: true } ), + depthFirstSearch: defineSearch( { dfs: true } ) +}); + +// nice, short mathemathical alias +elesfn.bfs = elesfn.breadthFirstSearch; +elesfn.dfs = elesfn.depthFirstSearch; + +module.exports = elesfn; + +},{"../../is":83}],7:[function(_dereq_,module,exports){ +'use strict'; + +var is = _dereq_( '../../is' ); + +var elesfn = ({ + + closenessCentralityNormalized: function( options ){ + options = options || {}; + + var cy = this.cy(); + + var harmonic = options.harmonic; + if( harmonic === undefined ){ + harmonic = true; + } + + var closenesses = {}; + var maxCloseness = 0; + var nodes = this.nodes(); + var fw = this.floydWarshall( { weight: options.weight, directed: options.directed } ); + + // Compute closeness for every node and find the maximum closeness + for( var i = 0; i < nodes.length; i++ ){ + var currCloseness = 0; + for( var j = 0; j < nodes.length; j++ ){ + if( i != j ){ + var d = fw.distance( nodes[ i ], nodes[ j ] ); + + if( harmonic ){ + currCloseness += 1 / d; + } else { + currCloseness += d; + } + } + } + + if( !harmonic ){ + currCloseness = 1 / currCloseness; + } + + if( maxCloseness < currCloseness ){ + maxCloseness = currCloseness; + } + + closenesses[ nodes[ i ].id() ] = currCloseness; + } + + return { + closeness: function( node ){ + if( is.string( node ) ){ + // from is a selector string + var node = (cy.filter( node )[0]).id(); + } else { + // from is a node + var node = node.id(); + } + + return closenesses[ node ] / maxCloseness; + } + }; + }, + + // Implemented from pseudocode from wikipedia + closenessCentrality: function( options ){ + options = options || {}; + + // root - mandatory! + if( options.root != null ){ + if( is.string( options.root ) ){ + // use it as a selector, e.g. "#rootID + var root = this.filter( options.root )[0]; + } else { + var root = options.root[0]; + } + } else { + return undefined; + } + + // weight - optional + if( options.weight != null && is.fn( options.weight ) ){ + var weight = options.weight; + } else { + var weight = function(){return 1;}; + } + + // directed - optional + if( options.directed != null && is.bool( options.directed ) ){ + var directed = options.directed; + } else { + var directed = false; + } + + var harmonic = options.harmonic; + if( harmonic === undefined ){ + harmonic = true; + } + + // we need distance from this node to every other node + var dijkstra = this.dijkstra( { + root: root, + weight: weight, + directed: directed + } ); + var totalDistance = 0; + + var nodes = this.nodes(); + for( var i = 0; i < nodes.length; i++ ){ + if( nodes[ i ].id() != root.id() ){ + var d = dijkstra.distanceTo( nodes[ i ] ); + + if( harmonic ){ + totalDistance += 1 / d; + } else { + totalDistance += d; + } + } + } + + return harmonic ? totalDistance : 1 / totalDistance; + } // closenessCentrality + +}); // elesfn + +// nice, short mathemathical alias +elesfn.cc = elesfn.closenessCentrality; +elesfn.ccn = elesfn.closenessCentralityNormalised = elesfn.closenessCentralityNormalized; + +module.exports = elesfn; + +},{"../../is":83}],8:[function(_dereq_,module,exports){ +'use strict'; + +var is = _dereq_( '../../is' ); +var util = _dereq_( '../../util' ); + +var elesfn = ({ + + degreeCentralityNormalized: function( options ){ + options = options || {}; + + var cy = this.cy(); + + // directed - optional + if( options.directed != null ){ + var directed = options.directed; + } else { + var directed = false; + } + + var nodes = this.nodes(); + var numNodes = nodes.length; + + if( !directed ){ + var degrees = {}; + var maxDegree = 0; + + for( var i = 0; i < numNodes; i++ ){ + var node = nodes[ i ]; + // add current node to the current options object and call degreeCentrality + var currDegree = this.degreeCentrality( util.extend( {}, options, {root: node} ) ); + if( maxDegree < currDegree.degree ) + maxDegree = currDegree.degree; + + degrees[ node.id() ] = currDegree.degree; + } + + return { + degree: function( node ){ + if( is.string( node ) ){ + // from is a selector string + var node = (cy.filter( node )[0]).id(); + } else { + // from is a node + var node = node.id(); + } + + return degrees[ node ] / maxDegree; + } + }; + } else { + var indegrees = {}; + var outdegrees = {}; + var maxIndegree = 0; + var maxOutdegree = 0; + + for( var i = 0; i < numNodes; i++ ){ + var node = nodes[ i ]; + // add current node to the current options object and call degreeCentrality + var currDegree = this.degreeCentrality( util.extend( {}, options, {root: node} ) ); + + if( maxIndegree < currDegree.indegree ) + maxIndegree = currDegree.indegree; + + if( maxOutdegree < currDegree.outdegree ) + maxOutdegree = currDegree.outdegree; + + indegrees[ node.id() ] = currDegree.indegree; + outdegrees[ node.id() ] = currDegree.outdegree; + } + + return { + indegree: function( node ){ + if( is.string( node ) ){ + // from is a selector string + var node = (cy.filter( node )[0]).id(); + } else { + // from is a node + var node = node.id(); + } + + return indegrees[ node ] / maxIndegree; + }, + outdegree: function( node ){ + if( is.string( node ) ){ + // from is a selector string + var node = (cy.filter( node )[0]).id(); + } else { + // from is a node + var node = node.id(); + } + + return outdegrees[ node ] / maxOutdegree; + } + + }; + } + + }, // degreeCentralityNormalized + + // Implemented from the algorithm in Opsahl's paper + // "Node centrality in weighted networks: Generalizing degree and shortest paths" + // check the heading 2 "Degree" + degreeCentrality: function( options ){ + options = options || {}; + + var callingEles = this; + + // root - mandatory! + if( options != null && options.root != null ){ + var root = is.string( options.root ) ? this.filter( options.root )[0] : options.root[0]; + } else { + return undefined; + } + + // weight - optional + if( options.weight != null && is.fn( options.weight ) ){ + var weightFn = options.weight; + } else { + // If not specified, assume each edge has equal weight (1) + var weightFn = function( e ){ + return 1; + }; + } + + // directed - optional + if( options.directed != null ){ + var directed = options.directed; + } else { + var directed = false; + } + + // alpha - optional + if( options.alpha != null && is.number( options.alpha ) ){ + var alpha = options.alpha; + } else { + alpha = 0; + } + + + if( !directed ){ + var connEdges = root.connectedEdges().intersection( callingEles ); + var k = connEdges.length; + var s = 0; + + // Now, sum edge weights + for( var i = 0; i < connEdges.length; i++ ){ + var edge = connEdges[ i ]; + s += weightFn.apply( edge, [ edge ] ); + } + + return { + degree: Math.pow( k, 1 - alpha ) * Math.pow( s, alpha ) + }; + } else { + var incoming = root.connectedEdges( 'edge[target = "' + root.id() + '"]' ).intersection( callingEles ); + var outgoing = root.connectedEdges( 'edge[source = "' + root.id() + '"]' ).intersection( callingEles ); + var k_in = incoming.length; + var k_out = outgoing.length; + var s_in = 0; + var s_out = 0; + + // Now, sum incoming edge weights + for( var i = 0; i < incoming.length; i++ ){ + var edge = incoming[ i ]; + s_in += weightFn.apply( edge, [ edge ] ); + } + + // Now, sum outgoing edge weights + for( var i = 0; i < outgoing.length; i++ ){ + var edge = outgoing[ i ]; + s_out += weightFn.apply( edge, [ edge ] ); + } + + return { + indegree: Math.pow( k_in, 1 - alpha ) * Math.pow( s_in, alpha ), + outdegree: Math.pow( k_out, 1 - alpha ) * Math.pow( s_out, alpha ) + }; + } + } // degreeCentrality + +}); // elesfn + +// nice, short mathemathical alias +elesfn.dc = elesfn.degreeCentrality; +elesfn.dcn = elesfn.degreeCentralityNormalised = elesfn.degreeCentralityNormalized; + +module.exports = elesfn; + +},{"../../is":83,"../../util":100}],9:[function(_dereq_,module,exports){ +'use strict'; + +var is = _dereq_( '../../is' ); +var Heap = _dereq_( '../../heap' ); + +var elesfn = ({ + + dijkstra: function( root, weightFn, directed ){ + var options; + if( is.plainObject( root ) && !is.elementOrCollection( root ) ){ + options = root; + root = options.root; + weightFn = options.weight; + directed = options.directed; + } + + var cy = this._private.cy; + weightFn = is.fn( weightFn ) ? weightFn : function(){ return 1; }; // if not specified, assume each edge has equal weight (1) + + var source = is.string( root ) ? this.filter( root )[0] : root[0]; + var dist = {}; + var prev = {}; + var knownDist = {}; + + var edges = this.edges().filter( function(){ return !this.isLoop(); } ); + var nodes = this.nodes(); + + var getDist = function( node ){ + return dist[ node.id() ]; + }; + + var setDist = function( node, d ){ + dist[ node.id() ] = d; + + Q.updateItem( node ); + }; + + var Q = new Heap( function( a, b ){ + return getDist( a ) - getDist( b ); + } ); + + for( var i = 0; i < nodes.length; i++ ){ + var node = nodes[ i ]; + + dist[ node.id() ] = node.same( source ) ? 0 : Infinity; + Q.push( node ); + } + + var distBetween = function( u, v ){ + var uvs = ( directed ? u.edgesTo( v ) : u.edgesWith( v ) ).intersect( edges ); + var smallestDistance = Infinity; + var smallestEdge; + + for( var i = 0; i < uvs.length; i++ ){ + var edge = uvs[ i ]; + var weight = weightFn.apply( edge, [ edge ] ); + + if( weight < smallestDistance || !smallestEdge ){ + smallestDistance = weight; + smallestEdge = edge; + } + } + + return { + edge: smallestEdge, + dist: smallestDistance + }; + }; + + while( Q.size() > 0 ){ + var u = Q.pop(); + var smalletsDist = getDist( u ); + var uid = u.id(); + + knownDist[ uid ] = smalletsDist; + + if( smalletsDist === Math.Infinite ){ + break; + } + + var neighbors = u.neighborhood().intersect( nodes ); + for( var i = 0; i < neighbors.length; i++ ){ + var v = neighbors[ i ]; + var vid = v.id(); + var vDist = distBetween( u, v ); + + var alt = smalletsDist + vDist.dist; + + if( alt < getDist( v ) ){ + setDist( v, alt ); + + prev[ vid ] = { + node: u, + edge: vDist.edge + }; + } + } // for + } // while + + return { + distanceTo: function( node ){ + var target = is.string( node ) ? nodes.filter( node )[0] : node[0]; + + return knownDist[ target.id() ]; + }, + + pathTo: function( node ){ + var target = is.string( node ) ? nodes.filter( node )[0] : node[0]; + var S = []; + var u = target; + + if( target.length > 0 ){ + S.unshift( target ); + + while( prev[ u.id() ] ){ + var p = prev[ u.id() ]; + + S.unshift( p.edge ); + S.unshift( p.node ); + + u = p.node; + } + } + + return cy.collection( S ); + } + }; + } +}); + +module.exports = elesfn; + +},{"../../heap":81,"../../is":83}],10:[function(_dereq_,module,exports){ +'use strict'; + +var is = _dereq_( '../../is' ); + +var elesfn = ({ + + // Implemented from pseudocode from wikipedia + floydWarshall: function( options ){ + options = options || {}; + + var cy = this.cy(); + + // Weight function - optional + if( options.weight != null && is.fn( options.weight ) ){ + var weightFn = options.weight; + } else { + // If not specified, assume each edge has equal weight (1) + var weightFn = function( e ){return 1;}; + } + + // directed - optional + if( options.directed != null ){ + var directed = options.directed; + } else { + var directed = false; + } + + var edges = this.edges().stdFilter( function( e ){ return !e.isLoop(); } ); + var nodes = this.nodes(); + var numNodes = nodes.length; + + // mapping: node id -> position in nodes array + var id2position = {}; + for( var i = 0; i < numNodes; i++ ){ + id2position[ nodes[ i ].id() ] = i; + } + + // Initialize distance matrix + var dist = []; + for( var i = 0; i < numNodes; i++ ){ + var newRow = new Array( numNodes ); + for( var j = 0; j < numNodes; j++ ){ + if( i == j ){ + newRow[ j ] = 0; + } else { + newRow[ j ] = Infinity; + } + } + dist.push( newRow ); + } + + // Initialize matrix used for path reconstruction + // Initialize distance matrix + var next = []; + var edgeNext = []; + + var initMatrix = function( next ){ + for( var i = 0; i < numNodes; i++ ){ + var newRow = new Array( numNodes ); + for( var j = 0; j < numNodes; j++ ){ + newRow[ j ] = undefined; + } + next.push( newRow ); + } + }; + + initMatrix( next ); + initMatrix( edgeNext ); + + // Process edges + for( var i = 0; i < edges.length ; i++ ){ + var sourceIndex = id2position[ edges[ i ].source().id() ]; + var targetIndex = id2position[ edges[ i ].target().id() ]; + var weight = weightFn.apply( edges[ i ], [ edges[ i ] ] ); + + // Check if already process another edge between same 2 nodes + if( dist[ sourceIndex ][ targetIndex ] > weight ){ + dist[ sourceIndex ][ targetIndex ] = weight; + next[ sourceIndex ][ targetIndex ] = targetIndex; + edgeNext[ sourceIndex ][ targetIndex ] = edges[ i ]; + } + } + + // If undirected graph, process 'reversed' edges + if( !directed ){ + for( var i = 0; i < edges.length ; i++ ){ + var sourceIndex = id2position[ edges[ i ].target().id() ]; + var targetIndex = id2position[ edges[ i ].source().id() ]; + var weight = weightFn.apply( edges[ i ], [ edges[ i ] ] ); + + // Check if already process another edge between same 2 nodes + if( dist[ sourceIndex ][ targetIndex ] > weight ){ + dist[ sourceIndex ][ targetIndex ] = weight; + next[ sourceIndex ][ targetIndex ] = targetIndex; + edgeNext[ sourceIndex ][ targetIndex ] = edges[ i ]; + } + } + } + + // Main loop + for( var k = 0; k < numNodes; k++ ){ + for( var i = 0; i < numNodes; i++ ){ + for( var j = 0; j < numNodes; j++ ){ + if( dist[ i ][ k ] + dist[ k ][ j ] < dist[ i ][ j ] ){ + dist[ i ][ j ] = dist[ i ][ k ] + dist[ k ][ j ]; + next[ i ][ j ] = next[ i ][ k ]; + } + } + } + } + + // Build result object + var position2id = []; + for( var i = 0; i < numNodes; i++ ){ + position2id.push( nodes[ i ].id() ); + } + + var res = { + distance: function( from, to ){ + if( is.string( from ) ){ + // from is a selector string + var fromId = (cy.filter( from )[0]).id(); + } else { + // from is a node + var fromId = from.id(); + } + + if( is.string( to ) ){ + // to is a selector string + var toId = (cy.filter( to )[0]).id(); + } else { + // to is a node + var toId = to.id(); + } + + return dist[ id2position[ fromId ] ][ id2position[ toId ] ]; + }, + + path: function( from, to ){ + var reconstructPathAux = function( from, to, next, position2id, edgeNext ){ + if( from === to ){ + return cy.getElementById( position2id[ from ] ); + } + if( next[ from ][ to ] === undefined ){ + return undefined; + } + + var path = [ cy.getElementById( position2id[ from ] ) ]; + var prev = from; + while( from !== to ){ + prev = from; + from = next[ from ][ to ]; + + var edge = edgeNext[ prev ][ from ]; + path.push( edge ); + + path.push( cy.getElementById( position2id[ from ] ) ); + } + return path; + }; + + if( is.string( from ) ){ + // from is a selector string + var fromId = (cy.filter( from )[0]).id(); + } else { + // from is a node + var fromId = from.id(); + } + + if( is.string( to ) ){ + // to is a selector string + var toId = (cy.filter( to )[0]).id(); + } else { + // to is a node + var toId = to.id(); + } + + var pathArr = reconstructPathAux( id2position[ fromId ], + id2position[ toId ], + next, + position2id, + edgeNext ); + + return cy.collection( pathArr ); + } + }; + + return res; + + } // floydWarshall + +}); // elesfn + +module.exports = elesfn; + +},{"../../is":83}],11:[function(_dereq_,module,exports){ +'use strict'; + +var util = _dereq_( '../../util' ); + +var elesfn = {}; + +[ + _dereq_( './bfs-dfs' ), + _dereq_( './dijkstra' ), + _dereq_( './kruskal' ), + _dereq_( './a-star' ), + _dereq_( './floyd-warshall' ), + _dereq_( './bellman-ford' ), + _dereq_( './kerger-stein' ), + _dereq_( './page-rank' ), + _dereq_( './degree-centrality' ), + _dereq_( './closeness-centrality' ), + _dereq_( './betweenness-centrality' ) +].forEach( function( props ){ + util.extend( elesfn, props ); +} ); + +module.exports = elesfn; + +},{"../../util":100,"./a-star":3,"./bellman-ford":4,"./betweenness-centrality":5,"./bfs-dfs":6,"./closeness-centrality":7,"./degree-centrality":8,"./dijkstra":9,"./floyd-warshall":10,"./kerger-stein":12,"./kruskal":13,"./page-rank":14}],12:[function(_dereq_,module,exports){ +'use strict'; + +var util = _dereq_( '../../util' ); + +var elesfn = ({ + + // Computes the minimum cut of an undirected graph + // Returns the correct answer with high probability + kargerStein: function( options ){ + var eles = this; + + options = options || {}; + + // Function which colapses 2 (meta) nodes into one + // Updates the remaining edge lists + // Receives as a paramater the edge which causes the collapse + var colapse = function( edgeIndex, nodeMap, remainingEdges ){ + var edgeInfo = remainingEdges[ edgeIndex ]; + var sourceIn = edgeInfo[1]; + var targetIn = edgeInfo[2]; + var partition1 = nodeMap[ sourceIn ]; + var partition2 = nodeMap[ targetIn ]; + + // Delete all edges between partition1 and partition2 + var newEdges = remainingEdges.filter( function( edge ){ + if( nodeMap[ edge[1] ] === partition1 && nodeMap[ edge[2] ] === partition2 ){ + return false; + } + if( nodeMap[ edge[1] ] === partition2 && nodeMap[ edge[2] ] === partition1 ){ + return false; + } + return true; + } ); + + // All edges pointing to partition2 should now point to partition1 + for( var i = 0; i < newEdges.length; i++ ){ + var edge = newEdges[ i ]; + if( edge[1] === partition2 ){ // Check source + newEdges[ i ] = edge.slice( 0 ); + newEdges[ i ][1] = partition1; + } else if( edge[2] === partition2 ){ // Check target + newEdges[ i ] = edge.slice( 0 ); + newEdges[ i ][2] = partition1; + } + } + + // Move all nodes from partition2 to partition1 + for( var i = 0; i < nodeMap.length; i++ ){ + if( nodeMap[ i ] === partition2 ){ + nodeMap[ i ] = partition1; + } + } + + return newEdges; + }; + + + // Contracts a graph until we reach a certain number of meta nodes + var contractUntil = function( metaNodeMap, + remainingEdges, + size, + sizeLimit ){ + // Stop condition + if( size <= sizeLimit ){ + return remainingEdges; + } + + // Choose an edge randomly + var edgeIndex = Math.floor( (Math.random() * remainingEdges.length) ); + + // Colapse graph based on edge + var newEdges = colapse( edgeIndex, metaNodeMap, remainingEdges ); + + return contractUntil( metaNodeMap, + newEdges, + size - 1, + sizeLimit ); + }; + + var cy = this._private.cy; + var edges = this.edges().stdFilter( function( e ){ return !e.isLoop(); } ); + var nodes = this.nodes(); + var numNodes = nodes.length; + var numEdges = edges.length; + var numIter = Math.ceil( Math.pow( Math.log( numNodes ) / Math.LN2, 2 ) ); + var stopSize = Math.floor( numNodes / Math.sqrt( 2 ) ); + + if( numNodes < 2 ){ + util.error( 'At least 2 nodes are required for Karger-Stein algorithm' ); + return undefined; + } + + // Create numerical identifiers for each node + // mapping: node id -> position in nodes array + // for reverse mapping, simply use nodes array + var id2position = {}; + for( var i = 0; i < numNodes; i++ ){ + id2position[ nodes[ i ].id() ] = i; + } + + // Now store edge destination as indexes + // Format for each edge (edge index, source node index, target node index) + var edgeIndexes = []; + for( var i = 0; i < numEdges; i++ ){ + var e = edges[ i ]; + edgeIndexes.push( [ i, id2position[ e.source().id() ], id2position[ e.target().id() ] ] ); + } + + // We will store the best cut found here + var minCutSize = Infinity; + var minCut; + + // Initial meta node partition + var originalMetaNode = []; + for( var i = 0; i < numNodes; i++ ){ + originalMetaNode.push( i ); + } + + // Main loop + for( var iter = 0; iter <= numIter; iter++ ){ + // Create new meta node partition + var metaNodeMap = originalMetaNode.slice( 0 ); + + // Contract until stop point (stopSize nodes) + var edgesState = contractUntil( metaNodeMap, edgeIndexes, numNodes, stopSize ); + + // Create a copy of the colapsed nodes state + var metaNodeMap2 = metaNodeMap.slice( 0 ); + + // Run 2 iterations starting in the stop state + var res1 = contractUntil( metaNodeMap, edgesState, stopSize, 2 ); + var res2 = contractUntil( metaNodeMap2, edgesState, stopSize, 2 ); + + // Is any of the 2 results the best cut so far? + if( res1.length <= res2.length && res1.length < minCutSize ){ + minCutSize = res1.length; + minCut = [ res1, metaNodeMap ]; + } else if( res2.length <= res1.length && res2.length < minCutSize ){ + minCutSize = res2.length; + minCut = [ res2, metaNodeMap2 ]; + } + } // end of main loop + + + // Construct result + var resEdges = (minCut[0]).map( function( e ){ return edges[ e[0] ]; } ); + var partition1 = []; + var partition2 = []; + + // traverse metaNodeMap for best cut + var witnessNodePartition = minCut[1][0]; + for( var i = 0; i < minCut[1].length; i++ ){ + var partitionId = minCut[1][ i ]; + if( partitionId === witnessNodePartition ){ + partition1.push( nodes[ i ] ); + } else { + partition2.push( nodes[ i ] ); + } + } + + var ret = { + cut: eles.spawn( cy, resEdges ), + partition1: eles.spawn( partition1 ), + partition2: eles.spawn( partition2 ) + }; + + return ret; + } +}); // elesfn + + +module.exports = elesfn; + +},{"../../util":100}],13:[function(_dereq_,module,exports){ +'use strict'; + +var is = _dereq_( '../../is' ); + +// search, spanning trees, etc +var elesfn = ({ + + // kruskal's algorithm (finds min spanning tree, assuming undirected graph) + // implemented from pseudocode from wikipedia + kruskal: function( weightFn ){ + var cy = this.cy(); + + weightFn = is.fn( weightFn ) ? weightFn : function(){ return 1; }; // if not specified, assume each edge has equal weight (1) + + function findSet( ele ){ + for( var i = 0; i < forest.length; i++ ){ + var eles = forest[ i ]; + + if( eles.anySame( ele ) ){ + return { + eles: eles, + index: i + }; + } + } + } + + var A = cy.collection( cy, [] ); + var forest = []; + var nodes = this.nodes(); + + for( var i = 0; i < nodes.length; i++ ){ + forest.push( nodes[ i ].collection() ); + } + + var edges = this.edges(); + var S = edges.toArray().sort( function( a, b ){ + var weightA = weightFn.call( a, a ); + var weightB = weightFn.call( b, b ); + + return weightA - weightB; + } ); + + for( var i = 0; i < S.length; i++ ){ + var edge = S[ i ]; + var u = edge.source()[0]; + var v = edge.target()[0]; + var setU = findSet( u ); + var setV = findSet( v ); + + if( setU.index !== setV.index ){ + A = A.add( edge ); + + // combine forests for u and v + forest[ setU.index ] = setU.eles.add( setV.eles ); + forest.splice( setV.index, 1 ); + } + } + + return nodes.add( A ); + } +}); + +module.exports = elesfn; + +},{"../../is":83}],14:[function(_dereq_,module,exports){ +'use strict'; + +var is = _dereq_( '../../is' ); + +var elesfn = ({ + + pageRank: function( options ){ + options = options || {}; + + var normalizeVector = function( vector ){ + var length = vector.length; + + // First, get sum of all elements + var total = 0; + for( var i = 0; i < length; i++ ){ + total += vector[ i ]; + } + + // Now, divide each by the sum of all elements + for( var i = 0; i < length; i++ ){ + vector[ i ] = vector[ i ] / total; + } + }; + + // dampingFactor - optional + if( options != null && + options.dampingFactor != null ){ + var dampingFactor = options.dampingFactor; + } else { + var dampingFactor = 0.8; // Default damping factor + } + + // desired precision - optional + if( options != null && + options.precision != null ){ + var epsilon = options.precision; + } else { + var epsilon = 0.000001; // Default precision + } + + // Max number of iterations - optional + if( options != null && + options.iterations != null ){ + var numIter = options.iterations; + } else { + var numIter = 200; // Default number of iterations + } + + // Weight function - optional + if( options != null && + options.weight != null && + is.fn( options.weight ) ){ + var weightFn = options.weight; + } else { + // If not specified, assume each edge has equal weight (1) + var weightFn = function( e ){return 1;}; + } + + var cy = this._private.cy; + var edges = this.edges().stdFilter( function( e ){ return !e.isLoop(); } ); + var nodes = this.nodes(); + var numNodes = nodes.length; + var numEdges = edges.length; + + // Create numerical identifiers for each node + // mapping: node id -> position in nodes array + // for reverse mapping, simply use nodes array + var id2position = {}; + for( var i = 0; i < numNodes; i++ ){ + id2position[ nodes[ i ].id() ] = i; + } + + // Construct transposed adjacency matrix + // First lets have a zeroed matrix of the right size + // We'll also keep track of the sum of each column + var matrix = []; + var columnSum = []; + var additionalProb = (1 - dampingFactor) / numNodes; + + // Create null matric + for( var i = 0; i < numNodes; i++ ){ + var newRow = []; + for( var j = 0; j < numNodes; j++ ){ + newRow.push( 0.0 ); + } + matrix.push( newRow ); + columnSum.push( 0.0 ); + } + + // Now, process edges + for( var i = 0; i < numEdges; i++ ){ + var edge = edges[ i ]; + var s = id2position[ edge.source().id() ]; + var t = id2position[ edge.target().id() ]; + var w = weightFn.apply( edge, [ edge ] ); + + // Update matrix + matrix[ t ][ s ] += w; + + // Update column sum + columnSum[ s ] += w; + } + + // Add additional probability based on damping factor + // Also, take into account columns that have sum = 0 + var p = 1.0 / numNodes + additionalProb; // Shorthand + // Traverse matrix, column by column + for( var j = 0; j < numNodes; j++ ){ + if( columnSum[ j ] === 0 ){ + // No 'links' out from node jth, assume equal probability for each possible node + for( var i = 0; i < numNodes; i++ ){ + matrix[ i ][ j ] = p; + } + } else { + // Node jth has outgoing link, compute normalized probabilities + for( var i = 0; i < numNodes; i++ ){ + matrix[ i ][ j ] = matrix[ i ][ j ] / columnSum[ j ] + additionalProb; + } + } + } + + // Compute dominant eigenvector using power method + var eigenvector = []; + var nullVector = []; + var previous; + + // Start with a vector of all 1's + // Also, initialize a null vector which will be used as shorthand + for( var i = 0; i < numNodes; i++ ){ + eigenvector.push( 1.0 ); + nullVector.push( 0.0 ); + } + + for( var iter = 0; iter < numIter; iter++ ){ + // New array with all 0's + var temp = nullVector.slice( 0 ); + + // Multiply matrix with previous result + for( var i = 0; i < numNodes; i++ ){ + for( var j = 0; j < numNodes; j++ ){ + temp[ i ] += matrix[ i ][ j ] * eigenvector[ j ]; + } + } + + normalizeVector( temp ); + previous = eigenvector; + eigenvector = temp; + + var diff = 0; + // Compute difference (squared module) of both vectors + for( var i = 0; i < numNodes; i++ ){ + diff += Math.pow( previous[ i ] - eigenvector[ i ], 2 ); + } + + // If difference is less than the desired threshold, stop iterating + if( diff < epsilon ){ + break; + } + } + + // Construct result + var res = { + rank: function( node ){ + if( is.string( node ) ){ + // is a selector string + var nodeId = (cy.filter( node )[0]).id(); + } else { + // is a node object + var nodeId = node.id(); + } + return eigenvector[ id2position[ nodeId ] ]; + } + }; + + + return res; + } // pageRank + +}); // elesfn + +module.exports = elesfn; + +},{"../../is":83}],15:[function(_dereq_,module,exports){ +'use strict'; + +var define = _dereq_( '../define' ); + +var elesfn = ({ + animate: define.animate(), + animation: define.animation(), + animated: define.animated(), + clearQueue: define.clearQueue(), + delay: define.delay(), + delayAnimation: define.delayAnimation(), + stop: define.stop() +}); + +module.exports = elesfn; + +},{"../define":44}],16:[function(_dereq_,module,exports){ +'use strict'; + +var util = _dereq_( '../util' ); + +var elesfn = ({ + classes: function( classes ){ + classes = classes.match( /\S+/g ) || []; + var self = this; + var changed = []; + var classesMap = {}; + + // fill in classes map + for( var i = 0; i < classes.length; i++ ){ + var cls = classes[ i ]; + + classesMap[ cls ] = true; + } + + // check and update each ele + for( var j = 0; j < self.length; j++ ){ + var ele = self[ j ]; + var _p = ele._private; + var eleClasses = _p.classes; + var changedEle = false; + + // check if ele has all of the passed classes + for( var i = 0; i < classes.length; i++ ){ + var cls = classes[ i ]; + var eleHasClass = eleClasses[ cls ]; + + if( !eleHasClass ){ + changedEle = true; + break; + } + } + + // check if ele has classes outside of those passed + if( !changedEle ){ + var classes = Object.keys( eleClasses ); + + for( var i = 0; i < classes.length; i++ ){ + var eleCls = classes[i]; + var eleHasClass = eleClasses[ eleCls ]; + var specdClass = classesMap[ eleCls ]; // i.e. this class is passed to the function + + if( eleHasClass && !specdClass ){ + changedEle = true; + break; + } + } + } + + if( changedEle ){ + _p.classes = util.copy( classesMap ); + + changed.push( ele ); + } + } + + // trigger update style on those eles that had class changes + if( changed.length > 0 ){ + this.spawn( changed ) + .updateStyle() + .trigger( 'class' ) + ; + } + + return self; + }, + + addClass: function( classes ){ + return this.toggleClass( classes, true ); + }, + + hasClass: function( className ){ + var ele = this[0]; + return ( ele != null && ele._private.classes[ className ] ) ? true : false; + }, + + toggleClass: function( classesStr, toggle ){ + var classes = classesStr.match( /\S+/g ) || []; + var self = this; + var changed = []; // eles who had classes changed + + for( var i = 0, il = self.length; i < il; i++ ){ + var ele = self[ i ]; + var changedEle = false; + + for( var j = 0; j < classes.length; j++ ){ + var cls = classes[ j ]; + var eleClasses = ele._private.classes; + var hasClass = eleClasses[ cls ]; + var shouldAdd = toggle || (toggle === undefined && !hasClass); + + if( shouldAdd ){ + eleClasses[ cls ] = true; + + if( !hasClass && !changedEle ){ + changed.push( ele ); + changedEle = true; + } + } else { // then remove + eleClasses[ cls ] = false; + + if( hasClass && !changedEle ){ + changed.push( ele ); + changedEle = true; + } + } + + } // for j classes + } // for i eles + + // trigger update style on those eles that had class changes + if( changed.length > 0 ){ + this.spawn( changed ) + .updateStyle() + .trigger( 'class' ) + ; + } + + return self; + }, + + removeClass: function( classes ){ + return this.toggleClass( classes, false ); + }, + + flashClass: function( classes, duration ){ + var self = this; + + if( duration == null ){ + duration = 250; + } else if( duration === 0 ){ + return self; // nothing to do really + } + + self.addClass( classes ); + setTimeout( function(){ + self.removeClass( classes ); + }, duration ); + + return self; + } +}); + +module.exports = elesfn; + +},{"../util":100}],17:[function(_dereq_,module,exports){ +'use strict'; + +var elesfn = ({ + allAre: function( selector ){ + return this.filter( selector ).length === this.length; + }, + + is: function( selector ){ + return this.filter( selector ).length > 0; + }, + + some: function( fn, thisArg ){ + for( var i = 0; i < this.length; i++ ){ + var ret = !thisArg ? fn( this[ i ], i, this ) : fn.apply( thisArg, [ this[ i ], i, this ] ); + + if( ret ){ + return true; + } + } + + return false; + }, + + every: function( fn, thisArg ){ + for( var i = 0; i < this.length; i++ ){ + var ret = !thisArg ? fn( this[ i ], i, this ) : fn.apply( thisArg, [ this[ i ], i, this ] ); + + if( !ret ){ + return false; + } + } + + return true; + }, + + same: function( collection ){ + collection = this.cy().collection( collection ); + + // cheap extra check + if( this.length !== collection.length ){ + return false; + } + + return this.intersect( collection ).length === this.length; + }, + + anySame: function( collection ){ + collection = this.cy().collection( collection ); + + return this.intersect( collection ).length > 0; + }, + + allAreNeighbors: function( collection ){ + collection = this.cy().collection( collection ); + + return this.neighborhood().intersect( collection ).length === collection.length; + } +}); + +elesfn.allAreNeighbours = elesfn.allAreNeighbors; + +module.exports = elesfn; + +},{}],18:[function(_dereq_,module,exports){ +'use strict'; + +var elesfn = ({ + parent: function( selector ){ + var parents = []; + var cy = this._private.cy; + + for( var i = 0; i < this.length; i++ ){ + var ele = this[ i ]; + var parent = cy.getElementById( ele._private.data.parent ); + + if( parent.size() > 0 ){ + parents.push( parent ); + } + } + + return this.spawn( parents, { unique: true } ).filter( selector ); + }, + + parents: function( selector ){ + var parents = []; + + var eles = this.parent(); + while( eles.nonempty() ){ + for( var i = 0; i < eles.length; i++ ){ + var ele = eles[ i ]; + parents.push( ele ); + } + + eles = eles.parent(); + } + + return this.spawn( parents, { unique: true } ).filter( selector ); + }, + + commonAncestors: function( selector ){ + var ancestors; + + for( var i = 0; i < this.length; i++ ){ + var ele = this[ i ]; + var parents = ele.parents(); + + ancestors = ancestors || parents; + + ancestors = ancestors.intersect( parents ); // current list must be common with current ele parents set + } + + return ancestors.filter( selector ); + }, + + orphans: function( selector ){ + return this.stdFilter( function( ele ){ + return ele.isNode() && ele.parent().empty(); + } ).filter( selector ); + }, + + nonorphans: function( selector ){ + return this.stdFilter( function( ele ){ + return ele.isNode() && ele.parent().nonempty(); + } ).filter( selector ); + }, + + children: function( selector ){ + var children = []; + + for( var i = 0; i < this.length; i++ ){ + var ele = this[ i ]; + children = children.concat( ele._private.children ); + } + + return this.spawn( children, { unique: true } ).filter( selector ); + }, + + siblings: function( selector ){ + return this.parent().children().not( this ).filter( selector ); + }, + + isParent: function(){ + var ele = this[0]; + + if( ele ){ + return ele._private.children.length !== 0; + } + }, + + isChild: function(){ + var ele = this[0]; + + if( ele ){ + return ele._private.data.parent !== undefined && ele.parent().length !== 0; + } + }, + + descendants: function( selector ){ + var elements = []; + + function add( eles ){ + for( var i = 0; i < eles.length; i++ ){ + var ele = eles[ i ]; + + elements.push( ele ); + + if( ele.children().nonempty() ){ + add( ele.children() ); + } + } + } + + add( this.children() ); + + return this.spawn( elements, { unique: true } ).filter( selector ); + } +}); + +// aliases +elesfn.ancestors = elesfn.parents; + +module.exports = elesfn; + +},{}],19:[function(_dereq_,module,exports){ +'use strict'; + +var define = _dereq_( '../define' ); +var fn, elesfn; + +fn = elesfn = ({ + + data: define.data( { + field: 'data', + bindingEvent: 'data', + allowBinding: true, + allowSetting: true, + settingEvent: 'data', + settingTriggersEvent: true, + triggerFnName: 'trigger', + allowGetting: true, + immutableKeys: { + 'id': true, + 'source': true, + 'target': true, + 'parent': true + }, + updateStyle: true + } ), + + removeData: define.removeData( { + field: 'data', + event: 'data', + triggerFnName: 'trigger', + triggerEvent: true, + immutableKeys: { + 'id': true, + 'source': true, + 'target': true, + 'parent': true + }, + updateStyle: true + } ), + + scratch: define.data( { + field: 'scratch', + bindingEvent: 'scratch', + allowBinding: true, + allowSetting: true, + settingEvent: 'scratch', + settingTriggersEvent: true, + triggerFnName: 'trigger', + allowGetting: true, + updateStyle: true + } ), + + removeScratch: define.removeData( { + field: 'scratch', + event: 'scratch', + triggerFnName: 'trigger', + triggerEvent: true, + updateStyle: true + } ), + + rscratch: define.data( { + field: 'rscratch', + allowBinding: false, + allowSetting: true, + settingTriggersEvent: false, + allowGetting: true + } ), + + removeRscratch: define.removeData( { + field: 'rscratch', + triggerEvent: false + } ), + + id: function(){ + var ele = this[0]; + + if( ele ){ + return ele._private.data.id; + } + } + +}); + +// aliases +fn.attr = fn.data; +fn.removeAttr = fn.removeData; + +module.exports = elesfn; + +},{"../define":44}],20:[function(_dereq_,module,exports){ +'use strict'; + +var util = _dereq_( '../util' ); + +var elesfn = {}; + +function defineDegreeFunction( callback ){ + return function( includeLoops ){ + var self = this; + + if( includeLoops === undefined ){ + includeLoops = true; + } + + if( self.length === 0 ){ return; } + + if( self.isNode() && !self.removed() ){ + var degree = 0; + var node = self[0]; + var connectedEdges = node._private.edges; + + for( var i = 0; i < connectedEdges.length; i++ ){ + var edge = connectedEdges[ i ]; + + if( !includeLoops && edge.isLoop() ){ + continue; + } + + degree += callback( node, edge ); + } + + return degree; + } else { + return; + } + }; +} + +util.extend( elesfn, { + degree: defineDegreeFunction( function( node, edge ){ + if( edge.source().same( edge.target() ) ){ + return 2; + } else { + return 1; + } + } ), + + indegree: defineDegreeFunction( function( node, edge ){ + if( edge.target().same( node ) ){ + return 1; + } else { + return 0; + } + } ), + + outdegree: defineDegreeFunction( function( node, edge ){ + if( edge.source().same( node ) ){ + return 1; + } else { + return 0; + } + } ) +} ); + +function defineDegreeBoundsFunction( degreeFn, callback ){ + return function( includeLoops ){ + var ret; + var nodes = this.nodes(); + + for( var i = 0; i < nodes.length; i++ ){ + var ele = nodes[ i ]; + var degree = ele[ degreeFn ]( includeLoops ); + if( degree !== undefined && (ret === undefined || callback( degree, ret )) ){ + ret = degree; + } + } + + return ret; + }; +} + +util.extend( elesfn, { + minDegree: defineDegreeBoundsFunction( 'degree', function( degree, min ){ + return degree < min; + } ), + + maxDegree: defineDegreeBoundsFunction( 'degree', function( degree, max ){ + return degree > max; + } ), + + minIndegree: defineDegreeBoundsFunction( 'indegree', function( degree, min ){ + return degree < min; + } ), + + maxIndegree: defineDegreeBoundsFunction( 'indegree', function( degree, max ){ + return degree > max; + } ), + + minOutdegree: defineDegreeBoundsFunction( 'outdegree', function( degree, min ){ + return degree < min; + } ), + + maxOutdegree: defineDegreeBoundsFunction( 'outdegree', function( degree, max ){ + return degree > max; + } ) +} ); + +util.extend( elesfn, { + totalDegree: function( includeLoops ){ + var total = 0; + var nodes = this.nodes(); + + for( var i = 0; i < nodes.length; i++ ){ + total += nodes[ i ].degree( includeLoops ); + } + + return total; + } +} ); + +module.exports = elesfn; + +},{"../util":100}],21:[function(_dereq_,module,exports){ +'use strict'; + +var define = _dereq_( '../define' ); +var is = _dereq_( '../is' ); +var util = _dereq_( '../util' ); +var math = _dereq_( '../math' ); +var fn, elesfn; + +fn = elesfn = ({ + + position: define.data( { + field: 'position', + bindingEvent: 'position', + allowBinding: true, + allowSetting: true, + settingEvent: 'position', + settingTriggersEvent: true, + triggerFnName: 'rtrigger', + allowGetting: true, + validKeys: [ 'x', 'y' ], + onSet: function( eles ){ + var updatedEles = eles.updateCompoundBounds(); + updatedEles.rtrigger( 'position' ); + }, + canSet: function( ele ){ + return !ele.locked() && !ele.isParent(); + } + } ), + + // position but no notification to renderer + silentPosition: define.data( { + field: 'position', + bindingEvent: 'position', + allowBinding: false, + allowSetting: true, + settingEvent: 'position', + settingTriggersEvent: false, + triggerFnName: 'trigger', + allowGetting: true, + validKeys: [ 'x', 'y' ], + onSet: function( eles ){ + eles.updateCompoundBounds(); + }, + canSet: function( ele ){ + return !ele.locked() && !ele.isParent(); + } + } ), + + positions: function( pos, silent ){ + if( is.plainObject( pos ) ){ + this.position( pos ); + + } else if( is.fn( pos ) ){ + var fn = pos; + + for( var i = 0; i < this.length; i++ ){ + var ele = this[ i ]; + + var pos = fn.apply( ele, [ i, ele ] ); + + if( pos && !ele.locked() && !ele.isParent() ){ + var elePos = ele._private.position; + elePos.x = pos.x; + elePos.y = pos.y; + } + } + + var updatedEles = this.updateCompoundBounds(); + var toTrigger = updatedEles.length > 0 ? this.add( updatedEles ) : this; + + if( silent ){ + toTrigger.trigger( 'position' ); + } else { + toTrigger.rtrigger( 'position' ); + } + } + + return this; // chaining + }, + + silentPositions: function( pos ){ + return this.positions( pos, true ); + }, + + // get/set the rendered (i.e. on screen) positon of the element + renderedPosition: function( dim, val ){ + var ele = this[0]; + var cy = this.cy(); + var zoom = cy.zoom(); + var pan = cy.pan(); + var rpos = is.plainObject( dim ) ? dim : undefined; + var setting = rpos !== undefined || ( val !== undefined && is.string( dim ) ); + + if( ele && ele.isNode() ){ // must have an element and must be a node to return position + if( setting ){ + for( var i = 0; i < this.length; i++ ){ + var ele = this[ i ]; + + if( val !== undefined ){ // set one dimension + ele._private.position[ dim ] = ( val - pan[ dim ] ) / zoom; + } else if( rpos !== undefined ){ // set whole position + ele._private.position = { + x: ( rpos.x - pan.x ) / zoom, + y: ( rpos.y - pan.y ) / zoom + }; + } + } + + this.rtrigger( 'position' ); + } else { // getting + var pos = ele._private.position; + rpos = { + x: pos.x * zoom + pan.x, + y: pos.y * zoom + pan.y + }; + + if( dim === undefined ){ // then return the whole rendered position + return rpos; + } else { // then return the specified dimension + return rpos[ dim ]; + } + } + } else if( !setting ){ + return undefined; // for empty collection case + } + + return this; // chaining + }, + + // get/set the position relative to the parent + relativePosition: function( dim, val ){ + var ele = this[0]; + var cy = this.cy(); + var ppos = is.plainObject( dim ) ? dim : undefined; + var setting = ppos !== undefined || ( val !== undefined && is.string( dim ) ); + var hasCompoundNodes = cy.hasCompoundNodes(); + + if( ele && ele.isNode() ){ // must have an element and must be a node to return position + if( setting ){ + for( var i = 0; i < this.length; i++ ){ + var ele = this[ i ]; + var parent = hasCompoundNodes ? ele.parent() : null; + var hasParent = parent && parent.length > 0; + var relativeToParent = hasParent; + + if( hasParent ){ + parent = parent[0]; + } + + var origin = relativeToParent ? parent._private.position : { x: 0, y: 0 }; + + if( val !== undefined ){ // set one dimension + ele._private.position[ dim ] = val + origin[ dim ]; + } else if( ppos !== undefined ){ // set whole position + ele._private.position = { + x: ppos.x + origin.x, + y: ppos.y + origin.y + }; + } + } + + this.rtrigger( 'position' ); + + } else { // getting + var pos = ele._private.position; + var parent = hasCompoundNodes ? ele.parent() : null; + var hasParent = parent && parent.length > 0; + var relativeToParent = hasParent; + + if( hasParent ){ + parent = parent[0]; + } + + var origin = relativeToParent ? parent._private.position : { x: 0, y: 0 }; + + ppos = { + x: pos.x - origin.x, + y: pos.y - origin.y + }; + + if( dim === undefined ){ // then return the whole rendered position + return ppos; + } else { // then return the specified dimension + return ppos[ dim ]; + } + } + } else if( !setting ){ + return undefined; // for empty collection case + } + + return this; // chaining + }, + + renderedBoundingBox: function( options ){ + var bb = this.boundingBox( options ); + var cy = this.cy(); + var zoom = cy.zoom(); + var pan = cy.pan(); + + var x1 = bb.x1 * zoom + pan.x; + var x2 = bb.x2 * zoom + pan.x; + var y1 = bb.y1 * zoom + pan.y; + var y2 = bb.y2 * zoom + pan.y; + + return { + x1: x1, + x2: x2, + y1: y1, + y2: y2, + w: x2 - x1, + h: y2 - y1 + }; + }, + + updateCompoundBounds: function(){ + var cy = this.cy(); + + // save cycles for non compound graphs or when style disabled + if( !cy.styleEnabled() || !cy.hasCompoundNodes() ){ return cy.collection(); } + + var updated = []; + + function update( parent ){ + if( !parent.isParent() ){ return; } + + var _p = parent._private; + var children = parent.children(); + var includeLabels = parent.pstyle( 'compound-sizing-wrt-labels' ).value === 'include'; + var bb = children.boundingBox( { + includeLabels: includeLabels, + includeShadows: false, + includeOverlays: false, + + // updating the compound bounds happens outside of the regular + // cache cycle (i.e. before fired events) + useCache: false + } ); + var padding = { + top: parent.pstyle( 'padding-top' ).pfValue, + bottom: parent.pstyle( 'padding-bottom' ).pfValue, + left: parent.pstyle( 'padding-left' ).pfValue, + right: parent.pstyle( 'padding-right' ).pfValue + }; + var pos = _p.position; + + _p.autoWidth = bb.w; + pos.x = (bb.x1 + bb.x2 - padding.left + padding.right) / 2; + + _p.autoHeight = bb.h; + pos.y = (bb.y1 + bb.y2 - padding.top + padding.bottom) / 2; + + updated.push( parent ); + } + + // go up, level by level + var eles = this; + while( eles.nonempty() ){ + + // update each parent node in this level + for( var i = 0; i < eles.length; i++ ){ + var ele = eles[ i ]; + + update( ele ); + } + + // next level + eles = eles.parent(); + } + + // return changed + return this.spawn( updated ); + } +}); + +var noninf = function( x ){ + if( x === Infinity || x === -Infinity ){ + return 0; + } + + return x; +}; + +var updateBounds = function( b, x1, y1, x2, y2 ){ + // don't update with zero area boxes + if( x2 - x1 === 0 || y2 - y1 === 0 ){ return; } + + b.x1 = x1 < b.x1 ? x1 : b.x1; + b.x2 = x2 > b.x2 ? x2 : b.x2; + b.y1 = y1 < b.y1 ? y1 : b.y1; + b.y2 = y2 > b.y2 ? y2 : b.y2; +}; + +var updateBoundsFromBox = function( b, b2 ){ + return updateBounds( b, b2.x1, b2.y1, b2.x2, b2.y2 ); +}; + +var prefixedProperty = function( obj, field, prefix ){ + return util.getPrefixedProperty( obj, field, prefix ); +}; + +var updateBoundsFromArrow = function( bounds, ele, prefix, options ){ + var _p = ele._private; + var rstyle = _p.rstyle; + var halfArW = rstyle.arrowWidth / 2; + var arrowType = ele.pstyle( prefix + '-arrow-shape' ).value; + var x; + var y; + + if( arrowType !== 'none' ){ + if( prefix === 'source' ){ + x = rstyle.srcX; + y = rstyle.srcY; + } else if( prefix === 'target' ){ + x = rstyle.tgtX; + y = rstyle.tgtY; + } else { + x = rstyle.midX; + y = rstyle.midY; + } + + updateBounds( bounds, x - halfArW, y - halfArW, x + halfArW, y + halfArW ); + } +}; + +var updateBoundsFromLabel = function( bounds, ele, prefix, options ){ + var prefixDash; + + if( prefix ){ + prefixDash = prefix + '-'; + } else { + prefixDash = ''; + } + + var _p = ele._private; + var rstyle = _p.rstyle; + var label = ele.pstyle( prefixDash + 'label' ).strValue; + + if( label ){ + var halign = ele.pstyle( 'text-halign' ); + var valign = ele.pstyle( 'text-valign' ); + var labelWidth = prefixedProperty( rstyle, 'labelWidth', prefix ); + var labelHeight = prefixedProperty( rstyle, 'labelHeight', prefix ); + var labelX = prefixedProperty( rstyle, 'labelX', prefix ); + var labelY = prefixedProperty( rstyle, 'labelY', prefix ); + var marginX = ele.pstyle( prefixDash + 'text-margin-x' ).pfValue; + var marginY = ele.pstyle( prefixDash + 'text-margin-y' ).pfValue; + var isEdge = ele.isEdge(); + var rotation = ele.pstyle( prefixDash + 'text-rotation' ); + var shadowR = ele.pstyle( 'text-shadow-blur' ).pfValue / 2; + var shadowX = ele.pstyle( 'text-shadow-offset-x' ).pfValue; + var shadowY = ele.pstyle( 'text-shadow-offset-y' ).pfValue; + var shadowOpacity = ele.pstyle( 'text-shadow-opacity' ).value; + var outlineWidth = ele.pstyle( 'text-outline-width' ).pfValue; + var borderWidth = ele.pstyle( 'text-border-width' ).pfValue; + var halfBorderWidth = borderWidth / 2; + + var lh = labelHeight; + var lw = labelWidth; + var lw_2 = lw / 2; + var lh_2 = lh / 2; + var lx1, lx2, ly1, ly2; + + if( isEdge ){ + lx1 = labelX - lw_2; + lx2 = labelX + lw_2; + ly1 = labelY - lh_2; + ly2 = labelY + lh_2; + } else { + switch( halign.value ){ + case 'left': + lx1 = labelX - lw; + lx2 = labelX; + break; + + case 'center': + lx1 = labelX - lw_2; + lx2 = labelX + lw_2; + break; + + case 'right': + lx1 = labelX; + lx2 = labelX + lw; + break; + } + + switch( valign.value ){ + case 'top': + ly1 = labelY - lh; + ly2 = labelY; + break; + + case 'center': + ly1 = labelY - lh_2; + ly2 = labelY + lh_2; + break; + + case 'bottom': + ly1 = labelY; + ly2 = labelY + lh; + break; + } + } + + var isAutorotate = ( isEdge && rotation.strValue === 'autorotate' ); + var isPfValue = ( rotation.pfValue != null && rotation.pfValue !== 0 ); + + if( isAutorotate || isPfValue ){ + var theta = isAutorotate ? prefixedProperty( _p.rstyle, 'labelAngle', prefix ) : rotation.pfValue; + var cos = Math.cos( theta ); + var sin = Math.sin( theta ); + + var rotate = function( x, y ){ + x = x - labelX; + y = y - labelY; + + return { + x: x * cos - y * sin + labelX, + y: x * sin + y * cos + labelY + }; + }; + + var px1y1 = rotate( lx1, ly1 ); + var px1y2 = rotate( lx1, ly2 ); + var px2y1 = rotate( lx2, ly1 ); + var px2y2 = rotate( lx2, ly2 ); + + lx1 = Math.min( px1y1.x, px1y2.x, px2y1.x, px2y2.x ); + lx2 = Math.max( px1y1.x, px1y2.x, px2y1.x, px2y2.x ); + ly1 = Math.min( px1y1.y, px1y2.y, px2y1.y, px2y2.y ); + ly2 = Math.max( px1y1.y, px1y2.y, px2y1.y, px2y2.y ); + } + + lx1 += marginX - Math.max( outlineWidth, halfBorderWidth ); + lx2 += marginX + Math.max( outlineWidth, halfBorderWidth ); + ly1 += marginY - Math.max( outlineWidth, halfBorderWidth ); + ly2 += marginY + Math.max( outlineWidth, halfBorderWidth ); + + updateBounds( bounds, lx1, ly1, lx2, ly2 ); + + if( options.includeShadows && shadowOpacity > 0 ){ + lx1 += - shadowR + shadowX; + lx2 += + shadowR + shadowX; + ly1 += - shadowR + shadowY; + ly2 += + shadowR + shadowY; + + updateBounds( bounds, lx1, ly1, lx2, ly2 ); + } + } + + return bounds; +}; + +// get the bounding box of the elements (in raw model position) +var boundingBoxImpl = function( ele, options ){ + var cy = ele._private.cy; + var cy_p = cy._private; + var styleEnabled = cy_p.styleEnabled; + + var bounds = { + x1: Infinity, + y1: Infinity, + x2: -Infinity, + y2: -Infinity + }; + + var _p = ele._private; + var display = styleEnabled ? ele.pstyle( 'display' ).value : 'element'; + var isNode = ele.isNode(); + var isEdge = ele.isEdge(); + var ex1, ex2, ey1, ey2, x, y; + var displayed = display !== 'none'; + + if( displayed ){ + var overlayOpacity = 0; + var overlayPadding = 0; + + if( styleEnabled && options.includeOverlays ){ + overlayOpacity = ele.pstyle( 'overlay-opacity' ).value; + + if( overlayOpacity !== 0 ){ + overlayPadding = ele.pstyle( 'overlay-padding' ).value; + } + } + + var w = 0; + var wHalf = 0; + + if( styleEnabled ){ + w = ele.pstyle( 'width' ).pfValue; + wHalf = w / 2; + } + + if( isNode && options.includeNodes ){ + var pos = _p.position; + x = pos.x; + y = pos.y; + var w = ele.outerWidth(); + var halfW = w / 2; + var h = ele.outerHeight(); + var halfH = h / 2; + + // handle node dimensions + ///////////////////////// + + ex1 = x - halfW - overlayPadding; + ex2 = x + halfW + overlayPadding; + ey1 = y - halfH - overlayPadding; + ey2 = y + halfH + overlayPadding; + + updateBounds( bounds, ex1, ey1, ex2, ey2 ); + + } else if( isEdge && options.includeEdges ){ + var rstyle = _p.rstyle || {}; + + // handle edge dimensions (rough box estimate) + ////////////////////////////////////////////// + if( styleEnabled ){ + ex1 = Math.min( rstyle.srcX, rstyle.midX, rstyle.tgtX ); + ex2 = Math.max( rstyle.srcX, rstyle.midX, rstyle.tgtX ); + ey1 = Math.min( rstyle.srcY, rstyle.midY, rstyle.tgtY ); + ey2 = Math.max( rstyle.srcY, rstyle.midY, rstyle.tgtY ); + + // take into account edge width + ex1 -= wHalf; + ex2 += wHalf; + ey1 -= wHalf; + ey2 += wHalf; + + updateBounds( bounds, ex1, ey1, ex2, ey2 ); + } + + // precise haystacks + //////////////////// + if( styleEnabled && ele.pstyle( 'curve-style' ).strValue === 'haystack' ){ + var hpts = rstyle.haystackPts; + + ex1 = hpts[0].x; + ey1 = hpts[0].y; + ex2 = hpts[1].x; + ey2 = hpts[1].y; + + if( ex1 > ex2 ){ + var temp = ex1; + ex1 = ex2; + ex2 = temp; + } + + if( ey1 > ey2 ){ + var temp = ey1; + ey1 = ey2; + ey2 = temp; + } + + updateBounds( bounds, ex1 - wHalf, ey1 - wHalf, ex2 + wHalf, ey2 + wHalf ); + + // handle points along edge + /////////////////////////// + } else { + var pts = rstyle.bezierPts || rstyle.linePts || []; + + for( var j = 0; j < pts.length; j++ ){ + var pt = pts[ j ]; + + ex1 = pt.x - wHalf; + ex2 = pt.x + wHalf; + ey1 = pt.y - wHalf; + ey2 = pt.y + wHalf; + + updateBounds( bounds, ex1, ey1, ex2, ey2 ); + } + + // fallback on source and target positions + ////////////////////////////////////////// + if( pts.length === 0 ){ + var n1 = _p.source; + var n1_p = n1._private; + var n1pos = n1_p.position; + + var n2 = _p.target; + var n2_p = n2._private; + var n2pos = n2_p.position; + + ex1 = n1pos.x; + ex2 = n2pos.x; + ey1 = n1pos.y; + ey2 = n2pos.y; + + if( ex1 > ex2 ){ + var temp = ex1; + ex1 = ex2; + ex2 = temp; + } + + if( ey1 > ey2 ){ + var temp = ey1; + ey1 = ey2; + ey2 = temp; + } + + // take into account edge width + ex1 -= wHalf; + ex2 += wHalf; + ey1 -= wHalf; + ey2 += wHalf; + + updateBounds( bounds, ex1, ey1, ex2, ey2 ); + } + } + + } // edges + + // shadow and overlay + ///////////////////// + + if( styleEnabled ){ + + ex1 = bounds.x1; + ex2 = bounds.x2; + ey1 = bounds.y1; + ey2 = bounds.y2; + + if( options.includeShadows && ele.pstyle('shadow-opacity').value > 0 ){ + var r = ele.pstyle('shadow-blur').pfValue / 2; + var ox = ele.pstyle('shadow-offset-x').pfValue; + var oy = ele.pstyle('shadow-offset-y').pfValue; + + updateBounds( bounds, ex1 - r + ox, ey1 - r + oy, ex2 + r + ox, ey2 + r + oy ); + } + + updateBounds( bounds, ex1 - overlayPadding, ey1 - overlayPadding, ex2 + overlayPadding, ey2 + overlayPadding ); + } + + // handle edge arrow size + ///////////////////////// + + if( styleEnabled && options.includeEdges && isEdge ){ + updateBoundsFromArrow( bounds, ele, 'mid-source', options ); + updateBoundsFromArrow( bounds, ele, 'mid-target', options ); + updateBoundsFromArrow( bounds, ele, 'source', options ); + updateBoundsFromArrow( bounds, ele, 'target', options ); + } + + // handle label dimensions + ////////////////////////// + + if( styleEnabled && options.includeLabels ){ + updateBoundsFromLabel( bounds, ele, null, options ); + + if( isEdge ){ + updateBoundsFromLabel( bounds, ele, 'source', options ); + updateBoundsFromLabel( bounds, ele, 'target', options ); + } + } // style enabled for labels + } // if displayed + + bounds.x1 = noninf( bounds.x1 ); + bounds.y1 = noninf( bounds.y1 ); + bounds.x2 = noninf( bounds.x2 ); + bounds.y2 = noninf( bounds.y2 ); + bounds.w = noninf( bounds.x2 - bounds.x1 ); + bounds.h = noninf( bounds.y2 - bounds.y1 ); + + // expand bounds by 1 because antialiasing can increase the visual/effective size by 1 on all sides + if( bounds.w > 0 && bounds.h > 0 && displayed ){ + math.expandBoundingBox( bounds, 1 ); + } + + return bounds; +}; + +var tf = function( val ){ + if( val ){ + return 't'; + } else { + return 'f'; + } +}; + +var getKey = function( opts ){ + var key = ''; + + key += tf( opts.incudeNodes ); + key += tf( opts.includeEdges ); + key += tf( opts.includeLabels ); + key += tf( opts.includeShadows ); + key += tf( opts.includeOverlays ); + + return key; +}; + +var cachedBoundingBoxImpl = function( ele, opts ){ + var _p = ele._private; + var bb; + var headless = ele.cy().headless(); + var key = opts === defBbOpts ? defBbOptsKey : getKey( opts ); + + if( !opts.useCache || headless || !_p.bbCache || !_p.bbCache[key] ){ + bb = boundingBoxImpl( ele, opts ); + + if( !headless ){ + _p.bbCache = _p.bbCache || {}; + _p.bbCache[key] = bb; + } + } else { + bb = _p.bbCache[key]; + } + + return bb; +}; + +var defBbOpts = { + includeNodes: true, + includeEdges: true, + includeLabels: true, + includeShadows: true, + includeOverlays: true, + useCache: true +}; + +var defBbOptsKey = getKey( defBbOpts ); + +elesfn.boundingBox = function( options ){ + // the main usecase is ele.boundingBox() for a single element with no/def options + // specified s.t. the cache is used, so check for this case to make it faster by + // avoiding the overhead of the rest of the function + if( this.length === 1 && this[0]._private.bbCache && (options === undefined || options.useCache === undefined || options.useCache === true) ){ + if( options === undefined ){ + options = defBbOpts; + } + + return cachedBoundingBoxImpl( this[0], options ); + } + + var bounds = { + x1: Infinity, + y1: Infinity, + x2: -Infinity, + y2: -Infinity + }; + + options = options || util.staticEmptyObject(); + + var opts = { + includeNodes: util.default( options.includeNodes, defBbOpts.includeNodes ), + includeEdges: util.default( options.includeEdges, defBbOpts.includeEdges ), + includeLabels: util.default( options.includeLabels, defBbOpts.includeLabels ), + includeShadows: util.default( options.includeShadows, defBbOpts.includeShadows ), + includeOverlays: util.default( options.includeOverlays, defBbOpts.includeOverlays ), + useCache: util.default( options.useCache, defBbOpts.useCache ) + }; + + var eles = this; + var cy = eles.cy(); + var renderer = eles.cy().renderer(); + var styleEnabled = cy.styleEnabled(); + + if( styleEnabled ){ + renderer.recalculateRenderedStyle( eles, opts.useCache ); + } + + for( var i = 0; i < eles.length; i++ ){ + var ele = eles[i]; + + if( styleEnabled && ele.isEdge() && ele.pstyle('curve-style').strValue === 'bezier' ){ + renderer.recalculateRenderedStyle( ele.parallelEdges(), opts.useCache ); // n.b. ele.parallelEdges() single is cached + } + + updateBoundsFromBox( bounds, cachedBoundingBoxImpl( ele, opts ) ); + } + + bounds.x1 = noninf( bounds.x1 ); + bounds.y1 = noninf( bounds.y1 ); + bounds.x2 = noninf( bounds.x2 ); + bounds.y2 = noninf( bounds.y2 ); + bounds.w = noninf( bounds.x2 - bounds.x1 ); + bounds.h = noninf( bounds.y2 - bounds.y1 ); + + return bounds; +}; + +var defineDimFns = function( opts ){ + opts.uppercaseName = util.capitalize( opts.name ); + opts.autoName = 'auto' + opts.uppercaseName; + opts.labelName = 'label' + opts.uppercaseName; + opts.outerName = 'outer' + opts.uppercaseName; + opts.uppercaseOuterName = util.capitalize( opts.outerName ); + + fn[ opts.name ] = function dimImpl(){ + var ele = this[0]; + var _p = ele._private; + var cy = _p.cy; + var styleEnabled = cy._private.styleEnabled; + + if( ele ){ + if( styleEnabled ){ + if( ele.isParent() ){ + return _p[ opts.autoName ] || 0; + } + + var d = ele.pstyle( opts.name ); + + switch( d.strValue ){ + case 'label': + return _p.rstyle[ opts.labelName ] || 0; + default: + return d.pfValue; + } + } else { + return 1; + } + } + }; + + fn[ 'outer' + opts.uppercaseName ] = function outerDimImpl(){ + var ele = this[0]; + var _p = ele._private; + var cy = _p.cy; + var styleEnabled = cy._private.styleEnabled; + + if( ele ){ + if( styleEnabled ){ + var dim = ele[ opts.name ](); + var border = ele.pstyle( 'border-width' ).pfValue; + var padding = ele.pstyle( opts.paddings[0] ).pfValue + ele.pstyle( opts.paddings[1] ).pfValue; + + return dim + border + padding; + } else { + return 1; + } + } + }; + + fn[ 'rendered' + opts.uppercaseName ] = function renderedDimImpl(){ + var ele = this[0]; + + if( ele ){ + var d = ele[ opts.name ](); + return d * this.cy().zoom(); + } + }; + + fn[ 'rendered' + opts.uppercaseOuterName ] = function renderedOuterDimImpl(){ + var ele = this[0]; + + if( ele ){ + var od = ele[ opts.outerName ](); + return od * this.cy().zoom(); + } + }; +}; + +defineDimFns( { + name: 'width', + paddings: [ 'padding-left', 'padding-right' ] +} ); + +defineDimFns( { + name: 'height', + paddings: [ 'padding-top', 'padding-bottom' ] +} ); + +// aliases +fn.modelPosition = fn.point = fn.position; +fn.modelPositions = fn.points = fn.positions; +fn.renderedPoint = fn.renderedPosition; +fn.relativePoint = fn.relativePosition; +fn.boundingbox = fn.boundingBox; +fn.renderedBoundingbox = fn.renderedBoundingBox; + +module.exports = elesfn; + +},{"../define":44,"../is":83,"../math":85,"../util":100}],22:[function(_dereq_,module,exports){ +'use strict'; + +var util = _dereq_( '../util' ); +var is = _dereq_( '../is' ); + +// represents a node or an edge +var Element = function( cy, params, restore ){ + var self = this; + restore = (restore === undefined || restore ? true : false); + + if( cy === undefined || params === undefined || !is.core( cy ) ){ + util.error( 'An element must have a core reference and parameters set' ); + return; + } + + var group = params.group; + + // try to automatically infer the group if unspecified + if( group == null ){ + if( params.data && params.data.source != null && params.data.target != null ){ + group = 'edges'; + } else { + group = 'nodes'; + } + } + + // validate group + if( group !== 'nodes' && group !== 'edges' ){ + util.error( 'An element must be of type `nodes` or `edges`; you specified `' + group + '`' ); + return; + } + + // make the element array-like, just like a collection + this.length = 1; + this[0] = this; + + // NOTE: when something is added here, add also to ele.json() + this._private = { + cy: cy, + single: true, // indicates this is an element + data: params.data || {}, // data object + position: params.position || {}, // (x, y) position pair + autoWidth: undefined, // width and height of nodes calculated by the renderer when set to special 'auto' value + autoHeight: undefined, + listeners: [], // array of bound listeners + group: group, // string; 'nodes' or 'edges' + style: {}, // properties as set by the style + rstyle: {}, // properties for style sent from the renderer to the core + styleCxts: [], // applied style contexts from the styler + removed: true, // whether it's inside the vis; true if removed (set true here since we call restore) + selected: params.selected ? true : false, // whether it's selected + selectable: params.selectable === undefined ? true : ( params.selectable ? true : false ), // whether it's selectable + locked: params.locked ? true : false, // whether the element is locked (cannot be moved) + grabbed: false, // whether the element is grabbed by the mouse; renderer sets this privately + grabbable: params.grabbable === undefined ? true : ( params.grabbable ? true : false ), // whether the element can be grabbed + active: false, // whether the element is active from user interaction + classes: {}, // map ( className => true ) + animation: { // object for currently-running animations + current: [], + queue: [] + }, + rscratch: {}, // object in which the renderer can store information + scratch: params.scratch || {}, // scratch objects + edges: [], // array of connected edges + children: [], // array of children + traversalCache: {} // cache of output of traversal functions + }; + + // renderedPosition overrides if specified + if( params.renderedPosition ){ + var rpos = params.renderedPosition; + var pan = cy.pan(); + var zoom = cy.zoom(); + + this._private.position = { + x: (rpos.x - pan.x) / zoom, + y: (rpos.y - pan.y) / zoom + }; + } + + if( is.string( params.classes ) ){ + var classes = params.classes.split( /\s+/ ); + for( var i = 0, l = classes.length; i < l; i++ ){ + var cls = classes[ i ]; + if( !cls || cls === '' ){ continue; } + + self._private.classes[ cls ] = true; + } + } + + if( params.style || params.css ){ + cy.style().applyBypass( this, params.style || params.css ); + } + + if( restore === undefined || restore ){ + this.restore(); + } + +}; + +module.exports = Element; + +},{"../is":83,"../util":100}],23:[function(_dereq_,module,exports){ +'use strict'; + +var define = _dereq_( '../define' ); + +var elesfn = ({ + on: define.on(), // .on( events [, selector] [, data], handler) + one: define.on( { unbindSelfOnTrigger: true } ), + once: define.on( { unbindAllBindersOnTrigger: true } ), + off: define.off(), // .off( events [, selector] [, handler] ) + trigger: define.trigger(), // .trigger( events [, extraParams] ) + + rtrigger: function( event, extraParams ){ // for internal use only + if( this.length === 0 ){ return; } // empty collections don't need to notify anything + + // notify renderer + this.cy().notify( { + type: event, + eles: this + } ); + + this.trigger( event, extraParams ); + return this; + } +}); + +// aliases: +define.eventAliasesOn( elesfn ); + +module.exports = elesfn; + +},{"../define":44}],24:[function(_dereq_,module,exports){ +'use strict'; + +var is = _dereq_( '../is' ); +var Selector = _dereq_( '../selector' ); + +var elesfn = ({ + nodes: function( selector ){ + return this.filter( function( i, element ){ + return element.isNode(); + } ).filter( selector ); + }, + + edges: function( selector ){ + return this.filter( function( i, element ){ + return element.isEdge(); + } ).filter( selector ); + }, + + filter: function( filter ){ + if( filter === undefined ){ // check this first b/c it's the most common/performant case + return this; + } else if( is.string( filter ) || is.elementOrCollection( filter ) ){ + return Selector( filter ).filter( this ); + } else if( is.fn( filter ) ){ + var elements = []; + + for( var i = 0; i < this.length; i++ ){ + var ele = this[ i ]; + + if( filter.apply( ele, [ i, ele ] ) ){ + elements.push( ele ); + } + } + + return this.spawn( elements ); + } + + return this.spawn(); // if not handled by above, give 'em an empty collection + }, + + not: function( toRemove ){ + if( !toRemove ){ + return this; + } else { + + if( is.string( toRemove ) ){ + toRemove = this.filter( toRemove ); + } + + var elements = []; + + for( var i = 0; i < this.length; i++ ){ + var element = this[ i ]; + + var remove = toRemove._private.ids[ element.id() ]; + if( !remove ){ + elements.push( element ); + } + } + + return this.spawn( elements ); + } + + }, + + absoluteComplement: function(){ + var cy = this._private.cy; + + return cy.mutableElements().not( this ); + }, + + intersect: function( other ){ + // if a selector is specified, then filter by it instead + if( is.string( other ) ){ + var selector = other; + return this.filter( selector ); + } + + var elements = []; + var col1 = this; + var col2 = other; + var col1Smaller = this.length < other.length; + // var ids1 = col1Smaller ? col1._private.ids : col2._private.ids; + var ids2 = col1Smaller ? col2._private.ids : col1._private.ids; + var col = col1Smaller ? col1 : col2; + + for( var i = 0; i < col.length; i++ ){ + var id = col[ i ]._private.data.id; + var ele = ids2[ id ]; + + if( ele ){ + elements.push( ele ); + } + } + + return this.spawn( elements ); + }, + + xor: function( other ){ + var cy = this._private.cy; + + if( is.string( other ) ){ + other = cy.$( other ); + } + + var elements = []; + var col1 = this; + var col2 = other; + + var add = function( col, other ){ + + for( var i = 0; i < col.length; i++ ){ + var ele = col[ i ]; + var id = ele._private.data.id; + var inOther = other._private.ids[ id ]; + + if( !inOther ){ + elements.push( ele ); + } + } + + }; + + add( col1, col2 ); + add( col2, col1 ); + + return this.spawn( elements ); + }, + + diff: function( other ){ + var cy = this._private.cy; + + if( is.string( other ) ){ + other = cy.$( other ); + } + + var left = []; + var right = []; + var both = []; + var col1 = this; + var col2 = other; + + var add = function( col, other, retEles ){ + + for( var i = 0; i < col.length; i++ ){ + var ele = col[ i ]; + var id = ele._private.data.id; + var inOther = other._private.ids[ id ]; + + if( inOther ){ + both.push( ele ); + } else { + retEles.push( ele ); + } + } + + }; + + add( col1, col2, left ); + add( col2, col1, right ); + + return { + left: this.spawn( left, { unique: true } ), + right: this.spawn( right, { unique: true } ), + both: this.spawn( both, { unique: true } ) + }; + }, + + add: function( toAdd ){ + var cy = this._private.cy; + + if( !toAdd ){ + return this; + } + + if( is.string( toAdd ) ){ + var selector = toAdd; + toAdd = cy.mutableElements().filter( selector ); + } + + var elements = []; + + for( var i = 0; i < this.length; i++ ){ + elements.push( this[ i ] ); + } + + for( var i = 0; i < toAdd.length; i++ ){ + + var add = !this._private.ids[ toAdd[ i ].id() ]; + if( add ){ + elements.push( toAdd[ i ] ); + } + } + + return this.spawn( elements ); + }, + + // in place merge on calling collection + merge: function( toAdd ){ + var _p = this._private; + var cy = _p.cy; + + if( !toAdd ){ + return this; + } + + if( toAdd && is.string( toAdd ) ){ + var selector = toAdd; + toAdd = cy.mutableElements().filter( selector ); + } + + for( var i = 0; i < toAdd.length; i++ ){ + var toAddEle = toAdd[ i ]; + var id = toAddEle._private.data.id; + var add = !_p.ids[ id ]; + + if( add ){ + var index = this.length++; + + this[ index ] = toAddEle; + _p.ids[ id ] = toAddEle; + _p.indexes[ id ] = index; + } else { // replace + var index = _p.indexes[ id ]; + + this[ index ] = toAddEle; + _p.ids[ id ] = toAddEle; + } + } + + return this; // chaining + }, + + // remove single ele in place in calling collection + unmergeOne: function( ele ){ + ele = ele[0]; + + var _p = this._private; + var id = ele._private.data.id; + var i = _p.indexes[ id ]; + + if( i == null ){ + return this; // no need to remove + } + + // remove ele + this[ i ] = undefined; + _p.ids[ id ] = undefined; + _p.indexes[ id ] = undefined; + + var unmergedLastEle = i === this.length - 1; + + // replace empty spot with last ele in collection + if( this.length > 1 && !unmergedLastEle ){ + var lastEleI = this.length - 1; + var lastEle = this[ lastEleI ]; + var lastEleId = lastEle._private.data.id; + + this[ lastEleI ] = undefined; + this[ i ] = lastEle; + _p.indexes[ lastEleId ] = i; + } + + // the collection is now 1 ele smaller + this.length--; + + return this; + }, + + // remove eles in place on calling collection + unmerge: function( toRemove ){ + var cy = this._private.cy; + + if( !toRemove ){ + return this; + } + + if( toRemove && is.string( toRemove ) ){ + var selector = toRemove; + toRemove = cy.mutableElements().filter( selector ); + } + + for( var i = 0; i < toRemove.length; i++ ){ + this.unmergeOne( toRemove[ i ] ); + } + + return this; // chaining + }, + + map: function( mapFn, thisArg ){ + var arr = []; + var eles = this; + + for( var i = 0; i < eles.length; i++ ){ + var ele = eles[ i ]; + var ret = thisArg ? mapFn.apply( thisArg, [ ele, i, eles ] ) : mapFn( ele, i, eles ); + + arr.push( ret ); + } + + return arr; + }, + + stdFilter: function( fn, thisArg ){ + var filterEles = []; + var eles = this; + + for( var i = 0; i < eles.length; i++ ){ + var ele = eles[ i ]; + var include = thisArg ? fn.apply( thisArg, [ ele, i, eles ] ) : fn( ele, i, eles ); + + if( include ){ + filterEles.push( ele ); + } + } + + return this.spawn( filterEles ); + }, + + max: function( valFn, thisArg ){ + var max = -Infinity; + var maxEle; + var eles = this; + + for( var i = 0; i < eles.length; i++ ){ + var ele = eles[ i ]; + var val = thisArg ? valFn.apply( thisArg, [ ele, i, eles ] ) : valFn( ele, i, eles ); + + if( val > max ){ + max = val; + maxEle = ele; + } + } + + return { + value: max, + ele: maxEle + }; + }, + + min: function( valFn, thisArg ){ + var min = Infinity; + var minEle; + var eles = this; + + for( var i = 0; i < eles.length; i++ ){ + var ele = eles[ i ]; + var val = thisArg ? valFn.apply( thisArg, [ ele, i, eles ] ) : valFn( ele, i, eles ); + + if( val < min ){ + min = val; + minEle = ele; + } + } + + return { + value: min, + ele: minEle + }; + } +}); + +// aliases +var fn = elesfn; +fn[ 'u' ] = fn[ '|' ] = fn[ '+' ] = fn.union = fn.or = fn.add; +fn[ '\\' ] = fn[ '!' ] = fn[ '-' ] = fn.difference = fn.relativeComplement = fn.subtract = fn.not; +fn[ 'n' ] = fn[ '&' ] = fn[ '.' ] = fn.and = fn.intersection = fn.intersect; +fn[ '^' ] = fn[ '(+)' ] = fn[ '(-)' ] = fn.symmetricDifference = fn.symdiff = fn.xor; +fn.fnFilter = fn.filterFn = fn.stdFilter; +fn.complement = fn.abscomp = fn.absoluteComplement; + +module.exports = elesfn; + +},{"../is":83,"../selector":87}],25:[function(_dereq_,module,exports){ +'use strict'; + +var elesfn = ({ + isNode: function(){ + return this.group() === 'nodes'; + }, + + isEdge: function(){ + return this.group() === 'edges'; + }, + + isLoop: function(){ + return this.isEdge() && this.source().id() === this.target().id(); + }, + + isSimple: function(){ + return this.isEdge() && this.source().id() !== this.target().id(); + }, + + group: function(){ + var ele = this[0]; + + if( ele ){ + return ele._private.group; + } + } +}); + + +module.exports = elesfn; + +},{}],26:[function(_dereq_,module,exports){ +'use strict'; + +var util = _dereq_( '../util' ); +var is = _dereq_( '../is' ); + +var Element = _dereq_( './element' ); + +// factory for generating edge ids when no id is specified for a new element +var idFactory = { + generate: function( cy, element, tryThisId ){ + var id = tryThisId != null ? tryThisId : util.uuid(); + + while( cy.hasElementWithId( id ) ){ + id = util.uuid(); + } + + return id; + } +}; + +// represents a set of nodes, edges, or both together +var Collection = function( cy, elements, options ){ + if( cy === undefined || !is.core( cy ) ){ + util.error( 'A collection must have a reference to the core' ); + return; + } + + var ids = {}; + var indexes = {}; + var createdElements = false; + + if( !elements ){ + elements = []; + } else if( elements.length > 0 && is.plainObject( elements[0] ) && !is.element( elements[0] ) ){ + createdElements = true; + + // make elements from json and restore all at once later + var eles = []; + var elesIds = {}; + + for( var i = 0, l = elements.length; i < l; i++ ){ + var json = elements[ i ]; + + if( json.data == null ){ + json.data = {}; + } + + var data = json.data; + + // make sure newly created elements have valid ids + if( data.id == null ){ + data.id = idFactory.generate( cy, json ); + } else if( cy.hasElementWithId( data.id ) || elesIds[ data.id ] ){ + continue; // can't create element if prior id already exists + } + + var ele = new Element( cy, json, false ); + eles.push( ele ); + elesIds[ data.id ] = true; + } + + elements = eles; + } + + this.length = 0; + + for( var i = 0, l = elements.length; i < l; i++ ){ + var element = elements[ i ]; + if( !element ){ continue; } + + var id = element._private.data.id; + + if( !options || (options.unique && !ids[ id ] ) ){ + ids[ id ] = element; + indexes[ id ] = this.length; + + this[ this.length ] = element; + this.length++; + } + } + + this._private = { + cy: cy, + ids: ids, + indexes: indexes + }; + + // restore the elements if we created them from json + if( createdElements ){ + this.restore(); + } +}; + +// Functions +//////////////////////////////////////////////////////////////////////////////////////////////////// + +// keep the prototypes in sync (an element has the same functions as a collection) +// and use elefn and elesfn as shorthands to the prototypes +var elesfn = Element.prototype = Collection.prototype; + +elesfn.instanceString = function(){ + return 'collection'; +}; + +elesfn.spawn = function( cy, eles, opts ){ + if( !is.core( cy ) ){ // cy is optional + opts = eles; + eles = cy; + cy = this.cy(); + } + + return new Collection( cy, eles, opts ); +}; + +elesfn.spawnSelf = function(){ + return this.spawn( this ); +}; + +elesfn.cy = function(){ + return this._private.cy; +}; + +elesfn.element = function(){ + return this[0]; +}; + +elesfn.collection = function(){ + if( is.collection( this ) ){ + return this; + } else { // an element + return new Collection( this._private.cy, [ this ] ); + } +}; + +elesfn.unique = function(){ + return new Collection( this._private.cy, this, { unique: true } ); +}; + +elesfn.hasElementWithId = function( id ){ + return !!this._private.ids[ id ]; +}; + +elesfn.getElementById = function( id ){ + var cy = this._private.cy; + var ele = this._private.ids[ id ]; + + return ele ? ele : new Collection( cy ); // get ele or empty collection +}; + +elesfn.poolIndex = function(){ + var cy = this._private.cy; + var eles = cy._private.elements; + var id = this._private.data.id; + + return eles._private.indexes[ id ]; +}; + +elesfn.json = function( obj ){ + var ele = this.element(); + var cy = this.cy(); + + if( ele == null && obj ){ return this; } // can't set to no eles + + if( ele == null ){ return undefined; } // can't get from no eles + + var p = ele._private; + + if( is.plainObject( obj ) ){ // set + + cy.startBatch(); + + if( obj.data ){ + ele.data( obj.data ); + } + + if( obj.position ){ + ele.position( obj.position ); + } + + // ignore group -- immutable + + var checkSwitch = function( k, trueFnName, falseFnName ){ + var obj_k = obj[ k ]; + + if( obj_k != null && obj_k !== p[ k ] ){ + if( obj_k ){ + ele[ trueFnName ](); + } else { + ele[ falseFnName ](); + } + } + }; + + checkSwitch( 'removed', 'remove', 'restore' ); + + checkSwitch( 'selected', 'select', 'unselect' ); + + checkSwitch( 'selectable', 'selectify', 'unselectify' ); + + checkSwitch( 'locked', 'lock', 'unlock' ); + + checkSwitch( 'grabbable', 'grabify', 'ungrabify' ); + + if( obj.classes != null ){ + ele.classes( obj.classes ); + } + + cy.endBatch(); + + return this; + + } else if( obj === undefined ){ // get + + var json = { + data: util.copy( p.data ), + position: util.copy( p.position ), + group: p.group, + removed: p.removed, + selected: p.selected, + selectable: p.selectable, + locked: p.locked, + grabbable: p.grabbable, + classes: null + }; + + json.classes = Object.keys( p.classes ).filter(function( cls ){ + return p.classes[cls]; + }).join(' '); + + return json; + } +}; + +elesfn.jsons = function(){ + var jsons = []; + + for( var i = 0; i < this.length; i++ ){ + var ele = this[ i ]; + var json = ele.json(); + + jsons.push( json ); + } + + return jsons; +}; + +elesfn.clone = function(){ + var cy = this.cy(); + var elesArr = []; + + for( var i = 0; i < this.length; i++ ){ + var ele = this[ i ]; + var json = ele.json(); + var clone = new Element( cy, json, false ); // NB no restore + + elesArr.push( clone ); + } + + return new Collection( cy, elesArr ); +}; +elesfn.copy = elesfn.clone; + +elesfn.restore = function( notifyRenderer ){ + var self = this; + var cy = self.cy(); + var cy_p = cy._private; + + if( notifyRenderer === undefined ){ + notifyRenderer = true; + } + + // create arrays of nodes and edges, since we need to + // restore the nodes first + var nodes = []; + var edges = []; + var elements; + for( var i = 0, l = self.length; i < l; i++ ){ + var ele = self[ i ]; + + if( !ele.removed() ){ + // don't need to handle this ele + continue; + } + + // keep nodes first in the array and edges after + if( ele.isNode() ){ // put to front of array if node + nodes.push( ele ); + } else { // put to end of array if edge + edges.push( ele ); + } + } + + elements = nodes.concat( edges ); + + var i; + var removeFromElements = function(){ + elements.splice( i, 1 ); + i--; + }; + + // now, restore each element + for( i = 0; i < elements.length; i++ ){ + var ele = elements[ i ]; + + var _private = ele._private; + var data = _private.data; + + // the traversal cache should start fresh when ele is added + _private.traversalCache = null; + + // set id and validate + if( data.id === undefined ){ + data.id = idFactory.generate( cy, ele ); + + } else if( is.number( data.id ) ){ + data.id = '' + data.id; // now it's a string + + } else if( is.emptyString( data.id ) || !is.string( data.id ) ){ + util.error( 'Can not create element with invalid string ID `' + data.id + '`' ); + + // can't create element if it has empty string as id or non-string id + removeFromElements(); + continue; + } else if( cy.hasElementWithId( data.id ) ){ + util.error( 'Can not create second element with ID `' + data.id + '`' ); + + // can't create element if one already has that id + removeFromElements(); + continue; + } + + var id = data.id; // id is finalised, now let's keep a ref + + if( ele.isNode() ){ // extra checks for nodes + var node = ele; + var pos = _private.position; + + // make sure the nodes have a defined position + + if( pos.x == null ){ + pos.x = 0; + } + + if( pos.y == null ){ + pos.y = 0; + } + } + + if( ele.isEdge() ){ // extra checks for edges + + var edge = ele; + var fields = [ 'source', 'target' ]; + var fieldsLength = fields.length; + var badSourceOrTarget = false; + for( var j = 0; j < fieldsLength; j++ ){ + + var field = fields[ j ]; + var val = data[ field ]; + + if( is.number( val ) ){ + val = data[ field ] = '' + data[ field ]; // now string + } + + if( val == null || val === '' ){ + // can't create if source or target is not defined properly + util.error( 'Can not create edge `' + id + '` with unspecified ' + field ); + badSourceOrTarget = true; + } else if( !cy.hasElementWithId( val ) ){ + // can't create edge if one of its nodes doesn't exist + util.error( 'Can not create edge `' + id + '` with nonexistant ' + field + ' `' + val + '`' ); + badSourceOrTarget = true; + } + } + + if( badSourceOrTarget ){ removeFromElements(); continue; } // can't create this + + var src = cy.getElementById( data.source ); + var tgt = cy.getElementById( data.target ); + + src._private.edges.push( edge ); + tgt._private.edges.push( edge ); + + edge._private.source = src; + edge._private.target = tgt; + } // if is edge + + // create mock ids / indexes maps for element so it can be used like collections + _private.ids = {}; + _private.ids[ id ] = ele; + _private.indexes = {}; + _private.indexes[ id ] = ele; + + _private.removed = false; + cy.addToPool( ele ); + } // for each element + + // do compound node sanity checks + for( var i = 0; i < nodes.length; i++ ){ // each node + var node = nodes[ i ]; + var data = node._private.data; + + if( is.number( data.parent ) ){ // then automake string + data.parent = '' + data.parent; + } + + var parentId = data.parent; + + var specifiedParent = parentId != null; + + if( specifiedParent ){ + var parent = cy.getElementById( parentId ); + + if( parent.empty() ){ + // non-existant parent; just remove it + data.parent = undefined; + } else { + var selfAsParent = false; + var ancestor = parent; + while( !ancestor.empty() ){ + if( node.same( ancestor ) ){ + // mark self as parent and remove from data + selfAsParent = true; + data.parent = undefined; // remove parent reference + + // exit or we loop forever + break; + } + + ancestor = ancestor.parent(); + } + + if( !selfAsParent ){ + // connect with children + parent[0]._private.children.push( node ); + node._private.parent = parent[0]; + + // let the core know we have a compound graph + cy_p.hasCompoundNodes = true; + } + } // else + } // if specified parent + } // for each node + + if( elements.length > 0 ){ + var restored = new Collection( cy, elements ); + + for( var i = 0; i < restored.length; i++ ){ + var ele = restored[i]; + + if( ele.isNode() ){ continue; } + + // adding an edge invalidates the traversal caches for the parallel edges + var pedges = ele.parallelEdges(); + for( var j = 0; j < pedges.length; j++ ){ + pedges[j]._private.traversalCache = null; + } + + // adding an edge invalidates the traversal cache for the connected nodes + ele.source()[0]._private.traversalCache = null; + ele.target()[0]._private.traversalCache = null; + } + + var toUpdateStyle; + + if( cy_p.hasCompoundNodes ){ + toUpdateStyle = restored.add( restored.connectedNodes() ).add( restored.parent() ); + } else { + toUpdateStyle = restored; + } + + toUpdateStyle.updateStyle( notifyRenderer ); + + if( notifyRenderer ){ + restored.rtrigger( 'add' ); + } else { + restored.trigger( 'add' ); + } + } + + return self; // chainability +}; + +elesfn.removed = function(){ + var ele = this[0]; + return ele && ele._private.removed; +}; + +elesfn.inside = function(){ + var ele = this[0]; + return ele && !ele._private.removed; +}; + +elesfn.remove = function( notifyRenderer ){ + var self = this; + var removed = []; + var elesToRemove = []; + var elesToRemoveIds = {}; + var cy = self._private.cy; + + if( notifyRenderer === undefined ){ + notifyRenderer = true; + } + + // add connected edges + function addConnectedEdges( node ){ + var edges = node._private.edges; + for( var i = 0; i < edges.length; i++ ){ + add( edges[ i ] ); + } + } + + + // add descendant nodes + function addChildren( node ){ + var children = node._private.children; + + for( var i = 0; i < children.length; i++ ){ + add( children[ i ] ); + } + } + + function add( ele ){ + var alreadyAdded = elesToRemoveIds[ ele.id() ]; + if( alreadyAdded ){ + return; + } else { + elesToRemoveIds[ ele.id() ] = true; + } + + if( ele.isNode() ){ + elesToRemove.push( ele ); // nodes are removed last + + addConnectedEdges( ele ); + addChildren( ele ); + } else { + elesToRemove.unshift( ele ); // edges are removed first + } + } + + // make the list of elements to remove + // (may be removing more than specified due to connected edges etc) + + for( var i = 0, l = self.length; i < l; i++ ){ + var ele = self[ i ]; + + add( ele ); + } + + function removeEdgeRef( node, edge ){ + var connectedEdges = node._private.edges; + + util.removeFromArray( connectedEdges, edge ); + + // removing an edges invalidates the traversal cache for its nodes + node._private.traversalCache = null; + } + + function removeParallelRefs( edge ){ + // removing an edge invalidates the traversal caches for the parallel edges + var pedges = edge.parallelEdges(); + for( var j = 0; j < pedges.length; j++ ){ + pedges[j]._private.traversalCache = null; + } + } + + var alteredParents = []; + alteredParents.ids = {}; + + function removeChildRef( parent, ele ){ + ele = ele[0]; + parent = parent[0]; + + var children = parent._private.children; + var pid = parent.id(); + + util.removeFromArray( children, ele ); + + if( !alteredParents.ids[ pid ] ){ + alteredParents.ids[ pid ] = true; + alteredParents.push( parent ); + } + } + + // remove from core pool + cy.removeFromPool( elesToRemove ); + + for( var i = 0; i < elesToRemove.length; i++ ){ + var ele = elesToRemove[ i ]; + + // mark as removed + ele._private.removed = true; + + // add to list of removed elements + removed.push( ele ); + + if( ele.isEdge() ){ // remove references to this edge in its connected nodes + var src = ele.source()[0]; + var tgt = ele.target()[0]; + + removeEdgeRef( src, ele ); + removeEdgeRef( tgt, ele ); + removeParallelRefs( ele ); + + } else { // remove reference to parent + var parent = ele.parent(); + + if( parent.length !== 0 ){ + removeChildRef( parent, ele ); + } + } + } + + // check to see if we have a compound graph or not + var elesStillInside = cy._private.elements; + cy._private.hasCompoundNodes = false; + for( var i = 0; i < elesStillInside.length; i++ ){ + var ele = elesStillInside[ i ]; + + if( ele.isParent() ){ + cy._private.hasCompoundNodes = true; + break; + } + } + + var removedElements = new Collection( this.cy(), removed ); + if( removedElements.size() > 0 ){ + // must manually notify since trigger won't do this automatically once removed + + if( notifyRenderer ){ + this.cy().notify( { + type: 'remove', + eles: removedElements + } ); + } + + removedElements.trigger( 'remove' ); + } + + // the parents who were modified by the removal need their style updated + for( var i = 0; i < alteredParents.length; i++ ){ + var ele = alteredParents[ i ]; + + if( !ele.removed() ){ + ele.updateStyle(); + } + } + + return new Collection( cy, removed ); +}; + +elesfn.move = function( struct ){ + var cy = this._private.cy; + + if( struct.source !== undefined || struct.target !== undefined ){ + var srcId = struct.source; + var tgtId = struct.target; + var srcExists = cy.hasElementWithId( srcId ); + var tgtExists = cy.hasElementWithId( tgtId ); + + if( srcExists || tgtExists ){ + var jsons = this.jsons(); + + this.remove(); + + for( var i = 0; i < jsons.length; i++ ){ + var json = jsons[i]; + var ele = this[i]; + + if( json.group === 'edges' ){ + if( srcExists ){ json.data.source = srcId; } + + if( tgtExists ){ json.data.target = tgtId; } + + json.scratch = ele._private.scratch; + } + } + + return cy.add( jsons ); + } + + } else if( struct.parent !== undefined ){ // move node to new parent + var parentId = struct.parent; + var parentExists = parentId === null || cy.hasElementWithId( parentId ); + + if( parentExists ){ + var jsons = this.jsons(); + var descs = this.descendants(); + var descsEtc = descs.union( descs.union( this ).connectedEdges() ); + + this.remove(); // NB: also removes descendants and their connected edges + + for( var i = 0; i < this.length; i++ ){ + var json = jsons[i]; + var ele = this[i]; + + if( json.group === 'nodes' ){ + json.data.parent = parentId === null ? undefined : parentId; + + json.scratch = ele._private.scratch; + } + } + + return cy.add( jsons ).union( descsEtc.restore() ); + } + } + + return this; // if nothing done +}; + +[ + _dereq_( './algorithms' ), + _dereq_( './animation' ), + _dereq_( './class' ), + _dereq_( './comparators' ), + _dereq_( './compounds' ), + _dereq_( './data' ), + _dereq_( './degree' ), + _dereq_( './dimensions' ), + _dereq_( './events' ), + _dereq_( './filter' ), + _dereq_( './group' ), + _dereq_( './index' ), + _dereq_( './iteration' ), + _dereq_( './layout' ), + _dereq_( './style' ), + _dereq_( './switch-functions' ), + _dereq_( './traversing' ) +].forEach( function( props ){ + util.extend( elesfn, props ); +} ); + +module.exports = Collection; + +},{"../is":83,"../util":100,"./algorithms":11,"./animation":15,"./class":16,"./comparators":17,"./compounds":18,"./data":19,"./degree":20,"./dimensions":21,"./element":22,"./events":23,"./filter":24,"./group":25,"./index":26,"./iteration":27,"./layout":28,"./style":29,"./switch-functions":30,"./traversing":31}],27:[function(_dereq_,module,exports){ +'use strict'; + +var is = _dereq_( '../is' ); +var zIndexSort = _dereq_( './zsort' ); + +var elesfn = ({ + each: function( fn ){ + if( is.fn( fn ) ){ + for( var i = 0; i < this.length; i++ ){ + var ele = this[ i ]; + var ret = fn.apply( ele, [ i, ele ] ); + + if( ret === false ){ break; } // exit each early on return false + } + } + return this; + }, + + forEach: function( fn, thisArg ){ + if( is.fn( fn ) ){ + + for( var i = 0; i < this.length; i++ ){ + var ele = this[ i ]; + var ret = thisArg ? fn.apply( thisArg, [ ele, i, this ] ) : fn( ele, i, this ); + + if( ret === false ){ break; } // exit each early on return false + } + } + + return this; + }, + + toArray: function(){ + var array = []; + + for( var i = 0; i < this.length; i++ ){ + array.push( this[ i ] ); + } + + return array; + }, + + slice: function( start, end ){ + var array = []; + var thisSize = this.length; + + if( end == null ){ + end = thisSize; + } + + if( start == null ){ + start = 0; + } + + if( start < 0 ){ + start = thisSize + start; + } + + if( end < 0 ){ + end = thisSize + end; + } + + for( var i = start; i >= 0 && i < end && i < thisSize; i++ ){ + array.push( this[ i ] ); + } + + return this.spawn( array ); + }, + + size: function(){ + return this.length; + }, + + eq: function( i ){ + return this[ i ] || this.spawn(); + }, + + first: function(){ + return this[0] || this.spawn(); + }, + + last: function(){ + return this[ this.length - 1 ] || this.spawn(); + }, + + empty: function(){ + return this.length === 0; + }, + + nonempty: function(){ + return !this.empty(); + }, + + sort: function( sortFn ){ + if( !is.fn( sortFn ) ){ + return this; + } + + var sorted = this.toArray().sort( sortFn ); + + return this.spawn( sorted ); + }, + + sortByZIndex: function(){ + return this.sort( zIndexSort ); + }, + + zDepth: function(){ + var ele = this[0]; + if( !ele ){ return undefined; } + + // var cy = ele.cy(); + var _p = ele._private; + var group = _p.group; + + if( group === 'nodes' ){ + var depth = _p.data.parent ? ele.parents().size() : 0; + + if( !ele.isParent() ){ + return Number.MAX_VALUE; // childless nodes always on top + } + + return depth; + } else { + var src = _p.source; + var tgt = _p.target; + var srcDepth = src.zDepth(); + var tgtDepth = tgt.zDepth(); + + return Math.max( srcDepth, tgtDepth, 0 ); // depth of deepest parent + } + } +}); + +module.exports = elesfn; + +},{"../is":83,"./zsort":32}],28:[function(_dereq_,module,exports){ +'use strict'; + +var is = _dereq_( '../is' ); +var util = _dereq_( '../util' ); +var Promise = _dereq_('../promise'); + +var elesfn = ({ + + // using standard layout options, apply position function (w/ or w/o animation) + layoutPositions: function( layout, options, fn ){ + var nodes = this.nodes(); + var cy = this.cy(); + + layout.trigger( { type: 'layoutstart', layout: layout } ); + + layout.animations = []; + + if( options.animate ){ + for( var i = 0; i < nodes.length; i++ ){ + var node = nodes[ i ]; + + var newPos = fn.call( node, i, node ); + var pos = node.position(); + + if( !is.number( pos.x ) || !is.number( pos.y ) ){ + node.silentPosition( { x: 0, y: 0 } ); + } + + var ani = node.animation( { + position: newPos, + duration: options.animationDuration, + easing: options.animationEasing + } ); + + layout.animations.push( ani ); + + ani.play(); + } + + var onStep; + cy.on( 'step.*', ( onStep = function(){ + if( options.fit ){ + cy.fit( options.eles, options.padding ); + } + }) ); + + layout.one('layoutstop', function(){ + cy.off('step.*', onStep); + }); + + layout.one( 'layoutready', options.ready ); + layout.trigger( { type: 'layoutready', layout: layout } ); + + Promise.all( layout.animations.map(function( ani ){ + return ani.promise(); + }) ).then(function(){ + cy.off('step.*', onStep); + + if( options.zoom != null ){ + cy.zoom( options.zoom ); + } + + if( options.pan ){ + cy.pan( options.pan ); + } + + if( options.fit ){ + cy.fit( options.eles, options.padding ); + } + + layout.one( 'layoutstop', options.stop ); + layout.trigger( { type: 'layoutstop', layout: layout } ); + }); + } else { + nodes.positions( fn ); + + if( options.fit ){ + cy.fit( options.eles, options.padding ); + } + + if( options.zoom != null ){ + cy.zoom( options.zoom ); + } + + if( options.pan ){ + cy.pan( options.pan ); + } + + layout.one( 'layoutready', options.ready ); + layout.trigger( { type: 'layoutready', layout: layout } ); + + layout.one( 'layoutstop', options.stop ); + layout.trigger( { type: 'layoutstop', layout: layout } ); + } + + return this; // chaining + }, + + layout: function( options ){ + var cy = this.cy(); + + cy.layout( util.extend( {}, options, { + eles: this + } ) ); + + return this; + }, + + makeLayout: function( options ){ + var cy = this.cy(); + + return cy.makeLayout( util.extend( {}, options, { + eles: this + } ) ); + } + +}); + +// aliases: +elesfn.createLayout = elesfn.makeLayout; + +module.exports = elesfn; + +},{"../is":83,"../promise":86,"../util":100}],29:[function(_dereq_,module,exports){ +'use strict'; + +var is = _dereq_( '../is' ); + +var elesfn = ({ + + // fully updates (recalculates) the style for the elements + updateStyle: function( notifyRenderer ){ + var cy = this._private.cy; + + if( !cy.styleEnabled() ){ return this; } + + if( cy._private.batchingStyle ){ + var bEles = cy._private.batchStyleEles; + + bEles.merge( this ); + + return this; // chaining and exit early when batching + } + + var style = cy.style(); + notifyRenderer = notifyRenderer || notifyRenderer === undefined ? true : false; + + style.apply( this ); + + var updatedCompounds = this.updateCompoundBounds(); + var toNotify = updatedCompounds.length > 0 ? this.add( updatedCompounds ) : this; + + if( notifyRenderer ){ + toNotify.rtrigger( 'style' ); // let renderer know we changed style + } else { + toNotify.trigger( 'style' ); // just fire the event + } + return this; // chaining + }, + + // just update the mappers in the elements' styles; cheaper than eles.updateStyle() + updateMappers: function( notifyRenderer ){ + var cy = this._private.cy; + var style = cy.style(); + notifyRenderer = notifyRenderer || notifyRenderer === undefined ? true : false; + + if( !cy.styleEnabled() ){ return this; } + + style.updateMappers( this ); + + var updatedCompounds = this.updateCompoundBounds(); + var toNotify = updatedCompounds.length > 0 ? this.add( updatedCompounds ) : this; + + if( notifyRenderer ){ + toNotify.rtrigger( 'style' ); // let renderer know we changed style + } else { + toNotify.trigger( 'style' ); // just fire the event + } + return this; // chaining + }, + + // get the internal parsed style object for the specified property + parsedStyle: function( property ){ + var ele = this[0]; + if( !ele.cy().styleEnabled() ){ return; } + + if( ele ){ + return ele._private.style[ property ] || ele.cy().style().getDefaultProperty( property ); + } + }, + + // get the specified css property as a rendered value (i.e. on-screen value) + // or get the whole rendered style if no property specified (NB doesn't allow setting) + renderedStyle: function( property ){ + var cy = this.cy(); + if( !cy.styleEnabled() ){ return this; } + + var ele = this[0]; + + if( ele ){ + var renstyle = ele.cy().style().getRenderedStyle( ele ); + + if( property === undefined ){ + return renstyle; + } else { + return renstyle[ property ]; + } + } + }, + + // read the calculated css style of the element or override the style (via a bypass) + style: function( name, value ){ + var cy = this.cy(); + + if( !cy.styleEnabled() ){ return this; } + + var updateTransitions = false; + var style = cy.style(); + + if( is.plainObject( name ) ){ // then extend the bypass + var props = name; + style.applyBypass( this, props, updateTransitions ); + + var updatedCompounds = this.updateCompoundBounds(); + var toNotify = updatedCompounds.length > 0 ? this.add( updatedCompounds ) : this; + toNotify.rtrigger( 'style' ); // let the renderer know we've updated style + + } else if( is.string( name ) ){ + + if( value === undefined ){ // then get the property from the style + var ele = this[0]; + + if( ele ){ + return style.getStylePropertyValue( ele, name ); + } else { // empty collection => can't get any value + return; + } + + } else { // then set the bypass with the property value + style.applyBypass( this, name, value, updateTransitions ); + + var updatedCompounds = this.updateCompoundBounds(); + var toNotify = updatedCompounds.length > 0 ? this.add( updatedCompounds ) : this; + toNotify.rtrigger( 'style' ); // let the renderer know we've updated style + } + + } else if( name === undefined ){ + var ele = this[0]; + + if( ele ){ + return style.getRawStyle( ele ); + } else { // empty collection => can't get any value + return; + } + } + + return this; // chaining + }, + + removeStyle: function( names ){ + var cy = this.cy(); + + if( !cy.styleEnabled() ){ return this; } + + var updateTransitions = false; + var style = cy.style(); + var eles = this; + + if( names === undefined ){ + for( var i = 0; i < eles.length; i++ ){ + var ele = eles[ i ]; + + style.removeAllBypasses( ele, updateTransitions ); + } + } else { + names = names.split( /\s+/ ); + + for( var i = 0; i < eles.length; i++ ){ + var ele = eles[ i ]; + + style.removeBypasses( ele, names, updateTransitions ); + } + } + + var updatedCompounds = this.updateCompoundBounds(); + var toNotify = updatedCompounds.length > 0 ? this.add( updatedCompounds ) : this; + toNotify.rtrigger( 'style' ); // let the renderer know we've updated style + + return this; // chaining + }, + + show: function(){ + this.css( 'display', 'element' ); + return this; // chaining + }, + + hide: function(){ + this.css( 'display', 'none' ); + return this; // chaining + }, + + visible: function(){ + var cy = this.cy(); + if( !cy.styleEnabled() ){ return true; } + + var ele = this[0]; + var hasCompoundNodes = cy.hasCompoundNodes(); + + if( ele ){ + if( + ele.pstyle( 'visibility' ).value !== 'visible' + || ele.pstyle( 'display' ).value !== 'element' + ){ + return false; + } + + if( ele._private.group === 'nodes' ){ + if( !hasCompoundNodes ){ return true; } + + var parents = ele._private.data.parent ? ele.parents() : null; + + if( parents ){ + for( var i = 0; i < parents.length; i++ ){ + var parent = parents[ i ]; + var pVis = parent.pstyle( 'visibility' ).value; + var pDis = parent.pstyle( 'display' ).value; + + if( pVis !== 'visible' || pDis !== 'element' ){ + return false; + } + } + } + + return true; + } else { + var src = ele._private.source; + var tgt = ele._private.target; + + return src.visible() && tgt.visible(); + } + + } + }, + + hidden: function(){ + var ele = this[0]; + + if( ele ){ + return !ele.visible(); + } + }, + + effectiveOpacity: function(){ + var cy = this.cy(); + if( !cy.styleEnabled() ){ return 1; } + + var hasCompoundNodes = cy.hasCompoundNodes(); + var ele = this[0]; + + if( ele ){ + var _p = ele._private; + var parentOpacity = ele.pstyle( 'opacity' ).value; + + if( !hasCompoundNodes ){ return parentOpacity; } + + var parents = !_p.data.parent ? null : ele.parents(); + + if( parents ){ + for( var i = 0; i < parents.length; i++ ){ + var parent = parents[ i ]; + var opacity = parent.pstyle( 'opacity' ).value; + + parentOpacity = opacity * parentOpacity; + } + } + + return parentOpacity; + } + }, + + transparent: function(){ + var cy = this.cy(); + if( !cy.styleEnabled() ){ return false; } + + var ele = this[0]; + var hasCompoundNodes = ele.cy().hasCompoundNodes(); + + if( ele ){ + if( !hasCompoundNodes ){ + return ele.pstyle( 'opacity' ).value === 0; + } else { + return ele.effectiveOpacity() === 0; + } + } + }, + + backgrounding: function(){ + var cy = this.cy(); + if( !cy.styleEnabled() ){ return false; } + + var ele = this[0]; + + return ele._private.backgrounding ? true : false; + } + +}); + + +elesfn.bypass = elesfn.css = elesfn.style; +elesfn.renderedCss = elesfn.renderedStyle; +elesfn.removeBypass = elesfn.removeCss = elesfn.removeStyle; +elesfn.pstyle = elesfn.parsedStyle; + +module.exports = elesfn; + +},{"../is":83}],30:[function(_dereq_,module,exports){ +'use strict'; + +var elesfn = {}; + +function defineSwitchFunction( params ){ + return function(){ + var args = arguments; + var changedEles = []; + + // e.g. cy.nodes().select( data, handler ) + if( args.length === 2 ){ + var data = args[0]; + var handler = args[1]; + this.on( params.event, data, handler ); + } + + // e.g. cy.nodes().select( handler ) + else if( args.length === 1 ){ + var handler = args[0]; + this.on( params.event, handler ); + } + + // e.g. cy.nodes().select() + else if( args.length === 0 ){ + for( var i = 0; i < this.length; i++ ){ + var ele = this[ i ]; + var able = !params.ableField || ele._private[ params.ableField ]; + var changed = ele._private[ params.field ] != params.value; + + if( params.overrideAble ){ + var overrideAble = params.overrideAble( ele ); + + if( overrideAble !== undefined ){ + able = overrideAble; + + if( !overrideAble ){ return this; } // to save cycles assume not able for all on override + } + } + + if( able ){ + ele._private[ params.field ] = params.value; + + if( changed ){ + changedEles.push( ele ); + } + } + } + + var changedColl = this.spawn( changedEles ); + changedColl.updateStyle(); // change of state => possible change of style + changedColl.trigger( params.event ); + } + + return this; + }; +} + +function defineSwitchSet( params ){ + elesfn[ params.field ] = function(){ + var ele = this[0]; + + if( ele ){ + if( params.overrideField ){ + var val = params.overrideField( ele ); + + if( val !== undefined ){ + return val; + } + } + + return ele._private[ params.field ]; + } + }; + + elesfn[ params.on ] = defineSwitchFunction( { + event: params.on, + field: params.field, + ableField: params.ableField, + overrideAble: params.overrideAble, + value: true + } ); + + elesfn[ params.off ] = defineSwitchFunction( { + event: params.off, + field: params.field, + ableField: params.ableField, + overrideAble: params.overrideAble, + value: false + } ); +} + +defineSwitchSet( { + field: 'locked', + overrideField: function( ele ){ + return ele.cy().autolock() ? true : undefined; + }, + on: 'lock', + off: 'unlock' +} ); + +defineSwitchSet( { + field: 'grabbable', + overrideField: function( ele ){ + return ele.cy().autoungrabify() ? false : undefined; + }, + on: 'grabify', + off: 'ungrabify' +} ); + +defineSwitchSet( { + field: 'selected', + ableField: 'selectable', + overrideAble: function( ele ){ + return ele.cy().autounselectify() ? false : undefined; + }, + on: 'select', + off: 'unselect' +} ); + +defineSwitchSet( { + field: 'selectable', + overrideField: function( ele ){ + return ele.cy().autounselectify() ? false : undefined; + }, + on: 'selectify', + off: 'unselectify' +} ); + +elesfn.deselect = elesfn.unselect; + +elesfn.grabbed = function(){ + var ele = this[0]; + if( ele ){ + return ele._private.grabbed; + } +}; + +defineSwitchSet( { + field: 'active', + on: 'activate', + off: 'unactivate' +} ); + +elesfn.inactive = function(){ + var ele = this[0]; + if( ele ){ + return !ele._private.active; + } +}; + +module.exports = elesfn; + +},{}],31:[function(_dereq_,module,exports){ +'use strict'; + +var util = _dereq_( '../util' ); +var is = _dereq_( '../is' ); + +var elesfn = {}; + +var cache = function( fn, name ){ + return function traversalCache( arg1, arg2, arg3, arg4 ){ + var selectorOrEles = arg1; + var eles = this; + var key; + + if( selectorOrEles == null ){ + key = 'null'; + } else if( is.elementOrCollection( selectorOrEles ) && selectorOrEles.length === 1 ){ + key = '#' + selectorOrEles.id(); + } + + if( eles.length === 1 && key ){ + var _p = eles[0]._private; + var tch = _p.traversalCache = _p.traversalCache || {}; + var ch = tch[ name ] = tch[ name ] || {}; + var cacheHit = ch[ key ]; + + if( cacheHit ){ + return cacheHit; + } else { + return ( ch[ key ] = fn.call( eles, arg1, arg2, arg3, arg4 ) ); + } + } else { + return fn.call( eles, arg1, arg2, arg3, arg4 ); + } + }; +}; + +// DAG functions +//////////////// + +var defineDagExtremity = function( params ){ + return function dagExtremityImpl( selector ){ + var eles = this; + var ret = []; + + for( var i = 0; i < eles.length; i++ ){ + var ele = eles[ i ]; + if( !ele.isNode() ){ + continue; + } + + var disqualified = false; + var edges = ele.connectedEdges(); + + for( var j = 0; j < edges.length; j++ ){ + var edge = edges[j]; + var src = edge.source(); + var tgt = edge.target(); + + if( + ( params.noIncomingEdges && tgt === ele && src !== ele ) + || ( params.noOutgoingEdges && src === ele && tgt !== ele ) + ){ + disqualified = true; + break; + } + } + + if( !disqualified ){ + ret.push( ele ); + } + } + + return this.spawn( ret, { unique: true } ).filter( selector ); + }; +}; + +var defineDagOneHop = function( params ){ + return function( selector ){ + var eles = this; + var oEles = []; + + for( var i = 0; i < eles.length; i++ ){ + var ele = eles[ i ]; + + if( !ele.isNode() ){ continue; } + + var edges = ele.connectedEdges(); + for( var j = 0; j < edges.length; j++ ){ + var edge = edges[ j ]; + var src = edge.source(); + var tgt = edge.target(); + + if( params.outgoing && src === ele ){ + oEles.push( edge ); + oEles.push( tgt ); + } else if( params.incoming && tgt === ele ){ + oEles.push( edge ); + oEles.push( src ); + } + } + } + + return this.spawn( oEles, { unique: true } ).filter( selector ); + }; +}; + +var defineDagAllHops = function( params ){ + return function( selector ){ + var eles = this; + var sEles = []; + var sElesIds = {}; + + for( ;; ){ + var next = params.outgoing ? eles.outgoers() : eles.incomers(); + + if( next.length === 0 ){ break; } // done if none left + + var newNext = false; + for( var i = 0; i < next.length; i++ ){ + var n = next[ i ]; + var nid = n.id(); + + if( !sElesIds[ nid ] ){ + sElesIds[ nid ] = true; + sEles.push( n ); + newNext = true; + } + } + + if( !newNext ){ break; } // done if touched all outgoers already + + eles = next; + } + + return this.spawn( sEles, { unique: true } ).filter( selector ); + }; +}; + +util.extend( elesfn, { + // get the root nodes in the DAG + roots: defineDagExtremity({ noIncomingEdges: true }), + + // get the leaf nodes in the DAG + leaves: defineDagExtremity({ noOutgoingEdges: true }), + + // normally called children in graph theory + // these nodes =edges=> outgoing nodes + outgoers: cache( defineDagOneHop({ outgoing: true }) , 'outgoers' ), + + // aka DAG descendants + successors: defineDagAllHops({ outgoing: true }), + + // normally called parents in graph theory + // these nodes <=edges= incoming nodes + incomers: cache( defineDagOneHop({ incoming: true }), 'incomers' ), + + // aka DAG ancestors + predecessors: defineDagAllHops({ incoming: true }) +} ); + + +// Neighbourhood functions +////////////////////////// + +util.extend( elesfn, { + neighborhood: cache(function( selector ){ + var elements = []; + var nodes = this.nodes(); + + for( var i = 0; i < nodes.length; i++ ){ // for all nodes + var node = nodes[ i ]; + var connectedEdges = node.connectedEdges(); + + // for each connected edge, add the edge and the other node + for( var j = 0; j < connectedEdges.length; j++ ){ + var edge = connectedEdges[ j ]; + var src = edge.source(); + var tgt = edge.target(); + var otherNode = node === src ? tgt : src; + + // need check in case of loop + if( otherNode.length > 0 ){ + elements.push( otherNode[0] ); // add node 1 hop away + } + + // add connected edge + elements.push( edge[0] ); + } + + } + + return ( this.spawn( elements, { unique: true } ) ).filter( selector ); + }, 'neighborhood'), + + closedNeighborhood: function( selector ){ + return this.neighborhood().add( this ).filter( selector ); + }, + + openNeighborhood: function( selector ){ + return this.neighborhood( selector ); + } +} ); + +// aliases +elesfn.neighbourhood = elesfn.neighborhood; +elesfn.closedNeighbourhood = elesfn.closedNeighborhood; +elesfn.openNeighbourhood = elesfn.openNeighborhood; + +// Edge functions +///////////////// + +util.extend( elesfn, { + source: cache(function sourceImpl( selector ){ + var ele = this[0]; + var src; + + if( ele ){ + src = ele._private.source || ele.cy().collection(); + } + + return src && selector ? src.filter( selector ) : src; + }, 'source'), + + target: cache(function targetImpl( selector ){ + var ele = this[0]; + var tgt; + + if( ele ){ + tgt = ele._private.target || ele.cy().collection(); + } + + return tgt && selector ? tgt.filter( selector ) : tgt; + }, 'target'), + + sources: defineSourceFunction( { + attr: 'source' + } ), + + targets: defineSourceFunction( { + attr: 'target' + } ) +} ); + +function defineSourceFunction( params ){ + return function sourceImpl( selector ){ + var sources = []; + + for( var i = 0; i < this.length; i++ ){ + var ele = this[ i ]; + var src = ele._private[ params.attr ]; + + if( src ){ + sources.push( src ); + } + } + + return this.spawn( sources, { unique: true } ).filter( selector ); + }; +} + +util.extend( elesfn, { + edgesWith: cache( defineEdgesWithFunction(), 'edgesWith', true ), + + edgesTo: cache( defineEdgesWithFunction( { + thisIsSrc: true + } ), 'edgesTo', true ) +} ); + +function defineEdgesWithFunction( params ){ + + return function edgesWithImpl( otherNodes ){ + var elements = []; + var cy = this._private.cy; + var p = params || {}; + + // get elements if a selector is specified + if( is.string( otherNodes ) ){ + otherNodes = cy.$( otherNodes ); + } + + var thisIds = this._private.ids; + var otherIds = otherNodes._private.ids; + + for( var h = 0; h < otherNodes.length; h++ ){ + var edges = otherNodes[ h ]._private.edges; + + for( var i = 0; i < edges.length; i++ ){ + var edge = edges[ i ]; + var edgeData = edge._private.data; + var thisToOther = thisIds[ edgeData.source ] && otherIds[ edgeData.target ]; + var otherToThis = otherIds[ edgeData.source ] && thisIds[ edgeData.target ]; + var edgeConnectsThisAndOther = thisToOther || otherToThis; + + if( !edgeConnectsThisAndOther ){ continue; } + + if( p.thisIsSrc || p.thisIsTgt ){ + if( p.thisIsSrc && !thisToOther ){ continue; } + + if( p.thisIsTgt && !otherToThis ){ continue; } + } + + elements.push( edge ); + } + } + + return this.spawn( elements, { unique: true } ); + }; +} + +util.extend( elesfn, { + connectedEdges: cache(function( selector ){ + var retEles = []; + + var eles = this; + for( var i = 0; i < eles.length; i++ ){ + var node = eles[ i ]; + if( !node.isNode() ){ continue; } + + var edges = node._private.edges; + + for( var j = 0; j < edges.length; j++ ){ + var edge = edges[ j ]; + retEles.push( edge ); + } + } + + return this.spawn( retEles, { unique: true } ).filter( selector ); + }, 'connectedEdges'), + + connectedNodes: cache(function( selector ){ + var retEles = []; + + var eles = this; + for( var i = 0; i < eles.length; i++ ){ + var edge = eles[ i ]; + if( !edge.isEdge() ){ continue; } + + retEles.push( edge.source()[0] ); + retEles.push( edge.target()[0] ); + } + + return this.spawn( retEles, { unique: true } ).filter( selector ); + }, 'connectedNodes'), + + parallelEdges: cache( defineParallelEdgesFunction(), 'parallelEdges' ), + + codirectedEdges: cache( defineParallelEdgesFunction( { + codirected: true + } ), 'codirectedEdges' ) +} ); + +function defineParallelEdgesFunction( params ){ + var defaults = { + codirected: false + }; + params = util.extend( {}, defaults, params ); + + return function parallelEdgesImpl( selector ){ // micro-optimised for renderer + var elements = []; + var edges = this.edges(); + var p = params; + + // look at all the edges in the collection + for( var i = 0; i < edges.length; i++ ){ + var edge1 = edges[ i ]; + var edge1_p = edge1._private; + var src1 = edge1_p.source; + var srcid1 = src1._private.data.id; + var tgtid1 = edge1_p.data.target; + var srcEdges1 = src1._private.edges; + + // look at edges connected to the src node of this edge + for( var j = 0; j < srcEdges1.length; j++ ){ + var edge2 = srcEdges1[ j ]; + var edge2data = edge2._private.data; + var tgtid2 = edge2data.target; + var srcid2 = edge2data.source; + + var codirected = tgtid2 === tgtid1 && srcid2 === srcid1; + var oppdirected = srcid1 === tgtid2 && tgtid1 === srcid2; + + if( (p.codirected && codirected) || (!p.codirected && (codirected || oppdirected)) ){ + elements.push( edge2 ); + } + } + } + + return this.spawn( elements, { unique: true } ).filter( selector ); + }; + +} + +// Misc functions +///////////////// + +util.extend( elesfn, { + components: function(){ + var self = this; + var cy = self.cy(); + var visited = self.spawn(); + var unvisited = self.nodes().spawnSelf(); + var components = []; + + var visitInComponent = function( node, component ){ + visited.merge( node ); + unvisited.unmerge( node ); + component.merge( node ); + }; + + if( unvisited.empty() ){ return self.spawn(); } + + do { + var component = cy.collection(); + components.push( component ); + + var root = unvisited[0]; + visitInComponent( root, component ); + + self.bfs({ + directed: false, + roots: root, + visit: function( i, depth, v, e, u ){ + visitInComponent( v, component ); + } + } ); + + } while( unvisited.length > 0 ); + + return components.map(function( component ){ + var connectedEdges = component.connectedEdges().stdFilter(function( edge ){ + return component.anySame( edge.source() ) && component.anySame( edge.target() ); + }); + + return component.union( connectedEdges ); + }); + } +} ); + +module.exports = elesfn; + +},{"../is":83,"../util":100}],32:[function(_dereq_,module,exports){ +'use strict'; + +var zIndexSort = function( a, b ){ + var cy = a.cy(); + var zDiff = a.pstyle( 'z-index' ).value - b.pstyle( 'z-index' ).value; + var depthA = 0; + var depthB = 0; + var hasCompoundNodes = cy.hasCompoundNodes(); + var aIsNode = a.isNode(); + var aIsEdge = !aIsNode; + var bIsNode = b.isNode(); + var bIsEdge = !bIsNode; + + // no need to calculate element depth if there is no compound node + if( hasCompoundNodes ){ + depthA = a.zDepth(); + depthB = b.zDepth(); + } + + var depthDiff = depthA - depthB; + var sameDepth = depthDiff === 0; + + if( sameDepth ){ + + if( aIsNode && bIsEdge ){ + return 1; // 'a' is a node, it should be drawn later + + } else if( aIsEdge && bIsNode ){ + return -1; // 'a' is an edge, it should be drawn first + + } else { // both nodes or both edges + if( zDiff === 0 ){ // same z-index => compare indices in the core (order added to graph w/ last on top) + return a.poolIndex() - b.poolIndex(); + } else { + return zDiff; + } + } + + // elements on different level + } else { + return depthDiff; // deeper element should be drawn later + } + +}; + +module.exports = zIndexSort; + +},{}],33:[function(_dereq_,module,exports){ +'use strict'; + +var is = _dereq_( '../is' ); +var util = _dereq_( '../util' ); +var Collection = _dereq_( '../collection' ); +var Element = _dereq_( '../collection/element' ); + +var corefn = { + add: function( opts ){ + + var elements; + var cy = this; + + // add the elements + if( is.elementOrCollection( opts ) ){ + var eles = opts; + + if( eles._private.cy === cy ){ // same instance => just restore + elements = eles.restore(); + + } else { // otherwise, copy from json + var jsons = []; + + for( var i = 0; i < eles.length; i++ ){ + var ele = eles[ i ]; + jsons.push( ele.json() ); + } + + elements = new Collection( cy, jsons ); + } + } + + // specify an array of options + else if( is.array( opts ) ){ + var jsons = opts; + + elements = new Collection( cy, jsons ); + } + + // specify via opts.nodes and opts.edges + else if( is.plainObject( opts ) && (is.array( opts.nodes ) || is.array( opts.edges )) ){ + var elesByGroup = opts; + var jsons = []; + + var grs = [ 'nodes', 'edges' ]; + for( var i = 0, il = grs.length; i < il; i++ ){ + var group = grs[ i ]; + var elesArray = elesByGroup[ group ]; + + if( is.array( elesArray ) ){ + + for( var j = 0, jl = elesArray.length; j < jl; j++ ){ + var json = util.extend( { group: group }, elesArray[ j ] ); + + jsons.push( json ); + } + } + } + + elements = new Collection( cy, jsons ); + } + + // specify options for one element + else { + var json = opts; + elements = (new Element( cy, json )).collection(); + } + + return elements; + }, + + remove: function( collection ){ + if( is.elementOrCollection( collection ) ){ + // already have right ref + } else if( is.string( collection ) ){ + var selector = collection; + collection = this.$( selector ); + } + + return collection.remove(); + }, + + load: function( elements, onload, ondone ){ + var cy = this; + + cy.notifications( false ); + + // remove old elements + var oldEles = cy.mutableElements(); + if( oldEles.length > 0 ){ + oldEles.remove(); + } + + if( elements != null ){ + if( is.plainObject( elements ) || is.array( elements ) ){ + cy.add( elements ); + } + } + + cy.one( 'layoutready', function( e ){ + cy.notifications( true ); + cy.trigger( e ); // we missed this event by turning notifications off, so pass it on + + cy.notify( { + type: 'load', + eles: cy.mutableElements() + } ); + + cy.one( 'load', onload ); + cy.trigger( 'load' ); + } ).one( 'layoutstop', function(){ + cy.one( 'done', ondone ); + cy.trigger( 'done' ); + } ); + + var layoutOpts = util.extend( {}, cy._private.options.layout ); + layoutOpts.eles = cy.elements(); + + cy.layout( layoutOpts ); + + return this; + } +}; + +module.exports = corefn; + +},{"../collection":26,"../collection/element":22,"../is":83,"../util":100}],34:[function(_dereq_,module,exports){ +'use strict'; + +var define = _dereq_( '../define' ); +var util = _dereq_( '../util' ); +var is = _dereq_( '../is' ); + +var corefn = ({ + + // pull in animation functions + animate: define.animate(), + animation: define.animation(), + animated: define.animated(), + clearQueue: define.clearQueue(), + delay: define.delay(), + delayAnimation: define.delayAnimation(), + stop: define.stop(), + + addToAnimationPool: function( eles ){ + var cy = this; + + if( !cy.styleEnabled() ){ return; } // save cycles when no style used + + cy._private.aniEles.merge( eles ); + }, + + stopAnimationLoop: function(){ + this._private.animationsRunning = false; + }, + + startAnimationLoop: function(){ + var cy = this; + + cy._private.animationsRunning = true; + + if( !cy.styleEnabled() ){ return; } // save cycles when no style used + + // NB the animation loop will exec in headless environments if style enabled + // and explicit cy.destroy() is necessary to stop the loop + + function globalAnimationStep(){ + if( !cy._private.animationsRunning ){ return; } + + util.requestAnimationFrame( function animationStep( now ){ + handleElements( now ); + globalAnimationStep(); + } ); + } + + var renderer = cy.renderer(); + + if( renderer && renderer.beforeRender ){ // let the renderer schedule animations + renderer.beforeRender( function rendererAnimationStep( willDraw, now ){ + handleElements( now ); + }, renderer.beforeRenderPriorities.animations ); + } else { // manage the animation loop ourselves + globalAnimationStep(); // first call + } + + function handleElements( now ){ + var eles = cy._private.aniEles; + var doneEles = []; + + function handleElement( ele, isCore ){ + var _p = ele._private; + var current = _p.animation.current; + var queue = _p.animation.queue; + var ranAnis = false; + + // if nothing currently animating, get something from the queue + if( current.length === 0 ){ + var next = queue.shift(); + + if( next ){ + current.push( next ); + } + } + + var callbacks = function( callbacks ){ + for( var j = callbacks.length - 1; j >= 0; j-- ){ + var cb = callbacks[ j ]; + + cb(); + } + + callbacks.splice( 0, callbacks.length ); + }; + + // step and remove if done + for( var i = current.length - 1; i >= 0; i-- ){ + var ani = current[ i ]; + var ani_p = ani._private; + + if( ani_p.stopped ){ + current.splice( i, 1 ); + + ani_p.hooked = false; + ani_p.playing = false; + ani_p.started = false; + + callbacks( ani_p.frames ); + + continue; + } + + if( !ani_p.playing && !ani_p.applying ){ continue; } + + // an apply() while playing shouldn't do anything + if( ani_p.playing && ani_p.applying ){ + ani_p.applying = false; + } + + if( !ani_p.started ){ + startAnimation( ele, ani, now ); + } + + step( ele, ani, now, isCore ); + + if( is.fn( ani_p.step ) ){ + ani_p.step.call( ele, now ); + } + + if( ani_p.applying ){ + ani_p.applying = false; + } + + callbacks( ani_p.frames ); + + if( ani.completed() ){ + current.splice( i, 1 ); + + ani_p.hooked = false; + ani_p.playing = false; + ani_p.started = false; + + callbacks( ani_p.completes ); + } + + ranAnis = true; + } + + if( !isCore && current.length === 0 && queue.length === 0 ){ + doneEles.push( ele ); + } + + return ranAnis; + } // handleElement + + // handle all eles + var ranEleAni = false; + for( var e = 0; e < eles.length; e++ ){ + var ele = eles[ e ]; + var handledThisEle = handleElement( ele ); + + ranEleAni = ranEleAni || handledThisEle; + } // each element + + var ranCoreAni = handleElement( cy, true ); + + // notify renderer + if( ranEleAni || ranCoreAni ){ + if( eles.length > 0 ){ + var updatedEles = eles.updateCompoundBounds().spawnSelf().merge( eles ); + + cy.notify({ + type: 'draw', + eles: updatedEles + }); + } else { + cy.notify({ + type: 'draw' + }); + } + } + + // remove elements from list of currently animating if its queues are empty + eles.unmerge( doneEles ); + + cy.trigger('step'); + + } // handleElements + + function startAnimation( self, ani, now ){ + var isCore = is.core( self ); + var isEles = !isCore; + var ele = self; + var style = cy._private.style; + var ani_p = ani._private; + + if( isEles ){ + var pos = ele._private.position; + + ani_p.startPosition = ani_p.startPosition || { + x: pos.x, + y: pos.y + }; + + ani_p.startStyle = ani_p.startStyle || style.getAnimationStartStyle( ele, ani_p.style ); + } + + if( isCore ){ + var pan = cy._private.pan; + + ani_p.startPan = ani_p.startPan || { + x: pan.x, + y: pan.y + }; + + ani_p.startZoom = ani_p.startZoom != null ? ani_p.startZoom : cy._private.zoom; + } + + ani_p.started = true; + ani_p.startTime = now - ani_p.progress * ani_p.duration; + } + + function step( self, ani, now, isCore ){ + var style = cy._private.style; + var isEles = !isCore; + var _p = self._private; + var ani_p = ani._private; + var pEasing = ani_p.easing; + var startTime = ani_p.startTime; + + if( !ani_p.easingImpl ){ + + if( pEasing == null ){ // use default + ani_p.easingImpl = easings[ 'linear' ]; + + } else { // then define w/ name + var easingVals; + + if( is.string( pEasing ) ){ + var easingProp = style.parse( 'transition-timing-function', pEasing ); + + easingVals = easingProp.value; + + } else { // then assume preparsed array + easingVals = pEasing; + } + + var name, args; + + if( is.string( easingVals ) ){ + name = easingVals; + args = []; + } else { + name = easingVals[1]; + args = easingVals.slice( 2 ).map( function( n ){ return +n; } ); + } + + if( args.length > 0 ){ // create with args + if( name === 'spring' ){ + args.push( ani_p.duration ); // need duration to generate spring + } + + ani_p.easingImpl = easings[ name ].apply( null, args ); + } else { // static impl by name + ani_p.easingImpl = easings[ name ]; + } + } + + } + + var easing = ani_p.easingImpl; + var percent; + + if( ani_p.duration === 0 ){ + percent = 1; + } else { + percent = (now - startTime) / ani_p.duration; + } + + if( ani_p.applying ){ + percent = ani_p.progress; + } + + if( percent < 0 ){ + percent = 0; + } else if( percent > 1 ){ + percent = 1; + } + + if( ani_p.delay == null ){ // then update + + var startPos = ani_p.startPosition; + var endPos = ani_p.position; + var pos = _p.position; + if( endPos && isEles ){ + if( valid( startPos.x, endPos.x ) ){ + pos.x = ease( startPos.x, endPos.x, percent, easing ); + } + + if( valid( startPos.y, endPos.y ) ){ + pos.y = ease( startPos.y, endPos.y, percent, easing ); + } + + self.trigger('position'); + } + + var startPan = ani_p.startPan; + var endPan = ani_p.pan; + var pan = _p.pan; + var animatingPan = endPan != null && isCore; + if( animatingPan ){ + if( valid( startPan.x, endPan.x ) ){ + pan.x = ease( startPan.x, endPan.x, percent, easing ); + } + + if( valid( startPan.y, endPan.y ) ){ + pan.y = ease( startPan.y, endPan.y, percent, easing ); + } + + self.trigger( 'pan' ); + } + + var startZoom = ani_p.startZoom; + var endZoom = ani_p.zoom; + var animatingZoom = endZoom != null && isCore; + if( animatingZoom ){ + if( valid( startZoom, endZoom ) ){ + _p.zoom = ease( startZoom, endZoom, percent, easing ); + } + + self.trigger( 'zoom' ); + } + + if( animatingPan || animatingZoom ){ + self.trigger( 'viewport' ); + } + + var props = ani_p.style; + if( props && props.length > 0 && isEles ){ + for( var i = 0; i < props.length; i++ ){ + var prop = props[ i ]; + var name = prop.name; + var end = prop; + + var start = ani_p.startStyle[ name ]; + var easedVal = ease( start, end, percent, easing ); + + style.overrideBypass( self, name, easedVal ); + } // for props + + self.trigger('style'); + + } // if + + } + + ani_p.progress = percent; + + return percent; + } + + function valid( start, end ){ + if( start == null || end == null ){ + return false; + } + + if( is.number( start ) && is.number( end ) ){ + return true; + } else if( (start) && (end) ){ + return true; + } + + return false; + } + + // assumes p0 = 0, p3 = 1 + function evalCubicBezier( p1, p2, t ){ + var one_t = 1 - t; + var tsq = t * t; + + return ( 3 * one_t * one_t * t * p1 ) + ( 3 * one_t * tsq * p2 ) + tsq * t; + } + + function cubicBezier( p1, p2 ){ + return function( start, end, percent ){ + return start + (end - start) * evalCubicBezier( p1, p2, percent ); + }; + } + + /*! Runge-Kutta spring physics function generator. Adapted from Framer.js, copyright Koen Bok. MIT License: http://en.wikipedia.org/wiki/MIT_License */ + /* Given a tension, friction, and duration, a simulation at 60FPS will first run without a defined duration in order to calculate the full path. A second pass + then adjusts the time delta -- using the relation between actual time and duration -- to calculate the path for the duration-constrained animation. */ + var generateSpringRK4 = (function(){ + function springAccelerationForState( state ){ + return (-state.tension * state.x) - (state.friction * state.v); + } + + function springEvaluateStateWithDerivative( initialState, dt, derivative ){ + var state = { + x: initialState.x + derivative.dx * dt, + v: initialState.v + derivative.dv * dt, + tension: initialState.tension, + friction: initialState.friction + }; + + return { dx: state.v, dv: springAccelerationForState( state ) }; + } + + function springIntegrateState( state, dt ){ + var a = { + dx: state.v, + dv: springAccelerationForState( state ) + }, + b = springEvaluateStateWithDerivative( state, dt * 0.5, a ), + c = springEvaluateStateWithDerivative( state, dt * 0.5, b ), + d = springEvaluateStateWithDerivative( state, dt, c ), + dxdt = 1.0 / 6.0 * (a.dx + 2.0 * (b.dx + c.dx) + d.dx), + dvdt = 1.0 / 6.0 * (a.dv + 2.0 * (b.dv + c.dv) + d.dv); + + state.x = state.x + dxdt * dt; + state.v = state.v + dvdt * dt; + + return state; + } + + return function springRK4Factory( tension, friction, duration ){ + + var initState = { + x: -1, + v: 0, + tension: null, + friction: null + }, + path = [0], + time_lapsed = 0, + tolerance = 1 / 10000, + DT = 16 / 1000, + have_duration, dt, last_state; + + tension = parseFloat( tension ) || 500; + friction = parseFloat( friction ) || 20; + duration = duration || null; + + initState.tension = tension; + initState.friction = friction; + + have_duration = duration !== null; + + /* Calculate the actual time it takes for this animation to complete with the provided conditions. */ + if( have_duration ){ + /* Run the simulation without a duration. */ + time_lapsed = springRK4Factory( tension, friction ); + /* Compute the adjusted time delta. */ + dt = time_lapsed / duration * DT; + } else { + dt = DT; + } + + while( true ){ + /* Next/step function .*/ + last_state = springIntegrateState( last_state || initState, dt ); + /* Store the position. */ + path.push( 1 + last_state.x ); + time_lapsed += 16; + /* If the change threshold is reached, break. */ + if( !(Math.abs( last_state.x ) > tolerance && Math.abs( last_state.v ) > tolerance) ){ + break; + } + } + + /* If duration is not defined, return the actual time required for completing this animation. Otherwise, return a closure that holds the + computed path and returns a snapshot of the position according to a given percentComplete. */ + return !have_duration ? time_lapsed : function( percentComplete ){ return path[ (percentComplete * (path.length - 1)) | 0 ]; }; + }; + }()); + + var easings = { + 'linear': function( start, end, percent ){ + return start + (end - start) * percent; + }, + + // default easings + 'ease': cubicBezier( 0.25, 0.1, 0.25, 1 ), + 'ease-in': cubicBezier( 0.42, 0, 1, 1 ), + 'ease-out': cubicBezier( 0, 0, 0.58, 1 ), + 'ease-in-out': cubicBezier( 0.42, 0, 0.58, 1 ), + + // sine + 'ease-in-sine': cubicBezier( 0.47, 0, 0.745, 0.715 ), + 'ease-out-sine': cubicBezier( 0.39, 0.575, 0.565, 1 ), + 'ease-in-out-sine': cubicBezier( 0.445, 0.05, 0.55, 0.95 ), + + // quad + 'ease-in-quad': cubicBezier( 0.55, 0.085, 0.68, 0.53 ), + 'ease-out-quad': cubicBezier( 0.25, 0.46, 0.45, 0.94 ), + 'ease-in-out-quad': cubicBezier( 0.455, 0.03, 0.515, 0.955 ), + + // cubic + 'ease-in-cubic': cubicBezier( 0.55, 0.055, 0.675, 0.19 ), + 'ease-out-cubic': cubicBezier( 0.215, 0.61, 0.355, 1 ), + 'ease-in-out-cubic': cubicBezier( 0.645, 0.045, 0.355, 1 ), + + // quart + 'ease-in-quart': cubicBezier( 0.895, 0.03, 0.685, 0.22 ), + 'ease-out-quart': cubicBezier( 0.165, 0.84, 0.44, 1 ), + 'ease-in-out-quart': cubicBezier( 0.77, 0, 0.175, 1 ), + + // quint + 'ease-in-quint': cubicBezier( 0.755, 0.05, 0.855, 0.06 ), + 'ease-out-quint': cubicBezier( 0.23, 1, 0.32, 1 ), + 'ease-in-out-quint': cubicBezier( 0.86, 0, 0.07, 1 ), + + // expo + 'ease-in-expo': cubicBezier( 0.95, 0.05, 0.795, 0.035 ), + 'ease-out-expo': cubicBezier( 0.19, 1, 0.22, 1 ), + 'ease-in-out-expo': cubicBezier( 1, 0, 0, 1 ), + + // circ + 'ease-in-circ': cubicBezier( 0.6, 0.04, 0.98, 0.335 ), + 'ease-out-circ': cubicBezier( 0.075, 0.82, 0.165, 1 ), + 'ease-in-out-circ': cubicBezier( 0.785, 0.135, 0.15, 0.86 ), + + + // user param easings... + + 'spring': function( tension, friction, duration ){ + if( duration === 0 ){ // can't get a spring w/ duration 0 + return easings.linear; // duration 0 => jump to end so impl doesn't matter + } + + var spring = generateSpringRK4( tension, friction, duration ); + + return function( start, end, percent ){ + return start + (end - start) * spring( percent ); + }; + }, + + 'cubic-bezier': function( x1, y1, x2, y2 ){ + return cubicBezier( x1, y1, x2, y2 ); + } + }; + + function ease( startProp, endProp, percent, easingFn ){ + if( percent < 0 ){ + percent = 0; + } else if( percent > 1 ){ + percent = 1; + } + + var start, end; + + if( startProp.pfValue != null || startProp.value != null ){ + start = startProp.pfValue != null ? startProp.pfValue : startProp.value; + } else { + start = startProp; + } + + if( endProp.pfValue != null || endProp.value != null ){ + end = endProp.pfValue != null ? endProp.pfValue : endProp.value; + } else { + end = endProp; + } + + if( is.number( start ) && is.number( end ) ){ + return easingFn( start, end, percent ); + + } else if( is.array( start ) && is.array( end ) ){ + var easedArr = []; + + for( var i = 0; i < end.length; i++ ){ + var si = start[ i ]; + var ei = end[ i ]; + + if( si != null && ei != null ){ + var val = easingFn( si, ei, percent ); + + if( startProp.roundValue ){ val = Math.round( val ); } + + easedArr.push( val ); + } else { + easedArr.push( ei ); + } + } + + return easedArr; + } + + return undefined; + } + + } + +}); + +module.exports = corefn; + +},{"../define":44,"../is":83,"../util":100}],35:[function(_dereq_,module,exports){ +'use strict'; + +var define = _dereq_( '../define' ); + +var corefn = ({ + on: define.on(), // .on( events [, selector] [, data], handler) + one: define.on( { unbindSelfOnTrigger: true } ), + once: define.on( { unbindAllBindersOnTrigger: true } ), + off: define.off(), // .off( events [, selector] [, handler] ) + trigger: define.trigger() // .trigger( events [, extraParams] ) +}); + +define.eventAliasesOn( corefn ); + +module.exports = corefn; + +},{"../define":44}],36:[function(_dereq_,module,exports){ +'use strict'; + +var corefn = ({ + + png: function( options ){ + var renderer = this._private.renderer; + options = options || {}; + + return renderer.png( options ); + }, + + jpg: function( options ){ + var renderer = this._private.renderer; + options = options || {}; + + options.bg = options.bg || '#fff'; + + return renderer.jpg( options ); + } + +}); + +corefn.jpeg = corefn.jpg; + +module.exports = corefn; + +},{}],37:[function(_dereq_,module,exports){ +'use strict'; + +var window = _dereq_( '../window' ); +var util = _dereq_( '../util' ); +var Collection = _dereq_( '../collection' ); +var is = _dereq_( '../is' ); +var Promise = _dereq_( '../promise' ); +var define = _dereq_( '../define' ); + +var Core = function( opts ){ + var cy = this; + + opts = util.extend( {}, opts ); + + var container = opts.container; + + // allow for passing a wrapped jquery object + // e.g. cytoscape({ container: $('#cy') }) + if( container && !is.htmlElement( container ) && is.htmlElement( container[0] ) ){ + container = container[0]; + } + + var reg = container ? container._cyreg : null; // e.g. already registered some info (e.g. readies) via jquery + reg = reg || {}; + + if( reg && reg.cy ){ + reg.cy.destroy(); + + reg = {}; // old instance => replace reg completely + } + + var readies = reg.readies = reg.readies || []; + + if( container ){ container._cyreg = reg; } // make sure container assoc'd reg points to this cy + reg.cy = cy; + + var head = window !== undefined && container !== undefined && !opts.headless; + var options = opts; + options.layout = util.extend( { name: head ? 'grid' : 'null' }, options.layout ); + options.renderer = util.extend( { name: head ? 'canvas' : 'null' }, options.renderer ); + + var defVal = function( def, val, altVal ){ + if( val !== undefined ){ + return val; + } else if( altVal !== undefined ){ + return altVal; + } else { + return def; + } + }; + + var _p = this._private = { + container: container, // html dom ele container + ready: false, // whether ready has been triggered + initrender: false, // has initrender has been triggered + options: options, // cached options + elements: new Collection( this ), // elements in the graph + listeners: [], // list of listeners + aniEles: new Collection( this ), // elements being animated + scratch: {}, // scratch object for core + layout: null, + renderer: null, + notificationsEnabled: true, // whether notifications are sent to the renderer + minZoom: 1e-50, + maxZoom: 1e50, + zoomingEnabled: defVal( true, options.zoomingEnabled ), + userZoomingEnabled: defVal( true, options.userZoomingEnabled ), + panningEnabled: defVal( true, options.panningEnabled ), + userPanningEnabled: defVal( true, options.userPanningEnabled ), + boxSelectionEnabled: defVal( true, options.boxSelectionEnabled ), + autolock: defVal( false, options.autolock, options.autolockNodes ), + autoungrabify: defVal( false, options.autoungrabify, options.autoungrabifyNodes ), + autounselectify: defVal( false, options.autounselectify ), + styleEnabled: options.styleEnabled === undefined ? head : options.styleEnabled, + zoom: is.number( options.zoom ) ? options.zoom : 1, + pan: { + x: is.plainObject( options.pan ) && is.number( options.pan.x ) ? options.pan.x : 0, + y: is.plainObject( options.pan ) && is.number( options.pan.y ) ? options.pan.y : 0 + }, + animation: { // object for currently-running animations + current: [], + queue: [] + }, + hasCompoundNodes: false + }; + + // set selection type + var selType = options.selectionType; + if( selType === undefined || (selType !== 'additive' && selType !== 'single') ){ + // then set default + + _p.selectionType = 'single'; + } else { + _p.selectionType = selType; + } + + // init zoom bounds + if( is.number( options.minZoom ) && is.number( options.maxZoom ) && options.minZoom < options.maxZoom ){ + _p.minZoom = options.minZoom; + _p.maxZoom = options.maxZoom; + } else if( is.number( options.minZoom ) && options.maxZoom === undefined ){ + _p.minZoom = options.minZoom; + } else if( is.number( options.maxZoom ) && options.minZoom === undefined ){ + _p.maxZoom = options.maxZoom; + } + + var loadExtData = function( extData, next ){ + var anyIsPromise = extData.some( is.promise ); + + if( anyIsPromise ){ + return Promise.all( extData ).then( next ); // load all data asynchronously, then exec rest of init + } else { + next( extData ); // exec synchronously for convenience + } + }; + + // create the renderer + cy.initRenderer( util.extend( { + hideEdgesOnViewport: options.hideEdgesOnViewport, + textureOnViewport: options.textureOnViewport, + wheelSensitivity: is.number( options.wheelSensitivity ) && options.wheelSensitivity > 0 ? options.wheelSensitivity : 1, + motionBlur: options.motionBlur === undefined ? false : options.motionBlur, // off by default + motionBlurOpacity: options.motionBlurOpacity === undefined ? 0.05 : options.motionBlurOpacity, + pixelRatio: is.number( options.pixelRatio ) && options.pixelRatio > 0 ? options.pixelRatio : undefined, + desktopTapThreshold: options.desktopTapThreshold === undefined ? 4 : options.desktopTapThreshold, + touchTapThreshold: options.touchTapThreshold === undefined ? 8 : options.touchTapThreshold + }, options.renderer ) ); + + loadExtData([ options.style, options.elements ], function( thens ){ + var initStyle = thens[0]; + var initEles = thens[1]; + + // init style + if( _p.styleEnabled ){ + cy.setStyle( initStyle ); + } + + // trigger the passed function for the `initrender` event + if( options.initrender ){ + cy.on( 'initrender', options.initrender ); + cy.on( 'initrender', function(){ + _p.initrender = true; + } ); + } + + // initial load + cy.load( initEles, function(){ // onready + cy.startAnimationLoop(); + _p.ready = true; + + // if a ready callback is specified as an option, the bind it + if( is.fn( options.ready ) ){ + cy.on( 'ready', options.ready ); + } + + // bind all the ready handlers registered before creating this instance + for( var i = 0; i < readies.length; i++ ){ + var fn = readies[ i ]; + cy.on( 'ready', fn ); + } + if( reg ){ reg.readies = []; } // clear b/c we've bound them all and don't want to keep it around in case a new core uses the same div etc + + cy.trigger( 'ready' ); + }, options.done ); + + } ); +}; + +var corefn = Core.prototype; // short alias + +util.extend( corefn, { + instanceString: function(){ + return 'core'; + }, + + isReady: function(){ + return this._private.ready; + }, + + ready: function( fn ){ + if( this.isReady() ){ + this.trigger( 'ready', [], fn ); // just calls fn as though triggered via ready event + } else { + this.on( 'ready', fn ); + } + + return this; + }, + + initrender: function(){ + return this._private.initrender; + }, + + destroy: function(){ + var cy = this; + + cy.stopAnimationLoop(); + + cy.destroyRenderer(); + + return cy; + }, + + hasElementWithId: function( id ){ + return this._private.elements.hasElementWithId( id ); + }, + + getElementById: function( id ){ + return this._private.elements.getElementById( id ); + }, + + selectionType: function(){ + return this._private.selectionType; + }, + + hasCompoundNodes: function(){ + return this._private.hasCompoundNodes; + }, + + headless: function(){ + return this._private.options.renderer.name === 'null'; + }, + + styleEnabled: function(){ + return this._private.styleEnabled; + }, + + addToPool: function( eles ){ + this._private.elements.merge( eles ); + + return this; // chaining + }, + + removeFromPool: function( eles ){ + this._private.elements.unmerge( eles ); + + return this; + }, + + container: function(){ + return this._private.container; + }, + + options: function(){ + return util.copy( this._private.options ); + }, + + json: function( obj ){ + var cy = this; + var _p = cy._private; + var eles = cy.mutableElements(); + + if( is.plainObject( obj ) ){ // set + + cy.startBatch(); + + if( obj.elements ){ + var idInJson = {}; + + var updateEles = function( jsons, gr ){ + for( var i = 0; i < jsons.length; i++ ){ + var json = jsons[ i ]; + var id = json.data.id; + var ele = cy.getElementById( id ); + + idInJson[ id ] = true; + + if( ele.length !== 0 ){ // existing element should be updated + ele.json( json ); + } else { // otherwise should be added + if( gr ){ + cy.add( util.extend( { group: gr }, json ) ); + } else { + cy.add( json ); + } + } + } + }; + + if( is.array( obj.elements ) ){ // elements: [] + updateEles( obj.elements ); + + } else { // elements: { nodes: [], edges: [] } + var grs = [ 'nodes', 'edges' ]; + for( var i = 0; i < grs.length; i++ ){ + var gr = grs[ i ]; + var elements = obj.elements[ gr ]; + + if( is.array( elements ) ){ + updateEles( elements, gr ); + } + } + } + + // elements not specified in json should be removed + eles.stdFilter( function( ele ){ + return !idInJson[ ele.id() ]; + } ).remove(); + } + + if( obj.style ){ + cy.style( obj.style ); + } + + if( obj.zoom != null && obj.zoom !== _p.zoom ){ + cy.zoom( obj.zoom ); + } + + if( obj.pan ){ + if( obj.pan.x !== _p.pan.x || obj.pan.y !== _p.pan.y ){ + cy.pan( obj.pan ); + } + } + + var fields = [ + 'minZoom', 'maxZoom', 'zoomingEnabled', 'userZoomingEnabled', + 'panningEnabled', 'userPanningEnabled', + 'boxSelectionEnabled', + 'autolock', 'autoungrabify', 'autounselectify' + ]; + + for( var i = 0; i < fields.length; i++ ){ + var f = fields[ i ]; + + if( obj[ f ] != null ){ + cy[ f ]( obj[ f ] ); + } + } + + cy.endBatch(); + + return this; // chaining + } else if( obj === undefined ){ // get + var json = {}; + + json.elements = {}; + eles.forEach( function( ele ){ + var group = ele.group(); + + if( !json.elements[ group ] ){ + json.elements[ group ] = []; + } + + json.elements[ group ].push( ele.json() ); + } ); + + if( this._private.styleEnabled ){ + json.style = cy.style().json(); + } + + json.zoomingEnabled = cy._private.zoomingEnabled; + json.userZoomingEnabled = cy._private.userZoomingEnabled; + json.zoom = cy._private.zoom; + json.minZoom = cy._private.minZoom; + json.maxZoom = cy._private.maxZoom; + json.panningEnabled = cy._private.panningEnabled; + json.userPanningEnabled = cy._private.userPanningEnabled; + json.pan = util.copy( cy._private.pan ); + json.boxSelectionEnabled = cy._private.boxSelectionEnabled; + json.renderer = util.copy( cy._private.options.renderer ); + json.hideEdgesOnViewport = cy._private.options.hideEdgesOnViewport; + json.textureOnViewport = cy._private.options.textureOnViewport; + json.wheelSensitivity = cy._private.options.wheelSensitivity; + json.motionBlur = cy._private.options.motionBlur; + + return json; + } + }, + + scratch: define.data( { + field: 'scratch', + bindingEvent: 'scratch', + allowBinding: true, + allowSetting: true, + settingEvent: 'scratch', + settingTriggersEvent: true, + triggerFnName: 'trigger', + allowGetting: true + } ), + + removeScratch: define.removeData( { + field: 'scratch', + event: 'scratch', + triggerFnName: 'trigger', + triggerEvent: true + } ) + +} ); + +[ + _dereq_( './add-remove' ), + _dereq_( './animation' ), + _dereq_( './events' ), + _dereq_( './export' ), + _dereq_( './layout' ), + _dereq_( './notification' ), + _dereq_( './renderer' ), + _dereq_( './search' ), + _dereq_( './style' ), + _dereq_( './viewport' ) +].forEach( function( props ){ + util.extend( corefn, props ); +} ); + +module.exports = Core; + +},{"../collection":26,"../define":44,"../is":83,"../promise":86,"../util":100,"../window":107,"./add-remove":33,"./animation":34,"./events":35,"./export":36,"./layout":38,"./notification":39,"./renderer":40,"./search":41,"./style":42,"./viewport":43}],38:[function(_dereq_,module,exports){ +'use strict'; + +var util = _dereq_( '../util' ); +var is = _dereq_( '../is' ); + +var corefn = ({ + + layout: function( params ){ + var layout = this._private.prevLayout = ( params == null ? this._private.prevLayout : this.makeLayout( params ) ); + + layout.run(); + + return this; // chaining + }, + + makeLayout: function( options ){ + var cy = this; + + if( options == null ){ + util.error( 'Layout options must be specified to make a layout' ); + return; + } + + if( options.name == null ){ + util.error( 'A `name` must be specified to make a layout' ); + return; + } + + var name = options.name; + var Layout = cy.extension( 'layout', name ); + + if( Layout == null ){ + util.error( 'Can not apply layout: No such layout `' + name + '` found; did you include its JS file?' ); + return; + } + + var eles; + if( is.string( options.eles ) ){ + eles = cy.$( options.eles ); + } else { + eles = options.eles != null ? options.eles : cy.$(); + } + + var layout = new Layout( util.extend( {}, options, { + cy: cy, + eles: eles + } ) ); + + return layout; + } + +}); + +corefn.createLayout = corefn.makeLayout; + +module.exports = corefn; + +},{"../is":83,"../util":100}],39:[function(_dereq_,module,exports){ +'use strict'; + +var corefn = ({ + notify: function( params ){ + var _p = this._private; + + if( _p.batchingNotify ){ + var bEles = _p.batchNotifyEles; + var bTypes = _p.batchNotifyTypes; + + if( params.eles ){ + bEles.merge( params.eles ); + } + + if( !bTypes.ids[ params.type ] ){ + bTypes.push( params.type ); + bTypes.ids[ params.type ] = true; + } + + return; // notifications are disabled during batching + } + + if( !_p.notificationsEnabled ){ return; } // exit on disabled + + var renderer = this.renderer(); + + renderer.notify( params ); + }, + + notifications: function( bool ){ + var p = this._private; + + if( bool === undefined ){ + return p.notificationsEnabled; + } else { + p.notificationsEnabled = bool ? true : false; + } + }, + + noNotifications: function( callback ){ + this.notifications( false ); + callback(); + this.notifications( true ); + }, + + startBatch: function(){ + var _p = this._private; + + if( _p.batchCount == null ){ + _p.batchCount = 0; + } + + if( _p.batchCount === 0 ){ + _p.batchingStyle = _p.batchingNotify = true; + _p.batchStyleEles = this.collection(); + _p.batchNotifyEles = this.collection(); + _p.batchNotifyTypes = []; + _p.batchNotifyTypes.ids = {}; + } + + _p.batchCount++; + + return this; + }, + + endBatch: function(){ + var _p = this._private; + + _p.batchCount--; + + if( _p.batchCount === 0 ){ + // update style for dirty eles + _p.batchingStyle = false; + _p.batchStyleEles.updateStyle(); + + // notify the renderer of queued eles and event types + _p.batchingNotify = false; + this.notify( { + type: _p.batchNotifyTypes, + eles: _p.batchNotifyEles + } ); + } + + return this; + }, + + batch: function( callback ){ + this.startBatch(); + callback(); + this.endBatch(); + + return this; + }, + + // for backwards compatibility + batchData: function( map ){ + var cy = this; + + return this.batch( function(){ + var ids = Object.keys( map ); + + for( var i = 0; i < ids.length; i++ ){ + var id = ids[i]; + var data = map[ id ]; + var ele = cy.getElementById( id ); + + ele.data( data ); + } + } ); + } +}); + +module.exports = corefn; + +},{}],40:[function(_dereq_,module,exports){ +'use strict'; + +var util = _dereq_( '../util' ); + +var corefn = ({ + + renderTo: function( context, zoom, pan, pxRatio ){ + var r = this._private.renderer; + + r.renderTo( context, zoom, pan, pxRatio ); + return this; + }, + + renderer: function(){ + return this._private.renderer; + }, + + forceRender: function(){ + this.notify( { + type: 'draw' + } ); + + return this; + }, + + resize: function(){ + this.invalidateSize(); + + this.notify( { + type: 'resize' + } ); + + this.trigger( 'resize' ); + + return this; + }, + + initRenderer: function( options ){ + var cy = this; + + var RendererProto = cy.extension( 'renderer', options.name ); + if( RendererProto == null ){ + util.error( 'Can not initialise: No such renderer `%s` found; did you include its JS file?', options.name ); + return; + } + + var rOpts = util.extend( {}, options, { + cy: cy + } ); + + cy._private.renderer = new RendererProto( rOpts ); + }, + + destroyRenderer: function(){ + var cy = this; + + cy.notify( { type: 'destroy' } ); // destroy the renderer + + var domEle = cy.container(); + if( domEle ){ + domEle._cyreg = null; + + while( domEle.childNodes.length > 0 ){ + domEle.removeChild( domEle.childNodes[0] ); + } + } + + cy._private.renderer = null; // to be extra safe, remove the ref + }, + + onRender: function( fn ){ + return this.on('render', fn); + }, + + offRender: function( fn ){ + return this.off('render', fn); + } + +}); + +corefn.invalidateDimensions = corefn.resize; + +module.exports = corefn; + +},{"../util":100}],41:[function(_dereq_,module,exports){ +'use strict'; + +var is = _dereq_( '../is' ); +var Collection = _dereq_( '../collection' ); + +var corefn = ({ + + // get a collection + // - empty collection on no args + // - collection of elements in the graph on selector arg + // - guarantee a returned collection when elements or collection specified + collection: function( eles, opts ){ + + if( is.string( eles ) ){ + return this.$( eles ); + + } else if( is.elementOrCollection( eles ) ){ + return eles.collection(); + + } else if( is.array( eles ) ){ + return new Collection( this, eles, opts ); + } + + return new Collection( this ); + }, + + nodes: function( selector ){ + var nodes = this.$( function(){ + return this.isNode(); + } ); + + if( selector ){ + return nodes.filter( selector ); + } + + return nodes; + }, + + edges: function( selector ){ + var edges = this.$( function(){ + return this.isEdge(); + } ); + + if( selector ){ + return edges.filter( selector ); + } + + return edges; + }, + + // search the graph like jQuery + $: function( selector ){ + var eles = this._private.elements; + + if( selector ){ + return eles.filter( selector ); + } else { + return eles.spawnSelf(); + } + }, + + mutableElements: function(){ + return this._private.elements; + } + +}); + +// aliases +corefn.elements = corefn.filter = corefn.$; + +module.exports = corefn; + +},{"../collection":26,"../is":83}],42:[function(_dereq_,module,exports){ +'use strict'; + +var is = _dereq_( '../is' ); +var Style = _dereq_( '../style' ); + +var corefn = ({ + + style: function( newStyle ){ + if( newStyle ){ + var s = this.setStyle( newStyle ); + + s.update(); + } + + return this._private.style; + }, + + setStyle: function( style ){ + var _p = this._private; + + if( is.stylesheet( style ) ){ + _p.style = style.generateStyle( this ); + + } else if( is.array( style ) ){ + _p.style = Style.fromJson( this, style ); + + } else if( is.string( style ) ){ + _p.style = Style.fromString( this, style ); + + } else { + _p.style = Style( this ); + } + + return _p.style; + } +}); + +module.exports = corefn; + +},{"../is":83,"../style":92}],43:[function(_dereq_,module,exports){ +'use strict'; + +var is = _dereq_( '../is' ); + +var corefn = ({ + + autolock: function( bool ){ + if( bool !== undefined ){ + this._private.autolock = bool ? true : false; + } else { + return this._private.autolock; + } + + return this; // chaining + }, + + autoungrabify: function( bool ){ + if( bool !== undefined ){ + this._private.autoungrabify = bool ? true : false; + } else { + return this._private.autoungrabify; + } + + return this; // chaining + }, + + autounselectify: function( bool ){ + if( bool !== undefined ){ + this._private.autounselectify = bool ? true : false; + } else { + return this._private.autounselectify; + } + + return this; // chaining + }, + + panningEnabled: function( bool ){ + if( bool !== undefined ){ + this._private.panningEnabled = bool ? true : false; + } else { + return this._private.panningEnabled; + } + + return this; // chaining + }, + + userPanningEnabled: function( bool ){ + if( bool !== undefined ){ + this._private.userPanningEnabled = bool ? true : false; + } else { + return this._private.userPanningEnabled; + } + + return this; // chaining + }, + + zoomingEnabled: function( bool ){ + if( bool !== undefined ){ + this._private.zoomingEnabled = bool ? true : false; + } else { + return this._private.zoomingEnabled; + } + + return this; // chaining + }, + + userZoomingEnabled: function( bool ){ + if( bool !== undefined ){ + this._private.userZoomingEnabled = bool ? true : false; + } else { + return this._private.userZoomingEnabled; + } + + return this; // chaining + }, + + boxSelectionEnabled: function( bool ){ + if( bool !== undefined ){ + this._private.boxSelectionEnabled = bool ? true : false; + } else { + return this._private.boxSelectionEnabled; + } + + return this; // chaining + }, + + pan: function(){ + var args = arguments; + var pan = this._private.pan; + var dim, val, dims, x, y; + + switch( args.length ){ + case 0: // .pan() + return pan; + + case 1: + + if( is.string( args[0] ) ){ // .pan('x') + dim = args[0]; + return pan[ dim ]; + + } else if( is.plainObject( args[0] ) ){ // .pan({ x: 0, y: 100 }) + if( !this._private.panningEnabled ){ + return this; + } + + dims = args[0]; + x = dims.x; + y = dims.y; + + if( is.number( x ) ){ + pan.x = x; + } + + if( is.number( y ) ){ + pan.y = y; + } + + this.trigger( 'pan viewport' ); + } + break; + + case 2: // .pan('x', 100) + if( !this._private.panningEnabled ){ + return this; + } + + dim = args[0]; + val = args[1]; + + if( (dim === 'x' || dim === 'y') && is.number( val ) ){ + pan[ dim ] = val; + } + + this.trigger( 'pan viewport' ); + break; + + default: + break; // invalid + } + + this.notify( { // notify the renderer that the viewport changed + type: 'viewport' + } ); + + return this; // chaining + }, + + panBy: function( params ){ + var args = arguments; + var pan = this._private.pan; + var dim, val, dims, x, y; + + if( !this._private.panningEnabled ){ + return this; + } + + switch( args.length ){ + case 1: + + if( is.plainObject( args[0] ) ){ // .panBy({ x: 0, y: 100 }) + dims = args[0]; + x = dims.x; + y = dims.y; + + if( is.number( x ) ){ + pan.x += x; + } + + if( is.number( y ) ){ + pan.y += y; + } + + this.trigger( 'pan viewport' ); + } + break; + + case 2: // .panBy('x', 100) + dim = args[0]; + val = args[1]; + + if( (dim === 'x' || dim === 'y') && is.number( val ) ){ + pan[ dim ] += val; + } + + this.trigger( 'pan viewport' ); + break; + + default: + break; // invalid + } + + this.notify( { // notify the renderer that the viewport changed + type: 'viewport' + } ); + + return this; // chaining + }, + + fit: function( elements, padding ){ + var viewportState = this.getFitViewport( elements, padding ); + + if( viewportState ){ + var _p = this._private; + _p.zoom = viewportState.zoom; + _p.pan = viewportState.pan; + + this.trigger( 'pan zoom viewport' ); + + this.notify( { // notify the renderer that the viewport changed + type: 'viewport' + } ); + } + + return this; // chaining + }, + + getFitViewport: function( elements, padding ){ + if( is.number( elements ) && padding === undefined ){ // elements is optional + padding = elements; + elements = undefined; + } + + if( !this._private.panningEnabled || !this._private.zoomingEnabled ){ + return; + } + + var bb; + + if( is.string( elements ) ){ + var sel = elements; + elements = this.$( sel ); + + } else if( is.boundingBox( elements ) ){ // assume bb + var bbe = elements; + bb = { + x1: bbe.x1, + y1: bbe.y1, + x2: bbe.x2, + y2: bbe.y2 + }; + + bb.w = bb.x2 - bb.x1; + bb.h = bb.y2 - bb.y1; + + } else if( !is.elementOrCollection( elements ) ){ + elements = this.mutableElements(); + } + + bb = bb || elements.boundingBox(); + + var w = this.width(); + var h = this.height(); + var zoom; + padding = is.number( padding ) ? padding : 0; + + if( !isNaN( w ) && !isNaN( h ) && w > 0 && h > 0 && !isNaN( bb.w ) && !isNaN( bb.h ) && bb.w > 0 && bb.h > 0 ){ + zoom = Math.min( (w - 2 * padding) / bb.w, (h - 2 * padding) / bb.h ); + + // crop zoom + zoom = zoom > this._private.maxZoom ? this._private.maxZoom : zoom; + zoom = zoom < this._private.minZoom ? this._private.minZoom : zoom; + + var pan = { // now pan to middle + x: (w - zoom * ( bb.x1 + bb.x2 )) / 2, + y: (h - zoom * ( bb.y1 + bb.y2 )) / 2 + }; + + return { + zoom: zoom, + pan: pan + }; + } + + return; + }, + + minZoom: function( zoom ){ + if( zoom === undefined ){ + return this._private.minZoom; + } else if( is.number( zoom ) ){ + this._private.minZoom = zoom; + } + + return this; + }, + + maxZoom: function( zoom ){ + if( zoom === undefined ){ + return this._private.maxZoom; + } else if( is.number( zoom ) ){ + this._private.maxZoom = zoom; + } + + return this; + }, + + zoom: function( params ){ + var pos; // in rendered px + var zoom; + + if( params === undefined ){ // then get the zoom + return this._private.zoom; + + } else if( is.number( params ) ){ // then set the zoom + zoom = params; + + } else if( is.plainObject( params ) ){ // then zoom about a point + zoom = params.level; + + if( params.position ){ + var p = params.position; + var pan = this._private.pan; + var z = this._private.zoom; + + pos = { // convert to rendered px + x: p.x * z + pan.x, + y: p.y * z + pan.y + }; + } else if( params.renderedPosition ){ + pos = params.renderedPosition; + } + + if( pos && !this._private.panningEnabled ){ + return this; // panning disabled + } + } + + if( !this._private.zoomingEnabled ){ + return this; // zooming disabled + } + + if( !is.number( zoom ) || ( pos && (!is.number( pos.x ) || !is.number( pos.y )) ) ){ + return this; // can't zoom with invalid params + } + + // crop zoom + zoom = zoom > this._private.maxZoom ? this._private.maxZoom : zoom; + zoom = zoom < this._private.minZoom ? this._private.minZoom : zoom; + + if( pos ){ // set zoom about position + var pan1 = this._private.pan; + var zoom1 = this._private.zoom; + var zoom2 = zoom; + + var pan2 = { + x: -zoom2 / zoom1 * (pos.x - pan1.x) + pos.x, + y: -zoom2 / zoom1 * (pos.y - pan1.y) + pos.y + }; + + this._private.zoom = zoom; + this._private.pan = pan2; + + var posChanged = pan1.x !== pan2.x || pan1.y !== pan2.y; + this.trigger( ' zoom ' + (posChanged ? ' pan ' : '') + ' viewport ' ); + + } else { // just set the zoom + this._private.zoom = zoom; + this.trigger( 'zoom viewport' ); + } + + this.notify( { // notify the renderer that the viewport changed + type: 'viewport' + } ); + + return this; // chaining + }, + + viewport: function( opts ){ + var _p = this._private; + var zoomDefd = true; + var panDefd = true; + var events = []; // to trigger + var zoomFailed = false; + var panFailed = false; + + if( !opts ){ return this; } + if( !is.number( opts.zoom ) ){ zoomDefd = false; } + if( !is.plainObject( opts.pan ) ){ panDefd = false; } + if( !zoomDefd && !panDefd ){ return this; } + + if( zoomDefd ){ + var z = opts.zoom; + + if( z < _p.minZoom || z > _p.maxZoom || !_p.zoomingEnabled ){ + zoomFailed = true; + + } else { + _p.zoom = z; + + events.push( 'zoom' ); + } + } + + if( panDefd && (!zoomFailed || !opts.cancelOnFailedZoom) && _p.panningEnabled ){ + var p = opts.pan; + + if( is.number( p.x ) ){ + _p.pan.x = p.x; + panFailed = false; + } + + if( is.number( p.y ) ){ + _p.pan.y = p.y; + panFailed = false; + } + + if( !panFailed ){ + events.push( 'pan' ); + } + } + + if( events.length > 0 ){ + events.push( 'viewport' ); + this.trigger( events.join( ' ' ) ); + + this.notify( { + type: 'viewport' + } ); + } + + return this; // chaining + }, + + center: function( elements ){ + var pan = this.getCenterPan( elements ); + + if( pan ){ + this._private.pan = pan; + + this.trigger( 'pan viewport' ); + + this.notify( { // notify the renderer that the viewport changed + type: 'viewport' + } ); + } + + return this; // chaining + }, + + getCenterPan: function( elements, zoom ){ + if( !this._private.panningEnabled ){ + return; + } + + if( is.string( elements ) ){ + var selector = elements; + elements = this.mutableElements().filter( selector ); + } else if( !is.elementOrCollection( elements ) ){ + elements = this.mutableElements(); + } + + var bb = elements.boundingBox(); + var w = this.width(); + var h = this.height(); + zoom = zoom === undefined ? this._private.zoom : zoom; + + var pan = { // middle + x: (w - zoom * ( bb.x1 + bb.x2 )) / 2, + y: (h - zoom * ( bb.y1 + bb.y2 )) / 2 + }; + + return pan; + }, + + reset: function(){ + if( !this._private.panningEnabled || !this._private.zoomingEnabled ){ + return this; + } + + this.viewport( { + pan: { x: 0, y: 0 }, + zoom: 1 + } ); + + return this; // chaining + }, + + invalidateSize: function(){ + this._private.sizeCache = null; + }, + + size: function(){ + var _p = this._private; + var container = _p.container; + + return ( _p.sizeCache = _p.sizeCache || ( container ? { + width: container.clientWidth, + height: container.clientHeight + } : { // fallback if no container (not 0 b/c can be used for dividing etc) + width: 1, + height: 1 + } ) ); + }, + + width: function(){ + return this.size().width; + }, + + height: function(){ + return this.size().height; + }, + + extent: function(){ + var pan = this._private.pan; + var zoom = this._private.zoom; + var rb = this.renderedExtent(); + + var b = { + x1: ( rb.x1 - pan.x ) / zoom, + x2: ( rb.x2 - pan.x ) / zoom, + y1: ( rb.y1 - pan.y ) / zoom, + y2: ( rb.y2 - pan.y ) / zoom + }; + + b.w = b.x2 - b.x1; + b.h = b.y2 - b.y1; + + return b; + }, + + renderedExtent: function(){ + var width = this.width(); + var height = this.height(); + + return { + x1: 0, + y1: 0, + x2: width, + y2: height, + w: width, + h: height + }; + } +}); + +// aliases +corefn.centre = corefn.center; + +// backwards compatibility +corefn.autolockNodes = corefn.autolock; +corefn.autoungrabifyNodes = corefn.autoungrabify; + +module.exports = corefn; + +},{"../is":83}],44:[function(_dereq_,module,exports){ +'use strict'; + +// use this module to cherry pick functions into your prototype +// (useful for functions shared between the core and collections, for example) + +// e.g. +// var foo = define.foo({ /* params... */ }) + +var util = _dereq_( './util' ); +var is = _dereq_( './is' ); +var Selector = _dereq_( './selector' ); +var Promise = _dereq_( './promise' ); +var Event = _dereq_( './event' ); +var Animation = _dereq_( './animation' ); + +var define = { + + // access data field + data: function( params ){ + var defaults = { + field: 'data', + bindingEvent: 'data', + allowBinding: false, + allowSetting: false, + allowGetting: false, + settingEvent: 'data', + settingTriggersEvent: false, + triggerFnName: 'trigger', + immutableKeys: {}, // key => true if immutable + updateStyle: false, + onSet: function( self ){}, + canSet: function( self ){ return true; } + }; + params = util.extend( {}, defaults, params ); + + return function dataImpl( name, value ){ + var p = params; + var self = this; + var selfIsArrayLike = self.length !== undefined; + var all = selfIsArrayLike ? self : [ self ]; // put in array if not array-like + var single = selfIsArrayLike ? self[0] : self; + + // .data('foo', ...) + if( is.string( name ) ){ // set or get property + + // .data('foo') + if( p.allowGetting && value === undefined ){ // get + + var ret; + if( single ){ + ret = single._private[ p.field ][ name ]; + } + return ret; + + // .data('foo', 'bar') + } else if( p.allowSetting && value !== undefined ){ // set + var valid = !p.immutableKeys[ name ]; + if( valid ){ + for( var i = 0, l = all.length; i < l; i++ ){ + if( p.canSet( all[ i ] ) ){ + all[ i ]._private[ p.field ][ name ] = value; + } + } + + // update mappers if asked + if( p.updateStyle ){ self.updateStyle(); } + + // call onSet callback + p.onSet( self ); + + if( p.settingTriggersEvent ){ + self[ p.triggerFnName ]( p.settingEvent ); + } + } + } + + // .data({ 'foo': 'bar' }) + } else if( p.allowSetting && is.plainObject( name ) ){ // extend + var obj = name; + var k, v; + var keys = Object.keys( obj ); + + for( var i = 0; i < keys.length; i++ ){ + k = keys[ i ]; + v = obj[ k ]; + + var valid = !p.immutableKeys[ k ]; + if( valid ){ + for( var j = 0; j < all.length; j++ ){ + var ele = all[j]; + + if( p.canSet( ele ) ){ + ele._private[ p.field ][ k ] = v; + } + } + } + } + + // update mappers if asked + if( p.updateStyle ){ self.updateStyle(); } + + // call onSet callback + p.onSet( self ); + + if( p.settingTriggersEvent ){ + self[ p.triggerFnName ]( p.settingEvent ); + } + + // .data(function(){ ... }) + } else if( p.allowBinding && is.fn( name ) ){ // bind to event + var fn = name; + self.on( p.bindingEvent, fn ); + + // .data() + } else if( p.allowGetting && name === undefined ){ // get whole object + var ret; + if( single ){ + ret = single._private[ p.field ]; + } + return ret; + } + + return self; // maintain chainability + }; // function + }, // data + + // remove data field + removeData: function( params ){ + var defaults = { + field: 'data', + event: 'data', + triggerFnName: 'trigger', + triggerEvent: false, + immutableKeys: {} // key => true if immutable + }; + params = util.extend( {}, defaults, params ); + + return function removeDataImpl( names ){ + var p = params; + var self = this; + var selfIsArrayLike = self.length !== undefined; + var all = selfIsArrayLike ? self : [ self ]; // put in array if not array-like + + // .removeData('foo bar') + if( is.string( names ) ){ // then get the list of keys, and delete them + var keys = names.split( /\s+/ ); + var l = keys.length; + + for( var i = 0; i < l; i++ ){ // delete each non-empty key + var key = keys[ i ]; + if( is.emptyString( key ) ){ continue; } + + var valid = !p.immutableKeys[ key ]; // not valid if immutable + if( valid ){ + for( var i_a = 0, l_a = all.length; i_a < l_a; i_a++ ){ + all[ i_a ]._private[ p.field ][ key ] = undefined; + } + } + } + + if( p.triggerEvent ){ + self[ p.triggerFnName ]( p.event ); + } + + // .removeData() + } else if( names === undefined ){ // then delete all keys + + for( var i_a = 0, l_a = all.length; i_a < l_a; i_a++ ){ + var _privateFields = all[ i_a ]._private[ p.field ]; + var keys = Object.keys( _privateFields ); + + for( var i = 0; i < keys.length; i++ ){ + var key = keys[i]; + var validKeyToDelete = !p.immutableKeys[ key ]; + + if( validKeyToDelete ){ + _privateFields[ key ] = undefined; + } + } + } + + if( p.triggerEvent ){ + self[ p.triggerFnName ]( p.event ); + } + } + + return self; // maintain chaining + }; // function + }, // removeData + + // event function reusable stuff + event: { + regex: /(\w+)(\.(?:\w+|\*))?/, // regex for matching event strings (e.g. "click.namespace") + universalNamespace: '.*', // matches as if no namespace specified and prevents users from unbinding accidentally + optionalTypeRegex: /(\w+)?(\.(?:\w+|\*))?/, + falseCallback: function(){ return false; } + }, + + // event binding + on: function( params ){ + var defaults = { + unbindSelfOnTrigger: false, + unbindAllBindersOnTrigger: false + }; + params = util.extend( {}, defaults, params ); + + return function onImpl( events, selector, data, callback ){ + var self = this; + var selfIsArrayLike = self.length !== undefined; + var all = selfIsArrayLike ? self : [ self ]; // put in array if not array-like + var eventsIsString = is.string( events ); + var p = params; + + if( is.plainObject( selector ) ){ // selector is actually data + callback = data; + data = selector; + selector = undefined; + } else if( is.fn( selector ) || selector === false ){ // selector is actually callback + callback = selector; + data = undefined; + selector = undefined; + } + + if( is.fn( data ) || data === false ){ // data is actually callback + callback = data; + data = undefined; + } + + // if there isn't a callback, we can't really do anything + // (can't speak for mapped events arg version) + if( !(is.fn( callback ) || callback === false) && eventsIsString ){ + return self; // maintain chaining + } + + if( eventsIsString ){ // then convert to map + var map = {}; + map[ events ] = callback; + events = map; + } + + var keys = Object.keys( events ); + + for( var k = 0; k < keys.length; k++ ){ + var evts = keys[k]; + + callback = events[ evts ]; + if( callback === false ){ + callback = define.event.falseCallback; + } + + if( !is.fn( callback ) ){ continue; } + + evts = evts.split( /\s+/ ); + for( var i = 0; i < evts.length; i++ ){ + var evt = evts[ i ]; + if( is.emptyString( evt ) ){ continue; } + + var match = evt.match( define.event.regex ); // type[.namespace] + + if( match ){ + var type = match[1]; + var namespace = match[2] ? match[2] : undefined; + + var listener = { + callback: callback, // callback to run + data: data, // extra data in eventObj.data + delegated: selector ? true : false, // whether the evt is delegated + selector: selector, // the selector to match for delegated events + selObj: new Selector( selector ), // cached selector object to save rebuilding + type: type, // the event type (e.g. 'click') + namespace: namespace, // the event namespace (e.g. ".foo") + unbindSelfOnTrigger: p.unbindSelfOnTrigger, + unbindAllBindersOnTrigger: p.unbindAllBindersOnTrigger, + binders: all // who bound together + }; + + for( var j = 0; j < all.length; j++ ){ + var _p = all[ j ]._private = all[ j ]._private || {}; + + _p.listeners = _p.listeners || []; + _p.listeners.push( listener ); + } + } + } // for events array + } // for events map + + return self; // maintain chaining + }; // function + }, // on + + eventAliasesOn: function( proto ){ + var p = proto; + + p.addListener = p.listen = p.bind = p.on; + p.removeListener = p.unlisten = p.unbind = p.off; + p.emit = p.trigger; + + // this is just a wrapper alias of .on() + p.pon = p.promiseOn = function( events, selector ){ + var self = this; + var args = Array.prototype.slice.call( arguments, 0 ); + + return new Promise( function( resolve, reject ){ + var callback = function( e ){ + self.off.apply( self, offArgs ); + + resolve( e ); + }; + + var onArgs = args.concat( [ callback ] ); + var offArgs = onArgs.concat( [] ); + + self.on.apply( self, onArgs ); + } ); + }; + }, + + off: function offImpl( params ){ + var defaults = { + }; + params = util.extend( {}, defaults, params ); + + return function( events, selector, callback ){ + var self = this; + var selfIsArrayLike = self.length !== undefined; + var all = selfIsArrayLike ? self : [ self ]; // put in array if not array-like + var eventsIsString = is.string( events ); + + if( arguments.length === 0 ){ // then unbind all + + for( var i = 0; i < all.length; i++ ){ + all[ i ]._private = all[ i ]._private || {}; + + _p.listeners = []; + } + + return self; // maintain chaining + } + + if( is.fn( selector ) || selector === false ){ // selector is actually callback + callback = selector; + selector = undefined; + } + + if( eventsIsString ){ // then convert to map + var map = {}; + map[ events ] = callback; + events = map; + } + + var keys = Object.keys( events ); + + for( var k = 0; k < keys.length; k++ ){ + var evts = keys[k]; + + callback = events[ evts ]; + + if( callback === false ){ + callback = define.event.falseCallback; + } + + evts = evts.split( /\s+/ ); + for( var h = 0; h < evts.length; h++ ){ + var evt = evts[ h ]; + if( is.emptyString( evt ) ){ continue; } + + var match = evt.match( define.event.optionalTypeRegex ); // [type][.namespace] + if( match ){ + var type = match[1] ? match[1] : undefined; + var namespace = match[2] ? match[2] : undefined; + + for( var i = 0; i < all.length; i++ ){ // + var _p = all[ i ]._private = all[ i ]._private || {}; + var listeners = _p.listeners = _p.listeners || []; + + for( var j = 0; j < listeners.length; j++ ){ + var listener = listeners[ j ]; + var nsMatches = !namespace || namespace === listener.namespace; + var typeMatches = !type || listener.type === type; + var cbMatches = !callback || callback === listener.callback; + var listenerMatches = nsMatches && typeMatches && cbMatches; + + // delete listener if it matches + if( listenerMatches ){ + listeners.splice( j, 1 ); + j--; + } + } // for listeners + } // for all + } // if match + } // for events array + + } // for events map + + return self; // maintain chaining + }; // function + }, // off + + trigger: function( params ){ + var defaults = {}; + params = util.extend( {}, defaults, params ); + + return function triggerImpl( events, extraParams, fnToTrigger ){ + var self = this; + var selfIsArrayLike = self.length !== undefined; + var all = selfIsArrayLike ? self : [ self ]; // put in array if not array-like + var eventsIsString = is.string( events ); + var eventsIsObject = is.plainObject( events ); + var eventsIsEvent = is.event( events ); + var _p = this._private = this._private || {}; + var cy = _p.cy || ( is.core( this ) ? this : null ); + var hasCompounds = cy ? cy.hasCompoundNodes() : false; + + if( eventsIsString ){ // then make a plain event object for each event name + var evts = events.split( /\s+/ ); + events = []; + + for( var i = 0; i < evts.length; i++ ){ + var evt = evts[ i ]; + if( is.emptyString( evt ) ){ continue; } + + var match = evt.match( define.event.regex ); // type[.namespace] + var type = match[1]; + var namespace = match[2] ? match[2] : undefined; + + events.push( { + type: type, + namespace: namespace + } ); + } + } else if( eventsIsObject ){ // put in length 1 array + var eventArgObj = events; + + events = [ eventArgObj ]; + } + + if( extraParams ){ + if( !is.array( extraParams ) ){ // make sure extra params are in an array if specified + extraParams = [ extraParams ]; + } + } else { // otherwise, we've got nothing + extraParams = []; + } + + for( var i = 0; i < events.length; i++ ){ // trigger each event in order + var evtObj = events[ i ]; + + for( var j = 0; j < all.length; j++ ){ // for each + var triggerer = all[ j ]; + var _p = triggerer._private = triggerer._private || {}; + var listeners = _p.listeners = _p.listeners || []; + var triggererIsElement = is.element( triggerer ); + var bubbleUp = triggererIsElement || params.layout; + + // create the event for this element from the event object + var evt; + + if( eventsIsEvent ){ // then just get the object + evt = evtObj; + + evt.cyTarget = evt.cyTarget || triggerer; + evt.cy = evt.cy || cy; + + } else { // then we have to make one + evt = new Event( evtObj, { + cyTarget: triggerer, + cy: cy, + namespace: evtObj.namespace + } ); + } + + // if a layout was specified, then put it in the typed event + if( evtObj.layout ){ + evt.layout = evtObj.layout; + } + + // if triggered by layout, put in event + if( params.layout ){ + evt.layout = triggerer; + } + + // create a rendered position based on the passed position + if( evt.cyPosition ){ + var pos = evt.cyPosition; + var zoom = cy.zoom(); + var pan = cy.pan(); + + evt.cyRenderedPosition = { + x: pos.x * zoom + pan.x, + y: pos.y * zoom + pan.y + }; + } + + if( fnToTrigger ){ // then override the listeners list with just the one we specified + listeners = [ { + namespace: evt.namespace, + type: evt.type, + callback: fnToTrigger + } ]; + } + + for( var k = 0; k < listeners.length; k++ ){ // check each listener + var lis = listeners[ k ]; + var nsMatches = !lis.namespace || lis.namespace === evt.namespace || lis.namespace === define.event.universalNamespace; + var typeMatches = lis.type === evt.type; + var targetMatches = lis.delegated ? ( triggerer !== evt.cyTarget && is.element( evt.cyTarget ) && lis.selObj.matches( evt.cyTarget ) ) : (true); // we're not going to validate the hierarchy; that's too expensive + var listenerMatches = nsMatches && typeMatches && targetMatches; + + if( listenerMatches ){ // then trigger it + var args = [ evt ]; + args = args.concat( extraParams ); // add extra params to args list + + if( lis.data ){ // add on data plugged into binding + evt.data = lis.data; + } else { // or clear it in case the event obj is reused + evt.data = undefined; + } + + if( lis.unbindSelfOnTrigger || lis.unbindAllBindersOnTrigger ){ // then remove listener + listeners.splice( k, 1 ); + k--; + } + + if( lis.unbindAllBindersOnTrigger ){ // then delete the listener for all binders + var binders = lis.binders; + for( var l = 0; l < binders.length; l++ ){ + var binder = binders[ l ]; + if( !binder || binder === triggerer ){ continue; } // already handled triggerer or we can't handle it + + var binderListeners = binder._private.listeners; + for( var m = 0; m < binderListeners.length; m++ ){ + var binderListener = binderListeners[ m ]; + + if( binderListener === lis ){ // delete listener from list + binderListeners.splice( m, 1 ); + m--; + } + } + } + } + + // run the callback + var context = lis.delegated ? evt.cyTarget : triggerer; + var ret = lis.callback.apply( context, args ); + + if( ret === false || evt.isPropagationStopped() ){ + // then don't bubble + bubbleUp = false; + + if( ret === false ){ + // returning false is a shorthand for stopping propagation and preventing the def. action + evt.stopPropagation(); + evt.preventDefault(); + } + } + } // if listener matches + } // for each listener + + // bubble up event for elements + if( bubbleUp ){ + var parent = hasCompounds ? triggerer._private.parent : null; + var hasParent = parent != null && parent.length !== 0; + + if( hasParent ){ // then bubble up to parent + parent = parent[0]; + parent.trigger( evt ); + } else { // otherwise, bubble up to the core + cy.trigger( evt ); + } + } + + } // for each of all + } // for each event + + return self; // maintain chaining + }; // function + }, // trigger + + animated: function( fnParams ){ + var defaults = {}; + fnParams = util.extend( {}, defaults, fnParams ); + + return function animatedImpl(){ + var self = this; + var selfIsArrayLike = self.length !== undefined; + var all = selfIsArrayLike ? self : [ self ]; // put in array if not array-like + var cy = this._private.cy || this; + + if( !cy.styleEnabled() ){ return false; } + + var ele = all[0]; + + if( ele ){ + return ele._private.animation.current.length > 0; + } + }; + }, // animated + + clearQueue: function( fnParams ){ + var defaults = {}; + fnParams = util.extend( {}, defaults, fnParams ); + + return function clearQueueImpl(){ + var self = this; + var selfIsArrayLike = self.length !== undefined; + var all = selfIsArrayLike ? self : [ self ]; // put in array if not array-like + var cy = this._private.cy || this; + + if( !cy.styleEnabled() ){ return this; } + + for( var i = 0; i < all.length; i++ ){ + var ele = all[ i ]; + ele._private.animation.queue = []; + } + + return this; + }; + }, // clearQueue + + delay: function( fnParams ){ + var defaults = {}; + fnParams = util.extend( {}, defaults, fnParams ); + + return function delayImpl( time, complete ){ + var cy = this._private.cy || this; + + if( !cy.styleEnabled() ){ return this; } + + return this.animate( { + delay: time, + duration: time, + complete: complete + } ); + }; + }, // delay + + delayAnimation: function( fnParams ){ + var defaults = {}; + fnParams = util.extend( {}, defaults, fnParams ); + + return function delayAnimationImpl( time, complete ){ + var cy = this._private.cy || this; + + if( !cy.styleEnabled() ){ return this; } + + return this.animation( { + delay: time, + duration: time, + complete: complete + } ); + }; + }, // delay + + animation: function( fnParams ){ + var defaults = {}; + fnParams = util.extend( {}, defaults, fnParams ); + + return function animationImpl( properties, params ){ + var self = this; + var selfIsArrayLike = self.length !== undefined; + var all = selfIsArrayLike ? self : [ self ]; // put in array if not array-like + var cy = this._private.cy || this; + var isCore = !selfIsArrayLike; + var isEles = !isCore; + + if( !cy.styleEnabled() ){ return this; } + + var style = cy.style(); + + properties = util.extend( {}, properties, params ); + + if( properties.duration === undefined ){ + properties.duration = 400; + } + + switch( properties.duration ){ + case 'slow': + properties.duration = 600; + break; + case 'fast': + properties.duration = 200; + break; + } + + var propertiesEmpty = Object.keys( properties ).length === 0; + + if( propertiesEmpty ){ + return new Animation( all[0], properties ); // nothing to animate + } + + if( isEles ){ + properties.style = style.getPropsList( properties.style || properties.css ); + + properties.css = undefined; + } + + if( properties.renderedPosition && isEles ){ + var rpos = properties.renderedPosition; + var pan = cy.pan(); + var zoom = cy.zoom(); + + properties.position = { + x: ( rpos.x - pan.x ) / zoom, + y: ( rpos.y - pan.y ) / zoom + }; + } + + // override pan w/ panBy if set + if( properties.panBy && isCore ){ + var panBy = properties.panBy; + var cyPan = cy.pan(); + + properties.pan = { + x: cyPan.x + panBy.x, + y: cyPan.y + panBy.y + }; + } + + // override pan w/ center if set + var center = properties.center || properties.centre; + if( center && isCore ){ + var centerPan = cy.getCenterPan( center.eles, properties.zoom ); + + if( centerPan ){ + properties.pan = centerPan; + } + } + + // override pan & zoom w/ fit if set + if( properties.fit && isCore ){ + var fit = properties.fit; + var fitVp = cy.getFitViewport( fit.eles || fit.boundingBox, fit.padding ); + + if( fitVp ){ + properties.pan = fitVp.pan; + properties.zoom = fitVp.zoom; + } + } + + return new Animation( all[0], properties ); + }; + }, // animate + + animate: function( fnParams ){ + var defaults = {}; + fnParams = util.extend( {}, defaults, fnParams ); + + return function animateImpl( properties, params ){ + var self = this; + var selfIsArrayLike = self.length !== undefined; + var all = selfIsArrayLike ? self : [ self ]; // put in array if not array-like + var cy = this._private.cy || this; + + if( !cy.styleEnabled() ){ return this; } + + if( params ){ + properties = util.extend( {}, properties, params ); + } + + // manually hook and run the animation + for( var i = 0; i < all.length; i++ ){ + var ele = all[ i ]; + var queue = ele.animated() && (properties.queue === undefined || properties.queue); + + var ani = ele.animation( properties, (queue ? { queue: true } : undefined) ); + + ani.play(); + } + + return this; // chaining + }; + }, // animate + + stop: function( fnParams ){ + var defaults = {}; + fnParams = util.extend( {}, defaults, fnParams ); + + return function stopImpl( clearQueue, jumpToEnd ){ + var self = this; + var selfIsArrayLike = self.length !== undefined; + var all = selfIsArrayLike ? self : [ self ]; // put in array if not array-like + var cy = this._private.cy || this; + + if( !cy.styleEnabled() ){ return this; } + + for( var i = 0; i < all.length; i++ ){ + var ele = all[ i ]; + var _p = ele._private; + var anis = _p.animation.current; + + for( var j = 0; j < anis.length; j++ ){ + var ani = anis[ j ]; + var ani_p = ani._private; + + if( jumpToEnd ){ + // next iteration of the animation loop, the animation + // will go straight to the end and be removed + ani_p.duration = 0; + } + } + + // clear the queue of future animations + if( clearQueue ){ + _p.animation.queue = []; + } + + if( !jumpToEnd ){ + _p.animation.current = []; + } + } + + // we have to notify (the animation loop doesn't do it for us on `stop`) + cy.notify( { + eles: this, + type: 'draw' + } ); + + return this; + }; + } // stop + +}; // define + +module.exports = define; + +},{"./animation":2,"./event":45,"./is":83,"./promise":86,"./selector":87,"./util":100}],45:[function(_dereq_,module,exports){ +'use strict'; + +/*! +Event object based on jQuery events, MIT license + +https://jquery.org/license/ +https://tldrlegal.com/license/mit-license +https://github.com/jquery/jquery/blob/master/src/event.js +*/ + +var Event = function( src, props ){ + // Allow instantiation without the 'new' keyword + if( !(this instanceof Event) ){ + return new Event( src, props ); + } + + // Event object + if( src && src.type ){ + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = ( src.defaultPrevented ) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if( props ){ + // util.extend( this, props ); + + // more efficient to manually copy fields we use + this.type = props.type !== undefined ? props.type : this.type; + this.cy = props.cy; + this.cyTarget = props.cyTarget; + this.cyPosition = props.cyPosition; + this.cyRenderedPosition = props.cyRenderedPosition; + this.namespace = props.namespace; + this.layout = props.layout; + this.data = props.data; + this.message = props.message; + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); +}; + +function returnFalse(){ + return false; +} + +function returnTrue(){ + return true; +} + +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +Event.prototype = { + instanceString: function(){ + return 'event'; + }, + + preventDefault: function(){ + this.isDefaultPrevented = returnTrue; + + var e = this.originalEvent; + if( !e ){ + return; + } + + // if preventDefault exists run it on the original event + if( e.preventDefault ){ + e.preventDefault(); + } + }, + + stopPropagation: function(){ + this.isPropagationStopped = returnTrue; + + var e = this.originalEvent; + if( !e ){ + return; + } + + // if stopPropagation exists run it on the original event + if( e.stopPropagation ){ + e.stopPropagation(); + } + }, + + stopImmediatePropagation: function(){ + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + }, + + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse +}; + +module.exports = Event; + +},{}],46:[function(_dereq_,module,exports){ +'use strict'; + +var util = _dereq_( './util' ); +var define = _dereq_( './define' ); +var Collection = _dereq_( './collection' ); +var Core = _dereq_( './core' ); +var incExts = _dereq_( './extensions' ); +var is = _dereq_( './is' ); + +// registered extensions to cytoscape, indexed by name +var extensions = {}; + +// registered modules for extensions, indexed by name +var modules = {}; + +function setExtension( type, name, registrant ){ + + var ext = registrant; + + var overrideErr = function( field ){ + util.error( 'Can not register `' + name + '` for `' + type + '` since `' + field + '` already exists in the prototype and can not be overridden' ); + }; + + if( type === 'core' ){ + if( Core.prototype[ name ] ){ + return overrideErr( name ); + } else { + Core.prototype[ name ] = registrant; + } + + } else if( type === 'collection' ){ + if( Collection.prototype[ name ] ){ + return overrideErr( name ); + } else { + Collection.prototype[ name ] = registrant; + } + + } else if( type === 'layout' ){ + // fill in missing layout functions in the prototype + + var Layout = function( options ){ + this.options = options; + + registrant.call( this, options ); + + // make sure layout has _private for use w/ std apis like .on() + if( !is.plainObject( this._private ) ){ + this._private = {}; + } + + this._private.cy = options.cy; + this._private.listeners = []; + }; + + var layoutProto = Layout.prototype = Object.create( registrant.prototype ); + + var optLayoutFns = []; + + for( var i = 0; i < optLayoutFns.length; i++ ){ + var fnName = optLayoutFns[ i ]; + + layoutProto[ fnName ] = layoutProto[ fnName ] || function(){ return this; }; + } + + // either .start() or .run() is defined, so autogen the other + if( layoutProto.start && !layoutProto.run ){ + layoutProto.run = function(){ this.start(); return this; }; + } else if( !layoutProto.start && layoutProto.run ){ + layoutProto.start = function(){ this.run(); return this; }; + } + + if( !layoutProto.stop ){ + layoutProto.stop = function(){ + var opts = this.options; + + if( opts && opts.animate ){ + var anis = this.animations; + for( var i = 0; i < anis.length; i++ ){ + anis[ i ].stop(); + } + } + + this.trigger( 'layoutstop' ); + + return this; + }; + } + + if( !layoutProto.destroy ){ + layoutProto.destroy = function(){ + return this; + }; + } + + layoutProto.on = define.on( { layout: true } ); + layoutProto.one = define.on( { layout: true, unbindSelfOnTrigger: true } ); + layoutProto.once = define.on( { layout: true, unbindAllBindersOnTrigger: true } ); + layoutProto.off = define.off( { layout: true } ); + layoutProto.trigger = define.trigger( { layout: true } ); + + define.eventAliasesOn( layoutProto ); + + ext = Layout; // replace with our wrapped layout + + } else if( type === 'renderer' && name !== 'null' && name !== 'base' ){ + // user registered renderers inherit from base + + var BaseRenderer = getExtension( 'renderer', 'base' ); + var bProto = BaseRenderer.prototype; + var RegistrantRenderer = registrant; + var rProto = registrant.prototype; + + var Renderer = function(){ + BaseRenderer.apply( this, arguments ); + RegistrantRenderer.apply( this, arguments ); + }; + + var proto = Renderer.prototype; + + for( var pName in bProto ){ + var pVal = bProto[ pName ]; + var existsInR = rProto[ pName ] != null; + + if( existsInR ){ + return overrideErr( pName ); + } + + proto[ pName ] = pVal; // take impl from base + } + + for( var pName in rProto ){ + proto[ pName ] = rProto[ pName ]; // take impl from registrant + } + + bProto.clientFunctions.forEach( function( name ){ + proto[ name ] = proto[ name ] || function(){ + util.error( 'Renderer does not implement `renderer.' + name + '()` on its prototype' ); + }; + } ); + + ext = Renderer; + + } + + return util.setMap( { + map: extensions, + keys: [ type, name ], + value: ext + } ); +} + +function getExtension( type, name ){ + return util.getMap( { + map: extensions, + keys: [ type, name ] + } ); +} + +function setModule( type, name, moduleType, moduleName, registrant ){ + return util.setMap( { + map: modules, + keys: [ type, name, moduleType, moduleName ], + value: registrant + } ); +} + +function getModule( type, name, moduleType, moduleName ){ + return util.getMap( { + map: modules, + keys: [ type, name, moduleType, moduleName ] + } ); +} + +var extension = function(){ + // e.g. extension('renderer', 'svg') + if( arguments.length === 2 ){ + return getExtension.apply( null, arguments ); + } + + // e.g. extension('renderer', 'svg', { ... }) + else if( arguments.length === 3 ){ + return setExtension.apply( null, arguments ); + } + + // e.g. extension('renderer', 'svg', 'nodeShape', 'ellipse') + else if( arguments.length === 4 ){ + return getModule.apply( null, arguments ); + } + + // e.g. extension('renderer', 'svg', 'nodeShape', 'ellipse', { ... }) + else if( arguments.length === 5 ){ + return setModule.apply( null, arguments ); + } + + else { + util.error( 'Invalid extension access syntax' ); + } + +}; + +// allows a core instance to access extensions internally +Core.prototype.extension = extension; + +// included extensions +incExts.forEach( function( group ){ + group.extensions.forEach( function( ext ){ + setExtension( group.type, ext.name, ext.impl ); + } ); +} ); + +module.exports = extension; + +},{"./collection":26,"./core":37,"./define":44,"./extensions":47,"./is":83,"./util":100}],47:[function(_dereq_,module,exports){ +'use strict'; + +module.exports = [ + { + type: 'layout', + extensions: _dereq_( './layout' ) + }, + + { + type: 'renderer', + extensions: _dereq_( './renderer' ) + } +]; + +},{"./layout":53,"./renderer":78}],48:[function(_dereq_,module,exports){ +'use strict'; + +var util = _dereq_( '../../util' ); +var math = _dereq_( '../../math' ); +var is = _dereq_( '../../is' ); + +var defaults = { + fit: true, // whether to fit the viewport to the graph + directed: false, // whether the tree is directed downwards (or edges can point in any direction if false) + padding: 30, // padding on fit + circle: false, // put depths in concentric circles if true, put depths top down if false + spacingFactor: 1.75, // positive spacing factor, larger => more space between nodes (N.B. n/a if causes overlap) + boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h } + avoidOverlap: true, // prevents node overlap, may overflow boundingBox if not enough space + roots: undefined, // the roots of the trees + maximalAdjustments: 0, // how many times to try to position the nodes in a maximal way (i.e. no backtracking) + animate: false, // whether to transition the node positions + animationDuration: 500, // duration of animation in ms if enabled + animationEasing: undefined, // easing of animation if enabled + ready: undefined, // callback on layoutready + stop: undefined // callback on layoutstop +}; + +function BreadthFirstLayout( options ){ + this.options = util.extend( {}, defaults, options ); +} + +BreadthFirstLayout.prototype.run = function(){ + var params = this.options; + var options = params; + + var cy = params.cy; + var eles = options.eles; + var nodes = eles.nodes().not( ':parent' ); + var graph = eles; + + var bb = math.makeBoundingBox( options.boundingBox ? options.boundingBox : { + x1: 0, y1: 0, w: cy.width(), h: cy.height() + } ); + + var roots; + if( is.elementOrCollection( options.roots ) ){ + roots = options.roots; + } else if( is.array( options.roots ) ){ + var rootsArray = []; + + for( var i = 0; i < options.roots.length; i++ ){ + var id = options.roots[ i ]; + var ele = cy.getElementById( id ); + rootsArray.push( ele ); + } + + roots = cy.collection( rootsArray ); + } else if( is.string( options.roots ) ){ + roots = cy.$( options.roots ); + + } else { + if( options.directed ){ + roots = nodes.roots(); + } else { + var components = []; + var unhandledNodes = nodes; + + while( unhandledNodes.length > 0 ){ + var currComp = cy.collection(); + + eles.bfs( { + roots: unhandledNodes[0], + visit: function( i, depth, node, edge, pNode ){ + currComp = currComp.add( node ); + }, + directed: false + } ); + + unhandledNodes = unhandledNodes.not( currComp ); + components.push( currComp ); + } + + roots = cy.collection(); + for( var i = 0; i < components.length; i++ ){ + var comp = components[ i ]; + var maxDegree = comp.maxDegree( false ); + var compRoots = comp.filter( function(){ + return this.degree( false ) === maxDegree; + } ); + + roots = roots.add( compRoots ); + } + + } + } + + + var depths = []; + var foundByBfs = {}; + var id2depth = {}; + var prevNode = {}; + var prevEdge = {}; + var successors = {}; + + // find the depths of the nodes + graph.bfs( { + roots: roots, + directed: options.directed, + visit: function( i, depth, node, edge, pNode ){ + var ele = this[0]; + var id = ele.id(); + + if( !depths[ depth ] ){ + depths[ depth ] = []; + } + + depths[ depth ].push( ele ); + foundByBfs[ id ] = true; + id2depth[ id ] = depth; + prevNode[ id ] = pNode; + prevEdge[ id ] = edge; + + if( pNode ){ + var prevId = pNode.id(); + var succ = successors[ prevId ] = successors[ prevId ] || []; + + succ.push( node ); + } + } + } ); + + // check for nodes not found by bfs + var orphanNodes = []; + for( var i = 0; i < nodes.length; i++ ){ + var ele = nodes[ i ]; + + if( foundByBfs[ ele.id() ] ){ + continue; + } else { + orphanNodes.push( ele ); + } + } + + // assign orphan nodes a depth from their neighborhood + var maxChecks = orphanNodes.length * 3; + var checks = 0; + while( orphanNodes.length !== 0 && checks < maxChecks ){ + var node = orphanNodes.shift(); + var neighbors = node.neighborhood().nodes(); + var assignedDepth = false; + + for( var i = 0; i < neighbors.length; i++ ){ + var depth = id2depth[ neighbors[ i ].id() ]; + + if( depth !== undefined ){ + depths[ depth ].push( node ); + assignedDepth = true; + break; + } + } + + if( !assignedDepth ){ + orphanNodes.push( node ); + } + + checks++; + } + + // assign orphan nodes that are still left to the depth of their subgraph + while( orphanNodes.length !== 0 ){ + var node = orphanNodes.shift(); + //var subgraph = graph.bfs( node ).path; + var assignedDepth = false; + + // for( var i = 0; i < subgraph.length; i++ ){ + // var depth = id2depth[ subgraph[i].id() ]; + + // if( depth !== undefined ){ + // depths[depth].push( node ); + // assignedDepth = true; + // break; + // } + // } + + if( !assignedDepth ){ // worst case if the graph really isn't tree friendly, then just dump it in 0 + if( depths.length === 0 ){ + depths.push( [] ); + } + + depths[0].push( node ); + } + } + + // assign the nodes a depth and index + var assignDepthsToEles = function(){ + for( var i = 0; i < depths.length; i++ ){ + var eles = depths[ i ]; + + for( var j = 0; j < eles.length; j++ ){ + var ele = eles[ j ]; + + ele._private.scratch.breadthfirst = { + depth: i, + index: j + }; + } + } + }; + assignDepthsToEles(); + + + var intersectsDepth = function( node ){ // returns true if has edges pointing in from a higher depth + var edges = node.connectedEdges( function(){ + return this.data( 'target' ) === node.id(); + } ); + var thisInfo = node._private.scratch.breadthfirst; + var highestDepthOfOther = 0; + var highestOther; + for( var i = 0; i < edges.length; i++ ){ + var edge = edges[ i ]; + var otherNode = edge.source()[0]; + var otherInfo = otherNode._private.scratch.breadthfirst; + + if( thisInfo.depth <= otherInfo.depth && highestDepthOfOther < otherInfo.depth ){ + highestDepthOfOther = otherInfo.depth; + highestOther = otherNode; + } + } + + return highestOther; + }; + + // make maximal if so set by adjusting depths + for( var adj = 0; adj < options.maximalAdjustments; adj++ ){ + + var nDepths = depths.length; + var elesToMove = []; + for( var i = 0; i < nDepths; i++ ){ + var depth = depths[ i ]; + + var nDepth = depth.length; + for( var j = 0; j < nDepth; j++ ){ + var ele = depth[ j ]; + var info = ele._private.scratch.breadthfirst; + var intEle = intersectsDepth( ele ); + + if( intEle ){ + info.intEle = intEle; + elesToMove.push( ele ); + } + } + } + + for( var i = 0; i < elesToMove.length; i++ ){ + var ele = elesToMove[ i ]; + var info = ele._private.scratch.breadthfirst; + var intEle = info.intEle; + var intInfo = intEle._private.scratch.breadthfirst; + + depths[ info.depth ].splice( info.index, 1 ); // remove from old depth & index + + // add to end of new depth + var newDepth = intInfo.depth + 1; + while( newDepth > depths.length - 1 ){ + depths.push( [] ); + } + depths[ newDepth ].push( ele ); + + info.depth = newDepth; + info.index = depths[ newDepth ].length - 1; + } + + assignDepthsToEles(); + } + + // find min distance we need to leave between nodes + var minDistance = 0; + if( options.avoidOverlap ){ + for( var i = 0; i < nodes.length; i++ ){ + var n = nodes[ i ]; + var nbb = n.boundingBox(); + var w = nbb.w; + var h = nbb.h; + + minDistance = Math.max( minDistance, w, h ); + } + minDistance *= options.spacingFactor; // just to have some nice spacing + } + + // get the weighted percent for an element based on its connectivity to other levels + var cachedWeightedPercent = {}; + var getWeightedPercent = function( ele ){ + if( cachedWeightedPercent[ ele.id() ] ){ + return cachedWeightedPercent[ ele.id() ]; + } + + var eleDepth = ele._private.scratch.breadthfirst.depth; + var neighbors = ele.neighborhood().nodes().not( ':parent' ); + var percent = 0; + var samples = 0; + + for( var i = 0; i < neighbors.length; i++ ){ + var neighbor = neighbors[ i ]; + var bf = neighbor._private.scratch.breadthfirst; + var index = bf.index; + var depth = bf.depth; + var nDepth = depths[ depth ].length; + + if( eleDepth > depth || eleDepth === 0 ){ // only get influenced by elements above + percent += index / nDepth; + samples++; + } + } + + samples = Math.max( 1, samples ); + percent = percent / samples; + + if( samples === 0 ){ // so lone nodes have a "don't care" state in sorting + percent = undefined; + } + + cachedWeightedPercent[ ele.id() ] = percent; + return percent; + }; + + + // rearrange the indices in each depth level based on connectivity + + var sortFn = function( a, b ){ + var apct = getWeightedPercent( a ); + var bpct = getWeightedPercent( b ); + + return apct - bpct; + }; + + for( var times = 0; times < 3; times++ ){ // do it a few times b/c the depths are dynamic and we want a more stable result + + for( var i = 0; i < depths.length; i++ ){ + depths[ i ] = depths[ i ].sort( sortFn ); + } + assignDepthsToEles(); // and update + + } + + var biggestDepthSize = 0; + for( var i = 0; i < depths.length; i++ ){ + biggestDepthSize = Math.max( depths[ i ].length, biggestDepthSize ); + } + + var center = { + x: bb.x1 + bb.w / 2, + y: bb.x1 + bb.h / 2 + }; + + var getPosition = function( ele, isBottomDepth ){ + var info = ele._private.scratch.breadthfirst; + var depth = info.depth; + var index = info.index; + var depthSize = depths[ depth ].length; + + var distanceX = Math.max( bb.w / (depthSize + 1), minDistance ); + var distanceY = Math.max( bb.h / (depths.length + 1), minDistance ); + var radiusStepSize = Math.min( bb.w / 2 / depths.length, bb.h / 2 / depths.length ); + radiusStepSize = Math.max( radiusStepSize, minDistance ); + + if( !options.circle ){ + + var epos = { + x: center.x + (index + 1 - (depthSize + 1) / 2) * distanceX, + y: (depth + 1) * distanceY + }; + + if( isBottomDepth ){ + return epos; + } + + // var succs = successors[ ele.id() ]; + // if( succs ){ + // epos.x = 0; + // + // for( var i = 0 ; i < succs.length; i++ ){ + // var spos = pos[ succs[i].id() ]; + // + // epos.x += spos.x; + // } + // + // epos.x /= succs.length; + // } else { + // //debugger; + // } + + return epos; + + } else { + if( options.circle ){ + var radius = radiusStepSize * depth + radiusStepSize - (depths.length > 0 && depths[0].length <= 3 ? radiusStepSize / 2 : 0); + var theta = 2 * Math.PI / depths[ depth ].length * index; + + if( depth === 0 && depths[0].length === 1 ){ + radius = 1; + } + + return { + x: center.x + radius * Math.cos( theta ), + y: center.y + radius * Math.sin( theta ) + }; + + } else { + return { + x: center.x + (index + 1 - (depthSize + 1) / 2) * distanceX, + y: (depth + 1) * distanceY + }; + } + } + + }; + + // get positions in reverse depth order + var pos = {}; + for( var i = depths.length - 1; i >= 0; i-- ){ + var depth = depths[ i ]; + + for( var j = 0; j < depth.length; j++ ){ + var node = depth[ j ]; + + pos[ node.id() ] = getPosition( node, i === depths.length - 1 ); + } + } + + nodes.layoutPositions( this, options, function(){ + return pos[ this.id() ]; + } ); + + return this; // chaining +}; + +module.exports = BreadthFirstLayout; + +},{"../../is":83,"../../math":85,"../../util":100}],49:[function(_dereq_,module,exports){ +'use strict'; + +var util = _dereq_( '../../util' ); +var math = _dereq_( '../../math' ); +var is = _dereq_( '../../is' ); + +var defaults = { + fit: true, // whether to fit the viewport to the graph + padding: 30, // the padding on fit + boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h } + avoidOverlap: true, // prevents node overlap, may overflow boundingBox and radius if not enough space + radius: undefined, // the radius of the circle + startAngle: 3 / 2 * Math.PI, // where nodes start in radians + sweep: undefined, // how many radians should be between the first and last node (defaults to full circle) + clockwise: true, // whether the layout should go clockwise (true) or counterclockwise/anticlockwise (false) + sort: undefined, // a sorting function to order the nodes; e.g. function(a, b){ return a.data('weight') - b.data('weight') } + animate: false, // whether to transition the node positions + animationDuration: 500, // duration of animation in ms if enabled + animationEasing: undefined, // easing of animation if enabled + ready: undefined, // callback on layoutready + stop: undefined // callback on layoutstop +}; + +function CircleLayout( options ){ + this.options = util.extend( {}, defaults, options ); +} + +CircleLayout.prototype.run = function(){ + var params = this.options; + var options = params; + + var cy = params.cy; + var eles = options.eles; + + var clockwise = options.counterclockwise !== undefined ? !options.counterclockwise : options.clockwise; + + var nodes = eles.nodes().not( ':parent' ); + + if( options.sort ){ + nodes = nodes.sort( options.sort ); + } + + var bb = math.makeBoundingBox( options.boundingBox ? options.boundingBox : { + x1: 0, y1: 0, w: cy.width(), h: cy.height() + } ); + + var center = { + x: bb.x1 + bb.w / 2, + y: bb.y1 + bb.h / 2 + }; + + var sweep = options.sweep === undefined ? 2 * Math.PI - 2 * Math.PI / nodes.length : options.sweep; + + var dTheta = sweep / ( Math.max( 1, nodes.length - 1 ) ); + var r; + + var minDistance = 0; + for( var i = 0; i < nodes.length; i++ ){ + var n = nodes[ i ]; + var nbb = n.boundingBox(); + var w = nbb.w; + var h = nbb.h; + + minDistance = Math.max( minDistance, w, h ); + } + + if( is.number( options.radius ) ){ + r = options.radius; + } else if( nodes.length <= 1 ){ + r = 0; + } else { + r = Math.min( bb.h, bb.w ) / 2 - minDistance; + } + + // calculate the radius + if( nodes.length > 1 && options.avoidOverlap ){ // but only if more than one node (can't overlap) + minDistance *= 1.75; // just to have some nice spacing + + var dcos = Math.cos( dTheta ) - Math.cos( 0 ); + var dsin = Math.sin( dTheta ) - Math.sin( 0 ); + var rMin = Math.sqrt( minDistance * minDistance / ( dcos * dcos + dsin * dsin ) ); // s.t. no nodes overlapping + r = Math.max( rMin, r ); + } + + var getPos = function( i, ele ){ + var theta = options.startAngle + i * dTheta * ( clockwise ? 1 : -1 ); + + var rx = r * Math.cos( theta ); + var ry = r * Math.sin( theta ); + var pos = { + x: center.x + rx, + y: center.y + ry + }; + + return pos; + }; + + nodes.layoutPositions( this, options, getPos ); + + return this; // chaining +}; + +module.exports = CircleLayout; + +},{"../../is":83,"../../math":85,"../../util":100}],50:[function(_dereq_,module,exports){ +'use strict'; + +var util = _dereq_( '../../util' ); +var math = _dereq_( '../../math' ); + +var defaults = { + fit: true, // whether to fit the viewport to the graph + padding: 30, // the padding on fit + startAngle: 3 / 2 * Math.PI, // where nodes start in radians + sweep: undefined, // how many radians should be between the first and last node (defaults to full circle) + clockwise: true, // whether the layout should go clockwise (true) or counterclockwise/anticlockwise (false) + equidistant: false, // whether levels have an equal radial distance betwen them, may cause bounding box overflow + minNodeSpacing: 10, // min spacing between outside of nodes (used for radius adjustment) + boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h } + avoidOverlap: true, // prevents node overlap, may overflow boundingBox if not enough space + height: undefined, // height of layout area (overrides container height) + width: undefined, // width of layout area (overrides container width) + concentric: function( node ){ // returns numeric value for each node, placing higher nodes in levels towards the centre + return node.degree(); + }, + levelWidth: function( nodes ){ // the variation of concentric values in each level + return nodes.maxDegree() / 4; + }, + animate: false, // whether to transition the node positions + animationDuration: 500, // duration of animation in ms if enabled + animationEasing: undefined, // easing of animation if enabled + ready: undefined, // callback on layoutready + stop: undefined // callback on layoutstop +}; + +function ConcentricLayout( options ){ + this.options = util.extend( {}, defaults, options ); +} + +ConcentricLayout.prototype.run = function(){ + var params = this.options; + var options = params; + + var clockwise = options.counterclockwise !== undefined ? !options.counterclockwise : options.clockwise; + + var cy = params.cy; + + var eles = options.eles; + var nodes = eles.nodes().not( ':parent' ); + + var bb = math.makeBoundingBox( options.boundingBox ? options.boundingBox : { + x1: 0, y1: 0, w: cy.width(), h: cy.height() + } ); + + var center = { + x: bb.x1 + bb.w / 2, + y: bb.y1 + bb.h / 2 + }; + + var nodeValues = []; // { node, value } + var theta = options.startAngle; + var maxNodeSize = 0; + + for( var i = 0; i < nodes.length; i++ ){ + var node = nodes[ i ]; + var value; + + // calculate the node value + value = options.concentric.apply( node, [ node ] ); + nodeValues.push( { + value: value, + node: node + } ); + + // for style mapping + node._private.scratch.concentric = value; + } + + // in case we used the `concentric` in style + nodes.updateStyle(); + + // calculate max size now based on potentially updated mappers + for( var i = 0; i < nodes.length; i++ ){ + var node = nodes[ i ]; + var nbb = node.boundingBox(); + + maxNodeSize = Math.max( maxNodeSize, nbb.w, nbb.h ); + } + + // sort node values in descreasing order + nodeValues.sort( function( a, b ){ + return b.value - a.value; + } ); + + var levelWidth = options.levelWidth( nodes ); + + // put the values into levels + var levels = [ [] ]; + var currentLevel = levels[0]; + for( var i = 0; i < nodeValues.length; i++ ){ + var val = nodeValues[ i ]; + + if( currentLevel.length > 0 ){ + var diff = Math.abs( currentLevel[0].value - val.value ); + + if( diff >= levelWidth ){ + currentLevel = []; + levels.push( currentLevel ); + } + } + + currentLevel.push( val ); + } + + // create positions from levels + + var minDist = maxNodeSize + options.minNodeSpacing; // min dist between nodes + + if( !options.avoidOverlap ){ // then strictly constrain to bb + var firstLvlHasMulti = levels.length > 0 && levels[0].length > 1; + var maxR = ( Math.min( bb.w, bb.h ) / 2 - minDist ); + var rStep = maxR / ( levels.length + firstLvlHasMulti ? 1 : 0 ); + + minDist = Math.min( minDist, rStep ); + } + + // find the metrics for each level + var r = 0; + for( var i = 0; i < levels.length; i++ ){ + var level = levels[ i ]; + var sweep = options.sweep === undefined ? 2 * Math.PI - 2 * Math.PI / level.length : options.sweep; + var dTheta = level.dTheta = sweep / ( Math.max( 1, level.length - 1 ) ); + + // calculate the radius + if( level.length > 1 && options.avoidOverlap ){ // but only if more than one node (can't overlap) + var dcos = Math.cos( dTheta ) - Math.cos( 0 ); + var dsin = Math.sin( dTheta ) - Math.sin( 0 ); + var rMin = Math.sqrt( minDist * minDist / ( dcos * dcos + dsin * dsin ) ); // s.t. no nodes overlapping + + r = Math.max( rMin, r ); + } + + level.r = r; + + r += minDist; + } + + if( options.equidistant ){ + var rDeltaMax = 0; + var r = 0; + + for( var i = 0; i < levels.length; i++ ){ + var level = levels[ i ]; + var rDelta = level.r - r; + + rDeltaMax = Math.max( rDeltaMax, rDelta ); + } + + r = 0; + for( var i = 0; i < levels.length; i++ ){ + var level = levels[ i ]; + + if( i === 0 ){ + r = level.r; + } + + level.r = r; + + r += rDeltaMax; + } + } + + // calculate the node positions + var pos = {}; // id => position + for( var i = 0; i < levels.length; i++ ){ + var level = levels[ i ]; + var dTheta = level.dTheta; + var r = level.r; + + for( var j = 0; j < level.length; j++ ){ + var val = level[ j ]; + var theta = options.startAngle + (clockwise ? 1 : -1) * dTheta * j; + + var p = { + x: center.x + r * Math.cos( theta ), + y: center.y + r * Math.sin( theta ) + }; + + pos[ val.node.id() ] = p; + } + } + + // position the nodes + nodes.layoutPositions( this, options, function(){ + var id = this.id(); + + return pos[ id ]; + } ); + + return this; // chaining +}; + +module.exports = ConcentricLayout; + +},{"../../math":85,"../../util":100}],51:[function(_dereq_,module,exports){ +'use strict'; + +/* +The CoSE layout was written by Gerardo Huck. +https://www.linkedin.com/in/gerardohuck/ + +Based on the following article: +http://dl.acm.org/citation.cfm?id=1498047 + +Modifications tracked on Github. +*/ + +var util = _dereq_( '../../util' ); +var math = _dereq_( '../../math' ); +var Thread = _dereq_( '../../thread' ); +var is = _dereq_( '../../is' ); + +var DEBUG; + +/** + * @brief : default layout options + */ +var defaults = { + // Called on `layoutready` + ready: function(){}, + + // Called on `layoutstop` + stop: function(){}, + + // Whether to animate while running the layout + animate: true, + + // The layout animates only after this many milliseconds + // (prevents flashing on fast runs) + animationThreshold: 250, + + // Number of iterations between consecutive screen positions update + // (0 -> only updated on the end) + refresh: 20, + + // Whether to fit the network view after when done + fit: true, + + // Padding on fit + padding: 30, + + // Constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h } + boundingBox: undefined, + + // Extra spacing between components in non-compound graphs + componentSpacing: 100, + + // Node repulsion (non overlapping) multiplier + nodeRepulsion: function( node ){ return 400000; }, + + // Node repulsion (overlapping) multiplier + nodeOverlap: 10, + + // Ideal edge (non nested) length + idealEdgeLength: function( edge ){ return 10; }, + + // Divisor to compute edge forces + edgeElasticity: function( edge ){ return 100; }, + + // Nesting factor (multiplier) to compute ideal edge length for nested edges + nestingFactor: 5, + + // Gravity force (constant) + gravity: 80, + + // Maximum number of iterations to perform + numIter: 1000, + + // Initial temperature (maximum node displacement) + initialTemp: 200, + + // Cooling factor (how the temperature is reduced between consecutive iterations + coolingFactor: 0.95, + + // Lower temperature threshold (below this point the layout will end) + minTemp: 1.0, + + // Whether to use threading to speed up the layout + useMultitasking: true +}; + + +/** + * @brief : constructor + * @arg options : object containing layout options + */ +function CoseLayout( options ){ + this.options = util.extend( {}, defaults, options ); + + this.options.layout = this; +} + + +/** + * @brief : runs the layout + */ +CoseLayout.prototype.run = function(){ + var options = this.options; + var cy = options.cy; + var layout = this; + var thread = this.thread; + + if( !thread || thread.stopped() ){ + thread = this.thread = Thread( { disabled: !options.useMultitasking } ); + } + + layout.stopped = false; + + layout.trigger( { type: 'layoutstart', layout: layout } ); + + // Set DEBUG - Global variable + if( true === options.debug ){ + DEBUG = true; + } else { + DEBUG = false; + } + + // Initialize layout info + var layoutInfo = createLayoutInfo( cy, layout, options ); + + // Show LayoutInfo contents if debugging + if( DEBUG ){ + printLayoutInfo( layoutInfo ); + } + + // If required, randomize node positions + // if (true === options.randomize) { + randomizePositions( layoutInfo, cy ); + // } + + var startTime = Date.now(); + var refreshRequested = false; + var refresh = function( rOpts ){ + rOpts = rOpts || {}; + + if( refreshRequested && !rOpts.next ){ + return; + } + + if( !rOpts.force && Date.now() - startTime < options.animationThreshold ){ + return; + } + + refreshRequested = true; + + util.requestAnimationFrame( function(){ + refreshPositions( layoutInfo, cy, options ); + + // Fit the graph if necessary + if( true === options.fit ){ + cy.fit( options.padding ); + } + + refreshRequested = false; + + if( rOpts.next ){ rOpts.next(); } + }); + }; + + thread.on( 'message', function( e ){ + var layoutNodes = e.message; + + layoutInfo.layoutNodes = layoutNodes; + refresh(); + } ); + + thread.pass( { + layoutInfo: layoutInfo, + options: { + animate: options.animate, + refresh: options.refresh, + componentSpacing: options.componentSpacing, + nodeOverlap: options.nodeOverlap, + nestingFactor: options.nestingFactor, + gravity: options.gravity, + numIter: options.numIter, + initialTemp: options.initialTemp, + coolingFactor: options.coolingFactor, + minTemp: options.minTemp + } + } ).run( function( pass ){ + var layoutInfo = pass.layoutInfo; + var options = pass.options; + var stopped = false; + + /** + * @brief : Performs one iteration of the physical simulation + * @arg layoutInfo : LayoutInfo object already initialized + * @arg cy : Cytoscape object + * @arg options : Layout options + */ + var step = function( layoutInfo, options, step ){ + // var s = "\n\n###############################"; + // s += "\nSTEP: " + step; + // s += "\n###############################\n"; + // logDebug(s); + + // Calculate node repulsions + calculateNodeForces( layoutInfo, options ); + // Calculate edge forces + calculateEdgeForces( layoutInfo, options ); + // Calculate gravity forces + calculateGravityForces( layoutInfo, options ); + // Propagate forces from parent to child + propagateForces( layoutInfo, options ); + // Update positions based on calculated forces + updatePositions( layoutInfo, options ); + }; + + /** + * @brief : Computes the node repulsion forces + */ + var calculateNodeForces = function( layoutInfo, options ){ + // Go through each of the graphs in graphSet + // Nodes only repel each other if they belong to the same graph + // var s = 'calculateNodeForces'; + // logDebug(s); + for( var i = 0; i < layoutInfo.graphSet.length; i ++ ){ + var graph = layoutInfo.graphSet[ i ]; + var numNodes = graph.length; + + // s = "Set: " + graph.toString(); + // logDebug(s); + + // Now get all the pairs of nodes + // Only get each pair once, (A, B) = (B, A) + for( var j = 0; j < numNodes; j++ ){ + var node1 = layoutInfo.layoutNodes[ layoutInfo.idToIndex[ graph[ j ] ] ]; + + for( var k = j + 1; k < numNodes; k++ ){ + var node2 = layoutInfo.layoutNodes[ layoutInfo.idToIndex[ graph[ k ] ] ]; + + nodeRepulsion( node1, node2, layoutInfo, options ); + } + } + } + }; + + /** + * @brief : Compute the node repulsion forces between a pair of nodes + */ + var nodeRepulsion = function( node1, node2, layoutInfo, options ){ + // var s = "Node repulsion. Node1: " + node1.id + " Node2: " + node2.id; + + var cmptId1 = node1.cmptId; + var cmptId2 = node2.cmptId; + + if( cmptId1 !== cmptId2 && !layoutInfo.isCompound ){ return; } + + // Get direction of line connecting both node centers + var directionX = node2.positionX - node1.positionX; + var directionY = node2.positionY - node1.positionY; + // s += "\ndirectionX: " + directionX + ", directionY: " + directionY; + + // If both centers are the same, apply a random force + if( 0 === directionX && 0 === directionY ){ + // s += "\nNodes have the same position."; + return; // TODO could be improved with random force + } + + var overlap = nodesOverlap( node1, node2, directionX, directionY ); + + if( overlap > 0 ){ + // s += "\nNodes DO overlap."; + // s += "\nOverlap: " + overlap; + // If nodes overlap, repulsion force is proportional + // to the overlap + var force = options.nodeOverlap * overlap; + + // Compute the module and components of the force vector + var distance = Math.sqrt( directionX * directionX + directionY * directionY ); + // s += "\nDistance: " + distance; + var forceX = force * directionX / distance; + var forceY = force * directionY / distance; + + } else { + // s += "\nNodes do NOT overlap."; + // If there's no overlap, force is inversely proportional + // to squared distance + + // Get clipping points for both nodes + var point1 = findClippingPoint( node1, directionX, directionY ); + var point2 = findClippingPoint( node2, -1 * directionX, -1 * directionY ); + + // Use clipping points to compute distance + var distanceX = point2.x - point1.x; + var distanceY = point2.y - point1.y; + var distanceSqr = distanceX * distanceX + distanceY * distanceY; + var distance = Math.sqrt( distanceSqr ); + // s += "\nDistance: " + distance; + + // Compute the module and components of the force vector + var force = ( node1.nodeRepulsion + node2.nodeRepulsion ) / distanceSqr; + var forceX = force * distanceX / distance; + var forceY = force * distanceY / distance; + } + + // Apply force + if( !node1.isLocked ){ + node1.offsetX -= forceX; + node1.offsetY -= forceY; + } + + if( !node2.isLocked ){ + node2.offsetX += forceX; + node2.offsetY += forceY; + } + + // s += "\nForceX: " + forceX + " ForceY: " + forceY; + // logDebug(s); + + return; + }; + + /** + * @brief : Determines whether two nodes overlap or not + * @return : Amount of overlapping (0 => no overlap) + */ + var nodesOverlap = function( node1, node2, dX, dY ){ + + if( dX > 0 ){ + var overlapX = node1.maxX - node2.minX; + } else { + var overlapX = node2.maxX - node1.minX; + } + + if( dY > 0 ){ + var overlapY = node1.maxY - node2.minY; + } else { + var overlapY = node2.maxY - node1.minY; + } + + if( overlapX >= 0 && overlapY >= 0 ){ + return Math.sqrt( overlapX * overlapX + overlapY * overlapY ); + } else { + return 0; + } + }; + + /** + * @brief : Finds the point in which an edge (direction dX, dY) intersects + * the rectangular bounding box of it's source/target node + */ + var findClippingPoint = function( node, dX, dY ){ + + // Shorcuts + var X = node.positionX; + var Y = node.positionY; + var H = node.height || 1; + var W = node.width || 1; + var dirSlope = dY / dX; + var nodeSlope = H / W; + + // var s = 'Computing clipping point of node ' + node.id + + // " . Height: " + H + ", Width: " + W + + // "\nDirection " + dX + ", " + dY; + // + // Compute intersection + var res = {}; + do { + // Case: Vertical direction (up) + if( 0 === dX && 0 < dY ){ + res.x = X; + // s += "\nUp direction"; + res.y = Y + H / 2; + break; + } + + // Case: Vertical direction (down) + if( 0 === dX && 0 > dY ){ + res.x = X; + res.y = Y + H / 2; + // s += "\nDown direction"; + break; + } + + // Case: Intersects the right border + if( 0 < dX && + -1 * nodeSlope <= dirSlope && + dirSlope <= nodeSlope ){ + res.x = X + W / 2; + res.y = Y + (W * dY / 2 / dX); + // s += "\nRightborder"; + break; + } + + // Case: Intersects the left border + if( 0 > dX && + -1 * nodeSlope <= dirSlope && + dirSlope <= nodeSlope ){ + res.x = X - W / 2; + res.y = Y - (W * dY / 2 / dX); + // s += "\nLeftborder"; + break; + } + + // Case: Intersects the top border + if( 0 < dY && + ( dirSlope <= -1 * nodeSlope || + dirSlope >= nodeSlope ) ){ + res.x = X + (H * dX / 2 / dY); + res.y = Y + H / 2; + // s += "\nTop border"; + break; + } + + // Case: Intersects the bottom border + if( 0 > dY && + ( dirSlope <= -1 * nodeSlope || + dirSlope >= nodeSlope ) ){ + res.x = X - (H * dX / 2 / dY); + res.y = Y - H / 2; + // s += "\nBottom border"; + break; + } + + } while( false); + + // s += "\nClipping point found at " + res.x + ", " + res.y; + // logDebug(s); + return res; + }; + + /** + * @brief : Calculates all edge forces + */ + var calculateEdgeForces = function( layoutInfo, options ){ + // Iterate over all edges + for( var i = 0; i < layoutInfo.edgeSize; i++ ){ + // Get edge, source & target nodes + var edge = layoutInfo.layoutEdges[ i ]; + var sourceIx = layoutInfo.idToIndex[ edge.sourceId ]; + var source = layoutInfo.layoutNodes[ sourceIx ]; + var targetIx = layoutInfo.idToIndex[ edge.targetId ]; + var target = layoutInfo.layoutNodes[ targetIx ]; + + // Get direction of line connecting both node centers + var directionX = target.positionX - source.positionX; + var directionY = target.positionY - source.positionY; + + // If both centers are the same, do nothing. + // A random force has already been applied as node repulsion + if( 0 === directionX && 0 === directionY ){ + return; + } + + // Get clipping points for both nodes + var point1 = findClippingPoint( source, directionX, directionY ); + var point2 = findClippingPoint( target, -1 * directionX, -1 * directionY ); + + + var lx = point2.x - point1.x; + var ly = point2.y - point1.y; + var l = Math.sqrt( lx * lx + ly * ly ); + + var force = Math.pow( edge.idealLength - l, 2 ) / edge.elasticity; + + if( 0 !== l ){ + var forceX = force * lx / l; + var forceY = force * ly / l; + } else { + var forceX = 0; + var forceY = 0; + } + + // Add this force to target and source nodes + if( !source.isLocked ){ + source.offsetX += forceX; + source.offsetY += forceY; + } + + if( !target.isLocked ){ + target.offsetX -= forceX; + target.offsetY -= forceY; + } + + // var s = 'Edge force between nodes ' + source.id + ' and ' + target.id; + // s += "\nDistance: " + l + " Force: (" + forceX + ", " + forceY + ")"; + // logDebug(s); + } + }; + + /** + * @brief : Computes gravity forces for all nodes + */ + var calculateGravityForces = function( layoutInfo, options ){ + var distThreshold = 1; + + // var s = 'calculateGravityForces'; + // logDebug(s); + for( var i = 0; i < layoutInfo.graphSet.length; i ++ ){ + var graph = layoutInfo.graphSet[ i ]; + var numNodes = graph.length; + + // s = "Set: " + graph.toString(); + // logDebug(s); + + // Compute graph center + if( 0 === i ){ + var centerX = layoutInfo.clientHeight / 2; + var centerY = layoutInfo.clientWidth / 2; + } else { + // Get Parent node for this graph, and use its position as center + var temp = layoutInfo.layoutNodes[ layoutInfo.idToIndex[ graph[0] ] ]; + var parent = layoutInfo.layoutNodes[ layoutInfo.idToIndex[ temp.parentId ] ]; + var centerX = parent.positionX; + var centerY = parent.positionY; + } + // s = "Center found at: " + centerX + ", " + centerY; + // logDebug(s); + + // Apply force to all nodes in graph + for( var j = 0; j < numNodes; j++ ){ + var node = layoutInfo.layoutNodes[ layoutInfo.idToIndex[ graph[ j ] ] ]; + // s = "Node: " + node.id; + + if( node.isLocked ){ continue; } + + var dx = centerX - node.positionX; + var dy = centerY - node.positionY; + var d = Math.sqrt( dx * dx + dy * dy ); + if( d > distThreshold ){ + var fx = options.gravity * dx / d; + var fy = options.gravity * dy / d; + node.offsetX += fx; + node.offsetY += fy; + // s += ": Applied force: " + fx + ", " + fy; + } else { + // s += ": skypped since it's too close to center"; + } + // logDebug(s); + } + } + }; + + /** + * @brief : This function propagates the existing offsets from + * parent nodes to its descendents. + * @arg layoutInfo : layoutInfo Object + * @arg cy : cytoscape Object + * @arg options : Layout options + */ + var propagateForces = function( layoutInfo, options ){ + // Inline implementation of a queue, used for traversing the graph in BFS order + var queue = []; + var start = 0; // Points to the start the queue + var end = -1; // Points to the end of the queue + + // logDebug('propagateForces'); + + // Start by visiting the nodes in the root graph + queue.push.apply( queue, layoutInfo.graphSet[0] ); + end += layoutInfo.graphSet[0].length; + + // Traverse the graph, level by level, + while( start <= end ){ + // Get the node to visit and remove it from queue + var nodeId = queue[ start++ ]; + var nodeIndex = layoutInfo.idToIndex[ nodeId ]; + var node = layoutInfo.layoutNodes[ nodeIndex ]; + var children = node.children; + + // We only need to process the node if it's compound + if( 0 < children.length && !node.isLocked ){ + var offX = node.offsetX; + var offY = node.offsetY; + + // var s = "Propagating offset from parent node : " + node.id + + // ". OffsetX: " + offX + ". OffsetY: " + offY; + // s += "\n Children: " + children.toString(); + // logDebug(s); + + for( var i = 0; i < children.length; i++ ){ + var childNode = layoutInfo.layoutNodes[ layoutInfo.idToIndex[ children[ i ] ] ]; + // Propagate offset + childNode.offsetX += offX; + childNode.offsetY += offY; + // Add children to queue to be visited + queue[ ++end ] = children[ i ]; + } + + // Reset parent offsets + node.offsetX = 0; + node.offsetY = 0; + } + + } + }; + + /** + * @brief : Updates the layout model positions, based on + * the accumulated forces + */ + var updatePositions = function( layoutInfo, options ){ + // var s = 'Updating positions'; + // logDebug(s); + + // Reset boundaries for compound nodes + for( var i = 0; i < layoutInfo.nodeSize; i++ ){ + var n = layoutInfo.layoutNodes[ i ]; + if( 0 < n.children.length ){ + // logDebug("Resetting boundaries of compound node: " + n.id); + n.maxX = undefined; + n.minX = undefined; + n.maxY = undefined; + n.minY = undefined; + } + } + + for( var i = 0; i < layoutInfo.nodeSize; i++ ){ + var n = layoutInfo.layoutNodes[ i ]; + if( 0 < n.children.length || n.isLocked ){ + // No need to set compound or locked node position + // logDebug("Skipping position update of node: " + n.id); + continue; + } + // s = "Node: " + n.id + " Previous position: (" + + // n.positionX + ", " + n.positionY + ")."; + + // Limit displacement in order to improve stability + var tempForce = limitForce( n.offsetX, n.offsetY, layoutInfo.temperature ); + n.positionX += tempForce.x; + n.positionY += tempForce.y; + n.offsetX = 0; + n.offsetY = 0; + n.minX = n.positionX - n.width; + n.maxX = n.positionX + n.width; + n.minY = n.positionY - n.height; + n.maxY = n.positionY + n.height; + // s += " New Position: (" + n.positionX + ", " + n.positionY + ")."; + // logDebug(s); + + // Update ancestry boudaries + updateAncestryBoundaries( n, layoutInfo ); + } + + // Update size, position of compund nodes + for( var i = 0; i < layoutInfo.nodeSize; i++ ){ + var n = layoutInfo.layoutNodes[ i ]; + if( 0 < n.children.length && !n.isLocked ){ + n.positionX = (n.maxX + n.minX) / 2; + n.positionY = (n.maxY + n.minY) / 2; + n.width = n.maxX - n.minX; + n.height = n.maxY - n.minY; + // s = "Updating position, size of compound node " + n.id; + // s += "\nPositionX: " + n.positionX + ", PositionY: " + n.positionY; + // s += "\nWidth: " + n.width + ", Height: " + n.height; + // logDebug(s); + } + } + }; + + /** + * @brief : Limits a force (forceX, forceY) to be not + * greater (in modulo) than max. + 8 Preserves force direction. + */ + var limitForce = function( forceX, forceY, max ){ + // var s = "Limiting force: (" + forceX + ", " + forceY + "). Max: " + max; + var force = Math.sqrt( forceX * forceX + forceY * forceY ); + + if( force > max ){ + var res = { + x: max * forceX / force, + y: max * forceY / force + }; + + } else { + var res = { + x: forceX, + y: forceY + }; + } + + // s += ".\nResult: (" + res.x + ", " + res.y + ")"; + // logDebug(s); + + return res; + }; + + /** + * @brief : Function used for keeping track of compound node + * sizes, since they should bound all their subnodes. + */ + var updateAncestryBoundaries = function( node, layoutInfo ){ + // var s = "Propagating new position/size of node " + node.id; + var parentId = node.parentId; + if( null == parentId ){ + // If there's no parent, we are done + // s += ". No parent node."; + // logDebug(s); + return; + } + + // Get Parent Node + var p = layoutInfo.layoutNodes[ layoutInfo.idToIndex[ parentId ] ]; + var flag = false; + + // MaxX + if( null == p.maxX || node.maxX + p.padRight > p.maxX ){ + p.maxX = node.maxX + p.padRight; + flag = true; + // s += "\nNew maxX for parent node " + p.id + ": " + p.maxX; + } + + // MinX + if( null == p.minX || node.minX - p.padLeft < p.minX ){ + p.minX = node.minX - p.padLeft; + flag = true; + // s += "\nNew minX for parent node " + p.id + ": " + p.minX; + } + + // MaxY + if( null == p.maxY || node.maxY + p.padBottom > p.maxY ){ + p.maxY = node.maxY + p.padBottom; + flag = true; + // s += "\nNew maxY for parent node " + p.id + ": " + p.maxY; + } + + // MinY + if( null == p.minY || node.minY - p.padTop < p.minY ){ + p.minY = node.minY - p.padTop; + flag = true; + // s += "\nNew minY for parent node " + p.id + ": " + p.minY; + } + + // If updated boundaries, propagate changes upward + if( flag ){ + // logDebug(s); + return updateAncestryBoundaries( p, layoutInfo ); + } + + // s += ". No changes in boundaries/position of parent node " + p.id; + // logDebug(s); + return; + }; + + var separateComponents = function( layutInfo, options ){ + var nodes = layoutInfo.layoutNodes; + var components = []; + + for( var i = 0; i < nodes.length; i++ ){ + var node = nodes[ i ]; + var cid = node.cmptId; + var component = components[ cid ] = components[ cid ] || []; + + component.push( node ); + } + + var totalA = 0; + + for( var i = 0; i < components.length; i++ ){ + var c = components[ i ]; + + if( !c ){ continue; } + + c.x1 = Infinity; + c.x2 = -Infinity; + c.y1 = Infinity; + c.y2 = -Infinity; + + for( var j = 0; j < c.length; j++ ){ + var n = c[ j ]; + + c.x1 = Math.min( c.x1, n.positionX - n.width / 2 ); + c.x2 = Math.max( c.x2, n.positionX + n.width / 2 ); + c.y1 = Math.min( c.y1, n.positionY - n.height / 2 ); + c.y2 = Math.max( c.y2, n.positionY + n.height / 2 ); + } + + c.w = c.x2 - c.x1; + c.h = c.y2 - c.y1; + + totalA += c.w * c.h; + } + + components.sort( function( c1, c2 ){ + return c2.w * c2.h - c1.w * c1.h; + } ); + + var x = 0; + var y = 0; + var usedW = 0; + var rowH = 0; + var maxRowW = Math.sqrt( totalA ) * layoutInfo.clientWidth / layoutInfo.clientHeight; + + for( var i = 0; i < components.length; i++ ){ + var c = components[ i ]; + + if( !c ){ continue; } + + for( var j = 0; j < c.length; j++ ){ + var n = c[ j ]; + + if( !n.isLocked ){ + n.positionX += x; + n.positionY += y; + } + } + + x += c.w + options.componentSpacing; + usedW += c.w + options.componentSpacing; + rowH = Math.max( rowH, c.h ); + + if( usedW > maxRowW ){ + y += rowH + options.componentSpacing; + x = 0; + usedW = 0; + rowH = 0; + } + } + }; + + var mainLoop = function( i ){ + if( stopped ){ + // logDebug("Layout manually stopped. Stopping computation in step " + i); + return false; + } + + // Do one step in the phisical simulation + step( layoutInfo, options, i ); + + // Update temperature + layoutInfo.temperature = layoutInfo.temperature * options.coolingFactor; + // logDebug("New temperature: " + layoutInfo.temperature); + + if( layoutInfo.temperature < options.minTemp ){ + // logDebug("Temperature drop below minimum threshold. Stopping computation in step " + i); + return false; + } + + return true; + }; + + var i = 0; + var loopRet; + + do { + var f = 0; + + while( f < options.refresh && i < options.numIter ){ + var loopRet = mainLoop( i ); + if( !loopRet ){ break; } + + f++; + i++; + } + + if( options.animate ){ + broadcast( layoutInfo.layoutNodes ); // eslint-disable-line no-undef + } + + } while( loopRet && i + 1 < options.numIter ); + + separateComponents( layoutInfo, options ); + + return layoutInfo; + } ).then( function( layoutInfoUpdated ){ + layoutInfo.layoutNodes = layoutInfoUpdated.layoutNodes; // get the positions + + thread.stop(); + done(); + } ); + + var done = function(){ + refresh({ + force: true, + next: function(){ + // Layout has finished + layout.one('layoutstop', options.stop); + layout.trigger({ type: 'layoutstop', layout: layout }); + } + }); + }; + + return this; // chaining +}; + + +/** + * @brief : called on continuous layouts to stop them before they finish + */ +CoseLayout.prototype.stop = function(){ + this.stopped = true; + + if( this.thread ){ + this.thread.stop(); + } + + this.trigger( 'layoutstop' ); + + return this; // chaining +}; + +CoseLayout.prototype.destroy = function(){ + if( this.thread ){ + this.thread.stop(); + } + + return this; // chaining +}; + + +/** + * @brief : Creates an object which is contains all the data + * used in the layout process + * @arg cy : cytoscape.js object + * @return : layoutInfo object initialized + */ +var createLayoutInfo = function( cy, layout, options ){ + // Shortcut + var edges = options.eles.edges(); + var nodes = options.eles.nodes(); + + var layoutInfo = { + isCompound: cy.hasCompoundNodes(), + layoutNodes: [], + idToIndex: {}, + nodeSize: nodes.size(), + graphSet: [], + indexToGraph: [], + layoutEdges: [], + edgeSize: edges.size(), + temperature: options.initialTemp, + clientWidth: cy.width(), + clientHeight: cy.width(), + boundingBox: math.makeBoundingBox( options.boundingBox ? options.boundingBox : { + x1: 0, y1: 0, w: cy.width(), h: cy.height() + } ) + }; + + var components = options.eles.components(); + var id2cmptId = {}; + + for( var i = 0; i < components.length; i++ ){ + var component = components[ i ]; + + for( var j = 0; j < component.length; j++ ){ + var node = component[ j ]; + + id2cmptId[ node.id() ] = i; + } + } + + // Iterate over all nodes, creating layout nodes + for( var i = 0; i < layoutInfo.nodeSize; i++ ){ + var n = nodes[ i ]; + var nbb = n.boundingBox(); + + var tempNode = {}; + tempNode.isLocked = n.locked(); + tempNode.id = n.data( 'id' ); + tempNode.parentId = n.data( 'parent' ); + tempNode.cmptId = id2cmptId[ n.id() ]; + tempNode.children = []; + tempNode.positionX = n.position( 'x' ); + tempNode.positionY = n.position( 'y' ); + tempNode.offsetX = 0; + tempNode.offsetY = 0; + tempNode.height = nbb.w; + tempNode.width = nbb.h; + tempNode.maxX = tempNode.positionX + tempNode.width / 2; + tempNode.minX = tempNode.positionX - tempNode.width / 2; + tempNode.maxY = tempNode.positionY + tempNode.height / 2; + tempNode.minY = tempNode.positionY - tempNode.height / 2; + tempNode.padLeft = parseFloat( n.style( 'padding-left' ) ); + tempNode.padRight = parseFloat( n.style( 'padding-right' ) ); + tempNode.padTop = parseFloat( n.style( 'padding-top' ) ); + tempNode.padBottom = parseFloat( n.style( 'padding-bottom' ) ); + + // forces + tempNode.nodeRepulsion = is.fn( options.nodeRepulsion ) ? options.nodeRepulsion.call( n, n ) : options.nodeRepulsion; + + // Add new node + layoutInfo.layoutNodes.push( tempNode ); + // Add entry to id-index map + layoutInfo.idToIndex[ tempNode.id ] = i; + } + + // Inline implementation of a queue, used for traversing the graph in BFS order + var queue = []; + var start = 0; // Points to the start the queue + var end = -1; // Points to the end of the queue + + var tempGraph = []; + + // Second pass to add child information and + // initialize queue for hierarchical traversal + for( var i = 0; i < layoutInfo.nodeSize; i++ ){ + var n = layoutInfo.layoutNodes[ i ]; + var p_id = n.parentId; + // Check if node n has a parent node + if( null != p_id ){ + // Add node Id to parent's list of children + layoutInfo.layoutNodes[ layoutInfo.idToIndex[ p_id ] ].children.push( n.id ); + } else { + // If a node doesn't have a parent, then it's in the root graph + queue[ ++end ] = n.id; + tempGraph.push( n.id ); + } + } + + // Add root graph to graphSet + layoutInfo.graphSet.push( tempGraph ); + + // Traverse the graph, level by level, + while( start <= end ){ + // Get the node to visit and remove it from queue + var node_id = queue[ start++ ]; + var node_ix = layoutInfo.idToIndex[ node_id ]; + var node = layoutInfo.layoutNodes[ node_ix ]; + var children = node.children; + if( children.length > 0 ){ + // Add children nodes as a new graph to graph set + layoutInfo.graphSet.push( children ); + // Add children to que queue to be visited + for( var i = 0; i < children.length; i++ ){ + queue[ ++end ] = children[ i ]; + } + } + } + + // Create indexToGraph map + for( var i = 0; i < layoutInfo.graphSet.length; i++ ){ + var graph = layoutInfo.graphSet[ i ]; + for( var j = 0; j < graph.length; j++ ){ + var index = layoutInfo.idToIndex[ graph[ j ] ]; + layoutInfo.indexToGraph[ index ] = i; + } + } + + // Iterate over all edges, creating Layout Edges + for( var i = 0; i < layoutInfo.edgeSize; i++ ){ + var e = edges[ i ]; + var tempEdge = {}; + tempEdge.id = e.data( 'id' ); + tempEdge.sourceId = e.data( 'source' ); + tempEdge.targetId = e.data( 'target' ); + + // Compute ideal length + var idealLength = is.fn( options.idealEdgeLength ) ? options.idealEdgeLength.call( e, e ) : options.idealEdgeLength; + var elasticity = is.fn( options.edgeElasticity ) ? options.edgeElasticity.call( e, e ) : options.edgeElasticity; + + // Check if it's an inter graph edge + var sourceIx = layoutInfo.idToIndex[ tempEdge.sourceId ]; + var targetIx = layoutInfo.idToIndex[ tempEdge.targetId ]; + var sourceGraph = layoutInfo.indexToGraph[ sourceIx ]; + var targetGraph = layoutInfo.indexToGraph[ targetIx ]; + + if( sourceGraph != targetGraph ){ + // Find lowest common graph ancestor + var lca = findLCA( tempEdge.sourceId, tempEdge.targetId, layoutInfo ); + + // Compute sum of node depths, relative to lca graph + var lcaGraph = layoutInfo.graphSet[ lca ]; + var depth = 0; + + // Source depth + var tempNode = layoutInfo.layoutNodes[ sourceIx ]; + while( -1 === lcaGraph.indexOf( tempNode.id ) ){ + tempNode = layoutInfo.layoutNodes[ layoutInfo.idToIndex[ tempNode.parentId ] ]; + depth++; + } + + // Target depth + tempNode = layoutInfo.layoutNodes[ targetIx ]; + while( -1 === lcaGraph.indexOf( tempNode.id ) ){ + tempNode = layoutInfo.layoutNodes[ layoutInfo.idToIndex[ tempNode.parentId ] ]; + depth++; + } + + // logDebug('LCA of nodes ' + tempEdge.sourceId + ' and ' + tempEdge.targetId + + // ". Index: " + lca + " Contents: " + lcaGraph.toString() + + // ". Depth: " + depth); + + // Update idealLength + idealLength *= depth * options.nestingFactor; + } + + tempEdge.idealLength = idealLength; + tempEdge.elasticity = elasticity; + + layoutInfo.layoutEdges.push( tempEdge ); + } + + // Finally, return layoutInfo object + return layoutInfo; +}; + + +/** + * @brief : This function finds the index of the lowest common + * graph ancestor between 2 nodes in the subtree + * (from the graph hierarchy induced tree) whose + * root is graphIx + * + * @arg node1: node1's ID + * @arg node2: node2's ID + * @arg layoutInfo: layoutInfo object + * + */ +var findLCA = function( node1, node2, layoutInfo ){ + // Find their common ancester, starting from the root graph + var res = findLCA_aux( node1, node2, 0, layoutInfo ); + if( 2 > res.count ){ + // If aux function couldn't find the common ancester, + // then it is the root graph + return 0; + } else { + return res.graph; + } +}; + + +/** + * @brief : Auxiliary function used for LCA computation + * + * @arg node1 : node1's ID + * @arg node2 : node2's ID + * @arg graphIx : subgraph index + * @arg layoutInfo : layoutInfo object + * + * @return : object of the form {count: X, graph: Y}, where: + * X is the number of ancesters (max: 2) found in + * graphIx (and it's subgraphs), + * Y is the graph index of the lowest graph containing + * all X nodes + */ +var findLCA_aux = function( node1, node2, graphIx, layoutInfo ){ + var graph = layoutInfo.graphSet[ graphIx ]; + // If both nodes belongs to graphIx + if( -1 < graph.indexOf( node1 ) && -1 < graph.indexOf( node2 ) ){ + return {count: 2, graph: graphIx}; + } + + // Make recursive calls for all subgraphs + var c = 0; + for( var i = 0; i < graph.length; i++ ){ + var nodeId = graph[ i ]; + var nodeIx = layoutInfo.idToIndex[ nodeId ]; + var children = layoutInfo.layoutNodes[ nodeIx ].children; + + // If the node has no child, skip it + if( 0 === children.length ){ + continue; + } + + var childGraphIx = layoutInfo.indexToGraph[ layoutInfo.idToIndex[ children[0] ] ]; + var result = findLCA_aux( node1, node2, childGraphIx, layoutInfo ); + if( 0 === result.count ){ + // Neither node1 nor node2 are present in this subgraph + continue; + } else if( 1 === result.count ){ + // One of (node1, node2) is present in this subgraph + c++; + if( 2 === c ){ + // We've already found both nodes, no need to keep searching + break; + } + } else { + // Both nodes are present in this subgraph + return result; + } + } + + return {count: c, graph: graphIx}; +}; + + +/** + * @brief: printsLayoutInfo into js console + * Only used for debbuging + */ +var printLayoutInfo = function( layoutInfo ){ + /* eslint-disable */ + + if( !DEBUG ){ + return; + } + console.debug( 'layoutNodes:' ); + for( var i = 0; i < layoutInfo.nodeSize; i++ ){ + var n = layoutInfo.layoutNodes[ i ]; + var s = + '\nindex: ' + i + + '\nId: ' + n.id + + '\nChildren: ' + n.children.toString() + + '\nparentId: ' + n.parentId + + '\npositionX: ' + n.positionX + + '\npositionY: ' + n.positionY + + '\nOffsetX: ' + n.offsetX + + '\nOffsetY: ' + n.offsetY + + '\npadLeft: ' + n.padLeft + + '\npadRight: ' + n.padRight + + '\npadTop: ' + n.padTop + + '\npadBottom: ' + n.padBottom; + + console.debug( s ); + } + + console.debug( 'idToIndex' ); + for( var i in layoutInfo.idToIndex ){ + console.debug( 'Id: ' + i + '\nIndex: ' + layoutInfo.idToIndex[ i ] ); + } + + console.debug( 'Graph Set' ); + var set = layoutInfo.graphSet; + for( var i = 0; i < set.length; i ++ ){ + console.debug( 'Set : ' + i + ': ' + set[ i ].toString() ); + } + + var s = 'IndexToGraph'; + for( var i = 0; i < layoutInfo.indexToGraph.length; i ++ ){ + s += '\nIndex : ' + i + ' Graph: ' + layoutInfo.indexToGraph[ i ]; + } + console.debug( s ); + + s = 'Layout Edges'; + for( var i = 0; i < layoutInfo.layoutEdges.length; i++ ){ + var e = layoutInfo.layoutEdges[ i ]; + s += '\nEdge Index: ' + i + ' ID: ' + e.id + + ' SouceID: ' + e.sourceId + ' TargetId: ' + e.targetId + + ' Ideal Length: ' + e.idealLength; + } + console.debug( s ); + + s = 'nodeSize: ' + layoutInfo.nodeSize; + s += '\nedgeSize: ' + layoutInfo.edgeSize; + s += '\ntemperature: ' + layoutInfo.temperature; + console.debug( s ); + + return; + /* eslint-enable */ +}; + + +/** + * @brief : Randomizes the position of all nodes + */ +var randomizePositions = function( layoutInfo, cy ){ + var width = layoutInfo.clientWidth; + var height = layoutInfo.clientHeight; + + for( var i = 0; i < layoutInfo.nodeSize; i++ ){ + var n = layoutInfo.layoutNodes[ i ]; + + // No need to randomize compound nodes or locked nodes + if( 0 === n.children.length && !n.isLocked ){ + n.positionX = Math.random() * width; + n.positionY = Math.random() * height; + } + } +}; + + +/** + * @brief : Updates the positions of nodes in the network + * @arg layoutInfo : LayoutInfo object + * @arg cy : Cytoscape object + * @arg options : Layout options + */ +var refreshPositions = function( layoutInfo, cy, options ){ + // var s = 'Refreshing positions'; + // logDebug(s); + + var layout = options.layout; + var nodes = options.eles.nodes(); + var bb = layoutInfo.boundingBox; + var coseBB = { x1: Infinity, x2: -Infinity, y1: Infinity, y2: -Infinity }; + + if( options.boundingBox ){ + nodes.forEach( function( node ){ + var lnode = layoutInfo.layoutNodes[ layoutInfo.idToIndex[ node.data( 'id' ) ] ]; + + coseBB.x1 = Math.min( coseBB.x1, lnode.positionX ); + coseBB.x2 = Math.max( coseBB.x2, lnode.positionX ); + + coseBB.y1 = Math.min( coseBB.y1, lnode.positionY ); + coseBB.y2 = Math.max( coseBB.y2, lnode.positionY ); + } ); + + coseBB.w = coseBB.x2 - coseBB.x1; + coseBB.h = coseBB.y2 - coseBB.y1; + } + + nodes.positions( function( i, ele ){ + var lnode = layoutInfo.layoutNodes[ layoutInfo.idToIndex[ ele.data( 'id' ) ] ]; + // s = "Node: " + lnode.id + ". Refreshed position: (" + + // lnode.positionX + ", " + lnode.positionY + ")."; + // logDebug(s); + + if( options.boundingBox ){ // then add extra bounding box constraint + var pctX = (lnode.positionX - coseBB.x1) / coseBB.w; + var pctY = (lnode.positionY - coseBB.y1) / coseBB.h; + + return { + x: bb.x1 + pctX * bb.w, + y: bb.y1 + pctY * bb.h + }; + } else { + return { + x: lnode.positionX, + y: lnode.positionY + }; + } + } ); + + // Trigger layoutReady only on first call + if( true !== layoutInfo.ready ){ + // s = 'Triggering layoutready'; + // logDebug(s); + layoutInfo.ready = true; + layout.one( 'layoutready', options.ready ); + layout.trigger( { type: 'layoutready', layout: this } ); + } +}; + +/** + * @brief : Logs a debug message in JS console, if DEBUG is ON + */ +// var logDebug = function(text) { +// if (DEBUG) { +// console.debug(text); +// } +// }; + +module.exports = CoseLayout; + +},{"../../is":83,"../../math":85,"../../thread":98,"../../util":100}],52:[function(_dereq_,module,exports){ +'use strict'; + +var util = _dereq_( '../../util' ); +var math = _dereq_( '../../math' ); + +var defaults = { + fit: true, // whether to fit the viewport to the graph + padding: 30, // padding used on fit + boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h } + avoidOverlap: true, // prevents node overlap, may overflow boundingBox if not enough space + avoidOverlapPadding: 10, // extra spacing around nodes when avoidOverlap: true + condense: false, // uses all available space on false, uses minimal space on true + rows: undefined, // force num of rows in the grid + cols: undefined, // force num of columns in the grid + position: function( node ){}, // returns { row, col } for element + sort: undefined, // a sorting function to order the nodes; e.g. function(a, b){ return a.data('weight') - b.data('weight') } + animate: false, // whether to transition the node positions + animationDuration: 500, // duration of animation in ms if enabled + animationEasing: undefined, // easing of animation if enabled + ready: undefined, // callback on layoutready + stop: undefined // callback on layoutstop +}; + +function GridLayout( options ){ + this.options = util.extend( {}, defaults, options ); +} + +GridLayout.prototype.run = function(){ + var params = this.options; + var options = params; + + var cy = params.cy; + var eles = options.eles; + var nodes = eles.nodes().not( ':parent' ); + + if( options.sort ){ + nodes = nodes.sort( options.sort ); + } + + var bb = math.makeBoundingBox( options.boundingBox ? options.boundingBox : { + x1: 0, y1: 0, w: cy.width(), h: cy.height() + } ); + + if( bb.h === 0 || bb.w === 0 ){ + nodes.layoutPositions( this, options, function(){ + return { x: bb.x1, y: bb.y1 }; + } ); + + } else { + + // width/height * splits^2 = cells where splits is number of times to split width + var cells = nodes.size(); + var splits = Math.sqrt( cells * bb.h / bb.w ); + var rows = Math.round( splits ); + var cols = Math.round( bb.w / bb.h * splits ); + + var small = function( val ){ + if( val == null ){ + return Math.min( rows, cols ); + } else { + var min = Math.min( rows, cols ); + if( min == rows ){ + rows = val; + } else { + cols = val; + } + } + }; + + var large = function( val ){ + if( val == null ){ + return Math.max( rows, cols ); + } else { + var max = Math.max( rows, cols ); + if( max == rows ){ + rows = val; + } else { + cols = val; + } + } + }; + + var oRows = options.rows; + var oCols = options.cols != null ? options.cols : options.columns; + + // if rows or columns were set in options, use those values + if( oRows != null && oCols != null ){ + rows = oRows; + cols = oCols; + } else if( oRows != null && oCols == null ){ + rows = oRows; + cols = Math.ceil( cells / rows ); + } else if( oRows == null && oCols != null ){ + cols = oCols; + rows = Math.ceil( cells / cols ); + } + + // otherwise use the automatic values and adjust accordingly + + // if rounding was up, see if we can reduce rows or columns + else if( cols * rows > cells ){ + var sm = small(); + var lg = large(); + + // reducing the small side takes away the most cells, so try it first + if( (sm - 1) * lg >= cells ){ + small( sm - 1 ); + } else if( (lg - 1) * sm >= cells ){ + large( lg - 1 ); + } + } else { + + // if rounding was too low, add rows or columns + while( cols * rows < cells ){ + var sm = small(); + var lg = large(); + + // try to add to larger side first (adds less in multiplication) + if( (lg + 1) * sm >= cells ){ + large( lg + 1 ); + } else { + small( sm + 1 ); + } + } + } + + var cellWidth = bb.w / cols; + var cellHeight = bb.h / rows; + + if( options.condense ){ + cellWidth = 0; + cellHeight = 0; + } + + if( options.avoidOverlap ){ + for( var i = 0; i < nodes.length; i++ ){ + var node = nodes[ i ]; + var pos = node._private.position; + + if( pos.x == null || pos.y == null ){ // for bb + pos.x = 0; + pos.y = 0; + } + + var nbb = node.boundingBox(); + var p = options.avoidOverlapPadding; + + var w = nbb.w + p; + var h = nbb.h + p; + + cellWidth = Math.max( cellWidth, w ); + cellHeight = Math.max( cellHeight, h ); + } + } + + var cellUsed = {}; // e.g. 'c-0-2' => true + + var used = function( row, col ){ + return cellUsed[ 'c-' + row + '-' + col ] ? true : false; + }; + + var use = function( row, col ){ + cellUsed[ 'c-' + row + '-' + col ] = true; + }; + + // to keep track of current cell position + var row = 0; + var col = 0; + var moveToNextCell = function(){ + col++; + if( col >= cols ){ + col = 0; + row++; + } + }; + + // get a cache of all the manual positions + var id2manPos = {}; + for( var i = 0; i < nodes.length; i++ ){ + var node = nodes[ i ]; + var rcPos = options.position( node ); + + if( rcPos && (rcPos.row !== undefined || rcPos.col !== undefined) ){ // must have at least row or col def'd + var pos = { + row: rcPos.row, + col: rcPos.col + }; + + if( pos.col === undefined ){ // find unused col + pos.col = 0; + + while( used( pos.row, pos.col ) ){ + pos.col++; + } + } else if( pos.row === undefined ){ // find unused row + pos.row = 0; + + while( used( pos.row, pos.col ) ){ + pos.row++; + } + } + + id2manPos[ node.id() ] = pos; + use( pos.row, pos.col ); + } + } + + var getPos = function( i, element ){ + var x, y; + + if( element.locked() || element.isParent() ){ + return false; + } + + // see if we have a manual position set + var rcPos = id2manPos[ element.id() ]; + if( rcPos ){ + x = rcPos.col * cellWidth + cellWidth / 2 + bb.x1; + y = rcPos.row * cellHeight + cellHeight / 2 + bb.y1; + + } else { // otherwise set automatically + + while( used( row, col ) ){ + moveToNextCell(); + } + + x = col * cellWidth + cellWidth / 2 + bb.x1; + y = row * cellHeight + cellHeight / 2 + bb.y1; + use( row, col ); + + moveToNextCell(); + } + + return { x: x, y: y }; + + }; + + nodes.layoutPositions( this, options, getPos ); + } + + return this; // chaining + +}; + +module.exports = GridLayout; + +},{"../../math":85,"../../util":100}],53:[function(_dereq_,module,exports){ +'use strict'; + +module.exports = [ + { name: 'breadthfirst', impl: _dereq_( './breadthfirst' ) }, + { name: 'circle', impl: _dereq_( './circle' ) }, + { name: 'concentric',impl: _dereq_( './concentric' ) }, + { name: 'cose', impl: _dereq_( './cose' ) }, + { name: 'grid', impl: _dereq_( './grid' ) }, + { name: 'null', impl: _dereq_( './null' ) }, + { name: 'preset', impl: _dereq_( './preset' ) }, + { name: 'random', impl: _dereq_( './random' ) } +]; + +},{"./breadthfirst":48,"./circle":49,"./concentric":50,"./cose":51,"./grid":52,"./null":54,"./preset":55,"./random":56}],54:[function(_dereq_,module,exports){ +'use strict'; + +var util = _dereq_( '../../util' ); + +// default layout options +var defaults = { + ready: function(){}, // on layoutready + stop: function(){} // on layoutstop +}; + +// constructor +// options : object containing layout options +function NullLayout( options ){ + this.options = util.extend( {}, defaults, options ); +} + +// runs the layout +NullLayout.prototype.run = function(){ + var options = this.options; + var eles = options.eles; // elements to consider in the layout + var layout = this; + + // cy is automatically populated for us in the constructor + var cy = options.cy; // jshint ignore:line + + layout.trigger( 'layoutstart' ); + + // puts all nodes at (0, 0) + eles.nodes().positions( function(){ + return { + x: 0, + y: 0 + }; + } ); + + // trigger layoutready when each node has had its position set at least once + layout.one( 'layoutready', options.ready ); + layout.trigger( 'layoutready' ); + + // trigger layoutstop when the layout stops (e.g. finishes) + layout.one( 'layoutstop', options.stop ); + layout.trigger( 'layoutstop' ); + + return this; // chaining +}; + +// called on continuous layouts to stop them before they finish +NullLayout.prototype.stop = function(){ + return this; // chaining +}; + +module.exports = NullLayout; + +},{"../../util":100}],55:[function(_dereq_,module,exports){ +'use strict'; + +var util = _dereq_( '../../util' ); +var is = _dereq_( '../../is' ); + +var defaults = { + positions: undefined, // map of (node id) => (position obj); or function(node){ return somPos; } + zoom: undefined, // the zoom level to set (prob want fit = false if set) + pan: undefined, // the pan level to set (prob want fit = false if set) + fit: true, // whether to fit to viewport + padding: 30, // padding on fit + animate: false, // whether to transition the node positions + animationDuration: 500, // duration of animation in ms if enabled + animationEasing: undefined, // easing of animation if enabled + ready: undefined, // callback on layoutready + stop: undefined // callback on layoutstop +}; + +function PresetLayout( options ){ + this.options = util.extend( {}, defaults, options ); +} + +PresetLayout.prototype.run = function(){ + var options = this.options; + var eles = options.eles; + + var nodes = eles.nodes(); + var posIsFn = is.fn( options.positions ); + + function getPosition( node ){ + if( options.positions == null ){ + return null; + } + + if( posIsFn ){ + return options.positions.apply( node, [ node ] ); + } + + var pos = options.positions[ node._private.data.id ]; + + if( pos == null ){ + return null; + } + + return pos; + } + + nodes.layoutPositions( this, options, function( i, node ){ + var position = getPosition( node ); + + if( node.locked() || position == null ){ + return false; + } + + return position; + } ); + + return this; // chaining +}; + +module.exports = PresetLayout; + +},{"../../is":83,"../../util":100}],56:[function(_dereq_,module,exports){ +'use strict'; + +var util = _dereq_( '../../util' ); +var math = _dereq_( '../../math' ); + +var defaults = { + fit: true, // whether to fit to viewport + padding: 30, // fit padding + boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h } + animate: false, // whether to transition the node positions + animationDuration: 500, // duration of animation in ms if enabled + animationEasing: undefined, // easing of animation if enabled + ready: undefined, // callback on layoutready + stop: undefined // callback on layoutstop +}; + +function RandomLayout( options ){ + this.options = util.extend( {}, defaults, options ); +} + +RandomLayout.prototype.run = function(){ + var options = this.options; + var cy = options.cy; + var eles = options.eles; + var nodes = eles.nodes().not( ':parent' ); + + var bb = math.makeBoundingBox( options.boundingBox ? options.boundingBox : { + x1: 0, y1: 0, w: cy.width(), h: cy.height() + } ); + + var getPos = function( i, node ){ + return { + x: bb.x1 + Math.round( Math.random() * bb.w ), + y: bb.y1 + Math.round( Math.random() * bb.h ) + }; + }; + + nodes.layoutPositions( this, options, getPos ); + + return this; // chaining +}; + +module.exports = RandomLayout; + +},{"../../math":85,"../../util":100}],57:[function(_dereq_,module,exports){ +'use strict'; + +var math = _dereq_( '../../../math' ); +var is = _dereq_( '../../../is' ); +var util = _dereq_( '../../../util' ); + +var BRp = {}; + +BRp.arrowShapeWidth = 0.3; + +BRp.registerArrowShapes = function(){ + var arrowShapes = this.arrowShapes = {}; + var renderer = this; + + // Contract for arrow shapes: + // 0, 0 is arrow tip + // (0, 1) is direction towards node + // (1, 0) is right + // + // functional api: + // collide: check x, y in shape + // roughCollide: called before collide, no false negatives + // draw: draw + // spacing: dist(arrowTip, nodeBoundary) + // gap: dist(edgeTip, nodeBoundary), edgeTip may != arrowTip + + var bbCollide = function( x, y, size, angle, translation, padding ){ + var x1 = translation.x - size / 2 - padding; + var x2 = translation.x + size / 2 + padding; + var y1 = translation.y - size / 2 - padding; + var y2 = translation.y + size / 2 + padding; + + var inside = (x1 <= x && x <= x2) && (y1 <= y && y <= y2); + + return inside; + }; + + var transform = function( x, y, size, angle, translation ){ + var xRotated = x * Math.cos( angle ) - y * Math.sin( angle ); + var yRotated = x * Math.sin( angle ) + y * Math.cos( angle ); + + var xScaled = xRotated * size; + var yScaled = yRotated * size; + + var xTranslated = xScaled + translation.x; + var yTranslated = yScaled + translation.y; + + return { + x: xTranslated, + y: yTranslated + }; + }; + + var transformPoints = function( pts, size, angle, translation ){ + var retPts = []; + + for( var i = 0; i < pts.length; i += 2 ){ + var x = pts[ i ]; + var y = pts[ i + 1]; + + retPts.push( transform( x, y, size, angle, translation ) ); + } + + return retPts; + }; + + var pointsToArr = function( pts ){ + var ret = []; + + for( var i = 0; i < pts.length; i++ ){ + var p = pts[ i ]; + + ret.push( p.x, p.y ); + } + + return ret; + }; + + var defineArrowShape = function( name, defn ){ + if( is.string( defn ) ){ + defn = arrowShapes[ defn ]; + } + + arrowShapes[ name ] = util.extend( { + name: name, + + points: [ + -0.15, -0.3, + 0.15, -0.3, + 0.15, 0.3, + -0.15, 0.3 + ], + + collide: function( x, y, size, angle, translation, padding ){ + var points = pointsToArr( transformPoints( this.points, size + 2 * padding, angle, translation ) ); + var inside = math.pointInsidePolygonPoints( x, y, points ); + + return inside; + }, + + roughCollide: bbCollide, + + draw: function( context, size, angle, translation ){ + var points = transformPoints( this.points, size, angle, translation ); + + renderer.arrowShapeImpl( 'polygon' )( context, points ); + }, + + spacing: function( edge ){ + return 0; + }, + + gap: function( edge ){ + return edge.pstyle( 'width' ).pfValue * 2; + } + }, defn ); + }; + + defineArrowShape( 'none', { + collide: util.falsify, + + roughCollide: util.falsify, + + draw: util.noop, + + spacing: util.zeroify, + + gap: util.zeroify + } ); + + defineArrowShape( 'triangle', { + points: [ + -0.15, -0.3, + 0, 0, + 0.15, -0.3 + ] + } ); + + defineArrowShape( 'arrow', 'triangle' ); + + defineArrowShape( 'triangle-backcurve', { + points: arrowShapes[ 'triangle' ].points, + + controlPoint: [ 0, -0.15 ], + + roughCollide: bbCollide, + + draw: function( context, size, angle, translation ){ + var ptsTrans = transformPoints( this.points, size, angle, translation ); + var ctrlPt = this.controlPoint; + var ctrlPtTrans = transform( ctrlPt[0], ctrlPt[1], size, angle, translation ); + + renderer.arrowShapeImpl( this.name )( context, ptsTrans, ctrlPtTrans ); + }, + + gap: function( edge ){ + return edge.pstyle( 'width' ).pfValue; + } + } ); + + + defineArrowShape( 'triangle-tee', { + points: [ + -0.15, -0.3, + 0, 0, + 0.15, -0.3, + -0.15, -0.3 + ], + + pointsTee: [ + -0.15, -0.4, + -0.15, -0.5, + 0.15, -0.5, + 0.15, -0.4 + ], + + collide: function( x, y, size, angle, translation, padding ){ + var triPts = pointsToArr( transformPoints( this.points, size + 2 * padding, angle, translation ) ); + var teePts = pointsToArr( transformPoints( this.pointsTee, size + 2 * padding, angle, translation ) ); + + var inside = math.pointInsidePolygonPoints( x, y, triPts ) || math.pointInsidePolygonPoints( x, y, teePts ); + + return inside; + }, + + draw: function( context, size, angle, translation ){ + var triPts = transformPoints( this.points, size, angle, translation ); + var teePts = transformPoints( this.pointsTee, size, angle, translation ); + + renderer.arrowShapeImpl( this.name )( context, triPts, teePts ); + } + } ); + + defineArrowShape( 'vee', { + points: [ + -0.15, -0.3, + 0, 0, + 0.15, -0.3, + 0, -0.15 + ], + + gap: function( edge ){ + return edge.pstyle( 'width' ).pfValue; + } + } ); + + defineArrowShape( 'circle', { + radius: 0.15, + + collide: function( x, y, size, angle, translation, padding ){ + var t = translation; + var inside = ( Math.pow( t.x - x, 2 ) + Math.pow( t.y - y, 2 ) <= Math.pow( (size + 2 * padding) * this.radius, 2 ) ); + + return inside; + }, + + draw: function( context, size, angle, translation ){ + renderer.arrowShapeImpl( this.name )( context, translation.x, translation.y, this.radius * size ); + }, + + spacing: function( edge ){ + return renderer.getArrowWidth( edge.pstyle( 'width' ).pfValue ) + * this.radius; + } + } ); + + defineArrowShape( 'inhibitor', { + points: [ + -0.15, 0, + -0.15, -0.1, + 0.15, -0.1, + 0.15, 0 + ], + + spacing: function( edge ){ + return 1; + }, + + gap: function( edge ){ + return 1; + } + } ); + + defineArrowShape( 'tee', 'inhibitor' ); + + defineArrowShape( 'square', { + points: [ + -0.15, 0.00, + 0.15, 0.00, + 0.15, -0.3, + -0.15, -0.3 + ] + } ); + + defineArrowShape( 'diamond', { + points: [ + -0.15, -0.15, + 0, -0.3, + 0.15, -0.15, + 0, 0 + ], + + gap: function( edge ){ + return edge.pstyle( 'width' ).pfValue; + } + } ); + +}; + +module.exports = BRp; + +},{"../../../is":83,"../../../math":85,"../../../util":100}],58:[function(_dereq_,module,exports){ +'use strict'; + +var math = _dereq_( '../../../math' ); +var is = _dereq_( '../../../is' ); +var util = _dereq_( '../../../util' ); +var zIndexSort = _dereq_( '../../../collection/zsort' ); + +var BRp = {}; + +BRp.registerCalculationListeners = function(){ + var cy = this.cy; + var elesToUpdate = cy.collection(); + var r = this; + + var enqueue = function( eles, e ){ + elesToUpdate.merge( eles ); + + for( var i = 0; i < eles.length; i++ ){ + var ele = eles[i]; + var _p = ele._private; + var rstyle = _p.rstyle; + + rstyle.clean = false; + _p.bbCache = null; + + var evts = rstyle.dirtyEvents = rstyle.dirtyEvents || { length: 0 }; + + if( !evts[ e.type ] ){ + evts[ e.type ] = true; + evts.length++; +// + // elesToUpdate.merge( ele ); + } + } + }; + + r.binder( cy ) + // nodes + + .on('position.* style.* free.*', 'node', function onDirtyModNode( e ){ + var node = e.cyTarget; + + enqueue( node, e ); + enqueue( node.connectedEdges(), e ); + + if( cy.hasCompoundNodes() ){ + var parents = node.parents(); + + enqueue( parents, e ); + enqueue( parents.connectedEdges(), e ); + } + }) + + .on('add.* background.*', 'node', function onDirtyAddNode( e ){ + var ele = e.cyTarget; + + enqueue( ele, e ); + }) + + // edges + + .on('add.* style.*', 'edge', function onDirtyEdge( e ){ + var edge = e.cyTarget; + + enqueue( edge, e ); + enqueue( edge.parallelEdges(), e ); + }) + + .on('remove.*', 'edge', function onDirtyRemoveEdge( e ){ + var edge = e.cyTarget; + var pEdges = edge.parallelEdges(); + + for( var i = 0; i < pEdges.length; i++ ){ + var pEdge = pEdges[i]; + + if( !pEdge.removed() ){ + enqueue( pEdge, e ); + } + } + }) + ; + + var updateEleCalcs = function( willDraw ){ + if( willDraw ){ + var fns = r.onUpdateEleCalcsFns; + + if( fns ){ for( var i = 0; i < fns.length; i++ ){ + var fn = fns[i]; + + fn( willDraw, elesToUpdate ); + } } + + r.recalculateRenderedStyle( elesToUpdate, false ); + + for( var i = 0; i < elesToUpdate.length; i++ ){ + elesToUpdate[i]._private.rstyle.dirtyEvents = null; + } + + elesToUpdate = cy.collection(); + } + }; + + r.beforeRender( updateEleCalcs, r.beforeRenderPriorities.eleCalcs ); +}; + +BRp.onUpdateEleCalcs = function( fn ){ + var fns = this.onUpdateEleCalcsFns = this.onUpdateEleCalcsFns || []; + + fns.push( fn ); +}; + +BRp.recalculateRenderedStyle = function( eles, useCache ){ + var edges = []; + var nodes = []; + + // use cache by default for perf + if( useCache === undefined ){ useCache = true; } + + for( var i = 0; i < eles.length; i++ ){ + var ele = eles[ i ]; + var _p = ele._private; + var rstyle = _p.rstyle; + + // only update if dirty and in graph + if( (useCache && rstyle.clean) || ele.removed() ){ continue; } + + if( _p.group === 'nodes' ){ + var pos = _p.position; + + nodes.push( ele ); + + rstyle.nodeX = pos.x; + rstyle.nodeY = pos.y; + rstyle.nodeW = ele.pstyle( 'width' ).pfValue; + rstyle.nodeH = ele.pstyle( 'height' ).pfValue; + } else { // edges + + edges.push( ele ); + + } // if edges + + rstyle.clean = true; + // rstyle.dirtyEvents = null; + } + + this.recalculateEdgeProjections( edges ); + this.recalculateLabelProjections( nodes, edges ); + + // update edge data from projections + for( var i = 0; i < edges.length; i++ ){ + var ele = edges[ i ]; + var _p = ele._private; + var rstyle = _p.rstyle; + var rs = _p.rscratch; + + // update rstyle positions + rstyle.srcX = rs.arrowStartX; + rstyle.srcY = rs.arrowStartY; + rstyle.tgtX = rs.arrowEndX; + rstyle.tgtY = rs.arrowEndY; + rstyle.midX = rs.midX; + rstyle.midY = rs.midY; + rstyle.labelAngle = rs.labelAngle; + rstyle.sourceLabelAngle = rs.sourceLabelAngle; + rstyle.targetLabelAngle = rs.targetLabelAngle; + } +}; + +// Project mouse +BRp.projectIntoViewport = function( clientX, clientY ){ + var offsets = this.findContainerClientCoords(); + var offsetLeft = offsets[0]; + var offsetTop = offsets[1]; + + var x = clientX - offsetLeft; + var y = clientY - offsetTop; + + x -= this.cy.pan().x; y -= this.cy.pan().y; x /= this.cy.zoom(); y /= this.cy.zoom(); + return [ x, y ]; +}; + +BRp.findContainerClientCoords = function(){ + var container = this.container; + + var bb = this.containerBB = this.containerBB || container.getBoundingClientRect(); + + return [ bb.left, bb.top, bb.right - bb.left, bb.bottom - bb.top ]; +}; + +BRp.invalidateContainerClientCoordsCache = function(){ + this.containerBB = null; +}; + +BRp.findNearestElement = function( x, y, visibleElementsOnly, isTouch ){ + return this.findNearestElements( x, y, visibleElementsOnly, isTouch )[0]; +}; + +BRp.findNearestElements = function( x, y, visibleElementsOnly, isTouch ){ + var self = this; + var r = this; + var eles = r.getCachedZSortedEles(); + var near = []; // 1 node max, 1 edge max + var zoom = r.cy.zoom(); + var hasCompounds = r.cy.hasCompoundNodes(); + var edgeThreshold = (isTouch ? 24 : 8) / zoom; + var nodeThreshold = (isTouch ? 8 : 2) / zoom; + var labelThreshold = (isTouch ? 8 : 2) / zoom; + var minSqDist = Infinity; + var nearEdge; + var nearNode; + + function addEle( ele, sqDist ){ + if( ele.isNode() ){ + if( nearNode ){ + return; // can't replace node + } else { + nearNode = ele; + near.push( ele ); + } + } + + if( ele.isEdge() && ( sqDist == null || sqDist < minSqDist ) ){ + if( nearEdge ){ // then replace existing edge + // can replace only if same z-index + if( nearEdge.pstyle( 'z-index' ).value === ele.pstyle('z-index').value ){ + for( var i = 0; i < near.length; i++ ){ + if( near[i].isEdge() ){ + near[i] = ele; + nearEdge = ele; + minSqDist = sqDist != null ? sqDist : minSqDist; + break; + } + } + } + } else { + near.push( ele ); + nearEdge = ele; + minSqDist = sqDist != null ? sqDist : minSqDist; + } + } + } + + function checkNode( node ){ + var _p = node._private; + + if( node.pstyle( 'events' ).strValue === 'no' ){ return; } + + var width = node.outerWidth() + 2 * nodeThreshold; + var height = node.outerHeight() + 2 * nodeThreshold; + var hw = width / 2; + var hh = height / 2; + var pos = _p.position; + + if( + pos.x - hw <= x && x <= pos.x + hw // bb check x + && + pos.y - hh <= y && y <= pos.y + hh // bb check y + ){ + var visible = !visibleElementsOnly || ( node.visible() && !node.transparent() ); + + // exit early if invisible edge and must be visible + if( visibleElementsOnly && !visible ){ + return; + } + + var shape = r.nodeShapes[ self.getNodeShape( node ) ]; + + if( + shape.checkPoint( x, y, 0, width, height, pos.x, pos.y ) + ){ + addEle( node, 0 ); + } + + } + } + + function checkEdge( edge ){ + var _p = edge._private; + + if( edge.pstyle('events').strValue === 'no' ){ return; } + + var rs = _p.rscratch; + var width = edge.pstyle( 'width' ).pfValue / 2 + edgeThreshold; // more like a distance radius from centre + var widthSq = width * width; + var width2 = width * 2; + var src = _p.source; + var tgt = _p.target; + var inEdgeBB = false; + var sqDist; + + // exit early if invisible edge and must be visible + var passedVisibilityCheck; + var passesVisibilityCheck = function(){ + if( passedVisibilityCheck !== undefined ){ + return passedVisibilityCheck; + } + + if( !visibleElementsOnly ){ + passedVisibilityCheck = true; + return true; + } + + var visible = edge.visible() && !edge.transparent(); + if( visible ){ + passedVisibilityCheck = true; + return true; + } + + passedVisibilityCheck = false; + return false; + }; + + if( rs.edgeType === 'segments' || rs.edgeType === 'straight' || rs.edgeType === 'haystack' ){ + var pts = rs.allpts; + + for( var i = 0; i + 3 < pts.length; i += 2 ){ + if( + (inEdgeBB = math.inLineVicinity( x, y, pts[ i ], pts[ i + 1], pts[ i + 2], pts[ i + 3], width2 )) + && passesVisibilityCheck() && + widthSq > ( sqDist = math.sqdistToFiniteLine( x, y, pts[ i ], pts[ i + 1], pts[ i + 2], pts[ i + 3] ) ) + ){ + addEle( edge, sqDist ); + } + } + + } else if( rs.edgeType === 'bezier' || rs.edgeType === 'multibezier' || rs.edgeType === 'self' || rs.edgeType === 'compound' ){ + var pts = rs.allpts; + for( var i = 0; i + 5 < rs.allpts.length; i += 4 ){ + if( + (inEdgeBB = math.inBezierVicinity( x, y, pts[ i ], pts[ i + 1], pts[ i + 2], pts[ i + 3], pts[ i + 4], pts[ i + 5], width2 )) + && passesVisibilityCheck() && + (widthSq > (sqDist = math.sqdistToQuadraticBezier( x, y, pts[ i ], pts[ i + 1], pts[ i + 2], pts[ i + 3], pts[ i + 4], pts[ i + 5] )) ) + ){ + addEle( edge, sqDist ); + } + } + } + + // if we're close to the edge but didn't hit it, maybe we hit its arrows + if( inEdgeBB && passesVisibilityCheck() ){ + var src = src || _p.source; + var tgt = tgt || _p.target; + + var eWidth = edge.pstyle( 'width' ).pfValue; + var arSize = self.getArrowWidth( eWidth ); + + var arrows = [ + { name: 'source', x: rs.arrowStartX, y: rs.arrowStartY, angle: rs.srcArrowAngle }, + { name: 'target', x: rs.arrowEndX, y: rs.arrowEndY, angle: rs.tgtArrowAngle }, + { name: 'mid-source', x: rs.midX, y: rs.midY, angle: rs.midsrcArrowAngle }, + { name: 'mid-target', x: rs.midX, y: rs.midY, angle: rs.midtgtArrowAngle } + ]; + + for( var i = 0; i < arrows.length; i++ ){ + var ar = arrows[ i ]; + var shape = r.arrowShapes[ edge.pstyle( ar.name + '-arrow-shape' ).value ]; + + if( + shape.roughCollide( x, y, arSize, ar.angle, { x: ar.x, y: ar.y }, edgeThreshold ) + && + shape.collide( x, y, arSize, ar.angle, { x: ar.x, y: ar.y }, edgeThreshold ) + ){ + addEle( edge ); + break; + } + } + } + + // for compound graphs, hitting edge may actually want a connected node instead (b/c edge may have greater z-index precedence) + if( hasCompounds && near.length > 0 ){ + checkNode( src ); + checkNode( tgt ); + } + } + + function preprop( obj, name, pre ){ + return util.getPrefixedProperty( obj, name, pre ); + } + + function checkLabel( ele, prefix ){ + var _p = ele._private; + var th = labelThreshold; + + var prefixDash; + if( prefix ){ + prefixDash = prefix + '-'; + } else { + prefixDash = ''; + } + + if( ele.pstyle( 'text-events' ).strValue === 'no' ){ return; } + + var rotation = ele.pstyle( prefixDash + 'text-rotation' ); + + // adjust bb w/ angle + if( rotation.strValue === 'autorotate' || !!rotation.pfValue ){ + + var rstyle = _p.rstyle; + var bw = ele.pstyle('text-border-width').pfValue; + var lw = preprop( rstyle, 'labelWidth', prefix ) + bw/2 + 2*th; + var lh = preprop( rstyle, 'labelHeight', prefix ) + bw/2 + 2*th; + var lx = preprop( rstyle, 'labelX', prefix ); + var ly = preprop( rstyle, 'labelY', prefix ); + + var theta = preprop( _p.rscratch, 'labelAngle', prefix ); + var cos = Math.cos( theta ); + var sin = Math.sin( theta ); + + var rotate = function( x, y ){ + x = x - lx; + y = y - ly; + + return { + x: x * cos - y * sin + lx, + y: x * sin + y * cos + ly + }; + }; + + var lx1 = lx - lw / 2; + var lx2 = lx + lw / 2; + var ly1 = ly - lh / 2; + var ly2 = ly + lh / 2; + + var px1y1 = rotate( lx1, ly1 ); + var px1y2 = rotate( lx1, ly2 ); + var px2y1 = rotate( lx2, ly1 ); + var px2y2 = rotate( lx2, ly2 ); + + var points = [ + px1y1.x, px1y1.y, + px2y1.x, px2y1.y, + px2y2.x, px2y2.y, + px1y2.x, px1y2.y + ]; + + if( math.pointInsidePolygonPoints( x, y, points ) ){ + addEle( ele ); + } + + } else { + var bb = ele.boundingBox( { + includeLabels: true, + includeNodes: false, + includeEdges: false + } ); + + // adjust bb w/ threshold + bb.x1 -= th; + bb.y1 -= th; + bb.x2 += th; + bb.y2 += th; + bb.w = bb.x2 - bb.x1; + bb.h = bb.y2 - bb.y1; + + if( math.inBoundingBox( bb, x, y ) ){ + addEle( ele ); + } + } + + } + + for( var i = eles.length - 1; i >= 0; i-- ){ // reverse order for precedence + var ele = eles[ i ]; + + if( ele.isNode() ){ + checkNode( ele ); + + checkLabel( ele ); + + } else { // then edge + checkEdge( ele ); + + checkLabel( ele ); + checkLabel( ele, 'source' ); + checkLabel( ele, 'target' ); + } + } + + return near; +}; + +// 'Give me everything from this box' +BRp.getAllInBox = function( x1, y1, x2, y2 ){ + var eles = this.getCachedZSortedEles(); + var nodes = eles.nodes; + var edges = eles.edges; + var box = []; + + var x1c = Math.min( x1, x2 ); + var x2c = Math.max( x1, x2 ); + var y1c = Math.min( y1, y2 ); + var y2c = Math.max( y1, y2 ); + + x1 = x1c; + x2 = x2c; + y1 = y1c; + y2 = y2c; + + var boxBb = math.makeBoundingBox( { + x1: x1, y1: y1, + x2: x2, y2: y2 + } ); + + for( var i = 0; i < nodes.length; i++ ){ + var node = nodes[ i ]; + var nodeBb = node.boundingBox( { + includeNodes: true, + includeEdges: false, + includeLabels: false, + includeShadows: false + } ); + + if( math.boundingBoxesIntersect( boxBb, nodeBb ) ){ + box.push( nodes[ i ] ); + } + } + + for( var e = 0; e < edges.length; e++ ){ + var edge = edges[ e ]; + var _p = edge._private; + var rs = _p.rscratch; + + if( rs.startX != null && rs.startY != null && !math.inBoundingBox( boxBb, rs.startX, rs.startY ) ){ continue; } + if( rs.endX != null && rs.endY != null && !math.inBoundingBox( boxBb, rs.endX, rs.endY ) ){ continue; } + + if( rs.edgeType === 'bezier' || rs.edgeType === 'multibezier' || rs.edgeType === 'self' || rs.edgeType === 'compound' || rs.edgeType === 'segments' || rs.edgeType === 'haystack' ){ + + var pts = _p.rstyle.bezierPts || _p.rstyle.linePts || _p.rstyle.haystackPts; + var allInside = true; + + for( var i = 0; i < pts.length; i++ ){ + if( !math.pointInBoundingBox( boxBb, pts[ i ] ) ){ + allInside = false; + break; + } + } + + if( allInside ){ + box.push( edge ); + } + + } else if( rs.edgeType === 'haystack' || rs.edgeType === 'straight' ){ + box.push( edge ); + } + + } + + return box; +}; + + +/** + * Returns the shape of the given node. If the height or width of the given node + * is set to auto, the node is considered to be a compound. + * + * @param node a node + * @return {String} shape of the node + */ +BRp.getNodeShape = function( node ){ + var r = this; + var shape = node.pstyle( 'shape' ).value; + + if( node.isParent() ){ + if( shape === 'rectangle' || shape === 'roundrectangle' ){ + return shape; + } else { + return 'rectangle'; + } + } + + if( shape === 'polygon' ){ + var points = node.pstyle( 'shape-polygon-points' ).value; + + return r.nodeShapes.makePolygon( points ).name; + } + + return shape; +}; + +BRp.updateCachedZSortedEles = function(){ + this.getCachedZSortedEles( true ); +}; + +BRp.updateCachedGrabbedEles = function(){ + var eles = this.cachedZSortedEles; + + eles.drag = []; + eles.nondrag = []; + + var grabTarget; + + for( var i = 0; i < eles.length; i++ ){ + var ele = eles[i]; + var rs = ele._private.rscratch; + + if( rs.isGrabTarget && !ele.isParent() ){ + grabTarget = ele; + } else if( rs.inDragLayer ){ + eles.drag.push( ele ); + } else { + eles.nondrag.push( ele ); + } + } + + // put the grab target node last so it's on top of its neighbourhood + if( grabTarget ){ + eles.drag.push( grabTarget ); + } +}; + +BRp.getCachedZSortedEles = function( forceRecalc ){ + if( forceRecalc || !this.cachedZSortedEles ){ + //console.time('cachezorder') + + var cyEles = this.cy.mutableElements(); + var eles = []; + + eles.nodes = []; + eles.edges = []; + + for( var i = 0; i < cyEles.length; i++ ){ + var ele = cyEles[i]; + + if( ele.animated() || (ele.visible() && !ele.transparent()) ){ + eles.push( ele ); + + if( ele.isNode() ){ + eles.nodes.push( ele ); + } else { + eles.edges.push( ele ); + } + } + } + + eles.sort( zIndexSort ); + + this.cachedZSortedEles = eles; + + this.updateCachedGrabbedEles(); + + //console.log('make cache') + + //console.timeEnd('cachezorder') + } else { + eles = this.cachedZSortedEles; + //console.log('read cache') + } + + return eles; +}; + +function pushBezierPts( r, edge, pts ){ + var qbezierAt = function( p1, p2, p3, t ){ return math.qbezierAt( p1, p2, p3, t ); }; + var _p = edge._private; + var bpts = _p.rstyle.bezierPts; + + for( var i = 0; i < r.bezierProjPcts.length; i++ ){ + var p = r.bezierProjPcts[i]; + + bpts.push( { + x: qbezierAt( pts[0], pts[2], pts[4], p ), + y: qbezierAt( pts[1], pts[3], pts[5], p ) + } ); + } +} + +BRp.projectLines = function( edge ){ + var _p = edge._private; + var rs = _p.rscratch; + var et = rs.edgeType; + + // clear the cached points state + _p.rstyle.bezierPts = null; + _p.rstyle.linePts = null; + _p.rstyle.haystackPts = null; + + if( et === 'multibezier' || et === 'bezier' || et === 'self' || et === 'compound' ){ + var bpts = _p.rstyle.bezierPts = []; // jshint ignore:line + + for( var i = 0; i + 5 < rs.allpts.length; i += 4 ){ + pushBezierPts( this, edge, rs.allpts.slice( i, i + 6 ) ); + } + } else if( et === 'segments' ){ + var lpts = _p.rstyle.linePts = []; + + for( var i = 0; i + 1 < rs.allpts.length; i += 2 ){ + lpts.push( { + x: rs.allpts[ i ], + y: rs.allpts[ i + 1] + } ); + } + } else if( et === 'haystack' ){ + var hpts = rs.haystackPts; + + _p.rstyle.haystackPts = [ + { x: hpts[0], y: hpts[1] }, + { x: hpts[2], y: hpts[3] } + ]; + } + + _p.rstyle.arrowWidth = this.getArrowWidth( edge.pstyle('width').pfValue ) * this.arrowShapeWidth; +}; + +BRp.projectBezier = BRp.projectLines; + +BRp.recalculateNodeLabelProjection = function( node ){ + var content = node.pstyle( 'label' ).strValue; + + if( is.emptyString(content) ){ return; } + + var textX, textY; + var _p = node._private; + var nodeWidth = node.width(); + var nodeHeight = node.height(); + var paddingLeft = node.pstyle('padding-left').pfValue; + var paddingRight = node.pstyle('padding-right').pfValue; + var paddingTop = node.pstyle('padding-top').pfValue; + var paddingBottom = node.pstyle('padding-bottom').pfValue; + var nodePos = _p.position; + var textHalign = node.pstyle( 'text-halign' ).strValue; + var textValign = node.pstyle( 'text-valign' ).strValue; + var rs = _p.rscratch; + var rstyle = _p.rstyle; + + switch( textHalign ){ + case 'left': + textX = nodePos.x - nodeWidth / 2 - paddingLeft; + break; + + case 'right': + textX = nodePos.x + nodeWidth / 2 + paddingRight; + break; + + default: // e.g. center + textX = nodePos.x; + } + + switch( textValign ){ + case 'top': + textY = nodePos.y - nodeHeight / 2 - paddingTop; + break; + + case 'bottom': + textY = nodePos.y + nodeHeight / 2 + paddingBottom; + break; + + default: // e.g. middle + textY = nodePos.y; + } + + rs.labelX = textX; + rs.labelY = textY; + rstyle.labelX = textX; + rstyle.labelY = textY; + + this.applyLabelDimensions( node ); +}; + +BRp.recalculateEdgeLabelProjections = function( edge ){ + var p; + var _p = edge._private; + var rs = _p.rscratch; + var r = this; + var content = { + mid: edge.pstyle('label').strValue, + source: edge.pstyle('source-label').strValue, + target: edge.pstyle('target-label').strValue + }; + + if( content.mid || content.source || content.target ){ + // then we have to calculate... + } else { + return; // no labels => no calcs + } + + // add center point to style so bounding box calculations can use it + // + p = { + x: rs.midX, + y: rs.midY + }; + + var setRs = function( propName, prefix, value ){ + util.setPrefixedProperty( _p.rscratch, propName, prefix, value ); + util.setPrefixedProperty( _p.rstyle, propName, prefix, value ); + }; + + setRs( 'labelX', null, p.x ); + setRs( 'labelY', null, p.y ); + + var createControlPointInfo = function(){ + if( createControlPointInfo.cache ){ return createControlPointInfo.cache; } // use cache so only 1x per edge + + var ctrlpts = []; + + // store each ctrlpt info init + for( var i = 0; i + 5 < rs.allpts.length; i += 4 ){ + var p0 = { x: rs.allpts[i], y: rs.allpts[i+1] }; + var p1 = { x: rs.allpts[i+2], y: rs.allpts[i+3] }; // ctrlpt + var p2 = { x: rs.allpts[i+4], y: rs.allpts[i+5] }; + + ctrlpts.push({ + p0: p0, + p1: p1, + p2: p2, + startDist: 0, + length: 0, + segments: [] + }); + } + + var bpts = _p.rstyle.bezierPts; + var nProjs = r.bezierProjPcts.length; + + function addSegment( cp, p0, p1, t0, t1 ){ + var length = math.dist( p0, p1 ); + var prevSegment = cp.segments[ cp.segments.length - 1 ]; + var segment = { + p0: p0, + p1: p1, + t0: t0, + t1: t1, + startDist: prevSegment ? prevSegment.startDist + prevSegment.length : 0, + length: length + }; + + cp.segments.push( segment ); + + cp.length += length; + } + + // update each ctrlpt with segment info + for( var i = 0; i < ctrlpts.length; i++ ){ + var cp = ctrlpts[i]; + var prevCp = ctrlpts[i - 1]; + + if( prevCp ){ + cp.startDist = prevCp.startDist + prevCp.length; + } + + addSegment( + cp, + cp.p0, bpts[ i * nProjs ], + 0, r.bezierProjPcts[ 0 ] + ); // first + + for( var j = 0; j < nProjs - 1; j++ ){ + addSegment( + cp, + bpts[ i * nProjs + j ], bpts[ i * nProjs + j + 1 ], + r.bezierProjPcts[ j ], r.bezierProjPcts[ j + 1 ] + ); + } + + addSegment( + cp, + bpts[ i * nProjs + nProjs - 1 ], cp.p2, + r.bezierProjPcts[ nProjs - 1 ], 1 + ); // last + } + + return ( createControlPointInfo.cache = ctrlpts ); + }; + + var calculateEndProjection = function( prefix ){ + var angle; + var isSrc = prefix === 'source'; + + if( !content[ prefix ] ){ return; } + + var offset = edge.pstyle(prefix+'-text-offset').pfValue; + + var lineAngle = function( p0, p1 ){ + var dx = p1.x - p0.x; + var dy = p1.y - p0.y; + + return Math.atan( dy / dx ); + }; + + var bezierAngle = function( p0, p1, p2, t ){ + var t0 = math.bound( 0, t - 0.001, 1 ); + var t1 = math.bound( 0, t + 0.001, 1 ); + + var lp0 = math.qbezierPtAt( p0, p1, p2, t0 ); + var lp1 = math.qbezierPtAt( p0, p1, p2, t1 ); + + return lineAngle( lp0, lp1 ); + }; + + switch( rs.edgeType ){ + case 'self': + case 'compound': + case 'bezier': + case 'multibezier': + var cps = createControlPointInfo(); + var selected; + var startDist = 0; + var totalDist = 0; + + // find the segment we're on + for( var i = 0; i < cps.length; i++ ){ + var cp = cps[ isSrc ? i : cps.length - 1 - i ]; + + for( var j = 0; j < cp.segments.length; j++ ){ + var seg = cp.segments[ isSrc ? j : cp.segments.length - 1 - j ]; + var lastSeg = i === cps.length - 1 && j === cp.segments.length - 1; + + startDist = totalDist; + totalDist += seg.length; + + if( totalDist >= offset || lastSeg ){ + selected = { cp: cp, segment: seg }; + break; + } + } + + if( selected ){ break; } + } + + var cp = selected.cp; + var seg = selected.segment; + var tSegment = ( offset - startDist ) / ( seg.length ); + var segDt = seg.t1 - seg.t0; + var t = isSrc ? seg.t0 + segDt * tSegment : seg.t1 - segDt * tSegment; + + t = math.bound( 0, t, 1 ); + p = math.qbezierPtAt( cp.p0, cp.p1, cp.p2, t ); + angle = bezierAngle( cp.p0, cp.p1, cp.p2, t, p ); + + break; + + case 'straight': + case 'segments': + case 'haystack': + var d = 0, di, d0; + var p0, p1; + var l = rs.allpts.length; + + for( var i = 0; i + 3 < l; i += 2 ){ + if( isSrc ){ + p0 = { x: rs.allpts[i], y: rs.allpts[i+1] }; + p1 = { x: rs.allpts[i+2], y: rs.allpts[i+3] }; + } else { + p0 = { x: rs.allpts[l-2-i], y: rs.allpts[l-1-i] }; + p1 = { x: rs.allpts[l-4-i], y: rs.allpts[l-3-i] }; + } + + di = math.dist( p0, p1 ); + d0 = d; + d += di; + + if( d >= offset ){ break; } + } + + var pD = offset - d0; + var t = pD / di; + + t = math.bound( 0, t, 1 ); + p = math.lineAt( p0, p1, t ); + angle = lineAngle( p0, p1 ); + + break; + } + + setRs( 'labelX', prefix, p.x ); + setRs( 'labelY', prefix, p.y ); + setRs( 'labelAutoAngle', prefix, angle ); + }; + + calculateEndProjection( 'source' ); + calculateEndProjection( 'target' ); + + this.applyLabelDimensions( edge ); +}; + +BRp.applyLabelDimensions = function( ele ){ + this.applyPrefixedLabelDimensions( ele ); + + if( ele.isEdge() ){ + this.applyPrefixedLabelDimensions( ele, 'source' ); + this.applyPrefixedLabelDimensions( ele, 'target' ); + } +}; + +BRp.applyPrefixedLabelDimensions = function( ele, prefix ){ + var _p = ele._private; + + var text = this.getLabelText( ele, prefix ); + var labelDims = this.calculateLabelDimensions( ele, text ); + + util.setPrefixedProperty( _p.rstyle, 'labelWidth', prefix, labelDims.width ); + util.setPrefixedProperty( _p.rscratch, 'labelWidth', prefix, labelDims.width ); + + util.setPrefixedProperty( _p.rstyle, 'labelHeight', prefix, labelDims.height ); + util.setPrefixedProperty( _p.rscratch, 'labelHeight', prefix, labelDims.height ); +}; + +BRp.getLabelText = function( ele, prefix ){ + var _p = ele._private; + var pfd = prefix ? prefix + '-' : ''; + var text = ele.pstyle( pfd + 'label' ).strValue; + var textTransform = ele.pstyle( 'text-transform' ).value; + var rscratch = function( propName, value ){ + if( value ){ + util.setPrefixedProperty( _p.rscratch, propName, prefix, value ); + return value; + } else { + return util.getPrefixedProperty( _p.rscratch, propName, prefix ); + } + }; + + if( textTransform == 'none' ){ + // passthrough + } else if( textTransform == 'uppercase' ){ + text = text.toUpperCase(); + } else if( textTransform == 'lowercase' ){ + text = text.toLowerCase(); + } + + if( ele.pstyle( 'text-wrap' ).value === 'wrap' ){ + //console.log('wrap'); + + var labelKey = rscratch( 'labelKey' ); + + // save recalc if the label is the same as before + if( labelKey && rscratch( 'labelWrapKey' ) === labelKey ){ + // console.log('wrap cache hit'); + return rscratch( 'labelWrapCachedText' ); + } + // console.log('wrap cache miss'); + + var lines = text.split( '\n' ); + var maxW = ele.pstyle( 'text-max-width' ).pfValue; + var wrappedLines = []; + + for( var l = 0; l < lines.length; l++ ){ + var line = lines[ l ]; + var lineDims = this.calculateLabelDimensions( ele, line, 'line=' + line ); + var lineW = lineDims.width; + + if( lineW > maxW ){ // line is too long + var words = line.split( /\s+/ ); // NB: assume collapsed whitespace into single space + var subline = ''; + + for( var w = 0; w < words.length; w++ ){ + var word = words[ w ]; + var testLine = subline.length === 0 ? word : subline + ' ' + word; + var testDims = this.calculateLabelDimensions( ele, testLine, 'testLine=' + testLine ); + var testW = testDims.width; + + if( testW <= maxW ){ // word fits on current line + subline += word + ' '; + } else { // word starts new line + wrappedLines.push( subline ); + subline = word + ' '; + } + } + + // if there's remaining text, put it in a wrapped line + if( !subline.match( /^\s+$/ ) ){ + wrappedLines.push( subline ); + } + } else { // line is already short enough + wrappedLines.push( line ); + } + } // for + + rscratch( 'labelWrapCachedLines', wrappedLines ); + text = rscratch( 'labelWrapCachedText', wrappedLines.join( '\n' ) ); + rscratch( 'labelWrapKey', labelKey ); + + // console.log(text) + } // if wrap + + return text; +}; + +BRp.calculateLabelDimensions = function( ele, text, extraKey ){ + var r = this; + + var cacheKey = ele._private.labelStyleKey + '$@$' + text; + + if( extraKey ){ + cacheKey += '$@$' + extraKey; + } + + var cache = r.labelDimCache || (r.labelDimCache = {}); + + if( cache[ cacheKey ] ){ + return cache[ cacheKey ]; + } + + var sizeMult = 1; // increase the scale to increase accuracy w.r.t. zoomed text + var fStyle = ele.pstyle( 'font-style' ).strValue; + var size = ( sizeMult * ele.pstyle( 'font-size' ).pfValue ) + 'px'; + var family = ele.pstyle( 'font-family' ).strValue; + var weight = ele.pstyle( 'font-weight' ).strValue; + + var div = this.labelCalcDiv; + + if( !div ){ + div = this.labelCalcDiv = document.createElement( 'div' ); // eslint-disable-line no-undef + document.body.appendChild( div ); // eslint-disable-line no-undef + } + + var ds = div.style; + + // from ele style + ds.fontFamily = family; + ds.fontStyle = fStyle; + ds.fontSize = size; + ds.fontWeight = weight; + + // forced style + ds.position = 'absolute'; + ds.left = '-9999px'; + ds.top = '-9999px'; + ds.zIndex = '-1'; + ds.visibility = 'hidden'; + ds.pointerEvents = 'none'; + ds.padding = '0'; + ds.lineHeight = '1'; + + if( ele.pstyle( 'text-wrap' ).value === 'wrap' ){ + ds.whiteSpace = 'pre'; // so newlines are taken into account + } else { + ds.whiteSpace = 'normal'; + } + + // put label content in div + div.textContent = text; + + cache[ cacheKey ] = { + width: Math.ceil( div.clientWidth / sizeMult ), + height: Math.ceil( div.clientHeight / sizeMult ) + }; + + return cache[ cacheKey ]; +}; + +BRp.recalculateLabelProjections = function( nodes, edges ){ + for( var i = 0; i < nodes.length; i++ ){ + this.recalculateNodeLabelProjection( nodes[ i ] ); + } + + for( var i = 0; i < edges.length; i++ ){ + this.recalculateEdgeLabelProjections( edges[ i ] ); + } +}; + +BRp.recalculateEdgeProjections = function( edges ){ + this.findEdgeControlPoints( edges ); +}; + + +// Find edge control points +BRp.findEdgeControlPoints = function( edges ){ + if( !edges || edges.length === 0 ){ return; } + + var r = this; + var cy = r.cy; + var hasCompounds = cy.hasCompoundNodes(); + var hashTable = {}; + var pairIds = []; + var haystackEdges = []; + + // create a table of edge (src, tgt) => list of edges between them + var pairId; + for( var i = 0; i < edges.length; i++ ){ + var edge = edges[ i ]; + var _p = edge._private; + var data = _p.data; + var curveStyle = edge.pstyle( 'curve-style' ).value; + var edgeIsUnbundled = curveStyle === 'unbundled-bezier' || curveStyle === 'segments'; + + // ignore edges who are not to be displayed + // they shouldn't take up space + if( edge.pstyle( 'display').value === 'none' ){ + continue; + } + + if( curveStyle === 'haystack' ){ + haystackEdges.push( edge ); + continue; + } + + var srcId = data.source; + var tgtId = data.target; + + pairId = srcId > tgtId ? + tgtId + '$-$' + srcId : + srcId + '$-$' + tgtId ; + + if( edgeIsUnbundled ){ + pairId = 'unbundled' + '$-$' + data.id; + } + + if( hashTable[ pairId ] == null ){ + hashTable[ pairId ] = []; + pairIds.push( pairId ); + } + + hashTable[ pairId ].push( edge ); + + if( edgeIsUnbundled ){ + hashTable[ pairId ].hasUnbundled = true; + } + } + + var src, tgt, src_p, tgt_p, srcPos, tgtPos, srcW, srcH, tgtW, tgtH, srcShape, tgtShape; + var vectorNormInverse; + var badBezier; + + // for each pair (src, tgt), create the ctrl pts + // Nested for loop is OK; total number of iterations for both loops = edgeCount + for( var p = 0; p < pairIds.length; p++ ){ + pairId = pairIds[ p ]; + var pairEdges = hashTable[ pairId ]; + + // for each pair id, the edges should be sorted by index + pairEdges.sort( function( edge1, edge2 ){ + return edge1.poolIndex() - edge2.poolIndex(); + } ); + + src = pairEdges[0]._private.source; + tgt = pairEdges[0]._private.target; + + // make sure src/tgt distinction is consistent for bundled edges + if( !pairEdges.hasUnbundled && src.id() > tgt.id() ){ + var temp = src; + src = tgt; + tgt = temp; + } + + src_p = src._private; + tgt_p = tgt._private; + + srcPos = src_p.position; + tgtPos = tgt_p.position; + + srcW = src.outerWidth(); + srcH = src.outerHeight(); + + tgtW = tgt.outerWidth(); + tgtH = tgt.outerHeight(); + + srcShape = r.nodeShapes[ this.getNodeShape( src ) ]; + tgtShape = r.nodeShapes[ this.getNodeShape( tgt ) ]; + + badBezier = false; + + + if( (pairEdges.length > 1 && src !== tgt) || pairEdges.hasUnbundled ){ + + // pt outside src shape to calc distance/displacement from src to tgt + var srcOutside = srcShape.intersectLine( + srcPos.x, + srcPos.y, + srcW, + srcH, + tgtPos.x, + tgtPos.y, + 0 + ); + + // pt outside tgt shape to calc distance/displacement from src to tgt + var tgtOutside = tgtShape.intersectLine( + tgtPos.x, + tgtPos.y, + tgtW, + tgtH, + srcPos.x, + srcPos.y, + 0 + ); + + var midptSrcPts = { + x1: srcOutside[0], + x2: tgtOutside[0], + y1: srcOutside[1], + y2: tgtOutside[1] + }; + + var posPts = { + x1: srcPos.x, + x2: tgtPos.x, + y1: srcPos.y, + y2: tgtPos.y + }; + + var dy = ( tgtOutside[1] - srcOutside[1] ); + var dx = ( tgtOutside[0] - srcOutside[0] ); + var l = Math.sqrt( dx * dx + dy * dy ); + + var vector = { + x: dx, + y: dy + }; + + var vectorNorm = { + x: vector.x / l, + y: vector.y / l + }; + vectorNormInverse = { + x: -vectorNorm.y, + y: vectorNorm.x + }; + + + // if node shapes overlap, then no ctrl pts to draw + if( + tgtShape.checkPoint( srcOutside[0], srcOutside[1], 0, tgtW, tgtH, tgtPos.x, tgtPos.y ) && + srcShape.checkPoint( tgtOutside[0], tgtOutside[1], 0, srcW, srcH, srcPos.x, srcPos.y ) + ){ + vectorNormInverse = {}; + badBezier = true; + } + + } + + var edge; + var edge_p; + var rs; + + for( var i = 0; i < pairEdges.length; i++ ){ + edge = pairEdges[ i ]; + edge_p = edge._private; + rs = edge_p.rscratch; + + var edgeIndex1 = rs.lastEdgeIndex; + var edgeIndex2 = i; + + var numEdges1 = rs.lastNumEdges; + var numEdges2 = pairEdges.length; + + var curveStyle = edge.pstyle( 'curve-style' ).value; + var ctrlptDists = edge.pstyle( 'control-point-distances' ); + var ctrlptWs = edge.pstyle( 'control-point-weights' ); + var bezierN = ctrlptDists && ctrlptWs ? Math.min( ctrlptDists.value.length, ctrlptWs.value.length ) : 1; + var stepSize = edge.pstyle( 'control-point-step-size' ).pfValue; + var ctrlptDist = ctrlptDists ? ctrlptDists.pfValue[0] : undefined; + var ctrlptWeight = ctrlptWs.value[0]; + var edgeIsUnbundled = curveStyle === 'unbundled-bezier' || curveStyle === 'segments'; + + var srcX1 = rs.lastSrcCtlPtX; + var srcX2 = srcPos.x; + var srcY1 = rs.lastSrcCtlPtY; + var srcY2 = srcPos.y; + var srcW1 = rs.lastSrcCtlPtW; + var srcW2 = src.outerWidth(); + var srcH1 = rs.lastSrcCtlPtH; + var srcH2 = src.outerHeight(); + + var tgtX1 = rs.lastTgtCtlPtX; + var tgtX2 = tgtPos.x; + var tgtY1 = rs.lastTgtCtlPtY; + var tgtY2 = tgtPos.y; + var tgtW1 = rs.lastTgtCtlPtW; + var tgtW2 = tgt.outerWidth(); + var tgtH1 = rs.lastTgtCtlPtH; + var tgtH2 = tgt.outerHeight(); + + var width1 = rs.lastW; + var width2 = edge.pstyle( 'control-point-step-size' ).pfValue; + + var edgeDistances = edge.pstyle('edge-distances').value; + + if( badBezier ){ + rs.badBezier = true; + } else { + rs.badBezier = false; + } + + if( srcX1 === srcX2 && srcY1 === srcY2 && srcW1 === srcW2 && srcH1 === srcH2 + && tgtX1 === tgtX2 && tgtY1 === tgtY2 && tgtW1 === tgtW2 && tgtH1 === tgtH2 + && width1 === width2 + && ((edgeIndex1 === edgeIndex2 && numEdges1 === numEdges2) || edgeIsUnbundled) ){ + // console.log('edge ctrl pt cache HIT') + continue; // then the control points haven't changed and we can skip calculating them + } else { + rs.lastSrcCtlPtX = srcX2; + rs.lastSrcCtlPtY = srcY2; + rs.lastSrcCtlPtW = srcW2; + rs.lastSrcCtlPtH = srcH2; + rs.lastTgtCtlPtX = tgtX2; + rs.lastTgtCtlPtY = tgtY2; + rs.lastTgtCtlPtW = tgtW2; + rs.lastTgtCtlPtH = tgtH2; + rs.lastEdgeIndex = edgeIndex2; + rs.lastNumEdges = numEdges2; + rs.lastWidth = width2; + // console.log('edge ctrl pt cache MISS') + } + + if( src === tgt ){ + // Self-edge + + rs.edgeType = 'self'; + + var j = i; + var loopDist = stepSize; + + if( edgeIsUnbundled ){ + j = 0; + loopDist = ctrlptDist; + } + + rs.ctrlpts = [ + srcPos.x, + srcPos.y - (1 + Math.pow( srcH, 1.12 ) / 100) * loopDist * (j / 3 + 1), + + srcPos.x - (1 + Math.pow( srcW, 1.12 ) / 100) * loopDist * (j / 3 + 1), + srcPos.y + ]; + + } else if( + hasCompounds && + ( src.isParent() || src.isChild() || tgt.isParent() || tgt.isChild() ) && + ( src.parents().anySame( tgt ) || tgt.parents().anySame( src ) ) + ){ + // Compound edge + + rs.edgeType = 'compound'; + + // because the line approximation doesn't apply for compound beziers + // (loop/self edges are already elided b/c of cheap src==tgt check) + rs.badBezier = false; + + var j = i; + var loopDist = stepSize; + + if( edgeIsUnbundled ){ + j = 0; + loopDist = ctrlptDist; + } + + var loopW = 50; + + var loopaPos = { + x: srcPos.x - srcW / 2, + y: srcPos.y - srcH / 2 + }; + + var loopbPos = { + x: tgtPos.x - tgtW / 2, + y: tgtPos.y - tgtH / 2 + }; + + var loopPos = { + x: Math.min( loopaPos.x, loopbPos.x ), + y: Math.min( loopaPos.y, loopbPos.y ) + }; + + // avoids cases with impossible beziers + var minCompoundStretch = 0.5; + var compoundStretchA = Math.max( minCompoundStretch, Math.log( srcW * 0.01 ) ); + var compoundStretchB = Math.max( minCompoundStretch, Math.log( tgtW * 0.01 ) ); + + rs.ctrlpts = [ + loopPos.x, + loopPos.y - (1 + Math.pow( loopW, 1.12 ) / 100) * loopDist * (j / 3 + 1) * compoundStretchA, + + loopPos.x - (1 + Math.pow( loopW, 1.12 ) / 100) * loopDist * (j / 3 + 1) * compoundStretchB, + loopPos.y + ]; + + } else if( curveStyle === 'segments' ){ + // Segments (multiple straight lines) + + rs.edgeType = 'segments'; + rs.segpts = []; + + var segmentWs = edge.pstyle( 'segment-weights' ).pfValue; + var segmentDs = edge.pstyle( 'segment-distances' ).pfValue; + var segmentsN = Math.min( segmentWs.length, segmentDs.length ); + + for( var s = 0; s < segmentsN; s++ ){ + var w = segmentWs[ s ]; + var d = segmentDs[ s ]; + + var w1 = 1 - w; + var w2 = w; + + var midptPts = edgeDistances === 'node-position' ? posPts : midptSrcPts; + + var adjustedMidpt = { + x: midptPts.x1 * w1 + midptPts.x2 * w2, + y: midptPts.y1 * w1 + midptPts.y2 * w2 + }; + + rs.segpts.push( + adjustedMidpt.x + vectorNormInverse.x * d, + adjustedMidpt.y + vectorNormInverse.y * d + ); + } + + // Straight edge + } else if( + pairEdges.length % 2 === 1 + && i === Math.floor( pairEdges.length / 2 ) + && !edgeIsUnbundled + ){ + + rs.edgeType = 'straight'; + + } else { + // (Multi)bezier + + var multi = edgeIsUnbundled; + + rs.edgeType = multi ? 'multibezier' : 'bezier'; + rs.ctrlpts = []; + + for( var b = 0; b < bezierN; b++ ){ + var normctrlptDist = (0.5 - pairEdges.length / 2 + i) * stepSize; + var manctrlptDist; + var sign = math.signum( normctrlptDist ); + + if( multi ){ + ctrlptDist = ctrlptDists ? ctrlptDists.pfValue[ b ] : stepSize; // fall back on step size + ctrlptWeight = ctrlptWs.value[ b ]; + } + + if( edgeIsUnbundled ){ // multi or single unbundled + manctrlptDist = ctrlptDist; + } else { + manctrlptDist = ctrlptDist !== undefined ? sign * ctrlptDist : undefined; + } + + var distanceFromMidpoint = manctrlptDist !== undefined ? manctrlptDist : normctrlptDist; + + var w1 = 1 - ctrlptWeight; + var w2 = ctrlptWeight; + + var midptPts = edgeDistances === 'node-position' ? posPts : midptSrcPts; + + var adjustedMidpt = { + x: midptPts.x1 * w1 + midptPts.x2 * w2, + y: midptPts.y1 * w1 + midptPts.y2 * w2 + }; + + rs.ctrlpts.push( + adjustedMidpt.x + vectorNormInverse.x * distanceFromMidpoint, + adjustedMidpt.y + vectorNormInverse.y * distanceFromMidpoint + ); + } + + } + + // find endpts for edge + this.findEndpoints( edge ); + + var badStart = !is.number( rs.startX ) || !is.number( rs.startY ); + var badAStart = !is.number( rs.arrowStartX ) || !is.number( rs.arrowStartY ); + var badEnd = !is.number( rs.endX ) || !is.number( rs.endY ); + var badAEnd = !is.number( rs.arrowEndX ) || !is.number( rs.arrowEndY ); + + var minCpADistFactor = 3; + var arrowW = this.getArrowWidth( edge.pstyle( 'width' ).pfValue ) * this.arrowShapeWidth; + var minCpADist = minCpADistFactor * arrowW; + + if( rs.edgeType === 'bezier' ){ + var startACpDist = math.dist( { x: rs.ctrlpts[0], y: rs.ctrlpts[1] }, { x: rs.startX, y: rs.startY } ); + var closeStartACp = startACpDist < minCpADist; + var endACpDist = math.dist( { x: rs.ctrlpts[0], y: rs.ctrlpts[1] }, { x: rs.endX, y: rs.endY } ); + var closeEndACp = endACpDist < minCpADist; + + var overlapping = false; + + if( badStart || badAStart || closeStartACp ){ + overlapping = true; + + // project control point along line from src centre to outside the src shape + // (otherwise intersection will yield nothing) + var cpD = { // delta + x: rs.ctrlpts[0] - srcPos.x, + y: rs.ctrlpts[1] - srcPos.y + }; + var cpL = Math.sqrt( cpD.x * cpD.x + cpD.y * cpD.y ); // length of line + var cpM = { // normalised delta + x: cpD.x / cpL, + y: cpD.y / cpL + }; + var radius = Math.max( srcW, srcH ); + var cpProj = { // *2 radius guarantees outside shape + x: rs.ctrlpts[0] + cpM.x * 2 * radius, + y: rs.ctrlpts[1] + cpM.y * 2 * radius + }; + + var srcCtrlPtIntn = srcShape.intersectLine( + srcPos.x, + srcPos.y, + srcW, + srcH, + cpProj.x, + cpProj.y, + 0 + ); + + if( closeStartACp ){ + rs.ctrlpts[0] = rs.ctrlpts[0] + cpM.x * (minCpADist - startACpDist); + rs.ctrlpts[1] = rs.ctrlpts[1] + cpM.y * (minCpADist - startACpDist); + } else { + rs.ctrlpts[0] = srcCtrlPtIntn[0] + cpM.x * minCpADist; + rs.ctrlpts[1] = srcCtrlPtIntn[1] + cpM.y * minCpADist; + } + } + + if( badEnd || badAEnd || closeEndACp ){ + overlapping = true; + + // project control point along line from tgt centre to outside the tgt shape + // (otherwise intersection will yield nothing) + var cpD = { // delta + x: rs.ctrlpts[0] - tgtPos.x, + y: rs.ctrlpts[1] - tgtPos.y + }; + var cpL = Math.sqrt( cpD.x * cpD.x + cpD.y * cpD.y ); // length of line + var cpM = { // normalised delta + x: cpD.x / cpL, + y: cpD.y / cpL + }; + var radius = Math.max( srcW, srcH ); + var cpProj = { // *2 radius guarantees outside shape + x: rs.ctrlpts[0] + cpM.x * 2 * radius, + y: rs.ctrlpts[1] + cpM.y * 2 * radius + }; + + var tgtCtrlPtIntn = tgtShape.intersectLine( + tgtPos.x, + tgtPos.y, + tgtW, + tgtH, + cpProj.x, + cpProj.y, + 0 + ); + + if( closeEndACp ){ + rs.ctrlpts[0] = rs.ctrlpts[0] + cpM.x * (minCpADist - endACpDist); + rs.ctrlpts[1] = rs.ctrlpts[1] + cpM.y * (minCpADist - endACpDist); + } else { + rs.ctrlpts[0] = tgtCtrlPtIntn[0] + cpM.x * minCpADist; + rs.ctrlpts[1] = tgtCtrlPtIntn[1] + cpM.y * minCpADist; + } + + } + + if( overlapping ){ + // recalc endpts + this.findEndpoints( edge ); + } + + } + + if( rs.edgeType === 'multibezier' || rs.edgeType === 'bezier' || rs.edgeType === 'self' || rs.edgeType === 'compound' ){ + rs.allpts = []; + + rs.allpts.push( rs.startX, rs.startY ); + + for( var b = 0; b + 1 < rs.ctrlpts.length; b += 2 ){ + // ctrl pt itself + rs.allpts.push( rs.ctrlpts[ b ], rs.ctrlpts[ b + 1] ); + + // the midpt between ctrlpts as intermediate destination pts + if( b + 3 < rs.ctrlpts.length ){ + rs.allpts.push( (rs.ctrlpts[ b ] + rs.ctrlpts[ b + 2]) / 2, (rs.ctrlpts[ b + 1] + rs.ctrlpts[ b + 3]) / 2 ); + } + } + + rs.allpts.push( rs.endX, rs.endY ); + + var m, mt; + if( rs.ctrlpts.length / 2 % 2 === 0 ){ + m = rs.allpts.length / 2 - 1; + + rs.midX = rs.allpts[ m ]; + rs.midY = rs.allpts[ m + 1]; + } else { + m = rs.allpts.length / 2 - 3; + mt = 0.5; + + rs.midX = math.qbezierAt( rs.allpts[ m ], rs.allpts[ m + 2], rs.allpts[ m + 4], mt ); + rs.midY = math.qbezierAt( rs.allpts[ m + 1], rs.allpts[ m + 3], rs.allpts[ m + 5], mt ); + } + + } else if( rs.edgeType === 'straight' ){ + // need to calc these after endpts + rs.allpts = [ rs.startX, rs.startY, rs.endX, rs.endY ]; + + // default midpt for labels etc + rs.midX = ( rs.startX + rs.endX + rs.arrowStartX + rs.arrowEndX ) / 4; + rs.midY = ( rs.startY + rs.endY + rs.arrowStartY + rs.arrowEndY ) / 4; + + } else if( rs.edgeType === 'segments' ){ + rs.allpts = []; + rs.allpts.push( rs.startX, rs.startY ); + rs.allpts.push.apply( rs.allpts, rs.segpts ); + rs.allpts.push( rs.endX, rs.endY ); + + if( rs.segpts.length % 4 === 0 ){ + var i2 = rs.segpts.length / 2; + var i1 = i2 - 2; + + rs.midX = ( rs.segpts[ i1 ] + rs.segpts[ i2 ] ) / 2; + rs.midY = ( rs.segpts[ i1 + 1] + rs.segpts[ i2 + 1] ) / 2; + } else { + var i1 = rs.segpts.length / 2 - 1; + + rs.midX = rs.segpts[ i1 ]; + rs.midY = rs.segpts[ i1 + 1]; + } + + + } + + this.projectLines( edge ); + this.calculateArrowAngles( edge ); + this.recalculateEdgeLabelProjections( edge ); + this.calculateLabelAngles( edge ); + + } // for pair edges + } // for pair ids + + for( var i = 0; i < haystackEdges.length; i++ ){ + var edge = haystackEdges[ i ]; + var _p = edge._private; + var rscratch = _p.rscratch; + var rs = rscratch; + + if( !rscratch.haystack ){ + var angle = Math.random() * 2 * Math.PI; + + rscratch.source = { + x: Math.cos( angle ), + y: Math.sin( angle ) + }; + + var angle = Math.random() * 2 * Math.PI; + + rscratch.target = { + x: Math.cos( angle ), + y: Math.sin( angle ) + }; + + } + + var src = _p.source; + var tgt = _p.target; + var srcPos = src._private.position; + var tgtPos = tgt._private.position; + var srcW = src.width(); + var tgtW = tgt.width(); + var srcH = src.height(); + var tgtH = tgt.height(); + var radius = edge.pstyle( 'haystack-radius' ).value; + var halfRadius = radius / 2; // b/c have to half width/height + + rs.haystackPts = rs.allpts = [ + rs.source.x * srcW * halfRadius + srcPos.x, + rs.source.y * srcH * halfRadius + srcPos.y, + rs.target.x * tgtW * halfRadius + tgtPos.x, + rs.target.y * tgtH * halfRadius + tgtPos.y + ]; + + rs.midX = (rs.allpts[0] + rs.allpts[2]) / 2; + rs.midY = (rs.allpts[1] + rs.allpts[3]) / 2; + + // always override as haystack in case set to different type previously + rscratch.edgeType = 'haystack'; + rscratch.haystack = true; + + this.projectLines( edge ); + this.calculateArrowAngles( edge ); + this.recalculateEdgeLabelProjections( edge ); + this.calculateLabelAngles( edge ); + } + + return hashTable; +}; + +var getAngleFromDisp = function( dispX, dispY ){ + return Math.atan2( dispY, dispX ) - Math.PI / 2; +}; + +BRp.calculateArrowAngles = function( edge ){ + var rs = edge._private.rscratch; + var isHaystack = rs.edgeType === 'haystack'; + var isMultibezier = rs.edgeType === 'multibezier'; + var isSegments = rs.edgeType === 'segments'; + var isCompound = rs.edgeType === 'compound'; + var isSelf = rs.edgeType === 'self'; + + // Displacement gives direction for arrowhead orientation + var dispX, dispY; + var startX, startY, endX, endY; + + var srcPos = edge._private.source._private.position; + var tgtPos = edge._private.target._private.position; + + if( isHaystack ){ + startX = rs.haystackPts[0]; + startY = rs.haystackPts[1]; + endX = rs.haystackPts[2]; + endY = rs.haystackPts[3]; + } else { + startX = rs.arrowStartX; + startY = rs.arrowStartY; + endX = rs.arrowEndX; + endY = rs.arrowEndY; + } + + // source + // + + dispX = srcPos.x - startX; + dispY = srcPos.y - startY; + + rs.srcArrowAngle = getAngleFromDisp( dispX, dispY ); + + // mid target + // + + var midX = rs.midX; + var midY = rs.midY; + + if( isHaystack ){ + midX = ( startX + endX ) / 2; + midY = ( startY + endY ) / 2; + } + + dispX = endX - startX; + dispY = endY - startY; + + if( isSelf ){ + dispX = -1; + dispY = 1; + } else if( isSegments ){ + var pts = rs.allpts; + + if( pts.length / 2 % 2 === 0 ){ + var i2 = pts.length / 2; + var i1 = i2 - 2; + + dispX = ( pts[ i2 ] - pts[ i1 ] ); + dispY = ( pts[ i2 + 1] - pts[ i1 + 1] ); + } else { + var i2 = pts.length / 2 - 1; + var i1 = i2 - 2; + var i3 = i2 + 2; + + dispX = ( pts[ i2 ] - pts[ i1 ] ); + dispY = ( pts[ i2 + 1] - pts[ i1 + 1] ); + } + } else if( isMultibezier || isCompound ){ + var pts = rs.allpts; + var cpts = rs.ctrlpts; + var bp0x, bp0y; + var bp1x, bp1y; + + if( cpts.length / 2 % 2 === 0 ){ + var p0 = pts.length / 2 - 1; // startpt + var ic = p0 + 2; + var p1 = ic + 2; + + bp0x = math.qbezierAt( pts[ p0 ], pts[ ic ], pts[ p1 ], 0.0 ); + bp0y = math.qbezierAt( pts[ p0 + 1], pts[ ic + 1], pts[ p1 + 1], 0.0 ); + + bp1x = math.qbezierAt( pts[ p0 ], pts[ ic ], pts[ p1 ], 0.0001 ); + bp1y = math.qbezierAt( pts[ p0 + 1], pts[ ic + 1], pts[ p1 + 1], 0.0001 ); + } else { + var ic = pts.length / 2 - 1; // ctrpt + var p0 = ic - 2; // startpt + var p1 = ic + 2; // endpt + + bp0x = math.qbezierAt( pts[ p0 ], pts[ ic ], pts[ p1 ], 0.4999 ); + bp0y = math.qbezierAt( pts[ p0 + 1], pts[ ic + 1], pts[ p1 + 1], 0.4999 ); + + bp1x = math.qbezierAt( pts[ p0 ], pts[ ic ], pts[ p1 ], 0.5 ); + bp1y = math.qbezierAt( pts[ p0 + 1], pts[ ic + 1], pts[ p1 + 1], 0.5 ); + } + + dispX = ( bp1x - bp0x ); + dispY = ( bp1y - bp0y ); + } + + rs.midtgtArrowAngle = getAngleFromDisp( dispX, dispY ); + + rs.midDispX = dispX; + rs.midDispY = dispY; + + // mid source + // + + dispX *= -1; + dispY *= -1; + + if( isSegments ){ + var pts = rs.allpts; + + if( pts.length / 2 % 2 === 0 ){ + // already ok + } else { + var i2 = pts.length / 2 - 1; + var i3 = i2 + 2; + + dispX = -( pts[ i3 ] - pts[ i2 ] ); + dispY = -( pts[ i3 + 1] - pts[ i2 + 1] ); + } + } + + rs.midsrcArrowAngle = getAngleFromDisp( dispX, dispY ); + + // target + // + + dispX = tgtPos.x - endX; + dispY = tgtPos.y - endY; + + rs.tgtArrowAngle = getAngleFromDisp( dispX, dispY ); +}; + +BRp.calculateLabelAngles = function( ele ){ + var _p = ele._private; + var rs = _p.rscratch; + var isEdge = ele.isEdge(); + var rot = ele.pstyle( 'text-rotation' ); + var rotStr = rot.strValue; + + if( rotStr === 'none' ){ + rs.labelAngle = rs.sourceLabelAngle = rs.targetLabelAngle = 0; + } else if( isEdge && rotStr === 'autorotate' ){ + rs.labelAngle = Math.atan( rs.midDispY / rs.midDispX ); + rs.sourceLabelAngle = rs.sourceLabelAutoAngle; + rs.targetLabelAngle = rs.targetLabelAutoAngle; + } else if( rotStr === 'autorotate' ){ + rs.labelAngle = rs.sourceLabelAngle = rs.targetLabelAngle = 0; + } else { + rs.labelAngle = rs.sourceLabelAngle = rs.targetLabelAngle = rot.pfValue; + } +}; + + +BRp.findEndpoints = function( edge ){ + var r = this; + var intersect; + + var source = edge.source()[0]; + var target = edge.target()[0]; + + var src_p = source._private; + var tgt_p = target._private; + + var srcPos = src_p.position; + var tgtPos = tgt_p.position; + + var tgtArShape = edge.pstyle( 'target-arrow-shape' ).value; + var srcArShape = edge.pstyle( 'source-arrow-shape' ).value; + + var rs = edge._private.rscratch; + + var et = rs.edgeType; + var bezier = et === 'bezier' || et === 'multibezier' || et === 'self' || et === 'compound'; + var multi = et !== 'bezier'; + var lines = et === 'straight' || et === 'segments'; + var segments = et === 'segments'; + var hasEndpts = bezier || multi || lines; + + var p1, p2; + + if( bezier ){ + var cpStart = [ rs.ctrlpts[0], rs.ctrlpts[1] ]; + var cpEnd = multi ? [ rs.ctrlpts[ rs.ctrlpts.length - 2], rs.ctrlpts[ rs.ctrlpts.length - 1] ] : cpStart; + + p1 = cpEnd; + p2 = cpStart; + } else if( lines ){ + var srcArrowFromPt = !segments ? [ tgtPos.x, tgtPos.y ] : rs.segpts.slice( 0, 2 ); + var tgtArrowFromPt = !segments ? [ srcPos.x, srcPos.y ] : rs.segpts.slice( rs.segpts.length - 2 ); + + p1 = tgtArrowFromPt; + p2 = srcArrowFromPt; + } + + intersect = r.nodeShapes[ this.getNodeShape( target ) ].intersectLine( + tgtPos.x, + tgtPos.y, + target.outerWidth(), + target.outerHeight(), + p1[0], + p1[1], + 0 + ); + + var arrowEnd = math.shortenIntersection( intersect, p1, + r.arrowShapes[ tgtArShape ].spacing( edge ) ); + var edgeEnd = math.shortenIntersection( intersect, p1, + r.arrowShapes[ tgtArShape ].gap( edge ) ); + + rs.endX = edgeEnd[0]; + rs.endY = edgeEnd[1]; + + rs.arrowEndX = arrowEnd[0]; + rs.arrowEndY = arrowEnd[1]; + + intersect = r.nodeShapes[ this.getNodeShape( source ) ].intersectLine( + srcPos.x, + srcPos.y, + source.outerWidth(), + source.outerHeight(), + p2[0], + p2[1], + 0 + ); + + var arrowStart = math.shortenIntersection( + intersect, p2, + r.arrowShapes[ srcArShape ].spacing( edge ) + ); + var edgeStart = math.shortenIntersection( + intersect, p2, + r.arrowShapes[ srcArShape ].gap( edge ) + ); + + rs.startX = edgeStart[0]; + rs.startY = edgeStart[1]; + + rs.arrowStartX = arrowStart[0]; + rs.arrowStartY = arrowStart[1]; + + if( hasEndpts ){ + if( !is.number( rs.startX ) || !is.number( rs.startY ) || !is.number( rs.endX ) || !is.number( rs.endY ) ){ + rs.badLine = true; + } else { + rs.badLine = false; + } + } +}; + +BRp.getArrowWidth = BRp.getArrowHeight = function( edgeWidth ){ + var cache = this.arrowWidthCache = this.arrowWidthCache || {}; + + var cachedVal = cache[ edgeWidth ]; + if( cachedVal ){ + return cachedVal; + } + + cachedVal = Math.max( Math.pow( edgeWidth * 13.37, 0.9 ), 29 ); + cache[ edgeWidth ] = cachedVal; + + return cachedVal; +}; + +module.exports = BRp; + +},{"../../../collection/zsort":32,"../../../is":83,"../../../math":85,"../../../util":100}],59:[function(_dereq_,module,exports){ +'use strict'; + +var BRp = {}; + +BRp.getCachedImage = function( url, onLoad ){ + var r = this; + var imageCache = r.imageCache = r.imageCache || {}; + + if( imageCache[ url ] && imageCache[ url ].image ){ + return imageCache[ url ].image; + } + + var cache = imageCache[ url ] = imageCache[ url ] || {}; + + var image = cache.image = new Image(); // eslint-disable-line no-undef + image.addEventListener('load', onLoad); + image.crossOrigin = 'Anonymous'; // prevent tainted canvas + image.src = url; + + return image; +}; + +module.exports = BRp; + +},{}],60:[function(_dereq_,module,exports){ +'use strict'; + +var is = _dereq_( '../../../is' ); +var util = _dereq_( '../../../util' ); + +var BaseRenderer = function( options ){ this.init( options ); }; +var BR = BaseRenderer; +var BRp = BR.prototype; + +BRp.clientFunctions = [ 'redrawHint', 'render', 'renderTo', 'matchCanvasSize', 'nodeShapeImpl', 'arrowShapeImpl' ]; + +BRp.init = function( options ){ + var r = this; + + r.options = options; + + r.cy = options.cy; + + r.container = options.cy.container(); + + r.selection = [ undefined, undefined, undefined, undefined, 0]; // Coordinates for selection box, plus enabled flag + + r.bezierProjPcts = [ 0.05, 0.225, 0.4, 0.5, 0.6, 0.775, 0.95 ]; + + //--Pointer-related data + r.hoverData = {down: null, last: null, + downTime: null, triggerMode: null, + dragging: false, + initialPan: [ null, null ], capture: false}; + + r.dragData = {possibleDragElements: []}; + + r.touchData = { + start: null, capture: false, + + // These 3 fields related to tap, taphold events + startPosition: [ null, null, null, null, null, null ], + singleTouchStartTime: null, + singleTouchMoved: true, + + now: [ null, null, null, null, null, null ], + earlier: [ null, null, null, null, null, null ] + }; + + r.redraws = 0; + r.showFps = options.showFps; + + r.hideEdgesOnViewport = options.hideEdgesOnViewport; + r.hideLabelsOnViewport = options.hideLabelsOnViewport; + r.textureOnViewport = options.textureOnViewport; + r.wheelSensitivity = options.wheelSensitivity; + r.motionBlurEnabled = options.motionBlur; // on by default + r.forcedPixelRatio = options.pixelRatio; + r.motionBlur = options.motionBlur; // for initial kick off + r.motionBlurOpacity = options.motionBlurOpacity; + r.motionBlurTransparency = 1 - r.motionBlurOpacity; + r.motionBlurPxRatio = 1; + r.mbPxRBlurry = 1; //0.8; + r.minMbLowQualFrames = 4; + r.fullQualityMb = false; + r.clearedForMotionBlur = []; + r.desktopTapThreshold = options.desktopTapThreshold; + r.desktopTapThreshold2 = options.desktopTapThreshold * options.desktopTapThreshold; + r.touchTapThreshold = options.touchTapThreshold; + r.touchTapThreshold2 = options.touchTapThreshold * options.touchTapThreshold; + r.tapholdDuration = 500; + + r.bindings = []; + r.beforeRenderCallbacks = []; + r.beforeRenderPriorities = { // higher priority execs before lower one + animations: 400, + eleCalcs: 300, + eleTxrDeq: 200, + lyrTxrDeq: 100 + }; + + r.registerNodeShapes(); + r.registerArrowShapes(); + r.registerCalculationListeners(); + r.load(); +}; + +BRp.notify = function( params ){ + var types; + var r = this; + + if( is.array( params.type ) ){ + types = params.type; + + } else { + types = [ params.type ]; + } + + var has = {}; + for( var i = 0; i < types.length; i++ ){ + var type = types[ i ]; + + has[ type ] = true; + } // for + + if( has['destroy'] ){ + r.destroy(); + return; + } + + if( has['add'] || has['remove'] || has['load'] || has['style'] ){ + r.updateCachedZSortedEles(); + } + + if( has['viewport'] ){ + r.redrawHint( 'select', true ); + } + + if( has['load'] || has['resize'] ){ + r.invalidateContainerClientCoordsCache(); + r.matchCanvasSize( r.container ); + } + + r.redrawHint( 'eles', true ); + r.redrawHint( 'drag', true ); + + this.startRenderLoop(); + + this.redraw(); +}; + +BRp.destroy = function(){ + var r = this; + + r.destroyed = true; + + r.cy.stopAnimationLoop(); + + for( var i = 0; i < r.bindings.length; i++ ){ + var binding = r.bindings[ i ]; + var b = binding; + var tgt = b.target; + + ( tgt.off || tgt.removeEventListener ).apply( tgt, b.args ); + } + + r.bindings = []; + r.beforeRenderCallbacks = []; + r.onUpdateEleCalcsFns = []; + + if( r.removeObserver ){ + r.removeObserver.disconnect(); + } + + if( r.styleObserver ){ + r.styleObserver.disconnect(); + } + + if( r.labelCalcDiv ){ + try { + document.body.removeChild( r.labelCalcDiv ); // eslint-disable-line no-undef + } catch( e ){ + // ie10 issue #1014 + } + } +}; + +[ + _dereq_( './arrow-shapes' ), + _dereq_( './coord-ele-math' ), + _dereq_( './images' ), + _dereq_( './load-listeners' ), + _dereq_( './node-shapes' ), + _dereq_( './redraw' ) +].forEach( function( props ){ + util.extend( BRp, props ); +} ); + +module.exports = BR; + +},{"../../../is":83,"../../../util":100,"./arrow-shapes":57,"./coord-ele-math":58,"./images":59,"./load-listeners":61,"./node-shapes":62,"./redraw":63}],61:[function(_dereq_,module,exports){ +'use strict'; + +var is = _dereq_( '../../../is' ); +var util = _dereq_( '../../../util' ); +var math = _dereq_( '../../../math' ); +var Event = _dereq_( '../../../event' ); + +var BRp = {}; + +BRp.registerBinding = function( target, event, handler, useCapture ){ + var args = Array.prototype.slice.apply( arguments, [1] ); // copy + var b = this.binder( target ); + + return b.on.apply( b, args ); +}; + +BRp.binder = function( tgt ){ + var r = this; + + var on = function(){ + var args = arguments; + + r.bindings.push({ + target: tgt, + args: args + }); + + ( tgt.addEventListener || tgt.on ).apply( tgt, args ); + + return this; + }; + + return { + on: on, + addEventListener: on, + addListener: on, + bind: on + }; +}; + +BRp.nodeIsDraggable = function( node ){ + return ( + node + && node.isNode() + && !node.locked() + && node.grabbable() + ); +}; + +BRp.nodeIsGrabbable = function( node ){ + return ( + this.nodeIsDraggable( node ) + && node.pstyle( 'opacity' ).value !== 0 + && node.pstyle( 'visibility' ).value === 'visible' + && node.pstyle( 'display' ).value === 'element' + ); +}; + +BRp.load = function(){ + var r = this; + + var triggerEvents = function( target, names, e, props ){ + if( target == null ){ + target = r.cy; + } + + for( var i = 0; i < names.length; i++ ){ + var name = names[ i ]; + + var event = new Event( e, util.extend( { type: name }, props ) ); + target.trigger( event ); + } + }; + + var isMultSelKeyDown = function( e ){ + return e.shiftKey || e.metaKey || e.ctrlKey; // maybe e.altKey + }; + + var allowPanningPassthrough = function( down, downs ){ + var allowPassthrough = true; + + if( r.cy.hasCompoundNodes() && down && down.isEdge() ){ + // a compound node below the edge => no passthrough panning + for( var i = 0; downs && i < downs.length; i++ ){ + var down = downs[i]; + + if( down.isNode() && down.isParent() ){ + allowPassthrough = false; + break; + } + } + } else { + allowPassthrough = true; + } + + return allowPassthrough; + }; + + var getDragListIds = function( opts ){ + var listHasId; + + if( opts.addToList && r.cy.hasCompoundNodes() ){ // only needed for compound graphs + if( !opts.addToList.hasId ){ // build ids lookup if doesn't already exist + opts.addToList.hasId = {}; + + for( var i = 0; i < opts.addToList.length; i++ ){ + var ele = opts.addToList[ i ]; + + opts.addToList.hasId[ ele.id() ] = true; + } + } + + listHasId = opts.addToList.hasId; + } + + return listHasId || {}; + }; + + var setGrabbed = function( ele ){ + ele[0]._private.grabbed = true; + }; + + var setFreed = function( ele ){ + ele[0]._private.grabbed = false; + }; + + var setInDragLayer = function( ele ){ + ele[0]._private.rscratch.inDragLayer = true; + }; + + var setOutDragLayer = function( ele ){ + ele[0]._private.rscratch.inDragLayer = false; + }; + + var setGrabTarget = function( ele ){ + ele[0]._private.rscratch.isGrabTarget = true; + }; + + var removeGrabTarget = function( ele ){ + ele[0]._private.rscratch.isGrabTarget = false; + }; + + var addToDragList = function( ele, opts ){ + var listHasId = getDragListIds( opts ); + + if( !listHasId[ ele.id() ] ){ + opts.addToList.push( ele ); + listHasId[ ele.id() ] = true; + + setGrabbed( ele ); + } + }; + + // helper function to determine which child nodes and inner edges + // of a compound node to be dragged as well as the grabbed and selected nodes + var addDescendantsToDrag = function( node, opts ){ + if( !node.cy().hasCompoundNodes() ){ + return; + } + + if( opts.inDragLayer == null && opts.addToList == null ){ return; } // nothing to do + + var innerNodes = node.descendants(); + + if( opts.inDragLayer ){ + innerNodes.forEach( setInDragLayer ); + innerNodes.connectedEdges().forEach( setInDragLayer ); + } + + if( opts.addToList ){ + innerNodes.forEach(function( ele ){ + addToDragList( ele, opts ); + }); + } + }; + + // adds the given nodes and its neighbourhood to the drag layer + var addNodesToDrag = function( nodes, opts ){ + opts = opts || {}; + + var hasCompoundNodes = nodes.cy().hasCompoundNodes(); + + if( opts.inDragLayer ){ + nodes.forEach( setInDragLayer ); + + nodes.neighborhood().stdFilter(function( ele ){ + return !hasCompoundNodes || ele.isEdge(); + }).forEach( setInDragLayer ); + } + + if( opts.addToList ){ + nodes.forEach(function( ele ){ + addToDragList( ele, opts ); + }); + } + + addDescendantsToDrag( nodes, opts ); // always add to drag + + // also add nodes and edges related to the topmost ancestor + updateAncestorsInDragLayer( nodes, { + inDragLayer: opts.inDragLayer + } ); + + r.updateCachedGrabbedEles(); + }; + + var addNodeToDrag = addNodesToDrag; + + var freeDraggedElements = function( grabbedEles ){ + if( !grabbedEles ){ return; } + + grabbedEles.hasId = {}; // clear the id list + + // just go over all elements rather than doing a bunch of (possibly expensive) traversals + r.getCachedZSortedEles().forEach(function( ele ){ + setFreed( ele ); + setOutDragLayer( ele ); + removeGrabTarget( ele ); + }); + + r.updateCachedGrabbedEles(); + }; + + // helper function to determine which ancestor nodes and edges should go + // to the drag layer (or should be removed from drag layer). + var updateAncestorsInDragLayer = function( node, opts ){ + + if( opts.inDragLayer == null && opts.addToList == null ){ return; } // nothing to do + + if( !node.cy().hasCompoundNodes() ){ + return; + } + + // find top-level parent + var parent = node.ancestors().orphans(); + + // no parent node: no nodes to add to the drag layer + if( parent.same( node ) ){ + return; + } + + var nodes = parent.descendants().spawnSelf() + .merge( parent ) + .unmerge( node ) + .unmerge( node.descendants() ) + ; + + var edges = nodes.connectedEdges(); + + if( opts.inDragLayer ){ + edges.forEach( setInDragLayer ); + nodes.forEach( setInDragLayer ); + } + + if( opts.addToList ){ + nodes.forEach(function( ele ){ + addToDragList( ele, opts ); + }); + } + }; + + var haveMutationsApi = typeof MutationObserver !== 'undefined'; + + // watch for when the cy container is removed from the dom + if( haveMutationsApi ){ + r.removeObserver = new MutationObserver( function( mutns ){ // eslint-disable-line no-undef + for( var i = 0; i < mutns.length; i++ ){ + var mutn = mutns[ i ]; + var rNodes = mutn.removedNodes; + + if( rNodes ){ for( var j = 0; j < rNodes.length; j++ ){ + var rNode = rNodes[ j ]; + + if( rNode === r.container ){ + r.destroy(); + break; + } + } } + } + } ); + + if( r.container.parentNode ){ + r.removeObserver.observe( r.container.parentNode, { childList: true } ); + } + } else { + r.registerBinding( r.container, 'DOMNodeRemoved', function( e ){ + r.destroy(); + } ); + } + + var onResize = util.debounce( function(){ + r.cy.invalidateSize(); + r.invalidateContainerClientCoordsCache(); + + r.matchCanvasSize( r.container ); + r.redrawHint( 'eles', true ); + r.redrawHint( 'drag', true ); + r.redraw(); + }, 100 ); + + if( haveMutationsApi ){ + r.styleObserver = new MutationObserver( onResize ); // eslint-disable-line no-undef + + r.styleObserver.observe( r.container, { attributes: true } ); + } + + // auto resize + r.registerBinding( window, 'resize', onResize ); // eslint-disable-line no-undef + + var invalCtnrBBOnScroll = function( domEle ){ + r.registerBinding( domEle, 'scroll', function( e ){ + r.invalidateContainerClientCoordsCache(); + } ); + }; + + var bbCtnr = r.cy.container(); + + for( ;; ){ + + invalCtnrBBOnScroll( bbCtnr ); + + if( bbCtnr.parentNode ){ + bbCtnr = bbCtnr.parentNode; + } else { + break; + } + + } + + // stop right click menu from appearing on cy + r.registerBinding( r.container, 'contextmenu', function( e ){ + e.preventDefault(); + } ); + + var inBoxSelection = function(){ + return r.selection[4] !== 0; + }; + + // Primary key + r.registerBinding( r.container, 'mousedown', function mousedownHandler( e ){ + e.preventDefault(); + r.hoverData.capture = true; + r.hoverData.which = e.which; + + var cy = r.cy; + var gpos = [ e.clientX, e.clientY ]; + var pos = r.projectIntoViewport( gpos[0], gpos[1] ); + var select = r.selection; + var nears = r.findNearestElements( pos[0], pos[1], true, false ); + var near = nears[0]; + var draggedElements = r.dragData.possibleDragElements; + + r.hoverData.mdownPos = pos; + r.hoverData.mdownGPos = gpos; + + var checkForTaphold = function(){ + r.hoverData.tapholdCancelled = false; + + clearTimeout( r.hoverData.tapholdTimeout ); + + r.hoverData.tapholdTimeout = setTimeout( function(){ + + if( r.hoverData.tapholdCancelled ){ + return; + } else { + var ele = r.hoverData.down; + + if( ele ){ + ele.trigger( new Event( e, { + type: 'taphold', + cyPosition: { x: pos[0], y: pos[1] } + } ) ); + } else { + cy.trigger( new Event( e, { + type: 'taphold', + cyPosition: { x: pos[0], y: pos[1] } + } ) ); + } + } + + }, r.tapholdDuration ); + }; + + // Right click button + if( e.which == 3 ){ + + r.hoverData.cxtStarted = true; + + var cxtEvt = new Event( e, { + type: 'cxttapstart', + cyPosition: { x: pos[0], y: pos[1] } + } ); + + if( near ){ + near.activate(); + near.trigger( cxtEvt ); + + r.hoverData.down = near; + } else { + cy.trigger( cxtEvt ); + } + + r.hoverData.downTime = (new Date()).getTime(); + r.hoverData.cxtDragged = false; + + // Primary button + } else if( e.which == 1 ){ + + if( near ){ + near.activate(); + } + + // Element dragging + { + // If something is under the cursor and it is draggable, prepare to grab it + if( near != null ){ + + if( r.nodeIsGrabbable( near ) ){ + + var grabEvent = new Event( e, { + type: 'grab', + cyPosition: { x: pos[0], y: pos[1] } + } ); + + setGrabTarget( near ); + + if( !near.selected() ){ + + draggedElements = r.dragData.possibleDragElements = []; + addNodeToDrag( near, { addToList: draggedElements } ); + + near.trigger( grabEvent ); + + } else if( near.selected() ){ + draggedElements = r.dragData.possibleDragElements = [ ]; + + var selectedNodes = cy.$( function(){ return this.isNode() && this.selected() && r.nodeIsGrabbable( this ); } ); + + addNodesToDrag( selectedNodes, { addToList: draggedElements } ); + + near.trigger( grabEvent ); + } + + r.redrawHint( 'eles', true ); + r.redrawHint( 'drag', true ); + + } + + } + + r.hoverData.down = near; + r.hoverData.downs = nears; + r.hoverData.downTime = (new Date()).getTime(); + } + + triggerEvents( near, [ 'mousedown', 'tapstart', 'vmousedown' ], e, { + cyPosition: { x: pos[0], y: pos[1] } + } ); + + if( near == null ){ + select[4] = 1; + + r.data.bgActivePosistion = { + x: pos[0], + y: pos[1] + }; + + r.redrawHint( 'select', true ); + + r.redraw(); + } else if( near.isEdge() ){ + select[4] = 1; // for future pan + } + + checkForTaphold(); + + } + + // Initialize selection box coordinates + select[0] = select[2] = pos[0]; + select[1] = select[3] = pos[1]; + + }, false ); + + r.registerBinding( window, 'mousemove', function mousemoveHandler( e ){ // eslint-disable-line no-undef + var preventDefault = false; + var capture = r.hoverData.capture; + + // save cycles if mouse events aren't to be captured + if( !capture ){ + var containerPageCoords = r.findContainerClientCoords(); + + if( e.clientX > containerPageCoords[0] && e.clientX < containerPageCoords[0] + r.canvasWidth + && e.clientY > containerPageCoords[1] && e.clientY < containerPageCoords[1] + r.canvasHeight + ){ + // inside container bounds so OK + } else { + return; + } + + var cyContainer = r.container; + var target = e.target; + var tParent = target.parentNode; + var containerIsTarget = false; + + while( tParent ){ + if( tParent === cyContainer ){ + containerIsTarget = true; + break; + } + + tParent = tParent.parentNode; + } + + if( !containerIsTarget ){ return; } // if target is outisde cy container, then this event is not for us + } + + var cy = r.cy; + var zoom = cy.zoom(); + var gpos = [ e.clientX, e.clientY ]; + var pos = r.projectIntoViewport( gpos[0], gpos[1] ); + var mdownPos = r.hoverData.mdownPos; + var mdownGPos = r.hoverData.mdownGPos; + var select = r.selection; + + var near = null; + if( !r.hoverData.draggingEles && !r.hoverData.dragging && !r.hoverData.selecting ){ + near = r.findNearestElement( pos[0], pos[1], true, false ); + } + var last = r.hoverData.last; + var down = r.hoverData.down; + + var disp = [ pos[0] - select[2], pos[1] - select[3] ]; + + var draggedElements = r.dragData.possibleDragElements; + + var isOverThresholdDrag; + + if( mdownGPos ){ + var dx = gpos[0] - mdownGPos[0]; + var dx2 = dx * dx; + var dy = gpos[1] - mdownGPos[1]; + var dy2 = dy * dy; + var dist2 = dx2 + dy2; + + isOverThresholdDrag = dist2 >= r.desktopTapThreshold2; + } + + var multSelKeyDown = isMultSelKeyDown( e ); + + if (isOverThresholdDrag) { + r.hoverData.tapholdCancelled = true; + } + + var updateDragDelta = function(){ + var dragDelta = r.hoverData.dragDelta = r.hoverData.dragDelta || []; + + if( dragDelta.length === 0 ){ + dragDelta.push( disp[0] ); + dragDelta.push( disp[1] ); + } else { + dragDelta[0] += disp[0]; + dragDelta[1] += disp[1]; + } + }; + + + preventDefault = true; + + triggerEvents( near, [ 'mousemove', 'vmousemove', 'tapdrag' ], e, { + cyPosition: { x: pos[0], y: pos[1] } + } ); + + // trigger context drag if rmouse down + if( r.hoverData.which === 3 ){ + // but only if over threshold + if( isOverThresholdDrag ){ + var cxtEvt = new Event( e, { + type: 'cxtdrag', + cyPosition: { x: pos[0], y: pos[1] } + } ); + + if( down ){ + down.trigger( cxtEvt ); + } else { + cy.trigger( cxtEvt ); + } + + r.hoverData.cxtDragged = true; + + if( !r.hoverData.cxtOver || near !== r.hoverData.cxtOver ){ + + if( r.hoverData.cxtOver ){ + r.hoverData.cxtOver.trigger( new Event( e, { + type: 'cxtdragout', + cyPosition: { x: pos[0], y: pos[1] } + } ) ); + } + + r.hoverData.cxtOver = near; + + if( near ){ + near.trigger( new Event( e, { + type: 'cxtdragover', + cyPosition: { x: pos[0], y: pos[1] } + } ) ); + } + + } + } + + // Check if we are drag panning the entire graph + } else if( r.hoverData.dragging ){ + preventDefault = true; + + if( cy.panningEnabled() && cy.userPanningEnabled() ){ + var deltaP; + + if( r.hoverData.justStartedPan ){ + var mdPos = r.hoverData.mdownPos; + + deltaP = { + x: ( pos[0] - mdPos[0] ) * zoom, + y: ( pos[1] - mdPos[1] ) * zoom + }; + + r.hoverData.justStartedPan = false; + + } else { + deltaP = { + x: disp[0] * zoom, + y: disp[1] * zoom + }; + + } + + cy.panBy( deltaP ); + + r.hoverData.dragged = true; + } + + // Needs reproject due to pan changing viewport + pos = r.projectIntoViewport( e.clientX, e.clientY ); + + // Checks primary button down & out of time & mouse not moved much + } else if( + select[4] == 1 && (down == null || down.isEdge()) + ){ + + if( isOverThresholdDrag ){ + + if( !r.hoverData.dragging && cy.boxSelectionEnabled() && ( multSelKeyDown || !cy.panningEnabled() || !cy.userPanningEnabled() ) ){ + r.data.bgActivePosistion = undefined; + + if( !r.hoverData.selecting ){ + cy.trigger('boxstart'); + } + + r.hoverData.selecting = true; + + r.redrawHint( 'select', true ); + r.redraw(); + + } else if( !r.hoverData.selecting && cy.panningEnabled() && cy.userPanningEnabled() ){ + var allowPassthrough = allowPanningPassthrough( down, r.hoverData.downs ); + + if( allowPassthrough ){ + r.hoverData.dragging = true; + r.hoverData.justStartedPan = true; + select[4] = 0; + + r.data.bgActivePosistion = math.array2point( mdownPos ); + + r.redrawHint( 'select', true ); + r.redraw(); + } + } + + if( down && down.isEdge() && down.active() ){ down.unactivate(); } + + } + + } else { + if( down && down.isEdge() && down.active() ){ down.unactivate(); } + + if( ( !down || !down.grabbed() ) && near != last ){ + + if( last ){ + triggerEvents( last, [ 'mouseout', 'tapdragout' ], e, { + cyPosition: { x: pos[0], y: pos[1] } + } ); + } + + if( near ){ + triggerEvents( near, [ 'mouseover', 'tapdragover' ], e, { + cyPosition: { x: pos[0], y: pos[1] } + } ); + } + + r.hoverData.last = near; + } + + if( down && r.nodeIsDraggable( down ) ){ + + if( isOverThresholdDrag ){ // then drag + + var justStartedDrag = !r.dragData.didDrag; + + if( justStartedDrag ){ + r.redrawHint( 'eles', true ); + } + + r.dragData.didDrag = true; // indicate that we actually did drag the node + + var toTrigger = []; + + // now, add the elements to the drag layer if not done already + if( !r.hoverData.draggingEles ){ + addNodesToDrag( cy.collection( draggedElements ), { inDragLayer: true } ); + } + + for( var i = 0; i < draggedElements.length; i++ ){ + var dEle = draggedElements[ i ]; + + // Locked nodes not draggable, as well as non-visible nodes + if( r.nodeIsDraggable( dEle ) && dEle.grabbed() ){ + var dPos = dEle._private.position; + + toTrigger.push( dEle ); + + if( is.number( disp[0] ) && is.number( disp[1] ) ){ + var updatePos = !dEle.isParent(); + + if( updatePos ){ + dPos.x += disp[0]; + dPos.y += disp[1]; + } + + if( justStartedDrag ){ + var dragDelta = r.hoverData.dragDelta; + + if( updatePos && dragDelta && is.number( dragDelta[0] ) && is.number( dragDelta[1] ) ){ + dPos.x += dragDelta[0]; + dPos.y += dragDelta[1]; + } + } + } + + } + } + + r.hoverData.draggingEles = true; + + var tcol = cy.collection( toTrigger ); + + tcol.updateCompoundBounds(); + tcol.trigger( 'position drag' ); + + r.redrawHint( 'drag', true ); + r.redraw(); + + } else { // otherwise save drag delta for when we actually start dragging so the relative grab pos is constant + updateDragDelta(); + } + } + + // prevent the dragging from triggering text selection on the page + preventDefault = true; + } + + select[2] = pos[0]; select[3] = pos[1]; + + if( preventDefault ){ + if( e.stopPropagation ) e.stopPropagation(); + if( e.preventDefault ) e.preventDefault(); + return false; + } + }, false ); + + r.registerBinding( window, 'mouseup', function mouseupHandler( e ){ // eslint-disable-line no-undef + var capture = r.hoverData.capture; + if( !capture ){ return; } + r.hoverData.capture = false; + + var cy = r.cy; var pos = r.projectIntoViewport( e.clientX, e.clientY ); var select = r.selection; + var near = r.findNearestElement( pos[0], pos[1], true, false ); + var draggedElements = r.dragData.possibleDragElements; var down = r.hoverData.down; + var multSelKeyDown = isMultSelKeyDown( e ); + + if( r.data.bgActivePosistion ){ + r.redrawHint( 'select', true ); + r.redraw(); + } + + r.hoverData.tapholdCancelled = true; + + r.data.bgActivePosistion = undefined; // not active bg now + + if( down ){ + down.unactivate(); + } + + if( r.hoverData.which === 3 ){ + var cxtEvt = new Event( e, { + type: 'cxttapend', + cyPosition: { x: pos[0], y: pos[1] } + } ); + + if( down ){ + down.trigger( cxtEvt ); + } else { + cy.trigger( cxtEvt ); + } + + if( !r.hoverData.cxtDragged ){ + var cxtTap = new Event( e, { + type: 'cxttap', + cyPosition: { x: pos[0], y: pos[1] } + } ); + + if( down ){ + down.trigger( cxtTap ); + } else { + cy.trigger( cxtTap ); + } + } + + r.hoverData.cxtDragged = false; + r.hoverData.which = null; + + } else if( r.hoverData.which === 1 ){ + + // Deselect all elements if nothing is currently under the mouse cursor and we aren't dragging something + if( (down == null) // not mousedown on node + && !r.dragData.didDrag // didn't move the node around + && !r.hoverData.selecting // not box selection + && !r.hoverData.dragged // didn't pan + && !isMultSelKeyDown( e ) + ){ + + cy.$( function(){ + return this.selected(); + } ).unselect(); + + if( draggedElements.length > 0 ){ + r.redrawHint( 'eles', true ); + } + + r.dragData.possibleDragElements = draggedElements = []; + } + + triggerEvents( near, [ 'mouseup', 'tapend', 'vmouseup' ], e, { + cyPosition: { x: pos[0], y: pos[1] } + } ); + + if( + !r.dragData.didDrag // didn't move a node around + && !r.hoverData.dragged // didn't pan + && !r.hoverData.selecting // not box selection + ){ + triggerEvents( down, ['click', 'tap', 'vclick'], e, { + cyPosition: { x: pos[0], y: pos[1] } + } ); + } + + // Single selection + if( near == down && !r.dragData.didDrag && !r.hoverData.selecting ){ + if( near != null && near._private.selectable ){ + + if( r.hoverData.dragging ){ + // if panning, don't change selection state + } else if( cy.selectionType() === 'additive' || multSelKeyDown ){ + if( near.selected() ){ + near.unselect(); + } else { + near.select(); + } + } else { + if( !multSelKeyDown ){ + cy.$( ':selected' ).unmerge( near ).unselect(); + near.select(); + } + } + + r.redrawHint( 'eles', true ); + } + } + + if( r.hoverData.selecting ){ + var box = cy.collection( r.getAllInBox( select[0], select[1], select[2], select[3] ) ); + + r.redrawHint( 'select', true ); + + if( box.length > 0 ){ + r.redrawHint( 'eles', true ); + } + + cy.trigger('boxend'); + + var eleWouldBeSelected = function( ele ){ return ele.selectable() && !ele.selected(); }; + + if( cy.selectionType() === 'additive' ){ + box + .trigger('box') + .stdFilter( eleWouldBeSelected ) + .select() + .trigger('boxselect') + ; + } else { + if( !multSelKeyDown ){ + cy.$( ':selected' ).unmerge( box ).unselect(); + } + + box + .trigger('box') + .stdFilter( eleWouldBeSelected ) + .select() + .trigger('boxselect') + ; + } + + // always need redraw in case eles unselectable + r.redraw(); + + } + + // Cancel drag pan + if( r.hoverData.dragging ){ + r.hoverData.dragging = false; + + r.redrawHint( 'select', true ); + r.redrawHint( 'eles', true ); + + r.redraw(); + } + + if( !select[4] ) { + r.redrawHint('drag', true); + r.redrawHint('eles', true); + + var downWasGrabbed = down && down.grabbed(); + + freeDraggedElements( draggedElements ); + + if( downWasGrabbed ){ down.trigger('free'); } + } + + } // else not right mouse + + select[4] = 0; r.hoverData.down = null; + + r.hoverData.cxtStarted = false; + r.hoverData.draggingEles = false; + r.hoverData.selecting = false; + r.dragData.didDrag = false; + r.hoverData.dragged = false; + r.hoverData.dragDelta = []; + r.hoverData.mdownPos = null; + r.hoverData.mdownGPos = null; + + }, false ); + + var wheelHandler = function( e ){ + + + if( r.scrollingPage ){ return; } // while scrolling, ignore wheel-to-zoom + + var cy = r.cy; + var pos = r.projectIntoViewport( e.clientX, e.clientY ); + var rpos = [ pos[0] * cy.zoom() + cy.pan().x, + pos[1] * cy.zoom() + cy.pan().y ]; + + if( r.hoverData.draggingEles || r.hoverData.dragging || r.hoverData.cxtStarted || inBoxSelection() ){ // if pan dragging or cxt dragging, wheel movements make no zoom + e.preventDefault(); + return; + } + + if( cy.panningEnabled() && cy.userPanningEnabled() && cy.zoomingEnabled() && cy.userZoomingEnabled() ){ + e.preventDefault(); + + r.data.wheelZooming = true; + clearTimeout( r.data.wheelTimeout ); + r.data.wheelTimeout = setTimeout( function(){ + r.data.wheelZooming = false; + + r.redrawHint( 'eles', true ); + r.redraw(); + }, 150 ); + + var diff = e.deltaY / -250 || e.wheelDeltaY / 1000 || e.wheelDelta / 1000; + diff = diff * r.wheelSensitivity; + + var needsWheelFix = e.deltaMode === 1; + if( needsWheelFix ){ // fixes slow wheel events on ff/linux and ff/windows + diff *= 33; + } + + cy.zoom( { + level: cy.zoom() * Math.pow( 10, diff ), + renderedPosition: { x: rpos[0], y: rpos[1] } + } ); + } + + }; + + // Functions to help with whether mouse wheel should trigger zooming + // -- + r.registerBinding( r.container, 'wheel', wheelHandler, true ); + + // disable nonstandard wheel events + // r.registerBinding(r.container, 'mousewheel', wheelHandler, true); + // r.registerBinding(r.container, 'DOMMouseScroll', wheelHandler, true); + // r.registerBinding(r.container, 'MozMousePixelScroll', wheelHandler, true); // older firefox + + r.registerBinding( window, 'scroll', function scrollHandler( e ){ // eslint-disable-line no-undef + r.scrollingPage = true; + + clearTimeout( r.scrollingPageTimeout ); + r.scrollingPageTimeout = setTimeout( function(){ + r.scrollingPage = false; + }, 250 ); + }, true ); + + // Functions to help with handling mouseout/mouseover on the Cytoscape container + // Handle mouseout on Cytoscape container + r.registerBinding( r.container, 'mouseout', function mouseOutHandler( e ){ + var pos = r.projectIntoViewport( e.clientX, e.clientY ); + + r.cy.trigger( new Event( e, { + type: 'mouseout', + cyPosition: { x: pos[0], y: pos[1] } + } ) ); + }, false ); + + r.registerBinding( r.container, 'mouseover', function mouseOverHandler( e ){ + var pos = r.projectIntoViewport( e.clientX, e.clientY ); + + r.cy.trigger( new Event( e, { + type: 'mouseover', + cyPosition: { x: pos[0], y: pos[1] } + } ) ); + }, false ); + + var f1x1, f1y1, f2x1, f2y1; // starting points for pinch-to-zoom + var distance1, distance1Sq; // initial distance between finger 1 and finger 2 for pinch-to-zoom + var center1, modelCenter1; // center point on start pinch to zoom + var offsetLeft, offsetTop; + var containerWidth, containerHeight; + var twoFingersStartInside; + + var distance = function( x1, y1, x2, y2 ){ + return Math.sqrt( (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1) ); + }; + + var distanceSq = function( x1, y1, x2, y2 ){ + return (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1); + }; + + var touchstartHandler; + r.registerBinding( r.container, 'touchstart', touchstartHandler = function( e ){ + r.touchData.capture = true; + r.data.bgActivePosistion = undefined; + + var cy = r.cy; + var now = r.touchData.now; + var earlier = r.touchData.earlier; + + if( e.touches[0] ){ var pos = r.projectIntoViewport( e.touches[0].clientX, e.touches[0].clientY ); now[0] = pos[0]; now[1] = pos[1]; } + if( e.touches[1] ){ var pos = r.projectIntoViewport( e.touches[1].clientX, e.touches[1].clientY ); now[2] = pos[0]; now[3] = pos[1]; } + if( e.touches[2] ){ var pos = r.projectIntoViewport( e.touches[2].clientX, e.touches[2].clientY ); now[4] = pos[0]; now[5] = pos[1]; } + + // record starting points for pinch-to-zoom + if( e.touches[1] ){ + + freeDraggedElements( r.dragData.touchDragEles ); + + var offsets = r.findContainerClientCoords(); + offsetLeft = offsets[0]; + offsetTop = offsets[1]; + containerWidth = offsets[2]; + containerHeight = offsets[3]; + + f1x1 = e.touches[0].clientX - offsetLeft; + f1y1 = e.touches[0].clientY - offsetTop; + + f2x1 = e.touches[1].clientX - offsetLeft; + f2y1 = e.touches[1].clientY - offsetTop; + + twoFingersStartInside = + 0 <= f1x1 && f1x1 <= containerWidth + && 0 <= f2x1 && f2x1 <= containerWidth + && 0 <= f1y1 && f1y1 <= containerHeight + && 0 <= f2y1 && f2y1 <= containerHeight + ; + + var pan = cy.pan(); + var zoom = cy.zoom(); + + distance1 = distance( f1x1, f1y1, f2x1, f2y1 ); + distance1Sq = distanceSq( f1x1, f1y1, f2x1, f2y1 ); + center1 = [ (f1x1 + f2x1) / 2, (f1y1 + f2y1) / 2 ]; + modelCenter1 = [ + (center1[0] - pan.x) / zoom, + (center1[1] - pan.y) / zoom + ]; + + // consider context tap + var cxtDistThreshold = 200; + var cxtDistThresholdSq = cxtDistThreshold * cxtDistThreshold; + if( distance1Sq < cxtDistThresholdSq && !e.touches[2] ){ + + var near1 = r.findNearestElement( now[0], now[1], true, true ); + var near2 = r.findNearestElement( now[2], now[3], true, true ); + + if( near1 && near1.isNode() ){ + near1.activate().trigger( new Event( e, { + type: 'cxttapstart', + cyPosition: { x: now[0], y: now[1] } + } ) ); + r.touchData.start = near1; + + } else if( near2 && near2.isNode() ){ + near2.activate().trigger( new Event( e, { + type: 'cxttapstart', + cyPosition: { x: now[0], y: now[1] } + } ) ); + r.touchData.start = near2; + + } else { + cy.trigger( new Event( e, { + type: 'cxttapstart', + cyPosition: { x: now[0], y: now[1] } + } ) ); + r.touchData.start = null; + } + + if( r.touchData.start ){ r.touchData.start._private.grabbed = false; } + r.touchData.cxt = true; + r.touchData.cxtDragged = false; + r.data.bgActivePosistion = undefined; + + r.redraw(); + return; + + } + + } + + if( e.touches[2] ){ + // ignore + } else if( e.touches[1] ){ + // ignore + } else if( e.touches[0] ){ + var nears = r.findNearestElements( now[0], now[1], true, true ); + var near = nears[0]; + + if( near != null ){ + near.activate(); + + r.touchData.start = near; + r.touchData.starts = nears; + + if( r.nodeIsGrabbable( near ) ){ + + var draggedEles = r.dragData.touchDragEles = []; + + r.redrawHint( 'eles', true ); + r.redrawHint( 'drag', true ); + + if( near.selected() ){ + // reset drag elements, since near will be added again + + var selectedNodes = cy.$( function(){ + return this.selected() && r.nodeIsGrabbable( this ); + } ); + + addNodesToDrag( selectedNodes, { addToList: draggedEles } ); + } else { + addNodeToDrag( near, { addToList: draggedEles } ); + } + + setGrabTarget( near ); + + near.trigger( new Event( e, { + type: 'grab', + cyPosition: { x: now[0], y: now[1] } + } ) ); + } + } + + triggerEvents( near, [ 'touchstart', 'tapstart', 'vmousedown' ], e, { + cyPosition: { x: now[0], y: now[1] } + } ); + + if( near == null ){ + r.data.bgActivePosistion = { + x: pos[0], + y: pos[1] + }; + + r.redrawHint( 'select', true ); + r.redraw(); + } + + + // Tap, taphold + // ----- + + r.touchData.startPosition = []; + for (var i=0; i<now.length; i++) { + earlier[i] = now[i]; + r.touchData.startPosition[i] = now[i]; + } + + r.touchData.startGPosition = [ e.touches[0].clientX, e.touches[0].clientY ]; + + r.touchData.singleTouchMoved = false; + r.touchData.singleTouchStartTime = +new Date(); + + clearTimeout( r.touchData.tapholdTimeout ); + r.touchData.tapholdTimeout = setTimeout( function(){ + if( + r.touchData.singleTouchMoved === false + && !r.pinching // if pinching, then taphold unselect shouldn't take effect + && !r.touchData.selecting // box selection shouldn't allow taphold through + ){ + triggerEvents( r.touchData.start, [ 'taphold' ], e, { + cyPosition: { x: now[0], y: now[1] } + } ); + + if( !r.touchData.start ){ + cy.$( ':selected' ).unselect(); + } + + } + }, r.tapholdDuration ); + } + + }, false ); + + var touchmoveHandler; + r.registerBinding(window, 'touchmove', touchmoveHandler = function(e) { // eslint-disable-line no-undef + var select = r.selection; + var capture = r.touchData.capture; + var cy = r.cy; + var now = r.touchData.now; + var earlier = r.touchData.earlier; + var zoom = cy.zoom(); + + if( e.touches[0] ){ var pos = r.projectIntoViewport( e.touches[0].clientX, e.touches[0].clientY ); now[0] = pos[0]; now[1] = pos[1]; } + if( e.touches[1] ){ var pos = r.projectIntoViewport( e.touches[1].clientX, e.touches[1].clientY ); now[2] = pos[0]; now[3] = pos[1]; } + if( e.touches[2] ){ var pos = r.projectIntoViewport( e.touches[2].clientX, e.touches[2].clientY ); now[4] = pos[0]; now[5] = pos[1]; } + + var isOverThresholdDrag; + + if( capture && e.touches[0] ){ + var disp = []; for (var j=0;j<now.length;j++) { disp[j] = now[j] - earlier[j]; } + var startGPos = r.touchData.startGPosition; + var dx = e.touches[0].clientX - startGPos[0]; + var dx2 = dx * dx; + var dy = e.touches[0].clientY - startGPos[1]; + var dy2 = dy * dy; + var dist2 = dx2 + dy2; + + isOverThresholdDrag = dist2 >= r.touchTapThreshold2; + } + + // context swipe cancelling + if( capture && r.touchData.cxt ){ + e.preventDefault(); + + var f1x2 = e.touches[0].clientX - offsetLeft, f1y2 = e.touches[0].clientY - offsetTop; + var f2x2 = e.touches[1].clientX - offsetLeft, f2y2 = e.touches[1].clientY - offsetTop; + // var distance2 = distance( f1x2, f1y2, f2x2, f2y2 ); + var distance2Sq = distanceSq( f1x2, f1y2, f2x2, f2y2 ); + var factorSq = distance2Sq / distance1Sq; + + var distThreshold = 150; + var distThresholdSq = distThreshold * distThreshold; + var factorThreshold = 1.5; + var factorThresholdSq = factorThreshold * factorThreshold; + + // cancel ctx gestures if the distance b/t the fingers increases + if( factorSq >= factorThresholdSq || distance2Sq >= distThresholdSq ){ + r.touchData.cxt = false; + if( r.touchData.start ){ r.touchData.start.unactivate(); r.touchData.start = null; } + r.data.bgActivePosistion = undefined; + r.redrawHint( 'select', true ); + + var cxtEvt = new Event( e, { + type: 'cxttapend', + cyPosition: { x: now[0], y: now[1] } + } ); + if( r.touchData.start ){ + r.touchData.start.trigger( cxtEvt ); + } else { + cy.trigger( cxtEvt ); + } + } + + } + + // context swipe + if( capture && r.touchData.cxt ){ + var cxtEvt = new Event( e, { + type: 'cxtdrag', + cyPosition: { x: now[0], y: now[1] } + } ); + r.data.bgActivePosistion = undefined; + r.redrawHint( 'select', true ); + + if( r.touchData.start ){ + r.touchData.start.trigger( cxtEvt ); + } else { + cy.trigger( cxtEvt ); + } + + if( r.touchData.start ){ r.touchData.start._private.grabbed = false; } + r.touchData.cxtDragged = true; + + var near = r.findNearestElement( now[0], now[1], true, true ); + + if( !r.touchData.cxtOver || near !== r.touchData.cxtOver ){ + + if( r.touchData.cxtOver ){ + r.touchData.cxtOver.trigger( new Event( e, { + type: 'cxtdragout', + cyPosition: { x: now[0], y: now[1] } + } ) ); + } + + r.touchData.cxtOver = near; + + if( near ){ + near.trigger( new Event( e, { + type: 'cxtdragover', + cyPosition: { x: now[0], y: now[1] } + } ) ); + + } + + } + + // box selection + } else if( capture && e.touches[2] && cy.boxSelectionEnabled() ){ + e.preventDefault(); + + r.data.bgActivePosistion = undefined; + + this.lastThreeTouch = +new Date(); + + if( !r.touchData.selecting ){ + cy.trigger('boxstart'); + } + + r.touchData.selecting = true; + + r.redrawHint( 'select', true ); + + if( !select || select.length === 0 || select[0] === undefined ){ + select[0] = (now[0] + now[2] + now[4]) / 3; + select[1] = (now[1] + now[3] + now[5]) / 3; + select[2] = (now[0] + now[2] + now[4]) / 3 + 1; + select[3] = (now[1] + now[3] + now[5]) / 3 + 1; + } else { + select[2] = (now[0] + now[2] + now[4]) / 3; + select[3] = (now[1] + now[3] + now[5]) / 3; + } + + select[4] = 1; + r.touchData.selecting = true; + + r.redraw(); + + // pinch to zoom + } else if( capture && e.touches[1] && cy.zoomingEnabled() && cy.panningEnabled() && cy.userZoomingEnabled() && cy.userPanningEnabled() ){ // two fingers => pinch to zoom + e.preventDefault(); + + r.data.bgActivePosistion = undefined; + r.redrawHint( 'select', true ); + + var draggedEles = r.dragData.touchDragEles; + if( draggedEles ){ + r.redrawHint( 'drag', true ); + + for( var i = 0; i < draggedEles.length; i++ ){ + draggedEles[ i ]._private.grabbed = false; + draggedEles[ i ]._private.rscratch.inDragLayer = false; + } + } + + // (x2, y2) for fingers 1 and 2 + var f1x2 = e.touches[0].clientX - offsetLeft, f1y2 = e.touches[0].clientY - offsetTop; + var f2x2 = e.touches[1].clientX - offsetLeft, f2y2 = e.touches[1].clientY - offsetTop; + + + var distance2 = distance( f1x2, f1y2, f2x2, f2y2 ); + // var distance2Sq = distanceSq( f1x2, f1y2, f2x2, f2y2 ); + // var factor = Math.sqrt( distance2Sq ) / Math.sqrt( distance1Sq ); + var factor = distance2 / distance1; + + if( factor != 1 && twoFingersStartInside ){ + // delta finger1 + var df1x = f1x2 - f1x1; + var df1y = f1y2 - f1y1; + + // delta finger 2 + var df2x = f2x2 - f2x1; + var df2y = f2y2 - f2y1; + + // translation is the normalised vector of the two fingers movement + // i.e. so pinching cancels out and moving together pans + var tx = (df1x + df2x) / 2; + var ty = (df1y + df2y) / 2; + + // adjust factor by the speed multiplier + // var speed = 1.5; + // if( factor > 1 ){ + // factor = (factor - 1) * speed + 1; + // } else { + // factor = 1 - (1 - factor) * speed; + // } + + // now calculate the zoom + var zoom1 = cy.zoom(); + var zoom2 = zoom1 * factor; + var pan1 = cy.pan(); + + // the model center point converted to the current rendered pos + var ctrx = modelCenter1[0] * zoom1 + pan1.x; + var ctry = modelCenter1[1] * zoom1 + pan1.y; + + var pan2 = { + x: -zoom2 / zoom1 * (ctrx - pan1.x - tx) + ctrx, + y: -zoom2 / zoom1 * (ctry - pan1.y - ty) + ctry + }; + + // remove dragged eles + if( r.touchData.start ){ + var draggedEles = r.dragData.touchDragEles; + + freeDraggedElements( draggedEles ); + + r.redrawHint( 'drag', true ); + r.redrawHint( 'eles', true ); + + r.touchData.start + .trigger( 'free' ) + .unactivate() + ; + } + + cy.viewport( { + zoom: zoom2, + pan: pan2, + cancelOnFailedZoom: true + } ); + + distance1 = distance2; + f1x1 = f1x2; + f1y1 = f1y2; + f2x1 = f2x2; + f2y1 = f2y2; + + r.pinching = true; + } + + // Re-project + if( e.touches[0] ){ var pos = r.projectIntoViewport( e.touches[0].clientX, e.touches[0].clientY ); now[0] = pos[0]; now[1] = pos[1]; } + if( e.touches[1] ){ var pos = r.projectIntoViewport( e.touches[1].clientX, e.touches[1].clientY ); now[2] = pos[0]; now[3] = pos[1]; } + if( e.touches[2] ){ var pos = r.projectIntoViewport( e.touches[2].clientX, e.touches[2].clientY ); now[4] = pos[0]; now[5] = pos[1]; } + + } else if( e.touches[0] ){ + var start = r.touchData.start; + var last = r.touchData.last; + var near; + + if( !r.hoverData.draggingEles && !r.swipePanning ){ + near = r.findNearestElement( now[0], now[1], true, true ); + } + + if( capture && start != null ){ + e.preventDefault(); + } + + // dragging nodes + if( capture && start != null && r.nodeIsDraggable( start ) ){ + + if( isOverThresholdDrag ){ // then dragging can happen + var draggedEles = r.dragData.touchDragEles; + var justStartedDrag = !r.dragData.didDrag; + + if( justStartedDrag ){ + addNodesToDrag( cy.collection( draggedEles ), { inDragLayer: true } ); + } + + for( var k = 0; k < draggedEles.length; k++ ){ + var draggedEle = draggedEles[ k ]; + + if( r.nodeIsDraggable( draggedEle ) && draggedEle.grabbed() ){ + r.dragData.didDrag = true; + var dPos = draggedEle._private.position; + var updatePos = !draggedEle.isParent(); + + if( updatePos && is.number( disp[0] ) && is.number( disp[1] ) ){ + dPos.x += disp[0]; + dPos.y += disp[1]; + } + + if( justStartedDrag ){ + r.redrawHint( 'eles', true ); + + var dragDelta = r.touchData.dragDelta; + + if( updatePos && dragDelta && is.number( dragDelta[0] ) && is.number( dragDelta[1] ) ){ + dPos.x += dragDelta[0]; + dPos.y += dragDelta[1]; + } + + } + } + } + + var tcol = cy.collection( draggedEles ); + + tcol.updateCompoundBounds(); + tcol.trigger( 'position drag' ); + + r.hoverData.draggingEles = true; + + r.redrawHint( 'drag', true ); + + if( + r.touchData.startPosition[0] == earlier[0] + && r.touchData.startPosition[1] == earlier[1] + ){ + + r.redrawHint( 'eles', true ); + } + + r.redraw(); + } else { // otherise keep track of drag delta for later + var dragDelta = r.touchData.dragDelta = r.touchData.dragDelta || []; + + if( dragDelta.length === 0 ){ + dragDelta.push( disp[0] ); + dragDelta.push( disp[1] ); + } else { + dragDelta[0] += disp[0]; + dragDelta[1] += disp[1]; + } + } + } + + // touchmove + { + triggerEvents( (start || near), [ 'touchmove', 'tapdrag', 'vmousemove' ], e, { + cyPosition: { x: now[0], y: now[1] } + } ); + + if( ( !start || !start.grabbed() ) && near != last ){ + if( last ){ last.trigger( new Event( e, { type: 'tapdragout', cyPosition: { x: now[0], y: now[1] } } ) ); } + if( near ){ near.trigger( new Event( e, { type: 'tapdragover', cyPosition: { x: now[0], y: now[1] } } ) ); } + } + + r.touchData.last = near; + } + + // check to cancel taphold + if( capture ){ + for( var i = 0; i < now.length; i++ ){ + if( now[ i ] + && r.touchData.startPosition[ i ] + && isOverThresholdDrag ){ + + r.touchData.singleTouchMoved = true; + } + } + } + + // panning + if( + capture + && ( start == null || start.isEdge() ) + && cy.panningEnabled() && cy.userPanningEnabled() + ){ + + var allowPassthrough = allowPanningPassthrough( start, r.touchData.starts ); + + if( allowPassthrough ){ + e.preventDefault(); + + if( r.swipePanning ){ + cy.panBy( { + x: disp[0] * zoom, + y: disp[1] * zoom + } ); + + } else if( isOverThresholdDrag ){ + r.swipePanning = true; + + cy.panBy( { + x: dx * zoom, + y: dy * zoom + } ); + + if( start ){ + start.unactivate(); + + if( !r.data.bgActivePosistion ){ + r.data.bgActivePosistion = math.array2point( r.touchData.startPosition ); + } + + r.redrawHint( 'select', true ); + + r.touchData.start = null; + } + } + + } + + // Re-project + var pos = r.projectIntoViewport( e.touches[0].clientX, e.touches[0].clientY ); + now[0] = pos[0]; now[1] = pos[1]; + } + } + + for( var j = 0; j < now.length; j++ ){ earlier[ j ] = now[ j ]; } + //r.redraw(); + + }, false ); + + var touchcancelHandler; + r.registerBinding( window, 'touchcancel', touchcancelHandler = function( e ){ // eslint-disable-line no-undef + var start = r.touchData.start; + + r.touchData.capture = false; + + if( start ){ + start.unactivate(); + } + } ); + + var touchendHandler; + r.registerBinding( window, 'touchend', touchendHandler = function( e ){ // eslint-disable-line no-undef + var start = r.touchData.start; + + var capture = r.touchData.capture; + + if( capture ){ + r.touchData.capture = false; + + e.preventDefault(); + } else { + return; + } + + var select = r.selection; + + r.swipePanning = false; + r.hoverData.draggingEles = false; + + var cy = r.cy; + var zoom = cy.zoom(); + var now = r.touchData.now; + var earlier = r.touchData.earlier; + + if( e.touches[0] ){ var pos = r.projectIntoViewport( e.touches[0].clientX, e.touches[0].clientY ); now[0] = pos[0]; now[1] = pos[1]; } + if( e.touches[1] ){ var pos = r.projectIntoViewport( e.touches[1].clientX, e.touches[1].clientY ); now[2] = pos[0]; now[3] = pos[1]; } + if( e.touches[2] ){ var pos = r.projectIntoViewport( e.touches[2].clientX, e.touches[2].clientY ); now[4] = pos[0]; now[5] = pos[1]; } + + if( start ){ + start.unactivate(); + } + + var ctxTapend; + if( r.touchData.cxt ){ + ctxTapend = new Event( e, { + type: 'cxttapend', + cyPosition: { x: now[0], y: now[1] } + } ); + + if( start ){ + start.trigger( ctxTapend ); + } else { + cy.trigger( ctxTapend ); + } + + if( !r.touchData.cxtDragged ){ + var ctxTap = new Event( e, { + type: 'cxttap', + cyPosition: { x: now[0], y: now[1] } + } ); + + if( start ){ + start.trigger( ctxTap ); + } else { + cy.trigger( ctxTap ); + } + + } + + if( r.touchData.start ){ r.touchData.start._private.grabbed = false; } + r.touchData.cxt = false; + r.touchData.start = null; + + r.redraw(); + return; + } + + // no more box selection if we don't have three fingers + if( !e.touches[2] && cy.boxSelectionEnabled() && r.touchData.selecting ){ + r.touchData.selecting = false; + + var box = cy.collection( r.getAllInBox( select[0], select[1], select[2], select[3] ) ); + + select[0] = undefined; + select[1] = undefined; + select[2] = undefined; + select[3] = undefined; + select[4] = 0; + + r.redrawHint( 'select', true ); + + cy.trigger('boxend'); + + var eleWouldBeSelected = function( ele ){ return ele.selectable() && !ele.selected(); }; + + box + .trigger('box') + .stdFilter( eleWouldBeSelected ) + .select() + .trigger('boxselect') + ; + + if( box.nonempty() ){ + r.redrawHint( 'eles', true ); + } + + r.redraw(); + } + + if( start != null ){ + start.unactivate(); + } + + if( e.touches[2] ){ + r.data.bgActivePosistion = undefined; + r.redrawHint( 'select', true ); + } else if( e.touches[1] ){ + // ignore + } else if( e.touches[0] ){ + // ignore + + // Last touch released + } else if( !e.touches[0] ){ + + r.data.bgActivePosistion = undefined; + r.redrawHint( 'select', true ); + + var draggedEles = r.dragData.touchDragEles; + + if( start != null ){ + + var startWasGrabbed = start._private.grabbed; + + freeDraggedElements( draggedEles ); + + r.redrawHint( 'drag', true ); + r.redrawHint( 'eles', true ); + + if( startWasGrabbed ){ + start.trigger( 'free' ); + } + + triggerEvents( start, [ 'touchend', 'tapend', 'vmouseup', 'tapdragout' ], e, { + cyPosition: { x: now[0], y: now[1] } + } ); + + start.unactivate(); + + r.touchData.start = null; + + } else { + var near = r.findNearestElement( now[0], now[1], true, true ); + + triggerEvents( near, [ 'touchend', 'tapend', 'vmouseup', 'tapdragout' ], e, { + cyPosition: { x: now[0], y: now[1] } + } ); + + } + + var dx = r.touchData.startPosition[0] - now[0]; + var dx2 = dx * dx; + var dy = r.touchData.startPosition[1] - now[1]; + var dy2 = dy * dy; + var dist2 = dx2 + dy2; + var rdist2 = dist2 * zoom * zoom; + + // Prepare to select the currently touched node, only if it hasn't been dragged past a certain distance + if( start != null + && !r.dragData.didDrag // didn't drag nodes around + && start._private.selectable + && rdist2 < r.touchTapThreshold2 + && !r.pinching // pinch to zoom should not affect selection + ){ + + if( cy.selectionType() === 'single' ){ + cy.$( ':selected' ).unmerge( start ).unselect(); + start.select(); + } else { + if( start.selected() ){ + start.unselect(); + } else { + start.select(); + } + } + + r.redrawHint( 'eles', true ); + } + + // Tap event, roughly same as mouse click event for touch + if( !r.touchData.singleTouchMoved ){ + triggerEvents( start, [ 'tap', 'vclick' ], e, { + cyPosition: { x: now[0], y: now[1] } + } ); + } + + r.touchData.singleTouchMoved = true; + } + + for( var j = 0; j < now.length; j++ ){ earlier[ j ] = now[ j ]; } + + r.dragData.didDrag = false; // reset for next mousedown + + if( e.touches.length === 0 ){ + r.touchData.dragDelta = []; + r.touchData.startPosition = null; + r.touchData.startGPosition = null; + } + + if( e.touches.length < 2 ){ + r.pinching = false; + r.redrawHint( 'eles', true ); + r.redraw(); + } + + //r.redraw(); + + }, false ); + + // fallback compatibility layer for ms pointer events + if( typeof TouchEvent === 'undefined' ){ + + var pointers = []; + + var makeTouch = function( e ){ + return { + clientX: e.clientX, + clientY: e.clientY, + force: 1, + identifier: e.pointerId, + pageX: e.pageX, + pageY: e.pageY, + radiusX: e.width / 2, + radiusY: e.height / 2, + screenX: e.screenX, + screenY: e.screenY, + target: e.target + }; + }; + + var makePointer = function( e ){ + return { + event: e, + touch: makeTouch( e ) + }; + }; + + var addPointer = function( e ){ + pointers.push( makePointer( e ) ); + }; + + var removePointer = function( e ){ + for( var i = 0; i < pointers.length; i++ ){ + var p = pointers[ i ]; + + if( p.event.pointerId === e.pointerId ){ + pointers.splice( i, 1 ); + return; + } + } + }; + + var updatePointer = function( e ){ + var p = pointers.filter( function( p ){ + return p.event.pointerId === e.pointerId; + } )[0]; + + p.event = e; + p.touch = makeTouch( e ); + }; + + var addTouchesToEvent = function( e ){ + e.touches = pointers.map( function( p ){ + return p.touch; + } ); + }; + + r.registerBinding( r.container, 'pointerdown', function( e ){ + if( e.pointerType === 'mouse' ){ return; } // mouse already handled + + e.preventDefault(); + + addPointer( e ); + + addTouchesToEvent( e ); + touchstartHandler( e ); + } ); + + r.registerBinding( r.container, 'pointerup', function( e ){ + if( e.pointerType === 'mouse' ){ return; } // mouse already handled + + removePointer( e ); + + addTouchesToEvent( e ); + touchendHandler( e ); + } ); + + r.registerBinding( r.container, 'pointercancel', function( e ){ + if( e.pointerType === 'mouse' ){ return; } // mouse already handled + + removePointer( e ); + + addTouchesToEvent( e ); + touchcancelHandler( e ); + } ); + + r.registerBinding( r.container, 'pointermove', function( e ){ + if( e.pointerType === 'mouse' ){ return; } // mouse already handled + + e.preventDefault(); + + updatePointer( e ); + + addTouchesToEvent( e ); + touchmoveHandler( e ); + } ); + + } +}; + +module.exports = BRp; + +},{"../../../event":45,"../../../is":83,"../../../math":85,"../../../util":100}],62:[function(_dereq_,module,exports){ +'use strict'; + +var math = _dereq_( '../../../math' ); + +var BRp = {}; + +BRp.generatePolygon = function( name, points ){ + return ( this.nodeShapes[ name ] = { + renderer: this, + + name: name, + + points: points, + + draw: function( context, centerX, centerY, width, height ){ + this.renderer.nodeShapeImpl( 'polygon', context, centerX, centerY, width, height, this.points ); + }, + + intersectLine: function( nodeX, nodeY, width, height, x, y, padding ){ + return math.polygonIntersectLine( + x, y, + this.points, + nodeX, + nodeY, + width / 2, height / 2, + padding ) + ; + }, + + checkPoint: function( x, y, padding, width, height, centerX, centerY ){ + return math.pointInsidePolygon( x, y, this.points, + centerX, centerY, width, height, [0, -1], padding ) + ; + } + } ); +}; + +BRp.generateEllipse = function(){ + return ( this.nodeShapes['ellipse'] = { + renderer: this, + + name: 'ellipse', + + draw: function( context, centerX, centerY, width, height ){ + this.renderer.nodeShapeImpl( this.name, context, centerX, centerY, width, height ); + }, + + intersectLine: function( nodeX, nodeY, width, height, x, y, padding ){ + return math.intersectLineEllipse( + x, y, + nodeX, + nodeY, + width / 2 + padding, + height / 2 + padding ) + ; + }, + + checkPoint: function( x, y, padding, width, height, centerX, centerY ){ + x -= centerX; + y -= centerY; + + x /= (width / 2 + padding); + y /= (height / 2 + padding); + + return x * x + y * y <= 1; + } + } ); +}; + +BRp.generateRoundRectangle = function(){ + return ( this.nodeShapes['roundrectangle'] = { + renderer: this, + + name: 'roundrectangle', + + points: math.generateUnitNgonPointsFitToSquare( 4, 0 ), + + draw: function( context, centerX, centerY, width, height ){ + this.renderer.nodeShapeImpl( this.name, context, centerX, centerY, width, height ); + }, + + intersectLine: function( nodeX, nodeY, width, height, x, y, padding ){ + return math.roundRectangleIntersectLine( + x, y, + nodeX, + nodeY, + width, height, + padding ) + ; + }, + + // Looks like the width passed into this function is actually the total width / 2 + checkPoint: function( + x, y, padding, width, height, centerX, centerY ){ + + var cornerRadius = math.getRoundRectangleRadius( width, height ); + + // Check hBox + if( math.pointInsidePolygon( x, y, this.points, + centerX, centerY, width, height - 2 * cornerRadius, [0, -1], padding ) ){ + return true; + } + + // Check vBox + if( math.pointInsidePolygon( x, y, this.points, + centerX, centerY, width - 2 * cornerRadius, height, [0, -1], padding ) ){ + return true; + } + + var checkInEllipse = function( x, y, centerX, centerY, width, height, padding ){ + x -= centerX; + y -= centerY; + + x /= (width / 2 + padding); + y /= (height / 2 + padding); + + return (x * x + y * y <= 1); + }; + + + // Check top left quarter circle + if( checkInEllipse( x, y, + centerX - width / 2 + cornerRadius, + centerY - height / 2 + cornerRadius, + cornerRadius * 2, cornerRadius * 2, padding ) ){ + + return true; + } + + // Check top right quarter circle + if( checkInEllipse( x, y, + centerX + width / 2 - cornerRadius, + centerY - height / 2 + cornerRadius, + cornerRadius * 2, cornerRadius * 2, padding ) ){ + + return true; + } + + // Check bottom right quarter circle + if( checkInEllipse( x, y, + centerX + width / 2 - cornerRadius, + centerY + height / 2 - cornerRadius, + cornerRadius * 2, cornerRadius * 2, padding ) ){ + + return true; + } + + // Check bottom left quarter circle + if( checkInEllipse( x, y, + centerX - width / 2 + cornerRadius, + centerY + height / 2 - cornerRadius, + cornerRadius * 2, cornerRadius * 2, padding ) ){ + + return true; + } + + return false; + } + } ); +}; + +BRp.registerNodeShapes = function(){ + var nodeShapes = this.nodeShapes = {}; + var renderer = this; + + this.generateEllipse(); + + this.generatePolygon( 'triangle', math.generateUnitNgonPointsFitToSquare( 3, 0 ) ); + + this.generatePolygon( 'rectangle', math.generateUnitNgonPointsFitToSquare( 4, 0 ) ); + nodeShapes[ 'square' ] = nodeShapes[ 'rectangle' ]; + + this.generateRoundRectangle(); + + this.generatePolygon( 'diamond', [ + 0, 1, + 1, 0, + 0, -1, + -1, 0 + ] ); + + this.generatePolygon( 'pentagon', math.generateUnitNgonPointsFitToSquare( 5, 0 ) ); + + this.generatePolygon( 'hexagon', math.generateUnitNgonPointsFitToSquare( 6, 0 ) ); + + this.generatePolygon( 'heptagon', math.generateUnitNgonPointsFitToSquare( 7, 0 ) ); + + this.generatePolygon( 'octagon', math.generateUnitNgonPointsFitToSquare( 8, 0 ) ); + + var star5Points = new Array( 20 ); + { + var outerPoints = math.generateUnitNgonPoints( 5, 0 ); + var innerPoints = math.generateUnitNgonPoints( 5, Math.PI / 5 ); + + // Outer radius is 1; inner radius of star is smaller + var innerRadius = 0.5 * (3 - Math.sqrt( 5 )); + innerRadius *= 1.57; + + for( var i = 0;i < innerPoints.length / 2;i++ ){ + innerPoints[ i * 2] *= innerRadius; + innerPoints[ i * 2 + 1] *= innerRadius; + } + + for( var i = 0;i < 20 / 4;i++ ){ + star5Points[ i * 4] = outerPoints[ i * 2]; + star5Points[ i * 4 + 1] = outerPoints[ i * 2 + 1]; + + star5Points[ i * 4 + 2] = innerPoints[ i * 2]; + star5Points[ i * 4 + 3] = innerPoints[ i * 2 + 1]; + } + } + + star5Points = math.fitPolygonToSquare( star5Points ); + + this.generatePolygon( 'star', star5Points ); + + this.generatePolygon( 'vee', [ + -1, -1, + 0, -0.333, + 1, -1, + 0, 1 + ] ); + + this.generatePolygon( 'rhomboid', [ + -1, -1, + 0.333, -1, + 1, 1, + -0.333, 1 + ] ); + + nodeShapes.makePolygon = function( points ){ + + // use caching on user-specified polygons so they are as fast as native shapes + + var key = points.join( '$' ); + var name = 'polygon-' + key; + var shape; + + if( (shape = this[ name ]) ){ // got cached shape + return shape; + } + + // create and cache new shape + return renderer.generatePolygon( name, points ); + }; + +}; + +module.exports = BRp; + +},{"../../../math":85}],63:[function(_dereq_,module,exports){ +'use strict'; + +var util = _dereq_( '../../../util' ); + +var BRp = {}; + +BRp.timeToRender = function(){ + return this.redrawTotalTime / this.redrawCount; +}; + +BRp.redraw = function( options ){ + options = options || util.staticEmptyObject(); + + var r = this; + + if( r.averageRedrawTime === undefined ){ r.averageRedrawTime = 0; } + if( r.lastRedrawTime === undefined ){ r.lastRedrawTime = 0; } + if( r.lastDrawTime === undefined ){ r.lastDrawTime = 0; } + + r.requestedFrame = true; + r.renderOptions = options; +}; + +BRp.beforeRender = function( fn, priority ){ + priority = priority || 0; + + var cbs = this.beforeRenderCallbacks; + + cbs.push({ fn: fn, priority: priority }); + + // higher priority callbacks executed first + cbs.sort(function( a, b ){ return b.priority - a.priority; }); +}; + +var beforeRenderCallbacks = function( r, willDraw, startTime ){ + var cbs = r.beforeRenderCallbacks; + + for( var i = 0; i < cbs.length; i++ ){ + cbs[i].fn( willDraw, startTime ); + } +}; + +BRp.startRenderLoop = function(){ + var r = this; + + if( r.renderLoopStarted ){ + return; + } else { + r.renderLoopStarted = true; + } + + var renderFn = function( requestTime ){ + if( r.destroyed ){ return; } + + if( r.requestedFrame && !r.skipFrame ){ + beforeRenderCallbacks( r, true, requestTime ); + + var startTime = util.performanceNow(); + + r.render( r.renderOptions ); + + var endTime = r.lastDrawTime = util.performanceNow(); + + if( r.averageRedrawTime === undefined ){ + r.averageRedrawTime = endTime - startTime; + } + + if( r.redrawCount === undefined ){ + r.redrawCount = 0; + } + + r.redrawCount++; + + if( r.redrawTotalTime === undefined ){ + r.redrawTotalTime = 0; + } + + var duration = endTime - startTime; + + r.redrawTotalTime += duration; + r.lastRedrawTime = duration; + + // use a weighted average with a bias from the previous average so we don't spike so easily + r.averageRedrawTime = r.averageRedrawTime / 2 + duration / 2; + + r.requestedFrame = false; + } else { + beforeRenderCallbacks( r, false, requestTime ); + } + + r.skipFrame = false; + + util.requestAnimationFrame( renderFn ); + }; + + util.requestAnimationFrame( renderFn ); + +}; + +module.exports = BRp; + +},{"../../../util":100}],64:[function(_dereq_,module,exports){ +'use strict'; + +var CRp = {}; + +var impl; + +CRp.arrowShapeImpl = function( name ){ + return ( impl || (impl = { + 'polygon': function( context, points ){ + for( var i = 0; i < points.length; i++ ){ + var pt = points[ i ]; + + context.lineTo( pt.x, pt.y ); + } + }, + + 'triangle-backcurve': function( context, points, controlPoint ){ + var firstPt; + + for( var i = 0; i < points.length; i++ ){ + var pt = points[ i ]; + + if( i === 0 ){ + firstPt = pt; + } + + context.lineTo( pt.x, pt.y ); + } + + context.quadraticCurveTo( controlPoint.x, controlPoint.y, firstPt.x, firstPt.y ); + }, + + 'triangle-tee': function( context, trianglePoints, teePoints ){ + if( context.beginPath ){ context.beginPath(); } + + var triPts = trianglePoints; + for( var i = 0; i < triPts.length; i++ ){ + var pt = triPts[ i ]; + + context.lineTo( pt.x, pt.y ); + } + + if( context.closePath ){ context.closePath(); } + + if( context.beginPath ){ context.beginPath(); } + + var teePts = teePoints; + var firstTeePt = teePoints[0]; + context.moveTo( firstTeePt.x, firstTeePt.y ); + + for( var i = 0; i < teePts.length; i++ ){ + var pt = teePts[ i ]; + + context.lineTo( pt.x, pt.y ); + } + + if( context.closePath ){ context.closePath(); } + }, + + 'circle': function( context, rx, ry, r ){ + context.arc( rx, ry, r, 0, Math.PI * 2, false ); + } + }) )[ name ]; +}; + +module.exports = CRp; + +},{}],65:[function(_dereq_,module,exports){ +'use strict'; + +var CRp = {}; + +CRp.drawEdge = function( context, edge, shiftToOriginWithBb, drawLabel, drawOverlayInstead ){ + var rs = edge._private.rscratch; + var usePaths = this.usePaths(); + + // if bezier ctrl pts can not be calculated, then die + if( rs.badLine || isNaN(rs.allpts[0]) ){ // isNaN in case edge is impossible and browser bugs (e.g. safari) + return; + } + + // Edge line width + if( edge.pstyle( 'width' ).pfValue <= 0 ){ + return; + } + + var bb; + if( shiftToOriginWithBb ){ + bb = shiftToOriginWithBb; + + context.translate( -bb.x1, -bb.y1 ); + } + + var overlayPadding = edge.pstyle( 'overlay-padding' ).pfValue; + var overlayOpacity = edge.pstyle( 'overlay-opacity' ).value; + var overlayColor = edge.pstyle( 'overlay-color' ).value; + + // Edge color & opacity + if( drawOverlayInstead ){ + + if( overlayOpacity === 0 ){ // exit early if no overlay + return; + } + + this.strokeStyle( context, overlayColor[0], overlayColor[1], overlayColor[2], overlayOpacity ); + context.lineCap = 'round'; + + if( rs.edgeType == 'self' && !usePaths ){ + context.lineCap = 'butt'; + } + + } else { + var lineColor = edge.pstyle( 'line-color' ).value; + + this.strokeStyle( context, lineColor[0], lineColor[1], lineColor[2], edge.pstyle( 'opacity' ).value ); + + context.lineCap = 'butt'; + } + + context.lineJoin = 'round'; + + var edgeWidth = edge.pstyle( 'width' ).pfValue + (drawOverlayInstead ? 2 * overlayPadding : 0); + var lineStyle = drawOverlayInstead ? 'solid' : edge.pstyle( 'line-style' ).value; + context.lineWidth = edgeWidth; + + var shadowBlur = edge.pstyle( 'shadow-blur' ).pfValue; + var shadowOpacity = edge.pstyle( 'shadow-opacity' ).value; + var shadowColor = edge.pstyle( 'shadow-color' ).value; + var shadowOffsetX = edge.pstyle( 'shadow-offset-x' ).pfValue; + var shadowOffsetY = edge.pstyle( 'shadow-offset-y' ).pfValue; + + this.shadowStyle( context, shadowColor, drawOverlayInstead ? 0 : shadowOpacity, shadowBlur, shadowOffsetX, shadowOffsetY ); + + this.drawEdgePath( + edge, + context, + rs.allpts, + lineStyle, + edgeWidth + ); + + this.drawArrowheads( context, edge, drawOverlayInstead ); + + this.shadowStyle( context, 'transparent', 0 ); // reset for next guy + + if( !drawOverlayInstead ){ + this.drawEdge( context, edge, false, drawLabel, true ); + } + + this.drawElementText( context, edge, drawLabel ); + + if( shiftToOriginWithBb ){ + context.translate( bb.x1, bb.y1 ); + } +}; + + +CRp.drawEdgePath = function( edge, context, pts, type, width ){ + var rs = edge._private.rscratch; + var canvasCxt = context; + var path; + var pathCacheHit = false; + var usePaths = this.usePaths(); + + if( usePaths ){ + var pathCacheKey = pts.join( '$' ); + var keyMatches = rs.pathCacheKey && rs.pathCacheKey === pathCacheKey; + + if( keyMatches ){ + path = context = rs.pathCache; + pathCacheHit = true; + } else { + path = context = new Path2D(); // eslint-disable-line no-undef + rs.pathCacheKey = pathCacheKey; + rs.pathCache = path; + } + } + + if( canvasCxt.setLineDash ){ // for very outofdate browsers + switch( type ){ + case 'dotted': + canvasCxt.setLineDash( [ 1, 1 ] ); + break; + + case 'dashed': + canvasCxt.setLineDash( [ 6, 3 ] ); + break; + + case 'solid': + canvasCxt.setLineDash( [ ] ); + break; + } + } + + if( !pathCacheHit && !rs.badLine ){ + if( context.beginPath ){ context.beginPath(); } + context.moveTo( pts[0], pts[1] ); + + switch( rs.edgeType ){ + case 'bezier': + case 'self': + case 'compound': + case 'multibezier': + for( var i = 2; i + 3 < pts.length; i += 4 ){ + context.quadraticCurveTo( pts[ i ], pts[ i + 1], pts[ i + 2], pts[ i + 3] ); + } + break; + + case 'straight': + case 'segments': + case 'haystack': + for( var i = 2; i + 1 < pts.length; i += 2 ){ + context.lineTo( pts[ i ], pts[ i + 1] ); + } + break; + } + } + + context = canvasCxt; + if( usePaths ){ + context.stroke( path ); + } else { + context.stroke(); + } + + // reset any line dashes + if( context.setLineDash ){ // for very outofdate browsers + context.setLineDash( [ ] ); + } + +}; + +CRp.drawArrowheads = function( context, edge, drawOverlayInstead ){ + if( drawOverlayInstead ){ return; } // don't do anything for overlays + + var rs = edge._private.rscratch; + var isHaystack = rs.edgeType === 'haystack'; + + if( !isHaystack ){ + this.drawArrowhead( context, edge, 'source', rs.arrowStartX, rs.arrowStartY, rs.srcArrowAngle ); + } + + this.drawArrowhead( context, edge, 'mid-target', rs.midX, rs.midY, rs.midtgtArrowAngle ); + + this.drawArrowhead( context, edge, 'mid-source', rs.midX, rs.midY, rs.midsrcArrowAngle ); + + if( !isHaystack ){ + this.drawArrowhead( context, edge, 'target', rs.arrowEndX, rs.arrowEndY, rs.tgtArrowAngle ); + } +}; + +CRp.drawArrowhead = function( context, edge, prefix, x, y, angle ){ + if( isNaN( x ) || x == null || isNaN( y ) || y == null || isNaN( angle ) || angle == null ){ return; } + + var self = this; + var arrowShape = edge.pstyle( prefix + '-arrow-shape' ).value; + + if( arrowShape === 'none' ){ + return; + } + + var gco = context.globalCompositeOperation; + + var arrowClearFill = edge.pstyle( prefix + '-arrow-fill' ).value === 'hollow' ? 'both' : 'filled'; + var arrowFill = edge.pstyle( prefix + '-arrow-fill' ).value; + var opacity = edge.pstyle( 'opacity' ).value; + + if( arrowShape === 'half-triangle-overshot' ){ + arrowFill = 'hollow'; + arrowClearFill = 'hollow'; + } + + if( opacity !== 1 || arrowFill === 'hollow' ){ // then extra clear is needed + context.globalCompositeOperation = 'destination-out'; + + self.fillStyle( context, 255, 255, 255, 1 ); + self.strokeStyle( context, 255, 255, 255, 1 ); + + self.drawArrowShape( edge, prefix, context, + arrowClearFill, edge.pstyle( 'width' ).pfValue, edge.pstyle( prefix + '-arrow-shape' ).value, + x, y, angle + ); + + context.globalCompositeOperation = gco; + } // otherwise, the opaque arrow clears it for free :) + + var color = edge.pstyle( prefix + '-arrow-color' ).value; + self.fillStyle( context, color[0], color[1], color[2], opacity ); + self.strokeStyle( context, color[0], color[1], color[2], opacity ); + + self.drawArrowShape( edge, prefix, context, + arrowFill, edge.pstyle( 'width' ).pfValue, edge.pstyle( prefix + '-arrow-shape' ).value, + x, y, angle + ); +}; + +CRp.drawArrowShape = function( edge, arrowType, context, fill, edgeWidth, shape, x, y, angle ){ + var r = this; + var usePaths = this.usePaths(); + var rs = edge._private.rscratch; + var pathCacheHit = false; + var path; + var canvasContext = context; + var translation = { x: x, y: y }; + var size = this.getArrowWidth( edgeWidth ); + var shapeImpl = r.arrowShapes[ shape ]; + + if( usePaths ){ + var pathCacheKey = size + '$' + shape + '$' + angle + '$' + x + '$' + y; + rs.arrowPathCacheKey = rs.arrowPathCacheKey || {}; + rs.arrowPathCache = rs.arrowPathCache || {}; + + var alreadyCached = rs.arrowPathCacheKey[ arrowType ] === pathCacheKey; + if( alreadyCached ){ + path = context = rs.arrowPathCache[ arrowType ]; + pathCacheHit = true; + } else { + path = context = new Path2D(); // eslint-disable-line no-undef + rs.arrowPathCacheKey[ arrowType ] = pathCacheKey; + rs.arrowPathCache[ arrowType ] = path; + } + } + + if( context.beginPath ){ context.beginPath(); } + + if( !pathCacheHit ){ + shapeImpl.draw( context, size, angle, translation ); + } + + if( !shapeImpl.leavePathOpen && context.closePath ){ + context.closePath(); + } + + context = canvasContext; + + if( fill === 'filled' || fill === 'both' ){ + if( usePaths ){ + context.fill( path ); + } else { + context.fill(); + } + } + + if( fill === 'hollow' || fill === 'both' ){ + context.lineWidth = ( shapeImpl.matchEdgeWidth ? edgeWidth : 1 ); + context.lineJoin = 'miter'; + + if( usePaths ){ + context.stroke( path ); + } else { + context.stroke(); + } + + } +}; + +module.exports = CRp; + +},{}],66:[function(_dereq_,module,exports){ +'use strict'; + +var math = _dereq_( '../../../math' ); + +var CRp = {}; + +CRp.drawElement = function( context, ele, shiftToOriginWithBb, showLabel ){ + var r = this; + + if( ele.isNode() ){ + r.drawNode( context, ele, shiftToOriginWithBb, showLabel ); + } else { + r.drawEdge( context, ele, shiftToOriginWithBb, showLabel ); + } +}; + +CRp.drawCachedElement = function( context, ele, pxRatio, extent ){ + var r = this; + var bb = ele.boundingBox(); + + if( !extent || math.boundingBoxesIntersect( bb, extent ) ){ + var cache = r.data.eleTxrCache.getElement( ele, bb, pxRatio ); + + if( cache ){ + context.drawImage( cache.texture.canvas, cache.x, 0, cache.width, cache.height, bb.x1, bb.y1, bb.w, bb.h ); + } else { // if the element is not cacheable, then draw directly + r.drawElement( context, ele ); + } + } +}; + +CRp.drawElements = function( context, eles ){ + var r = this; + + for( var i = 0; i < eles.length; i++ ){ + var ele = eles[ i ]; + + r.drawElement( context, ele ); + } +}; + +CRp.drawCachedElements = function( context, eles, pxRatio, extent ){ + var r = this; + + for( var i = 0; i < eles.length; i++ ){ + var ele = eles[ i ]; + + r.drawCachedElement( context, ele, pxRatio, extent ); + } +}; + +CRp.drawCachedNodes = function( context, eles, pxRatio, extent ){ + var r = this; + + for( var i = 0; i < eles.length; i++ ){ + var ele = eles[ i ]; + + if( !ele.isNode() ){ continue; } + + r.drawCachedElement( context, ele, pxRatio, extent ); + } +}; + +CRp.drawLayeredElements = function( context, eles, pxRatio, extent ){ + var r = this; + + var layers = r.data.lyrTxrCache.getLayers( eles, pxRatio ); + + if( layers ){ + for( var i = 0; i < layers.length; i++ ){ + var layer = layers[i]; + var bb = layer.bb; + + context.drawImage( layer.canvas, bb.x1, bb.y1, bb.w, bb.h ); + } + } else { // fall back on plain caching if no layers + r.drawCachedElements( context, eles, pxRatio, extent ); + } +}; + +module.exports = CRp; + +},{"../../../math":85}],67:[function(_dereq_,module,exports){ +'use strict'; + +var CRp = {}; + +CRp.safeDrawImage = function( context, img, ix, iy, iw, ih, x, y, w, h ){ + var r = this; + + try { + context.drawImage( img, ix, iy, iw, ih, x, y, w, h ); + } catch( e ){ + r.redrawHint( 'eles', true ); + r.redrawHint( 'drag', true ); + + r.drawingImage = true; + + r.redraw(); + } +}; + +CRp.drawInscribedImage = function( context, img, node ){ + var r = this; + var nodeX = node._private.position.x; + var nodeY = node._private.position.y; + var fit = node.pstyle( 'background-fit' ).value; + var xPos = node.pstyle( 'background-position-x' ); + var yPos = node.pstyle( 'background-position-y' ); + var repeat = node.pstyle( 'background-repeat' ).value; + var nodeW = node.width(); + var nodeH = node.height(); + var rs = node._private.rscratch; + var clip = node.pstyle( 'background-clip' ).value; + var shouldClip = clip === 'node'; + var imgOpacity = node.pstyle( 'background-image-opacity' ).value; + + var imgW = img.width || img.cachedW; + var imgH = img.height || img.cachedH; + + // workaround for broken browsers like ie + if( null == imgW || null == imgH ){ + document.body.appendChild( img ); // eslint-disable-line no-undef + + imgW = img.cachedW = img.width || img.offsetWidth; + imgH = img.cachedH = img.height || img.offsetHeight; + + document.body.removeChild( img ); // eslint-disable-line no-undef + } + + var w = imgW; + var h = imgH; + + var bgW = node.pstyle( 'background-width' ); + if( bgW.value !== 'auto' ){ + if( bgW.units === '%' ){ + w = bgW.value / 100 * nodeW; + } else { + w = bgW.pfValue; + } + } + + var bgH = node.pstyle( 'background-height' ); + if( bgH.value !== 'auto' ){ + if( bgH.units === '%' ){ + h = bgH.value / 100 * nodeH; + } else { + h = bgH.pfValue; + } + } + + if( w === 0 || h === 0 ){ + return; // no point in drawing empty image (and chrome is broken in this case) + } + + if( fit === 'contain' ){ + var scale = Math.min( nodeW / w, nodeH / h ); + + w *= scale; + h *= scale; + + } else if( fit === 'cover' ){ + var scale = Math.max( nodeW / w, nodeH / h ); + + w *= scale; + h *= scale; + } + + var x = (nodeX - nodeW / 2); // left + if( xPos.units === '%' ){ + x += (nodeW - w) * xPos.value / 100; + } else { + x += xPos.pfValue; + } + + var y = (nodeY - nodeH / 2); // top + if( yPos.units === '%' ){ + y += (nodeH - h) * yPos.value / 100; + } else { + y += yPos.pfValue; + } + + if( rs.pathCache ){ + x -= nodeX; + y -= nodeY; + + nodeX = 0; + nodeY = 0; + } + + var gAlpha = context.globalAlpha; + + context.globalAlpha = imgOpacity; + + if( repeat === 'no-repeat' ){ + + if( shouldClip ){ + context.save(); + + if( rs.pathCache ){ + context.clip( rs.pathCache ); + } else { + r.nodeShapes[ r.getNodeShape( node ) ].draw( + context, + nodeX, nodeY, + nodeW, nodeH ); + + context.clip(); + } + } + + r.safeDrawImage( context, img, 0, 0, imgW, imgH, x, y, w, h ); + + if( shouldClip ){ + context.restore(); + } + } else { + var pattern = context.createPattern( img, repeat ); + context.fillStyle = pattern; + + r.nodeShapes[ r.getNodeShape( node ) ].draw( + context, + nodeX, nodeY, + nodeW, nodeH ); + + context.translate( x, y ); + context.fill(); + context.translate( -x, -y ); + } + + context.globalAlpha = gAlpha; + +}; + +module.exports = CRp; + +},{}],68:[function(_dereq_,module,exports){ +'use strict'; + +var util = _dereq_( '../../../util' ); +var math = _dereq_( '../../../math' ); + +var CRp = {}; + +CRp.eleTextBiggerThanMin = function( ele, scale ){ + if( !scale ){ + var zoom = ele.cy().zoom(); + var pxRatio = this.getPixelRatio(); + var lvl = Math.ceil( math.log2( zoom * pxRatio ) ); // the effective texture level + + scale = Math.pow( 2, lvl ); + } + + var computedSize = ele.pstyle( 'font-size' ).pfValue * scale; + var minSize = ele.pstyle( 'min-zoomed-font-size' ).pfValue; + + if( computedSize < minSize ){ + return false; + } + + return true; +}; + +CRp.drawElementText = function( context, ele, force ){ + var r = this; + + if( force === undefined ){ + if( !r.eleTextBiggerThanMin( ele ) ){ return; } + } else { + if( !force ){ return; } + } + + if( ele.isNode() ){ + var label = ele.pstyle( 'label' ); + + if( !label || !label.value ){ return; } + + var textHalign = ele.pstyle( 'text-halign' ).strValue; + var textValign = ele.pstyle( 'text-valign' ).strValue; + + switch( textHalign ){ + case 'left': + context.textAlign = 'right'; + break; + + case 'right': + context.textAlign = 'left'; + break; + + default: // e.g. center + context.textAlign = 'center'; + } + + context.textBaseline = 'bottom'; + } else { + var label = ele.pstyle( 'label' ); + var srcLabel = ele.pstyle( 'source-label' ); + var tgtLabel = ele.pstyle( 'target-label' ); + + if( + ( !label || !label.value ) + && ( !srcLabel || !srcLabel.value ) + && ( !tgtLabel || !tgtLabel.value ) + ){ + return; + } + + context.textAlign = 'center'; + context.textBaseline = 'bottom'; + } + + + r.drawText( context, ele ); + + if( ele.isEdge() ){ + r.drawText( context, ele, 'source' ); + + r.drawText( context, ele, 'target' ); + } +}; + +CRp.drawNodeText = CRp.drawEdgeText = CRp.drawElementText; + +CRp.getFontCache = function( context ){ + var cache; + + this.fontCaches = this.fontCaches || []; + + for( var i = 0; i < this.fontCaches.length; i++ ){ + cache = this.fontCaches[ i ]; + + if( cache.context === context ){ + return cache; + } + } + + cache = { + context: context + }; + this.fontCaches.push( cache ); + + return cache; +}; + +// set up canvas context with font +// returns transformed text string +CRp.setupTextStyle = function( context, ele ){ + // Font style + var parentOpacity = ele.effectiveOpacity(); + var labelStyle = ele.pstyle( 'font-style' ).strValue; + var labelSize = ele.pstyle( 'font-size' ).pfValue + 'px'; + var labelFamily = ele.pstyle( 'font-family' ).strValue; + var labelWeight = ele.pstyle( 'font-weight' ).strValue; + var opacity = ele.pstyle( 'text-opacity' ).value * ele.pstyle( 'opacity' ).value * parentOpacity; + var outlineOpacity = ele.pstyle( 'text-outline-opacity' ).value * opacity; + var color = ele.pstyle( 'color' ).value; + var outlineColor = ele.pstyle( 'text-outline-color' ).value; + var shadowBlur = ele.pstyle( 'text-shadow-blur' ).pfValue; + var shadowOpacity = ele.pstyle( 'text-shadow-opacity' ).value; + var shadowColor = ele.pstyle( 'text-shadow-color' ).value; + var shadowOffsetX = ele.pstyle( 'text-shadow-offset-x' ).pfValue; + var shadowOffsetY = ele.pstyle( 'text-shadow-offset-y' ).pfValue; + + var fontCacheKey = ele._private.fontKey; + var cache = this.getFontCache( context ); + + if( cache.key !== fontCacheKey ){ + context.font = labelStyle + ' ' + labelWeight + ' ' + labelSize + ' ' + labelFamily; + + cache.key = fontCacheKey; + } + + // Calculate text draw position based on text alignment + + // so text outlines aren't jagged + context.lineJoin = 'round'; + + this.fillStyle( context, color[ 0 ], color[ 1 ], color[ 2 ], opacity ); + + this.strokeStyle( context, outlineColor[ 0 ], outlineColor[ 1 ], outlineColor[ 2 ], outlineOpacity ); + + this.shadowStyle( context, shadowColor, shadowOpacity, shadowBlur, shadowOffsetX, shadowOffsetY ); +}; + +function roundRect( ctx, x, y, width, height, radius ){ + var radius = radius || 5; + ctx.beginPath(); + ctx.moveTo( x + radius, y ); + ctx.lineTo( x + width - radius, y ); + ctx.quadraticCurveTo( x + width, y, x + width, y + radius ); + ctx.lineTo( x + width, y + height - radius ); + ctx.quadraticCurveTo( x + width, y + height, x + width - radius, y + height ); + ctx.lineTo( x + radius, y + height ); + ctx.quadraticCurveTo( x, y + height, x, y + height - radius ); + ctx.lineTo( x, y + radius ); + ctx.quadraticCurveTo( x, y, x + radius, y ); + ctx.closePath(); + ctx.fill(); +} + +// Draw text +CRp.drawText = function( context, ele, prefix ){ + var _p = ele._private; + var rscratch = _p.rscratch; + var parentOpacity = ele.effectiveOpacity(); + if( parentOpacity === 0 || ele.pstyle( 'text-opacity' ).value === 0 ){ + return; + } + + var textX = util.getPrefixedProperty( rscratch, 'labelX', prefix ); + var textY = util.getPrefixedProperty( rscratch, 'labelY', prefix ); + var text = this.getLabelText( ele, prefix ); + + if( text != null && text !== '' && !isNaN( textX ) && !isNaN( textY ) ){ + this.setupTextStyle( context, ele ); + + var pdash = prefix ? prefix + '-' : ''; + var textW = util.getPrefixedProperty( rscratch, 'labelWidth', prefix ); + var textH = util.getPrefixedProperty( rscratch, 'labelHeight', prefix ); + var textAngle = util.getPrefixedProperty( rscratch, 'labelAngle', prefix ); + var marginX = ele.pstyle( pdash + 'text-margin-x' ).pfValue; + var marginY = ele.pstyle( pdash + 'text-margin-y' ).pfValue; + + var isEdge = ele.isEdge(); + var isNode = ele.isNode(); + + var halign = ele.pstyle( 'text-halign' ).value; + var valign = ele.pstyle( 'text-valign' ).value; + + if( isEdge ){ + halign = 'center'; + valign = 'center'; + } + + textX += marginX; + textY += marginY; + + var rotation = ele.pstyle( 'text-rotation' ); + var theta; + + if( rotation.strValue === 'autorotate' ){ + theta = isEdge ? textAngle : 0; + } else if( rotation.strValue === 'none' ){ + theta = 0; + } else { + theta = rotation.pfValue; + } + + if( theta !== 0 ){ + var orgTextX = textX; + var orgTextY = textY; + + context.translate( orgTextX, orgTextY ); + context.rotate( theta ); + + textX = 0; + textY = 0; + } + + if( isNode ){ + var pLeft = ele.pstyle( 'padding-left' ).pfValue; + var pRight = ele.pstyle( 'padding-right' ).pfValue; + var pTop = ele.pstyle( 'padding-top' ).pfValue; + var pBottom = ele.pstyle( 'padding-bottom' ).pfValue; + + textX += pLeft / 2; + textX -= pRight / 2; + + textY += pTop / 2; + textY -= pBottom / 2; + } + + switch( valign ){ + case 'top': + break; + case 'center': + textY += textH / 2; + break; + case 'bottom': + textY += textH; + break; + } + + var backgroundOpacity = ele.pstyle( 'text-background-opacity' ).value; + var borderOpacity = ele.pstyle( 'text-border-opacity' ).value; + var textBorderWidth = ele.pstyle( 'text-border-width' ).pfValue; + + if( backgroundOpacity > 0 || ( textBorderWidth > 0 && borderOpacity > 0 ) ){ + var bgX = textX; + + switch( halign ){ + case 'left': + bgX -= textW; + break; + case 'center': + bgX -= textW / 2; + break; + case 'right': + break; + } + + var bgY = textY; + + switch( valign ){ + case 'top': + bgY -= textH; + break; + case 'center': + bgY -= textH / 2; + break; + case 'bottom': + break; + } + + if( backgroundOpacity > 0 ){ + var textFill = context.fillStyle; + var textBackgroundColor = ele.pstyle( 'text-background-color' ).value; + + context.fillStyle = 'rgba(' + textBackgroundColor[ 0 ] + ',' + textBackgroundColor[ 1 ] + ',' + textBackgroundColor[ 2 ] + ',' + backgroundOpacity * parentOpacity + ')'; + var styleShape = ele.pstyle( 'text-background-shape' ).strValue; + if( styleShape == 'roundrectangle' ){ + roundRect( context, bgX, bgY, textW, textH, 2 ); + } else { + context.fillRect( bgX, bgY, textW, textH ); + } + context.fillStyle = textFill; + } + + if( textBorderWidth > 0 && borderOpacity > 0 ){ + var textStroke = context.strokeStyle; + var textLineWidth = context.lineWidth; + var textBorderColor = ele.pstyle( 'text-border-color' ).value; + var textBorderStyle = ele.pstyle( 'text-border-style' ).value; + + context.strokeStyle = 'rgba(' + textBorderColor[ 0 ] + ',' + textBorderColor[ 1 ] + ',' + textBorderColor[ 2 ] + ',' + borderOpacity * parentOpacity + ')'; + context.lineWidth = textBorderWidth; + + if( context.setLineDash ){ // for very outofdate browsers + switch( textBorderStyle ){ + case 'dotted': + context.setLineDash( [ 1, 1 ] ); + break; + case 'dashed': + context.setLineDash( [ 4, 2 ] ); + break; + case 'double': + context.lineWidth = textBorderWidth / 4; // 50% reserved for white between the two borders + context.setLineDash( [] ); + break; + case 'solid': + context.setLineDash( [] ); + break; + } + } + + context.strokeRect( bgX, bgY, textW, textH ); + + if( textBorderStyle === 'double' ){ + var whiteWidth = textBorderWidth / 2; + + context.strokeRect( bgX + whiteWidth, bgY + whiteWidth, textW - whiteWidth * 2, textH - whiteWidth * 2 ); + } + + if( context.setLineDash ){ // for very outofdate browsers + context.setLineDash( [] ); + } + context.lineWidth = textLineWidth; + context.strokeStyle = textStroke; + } + + } + + var lineWidth = 2 * ele.pstyle( 'text-outline-width' ).pfValue; // *2 b/c the stroke is drawn centred on the middle + + if( lineWidth > 0 ){ + context.lineWidth = lineWidth; + } + + if( ele.pstyle( 'text-wrap' ).value === 'wrap' ){ + var lines = rscratch.labelWrapCachedLines; + var lineHeight = textH / lines.length; + + switch( valign ){ + case 'top': + textY -= ( lines.length - 1 ) * lineHeight; + break; + + case 'bottom': + // nothing required + break; + + default: + case 'center': + textY -= ( lines.length - 1 ) * lineHeight / 2; + } + + for( var l = 0; l < lines.length; l++ ){ + if( lineWidth > 0 ){ + context.strokeText( lines[ l ], textX, textY ); + } + + context.fillText( lines[ l ], textX, textY ); + + textY += lineHeight; + } + + } else { + if( lineWidth > 0 ){ + context.strokeText( text, textX, textY ); + } + + context.fillText( text, textX, textY ); + } + + if( theta !== 0 ){ + context.rotate( -theta ); + context.translate( -orgTextX, -orgTextY ); + } + + this.shadowStyle( context, 'transparent', 0 ); // reset for next guy + } +}; + +module.exports = CRp; + +},{"../../../math":85,"../../../util":100}],69:[function(_dereq_,module,exports){ +'use strict'; + +var is = _dereq_( '../../../is' ); + +var CRp = {}; + +CRp.drawNode = function( context, node, shiftToOriginWithBb, drawLabel ){ + var r = this; + var nodeWidth, nodeHeight; + var rs = node._private.rscratch; + var _p = node._private; + var pos = pos || _p.position; + + if( !is.number( pos.x ) || !is.number( pos.y ) ){ + return; // can't draw node with undefined position + } + + var usePaths = this.usePaths(); + var path; + var pathCacheHit = false; + + var parentOpacity = node.effectiveOpacity(); + if( parentOpacity === 0 ){ return; } + + nodeWidth = node.width() + node.pstyle( 'padding-left' ).pfValue + node.pstyle( 'padding-right' ).pfValue; + nodeHeight = node.height() + node.pstyle( 'padding-top' ).pfValue + node.pstyle( 'padding-bottom' ).pfValue; + + context.lineWidth = node.pstyle( 'border-width' ).pfValue; + + // + // setup shift + + var bb; + if( shiftToOriginWithBb ){ + bb = shiftToOriginWithBb; + + context.translate( -bb.x1, -bb.y1 ); + } + + // + // load bg image + + var bgImgProp = node.pstyle( 'background-image' ); + var url = bgImgProp.value[2] || bgImgProp.value[1]; + var image; + + if( url !== undefined ){ + + // get image, and if not loaded then ask to redraw when later loaded + image = this.getCachedImage( url, function(){ + node.trigger('background'); + + r.redrawHint( 'eles', true ); + r.redrawHint( 'drag', true ); + + r.drawingImage = true; + + r.redraw(); + } ); + + var prevBging = _p.backgrounding; + _p.backgrounding = !image.complete; + + if( prevBging !== _p.backgrounding ){ // update style b/c :backgrounding state changed + node.updateStyle( false ); + } + } + + // + // setup styles + + var bgColor = node.pstyle( 'background-color' ).value; + var borderColor = node.pstyle( 'border-color' ).value; + var borderStyle = node.pstyle( 'border-style' ).value; + + this.fillStyle( context, bgColor[0], bgColor[1], bgColor[2], node.pstyle( 'background-opacity' ).value * parentOpacity ); + + this.strokeStyle( context, borderColor[0], borderColor[1], borderColor[2], node.pstyle( 'border-opacity' ).value * parentOpacity ); + + var shadowBlur = node.pstyle( 'shadow-blur' ).pfValue; + var shadowOpacity = node.pstyle( 'shadow-opacity' ).value; + var shadowColor = node.pstyle( 'shadow-color' ).value; + var shadowOffsetX = node.pstyle( 'shadow-offset-x' ).pfValue; + var shadowOffsetY = node.pstyle( 'shadow-offset-y' ).pfValue; + + this.shadowStyle( context, shadowColor, shadowOpacity, shadowBlur, shadowOffsetX, shadowOffsetY ); + + context.lineJoin = 'miter'; // so borders are square with the node shape + + if( context.setLineDash ){ // for very outofdate browsers + switch( borderStyle ){ + case 'dotted': + context.setLineDash( [ 1, 1 ] ); + break; + + case 'dashed': + context.setLineDash( [ 4, 2 ] ); + break; + + case 'solid': + case 'double': + context.setLineDash( [ ] ); + break; + } + } + + + // + // draw shape + + var styleShape = node.pstyle('shape').strValue; + var shapePts = node.pstyle('shape-polygon-points').pfValue; + + if( usePaths ){ + var pathCacheKey = styleShape + '$' + nodeWidth + '$' + nodeHeight + ( styleShape === 'polygon' ? '$' + shapePts.join('$') : '' ); + + context.translate( pos.x, pos.y ); + + if( rs.pathCacheKey === pathCacheKey ){ + path = rs.pathCache; + pathCacheHit = true; + } else { + path = new Path2D(); // eslint-disable-line no-undef + rs.pathCacheKey = pathCacheKey; + rs.pathCache = path; + } + } + + if( !pathCacheHit ){ + + var npos = pos; + + if( usePaths ){ + npos = { + x: 0, + y: 0 + }; + } + + r.nodeShapes[ this.getNodeShape( node ) ].draw( + ( path || context ), + npos.x, + npos.y, + nodeWidth, + nodeHeight ); + } + + if( usePaths ){ + context.fill( path ); + } else { + context.fill(); + } + + this.shadowStyle( context, 'transparent', 0 ); // reset for next guy + + // + // bg image + + if( url !== undefined ){ + if( image.complete ){ + this.drawInscribedImage( context, image, node ); + } + } + + // + // pie + + var darkness = node.pstyle( 'background-blacken' ).value; + var borderWidth = node.pstyle( 'border-width' ).pfValue; + + if( this.hasPie( node ) ){ + this.drawPie( context, node, parentOpacity ); + + // redraw path for blacken and border + if( darkness !== 0 || borderWidth !== 0 ){ + + if( !usePaths ){ + r.nodeShapes[ this.getNodeShape( node ) ].draw( + context, + pos.x, + pos.y, + nodeWidth, + nodeHeight ); + } + } + } + + // + // darken/lighten + + if( darkness > 0 ){ + this.fillStyle( context, 0, 0, 0, darkness ); + + if( usePaths ){ + context.fill( path ); + } else { + context.fill(); + } + + } else if( darkness < 0 ){ + this.fillStyle( context, 255, 255, 255, -darkness ); + + if( usePaths ){ + context.fill( path ); + } else { + context.fill(); + } + } + + // + // border + + if( borderWidth > 0 ){ + + if( usePaths ){ + context.stroke( path ); + } else { + context.stroke(); + } + + if( borderStyle === 'double' ){ + context.lineWidth = node.pstyle( 'border-width' ).pfValue / 3; + + var gco = context.globalCompositeOperation; + context.globalCompositeOperation = 'destination-out'; + + if( usePaths ){ + context.stroke( path ); + } else { + context.stroke(); + } + + context.globalCompositeOperation = gco; + } + + } + + if( usePaths ){ + context.translate( -pos.x, -pos.y ); + } + + // reset in case we changed the border style + if( context.setLineDash ){ // for very outofdate browsers + context.setLineDash( [ ] ); + } + + // + // label + + r.drawElementText( context, node, drawLabel ); + + // + // overlay + + var overlayPadding = node.pstyle( 'overlay-padding' ).pfValue; + var overlayOpacity = node.pstyle( 'overlay-opacity' ).value; + var overlayColor = node.pstyle( 'overlay-color' ).value; + + if( overlayOpacity > 0 ){ + this.fillStyle( context, overlayColor[0], overlayColor[1], overlayColor[2], overlayOpacity ); + + r.nodeShapes[ 'roundrectangle' ].draw( + context, + node._private.position.x, + node._private.position.y, + nodeWidth + overlayPadding * 2, + nodeHeight + overlayPadding * 2 + ); + + context.fill(); + } + + // + // clean up shift + + if( shiftToOriginWithBb ){ + context.translate( bb.x1, bb.y1 ); + } + +}; + +// does the node have at least one pie piece? +CRp.hasPie = function( node ){ + node = node[0]; // ensure ele ref + + return node._private.hasPie; +}; + +CRp.drawPie = function( context, node, nodeOpacity, pos ){ + node = node[0]; // ensure ele ref + + var _p = node._private; + var cyStyle = node.cy().style(); + var pieSize = node.pstyle( 'pie-size' ); + var nodeW = node.width(); + var nodeH = node.height(); + var pos = pos || _p.position; + var x = pos.x; + var y = pos.y; + var radius = Math.min( nodeW, nodeH ) / 2; // must fit in node + var lastPercent = 0; // what % to continue drawing pie slices from on [0, 1] + var usePaths = this.usePaths(); + + if( usePaths ){ + x = 0; + y = 0; + } + + if( pieSize.units === '%' ){ + radius = radius * pieSize.value / 100; + } else if( pieSize.pfValue !== undefined ){ + radius = pieSize.pfValue / 2; + } + + for( var i = 1; i <= cyStyle.pieBackgroundN; i++ ){ // 1..N + var size = node.pstyle( 'pie-' + i + '-background-size' ).value; + var color = node.pstyle( 'pie-' + i + '-background-color' ).value; + var opacity = node.pstyle( 'pie-' + i + '-background-opacity' ).value * nodeOpacity; + var percent = size / 100; // map integer range [0, 100] to [0, 1] + + // percent can't push beyond 1 + if( percent + lastPercent > 1 ){ + percent = 1 - lastPercent; + } + + var angleStart = 1.5 * Math.PI + 2 * Math.PI * lastPercent; // start at 12 o'clock and go clockwise + var angleDelta = 2 * Math.PI * percent; + var angleEnd = angleStart + angleDelta; + + // ignore if + // - zero size + // - we're already beyond the full circle + // - adding the current slice would go beyond the full circle + if( size === 0 || lastPercent >= 1 || lastPercent + percent > 1 ){ + continue; + } + + context.beginPath(); + context.moveTo( x, y ); + context.arc( x, y, radius, angleStart, angleEnd ); + context.closePath(); + + this.fillStyle( context, color[0], color[1], color[2], opacity ); + + context.fill(); + + lastPercent += percent; + } + +}; + + +module.exports = CRp; + +},{"../../../is":83}],70:[function(_dereq_,module,exports){ +'use strict'; + +var CRp = {}; + +var util = _dereq_( '../../../util' ); + +var motionBlurDelay = 100; + +// var isFirefox = typeof InstallTrigger !== 'undefined'; + +CRp.getPixelRatio = function(){ + var context = this.data.contexts[0]; + + if( this.forcedPixelRatio != null ){ + return this.forcedPixelRatio; + } + + var backingStore = context.backingStorePixelRatio || + context.webkitBackingStorePixelRatio || + context.mozBackingStorePixelRatio || + context.msBackingStorePixelRatio || + context.oBackingStorePixelRatio || + context.backingStorePixelRatio || 1; + + return (window.devicePixelRatio || 1) / backingStore; // eslint-disable-line no-undef +}; + +CRp.paintCache = function( context ){ + var caches = this.paintCaches = this.paintCaches || []; + var needToCreateCache = true; + var cache; + + for( var i = 0; i < caches.length; i++ ){ + cache = caches[ i ]; + + if( cache.context === context ){ + needToCreateCache = false; + break; + } + } + + if( needToCreateCache ){ + cache = { + context: context + }; + caches.push( cache ); + } + + return cache; +}; + +CRp.fillStyle = function( context, r, g, b, a ){ + context.fillStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')'; + + // turn off for now, seems context does its own caching + + // var cache = this.paintCache(context); + + // var fillStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')'; + + // if( cache.fillStyle !== fillStyle ){ + // context.fillStyle = cache.fillStyle = fillStyle; + // } +}; + +CRp.strokeStyle = function( context, r, g, b, a ){ + context.strokeStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')'; + + // turn off for now, seems context does its own caching + + // var cache = this.paintCache(context); + + // var strokeStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')'; + + // if( cache.strokeStyle !== strokeStyle ){ + // context.strokeStyle = cache.strokeStyle = strokeStyle; + // } +}; + +CRp.shadowStyle = function( context, color, opacity, blur, offsetX, offsetY ){ + var zoom = this.cy.zoom(); + + // var cache = this.paintCache( context ); + // + // // don't make expensive changes to the shadow style if it's not used + // if( cache.shadowOpacity === 0 && opacity === 0 ){ + // return; + // } + // + // cache.shadowOpacity = opacity; + + if( opacity > 0 ){ + context.shadowBlur = blur * zoom; + context.shadowColor = 'rgba(' + color[0] + ',' + color[1] + ',' + color[2] + ',' + opacity + ')'; + context.shadowOffsetX = offsetX * zoom; + context.shadowOffsetY = offsetY * zoom; + } else { + context.shadowBlur = 0; + context.shadowColor = 'transparent'; + context.shadowOffsetX = 0; + context.shadowOffsetY = 0; + } +}; + +// Resize canvas +CRp.matchCanvasSize = function( container ){ + var r = this; + var data = r.data; + var width = container.clientWidth; + var height = container.clientHeight; + var pixelRatio = r.getPixelRatio(); + var mbPxRatio = r.motionBlurPxRatio; + + if( + container === r.data.bufferCanvases[ r.MOTIONBLUR_BUFFER_NODE ] || + container === r.data.bufferCanvases[ r.MOTIONBLUR_BUFFER_DRAG ] + ){ + pixelRatio = mbPxRatio; + } + + var canvasWidth = width * pixelRatio; + var canvasHeight = height * pixelRatio; + var canvas; + + if( canvasWidth === r.canvasWidth && canvasHeight === r.canvasHeight ){ + return; // save cycles if same + } + + r.fontCaches = null; // resizing resets the style + + var canvasContainer = data.canvasContainer; + canvasContainer.style.width = width + 'px'; + canvasContainer.style.height = height + 'px'; + + for( var i = 0; i < r.CANVAS_LAYERS; i++ ){ + + canvas = data.canvases[ i ]; + + if( canvas.width !== canvasWidth || canvas.height !== canvasHeight ){ + + canvas.width = canvasWidth; + canvas.height = canvasHeight; + + canvas.style.width = width + 'px'; + canvas.style.height = height + 'px'; + } + } + + for( var i = 0; i < r.BUFFER_COUNT; i++ ){ + + canvas = data.bufferCanvases[ i ]; + + if( canvas.width !== canvasWidth || canvas.height !== canvasHeight ){ + + canvas.width = canvasWidth; + canvas.height = canvasHeight; + + canvas.style.width = width + 'px'; + canvas.style.height = height + 'px'; + } + } + + r.textureMult = 1; + if( pixelRatio <= 1 ){ + canvas = data.bufferCanvases[ r.TEXTURE_BUFFER ]; + + r.textureMult = 2; + canvas.width = canvasWidth * r.textureMult; + canvas.height = canvasHeight * r.textureMult; + } + + r.canvasWidth = canvasWidth; + r.canvasHeight = canvasHeight; + +}; + +CRp.renderTo = function( cxt, zoom, pan, pxRatio ){ + this.render( { + forcedContext: cxt, + forcedZoom: zoom, + forcedPan: pan, + drawAllLayers: true, + forcedPxRatio: pxRatio + } ); +}; + +CRp.render = function( options ){ + options = options || util.staticEmptyObject(); + + var forcedContext = options.forcedContext; + var drawAllLayers = options.drawAllLayers; + var drawOnlyNodeLayer = options.drawOnlyNodeLayer; + var forcedZoom = options.forcedZoom; + var forcedPan = options.forcedPan; + var r = this; + var pixelRatio = options.forcedPxRatio === undefined ? this.getPixelRatio() : options.forcedPxRatio; + var cy = r.cy; var data = r.data; + var needDraw = data.canvasNeedsRedraw; + var textureDraw = r.textureOnViewport && !forcedContext && (r.pinching || r.hoverData.dragging || r.swipePanning || r.data.wheelZooming); + var motionBlur = options.motionBlur !== undefined ? options.motionBlur : r.motionBlur; + var mbPxRatio = r.motionBlurPxRatio; + var hasCompoundNodes = cy.hasCompoundNodes(); + var inNodeDragGesture = r.hoverData.draggingEles; + var inBoxSelection = r.hoverData.selecting || r.touchData.selecting ? true : false; + motionBlur = motionBlur && !forcedContext && r.motionBlurEnabled && !inBoxSelection; + var motionBlurFadeEffect = motionBlur; + + if( !forcedContext ){ + if( r.prevPxRatio !== pixelRatio ){ + r.invalidateContainerClientCoordsCache(); + r.matchCanvasSize( r.container ); + + r.redrawHint('eles', true); + r.redrawHint('drag', true); + } + + r.prevPxRatio = pixelRatio; + } + + if( !forcedContext && r.motionBlurTimeout ){ + clearTimeout( r.motionBlurTimeout ); + } + + if( motionBlur ){ + if( r.mbFrames == null ){ + r.mbFrames = 0; + } + + if( !r.drawingImage ){ // image loading frames don't count towards motion blur blurry frames + r.mbFrames++; + } + + if( r.mbFrames < 3 ){ // need several frames before even high quality motionblur + motionBlurFadeEffect = false; + } + + // go to lower quality blurry frames when several m/b frames have been rendered (avoids flashing) + if( r.mbFrames > r.minMbLowQualFrames ){ + //r.fullQualityMb = false; + r.motionBlurPxRatio = r.mbPxRBlurry; + } + } + + if( r.clearingMotionBlur ){ + r.motionBlurPxRatio = 1; + } + + // b/c drawToContext() may be async w.r.t. redraw(), keep track of last texture frame + // because a rogue async texture frame would clear needDraw + if( r.textureDrawLastFrame && !textureDraw ){ + needDraw[ r.NODE ] = true; + needDraw[ r.SELECT_BOX ] = true; + } + + var coreStyle = cy.style()._private.coreStyle; + + var zoom = cy.zoom(); + var effectiveZoom = forcedZoom !== undefined ? forcedZoom : zoom; + var pan = cy.pan(); + var effectivePan = { + x: pan.x, + y: pan.y + }; + + var vp = { + zoom: zoom, + pan: { + x: pan.x, + y: pan.y + } + }; + var prevVp = r.prevViewport; + var viewportIsDiff = prevVp === undefined || vp.zoom !== prevVp.zoom || vp.pan.x !== prevVp.pan.x || vp.pan.y !== prevVp.pan.y; + + // we want the low quality motionblur only when the viewport is being manipulated etc (where it's not noticed) + if( !viewportIsDiff && !(inNodeDragGesture && !hasCompoundNodes) ){ + r.motionBlurPxRatio = 1; + } + + if( forcedPan ){ + effectivePan = forcedPan; + } + + // apply pixel ratio + + effectiveZoom *= pixelRatio; + effectivePan.x *= pixelRatio; + effectivePan.y *= pixelRatio; + + var eles = r.getCachedZSortedEles(); + + function mbclear( context, x, y, w, h ){ + var gco = context.globalCompositeOperation; + + context.globalCompositeOperation = 'destination-out'; + r.fillStyle( context, 255, 255, 255, r.motionBlurTransparency ); + context.fillRect( x, y, w, h ); + + context.globalCompositeOperation = gco; + } + + function setContextTransform( context, clear ){ + var ePan, eZoom, w, h; + + if( !r.clearingMotionBlur && (context === data.bufferContexts[ r.MOTIONBLUR_BUFFER_NODE ] || context === data.bufferContexts[ r.MOTIONBLUR_BUFFER_DRAG ]) ){ + ePan = { + x: pan.x * mbPxRatio, + y: pan.y * mbPxRatio + }; + + eZoom = zoom * mbPxRatio; + + w = r.canvasWidth * mbPxRatio; + h = r.canvasHeight * mbPxRatio; + } else { + ePan = effectivePan; + eZoom = effectiveZoom; + + w = r.canvasWidth; + h = r.canvasHeight; + } + + context.setTransform( 1, 0, 0, 1, 0, 0 ); + + if( clear === 'motionBlur' ){ + mbclear( context, 0, 0, w, h ); + } else if( !forcedContext && (clear === undefined || clear) ){ + context.clearRect( 0, 0, w, h ); + } + + if( !drawAllLayers ){ + context.translate( ePan.x, ePan.y ); + context.scale( eZoom, eZoom ); + } + if( forcedPan ){ + context.translate( forcedPan.x, forcedPan.y ); + } + if( forcedZoom ){ + context.scale( forcedZoom, forcedZoom ); + } + } + + if( !textureDraw ){ + r.textureDrawLastFrame = false; + } + + if( textureDraw ){ + r.textureDrawLastFrame = true; + + var bb; + + if( !r.textureCache ){ + r.textureCache = {}; + + bb = r.textureCache.bb = cy.mutableElements().boundingBox(); + + r.textureCache.texture = r.data.bufferCanvases[ r.TEXTURE_BUFFER ]; + + var cxt = r.data.bufferContexts[ r.TEXTURE_BUFFER ]; + + cxt.setTransform( 1, 0, 0, 1, 0, 0 ); + cxt.clearRect( 0, 0, r.canvasWidth * r.textureMult, r.canvasHeight * r.textureMult ); + + r.render( { + forcedContext: cxt, + drawOnlyNodeLayer: true, + forcedPxRatio: pixelRatio * r.textureMult + } ); + + var vp = r.textureCache.viewport = { + zoom: cy.zoom(), + pan: cy.pan(), + width: r.canvasWidth, + height: r.canvasHeight + }; + + vp.mpan = { + x: (0 - vp.pan.x) / vp.zoom, + y: (0 - vp.pan.y) / vp.zoom + }; + } + + needDraw[ r.DRAG ] = false; + needDraw[ r.NODE ] = false; + + var context = data.contexts[ r.NODE ]; + + var texture = r.textureCache.texture; + var vp = r.textureCache.viewport; + bb = r.textureCache.bb; + + context.setTransform( 1, 0, 0, 1, 0, 0 ); + + if( motionBlur ){ + mbclear( context, 0, 0, vp.width, vp.height ); + } else { + context.clearRect( 0, 0, vp.width, vp.height ); + } + + var outsideBgColor = coreStyle[ 'outside-texture-bg-color' ].value; + var outsideBgOpacity = coreStyle[ 'outside-texture-bg-opacity' ].value; + r.fillStyle( context, outsideBgColor[0], outsideBgColor[1], outsideBgColor[2], outsideBgOpacity ); + context.fillRect( 0, 0, vp.width, vp.height ); + + var zoom = cy.zoom(); + + setContextTransform( context, false ); + + context.clearRect( vp.mpan.x, vp.mpan.y, vp.width / vp.zoom / pixelRatio, vp.height / vp.zoom / pixelRatio ); + context.drawImage( texture, vp.mpan.x, vp.mpan.y, vp.width / vp.zoom / pixelRatio, vp.height / vp.zoom / pixelRatio ); + + } else if( r.textureOnViewport && !forcedContext ){ // clear the cache since we don't need it + r.textureCache = null; + } + + var extent = cy.extent(); + var vpManip = (r.pinching || r.hoverData.dragging || r.swipePanning || r.data.wheelZooming || r.hoverData.draggingEles); + var hideEdges = r.hideEdgesOnViewport && vpManip; + + var needMbClear = []; + + needMbClear[ r.NODE ] = !needDraw[ r.NODE ] && motionBlur && !r.clearedForMotionBlur[ r.NODE ] || r.clearingMotionBlur; + if( needMbClear[ r.NODE ] ){ r.clearedForMotionBlur[ r.NODE ] = true; } + + needMbClear[ r.DRAG ] = !needDraw[ r.DRAG ] && motionBlur && !r.clearedForMotionBlur[ r.DRAG ] || r.clearingMotionBlur; + if( needMbClear[ r.DRAG ] ){ r.clearedForMotionBlur[ r.DRAG ] = true; } + + if( needDraw[ r.NODE ] || drawAllLayers || drawOnlyNodeLayer || needMbClear[ r.NODE ] ){ + var useBuffer = motionBlur && !needMbClear[ r.NODE ] && mbPxRatio !== 1; + var context = forcedContext || ( useBuffer ? r.data.bufferContexts[ r.MOTIONBLUR_BUFFER_NODE ] : data.contexts[ r.NODE ] ); + var clear = motionBlur && !useBuffer ? 'motionBlur' : undefined; + + setContextTransform( context, clear ); + + if( hideEdges ){ + r.drawCachedNodes( context, eles.nondrag, pixelRatio, extent ); + } else { + r.drawLayeredElements( context, eles.nondrag, pixelRatio, extent ); + } + + if( !drawAllLayers && !motionBlur ){ + needDraw[ r.NODE ] = false; + } + } + + if( !drawOnlyNodeLayer && (needDraw[ r.DRAG ] || drawAllLayers || needMbClear[ r.DRAG ]) ){ + var useBuffer = motionBlur && !needMbClear[ r.DRAG ] && mbPxRatio !== 1; + var context = forcedContext || ( useBuffer ? r.data.bufferContexts[ r.MOTIONBLUR_BUFFER_DRAG ] : data.contexts[ r.DRAG ] ); + + setContextTransform( context, motionBlur && !useBuffer ? 'motionBlur' : undefined ); + + if( hideEdges ){ + r.drawCachedNodes( context, eles.drag, pixelRatio, extent ); + } else { + r.drawCachedElements( context, eles.drag, pixelRatio, extent ); + } + + if( !drawAllLayers && !motionBlur ){ + needDraw[ r.DRAG ] = false; + } + } + + if( r.showFps || (!drawOnlyNodeLayer && (needDraw[ r.SELECT_BOX ] && !drawAllLayers)) ){ + var context = forcedContext || data.contexts[ r.SELECT_BOX ]; + + setContextTransform( context ); + + if( r.selection[4] == 1 && ( r.hoverData.selecting || r.touchData.selecting ) ){ + var zoom = r.cy.zoom(); + var borderWidth = coreStyle[ 'selection-box-border-width' ].value / zoom; + + context.lineWidth = borderWidth; + context.fillStyle = 'rgba(' + + coreStyle[ 'selection-box-color' ].value[0] + ',' + + coreStyle[ 'selection-box-color' ].value[1] + ',' + + coreStyle[ 'selection-box-color' ].value[2] + ',' + + coreStyle[ 'selection-box-opacity' ].value + ')'; + + context.fillRect( + r.selection[0], + r.selection[1], + r.selection[2] - r.selection[0], + r.selection[3] - r.selection[1] ); + + if( borderWidth > 0 ){ + context.strokeStyle = 'rgba(' + + coreStyle[ 'selection-box-border-color' ].value[0] + ',' + + coreStyle[ 'selection-box-border-color' ].value[1] + ',' + + coreStyle[ 'selection-box-border-color' ].value[2] + ',' + + coreStyle[ 'selection-box-opacity' ].value + ')'; + + context.strokeRect( + r.selection[0], + r.selection[1], + r.selection[2] - r.selection[0], + r.selection[3] - r.selection[1] ); + } + } + + if( data.bgActivePosistion && !r.hoverData.selecting ){ + var zoom = r.cy.zoom(); + var pos = data.bgActivePosistion; + + context.fillStyle = 'rgba(' + + coreStyle[ 'active-bg-color' ].value[0] + ',' + + coreStyle[ 'active-bg-color' ].value[1] + ',' + + coreStyle[ 'active-bg-color' ].value[2] + ',' + + coreStyle[ 'active-bg-opacity' ].value + ')'; + + context.beginPath(); + context.arc( pos.x, pos.y, coreStyle[ 'active-bg-size' ].pfValue / zoom, 0, 2 * Math.PI ); + context.fill(); + } + + var timeToRender = r.lastRedrawTime; + if( r.showFps && timeToRender ){ + timeToRender = Math.round( timeToRender ); + var fps = Math.round( 1000 / timeToRender ); + + context.setTransform( 1, 0, 0, 1, 0, 0 ); + + context.fillStyle = 'rgba(255, 0, 0, 0.75)'; + context.strokeStyle = 'rgba(255, 0, 0, 0.75)'; + context.lineWidth = 1; + context.fillText( '1 frame = ' + timeToRender + ' ms = ' + fps + ' fps', 0, 20 ); + + var maxFps = 60; + context.strokeRect( 0, 30, 250, 20 ); + context.fillRect( 0, 30, 250 * Math.min( fps / maxFps, 1 ), 20 ); + } + + if( !drawAllLayers ){ + needDraw[ r.SELECT_BOX ] = false; + } + } + + // motionblur: blit rendered blurry frames + if( motionBlur && mbPxRatio !== 1 ){ + var cxtNode = data.contexts[ r.NODE ]; + var txtNode = r.data.bufferCanvases[ r.MOTIONBLUR_BUFFER_NODE ]; + + var cxtDrag = data.contexts[ r.DRAG ]; + var txtDrag = r.data.bufferCanvases[ r.MOTIONBLUR_BUFFER_DRAG ]; + + var drawMotionBlur = function( cxt, txt, needClear ){ + cxt.setTransform( 1, 0, 0, 1, 0, 0 ); + + if( needClear || !motionBlurFadeEffect ){ + cxt.clearRect( 0, 0, r.canvasWidth, r.canvasHeight ); + } else { + mbclear( cxt, 0, 0, r.canvasWidth, r.canvasHeight ); + } + + var pxr = mbPxRatio; + + cxt.drawImage( + txt, // img + 0, 0, // sx, sy + r.canvasWidth * pxr, r.canvasHeight * pxr, // sw, sh + 0, 0, // x, y + r.canvasWidth, r.canvasHeight // w, h + ); + }; + + if( needDraw[ r.NODE ] || needMbClear[ r.NODE ] ){ + drawMotionBlur( cxtNode, txtNode, needMbClear[ r.NODE ] ); + needDraw[ r.NODE ] = false; + } + + if( needDraw[ r.DRAG ] || needMbClear[ r.DRAG ] ){ + drawMotionBlur( cxtDrag, txtDrag, needMbClear[ r.DRAG ] ); + needDraw[ r.DRAG ] = false; + } + } + + r.prevViewport = vp; + + if( r.clearingMotionBlur ){ + r.clearingMotionBlur = false; + r.motionBlurCleared = true; + r.motionBlur = true; + } + + if( motionBlur ){ + r.motionBlurTimeout = setTimeout( function(){ + r.motionBlurTimeout = null; + + r.clearedForMotionBlur[ r.NODE ] = false; + r.clearedForMotionBlur[ r.DRAG ] = false; + r.motionBlur = false; + r.clearingMotionBlur = !textureDraw; + r.mbFrames = 0; + + needDraw[ r.NODE ] = true; + needDraw[ r.DRAG ] = true; + + r.redraw(); + }, motionBlurDelay ); + } + + r.drawingImage = false; + + + if( !forcedContext && !r.initrender ){ + r.initrender = true; + cy.trigger( 'initrender' ); + } + + if( !forcedContext ){ + cy.trigger('render'); + } + +}; + +module.exports = CRp; + +},{"../../../util":100}],71:[function(_dereq_,module,exports){ +'use strict'; + +var math = _dereq_( '../../../math' ); + +var CRp = {}; + +// @O Polygon drawing +CRp.drawPolygonPath = function( + context, x, y, width, height, points ){ + + var halfW = width / 2; + var halfH = height / 2; + + if( context.beginPath ){ context.beginPath(); } + + context.moveTo( x + halfW * points[0], y + halfH * points[1] ); + + for( var i = 1; i < points.length / 2; i++ ){ + context.lineTo( x + halfW * points[ i * 2], y + halfH * points[ i * 2 + 1] ); + } + + context.closePath(); +}; + +// Round rectangle drawing +CRp.drawRoundRectanglePath = function( + context, x, y, width, height ){ + + var halfWidth = width / 2; + var halfHeight = height / 2; + var cornerRadius = math.getRoundRectangleRadius( width, height ); + + if( context.beginPath ){ context.beginPath(); } + + // Start at top middle + context.moveTo( x, y - halfHeight ); + // Arc from middle top to right side + context.arcTo( x + halfWidth, y - halfHeight, x + halfWidth, y, cornerRadius ); + // Arc from right side to bottom + context.arcTo( x + halfWidth, y + halfHeight, x, y + halfHeight, cornerRadius ); + // Arc from bottom to left side + context.arcTo( x - halfWidth, y + halfHeight, x - halfWidth, y, cornerRadius ); + // Arc from left side to topBorder + context.arcTo( x - halfWidth, y - halfHeight, x, y - halfHeight, cornerRadius ); + // Join line + context.lineTo( x, y - halfHeight ); + + + context.closePath(); +}; + +var sin0 = Math.sin( 0 ); +var cos0 = Math.cos( 0 ); + +var sin = {}; +var cos = {}; + +var ellipseStepSize = Math.PI / 40; + +for( var i = 0 * Math.PI; i < 2 * Math.PI; i += ellipseStepSize ){ + sin[ i ] = Math.sin( i ); + cos[ i ] = Math.cos( i ); +} + +CRp.drawEllipsePath = function( context, centerX, centerY, width, height ){ + if( context.beginPath ){ context.beginPath(); } + + if( context.ellipse ){ + context.ellipse( centerX, centerY, width / 2, height / 2, 0, 0, 2 * Math.PI ); + } else { + var xPos, yPos; + var rw = width / 2; + var rh = height / 2; + for( var i = 0 * Math.PI; i < 2 * Math.PI; i += ellipseStepSize ){ + xPos = centerX - (rw * sin[ i ]) * sin0 + (rw * cos[ i ]) * cos0; + yPos = centerY + (rh * cos[ i ]) * sin0 + (rh * sin[ i ]) * cos0; + + if( i === 0 ){ + context.moveTo( xPos, yPos ); + } else { + context.lineTo( xPos, yPos ); + } + } + } + + context.closePath(); + }; + +module.exports = CRp; + +},{"../../../math":85}],72:[function(_dereq_,module,exports){ +'use strict'; + +var math = _dereq_( '../../../math' ); +var util = _dereq_( '../../../util' ); +var Heap = _dereq_( '../../../heap' ); +var defs = _dereq_( './texture-cache-defs' ); + +var minTxrH = 25; // the size of the texture cache for small height eles (special case) +var txrStepH = 50; // the min size of the regular cache, and the size it increases with each step up +var minLvl = -4; // when scaling smaller than that we don't need to re-render +var maxLvl = 2; // when larger than this scale just render directly (caching is not helpful) +var maxZoom = 3.99; // beyond this zoom level, layered textures are not used +var eleTxrSpacing = 8; // spacing between elements on textures to avoid blitting overlaps +var defTxrWidth = 1024; // default/minimum texture width +var maxTxrW = 1024; // the maximum width of a texture +var maxTxrH = 1024; // the maximum height of a texture +var minUtility = 0.5; // if usage of texture is less than this, it is retired +var maxFullness = 0.8; // fullness of texture after which queue removal is checked +var maxFullnessChecks = 10; // dequeued after this many checks +var allowEdgeTxrCaching = false; // whether edges can be cached as textures (TODO maybe better on if webgl supported?) +var allowParentTxrCaching = false; // whether parent nodes can be cached as textures (TODO maybe better on if webgl supported?) +var deqCost = 0.15; // % of add'l rendering cost allowed for dequeuing ele caches each frame +var deqAvgCost = 0.1; // % of add'l rendering cost compared to average overall redraw time +var deqNoDrawCost = 0.9; // % of avg frame time that can be used for dequeueing when not drawing +var deqFastCost = 0.9; // % of frame time to be used when >60fps +var deqRedrawThreshold = 100; // time to batch redraws together from dequeueing to allow more dequeueing calcs to happen in the meanwhile +var maxDeqSize = 1; // number of eles to dequeue and render at higher texture in each batch + +var getTxrReasons = { + dequeue: 'dequeue', + downscale: 'downscale', + highQuality: 'highQuality' +}; + +var ElementTextureCache = function( renderer ){ + var self = this; + + self.renderer = renderer; + self.onDequeues = []; + + self.setupDequeueing(); +}; + +var ETCp = ElementTextureCache.prototype; + +ETCp.reasons = getTxrReasons; + +// the list of textures in which new subtextures for elements can be placed +ETCp.getTextureQueue = function( txrH ){ + var self = this; + self.eleImgCaches = self.eleImgCaches || {}; + + return ( self.eleImgCaches[ txrH ] = self.eleImgCaches[ txrH ] || [] ); +}; + +// the list of usused textures which can be recycled (in use in texture queue) +ETCp.getRetiredTextureQueue = function( txrH ){ + var self = this; + + var rtxtrQs = self.eleImgCaches.retired = self.eleImgCaches.retired || {}; + var rtxtrQ = rtxtrQs[ txrH ] = rtxtrQs[ txrH ] || []; + + return rtxtrQ; +}; + +// queue of element draw requests at different scale levels +ETCp.getElementQueue = function(){ + var self = this; + + var q = self.eleCacheQueue = self.eleCacheQueue || new Heap(function( a, b ){ + return b.reqs - a.reqs; + }); + + return q; +}; + +// queue of element draw requests at different scale levels (element id lookup) +ETCp.getElementIdToQueue = function(){ + var self = this; + + var id2q = self.eleIdToCacheQueue = self.eleIdToCacheQueue || {}; + + return id2q; +}; + +ETCp.getElement = function( ele, bb, pxRatio, lvl, reason ){ + var self = this; + var r = this.renderer; + var rs = ele._private.rscratch; + var zoom = r.cy.zoom(); + + if( lvl == null ){ + lvl = Math.ceil( math.log2( zoom * pxRatio ) ); + } + + if( lvl < minLvl ){ + lvl = minLvl; + } else if( zoom >= maxZoom || lvl > maxLvl ){ + return null; + } + + var scale = Math.pow( 2, lvl ); + var eleScaledH = bb.h * scale; + var eleScaledW = bb.w * scale; + var caches = rs.imgCaches = rs.imgCaches || {}; + var eleCache = caches[lvl]; + + if( eleCache ){ + return eleCache; + } + + var txrH; // which texture height this ele belongs to + + if( eleScaledH <= minTxrH ){ + txrH = minTxrH; + } else if( eleScaledH <= txrStepH ){ + txrH = txrStepH; + } else { + txrH = Math.ceil( eleScaledH / txrStepH ) * txrStepH; + } + + if( + eleScaledH > maxTxrH + || eleScaledW > maxTxrW + || ( !allowEdgeTxrCaching && ele.isEdge() ) + || ( !allowParentTxrCaching && ele.isParent() ) + ){ + return null; // caching large elements is not efficient + } + + var txrQ = self.getTextureQueue( txrH ); + + // first try the second last one in case it has space at the end + var txr = txrQ[ txrQ.length - 2 ]; + + var addNewTxr = function(){ + return self.recycleTexture( txrH, eleScaledW ) || self.addTexture( txrH, eleScaledW ); + }; + + // try the last one if there is no second last one + if( !txr ){ + txr = txrQ[ txrQ.length - 1 ]; + } + + // if the last one doesn't exist, we need a first one + if( !txr ){ + txr = addNewTxr(); + } + + // if there's no room in the current texture, we need a new one + if( txr.width - txr.usedWidth < eleScaledW ){ + txr = addNewTxr(); + } + + var scaledLabelShown = r.eleTextBiggerThanMin( ele, scale ); + var scalableFrom = function( otherCache ){ + return otherCache && otherCache.scaledLabelShown === scaledLabelShown; + }; + + var deqing = reason && reason === getTxrReasons.dequeue; + var highQualityReq = reason && reason === getTxrReasons.highQuality; + var downscaleReq = reason && reason === getTxrReasons.downscale; + + var higherCache; // the nearest cache with a higher level + for( var l = lvl + 1; l <= maxLvl; l++ ){ + var c = caches[l]; + + if( c ){ higherCache = c; break; } + } + + var oneUpCache = higherCache && higherCache.level === lvl + 1 ? higherCache : null; + + var downscale = function(){ + txr.context.drawImage( + oneUpCache.texture.canvas, + oneUpCache.x, 0, + oneUpCache.width, oneUpCache.height, + txr.usedWidth, 0, + eleScaledW, eleScaledH + ); + }; + + if( scalableFrom(oneUpCache) ){ + // then we can relatively cheaply rescale the existing image w/o rerendering + downscale(); + + } else if( scalableFrom(higherCache) ){ + // then use the higher cache for now and queue the next level down + // to cheaply scale towards the smaller level + + if( highQualityReq ){ + for( var l = higherCache.level; l > lvl; l-- ){ + oneUpCache = self.getElement( ele, bb, pxRatio, l, getTxrReasons.downscale ); + } + + downscale(); + + } else { + self.queueElement( ele, bb, higherCache.level - 1 ); + + return higherCache; + } + } else { + + var lowerCache; // the nearest cache with a lower level + if( !deqing && !highQualityReq && !downscaleReq ){ + for( var l = lvl - 1; l >= minLvl; l-- ){ + var c = caches[l]; + + if( c ){ lowerCache = c; break; } + } + } + + if( scalableFrom(lowerCache) ){ + // then use the lower quality cache for now and queue the better one for later + + self.queueElement( ele, bb, lvl ); + + return lowerCache; + } + + txr.context.translate( txr.usedWidth, 0 ); + txr.context.scale( scale, scale ); + + r.drawElement( txr.context, ele, bb, scaledLabelShown ); + + txr.context.scale( 1/scale, 1/scale ); + txr.context.translate( -txr.usedWidth, 0 ); + } + + eleCache = caches[lvl] = { + ele: ele, + x: txr.usedWidth, + texture: txr, + level: lvl, + scale: scale, + width: eleScaledW, + height: eleScaledH, + scaledLabelShown: scaledLabelShown + }; + + txr.usedWidth += Math.ceil( eleScaledW + eleTxrSpacing ); + + txr.eleCaches.push( eleCache ); + + self.checkTextureFullness( txr ); + + return eleCache; +}; + +ETCp.invalidateElement = function( ele ){ + var self = this; + var caches = ele._private.rscratch.imgCaches; + + if( caches ){ + for( var lvl = minLvl; lvl <= maxLvl; lvl++ ){ + var cache = caches[ lvl ]; + + if( cache ){ + var txr = cache.texture; + + // remove space from the texture it belongs to + txr.invalidatedWidth += cache.width; + + // remove refs with the element + caches[ lvl ] = null; + util.removeFromArray( txr.eleCaches, cache ); + + // might have to remove the entire texture if it's not efficiently using its space + self.checkTextureUtility( txr ); + } + } + } +}; + +ETCp.checkTextureUtility = function( txr ){ + // invalidate all entries in the cache if the cache size is small + if( txr.invalidatedWidth >= minUtility * txr.width ){ + this.retireTexture( txr ); + } +}; + +ETCp.checkTextureFullness = function( txr ){ + // if texture has been mostly filled and passed over several times, remove + // it from the queue so we don't need to waste time looking at it to put new things + + var self = this; + var txrQ = self.getTextureQueue( txr.height ); + + if( txr.usedWidth / txr.width > maxFullness && txr.fullnessChecks >= maxFullnessChecks ){ + util.removeFromArray( txrQ, txr ); + } else { + txr.fullnessChecks++; + } +}; + +ETCp.retireTexture = function( txr ){ + var self = this; + var txrH = txr.height; + var txrQ = self.getTextureQueue( txrH ); + + // retire the texture from the active / searchable queue: + + util.removeFromArray( txrQ, txr ); + + txr.retired = true; + + // remove the refs from the eles to the caches: + + var eleCaches = txr.eleCaches; + + for( var i = 0; i < eleCaches.length; i++ ){ + var eleCache = eleCaches[i]; + var ele = eleCache.ele; + var lvl = eleCache.level; + var imgCaches = ele._private.rscratch.imgCaches; + + if( imgCaches ){ + imgCaches[ lvl ] = null; + } + } + + util.clearArray( eleCaches ); + + // add the texture to a retired queue so it can be recycled in future: + + var rtxtrQ = self.getRetiredTextureQueue( txrH ); + + rtxtrQ.push( txr ); +}; + +ETCp.addTexture = function( txrH, minW ){ + var self = this; + var txrQ = self.getTextureQueue( txrH ); + var txr = {}; + + txrQ.push( txr ); + + txr.eleCaches = []; + + txr.height = txrH; + txr.width = Math.max( defTxrWidth, minW ); + txr.usedWidth = 0; + txr.invalidatedWidth = 0; + txr.fullnessChecks = 0; + + txr.canvas = document.createElement('canvas'); // eslint-disable-line no-undef + txr.canvas.width = txr.width; + txr.canvas.height = txr.height; + + txr.context = txr.canvas.getContext('2d'); + + return txr; +}; + +ETCp.recycleTexture = function( txrH, minW ){ + var self = this; + var txrQ = self.getTextureQueue( txrH ); + var rtxtrQ = self.getRetiredTextureQueue( txrH ); + + for( var i = 0; i < rtxtrQ.length; i++ ){ + var txr = rtxtrQ[i]; + + if( txr.width >= minW ){ + txr.retired = false; + + txr.usedWidth = 0; + txr.invalidatedWidth = 0; + txr.fullnessChecks = 0; + + util.clearArray( txr.eleCaches ); + + txr.context.clearRect( 0, 0, txr.width, txr.height ); + + util.removeFromArray( rtxtrQ, txr ); + txrQ.push( txr ); + + return txr; + } + } +}; + +ETCp.queueElement = function( ele, bb, lvl ){ + var self = this; + var q = self.getElementQueue(); + var id2q = self.getElementIdToQueue(); + var id = ele.id(); + var existingReq = id2q[ id ]; + + if( existingReq ){ // use the max lvl b/c in between lvls are cheap to make + existingReq.level = Math.max( existingReq.level, lvl ); + existingReq.reqs++; + + q.updateItem( existingReq ); + } else { + var req = { + ele: ele, + bb: bb, + position: math.copyPosition( ele.position() ), + level: lvl, + reqs: 1 + }; + + if( ele.isEdge() ){ + req.positions = { + source: math.copyPosition( ele.source().position() ), + target: math.copyPosition( ele.target().position() ) + }; + } + + q.push( req ); + + id2q[ id ] = req; + } +}; + +ETCp.dequeue = function( pxRatio, extent ){ + var self = this; + var q = self.getElementQueue(); + var id2q = self.getElementIdToQueue(); + var dequeued = []; + + for( var i = 0; i < maxDeqSize; i++ ){ + if( q.size() > 0 ){ + var req = q.pop(); + + id2q[ req.ele.id() ] = null; + + dequeued.push( req ); + + var ele = req.ele; + var bb; + + if( + ( ele.isEdge() + && ( + !math.arePositionsSame( ele.source().position(), req.positions.source ) + || !math.arePositionsSame( ele.target().position(), req.positions.target ) + ) + ) + || ( !math.arePositionsSame( ele.position(), req.position ) ) + ){ + bb = ele.boundingBox(); + } else { + bb = req.bb; + } + + self.getElement( req.ele, bb, pxRatio, req.level, getTxrReasons.dequeue ); + } else { + break; + } + } + + return dequeued; +}; + +ETCp.onDequeue = function( fn ){ this.onDequeues.push( fn ); }; +ETCp.offDequeue = function( fn ){ util.removeFromArray( this.onDequeues, fn ); }; + +ETCp.setupDequeueing = defs.setupDequeueing({ + deqRedrawThreshold: deqRedrawThreshold, + deqCost: deqCost, + deqAvgCost: deqAvgCost, + deqNoDrawCost: deqNoDrawCost, + deqFastCost: deqFastCost, + deq: function( self, pxRatio, extent ){ + return self.dequeue( pxRatio, extent ); + }, + onDeqd: function( self, deqd ){ + for( var i = 0; i < self.onDequeues.length; i++ ){ + var fn = self.onDequeues[i]; + + fn( deqd ); + } + }, + shouldRedraw: function( self, deqd, pxRatio, extent ){ + for( var i = 0; i < deqd.length; i++ ){ + var bb = deqd[i].bb; + + if( math.boundingBoxesIntersect( bb, extent ) ){ + return true; + } + } + + return false; + }, + priority: function( self ){ + return self.renderer.beforeRenderPriorities.eleTxrDeq; + } +}); + +module.exports = ElementTextureCache; + +},{"../../../heap":81,"../../../math":85,"../../../util":100,"./texture-cache-defs":77}],73:[function(_dereq_,module,exports){ +'use strict'; + +var is = _dereq_( '../../../is' ); + +var CRp = {}; + +CRp.createBuffer = function( w, h ){ + var buffer = document.createElement( 'canvas' ); // eslint-disable-line no-undef + buffer.width = w; + buffer.height = h; + + return [ buffer, buffer.getContext( '2d' ) ]; +}; + +CRp.bufferCanvasImage = function( options ){ + var cy = this.cy; + var eles = cy.mutableElements(); + var bb = eles.boundingBox(); + var width = options.full ? Math.ceil( bb.w ) : this.container.clientWidth; + var height = options.full ? Math.ceil( bb.h ) : this.container.clientHeight; + var specdMaxDims = is.number( options.maxWidth ) || is.number( options.maxHeight ); + var pxRatio = this.getPixelRatio(); + var scale = 1; + + if( options.scale !== undefined ){ + width *= options.scale; + height *= options.scale; + + scale = options.scale; + } else if( specdMaxDims ){ + var maxScaleW = Infinity; + var maxScaleH = Infinity; + + if( is.number( options.maxWidth ) ){ + maxScaleW = scale * options.maxWidth / width; + } + + if( is.number( options.maxHeight ) ){ + maxScaleH = scale * options.maxHeight / height; + } + + scale = Math.min( maxScaleW, maxScaleH ); + + width *= scale; + height *= scale; + } + + if( !specdMaxDims ){ + width *= pxRatio; + height *= pxRatio; + scale *= pxRatio; + } + + var buffCanvas = document.createElement( 'canvas' ); // eslint-disable-line no-undef + + buffCanvas.width = width; + buffCanvas.height = height; + + buffCanvas.style.width = width + 'px'; + buffCanvas.style.height = height + 'px'; + + var buffCxt = buffCanvas.getContext( '2d' ); + + // Rasterize the layers, but only if container has nonzero size + if( width > 0 && height > 0 ){ + + buffCxt.clearRect( 0, 0, width, height ); + + if( options.bg ){ + buffCxt.fillStyle = options.bg; + buffCxt.rect( 0, 0, width, height ); + buffCxt.fill(); + } + + buffCxt.globalCompositeOperation = 'source-over'; + + var zsortedEles = this.getCachedZSortedEles(); + + if( options.full ){ // draw the full bounds of the graph + buffCxt.translate( -bb.x1 * scale, -bb.y1 * scale ); + buffCxt.scale( scale, scale ); + + this.drawElements( buffCxt, zsortedEles ); + } else { // draw the current view + var pan = cy.pan(); + + var translation = { + x: pan.x * scale, + y: pan.y * scale + }; + + scale *= cy.zoom(); + + buffCxt.translate( translation.x, translation.y ); + buffCxt.scale( scale, scale ); + + this.drawElements( buffCxt, zsortedEles ); + } + } + + return buffCanvas; +}; + +CRp.png = function( options ){ + return this.bufferCanvasImage( options ).toDataURL( 'image/png' ); +}; + +CRp.jpg = function( options ){ + return this.bufferCanvasImage( options ).toDataURL( 'image/jpeg' ); +}; + +module.exports = CRp; + +},{"../../../is":83}],74:[function(_dereq_,module,exports){ +/* +The canvas renderer was written by Yue Dong. + +Modifications tracked on Github. +*/ + +'use strict'; + +var util = _dereq_( '../../../util' ); +var is = _dereq_( '../../../is' ); +var ElementTextureCache = _dereq_('./ele-texture-cache'); +var LayeredTextureCache = _dereq_('./layered-texture-cache'); + +var CR = CanvasRenderer; +var CRp = CanvasRenderer.prototype; + +CRp.CANVAS_LAYERS = 3; +// +CRp.SELECT_BOX = 0; +CRp.DRAG = 1; +CRp.NODE = 2; + +CRp.BUFFER_COUNT = 3; +// +CRp.TEXTURE_BUFFER = 0; +CRp.MOTIONBLUR_BUFFER_NODE = 1; +CRp.MOTIONBLUR_BUFFER_DRAG = 2; + +function CanvasRenderer( options ){ + var r = this; + + r.data = { + canvases: new Array( CRp.CANVAS_LAYERS ), + contexts: new Array( CRp.CANVAS_LAYERS ), + canvasNeedsRedraw: new Array( CRp.CANVAS_LAYERS ), + + bufferCanvases: new Array( CRp.BUFFER_COUNT ), + bufferContexts: new Array( CRp.CANVAS_LAYERS ), + }; + + r.data.canvasContainer = document.createElement( 'div' ); // eslint-disable-line no-undef + var containerStyle = r.data.canvasContainer.style; + r.data.canvasContainer.setAttribute( 'style', '-webkit-tap-highlight-color: rgba(0,0,0,0);' ); + containerStyle.position = 'relative'; + containerStyle.zIndex = '0'; + containerStyle.overflow = 'hidden'; + + var container = options.cy.container(); + container.appendChild( r.data.canvasContainer ); + container.setAttribute( 'style', ( container.getAttribute( 'style' ) || '' ) + '-webkit-tap-highlight-color: rgba(0,0,0,0);' ); + + for( var i = 0; i < CRp.CANVAS_LAYERS; i++ ){ + var canvas = r.data.canvases[ i ] = document.createElement( 'canvas' ); // eslint-disable-line no-undef + r.data.contexts[ i ] = canvas.getContext( '2d' ); + canvas.setAttribute( 'style', '-webkit-user-select: none; -moz-user-select: -moz-none; user-select: none; -webkit-tap-highlight-color: rgba(0,0,0,0); outline-style: none;' + ( is.ms() ? ' -ms-touch-action: none; touch-action: none; ' : '' ) ); + canvas.style.position = 'absolute'; + canvas.setAttribute( 'data-id', 'layer' + i ); + canvas.style.zIndex = String( CRp.CANVAS_LAYERS - i ); + r.data.canvasContainer.appendChild( canvas ); + + r.data.canvasNeedsRedraw[ i ] = false; + } + r.data.topCanvas = r.data.canvases[0]; + + r.data.canvases[ CRp.NODE ].setAttribute( 'data-id', 'layer' + CRp.NODE + '-node' ); + r.data.canvases[ CRp.SELECT_BOX ].setAttribute( 'data-id', 'layer' + CRp.SELECT_BOX + '-selectbox' ); + r.data.canvases[ CRp.DRAG ].setAttribute( 'data-id', 'layer' + CRp.DRAG + '-drag' ); + + for( var i = 0; i < CRp.BUFFER_COUNT; i++ ){ + r.data.bufferCanvases[ i ] = document.createElement( 'canvas' ); // eslint-disable-line no-undef + r.data.bufferContexts[ i ] = r.data.bufferCanvases[ i ].getContext( '2d' ); + r.data.bufferCanvases[ i ].style.position = 'absolute'; + r.data.bufferCanvases[ i ].setAttribute( 'data-id', 'buffer' + i ); + r.data.bufferCanvases[ i ].style.zIndex = String( -i - 1 ); + r.data.bufferCanvases[ i ].style.visibility = 'hidden'; + //r.data.canvasContainer.appendChild(r.data.bufferCanvases[i]); + } + + r.pathsEnabled = true; + + r.data.eleTxrCache = new ElementTextureCache( r ); + r.data.lyrTxrCache = new LayeredTextureCache( r, r.data.eleTxrCache ); + + r.onUpdateEleCalcs(function invalidateTextureCaches( willDraw, eles ){ + for( var i = 0; i < eles.length; i++ ){ + var ele = eles[i]; + var rs = ele._private.rstyle; + var de = rs.dirtyEvents; + + if( ele.isNode() && de && de.length === 1 && de['position'] ){ + // then keep cached ele texture + } else { + r.data.eleTxrCache.invalidateElement( ele ); + } + } + + if( eles.length > 0 ){ + r.data.lyrTxrCache.invalidateElements( eles ); + } + }); +} + +CRp.redrawHint = function( group, bool ){ + var r = this; + + switch( group ){ + case 'eles': + r.data.canvasNeedsRedraw[ CRp.NODE ] = bool; + break; + case 'drag': + r.data.canvasNeedsRedraw[ CRp.DRAG ] = bool; + break; + case 'select': + r.data.canvasNeedsRedraw[ CRp.SELECT_BOX ] = bool; + break; + } +}; + +// whether to use Path2D caching for drawing +var pathsImpld = typeof Path2D !== 'undefined'; + +CRp.path2dEnabled = function( on ){ + if( on === undefined ){ + return this.pathsEnabled; + } + + this.pathsEnabled = on ? true : false; +}; + +CRp.usePaths = function(){ + return pathsImpld && this.pathsEnabled; +}; + +[ + _dereq_( './arrow-shapes' ), + _dereq_( './drawing-elements' ), + _dereq_( './drawing-edges' ), + _dereq_( './drawing-images' ), + _dereq_( './drawing-label-text' ), + _dereq_( './drawing-nodes' ), + _dereq_( './drawing-redraw' ), + _dereq_( './drawing-shapes' ), + _dereq_( './export-image' ), + _dereq_( './node-shapes' ) +].forEach( function( props ){ + util.extend( CRp, props ); +} ); + +module.exports = CR; + +},{"../../../is":83,"../../../util":100,"./arrow-shapes":64,"./drawing-edges":65,"./drawing-elements":66,"./drawing-images":67,"./drawing-label-text":68,"./drawing-nodes":69,"./drawing-redraw":70,"./drawing-shapes":71,"./ele-texture-cache":72,"./export-image":73,"./layered-texture-cache":75,"./node-shapes":76}],75:[function(_dereq_,module,exports){ +'use strict'; + +var util = _dereq_( '../../../util' ); +var math = _dereq_( '../../../math' ); +var Heap = _dereq_( '../../../heap' ); +var is = _dereq_( '../../../is' ); +var defs = _dereq_( './texture-cache-defs' ); + +var defNumLayers = 1; // default number of layers to use +var minLvl = -4; // when scaling smaller than that we don't need to re-render +var maxLvl = 2; // when larger than this scale just render directly (caching is not helpful) +var maxZoom = 3.99; // beyond this zoom level, layered textures are not used +var deqRedrawThreshold = 50; // time to batch redraws together from dequeueing to allow more dequeueing calcs to happen in the meanwhile +var refineEleDebounceTime = 50; // time to debounce sharper ele texture updates +var disableEleImgSmoothing = true; // when drawing eles on layers from an ele cache ; crisper and more performant when true +var deqCost = 0.15; // % of add'l rendering cost allowed for dequeuing ele caches each frame +var deqAvgCost = 0.1; // % of add'l rendering cost compared to average overall redraw time +var deqNoDrawCost = 0.9; // % of avg frame time that can be used for dequeueing when not drawing +var deqFastCost = 0.9; // % of frame time to be used when >60fps +var maxDeqSize = 1; // number of eles to dequeue and render at higher texture in each batch +var invalidThreshold = 250; // time threshold for disabling b/c of invalidations +var maxLayerArea = 4000 * 4000; // layers can't be bigger than this +var alwaysQueue = true; // never draw all the layers in a level on a frame; draw directly until all dequeued +var useHighQualityEleTxrReqs = true; // whether to use high quality ele txr requests (generally faster and cheaper in the longterm) + +var useEleTxrCaching = true; // whether to use individual ele texture caching underneath this cache + +// var log = function(){ console.log.apply( console, arguments ); }; + +var LayeredTextureCache = function( renderer, eleTxrCache ){ + var self = this; + + var r = self.renderer = renderer; + + self.layersByLevel = {}; // e.g. 2 => [ layer1, layer2, ..., layerN ] + + self.firstGet = true; + + self.lastInvalidationTime = util.performanceNow() - 2*invalidThreshold; + + self.skipping = false; + + r.beforeRender(function( willDraw, now ){ + if( now - self.lastInvalidationTime <= invalidThreshold ){ + self.skipping = true; + } else { + self.skipping = false; + } + }); + + var qSort = function(a, b){ + return b.reqs - a.reqs; + }; + + self.layersQueue = new Heap( qSort ); + + self.eleTxrCache = eleTxrCache; + + self.setupEleCacheInvalidation(); + + self.setupDequeueing(); +}; + +var LTCp = LayeredTextureCache.prototype; + +var layerIdPool = 0; +var MAX_INT = Math.pow(2, 53) - 1; + +LTCp.makeLayer = function( bb, lvl ){ + var scale = Math.pow( 2, lvl ); + + var w = Math.ceil( bb.w * scale ); + var h = Math.ceil( bb.h * scale ); + + var canvas = document.createElement('canvas'); // eslint-disable-line no-undef + + canvas.width = w; + canvas.height = h; + + var layer = { + id: (layerIdPool = ++layerIdPool % MAX_INT ), + bb: bb, + level: lvl, + width: w, + height: h, + canvas: canvas, + context: canvas.getContext('2d'), + eles: [], + elesQueue: [], + reqs: 0 + }; + + // log('make layer %s with w %s and h %s and lvl %s', layer.id, layer.width, layer.height, layer.level); + + var cxt = layer.context; + var dx = -layer.bb.x1; + var dy = -layer.bb.y1; + + // do the transform on creation to save cycles (it's the same for all eles) + cxt.scale( scale, scale ); + cxt.translate( dx, dy ); + + return layer; +}; + +LTCp.getLayers = function( eles, pxRatio, lvl ){ + var self = this; + var r = self.renderer; + var cy = r.cy; + var zoom = cy.zoom(); + var firstGet = self.firstGet; + + self.firstGet = false; + + // log('--\nget layers with %s eles', eles.length); + //log eles.map(function(ele){ return ele.id() }) ); + + if( lvl == null ){ + lvl = Math.ceil( math.log2( zoom * pxRatio ) ); + + if( lvl < minLvl ){ + lvl = minLvl; + } else if( zoom >= maxZoom || lvl > maxLvl ){ + return null; + } + } + + self.validateLayersElesOrdering( lvl, eles ); + + var layersByLvl = self.layersByLevel; + var scale = Math.pow( 2, lvl ); + var layers = layersByLvl[ lvl ] = layersByLvl[ lvl ] || []; + var bb; + + var lvlComplete = self.levelIsComplete( lvl, eles ); + var tmpLayers; + + var checkTempLevels = function(){ + var canUseAsTmpLvl = function( l ){ + self.validateLayersElesOrdering( l, eles ); + + if( self.levelIsComplete( l, eles ) ){ + tmpLayers = layersByLvl[l]; + return true; + } + }; + + var checkLvls = function( dir ){ + if( tmpLayers ){ return; } + + for( var l = lvl + dir; minLvl <= l && l <= maxLvl; l += dir ){ + if( canUseAsTmpLvl(l) ){ break; } + } + }; + + checkLvls( +1 ); + checkLvls( -1 ); + + // remove the invalid layers; they will be replaced as needed later in this function + for( var i = layers.length - 1; i >= 0; i-- ){ + var layer = layers[i]; + + if( layer.invalid ){ + util.removeFromArray( layers, layer ); + } + } + }; + + if( !lvlComplete ){ + // if the current level is incomplete, then use the closest, best quality layerset temporarily + // and later queue the current layerset so we can get the proper quality level soon + + checkTempLevels(); + + } else { + // log('level complete, using existing layers\n--'); + return layers; + } + + var getBb = function(){ + if( !bb ){ + bb = math.makeBoundingBox(); + + for( var i = 0; i < eles.length; i++ ){ + math.updateBoundingBox( bb, eles[i].boundingBox() ); + } + } + + return bb; + }; + + var makeLayer = function( opts ){ + opts = opts || {}; + + var after = opts.after; + + getBb(); + + var area = ( bb.w * scale ) * ( bb.h * scale ); + + if( area > maxLayerArea ){ + return null; + } + + var layer = self.makeLayer( bb, lvl ); + + if( after != null ){ + var index = layers.indexOf( after ) + 1; + + layers.splice( index, 0, layer ); + } else if( opts.insert === undefined || opts.insert ){ + // no after specified => first layer made so put at start + layers.unshift( layer ); + } + + // if( tmpLayers ){ + //self.queueLayer( layer ); + // } + + return layer; + }; + + if( self.skipping && !firstGet ){ + // log('skip layers'); + return null; + } + + // log('do layers'); + + var layer = null; + var maxElesPerLayer = eles.length / defNumLayers; + var allowLazyQueueing = alwaysQueue && !firstGet; + + for( var i = 0; i < eles.length; i++ ){ + var ele = eles[i]; + var rs = ele._private.rscratch; + var caches = rs.imgLayerCaches = rs.imgLayerCaches || {}; + + // log('look at ele', ele.id()); + + var existingLayer = caches[ lvl ]; + + if( existingLayer ){ + // reuse layer for later eles + // log('reuse layer for', ele.id()); + layer = existingLayer; + continue; + } + + if( + !layer + || layer.eles.length >= maxElesPerLayer + || ( defNumLayers > 1 && !math.boundingBoxInBoundingBox( layer.bb, ele.boundingBox() ) ) + ){ + // log('make new layer for ele %s', ele.id()); + + layer = makeLayer({ insert: true, after: layer }); + + // if now layer can be built then we can't use layers at this level + if( !layer ){ return null; } + + // log('new layer with id %s', layer.id); + } + + if( tmpLayers || allowLazyQueueing ){ + // log('queue ele %s in layer %s', ele.id(), layer.id); + self.queueLayer( layer, ele ); + } else { + // log('draw ele %s in layer %s', ele.id(), layer.id); + self.drawEleInLayer( layer, ele, lvl, pxRatio ); + } + + layer.eles.push( ele ); + + caches[ lvl ] = layer; + } + + // log('--'); + + if( tmpLayers ){ // then we only queued the current layerset and can't draw it yet + return tmpLayers; + } + + if( allowLazyQueueing ){ + // log('lazy queue level', lvl); + return null; + } + + return layers; +}; + +// a layer may want to use an ele cache of a higher level to avoid blurriness +// so the layer level might not equal the ele level +LTCp.getEleLevelForLayerLevel = function( lvl, pxRatio ){ + return lvl; +}; + +function imgSmoothing( context, bool ){ + if( context.imageSmoothingEnabled != null ){ + context.imageSmoothingEnabled = bool; + } else { + context.webkitImageSmoothingEnabled = bool; + context.mozImageSmoothingEnabled = bool; + context.msImageSmoothingEnabled = bool; + } +} + +LTCp.drawEleInLayer = function( layer, ele, lvl, pxRatio ){ + var self = this; + var r = this.renderer; + var context = layer.context; + var bb = ele.boundingBox(); + var eleCache = self.eleTxrCache; + var reason = useHighQualityEleTxrReqs ? eleCache.reasons.highQuality : undefined; + + lvl = self.getEleLevelForLayerLevel( lvl, pxRatio ); + + var cache = useEleTxrCaching ? eleCache.getElement( ele, bb, null, lvl, reason ) : null; + + if( cache ){ + if( disableEleImgSmoothing ){ imgSmoothing( context, false ); } + + context.drawImage( cache.texture.canvas, cache.x, 0, cache.width, cache.height, bb.x1, bb.y1, bb.w, bb.h ); + + if( disableEleImgSmoothing ){ imgSmoothing( context, true ); } + } else { // if the element is not cacheable, then draw directly + r.drawElement( context, ele ); + } +}; + +LTCp.levelIsComplete = function( lvl, eles ){ + var self = this; + var layers = self.layersByLevel[ lvl ]; + + if( !layers || layers.length === 0 ){ return false; } + + var numElesInLayers = 0; + + for( var i = 0; i < layers.length; i++ ){ + var layer = layers[i]; + + // if there are any eles needed to be drawn yet, the level is not complete + if( layer.reqs > 0 ){ return false; } + + // if the layer is invalid, the level is not complete + if( layer.invalid ){ return false; } + + numElesInLayers += layer.eles.length; + } + + // we should have exactly the number of eles passed in to be complete + if( numElesInLayers !== eles.length ){ return false; } + + return true; +}; + +LTCp.validateLayersElesOrdering = function( lvl, eles ){ + var layers = this.layersByLevel[ lvl ]; + + if( !layers ){ return; } + + // if in a layer the eles are not in the same order, then the layer is invalid + // (i.e. there is an ele in between the eles in the layer) + + for( var i = 0; i < layers.length; i++ ){ + var layer = layers[i]; + var offset = -1; + + // find the offset + for( var j = 0; j < eles.length; j++ ){ + if( layer.eles[0] === eles[j] ){ + offset = j; + break; + } + } + + if( offset < 0 ){ + // then the layer has nonexistant elements and is invalid + this.invalidateLayer( layer ); + continue; + } + + // the eles in the layer must be in the same continuous order, else the layer is invalid + + var o = offset; + + for( var j = 0; j < layer.eles.length; j++ ){ + if( layer.eles[j] !== eles[o+j] ){ + // log('invalidate based on ordering', layer.id); + + this.invalidateLayer( layer ); + break; + } + } + } +}; + +LTCp.updateElementsInLayers = function( eles, update ){ + var self = this; + var isEles = is.element( eles[0] ); + + // collect udpated elements (cascaded from the layers) and update each + // layer itself along the way + for( var i = 0; i < eles.length; i++ ){ + var req = isEles ? null : eles[i]; + var ele = isEles ? eles[i] : eles[i].ele; + var rs = ele._private.rscratch; + var caches = rs.imgLayerCaches = rs.imgLayerCaches || {}; + + for( var l = minLvl; l <= maxLvl; l++ ){ + var layer = caches[l]; + + if( !layer ){ continue; } + + // if update is a request from the ele cache, then it affects only + // the matching level + if( req && self.getEleLevelForLayerLevel( layer.level ) !== req.level ){ + continue; + } + + update( layer, ele, req ); + } + } +}; + +LTCp.haveLayers = function(){ + var self = this; + var haveLayers = false; + + for( var l = minLvl; l <= maxLvl; l++ ){ + var layers = self.layersByLevel[l]; + + if( layers && layers.length > 0 ){ + haveLayers = true; + break; + } + } + + return haveLayers; +}; + +LTCp.invalidateElements = function( eles ){ + var self = this; + + self.lastInvalidationTime = util.performanceNow(); + + // log('update invalidate layer time from eles'); + + if( eles.length === 0 || !self.haveLayers() ){ return; } + + self.updateElementsInLayers( eles, function invalAssocLayers( layer, ele, req ){ + self.invalidateLayer( layer ); + } ); +}; + +LTCp.invalidateLayer = function( layer ){ + // log('update invalidate layer time'); + + this.lastInvalidationTime = util.performanceNow(); + + if( layer.invalid ){ return; } // save cycles + + var lvl = layer.level; + var eles = layer.eles; + var layers = this.layersByLevel[ lvl ]; + + // log('invalidate layer', layer.id ); + + util.removeFromArray( layers, layer ); + // layer.eles = []; + + layer.elesQueue = []; + + layer.invalid = true; + + if( layer.replacement ){ + layer.replacement.invalid = true; + } + + for( var i = 0; i < eles.length; i++ ){ + var caches = eles[i]._private.rscratch.imgLayerCaches; + + if( caches ){ + caches[ lvl ] = null; + } + } +}; + +LTCp.refineElementTextures = function( eles ){ + var self = this; + + // log('refine', eles.length); + + self.updateElementsInLayers( eles, function refineEachEle( layer, ele, req ){ + var rLyr = layer.replacement; + + if( !rLyr ){ + rLyr = layer.replacement = self.makeLayer( layer.bb, layer.level ); + rLyr.replaces = layer; + rLyr.eles = layer.eles; + + // log('make replacement layer %s for %s with level %s', rLyr.id, layer.id, rLyr.level); + } + + if( !rLyr.reqs ){ + for( var i = 0; i < rLyr.eles.length; i++ ){ + self.queueLayer( rLyr, rLyr.eles[i] ); + } + + // log('queue replacement layer refinement', rLyr.id); + } + } ); +}; + +LTCp.setupEleCacheInvalidation = function(){ + var self = this; + var eleDeqs = []; + + if( !useEleTxrCaching ){ return; } + + var updatedElesInLayers = util.debounce( function(){ + self.refineElementTextures( eleDeqs ); + + eleDeqs = []; + }, refineEleDebounceTime ); + + self.eleTxrCache.onDequeue(function( reqs ){ + for( var i = 0; i < reqs.length; i++ ){ + eleDeqs.push( reqs[i] ); + } + + updatedElesInLayers(); + }); +}; + +LTCp.queueLayer = function( layer, ele ){ + var self = this; + var q = self.layersQueue; + var elesQ = layer.elesQueue; + var hasId = elesQ.hasId = elesQ.hasId || {}; + + // if a layer is going to be replaced, queuing is a waste of time + if( layer.replacement ){ return; } + + if( ele ){ + if( hasId[ ele.id() ] ){ + return; + } + + elesQ.push( ele ); + hasId[ ele.id() ] = true; + } + + if( layer.reqs ){ + layer.reqs++; + + q.updateItem( layer ); + } else { + layer.reqs = 1; + + q.push( layer ); + } +}; + +LTCp.dequeue = function( pxRatio ){ + var self = this; + var q = self.layersQueue; + var deqd = []; + var eleDeqs = 0; + + while( eleDeqs < maxDeqSize ){ + if( q.size() === 0 ){ break; } + + var layer = q.peek(); + + // if a layer has been or will be replaced, then don't waste time with it + if( layer.replacement ){ + // log('layer %s in queue skipped b/c it already has a replacement', layer.id); + q.pop(); + continue; + } + + // if this is a replacement layer that has been superceded, then forget it + if( layer.replaces && layer !== layer.replaces.replacement ){ + // log('layer is no longer the most uptodate replacement; dequeued', layer.id) + q.pop(); + continue; + } + + if( layer.invalid ){ + // log('replacement layer %s is invalid; dequeued', layer.id); + q.pop(); + continue; + } + + var ele = layer.elesQueue.shift(); + + if( ele ){ + // log('dequeue layer %s', layer.id); + + self.drawEleInLayer( layer, ele, layer.level, pxRatio ); + + eleDeqs++; + } + + if( deqd.length === 0 ){ + // we need only one entry in deqd to queue redrawing etc + deqd.push( true ); + } + + // if the layer has all its eles done, then remove from the queue + if( layer.elesQueue.length === 0 ){ + q.pop(); + + layer.reqs = 0; + + // log('dequeue of layer %s complete', layer.id); + + // when a replacement layer is dequeued, it replaces the old layer in the level + if( layer.replaces ){ + self.applyLayerReplacement( layer ); + } + + self.requestRedraw(); + } + } + + return deqd; +}; + +LTCp.applyLayerReplacement = function( layer ){ + var self = this; + var layersInLevel = self.layersByLevel[ layer.level ]; + var replaced = layer.replaces; + var index = layersInLevel.indexOf( replaced ); + + // if the replaced layer is not in the active list for the level, then replacing + // refs would be a mistake (i.e. overwriting the true active layer) + if( index < 0 || replaced.invalid ){ + // log('replacement layer would have no effect', layer.id); + return; + } + + layersInLevel[ index ] = layer; // replace level ref + + // replace refs in eles + for( var i = 0; i < layer.eles.length; i++ ){ + var _p = layer.eles[i]._private; + var cache = _p.imgLayerCaches = _p.imgLayerCaches || {}; + + if( cache ){ + cache[ layer.level ] = layer; + } + } + + // log('apply replacement layer %s over %s', layer.id, replaced.id); + + self.requestRedraw(); +}; + +LTCp.requestRedraw = util.debounce( function(){ + var r = this.renderer; + + r.redrawHint( 'eles', true ); + r.redrawHint( 'drag', true ); + r.redraw(); +}, 100 ); + +LTCp.setupDequeueing = defs.setupDequeueing({ + deqRedrawThreshold: deqRedrawThreshold, + deqCost: deqCost, + deqAvgCost: deqAvgCost, + deqNoDrawCost: deqNoDrawCost, + deqFastCost: deqFastCost, + deq: function( self, pxRatio ){ + return self.dequeue( pxRatio ); + }, + onDeqd: util.noop, + shouldRedraw: util.trueify, + priority: function( self ){ + return self.renderer.beforeRenderPriorities.lyrTxrDeq; + } +}); + +module.exports = LayeredTextureCache; + +},{"../../../heap":81,"../../../is":83,"../../../math":85,"../../../util":100,"./texture-cache-defs":77}],76:[function(_dereq_,module,exports){ +'use strict'; + +var CRp = {}; + +CRp.nodeShapeImpl = function( name, context, centerX, centerY, width, height, points ){ + switch( name ){ + case 'ellipse': + return this.drawEllipsePath( context, centerX, centerY, width, height ); + case 'polygon': + return this.drawPolygonPath( context, centerX, centerY, width, height, points ); + case 'roundrectangle': + return this.drawRoundRectanglePath( context, centerX, centerY, width, height ); + } +}; + +module.exports = CRp; + +},{}],77:[function(_dereq_,module,exports){ +'use strict'; + +var util = _dereq_( '../../../util' ); + +var fullFpsTime = 1000/60; // assume 60 frames per second + +module.exports = { + setupDequeueing: function( opts ){ + return function setupDequeueingImpl(){ + var self = this; + var r = this.renderer; + + if( self.dequeueingSetup ){ + return; + } else { + self.dequeueingSetup = true; + } + + var queueRedraw = util.debounce( function(){ + r.redrawHint( 'eles', true ); + r.redrawHint( 'drag', true ); + + r.redraw(); + }, opts.deqRedrawThreshold ); + + var dequeue = function( willDraw, frameStartTime ){ + var startTime = util.performanceNow(); + var avgRenderTime = r.averageRedrawTime; + var renderTime = r.lastRedrawTime; + var deqd = []; + var extent = r.cy.extent(); + var pixelRatio = r.getPixelRatio(); + + while( true ){ + var now = util.performanceNow(); + var duration = now - startTime; + var frameDuration = now - frameStartTime; + + if( renderTime < fullFpsTime ){ + // if we're rendering faster than the ideal fps, then do dequeueing + // during all of the remaining frame time + + var timeAvailable = fullFpsTime - ( willDraw ? avgRenderTime : 0 ); + + if( frameDuration >= opts.deqFastCost * timeAvailable ){ + break; + } + } else { + if( willDraw ){ + if( + duration >= opts.deqCost * renderTime + || duration >= opts.deqAvgCost * avgRenderTime + ){ + break; + } + } else if( frameDuration >= opts.deqNoDrawCost * fullFpsTime ){ + break; + } + } + + var thisDeqd = opts.deq( self, pixelRatio, extent ); + + if( thisDeqd.length > 0 ){ + for( var i = 0; i < thisDeqd.length; i++ ){ + deqd.push( thisDeqd[i] ); + } + } else { + break; + } + } + + // callbacks on dequeue + if( deqd.length > 0 ){ + opts.onDeqd( self, deqd ); + + if( !willDraw && opts.shouldRedraw( self, deqd, pixelRatio, extent ) ){ + queueRedraw(); + } + } + }; + + var priority = opts.priority || util.noop; + + r.beforeRender( dequeue, priority( self ) ); + }; + } +}; + +},{"../../../util":100}],78:[function(_dereq_,module,exports){ +'use strict'; + +module.exports = [ + { name: 'null', impl: _dereq_( './null' ) }, + { name: 'base', impl: _dereq_( './base' ) }, + { name: 'canvas', impl: _dereq_( './canvas' ) } +]; + +},{"./base":60,"./canvas":74,"./null":79}],79:[function(_dereq_,module,exports){ +'use strict'; + +function NullRenderer( options ){ + this.options = options; + this.notifications = 0; // for testing +} + +var noop = function(){}; + +NullRenderer.prototype = { + recalculateRenderedStyle: noop, + notify: function(){ this.notifications++; }, + init: noop +}; + +module.exports = NullRenderer; + +},{}],80:[function(_dereq_,module,exports){ +/*! Weaver licensed under MIT (https://tldrlegal.com/license/mit-license), copyright Max Franz */ + +'use strict'; + +var is = _dereq_('./is'); +var util = _dereq_('./util'); +var Thread = _dereq_('./thread'); +var Promise = _dereq_('./promise'); +var define = _dereq_('./define'); + +var Fabric = function( N ){ + if( !(this instanceof Fabric) ){ + return new Fabric( N ); + } + + this._private = { + pass: [] + }; + + var defN = 4; + + if( is.number(N) ){ + // then use the specified number of threads + } if( typeof navigator !== 'undefined' && navigator.hardwareConcurrency != null ){ + N = navigator.hardwareConcurrency; + } else { + try{ + N = _dereq_('os').cpus().length; + } catch( err ){ + N = defN; + } + } // TODO could use an estimation here but would the additional expense be worth it? + + for( var i = 0; i < N; i++ ){ + this[i] = new Thread(); + } + + this.length = N; +}; + +var fabfn = Fabric.prototype; // short alias + +util.extend(fabfn, { + + instanceString: function(){ return 'fabric'; }, + + // require fn in all threads + require: function( fn, as ){ + for( var i = 0; i < this.length; i++ ){ + var thread = this[i]; + + thread.require( fn, as ); + } + + return this; + }, + + // get a random thread + random: function(){ + var i = Math.round( (this.length - 1) * Math.random() ); + var thread = this[i]; + + return thread; + }, + + // run on random thread + run: function( fn ){ + var pass = this._private.pass.shift(); + + return this.random().pass( pass ).run( fn ); + }, + + // sends a random thread a message + message: function( m ){ + return this.random().message( m ); + }, + + // send all threads a message + broadcast: function( m ){ + for( var i = 0; i < this.length; i++ ){ + var thread = this[i]; + + thread.message( m ); + } + + return this; // chaining + }, + + // stop all threads + stop: function(){ + for( var i = 0; i < this.length; i++ ){ + var thread = this[i]; + + thread.stop(); + } + + return this; // chaining + }, + + // pass data to be used with .spread() etc. + pass: function( data ){ + var pass = this._private.pass; + + if( is.array(data) ){ + pass.push( data ); + } else { + throw 'Only arrays may be used with fabric.pass()'; + } + + return this; // chaining + }, + + spreadSize: function(){ + var subsize = Math.ceil( this._private.pass[0].length / this.length ); + + subsize = Math.max( 1, subsize ); // don't pass less than one ele to each thread + + return subsize; + }, + + // split the data into slices to spread the data equally among threads + spread: function( fn ){ + var self = this; + var _p = self._private; + var subsize = self.spreadSize(); // number of pass eles to handle in each thread + var pass = _p.pass.shift().concat([]); // keep a copy + var runPs = []; + + for( var i = 0; i < this.length; i++ ){ + var thread = this[i]; + var slice = pass.splice( 0, subsize ); + + var runP = thread.pass( slice ).run( fn ); + + runPs.push( runP ); + + var doneEarly = pass.length === 0; + if( doneEarly ){ break; } + } + + return Promise.all( runPs ).then(function( thens ){ + var postpass = []; + var p = 0; + + // fill postpass with the total result joined from all threads + for( var i = 0; i < thens.length; i++ ){ + var then = thens[i]; // array result from thread i + + for( var j = 0; j < then.length; j++ ){ + var t = then[j]; // array element + + postpass[ p++ ] = t; + } + } + + return postpass; + }); + }, + + // parallel version of array.map() + map: function( fn ){ + var self = this; + + self.require( fn, '_$_$_fabmap' ); + + return self.spread(function( split ){ + var mapped = []; + var origResolve = resolve; // jshint ignore:line + + resolve = function( val ){ // jshint ignore:line + mapped.push( val ); + }; + + for( var i = 0; i < split.length; i++ ){ + var oldLen = mapped.length; + var ret = _$_$_fabmap( split[i] ); // jshint ignore:line + var nothingInsdByResolve = oldLen === mapped.length; + + if( nothingInsdByResolve ){ + mapped.push( ret ); + } + } + + resolve = origResolve; // jshint ignore:line + + return mapped; + }); + + }, + + // parallel version of array.filter() + filter: function( fn ){ + var _p = this._private; + var pass = _p.pass[0]; + + return this.map( fn ).then(function( include ){ + var ret = []; + + for( var i = 0; i < pass.length; i++ ){ + var datum = pass[i]; + var incDatum = include[i]; + + if( incDatum ){ + ret.push( datum ); + } + } + + return ret; + }); + }, + + // sorts the passed array using a divide and conquer strategy + sort: function( cmp ){ + var self = this; + var P = this._private.pass[0].length; + var subsize = this.spreadSize(); + + cmp = cmp || function( a, b ){ // default comparison function + if( a < b ){ + return -1; + } else if( a > b ){ + return 1; + } + + return 0; + }; + + self.require( cmp, '_$_$_cmp' ); + + return self.spread(function( split ){ // sort each split normally + var sortedSplit = split.sort( _$_$_cmp ); // jshint ignore:line + resolve( sortedSplit ); // jshint ignore:line + + }).then(function( joined ){ + // do all the merging in the main thread to minimise data transfer + + // TODO could do merging in separate threads but would incur add'l cost of data transfer + // for each level of the merge + + var merge = function( i, j, max ){ + // don't overflow array + j = Math.min( j, P ); + max = Math.min( max, P ); + + // left and right sides of merge + var l = i; + var r = j; + + var sorted = []; + + for( var k = l; k < max; k++ ){ + + var eleI = joined[i]; + var eleJ = joined[j]; + + if( i < r && ( j >= max || cmp(eleI, eleJ) <= 0 ) ){ + sorted.push( eleI ); + i++; + } else { + sorted.push( eleJ ); + j++; + } + + } + + // in the array proper, put the sorted values + for( var k = 0; k < sorted.length; k++ ){ // kth sorted item + var index = l + k; + + joined[ index ] = sorted[k]; + } + }; + + for( var splitL = subsize; splitL < P; splitL *= 2 ){ // merge until array is "split" as 1 + + for( var i = 0; i < P; i += 2*splitL ){ + merge( i, i + splitL, i + 2*splitL ); + } + + } + + return joined; + }); + } + + +}); + +var defineRandomPasser = function( opts ){ + opts = opts || {}; + + return function( fn, arg1 ){ + var pass = this._private.pass.shift(); + + return this.random().pass( pass )[ opts.threadFn ]( fn, arg1 ); + }; +}; + +util.extend(fabfn, { + randomMap: defineRandomPasser({ threadFn: 'map' }), + + reduce: defineRandomPasser({ threadFn: 'reduce' }), + + reduceRight: defineRandomPasser({ threadFn: 'reduceRight' }) +}); + +// aliases +var fn = fabfn; +fn.promise = fn.run; +fn.terminate = fn.halt = fn.stop; +fn.include = fn.require; + +// pull in event apis +util.extend(fabfn, { + on: define.on(), + one: define.on({ unbindSelfOnTrigger: true }), + off: define.off(), + trigger: define.trigger() +}); + +define.eventAliasesOn( fabfn ); + +module.exports = Fabric; + +},{"./define":44,"./is":83,"./promise":86,"./thread":98,"./util":100,"os":undefined}],81:[function(_dereq_,module,exports){ +/*! +Ported by Xueqiao Xu <xueqiaoxu@gmail.com>; + +PSF LICENSE AGREEMENT FOR PYTHON 2.7.2 + +1. This LICENSE AGREEMENT is between the Python Software Foundation (“PSF”), and the Individual or Organization (“Licensee”) accessing and otherwise using Python 2.7.2 software in source or binary form and its associated documentation. +2. Subject to the terms and conditions of this License Agreement, PSF hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use Python 2.7.2 alone or in any derivative version, provided, however, that PSF’s License Agreement and PSF’s notice of copyright, i.e., “Copyright © 2001-2012 Python Software Foundation; All Rights Reserved” are retained in Python 2.7.2 alone or in any derivative version prepared by Licensee. +3. In the event Licensee prepares a derivative work that is based on or incorporates Python 2.7.2 or any part thereof, and wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in any such work a brief summary of the changes made to Python 2.7.2. +4. PSF is making Python 2.7.2 available to Licensee on an “AS IS” basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 2.7.2 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. +5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 2.7.2 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.7.2, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. +6. This License Agreement will automatically terminate upon a material breach of its terms and conditions. +7. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between PSF and Licensee. This License Agreement does not grant permission to use PSF trademarks or trade name in a trademark sense to endorse or promote products or services of Licensee, or any third party. +8. By copying, installing or otherwise using Python 2.7.2, Licensee agrees to be bound by the terms and conditions of this License Agreement. +*/ + +'use strict'; +/* jshint ignore:start */ + +// Generated by CoffeeScript 1.8.0 +(function(){ + var Heap, defaultCmp, floor, heapify, heappop, heappush, heappushpop, heapreplace, insort, min, nlargest, nsmallest, updateItem, _siftdown, _siftup; + + floor = Math.floor, min = Math.min; + + + /* + Default comparison function to be used + */ + + defaultCmp = function( x, y ){ + if( x < y ){ + return -1; + } + if( x > y ){ + return 1; + } + return 0; + }; + + + /* + Insert item x in list a, and keep it sorted assuming a is sorted. + + If x is already in a, insert it to the right of the rightmost x. + + Optional args lo (default 0) and hi (default a.length) bound the slice + of a to be searched. + */ + + insort = function( a, x, lo, hi, cmp ){ + var mid; + if( lo == null ){ + lo = 0; + } + if( cmp == null ){ + cmp = defaultCmp; + } + if( lo < 0 ){ + throw new Error( 'lo must be non-negative' ); + } + if( hi == null ){ + hi = a.length; + } + while( lo < hi ){ + mid = floor( (lo + hi) / 2 ); + if( cmp( x, a[ mid ] ) < 0 ){ + hi = mid; + } else { + lo = mid + 1; + } + } + return ([].splice.apply( a, [ lo, lo - lo ].concat( x ) ), x); + }; + + + /* + Push item onto heap, maintaining the heap invariant. + */ + + heappush = function( array, item, cmp ){ + if( cmp == null ){ + cmp = defaultCmp; + } + array.push( item ); + return _siftdown( array, 0, array.length - 1, cmp ); + }; + + + /* + Pop the smallest item off the heap, maintaining the heap invariant. + */ + + heappop = function( array, cmp ){ + var lastelt, returnitem; + if( cmp == null ){ + cmp = defaultCmp; + } + lastelt = array.pop(); + if( array.length ){ + returnitem = array[0]; + array[0] = lastelt; + _siftup( array, 0, cmp ); + } else { + returnitem = lastelt; + } + return returnitem; + }; + + + /* + Pop and return the current smallest value, and add the new item. + + This is more efficient than heappop() followed by heappush(), and can be + more appropriate when using a fixed size heap. Note that the value + returned may be larger than item! That constrains reasonable use of + this routine unless written as part of a conditional replacement: + if item > array[0] + item = heapreplace(array, item) + */ + + heapreplace = function( array, item, cmp ){ + var returnitem; + if( cmp == null ){ + cmp = defaultCmp; + } + returnitem = array[0]; + array[0] = item; + _siftup( array, 0, cmp ); + return returnitem; + }; + + + /* + Fast version of a heappush followed by a heappop. + */ + + heappushpop = function( array, item, cmp ){ + var _ref; + if( cmp == null ){ + cmp = defaultCmp; + } + if( array.length && cmp( array[0], item ) < 0 ){ + _ref = [ array[0], item ], item = _ref[0], array[0] = _ref[1]; + _siftup( array, 0, cmp ); + } + return item; + }; + + + /* + Transform list into a heap, in-place, in O(array.length) time. + */ + + heapify = function( array, cmp ){ + var i, _i, _j, _len, _ref, _ref1, _results, _results1; + if( cmp == null ){ + cmp = defaultCmp; + } + _ref1 = (function(){ + _results1 = []; + for( var _j = 0, _ref = floor( array.length / 2 ); 0 <= _ref ? _j < _ref : _j > _ref; 0 <= _ref ? _j++ : _j-- ){ _results1.push( _j ); } + return _results1; + }).apply( this ).reverse(); + _results = []; + for( _i = 0, _len = _ref1.length; _i < _len; _i++ ){ + i = _ref1[ _i ]; + _results.push( _siftup( array, i, cmp ) ); + } + return _results; + }; + + + /* + Update the position of the given item in the heap. + This function should be called every time the item is being modified. + */ + + updateItem = function( array, item, cmp ){ + var pos; + if( cmp == null ){ + cmp = defaultCmp; + } + pos = array.indexOf( item ); + if( pos === -1 ){ + return; + } + _siftdown( array, 0, pos, cmp ); + return _siftup( array, pos, cmp ); + }; + + + /* + Find the n largest elements in a dataset. + */ + + nlargest = function( array, n, cmp ){ + var elem, result, _i, _len, _ref; + if( cmp == null ){ + cmp = defaultCmp; + } + result = array.slice( 0, n ); + if( !result.length ){ + return result; + } + heapify( result, cmp ); + _ref = array.slice( n ); + for( _i = 0, _len = _ref.length; _i < _len; _i++ ){ + elem = _ref[ _i ]; + heappushpop( result, elem, cmp ); + } + return result.sort( cmp ).reverse(); + }; + + + /* + Find the n smallest elements in a dataset. + */ + + nsmallest = function( array, n, cmp ){ + var elem, i, los, result, _i, _j, _len, _ref, _ref1, _results; + if( cmp == null ){ + cmp = defaultCmp; + } + if( n * 10 <= array.length ){ + result = array.slice( 0, n ).sort( cmp ); + if( !result.length ){ + return result; + } + los = result[ result.length - 1]; + _ref = array.slice( n ); + for( _i = 0, _len = _ref.length; _i < _len; _i++ ){ + elem = _ref[ _i ]; + if( cmp( elem, los ) < 0 ){ + insort( result, elem, 0, null, cmp ); + result.pop(); + los = result[ result.length - 1]; + } + } + return result; + } + heapify( array, cmp ); + _results = []; + for( i = _j = 0, _ref1 = min( n, array.length ); 0 <= _ref1 ? _j < _ref1 : _j > _ref1; i = 0 <= _ref1 ? ++_j : --_j ){ + _results.push( heappop( array, cmp ) ); + } + return _results; + }; + + _siftdown = function( array, startpos, pos, cmp ){ + var newitem, parent, parentpos; + if( cmp == null ){ + cmp = defaultCmp; + } + newitem = array[ pos ]; + while( pos > startpos ){ + parentpos = (pos - 1) >> 1; + parent = array[ parentpos ]; + if( cmp( newitem, parent ) < 0 ){ + array[ pos ] = parent; + pos = parentpos; + continue; + } + break; + } + return array[ pos ] = newitem; + }; + + _siftup = function( array, pos, cmp ){ + var childpos, endpos, newitem, rightpos, startpos; + if( cmp == null ){ + cmp = defaultCmp; + } + endpos = array.length; + startpos = pos; + newitem = array[ pos ]; + childpos = 2 * pos + 1; + while( childpos < endpos ){ + rightpos = childpos + 1; + if( rightpos < endpos && !(cmp( array[ childpos ], array[ rightpos ] ) < 0) ){ + childpos = rightpos; + } + array[ pos ] = array[ childpos ]; + pos = childpos; + childpos = 2 * pos + 1; + } + array[ pos ] = newitem; + return _siftdown( array, startpos, pos, cmp ); + }; + + Heap = (function(){ + Heap.push = heappush; + + Heap.pop = heappop; + + Heap.replace = heapreplace; + + Heap.pushpop = heappushpop; + + Heap.heapify = heapify; + + Heap.updateItem = updateItem; + + Heap.nlargest = nlargest; + + Heap.nsmallest = nsmallest; + + function Heap( cmp ){ + this.cmp = cmp != null ? cmp : defaultCmp; + this.nodes = []; + } + + Heap.prototype.push = function( x ){ + return heappush( this.nodes, x, this.cmp ); + }; + + Heap.prototype.pop = function(){ + return heappop( this.nodes, this.cmp ); + }; + + Heap.prototype.peek = function(){ + return this.nodes[0]; + }; + + Heap.prototype.contains = function( x ){ + return this.nodes.indexOf( x ) !== -1; + }; + + Heap.prototype.replace = function( x ){ + return heapreplace( this.nodes, x, this.cmp ); + }; + + Heap.prototype.pushpop = function( x ){ + return heappushpop( this.nodes, x, this.cmp ); + }; + + Heap.prototype.heapify = function(){ + return heapify( this.nodes, this.cmp ); + }; + + Heap.prototype.updateItem = function( x ){ + return updateItem( this.nodes, x, this.cmp ); + }; + + Heap.prototype.clear = function(){ + return this.nodes = []; + }; + + Heap.prototype.empty = function(){ + return this.nodes.length === 0; + }; + + Heap.prototype.size = function(){ + return this.nodes.length; + }; + + Heap.prototype.clone = function(){ + var heap; + heap = new Heap(); + heap.nodes = this.nodes.slice( 0 ); + return heap; + }; + + Heap.prototype.toArray = function(){ + return this.nodes.slice( 0 ); + }; + + Heap.prototype.insert = Heap.prototype.push; + + Heap.prototype.top = Heap.prototype.peek; + + Heap.prototype.front = Heap.prototype.peek; + + Heap.prototype.has = Heap.prototype.contains; + + Heap.prototype.copy = Heap.prototype.clone; + + return Heap; + + })(); + + (function( root, factory ){ + if( typeof define === 'function' && define.amd ){ // eslint-disable-line no-undef + return define( [], factory ); // eslint-disable-line no-undef + } else if( typeof exports === 'object' ){ + return module.exports = factory(); + } else { + return root.Heap = factory(); + } + })( this, function(){ + return Heap; + } ); + +}).call( this ); + +/* jshint ignore:end */ + +},{}],82:[function(_dereq_,module,exports){ +'use strict'; + +_dereq_('./-preamble'); + +var window = _dereq_( './window' ); +var is = _dereq_( './is' ); +var Core = _dereq_( './core' ); +var extension = _dereq_( './extension' ); +var registerJquery = _dereq_( './jquery-plugin' ); +var Stylesheet = _dereq_( './stylesheet' ); +var Thread = _dereq_( './thread' ); +var Fabric = _dereq_( './fabric' ); + +var cytoscape = function( options ){ // jshint ignore:line + // if no options specified, use default + if( options === undefined ){ + options = {}; + } + + // create instance + if( is.plainObject( options ) ){ + return new Core( options ); + } + + // allow for registration of extensions + else if( is.string( options ) ){ + return extension.apply( extension, arguments ); + } +}; + +// replaced by build system +cytoscape.version = _dereq_('./version.json'); + +// try to register w/ jquery +if( window && window.jQuery ){ + registerJquery( window.jQuery, cytoscape ); +} + +// expose register api +cytoscape.registerJquery = function( jQuery ){ + registerJquery( jQuery, cytoscape ); +}; + +// expose public apis (mostly for extensions) +cytoscape.stylesheet = cytoscape.Stylesheet = Stylesheet; +cytoscape.thread = cytoscape.Thread = Thread; +cytoscape.fabric = cytoscape.Fabric = Fabric; + +module.exports = cytoscape; + +},{"./-preamble":1,"./core":37,"./extension":46,"./fabric":80,"./is":83,"./jquery-plugin":84,"./stylesheet":97,"./thread":98,"./version.json":106,"./window":107}],83:[function(_dereq_,module,exports){ +'use strict'; + +/*global HTMLElement DocumentTouch */ + +var window = _dereq_( './window' ); +var navigator = window ? window.navigator : null; +var document = window ? window.document : null; + +var typeofstr = typeof ''; +var typeofobj = typeof {}; +var typeoffn = typeof function(){}; +var typeofhtmlele = typeof HTMLElement; + +var instanceStr = function( obj ){ + return obj && obj.instanceString && is.fn( obj.instanceString ) ? obj.instanceString() : null; +}; + +var is = { + defined: function( obj ){ + return obj != null; // not undefined or null + }, + + string: function( obj ){ + return obj != null && typeof obj == typeofstr; + }, + + fn: function( obj ){ + return obj != null && typeof obj === typeoffn; + }, + + array: function( obj ){ + return Array.isArray ? Array.isArray( obj ) : obj != null && obj instanceof Array; + }, + + plainObject: function( obj ){ + return obj != null && typeof obj === typeofobj && !is.array( obj ) && obj.constructor === Object; + }, + + object: function( obj ){ + return obj != null && typeof obj === typeofobj; + }, + + number: function( obj ){ + return obj != null && typeof obj === typeof 1 && !isNaN( obj ); + }, + + integer: function( obj ){ + return is.number( obj ) && Math.floor( obj ) === obj; + }, + + bool: function( obj ){ + return obj != null && typeof obj === typeof true; + }, + + htmlElement: function( obj ){ + if( 'undefined' === typeofhtmlele ){ + return undefined; + } else { + return null != obj && obj instanceof HTMLElement; + } + }, + + elementOrCollection: function( obj ){ + return is.element( obj ) || is.collection( obj ); + }, + + element: function( obj ){ + return instanceStr( obj ) === 'collection' && obj._private.single; + }, + + collection: function( obj ){ + return instanceStr( obj ) === 'collection' && !obj._private.single; + }, + + core: function( obj ){ + return instanceStr( obj ) === 'core'; + }, + + style: function( obj ){ + return instanceStr( obj ) === 'style'; + }, + + stylesheet: function( obj ){ + return instanceStr( obj ) === 'stylesheet'; + }, + + event: function( obj ){ + return instanceStr( obj ) === 'event'; + }, + + thread: function( obj ){ + return instanceStr( obj ) === 'thread'; + }, + + fabric: function( obj ){ + return instanceStr( obj ) === 'fabric'; + }, + + emptyString: function( obj ){ + if( obj === undefined || obj === null ){ // null is empty + return true; + } else if( obj === '' || obj.match( /^\s+$/ ) ){ + return true; // empty string is empty + } + + return false; // otherwise, we don't know what we've got + }, + + nonemptyString: function( obj ){ + if( obj && is.string( obj ) && obj !== '' && !obj.match( /^\s+$/ ) ){ + return true; + } + + return false; + }, + + domElement: function( obj ){ + if( typeof HTMLElement === 'undefined' ){ + return false; // we're not in a browser so it doesn't matter + } else { + return obj instanceof HTMLElement; + } + }, + + boundingBox: function( obj ){ + return is.plainObject( obj ) && + is.number( obj.x1 ) && is.number( obj.x2 ) && + is.number( obj.y1 ) && is.number( obj.y2 ) + ; + }, + + promise: function( obj ){ + return is.object( obj ) && is.fn( obj.then ); + }, + + touch: function(){ + return window && ( ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch ); + }, + + gecko: function(){ + return window && ( typeof InstallTrigger !== 'undefined' || ('MozAppearance' in document.documentElement.style) ); + }, + + webkit: function(){ + return window && ( typeof webkitURL !== 'undefined' || ('WebkitAppearance' in document.documentElement.style) ); + }, + + chromium: function(){ + return window && ( typeof chrome !== 'undefined' ); + }, + + khtml: function(){ + return navigator && navigator.vendor.match( /kde/i ); // probably a better way to detect this... + }, + + khtmlEtc: function(){ + return is.khtml() || is.webkit() || is.chromium(); + }, + + ms: function(){ + return navigator && navigator.userAgent.match( /msie|trident|edge/i ); // probably a better way to detect this... + }, + + windows: function(){ + return navigator && navigator.appVersion.match( /Win/i ); + }, + + mac: function(){ + return navigator && navigator.appVersion.match( /Mac/i ); + }, + + linux: function(){ + return navigator && navigator.appVersion.match( /Linux/i ); + }, + + unix: function(){ + return navigator && navigator.appVersion.match( /X11/i ); + } +}; + +module.exports = is; + +},{"./window":107}],84:[function(_dereq_,module,exports){ +'use strict'; + +var is = _dereq_( './is' ); + +var cyReg = function( $ele ){ + var d = $ele[0]._cyreg = $ele[0]._cyreg || {}; + + return d; +}; + +var registerJquery = function( $, cytoscape ){ + if( !$ ){ return; } // no jquery => don't need this + + if( $.fn.cytoscape ){ return; } // already registered + + // allow calls on a jQuery selector by proxying calls to $.cytoscape + // e.g. $("#foo").cytoscape(options) => $.cytoscape(options) on #foo + $.fn.cytoscape = function( opts ){ + var $this = $( this ); + + // get object + if( opts === 'get' ){ + return cyReg( $this ).cy; + } + + // bind to ready + else if( is.fn( opts ) ){ + + var ready = opts; + var cy = cyReg( $this ).cy; + + if( cy && cy.isReady() ){ // already ready so just trigger now + cy.trigger( 'ready', [], ready ); + + } else { // not yet ready, so add to readies list + var data = cyReg( $this ); + var readies = data.readies = data.readies || []; + + readies.push( ready ); + } + + } + + // proxy to create instance + else if( is.plainObject( opts ) ){ + return $this.each( function(){ + var options = $.extend( {}, opts, { + container: $( this )[0] + } ); + + cytoscape( options ); + } ); + } + }; + + // allow access to the global cytoscape object under jquery for legacy reasons + $.cytoscape = cytoscape; + + // use short alias (cy) if not already defined + if( $.fn.cy == null && $.cy == null ){ + $.fn.cy = $.fn.cytoscape; + $.cy = $.cytoscape; + } +}; + +module.exports = registerJquery; + +},{"./is":83}],85:[function(_dereq_,module,exports){ +'use strict'; + +var math = {}; + +math.arePositionsSame = function( p1, p2 ){ + return p1.x === p2.x && p1.y === p2.y; +}; + +math.copyPosition = function( p ){ + return { x: p.x, y: p.y }; +}; + +math.array2point = function( arr ){ + return { + x: arr[0], + y: arr[1] + }; +}; + +math.deg2rad = function( deg ){ + return Math.PI * deg / 180; +}; + +math.log2 = Math.log2 || function( n ){ + return Math.log( n ) / Math.log( 2 ); +}; + +math.signum = function( x ){ + if( x > 0 ){ + return 1; + } else if( x < 0 ){ + return -1; + } else { + return 0; + } +}; + +math.dist = function( p1, p2 ){ + return Math.sqrt( math.sqdist( p1, p2 ) ); +}; + +math.sqdist = function( p1, p2 ){ + var dx = p2.x - p1.x; + var dy = p2.y - p1.y; + + return dx * dx + dy * dy; +}; + +// from http://en.wikipedia.org/wiki/Bézier_curve#Quadratic_curves +math.qbezierAt = function( p0, p1, p2, t ){ + return (1 - t) * (1 - t) * p0 + 2 * (1 - t) * t * p1 + t * t * p2; +}; + +math.qbezierPtAt = function( p0, p1, p2, t ){ + return { + x: math.qbezierAt( p0.x, p1.x, p2.x, t ), + y: math.qbezierAt( p0.y, p1.y, p2.y, t ) + }; +}; + +math.lineAt = function( p0, p1, t, d ){ + var vec = { + x: p1.x - p0.x, + y: p1.y - p0.y + }; + + var vecDist = math.dist( p0, p1 ); + + var normVec = { + x: vec.x / vecDist, + y: vec.y / vecDist + }; + + t = t == null ? 0 : t; + + var d = d != null ? d : t * vecDist; + + return { + x: p0.x + normVec.x * d, + y: p0.y + normVec.y * d + }; +}; + +math.lineAtDist = function( p0, p1, d ){ + return math.lineAt( p0, p1, undefined, d ); +}; + +// get angle at A via cosine law +math.triangleAngle = function( A, B, C ){ + var a = math.dist( B, C ); + var b = math.dist( A, C ); + var c = math.dist( A, B ); + + return Math.acos( (a*a + b*b - c*c)/(2*a*b) ); +}; + +math.bound = function( min, val, max ){ + return Math.max( min, Math.min( max, val ) ); +}; + +// makes a full bb (x1, y1, x2, y2, w, h) from implicit params +math.makeBoundingBox = function( bb ){ + if( bb == null ){ + return { + x1: Infinity, + y1: Infinity, + x2: -Infinity, + y2: -Infinity, + w: 0, + h: 0 + }; + } else if( bb.x1 != null && bb.y1 != null ){ + if( bb.x2 != null && bb.y2 != null && bb.x2 >= bb.x1 && bb.y2 >= bb.y1 ){ + return { + x1: bb.x1, + y1: bb.y1, + x2: bb.x2, + y2: bb.y2, + w: bb.x2 - bb.x1, + h: bb.y2 - bb.y1 + }; + } else if( bb.w != null && bb.h != null && bb.w >= 0 && bb.h >= 0 ){ + return { + x1: bb.x1, + y1: bb.y1, + x2: bb.x1 + bb.w, + y2: bb.y1 + bb.h, + w: bb.w, + h: bb.h + }; + } + } +}; + +math.updateBoundingBox = function( bb1, bb2 ){ + // update bb1 with bb2 bounds + + bb1.x1 = Math.min( bb1.x1, bb2.x1 ); + bb1.x2 = Math.max( bb1.x2, bb2.x2 ); + bb1.w = bb1.x2 - bb1.x1; + + bb1.y1 = Math.min( bb1.y1, bb2.y1 ); + bb1.y2 = Math.max( bb1.y2, bb2.y2 ); + bb1.h = bb1.y2 - bb1.y1; +}; + +math.expandBoundingBox = function( bb, padding ){ + bb.x1 -= padding; + bb.x2 += padding; + bb.y1 -= padding; + bb.y2 += padding; + bb.w = bb.x2 - bb.x1; + bb.h = bb.y2 - bb.y1; + + return bb; +}; + +math.boundingBoxesIntersect = function( bb1, bb2 ){ + // case: one bb to right of other + if( bb1.x1 > bb2.x2 ){ return false; } + if( bb2.x1 > bb1.x2 ){ return false; } + + // case: one bb to left of other + if( bb1.x2 < bb2.x1 ){ return false; } + if( bb2.x2 < bb1.x1 ){ return false; } + + // case: one bb above other + if( bb1.y2 < bb2.y1 ){ return false; } + if( bb2.y2 < bb1.y1 ){ return false; } + + // case: one bb below other + if( bb1.y1 > bb2.y2 ){ return false; } + if( bb2.y1 > bb1.y2 ){ return false; } + + // otherwise, must have some overlap + return true; +}; + +math.inBoundingBox = function( bb, x, y ){ + return bb.x1 <= x && x <= bb.x2 && bb.y1 <= y && y <= bb.y2; +}; + +math.pointInBoundingBox = function( bb, pt ){ + return this.inBoundingBox( bb, pt.x, pt.y ); +}; + +math.boundingBoxInBoundingBox = function( bb1, bb2 ){ + return ( + math.inBoundingBox( bb1, bb2.x1, bb2.y1 ) + && math.inBoundingBox( bb1, bb2.x2, bb2.y2 ) + ); +}; + +math.roundRectangleIntersectLine = function( + x, y, nodeX, nodeY, width, height, padding ){ + + var cornerRadius = this.getRoundRectangleRadius( width, height ); + + var halfWidth = width / 2; + var halfHeight = height / 2; + + // Check intersections with straight line segments + var straightLineIntersections; + + // Top segment, left to right + { + var topStartX = nodeX - halfWidth + cornerRadius - padding; + var topStartY = nodeY - halfHeight - padding; + var topEndX = nodeX + halfWidth - cornerRadius + padding; + var topEndY = topStartY; + + straightLineIntersections = this.finiteLinesIntersect( + x, y, nodeX, nodeY, topStartX, topStartY, topEndX, topEndY, false ); + + if( straightLineIntersections.length > 0 ){ + return straightLineIntersections; + } + } + + // Right segment, top to bottom + { + var rightStartX = nodeX + halfWidth + padding; + var rightStartY = nodeY - halfHeight + cornerRadius - padding; + var rightEndX = rightStartX; + var rightEndY = nodeY + halfHeight - cornerRadius + padding; + + straightLineIntersections = this.finiteLinesIntersect( + x, y, nodeX, nodeY, rightStartX, rightStartY, rightEndX, rightEndY, false ); + + if( straightLineIntersections.length > 0 ){ + return straightLineIntersections; + } + } + + // Bottom segment, left to right + { + var bottomStartX = nodeX - halfWidth + cornerRadius - padding; + var bottomStartY = nodeY + halfHeight + padding; + var bottomEndX = nodeX + halfWidth - cornerRadius + padding; + var bottomEndY = bottomStartY; + + straightLineIntersections = this.finiteLinesIntersect( + x, y, nodeX, nodeY, bottomStartX, bottomStartY, bottomEndX, bottomEndY, false ); + + if( straightLineIntersections.length > 0 ){ + return straightLineIntersections; + } + } + + // Left segment, top to bottom + { + var leftStartX = nodeX - halfWidth - padding; + var leftStartY = nodeY - halfHeight + cornerRadius - padding; + var leftEndX = leftStartX; + var leftEndY = nodeY + halfHeight - cornerRadius + padding; + + straightLineIntersections = this.finiteLinesIntersect( + x, y, nodeX, nodeY, leftStartX, leftStartY, leftEndX, leftEndY, false ); + + if( straightLineIntersections.length > 0 ){ + return straightLineIntersections; + } + } + + // Check intersections with arc segments + var arcIntersections; + + // Top Left + { + var topLeftCenterX = nodeX - halfWidth + cornerRadius; + var topLeftCenterY = nodeY - halfHeight + cornerRadius; + arcIntersections = this.intersectLineCircle( + x, y, nodeX, nodeY, + topLeftCenterX, topLeftCenterY, cornerRadius + padding ); + + // Ensure the intersection is on the desired quarter of the circle + if( arcIntersections.length > 0 + && arcIntersections[0] <= topLeftCenterX + && arcIntersections[1] <= topLeftCenterY ){ + return [ arcIntersections[0], arcIntersections[1] ]; + } + } + + // Top Right + { + var topRightCenterX = nodeX + halfWidth - cornerRadius; + var topRightCenterY = nodeY - halfHeight + cornerRadius; + arcIntersections = this.intersectLineCircle( + x, y, nodeX, nodeY, + topRightCenterX, topRightCenterY, cornerRadius + padding ); + + // Ensure the intersection is on the desired quarter of the circle + if( arcIntersections.length > 0 + && arcIntersections[0] >= topRightCenterX + && arcIntersections[1] <= topRightCenterY ){ + return [ arcIntersections[0], arcIntersections[1] ]; + } + } + + // Bottom Right + { + var bottomRightCenterX = nodeX + halfWidth - cornerRadius; + var bottomRightCenterY = nodeY + halfHeight - cornerRadius; + arcIntersections = this.intersectLineCircle( + x, y, nodeX, nodeY, + bottomRightCenterX, bottomRightCenterY, cornerRadius + padding ); + + // Ensure the intersection is on the desired quarter of the circle + if( arcIntersections.length > 0 + && arcIntersections[0] >= bottomRightCenterX + && arcIntersections[1] >= bottomRightCenterY ){ + return [ arcIntersections[0], arcIntersections[1] ]; + } + } + + // Bottom Left + { + var bottomLeftCenterX = nodeX - halfWidth + cornerRadius; + var bottomLeftCenterY = nodeY + halfHeight - cornerRadius; + arcIntersections = this.intersectLineCircle( + x, y, nodeX, nodeY, + bottomLeftCenterX, bottomLeftCenterY, cornerRadius + padding ); + + // Ensure the intersection is on the desired quarter of the circle + if( arcIntersections.length > 0 + && arcIntersections[0] <= bottomLeftCenterX + && arcIntersections[1] >= bottomLeftCenterY ){ + return [ arcIntersections[0], arcIntersections[1] ]; + } + } + + return []; // if nothing +}; + +math.inLineVicinity = function( x, y, lx1, ly1, lx2, ly2, tolerance ){ + var t = tolerance; + + var x1 = Math.min( lx1, lx2 ); + var x2 = Math.max( lx1, lx2 ); + var y1 = Math.min( ly1, ly2 ); + var y2 = Math.max( ly1, ly2 ); + + return x1 - t <= x && x <= x2 + t + && y1 - t <= y && y <= y2 + t; +}; + +math.inBezierVicinity = function( + x, y, x1, y1, x2, y2, x3, y3, tolerance ){ + + var bb = { + x1: Math.min( x1, x3, x2 ) - tolerance, + x2: Math.max( x1, x3, x2 ) + tolerance, + y1: Math.min( y1, y3, y2 ) - tolerance, + y2: Math.max( y1, y3, y2 ) + tolerance + }; + + // if outside the rough bounding box for the bezier, then it can't be a hit + if( x < bb.x1 || x > bb.x2 || y < bb.y1 || y > bb.y2 ){ + // console.log('bezier out of rough bb') + return false; + } else { + // console.log('do more expensive check'); + return true; + } + +}; + +math.solveCubic = function( a, b, c, d, result ){ + + // Solves a cubic function, returns root in form [r1, i1, r2, i2, r3, i3], where + // r is the real component, i is the imaginary component + + // An implementation of the Cardano method from the year 1545 + // http://en.wikipedia.org/wiki/Cubic_function#The_nature_of_the_roots + + b /= a; + c /= a; + d /= a; + + var discriminant, q, r, dum1, s, t, term1, r13; + + q = (3.0 * c - (b * b)) / 9.0; + r = -(27.0 * d) + b * (9.0 * c - 2.0 * (b * b)); + r /= 54.0; + + discriminant = q * q * q + r * r; + result[1] = 0; + term1 = (b / 3.0); + + if( discriminant > 0 ){ + s = r + Math.sqrt( discriminant ); + s = ((s < 0) ? -Math.pow( -s, (1.0 / 3.0) ) : Math.pow( s, (1.0 / 3.0) )); + t = r - Math.sqrt( discriminant ); + t = ((t < 0) ? -Math.pow( -t, (1.0 / 3.0) ) : Math.pow( t, (1.0 / 3.0) )); + result[0] = -term1 + s + t; + term1 += (s + t) / 2.0; + result[4] = result[2] = -term1; + term1 = Math.sqrt( 3.0 ) * (-t + s) / 2; + result[3] = term1; + result[5] = -term1; + return; + } + + result[5] = result[3] = 0; + + if( discriminant === 0 ){ + r13 = ((r < 0) ? -Math.pow( -r, (1.0 / 3.0) ) : Math.pow( r, (1.0 / 3.0) )); + result[0] = -term1 + 2.0 * r13; + result[4] = result[2] = -(r13 + term1); + return; + } + + q = -q; + dum1 = q * q * q; + dum1 = Math.acos( r / Math.sqrt( dum1 ) ); + r13 = 2.0 * Math.sqrt( q ); + result[0] = -term1 + r13 * Math.cos( dum1 / 3.0 ); + result[2] = -term1 + r13 * Math.cos( (dum1 + 2.0 * Math.PI) / 3.0 ); + result[4] = -term1 + r13 * Math.cos( (dum1 + 4.0 * Math.PI) / 3.0 ); + + return; +}; + +math.sqdistToQuadraticBezier = function( + x, y, x1, y1, x2, y2, x3, y3 ){ + + // Find minimum distance by using the minimum of the distance + // function between the given point and the curve + + // This gives the coefficients of the resulting cubic equation + // whose roots tell us where a possible minimum is + // (Coefficients are divided by 4) + + var a = 1.0 * x1 * x1 - 4 * x1 * x2 + 2 * x1 * x3 + 4 * x2 * x2 - 4 * x2 * x3 + x3 * x3 + + y1 * y1 - 4 * y1 * y2 + 2 * y1 * y3 + 4 * y2 * y2 - 4 * y2 * y3 + y3 * y3; + + var b = 1.0 * 9 * x1 * x2 - 3 * x1 * x1 - 3 * x1 * x3 - 6 * x2 * x2 + 3 * x2 * x3 + + 9 * y1 * y2 - 3 * y1 * y1 - 3 * y1 * y3 - 6 * y2 * y2 + 3 * y2 * y3; + + var c = 1.0 * 3 * x1 * x1 - 6 * x1 * x2 + x1 * x3 - x1 * x + 2 * x2 * x2 + 2 * x2 * x - x3 * x + + 3 * y1 * y1 - 6 * y1 * y2 + y1 * y3 - y1 * y + 2 * y2 * y2 + 2 * y2 * y - y3 * y; + + var d = 1.0 * x1 * x2 - x1 * x1 + x1 * x - x2 * x + + y1 * y2 - y1 * y1 + y1 * y - y2 * y; + + // debug("coefficients: " + a / a + ", " + b / a + ", " + c / a + ", " + d / a); + + var roots = []; + + // Use the cubic solving algorithm + this.solveCubic( a, b, c, d, roots ); + + var zeroThreshold = 0.0000001; + + var params = []; + + for( var index = 0; index < 6; index += 2 ){ + if( Math.abs( roots[ index + 1] ) < zeroThreshold + && roots[ index ] >= 0 + && roots[ index ] <= 1.0 ){ + params.push( roots[ index ] ); + } + } + + params.push( 1.0 ); + params.push( 0.0 ); + + var minDistanceSquared = -1; + var closestParam; + + var curX, curY, distSquared; + for( var i = 0; i < params.length; i++ ){ + curX = Math.pow( 1.0 - params[ i ], 2.0 ) * x1 + + 2.0 * (1 - params[ i ]) * params[ i ] * x2 + + params[ i ] * params[ i ] * x3; + + curY = Math.pow( 1 - params[ i ], 2.0 ) * y1 + + 2 * (1.0 - params[ i ]) * params[ i ] * y2 + + params[ i ] * params[ i ] * y3; + + distSquared = Math.pow( curX - x, 2 ) + Math.pow( curY - y, 2 ); + // debug('distance for param ' + params[i] + ": " + Math.sqrt(distSquared)); + if( minDistanceSquared >= 0 ){ + if( distSquared < minDistanceSquared ){ + minDistanceSquared = distSquared; + closestParam = params[ i ]; + } + } else { + minDistanceSquared = distSquared; + closestParam = params[ i ]; + } + } + + return minDistanceSquared; +}; + +math.sqdistToFiniteLine = function( x, y, x1, y1, x2, y2 ){ + var offset = [ x - x1, y - y1 ]; + var line = [ x2 - x1, y2 - y1 ]; + + var lineSq = line[0] * line[0] + line[1] * line[1]; + var hypSq = offset[0] * offset[0] + offset[1] * offset[1]; + + var dotProduct = offset[0] * line[0] + offset[1] * line[1]; + var adjSq = dotProduct * dotProduct / lineSq; + + if( dotProduct < 0 ){ + return hypSq; + } + + if( adjSq > lineSq ){ + return (x - x2) * (x - x2) + (y - y2) * (y - y2); + } + + return hypSq - adjSq; +}; + +math.pointInsidePolygonPoints = function( x, y, points ){ + var x1, y1, x2, y2; + var y3; + + // Intersect with vertical line through (x, y) + var up = 0; + var down = 0; + for( var i = 0; i < points.length / 2; i++ ){ + + x1 = points[ i * 2]; + y1 = points[ i * 2 + 1]; + + if( i + 1 < points.length / 2 ){ + x2 = points[ (i + 1) * 2]; + y2 = points[ (i + 1) * 2 + 1]; + } else { + x2 = points[ (i + 1 - points.length / 2) * 2]; + y2 = points[ (i + 1 - points.length / 2) * 2 + 1]; + } + + if( x1 == x && x2 == x ){ + // then ignore + } else if( (x1 >= x && x >= x2) + || (x1 <= x && x <= x2) ){ + + y3 = (x - x1) / (x2 - x1) * (y2 - y1) + y1; + + if( y3 > y ){ + up++; + } + + if( y3 < y ){ + down++; + } + + } else { + continue; + } + + } + + if( up % 2 === 0 ){ + return false; + } else { + return true; + } +}; + +math.pointInsidePolygon = function( + x, y, basePoints, centerX, centerY, width, height, direction, padding ){ + + //var direction = arguments[6]; + var transformedPoints = new Array( basePoints.length ); + + // Gives negative angle + var angle; + + if( direction[0] != null ){ + angle = Math.atan( direction[1] / direction[0] ); + + if( direction[0] < 0 ){ + angle = angle + Math.PI / 2; + } else { + angle = -angle - Math.PI / 2; + } + } else { + angle = direction; + } + + var cos = Math.cos( -angle ); + var sin = Math.sin( -angle ); + + // console.log("base: " + basePoints); + for( var i = 0; i < transformedPoints.length / 2; i++ ){ + transformedPoints[ i * 2] = + width / 2 * (basePoints[ i * 2] * cos + - basePoints[ i * 2 + 1] * sin); + + transformedPoints[ i * 2 + 1] = + height / 2 * (basePoints[ i * 2 + 1] * cos + + basePoints[ i * 2] * sin); + + transformedPoints[ i * 2] += centerX; + transformedPoints[ i * 2 + 1] += centerY; + } + + var points; + + if( padding > 0 ){ + var expandedLineSet = this.expandPolygon( + transformedPoints, + -padding ); + + points = this.joinLines( expandedLineSet ); + } else { + points = transformedPoints; + } + + return math.pointInsidePolygonPoints( x, y, points ); +}; + +math.joinLines = function( lineSet ){ + + var vertices = new Array( lineSet.length / 2 ); + + var currentLineStartX, currentLineStartY, currentLineEndX, currentLineEndY; + var nextLineStartX, nextLineStartY, nextLineEndX, nextLineEndY; + + for( var i = 0; i < lineSet.length / 4; i++ ){ + currentLineStartX = lineSet[ i * 4]; + currentLineStartY = lineSet[ i * 4 + 1]; + currentLineEndX = lineSet[ i * 4 + 2]; + currentLineEndY = lineSet[ i * 4 + 3]; + + if( i < lineSet.length / 4 - 1 ){ + nextLineStartX = lineSet[ (i + 1) * 4]; + nextLineStartY = lineSet[ (i + 1) * 4 + 1]; + nextLineEndX = lineSet[ (i + 1) * 4 + 2]; + nextLineEndY = lineSet[ (i + 1) * 4 + 3]; + } else { + nextLineStartX = lineSet[0]; + nextLineStartY = lineSet[1]; + nextLineEndX = lineSet[2]; + nextLineEndY = lineSet[3]; + } + + var intersection = this.finiteLinesIntersect( + currentLineStartX, currentLineStartY, + currentLineEndX, currentLineEndY, + nextLineStartX, nextLineStartY, + nextLineEndX, nextLineEndY, + true ); + + vertices[ i * 2] = intersection[0]; + vertices[ i * 2 + 1] = intersection[1]; + } + + return vertices; +}; + +math.expandPolygon = function( points, pad ){ + + var expandedLineSet = new Array( points.length * 2 ); + + var currentPointX, currentPointY, nextPointX, nextPointY; + + for( var i = 0; i < points.length / 2; i++ ){ + currentPointX = points[ i * 2]; + currentPointY = points[ i * 2 + 1]; + + if( i < points.length / 2 - 1 ){ + nextPointX = points[ (i + 1) * 2]; + nextPointY = points[ (i + 1) * 2 + 1]; + } else { + nextPointX = points[0]; + nextPointY = points[1]; + } + + // Current line: [currentPointX, currentPointY] to [nextPointX, nextPointY] + + // Assume CCW polygon winding + + var offsetX = (nextPointY - currentPointY); + var offsetY = -(nextPointX - currentPointX); + + // Normalize + var offsetLength = Math.sqrt( offsetX * offsetX + offsetY * offsetY ); + var normalizedOffsetX = offsetX / offsetLength; + var normalizedOffsetY = offsetY / offsetLength; + + expandedLineSet[ i * 4] = currentPointX + normalizedOffsetX * pad; + expandedLineSet[ i * 4 + 1] = currentPointY + normalizedOffsetY * pad; + expandedLineSet[ i * 4 + 2] = nextPointX + normalizedOffsetX * pad; + expandedLineSet[ i * 4 + 3] = nextPointY + normalizedOffsetY * pad; + } + + return expandedLineSet; +}; + +math.intersectLineEllipse = function( + x, y, centerX, centerY, ellipseWradius, ellipseHradius ){ + + var dispX = centerX - x; + var dispY = centerY - y; + + dispX /= ellipseWradius; + dispY /= ellipseHradius; + + var len = Math.sqrt( dispX * dispX + dispY * dispY ); + + var newLength = len - 1; + + if( newLength < 0 ){ + return []; + } + + var lenProportion = newLength / len; + + return [ (centerX - x) * lenProportion + x, (centerY - y) * lenProportion + y ]; +}; + +// Returns intersections of increasing distance from line's start point +math.intersectLineCircle = function( + x1, y1, x2, y2, centerX, centerY, radius ){ + + // Calculate d, direction vector of line + var d = [ x2 - x1, y2 - y1 ]; // Direction vector of line + var c = [ centerX, centerY ]; // Center of circle + var f = [ x1 - centerX, y1 - centerY ]; + + var a = d[0] * d[0] + d[1] * d[1]; + var b = 2 * (f[0] * d[0] + f[1] * d[1]); + var c = (f[0] * f[0] + f[1] * f[1]) - radius * radius ; + + var discriminant = b * b - 4 * a * c; + + if( discriminant < 0 ){ + return []; + } + + var t1 = (-b + Math.sqrt( discriminant )) / (2 * a); + var t2 = (-b - Math.sqrt( discriminant )) / (2 * a); + + var tMin = Math.min( t1, t2 ); + var tMax = Math.max( t1, t2 ); + var inRangeParams = []; + + if( tMin >= 0 && tMin <= 1 ){ + inRangeParams.push( tMin ); + } + + if( tMax >= 0 && tMax <= 1 ){ + inRangeParams.push( tMax ); + } + + if( inRangeParams.length === 0 ){ + return []; + } + + var nearIntersectionX = inRangeParams[0] * d[0] + x1; + var nearIntersectionY = inRangeParams[0] * d[1] + y1; + + if( inRangeParams.length > 1 ){ + + if( inRangeParams[0] == inRangeParams[1] ){ + return [ nearIntersectionX, nearIntersectionY ]; + } else { + + var farIntersectionX = inRangeParams[1] * d[0] + x1; + var farIntersectionY = inRangeParams[1] * d[1] + y1; + + return [ nearIntersectionX, nearIntersectionY, farIntersectionX, farIntersectionY ]; + } + + } else { + return [ nearIntersectionX, nearIntersectionY ]; + } + +}; + +math.findCircleNearPoint = function( centerX, centerY, + radius, farX, farY ){ + + var displacementX = farX - centerX; + var displacementY = farY - centerY; + var distance = Math.sqrt( displacementX * displacementX + + displacementY * displacementY ); + + var unitDisplacementX = displacementX / distance; + var unitDisplacementY = displacementY / distance; + + return [ centerX + unitDisplacementX * radius, + centerY + unitDisplacementY * radius ]; +}; + +math.findMaxSqDistanceToOrigin = function( points ){ + var maxSqDistance = 0.000001; + var sqDistance; + + for( var i = 0; i < points.length / 2; i++ ){ + + sqDistance = points[ i * 2] * points[ i * 2] + + points[ i * 2 + 1] * points[ i * 2 + 1]; + + if( sqDistance > maxSqDistance ){ + maxSqDistance = sqDistance; + } + } + + return maxSqDistance; +}; + +math.midOfThree = function( a, b, c ){ + if( (b <= a && a <= c) || (c <= a && a <= b) ){ + return a; + } else if( (a <= b && b <= c) || (c <= b && b <= a) ){ + return b; + } else { + return c; + } +}; + +math.finiteLinesIntersect = function( x1, y1, x2, y2, x3, y3, x4, y4, infiniteLines ){ + + var dx13 = x1 - x3; + var dx21 = x2 - x1; + var dx43 = x4 - x3; + + var dy13 = y1 - y3; + var dy21 = y2 - y1; + var dy43 = y4 - y3; + + var ua_t = dx43 * dy13 - dy43 * dx13; + var ub_t = dx21 * dy13 - dy21 * dx13; + var u_b = dy43 * dx21 - dx43 * dy21; + + if( u_b !== 0 ){ + var ua = ua_t / u_b; + var ub = ub_t / u_b; + + var flptThreshold = 0.001; + var min = 0 - flptThreshold; + var max = 1 + flptThreshold; + + if( min <= ua && ua <= max && min <= ub && ub <= max ){ + return [ x1 + ua * dx21, y1 + ua * dy21 ]; + + } else { + if( !infiniteLines ){ + return []; + } else { + return [ x1 + ua * dx21, y1 + ua * dy21 ]; + } + } + } else { + if( ua_t === 0 || ub_t === 0 ){ + + // Parallel, coincident lines. Check if overlap + + // Check endpoint of second line + if( this.midOfThree( x1, x2, x4 ) === x4 ){ + return [ x4, y4 ]; + } + + // Check start point of second line + if( this.midOfThree( x1, x2, x3 ) === x3 ){ + return [ x3, y3 ]; + } + + // Endpoint of first line + if( this.midOfThree( x3, x4, x2 ) === x2 ){ + return [ x2, y2 ]; + } + + return []; + } else { + + // Parallel, non-coincident + return []; + } + } +}; + +math.polygonIntersectLine = function( + x, y, basePoints, centerX, centerY, width, height, padding ){ + + var intersections = []; + var intersection; + + var transformedPoints = new Array( basePoints.length ); + + for( var i = 0; i < transformedPoints.length / 2; i++ ){ + transformedPoints[ i * 2] = basePoints[ i * 2] * width + centerX; + transformedPoints[ i * 2 + 1] = basePoints[ i * 2 + 1] * height + centerY; + } + + var points; + + if( padding > 0 ){ + var expandedLineSet = math.expandPolygon( + transformedPoints, + -padding ); + + points = math.joinLines( expandedLineSet ); + } else { + points = transformedPoints; + } + // var points = transformedPoints; + + var currentX, currentY, nextX, nextY; + + for( var i = 0; i < points.length / 2; i++ ){ + + currentX = points[ i * 2]; + currentY = points[ i * 2 + 1]; + + if( i < points.length / 2 - 1 ){ + nextX = points[ (i + 1) * 2]; + nextY = points[ (i + 1) * 2 + 1]; + } else { + nextX = points[0]; + nextY = points[1]; + } + + intersection = this.finiteLinesIntersect( + x, y, centerX, centerY, + currentX, currentY, + nextX, nextY ); + + if( intersection.length !== 0 ){ + intersections.push( intersection[0], intersection[1] ); + } + } + + return intersections; +}; + +math.shortenIntersection = function( + intersection, offset, amount ){ + + var disp = [ intersection[0] - offset[0], intersection[1] - offset[1] ]; + + var length = Math.sqrt( disp[0] * disp[0] + disp[1] * disp[1] ); + + var lenRatio = (length - amount) / length; + + if( lenRatio < 0 ){ + lenRatio = 0.00001; + } + + return [ offset[0] + lenRatio * disp[0], offset[1] + lenRatio * disp[1] ]; +}; + +math.generateUnitNgonPointsFitToSquare = function( sides, rotationRadians ){ + var points = math.generateUnitNgonPoints( sides, rotationRadians ); + points = math.fitPolygonToSquare( points ); + + return points; +}; + +math.fitPolygonToSquare = function( points ){ + var x, y; + var sides = points.length / 2; + var minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity; + + for( var i = 0; i < sides; i++ ){ + x = points[2 * i ]; + y = points[2 * i + 1]; + + minX = Math.min( minX, x ); + maxX = Math.max( maxX, x ); + minY = Math.min( minY, y ); + maxY = Math.max( maxY, y ); + } + + // stretch factors + var sx = 2 / (maxX - minX); + var sy = 2 / (maxY - minY); + + for( var i = 0; i < sides; i++ ){ + x = points[2 * i ] = points[2 * i ] * sx; + y = points[2 * i + 1] = points[2 * i + 1] * sy; + + minX = Math.min( minX, x ); + maxX = Math.max( maxX, x ); + minY = Math.min( minY, y ); + maxY = Math.max( maxY, y ); + } + + if( minY < -1 ){ + for( var i = 0; i < sides; i++ ){ + y = points[2 * i + 1] = points[2 * i + 1] + (-1 - minY); + } + } + + return points; +}; + +math.generateUnitNgonPoints = function( sides, rotationRadians ){ + + var increment = 1.0 / sides * 2 * Math.PI; + var startAngle = sides % 2 === 0 ? + Math.PI / 2.0 + increment / 2.0 : Math.PI / 2.0; + // console.log(nodeShapes['square']); + startAngle += rotationRadians; + + var points = new Array( sides * 2 ); + + var currentAngle, x, y; + for( var i = 0; i < sides; i++ ){ + currentAngle = i * increment + startAngle; + + x = points[2 * i ] = Math.cos( currentAngle );// * (1 + i/2); + y = points[2 * i + 1] = Math.sin( -currentAngle );// * (1 + i/2); + } + + return points; +}; + +math.getRoundRectangleRadius = function( width, height ){ + + // Set the default radius, unless half of width or height is smaller than default + return Math.min( width / 4, height / 4, 8 ); +}; + +module.exports = math; + +},{}],86:[function(_dereq_,module,exports){ +/*! +Embeddable Minimum Strictly-Compliant Promises/A+ 1.1.1 Thenable +Copyright (c) 2013-2014 Ralf S. Engelschall (http://engelschall.com) +Licensed under The MIT License (http://opensource.org/licenses/MIT) +*/ + +'use strict'; + +/* promise states [Promises/A+ 2.1] */ +var STATE_PENDING = 0; /* [Promises/A+ 2.1.1] */ +var STATE_FULFILLED = 1; /* [Promises/A+ 2.1.2] */ +var STATE_REJECTED = 2; /* [Promises/A+ 2.1.3] */ + +/* promise object constructor */ +var api = function( executor ){ + /* optionally support non-constructor/plain-function call */ + if( !(this instanceof api) ) + return new api( executor ); + + /* initialize object */ + this.id = 'Thenable/1.0.7'; + this.state = STATE_PENDING; /* initial state */ + this.fulfillValue = undefined; /* initial value */ /* [Promises/A+ 1.3, 2.1.2.2] */ + this.rejectReason = undefined; /* initial reason */ /* [Promises/A+ 1.5, 2.1.3.2] */ + this.onFulfilled = []; /* initial handlers */ + this.onRejected = []; /* initial handlers */ + + /* provide optional information-hiding proxy */ + this.proxy = { + then: this.then.bind( this ) + }; + + /* support optional executor function */ + if( typeof executor === 'function' ) + executor.call( this, this.fulfill.bind( this ), this.reject.bind( this ) ); +}; + +/* promise API methods */ +api.prototype = { + /* promise resolving methods */ + fulfill: function( value ){ return deliver( this, STATE_FULFILLED, 'fulfillValue', value ); }, + reject: function( value ){ return deliver( this, STATE_REJECTED, 'rejectReason', value ); }, + + /* "The then Method" [Promises/A+ 1.1, 1.2, 2.2] */ + then: function( onFulfilled, onRejected ){ + var curr = this; + var next = new api(); /* [Promises/A+ 2.2.7] */ + curr.onFulfilled.push( + resolver( onFulfilled, next, 'fulfill' ) ); /* [Promises/A+ 2.2.2/2.2.6] */ + curr.onRejected.push( + resolver( onRejected, next, 'reject' ) ); /* [Promises/A+ 2.2.3/2.2.6] */ + execute( curr ); + return next.proxy; /* [Promises/A+ 2.2.7, 3.3] */ + } +}; + +/* deliver an action */ +var deliver = function( curr, state, name, value ){ + if( curr.state === STATE_PENDING ){ + curr.state = state; /* [Promises/A+ 2.1.2.1, 2.1.3.1] */ + curr[ name ] = value; /* [Promises/A+ 2.1.2.2, 2.1.3.2] */ + execute( curr ); + } + return curr; +}; + +/* execute all handlers */ +var execute = function( curr ){ + if( curr.state === STATE_FULFILLED ) + execute_handlers( curr, 'onFulfilled', curr.fulfillValue ); + else if( curr.state === STATE_REJECTED ) + execute_handlers( curr, 'onRejected', curr.rejectReason ); +}; + +/* execute particular set of handlers */ +var execute_handlers = function( curr, name, value ){ + /* global setImmediate: true */ + /* global setTimeout: true */ + + /* short-circuit processing */ + if( curr[ name ].length === 0 ) + return; + + /* iterate over all handlers, exactly once */ + var handlers = curr[ name ]; + curr[ name ] = []; /* [Promises/A+ 2.2.2.3, 2.2.3.3] */ + var func = function(){ + for( var i = 0; i < handlers.length; i++ ) + handlers[ i ]( value ); /* [Promises/A+ 2.2.5] */ + }; + + /* execute procedure asynchronously */ /* [Promises/A+ 2.2.4, 3.1] */ + if( typeof setImmediate === 'function' ) + setImmediate( func ); + else + setTimeout( func, 0 ); +}; + +/* generate a resolver function */ +var resolver = function( cb, next, method ){ + return function( value ){ + if( typeof cb !== 'function' ) /* [Promises/A+ 2.2.1, 2.2.7.3, 2.2.7.4] */ + next[ method ].call( next, value ); /* [Promises/A+ 2.2.7.3, 2.2.7.4] */ + else { + var result; + try { result = cb( value ); } /* [Promises/A+ 2.2.2.1, 2.2.3.1, 2.2.5, 3.2] */ + catch( e ){ + next.reject( e ); /* [Promises/A+ 2.2.7.2] */ + return; + } + resolve( next, result ); /* [Promises/A+ 2.2.7.1] */ + } + }; +}; + +/* "Promise Resolution Procedure" */ /* [Promises/A+ 2.3] */ +var resolve = function( promise, x ){ + /* sanity check arguments */ /* [Promises/A+ 2.3.1] */ + if( promise === x || promise.proxy === x ){ + promise.reject( new TypeError( 'cannot resolve promise with itself' ) ); + return; + } + + /* surgically check for a "then" method + (mainly to just call the "getter" of "then" only once) */ + var then; + if( (typeof x === 'object' && x !== null) || typeof x === 'function' ){ + try { then = x.then; } /* [Promises/A+ 2.3.3.1, 3.5] */ + catch( e ){ + promise.reject( e ); /* [Promises/A+ 2.3.3.2] */ + return; + } + } + + /* handle own Thenables [Promises/A+ 2.3.2] + and similar "thenables" [Promises/A+ 2.3.3] */ + if( typeof then === 'function' ){ + var resolved = false; + try { + /* call retrieved "then" method */ /* [Promises/A+ 2.3.3.3] */ + then.call( x, + /* resolvePromise */ /* [Promises/A+ 2.3.3.3.1] */ + function( y ){ + if( resolved ) return; resolved = true; /* [Promises/A+ 2.3.3.3.3] */ + if( y === x ) /* [Promises/A+ 3.6] */ + promise.reject( new TypeError( 'circular thenable chain' ) ); + else + resolve( promise, y ); + }, + + /* rejectPromise */ /* [Promises/A+ 2.3.3.3.2] */ + function( r ){ + if( resolved ) return; resolved = true; /* [Promises/A+ 2.3.3.3.3] */ + promise.reject( r ); + } + ); + } + catch( e ){ + if( !resolved ) /* [Promises/A+ 2.3.3.3.3] */ + promise.reject( e ); /* [Promises/A+ 2.3.3.3.4] */ + } + return; + } + + /* handle other values */ + promise.fulfill( x ); /* [Promises/A+ 2.3.4, 2.3.3.4] */ +}; + +// so we always have Promise.all() +api.all = function( ps ){ + return new api(function( resolveAll, rejectAll ){ + var vals = new Array( ps.length ); + var doneCount = 0; + + var fulfill = function( i, val ){ + vals[ i ] = val; + doneCount++; + + if( doneCount === ps.length ){ + resolveAll( vals ); + } + }; + + for( var i = 0; i < ps.length; i++ ){ + (function( i ){ + var p = ps[i]; + var isPromise = p != null && p.then != null; + + if( isPromise ){ + p.then( function( val ){ + fulfill( i, val ); + }, function( err ){ + rejectAll( err ); + } ); + } else { + var val = p; + fulfill( i, val ); + } + })( i ); + } + + } ); +}; + +api.resolve = function( val ){ + return new api(function( resolve, reject ){ resolve( val ); }); +}; + +api.reject = function( val ){ + return new api(function( resolve, reject ){ reject( val ); }); +}; + +module.exports = typeof Promise !== 'undefined' ? Promise : api; // eslint-disable-line no-undef + +},{}],87:[function(_dereq_,module,exports){ +'use strict'; + +var is = _dereq_( './is' ); +var util = _dereq_( './util' ); + +var Selector = function( selector ){ + + if( !(this instanceof Selector) ){ + return new Selector( selector ); + } + + var self = this; + + self._private = { + selectorText: null, + invalid: true + }; + + // storage for parsed queries + var newQuery = function(){ + return { + classes: [], + colonSelectors: [], + data: [], + group: null, + ids: [], + meta: [], + + // fake selectors + collection: null, // a collection to match against + filter: null, // filter function + + // these are defined in the upward direction rather than down (e.g. child) + // because we need to go up in Selector.filter() + parent: null, // parent query obj + ancestor: null, // ancestor query obj + subject: null, // defines subject in compound query (subject query obj; points to self if subject) + + // use these only when subject has been defined + child: null, + descendant: null + }; + }; + + if( !selector || ( is.string( selector ) && selector.match( /^\s*$/ ) ) ){ + + self.length = 0; + + } else if( selector === '*' || selector === 'edge' || selector === 'node' ){ + + // make single, group-only selectors cheap to make and cheap to filter + + self[0] = newQuery(); + self[0].group = selector === '*' ? selector : selector + 's'; + self[0].groupOnly = true; + self._private.invalid = false; + self._private.selectorText = selector; + self.length = 1; + + } else if( is.elementOrCollection( selector ) ){ + + var collection = selector.collection(); + + self[0] = newQuery(); + self[0].collection = collection; + self.length = 1; + + } else if( is.fn( selector ) ){ + + self[0] = newQuery(); + self[0].filter = selector; + self.length = 1; + + } else if( is.string( selector ) ){ + + // the current subject in the query + var currentSubject = null; + + // tokens in the query language + var tokens = { + metaChar: '[\\!\\"\\#\\$\\%\\&\\\'\\(\\)\\*\\+\\,\\.\\/\\:\\;\\<\\=\\>\\?\\@\\[\\]\\^\\`\\{\\|\\}\\~]', // chars we need to escape in var names, etc + comparatorOp: '=|\\!=|>|>=|<|<=|\\$=|\\^=|\\*=', // binary comparison op (used in data selectors) + boolOp: '\\?|\\!|\\^', // boolean (unary) operators (used in data selectors) + string: '"(?:\\\\"|[^"])+"' + '|' + "'(?:\\\\'|[^'])+'", // string literals (used in data selectors) -- doublequotes | singlequotes + number: util.regex.number, // number literal (used in data selectors) --- e.g. 0.1234, 1234, 12e123 + meta: 'degree|indegree|outdegree', // allowed metadata fields (i.e. allowed functions to use from Collection) + separator: '\\s*,\\s*', // queries are separated by commas, e.g. edge[foo = 'bar'], node.someClass + descendant: '\\s+', + child: '\\s+>\\s+', + subject: '\\$' + }; + tokens.variable = '(?:[\\w-]|(?:\\\\' + tokens.metaChar + '))+'; // a variable name + tokens.value = tokens.string + '|' + tokens.number; // a value literal, either a string or number + tokens.className = tokens.variable; // a class name (follows variable conventions) + tokens.id = tokens.variable; // an element id (follows variable conventions) + + // when a token like a variable has escaped meta characters, we need to clean the backslashes out + // so that values get compared properly in Selector.filter() + var cleanMetaChars = function( str ){ + return str.replace( new RegExp( '\\\\(' + tokens.metaChar + ')', 'g' ), function( match, $1, offset, original ){ + return $1; + } ); + }; + + // add @ variants to comparatorOp + var ops = tokens.comparatorOp.split( '|' ); + for( var i = 0; i < ops.length; i++ ){ + var op = ops[ i ]; + tokens.comparatorOp += '|@' + op; + } + + // add ! variants to comparatorOp + var ops = tokens.comparatorOp.split( '|' ); + for( var i = 0; i < ops.length; i++ ){ + var op = ops[ i ]; + + if( op.indexOf( '!' ) >= 0 ){ continue; } // skip ops that explicitly contain ! + if( op === '=' ){ continue; } // skip = b/c != is explicitly defined + + tokens.comparatorOp += '|\\!' + op; + } + + // NOTE: add new expression syntax here to have it recognised by the parser; + // - a query contains all adjacent (i.e. no separator in between) expressions; + // - the current query is stored in self[i] --- you can use the reference to `this` in the populate function; + // - you need to check the query objects in Selector.filter() for it actually filter properly, but that's pretty straight forward + // - when you add something here, also add to Selector.toString() + var exprs = [ + { + name: 'group', + query: true, + regex: '(node|edge|\\*)', + populate: function( group ){ + this.group = group === '*' ? group : group + 's'; + } + }, + + { + name: 'state', + query: true, + // NB: if one colon selector is a substring of another from its start, place the longer one first + // e.g. :foobar|:foo + regex: '(:selected|:unselected|:locked|:unlocked|:visible|:hidden|:transparent|:grabbed|:free|:removed|:inside|:grabbable|:ungrabbable|:animated|:unanimated|:selectable|:unselectable|:orphan|:nonorphan|:parent|:child|:loop|:simple|:active|:inactive|:touch|:backgrounding|:nonbackgrounding)', + populate: function( state ){ + this.colonSelectors.push( state ); + } + }, + + { + name: 'id', + query: true, + regex: '\\#(' + tokens.id + ')', + populate: function( id ){ + this.ids.push( cleanMetaChars( id ) ); + } + }, + + { + name: 'className', + query: true, + regex: '\\.(' + tokens.className + ')', + populate: function( className ){ + this.classes.push( cleanMetaChars( className ) ); + } + }, + + { + name: 'dataExists', + query: true, + regex: '\\[\\s*(' + tokens.variable + ')\\s*\\]', + populate: function( variable ){ + this.data.push( { + field: cleanMetaChars( variable ) + } ); + } + }, + + { + name: 'dataCompare', + query: true, + regex: '\\[\\s*(' + tokens.variable + ')\\s*(' + tokens.comparatorOp + ')\\s*(' + tokens.value + ')\\s*\\]', + populate: function( variable, comparatorOp, value ){ + var valueIsString = new RegExp( '^' + tokens.string + '$' ).exec( value ) != null; + + if( valueIsString ){ + value = value.substring( 1, value.length - 1 ); + } else { + value = parseFloat( value ); + } + + this.data.push( { + field: cleanMetaChars( variable ), + operator: comparatorOp, + value: value + } ); + } + }, + + { + name: 'dataBool', + query: true, + regex: '\\[\\s*(' + tokens.boolOp + ')\\s*(' + tokens.variable + ')\\s*\\]', + populate: function( boolOp, variable ){ + this.data.push( { + field: cleanMetaChars( variable ), + operator: boolOp + } ); + } + }, + + { + name: 'metaCompare', + query: true, + regex: '\\[\\[\\s*(' + tokens.meta + ')\\s*(' + tokens.comparatorOp + ')\\s*(' + tokens.number + ')\\s*\\]\\]', + populate: function( meta, comparatorOp, number ){ + this.meta.push( { + field: cleanMetaChars( meta ), + operator: comparatorOp, + value: parseFloat( number ) + } ); + } + }, + + { + name: 'nextQuery', + separator: true, + regex: tokens.separator, + populate: function(){ + // go on to next query + self[ ++i ] = newQuery(); + currentSubject = null; + } + }, + + { + name: 'child', + separator: true, + regex: tokens.child, + populate: function(){ + // this query is the parent of the following query + var childQuery = newQuery(); + childQuery.parent = this; + childQuery.subject = currentSubject; + + // we're now populating the child query with expressions that follow + self[ i ] = childQuery; + } + }, + + { + name: 'descendant', + separator: true, + regex: tokens.descendant, + populate: function(){ + // this query is the ancestor of the following query + var descendantQuery = newQuery(); + descendantQuery.ancestor = this; + descendantQuery.subject = currentSubject; + + // we're now populating the descendant query with expressions that follow + self[ i ] = descendantQuery; + } + }, + + { + name: 'subject', + modifier: true, + regex: tokens.subject, + populate: function(){ + if( currentSubject != null && this.subject != this ){ + util.error( 'Redefinition of subject in selector `' + selector + '`' ); + return false; + } + + currentSubject = this; + this.subject = this; + } + + } + ]; + + self._private.selectorText = selector; + var remaining = selector; + var i = 0; + + // of all the expressions, find the first match in the remaining text + var consumeExpr = function( expectation ){ + var expr; + var match; + var name; + + for( var j = 0; j < exprs.length; j++ ){ + var e = exprs[ j ]; + var n = e.name; + + // ignore this expression if it doesn't meet the expectation function + if( is.fn( expectation ) && !expectation( n, e ) ){ continue; } + + var m = remaining.match( new RegExp( '^' + e.regex ) ); + + if( m != null ){ + match = m; + expr = e; + name = n; + + var consumed = m[0]; + remaining = remaining.substring( consumed.length ); + + break; // we've consumed one expr, so we can return now + } + } + + return { + expr: expr, + match: match, + name: name + }; + }; + + // consume all leading whitespace + var consumeWhitespace = function(){ + var match = remaining.match( /^\s+/ ); + + if( match ){ + var consumed = match[0]; + remaining = remaining.substring( consumed.length ); + } + }; + + self[0] = newQuery(); // get started + + consumeWhitespace(); // get rid of leading whitespace + for( ;; ){ + var check = consumeExpr(); + + if( check.expr == null ){ + util.error( 'The selector `' + selector + '`is invalid' ); + return; + } else { + var args = []; + for( var j = 1; j < check.match.length; j++ ){ + args.push( check.match[ j ] ); + } + + // let the token populate the selector object (i.e. in self[i]) + var ret = check.expr.populate.apply( self[ i ], args ); + + if( ret === false ){ return; } // exit if population failed + } + + // we're done when there's nothing left to parse + if( remaining.match( /^\s*$/ ) ){ + break; + } + } + + self.length = i + 1; + + // adjust references for subject + for( var j = 0; j < self.length; j++ ){ + var query = self[ j ]; + + if( query.subject != null ){ + // go up the tree until we reach the subject + for( ;; ){ + if( query.subject == query ){ break; } // done if subject is self + + if( query.parent != null ){ // swap parent/child reference + var parent = query.parent; + var child = query; + + child.parent = null; + parent.child = child; + + query = parent; // go up the tree + } else if( query.ancestor != null ){ // swap ancestor/descendant + var ancestor = query.ancestor; + var descendant = query; + + descendant.ancestor = null; + ancestor.descendant = descendant; + + query = ancestor; // go up the tree + } else { + util.error( 'When adjusting references for the selector `' + query + '`, neither parent nor ancestor was found' ); + break; + } + } // for + + self[ j ] = query.subject; // subject should be the root query + } // if + } // for + + } else { + util.error( 'A selector must be created from a string; found ' + selector ); + return; + } + + self._private.invalid = false; + +}; + +var selfn = Selector.prototype; + +selfn.size = function(){ + return this.length; +}; + +selfn.eq = function( i ){ + return this[ i ]; +}; + +var queryMatches = function( query, ele ){ + var ele_p = ele._private; + + // make single group-only selectors really cheap to check since they're the most common ones + if( query.groupOnly ){ + return query.group === '*' || query.group === ele_p.group; + } + + // check group + if( query.group != null && query.group != '*' && query.group != ele_p.group ){ + return false; + } + + var cy = ele.cy(); + + // check colon selectors + var allColonSelectorsMatch = true; + for( var k = 0; k < query.colonSelectors.length; k++ ){ + var sel = query.colonSelectors[ k ]; + + switch( sel ){ + case ':selected': + allColonSelectorsMatch = ele.selected(); + break; + case ':unselected': + allColonSelectorsMatch = !ele.selected(); + break; + case ':selectable': + allColonSelectorsMatch = ele.selectable(); + break; + case ':unselectable': + allColonSelectorsMatch = !ele.selectable(); + break; + case ':locked': + allColonSelectorsMatch = ele.locked(); + break; + case ':unlocked': + allColonSelectorsMatch = !ele.locked(); + break; + case ':visible': + allColonSelectorsMatch = ele.visible(); + break; + case ':hidden': + allColonSelectorsMatch = !ele.visible(); + break; + case ':transparent': + allColonSelectorsMatch = ele.transparent(); + break; + case ':grabbed': + allColonSelectorsMatch = ele.grabbed(); + break; + case ':free': + allColonSelectorsMatch = !ele.grabbed(); + break; + case ':removed': + allColonSelectorsMatch = ele.removed(); + break; + case ':inside': + allColonSelectorsMatch = !ele.removed(); + break; + case ':grabbable': + allColonSelectorsMatch = ele.grabbable(); + break; + case ':ungrabbable': + allColonSelectorsMatch = !ele.grabbable(); + break; + case ':animated': + allColonSelectorsMatch = ele.animated(); + break; + case ':unanimated': + allColonSelectorsMatch = !ele.animated(); + break; + case ':parent': + allColonSelectorsMatch = ele.isNode() && ele.children().nonempty(); + break; + case ':child': + case ':nonorphan': + allColonSelectorsMatch = ele.isNode() && ele.parent().nonempty(); + break; + case ':orphan': + allColonSelectorsMatch = ele.isNode() && ele.parent().empty(); + break; + case ':loop': + allColonSelectorsMatch = ele.isEdge() && ele.data( 'source' ) === ele.data( 'target' ); + break; + case ':simple': + allColonSelectorsMatch = ele.isEdge() && ele.data( 'source' ) !== ele.data( 'target' ); + break; + case ':active': + allColonSelectorsMatch = ele.active(); + break; + case ':inactive': + allColonSelectorsMatch = !ele.active(); + break; + case ':touch': + allColonSelectorsMatch = is.touch(); + break; + case ':backgrounding': + allColonSelectorsMatch = ele.backgrounding(); + break; + case ':nonbackgrounding': + allColonSelectorsMatch = !ele.backgrounding(); + break; + } + + if( !allColonSelectorsMatch ) break; + } + if( !allColonSelectorsMatch ) return false; + + // check id + var allIdsMatch = true; + for( var k = 0; k < query.ids.length; k++ ){ + var id = query.ids[ k ]; + var actualId = ele_p.data.id; + + allIdsMatch = allIdsMatch && (id == actualId); + + if( !allIdsMatch ) break; + } + if( !allIdsMatch ) return false; + + // check classes + var allClassesMatch = true; + for( var k = 0; k < query.classes.length; k++ ){ + var cls = query.classes[ k ]; + + allClassesMatch = allClassesMatch && ele.hasClass( cls ); + + if( !allClassesMatch ) break; + } + if( !allClassesMatch ) return false; + + // generic checking for data/metadata + var operandsMatch = function( params ){ + var allDataMatches = true; + for( var k = 0; k < query[ params.name ].length; k++ ){ + var data = query[ params.name ][ k ]; + var operator = data.operator; + var value = data.value; + var field = data.field; + var matches; + + if( operator != null && value != null ){ + + var fieldVal = params.fieldValue( field ); + var fieldStr = !is.string( fieldVal ) && !is.number( fieldVal ) ? '' : '' + fieldVal; + var valStr = '' + value; + + var caseInsensitive = false; + if( operator.indexOf( '@' ) >= 0 ){ + fieldStr = fieldStr.toLowerCase(); + valStr = valStr.toLowerCase(); + + operator = operator.replace( '@', '' ); + caseInsensitive = true; + } + + var notExpr = false; + if( operator.indexOf( '!' ) >= 0 ){ + operator = operator.replace( '!', '' ); + notExpr = true; + } + + // if we're doing a case insensitive comparison, then we're using a STRING comparison + // even if we're comparing numbers + if( caseInsensitive ){ + value = valStr.toLowerCase(); + fieldVal = fieldStr.toLowerCase(); + } + + var isIneqCmp = false; + + switch( operator ){ + case '*=': + matches = fieldStr.indexOf( valStr ) >= 0; + break; + case '$=': + matches = fieldStr.indexOf( valStr, fieldStr.length - valStr.length ) >= 0; + break; + case '^=': + matches = fieldStr.indexOf( valStr ) === 0; + break; + case '=': + matches = fieldVal === value; + break; + case '>': + isIneqCmp = true; + matches = fieldVal > value; + break; + case '>=': + isIneqCmp = true; + matches = fieldVal >= value; + break; + case '<': + isIneqCmp = true; + matches = fieldVal < value; + break; + case '<=': + isIneqCmp = true; + matches = fieldVal <= value; + break; + default: + matches = false; + break; + } + + // apply the not op, but null vals for inequalities should always stay non-matching + if( notExpr && ( fieldVal != null || !isIneqCmp ) ){ + matches = !matches; + } + } else if( operator != null ){ + switch( operator ){ + case '?': + matches = params.fieldTruthy( field ); + break; + case '!': + matches = !params.fieldTruthy( field ); + break; + case '^': + matches = params.fieldUndefined( field ); + break; + } + } else { + matches = !params.fieldUndefined( field ); + } + + if( !matches ){ + allDataMatches = false; + break; + } + } // for + + return allDataMatches; + }; // operandsMatch + + // check data matches + var allDataMatches = operandsMatch( { + name: 'data', + fieldValue: function( field ){ + return ele_p.data[ field ]; + }, + fieldUndefined: function( field ){ + return ele_p.data[ field ] === undefined; + }, + fieldTruthy: function( field ){ + if( ele_p.data[ field ] ){ + return true; + } + return false; + } + } ); + + if( !allDataMatches ){ + return false; + } + + // check metadata matches + var allMetaMatches = operandsMatch( { + name: 'meta', + fieldValue: function( field ){ + return ele[ field ](); + }, + fieldUndefined: function( field ){ + return ele[ field ]() == null; + }, + fieldTruthy: function( field ){ + if( ele[ field ]() ){ + return true; + } + return false; + } + } ); + + if( !allMetaMatches ){ + return false; + } + + // check collection + if( query.collection != null ){ + var matchesAny = query.collection.hasElementWithId( ele.id() ); + + if( !matchesAny ){ + return false; + } + } + + // check filter function + if( query.filter != null && ele.collection().filter( query.filter ).size() === 0 ){ + return false; + } + + // check parent/child relations + var confirmRelations = function( query, eles ){ + if( query != null ){ + var matches = false; + + if( !cy.hasCompoundNodes() ){ + return false; + } + + eles = eles(); // save cycles if query == null + + // query must match for at least one element (may be recursive) + for( var i = 0; i < eles.length; i++ ){ + if( queryMatches( query, eles[ i ] ) ){ + matches = true; + break; + } + } + + return matches; + } else { + return true; + } + }; + + if( !confirmRelations( query.parent, function(){ + return ele.parent(); + } ) ){ return false; } + + if( !confirmRelations( query.ancestor, function(){ + return ele.parents(); + } ) ){ return false; } + + if( !confirmRelations( query.child, function(){ + return ele.children(); + } ) ){ return false; } + + if( !confirmRelations( query.descendant, function(){ + return ele.descendants(); + } ) ){ return false; } + + // we've reached the end, so we've matched everything for this query + return true; +}; // queryMatches + +// filter an existing collection +selfn.filter = function( collection ){ + var self = this; + var cy = collection.cy(); + + // don't bother trying if it's invalid + if( self._private.invalid ){ + return cy.collection(); + } + + var selectorFunction = function( i, element ){ + for( var j = 0; j < self.length; j++ ){ + var query = self[ j ]; + + if( queryMatches( query, element ) ){ + return true; + } + } + + return false; + }; + + if( self._private.selectorText == null ){ + selectorFunction = function(){ return true; }; + } + + var filteredCollection = collection.filter( selectorFunction ); + + return filteredCollection; +}; // filter + +// does selector match a single element? +selfn.matches = function( ele ){ + var self = this; + + // don't bother trying if it's invalid + if( self._private.invalid ){ + return false; + } + + for( var j = 0; j < self.length; j++ ){ + var query = self[ j ]; + + if( queryMatches( query, ele ) ){ + return true; + } + } + + return false; +}; // filter + +// ith query to string +selfn.toString = selfn.selector = function(){ + + var str = ''; + + var clean = function( obj, isValue ){ + if( is.string( obj ) ){ + return isValue ? '"' + obj + '"' : obj; + } + return ''; + }; + + var queryToString = function( query ){ + var str = ''; + + if( query.subject === query ){ + str += '$'; + } + + var group = clean( query.group ); + str += group.substring( 0, group.length - 1 ); + + for( var j = 0; j < query.data.length; j++ ){ + var data = query.data[ j ]; + + if( data.value ){ + str += '[' + data.field + clean( data.operator ) + clean( data.value, true ) + ']'; + } else { + str += '[' + clean( data.operator ) + data.field + ']'; + } + } + + for( var j = 0; j < query.meta.length; j++ ){ + var meta = query.meta[ j ]; + str += '[[' + meta.field + clean( meta.operator ) + clean( meta.value, true ) + ']]'; + } + + for( var j = 0; j < query.colonSelectors.length; j++ ){ + var sel = query.colonSelectors[ i ]; + str += sel; + } + + for( var j = 0; j < query.ids.length; j++ ){ + var sel = '#' + query.ids[ i ]; + str += sel; + } + + for( var j = 0; j < query.classes.length; j++ ){ + var sel = '.' + query.classes[ j ]; + str += sel; + } + + if( query.parent != null ){ + str = queryToString( query.parent ) + ' > ' + str; + } + + if( query.ancestor != null ){ + str = queryToString( query.ancestor ) + ' ' + str; + } + + if( query.child != null ){ + str += ' > ' + queryToString( query.child ); + } + + if( query.descendant != null ){ + str += ' ' + queryToString( query.descendant ); + } + + return str; + }; + + for( var i = 0; i < this.length; i++ ){ + var query = this[ i ]; + + str += queryToString( query ); + + if( this.length > 1 && i < this.length - 1 ){ + str += ', '; + } + } + + return str; +}; + +module.exports = Selector; + +},{"./is":83,"./util":100}],88:[function(_dereq_,module,exports){ +'use strict'; + +var util = _dereq_( '../util' ); +var is = _dereq_( '../is' ); + +var styfn = {}; + +// (potentially expensive calculation) +// apply the style to the element based on +// - its bypass +// - what selectors match it +styfn.apply = function( eles ){ + var self = this; + var _p = self._private; + + if( _p.newStyle ){ // clear style caches + _p.contextStyles = {}; + _p.propDiffs = {}; + + self.cleanElements( eles, true ); + } + + for( var ie = 0; ie < eles.length; ie++ ){ + var ele = eles[ ie ]; + + var cxtMeta = self.getContextMeta( ele ); + var cxtStyle = self.getContextStyle( cxtMeta ); + var app = self.applyContextStyle( cxtMeta, cxtStyle, ele ); + + self.updateTransitions( ele, app.diffProps ); + self.updateStyleHints( ele ); + + } // for elements + + _p.newStyle = false; +}; + +styfn.getPropertiesDiff = function( oldCxtKey, newCxtKey ){ + var self = this; + var cache = self._private.propDiffs = self._private.propDiffs || {}; + var dualCxtKey = oldCxtKey + '-' + newCxtKey; + var cachedVal = cache[ dualCxtKey ]; + + if( cachedVal ){ + return cachedVal; + } + + var diffProps = []; + var addedProp = {}; + + for( var i = 0; i < self.length; i++ ){ + var cxt = self[ i ]; + var oldHasCxt = oldCxtKey[ i ] === 't'; + var newHasCxt = newCxtKey[ i ] === 't'; + var cxtHasDiffed = oldHasCxt !== newHasCxt; + var cxtHasMappedProps = cxt.mappedProperties.length > 0; + + if( cxtHasDiffed || cxtHasMappedProps ){ + var props; + + if( cxtHasDiffed && cxtHasMappedProps ){ + props = cxt.properties; // suffices b/c mappedProperties is a subset of properties + } else if( cxtHasDiffed ){ + props = cxt.properties; // need to check them all + } else if( cxtHasMappedProps ){ + props = cxt.mappedProperties; // only need to check mapped + } + + for( var j = 0; j < props.length; j++ ){ + var prop = props[ j ]; + var name = prop.name; + + // if a later context overrides this property, then the fact that this context has switched/diffed doesn't matter + // (semi expensive check since it makes this function O(n^2) on context length, but worth it since overall result + // is cached) + var laterCxtOverrides = false; + for( var k = i + 1; k < self.length; k++ ){ + var laterCxt = self[ k ]; + var hasLaterCxt = newCxtKey[ k ] === 't'; + + if( !hasLaterCxt ){ continue; } // can't override unless the context is active + + laterCxtOverrides = laterCxt.properties[ prop.name ] != null; + + if( laterCxtOverrides ){ break; } // exit early as long as one later context overrides + } + + if( !addedProp[ name ] && !laterCxtOverrides ){ + addedProp[ name ] = true; + diffProps.push( name ); + } + } // for props + } // if + + } // for contexts + + cache[ dualCxtKey ] = diffProps; + return diffProps; +}; + +styfn.getContextMeta = function( ele ){ + var self = this; + var cxtKey = ''; + var diffProps; + var prevKey = ele._private.styleCxtKey || ''; + + if( self._private.newStyle ){ + prevKey = ''; // since we need to apply all style if a fresh stylesheet + } + + // get the cxt key + for( var i = 0; i < self.length; i++ ){ + var context = self[ i ]; + var contextSelectorMatches = context.selector && context.selector.matches( ele ); // NB: context.selector may be null for 'core' + + if( contextSelectorMatches ){ + cxtKey += 't'; + } else { + cxtKey += 'f'; + } + } // for context + + diffProps = self.getPropertiesDiff( prevKey, cxtKey ); + + ele._private.styleCxtKey = cxtKey; + + return { + key: cxtKey, + diffPropNames: diffProps + }; +}; + +// gets a computed ele style object based on matched contexts +styfn.getContextStyle = function( cxtMeta ){ + var cxtKey = cxtMeta.key; + var self = this; + var cxtStyles = this._private.contextStyles = this._private.contextStyles || {}; + + // if already computed style, returned cached copy + if( cxtStyles[ cxtKey ] ){ return cxtStyles[ cxtKey ]; } + + var style = { + _private: { + key: cxtKey + } + }; + + for( var i = 0; i < self.length; i++ ){ + var cxt = self[ i ]; + var hasCxt = cxtKey[ i ] === 't'; + + if( !hasCxt ){ continue; } + + for( var j = 0; j < cxt.properties.length; j++ ){ + var prop = cxt.properties[ j ]; + var styProp = style[ prop.name ] = prop; + + styProp.context = cxt; + } + } + + cxtStyles[ cxtKey ] = style; + return style; +}; + +styfn.applyContextStyle = function( cxtMeta, cxtStyle, ele ){ + var self = this; + var diffProps = cxtMeta.diffPropNames; + var retDiffProps = {}; + + for( var i = 0; i < diffProps.length; i++ ){ + var diffPropName = diffProps[ i ]; + var cxtProp = cxtStyle[ diffPropName ]; + var eleProp = ele.pstyle( diffPropName ); + + if( !cxtProp ){ // no context prop means delete + if( eleProp.bypass ){ + cxtProp = { name: diffPropName, deleteBypassed: true }; + } else { + cxtProp = { name: diffPropName, delete: true }; + } + } + + // save cycles when the context prop doesn't need to be applied + if( eleProp === cxtProp ){ continue; } + + var retDiffProp = retDiffProps[ diffPropName ] = { + prev: eleProp + }; + + self.applyParsedProperty( ele, cxtProp ); + + retDiffProp.next = ele.pstyle( diffPropName ); + + if( retDiffProp.next && retDiffProp.next.bypass ){ + retDiffProp.next = retDiffProp.next.bypassed; + } + } + + return { + diffProps: retDiffProps + }; +}; + +styfn.updateStyleHints = function(ele){ + var _p = ele._private; + var self = this; + + if( ele.removed() ){ return; } + + // set whether has pie or not; for greater efficiency + var hasPie = false; + if( _p.group === 'nodes' ){ + for( var i = 1; i <= self.pieBackgroundN; i++ ){ // 1..N + var size = ele.pstyle( 'pie-' + i + '-background-size' ).value; + + if( size > 0 ){ + hasPie = true; + break; + } + } + } + + _p.hasPie = hasPie; + + var transform = ele.pstyle( 'text-transform' ).strValue; + var content = ele.pstyle( 'label' ).strValue; + var srcContent = ele.pstyle( 'source-label' ).strValue; + var tgtContent = ele.pstyle( 'target-label' ).strValue; + var fStyle = ele.pstyle( 'font-style' ).strValue; + var size = ele.pstyle( 'font-size' ).pfValue + 'px'; + var family = ele.pstyle( 'font-family' ).strValue; + // var variant = style['font-variant'].strValue; + var weight = ele.pstyle( 'font-weight' ).strValue; + var valign = ele.pstyle( 'text-valign' ).strValue; + var halign = ele.pstyle( 'text-valign' ).strValue; + var oWidth = ele.pstyle( 'text-outline-width' ).pfValue; + var wrap = ele.pstyle( 'text-wrap' ).strValue; + var wrapW = ele.pstyle( 'text-max-width' ).pfValue; + var labelStyleKey = fStyle + '$' + size + '$' + family + '$' + weight + '$' + transform + '$' + valign + '$' + halign + '$' + oWidth + '$' + wrap + '$' + wrapW; + _p.labelStyleKey = labelStyleKey; + _p.sourceLabelKey = labelStyleKey + '$' + srcContent; + _p.targetLabelKey = labelStyleKey + '$' + tgtContent; + _p.labelKey = labelStyleKey + '$' + content; + _p.fontKey = fStyle + '$' + weight + '$' + size + '$' + family; + + _p.styleKey = Date.now(); +}; + +// apply a property to the style (for internal use) +// returns whether application was successful +// +// now, this function flattens the property, and here's how: +// +// for parsedProp:{ bypass: true, deleteBypass: true } +// no property is generated, instead the bypass property in the +// element's style is replaced by what's pointed to by the `bypassed` +// field in the bypass property (i.e. restoring the property the +// bypass was overriding) +// +// for parsedProp:{ mapped: truthy } +// the generated flattenedProp:{ mapping: prop } +// +// for parsedProp:{ bypass: true } +// the generated flattenedProp:{ bypassed: parsedProp } +styfn.applyParsedProperty = function( ele, parsedProp ){ + var self = this; + var prop = parsedProp; + var style = ele._private.style; + var fieldVal, flatProp; + var types = self.types; + var type = self.properties[ prop.name ].type; + var propIsBypass = prop.bypass; + var origProp = style[ prop.name ]; + var origPropIsBypass = origProp && origProp.bypass; + var _p = ele._private; + + // edges connected to compound nodes can not be haystacks + if( + parsedProp.name === 'curve-style' + && parsedProp.value === 'haystack' + && ele.isEdge() + && ( ele.isLoop() || ele.source().isParent() || ele.target().isParent() ) + ){ + prop = parsedProp = this.parse( parsedProp.name, 'bezier', propIsBypass ); + } + + if( prop.delete ){ // delete the property and use the default value on falsey value + style[ prop.name ] = undefined; + + return true; + } + + if( prop.deleteBypassed ){ // delete the property that the + if( !origProp ){ + return true; // can't delete if no prop + + } else if( origProp.bypass ){ // delete bypassed + origProp.bypassed = undefined; + return true; + + } else { + return false; // we're unsuccessful deleting the bypassed + } + } + + // check if we need to delete the current bypass + if( prop.deleteBypass ){ // then this property is just here to indicate we need to delete + if( !origProp ){ + return true; // property is already not defined + + } else if( origProp.bypass ){ // then replace the bypass property with the original + // because the bypassed property was already applied (and therefore parsed), we can just replace it (no reapplying necessary) + style[ prop.name ] = origProp.bypassed; + return true; + + } else { + return false; // we're unsuccessful deleting the bypass + } + } + + var printMappingErr = function(){ + util.error( 'Do not assign mappings to elements without corresponding data (e.g. ele `' + ele.id() + '` for property `' + prop.name + '` with data field `' + prop.field + '`); try a `[' + prop.field + ']` selector to limit scope to elements with `' + prop.field + '` defined' ); + }; + + // put the property in the style objects + switch( prop.mapped ){ // flatten the property if mapped + case types.mapData: + case types.mapLayoutData: + case types.mapScratch: + + var isLayout = prop.mapped === types.mapLayoutData; + var isScratch = prop.mapped === types.mapScratch; + + // flatten the field (e.g. data.foo.bar) + var fields = prop.field.split( '.' ); + var fieldVal; + + if( isScratch || isLayout ){ + fieldVal = _p.scratch; + } else { + fieldVal = _p.data; + } + + for( var i = 0; i < fields.length && fieldVal; i++ ){ + var field = fields[ i ]; + fieldVal = fieldVal[ field ]; + } + + var percent; + if( !is.number( fieldVal ) ){ // then keep the mapping but assume 0% for now + percent = 0; + } else { + percent = (fieldVal - prop.fieldMin) / (prop.fieldMax - prop.fieldMin); + } + + // make sure to bound percent value + if( percent < 0 ){ + percent = 0; + } else if( percent > 1 ){ + percent = 1; + } + + if( type.color ){ + var r1 = prop.valueMin[0]; + var r2 = prop.valueMax[0]; + var g1 = prop.valueMin[1]; + var g2 = prop.valueMax[1]; + var b1 = prop.valueMin[2]; + var b2 = prop.valueMax[2]; + var a1 = prop.valueMin[3] == null ? 1 : prop.valueMin[3]; + var a2 = prop.valueMax[3] == null ? 1 : prop.valueMax[3]; + + var clr = [ + Math.round( r1 + (r2 - r1) * percent ), + Math.round( g1 + (g2 - g1) * percent ), + Math.round( b1 + (b2 - b1) * percent ), + Math.round( a1 + (a2 - a1) * percent ) + ]; + + flatProp = { // colours are simple, so just create the flat property instead of expensive string parsing + bypass: prop.bypass, // we're a bypass if the mapping property is a bypass + name: prop.name, + value: clr, + strValue: 'rgb(' + clr[0] + ', ' + clr[1] + ', ' + clr[2] + ')' + }; + + } else if( type.number ){ + var calcValue = prop.valueMin + (prop.valueMax - prop.valueMin) * percent; + flatProp = this.parse( prop.name, calcValue, prop.bypass, true ); + + } else { + return false; // can only map to colours and numbers + } + + if( !flatProp ){ // if we can't flatten the property, then use the origProp so we still keep the mapping itself + flatProp = this.parse( prop.name, origProp.strValue, prop.bypass, true ); + } + + if( !flatProp ){ printMappingErr(); } + flatProp.mapping = prop; // keep a reference to the mapping + prop = flatProp; // the flattened (mapped) property is the one we want + + break; + + // direct mapping + case types.data: + case types.layoutData: + case types.scratch: + var isLayout = prop.mapped === types.layoutData; + var isScratch = prop.mapped === types.scratch; + + // flatten the field (e.g. data.foo.bar) + var fields = prop.field.split( '.' ); + var fieldVal; + + if( isScratch || isLayout ){ + fieldVal = _p.scratch; + } else { + fieldVal = _p.data; + } + + if( fieldVal ){ for( var i = 0; i < fields.length; i++ ){ + var field = fields[ i ]; + fieldVal = fieldVal[ field ]; + } } + + flatProp = this.parse( prop.name, fieldVal, prop.bypass, true ); + + if( !flatProp ){ // if we can't flatten the property, then use the origProp so we still keep the mapping itself + var flatPropVal = origProp ? origProp.strValue : ''; + + flatProp = this.parse( prop.name, flatPropVal, prop.bypass, true ); + } + + if( !flatProp ){ printMappingErr(); } + flatProp.mapping = prop; // keep a reference to the mapping + prop = flatProp; // the flattened (mapped) property is the one we want + + break; + + case types.fn: + var fn = prop.value; + var fnRetVal = fn( ele ); + + flatProp = this.parse( prop.name, fnRetVal, prop.bypass, true ); + flatProp.mapping = prop; // keep a reference to the mapping + prop = flatProp; // the flattened (mapped) property is the one we want + + break; + + case undefined: + break; // just set the property + + default: + return false; // not a valid mapping + } + + // if the property is a bypass property, then link the resultant property to the original one + if( propIsBypass ){ + if( origPropIsBypass ){ // then this bypass overrides the existing one + prop.bypassed = origProp.bypassed; // steal bypassed prop from old bypass + } else { // then link the orig prop to the new bypass + prop.bypassed = origProp; + } + + style[ prop.name ] = prop; // and set + + } else { // prop is not bypass + if( origPropIsBypass ){ // then keep the orig prop (since it's a bypass) and link to the new prop + origProp.bypassed = prop; + } else { // then just replace the old prop with the new one + style[ prop.name ] = prop; + } + } + + return true; +}; + +styfn.cleanElements = function( eles, keepBypasses ){ + var self = this; + var props = self.properties; + + for( var i = 0; i < eles.length; i++ ){ + var ele = eles[i]; + + if( !keepBypasses ){ + ele._private.style = {}; + } else { + var style = ele._private.style; + + for( var j = 0; j < props.length; j++ ){ + var prop = props[j]; + var eleProp = style[ prop.name ]; + + if( eleProp ){ + if( eleProp.bypass ){ + eleProp.bypassed = null; + } else { + style[ prop.name ] = null; + } + } + } + } + } +}; + +// updates the visual style for all elements (useful for manual style modification after init) +styfn.update = function(){ + var cy = this._private.cy; + var eles = cy.mutableElements(); + + eles.updateStyle(); +}; + +// just update the functional properties (i.e. mappings) in the elements' +// styles (less expensive than recalculation) +styfn.updateMappers = function( eles ){ + var self = this; + + for( var i = 0; i < eles.length; i++ ){ // for each ele + var ele = eles[ i ]; + var style = ele._private.style; + + for( var j = 0; j < self.properties.length; j++ ){ // for each prop + var prop = self.properties[ j ]; + var propInStyle = style[ prop.name ]; + + if( propInStyle && propInStyle.mapping ){ + var mapping = propInStyle.mapping; + this.applyParsedProperty( ele, mapping ); // reapply the mapping property + } + } + + this.updateStyleHints( ele ); + } +}; + +// diffProps : { name => { prev, next } } +styfn.updateTransitions = function( ele, diffProps, isBypass ){ + var self = this; + var _p = ele._private; + var props = ele.pstyle( 'transition-property' ).value; + var duration = ele.pstyle( 'transition-duration' ).pfValue; + var delay = ele.pstyle( 'transition-delay' ).pfValue; + + if( props.length > 0 && duration > 0 ){ + + var css = {}; + + // build up the style to animate towards + var anyPrev = false; + for( var i = 0; i < props.length; i++ ){ + var prop = props[ i ]; + var styProp = ele.pstyle( prop ); + var diffProp = diffProps[ prop ]; + + if( !diffProp ){ continue; } + + var prevProp = diffProp.prev; + var fromProp = prevProp; + var toProp = diffProp.next != null ? diffProp.next : styProp; + var diff = false; + var initVal; + var initDt = 0.000001; // delta time % value for initVal (allows animating out of init zero opacity) + + if( !fromProp ){ continue; } + + // consider px values + if( is.number( fromProp.pfValue ) && is.number( toProp.pfValue ) ){ + diff = toProp.pfValue - fromProp.pfValue; // nonzero is truthy + initVal = fromProp.pfValue + initDt * diff; + + // consider numerical values + } else if( is.number( fromProp.value ) && is.number( toProp.value ) ){ + diff = toProp.value - fromProp.value; // nonzero is truthy + initVal = fromProp.value + initDt * diff; + + // consider colour values + } else if( is.array( fromProp.value ) && is.array( toProp.value ) ){ + diff = fromProp.value[0] !== toProp.value[0] + || fromProp.value[1] !== toProp.value[1] + || fromProp.value[2] !== toProp.value[2] + ; + + initVal = fromProp.strValue; + } + + // the previous value is good for an animation only if it's different + if( diff ){ + css[ prop ] = toProp.strValue; // to val + this.applyBypass( ele, prop, initVal ); // from val + anyPrev = true; + } + + } // end if props allow ani + + // can't transition if there's nothing previous to transition from + if( !anyPrev ){ return; } + + _p.transitioning = true; + + ele.stop(); + + if( delay > 0 ){ + ele.delay( delay ); + } + + ele.animate( { + css: css + }, { + duration: duration, + easing: ele.pstyle( 'transition-timing-function' ).value, + queue: false, + complete: function(){ + if( !isBypass ){ + self.removeBypasses( ele, props ); + } + + _p.transitioning = false; + } + } ); + + } else if( _p.transitioning ){ + ele.stop(); + + this.removeBypasses( ele, props ); + + _p.transitioning = false; + } +}; + +module.exports = styfn; + +},{"../is":83,"../util":100}],89:[function(_dereq_,module,exports){ +'use strict'; + +var is = _dereq_( '../is' ); +var util = _dereq_( '../util' ); + +var styfn = {}; + +// bypasses are applied to an existing style on an element, and just tacked on temporarily +// returns true iff application was successful for at least 1 specified property +styfn.applyBypass = function( eles, name, value, updateTransitions ){ + var self = this; + var props = []; + var isBypass = true; + + // put all the properties (can specify one or many) in an array after parsing them + if( name === '*' || name === '**' ){ // apply to all property names + + if( value !== undefined ){ + for( var i = 0; i < self.properties.length; i++ ){ + var prop = self.properties[ i ]; + var name = prop.name; + + var parsedProp = this.parse( name, value, true ); + + if( parsedProp ){ + props.push( parsedProp ); + } + } + } + + } else if( is.string( name ) ){ // then parse the single property + var parsedProp = this.parse( name, value, true ); + + if( parsedProp ){ + props.push( parsedProp ); + } + } else if( is.plainObject( name ) ){ // then parse each property + var specifiedProps = name; + updateTransitions = value; + + for( var i = 0; i < self.properties.length; i++ ){ + var prop = self.properties[ i ]; + var name = prop.name; + var value = specifiedProps[ name ]; + + if( value === undefined ){ // try camel case name too + value = specifiedProps[ util.dash2camel( name ) ]; + } + + if( value !== undefined ){ + var parsedProp = this.parse( name, value, true ); + + if( parsedProp ){ + props.push( parsedProp ); + } + } + } + } else { // can't do anything without well defined properties + return false; + } + + // we've failed if there are no valid properties + if( props.length === 0 ){ return false; } + + // now, apply the bypass properties on the elements + var ret = false; // return true if at least one succesful bypass applied + for( var i = 0; i < eles.length; i++ ){ // for each ele + var ele = eles[ i ]; + var diffProps = {}; + var diffProp; + + for( var j = 0; j < props.length; j++ ){ // for each prop + var prop = props[ j ]; + + if( updateTransitions ){ + var prevProp = ele.pstyle( prop.name ); + diffProp = diffProps[ prop.name ] = { prev: prevProp }; + } + + ret = this.applyParsedProperty( ele, prop ) || ret; + + if( updateTransitions ){ + diffProp.next = ele.pstyle( prop.name ); + } + + } // for props + + if( ret ){ + this.updateStyleHints( ele ); + } + + if( updateTransitions ){ + this.updateTransitions( ele, diffProps, isBypass ); + } + } // for eles + + return ret; +}; + +// only useful in specific cases like animation +styfn.overrideBypass = function( eles, name, value ){ + name = util.camel2dash( name ); + + for( var i = 0; i < eles.length; i++ ){ + var ele = eles[ i ]; + var prop = ele._private.style[ name ]; + var type = this.properties[ name ].type; + var isColor = type.color; + var isMulti = type.mutiple; + + if( !prop || !prop.bypass ){ // need a bypass if one doesn't exist + this.applyBypass( ele, name, value ); + continue; + } + + prop.value = value; + + if( prop.pfValue != null ){ + prop.pfValue = value; + } + + if( isColor ){ + prop.strValue = 'rgb(' + value.join( ',' ) + ')'; + } else if( isMulti ){ + prop.strValue = value.join( ' ' ); + } else { + prop.strValue = '' + value; + } + } +}; + +styfn.removeAllBypasses = function( eles, updateTransitions ){ + return this.removeBypasses( eles, this.propertyNames, updateTransitions ); +}; + +styfn.removeBypasses = function( eles, props, updateTransitions ){ + var isBypass = true; + + for( var j = 0; j < eles.length; j++ ){ + var ele = eles[ j ]; + var diffProps = {}; + + for( var i = 0; i < props.length; i++ ){ + var name = props[ i ]; + var prop = this.properties[ name ]; + var prevProp = ele.pstyle( prop.name ); + + if( !prevProp || !prevProp.bypass ){ + // if a bypass doesn't exist for the prop, nothing needs to be removed + continue; + } + + var value = ''; // empty => remove bypass + var parsedProp = this.parse( name, value, true ); + var diffProp = diffProps[ prop.name ] = { prev: prevProp }; + + this.applyParsedProperty( ele, parsedProp ); + + diffProp.next = ele.pstyle( prop.name ); + } // for props + + this.updateStyleHints( ele ); + + if( updateTransitions ){ + this.updateTransitions( ele, diffProps, isBypass ); + } + } // for eles +}; + +module.exports = styfn; + +},{"../is":83,"../util":100}],90:[function(_dereq_,module,exports){ +'use strict'; + +var window = _dereq_( '../window' ); + +var styfn = {}; + +// gets what an em size corresponds to in pixels relative to a dom element +styfn.getEmSizeInPixels = function(){ + var px = this.containerCss( 'font-size' ); + + if( px != null ){ + return parseFloat( px ); + } else { + return 1; // for headless + } +}; + +// gets css property from the core container +styfn.containerCss = function( propName ){ + var cy = this._private.cy; + var domElement = cy.container(); + + if( window && domElement && window.getComputedStyle ){ + return window.getComputedStyle( domElement ).getPropertyValue( propName ); + } +}; + +module.exports = styfn; + +},{"../window":107}],91:[function(_dereq_,module,exports){ +'use strict'; + +var util = _dereq_( '../util' ); +var is = _dereq_( '../is' ); + +var styfn = {}; + +// gets the rendered style for an element +styfn.getRenderedStyle = function( ele ){ + return this.getRawStyle( ele, true ); +}; + +// gets the raw style for an element +styfn.getRawStyle = function( ele, isRenderedVal ){ + var self = this; + var ele = ele[0]; // insure it's an element + + if( ele ){ + var rstyle = {}; + + for( var i = 0; i < self.properties.length; i++ ){ + var prop = self.properties[ i ]; + var val = self.getStylePropertyValue( ele, prop.name, isRenderedVal ); + + if( val ){ + rstyle[ prop.name ] = val; + rstyle[ util.dash2camel( prop.name ) ] = val; + } + } + + return rstyle; + } +}; + +styfn.getStylePropertyValue = function( ele, propName, isRenderedVal ){ + var self = this; + var ele = ele[0]; // insure it's an element + + if( ele ){ + var prop = self.properties[ propName ]; + var type = prop.type; + var styleProp = ele.pstyle( prop.name ); + var zoom = ele.cy().zoom(); + + if( styleProp ){ + var units = styleProp.units ? type.implicitUnits || 'px' : null; + var val = units ? [].concat( styleProp.pfValue ).map( function( pfValue ){ + return ( pfValue * (isRenderedVal ? zoom : 1) ) + units; + } ).join( ' ' ) : styleProp.strValue; + + return val; + } + } +}; + +styfn.getAnimationStartStyle = function( ele, aniProps ){ + var rstyle = {}; + + for( var i = 0; i < aniProps.length; i++ ){ + var aniProp = aniProps[ i ]; + var name = aniProp.name; + + var styleProp = ele.pstyle( name ); + + if( styleProp !== undefined ){ // then make a prop of it + if( is.plainObject( styleProp ) ){ + styleProp = this.parse( name, styleProp.strValue ); + } else { + styleProp = this.parse( name, styleProp ); + } + } + + if( styleProp ){ + rstyle[ name ] = styleProp; + } + } + + return rstyle; +}; + +styfn.getPropsList = function( propsObj ){ + var self = this; + var rstyle = []; + var style = propsObj; + var props = self.properties; + + if( style ){ + var names = Object.keys( style ); + + for( var i = 0; i < names.length; i++ ){ + var name = names[i]; + var val = style[ name ]; + var prop = props[ name ] || props[ util.camel2dash( name ) ]; + var styleProp = this.parse( prop.name, val ); + + rstyle.push( styleProp ); + } + } + + return rstyle; +}; + +module.exports = styfn; + +},{"../is":83,"../util":100}],92:[function(_dereq_,module,exports){ +'use strict'; + +var is = _dereq_( '../is' ); +var util = _dereq_( '../util' ); +var Selector = _dereq_( '../selector' ); + +var Style = function( cy ){ + + if( !(this instanceof Style) ){ + return new Style( cy ); + } + + if( !is.core( cy ) ){ + util.error( 'A style must have a core reference' ); + return; + } + + this._private = { + cy: cy, + coreStyle: {} + }; + + this.length = 0; + + this.resetToDefault(); +}; + +var styfn = Style.prototype; + +styfn.instanceString = function(){ + return 'style'; +}; + +// remove all contexts +styfn.clear = function(){ + for( var i = 0; i < this.length; i++ ){ + this[ i ] = undefined; + } + this.length = 0; + + var _p = this._private; + + _p.newStyle = true; + + return this; // chaining +}; + +styfn.resetToDefault = function(){ + this.clear(); + this.addDefaultStylesheet(); + + return this; +}; + +// builds a style object for the 'core' selector +styfn.core = function(){ + return this._private.coreStyle; +}; + +// create a new context from the specified selector string and switch to that context +styfn.selector = function( selectorStr ){ + // 'core' is a special case and does not need a selector + var selector = selectorStr === 'core' ? null : new Selector( selectorStr ); + + var i = this.length++; // new context means new index + this[ i ] = { + selector: selector, + properties: [], + mappedProperties: [], + index: i + }; + + return this; // chaining +}; + +// add one or many css rules to the current context +styfn.css = function(){ + var self = this; + var args = arguments; + + switch( args.length ){ + case 1: + var map = args[0]; + + for( var i = 0; i < self.properties.length; i++ ){ + var prop = self.properties[ i ]; + var mapVal = map[ prop.name ]; + + if( mapVal === undefined ){ + mapVal = map[ util.dash2camel( prop.name ) ]; + } + + if( mapVal !== undefined ){ + this.cssRule( prop.name, mapVal ); + } + } + + break; + + case 2: + this.cssRule( args[0], args[1] ); + break; + + default: + break; // do nothing if args are invalid + } + + return this; // chaining +}; +styfn.style = styfn.css; + +// add a single css rule to the current context +styfn.cssRule = function( name, value ){ + // name-value pair + var property = this.parse( name, value ); + + // add property to current context if valid + if( property ){ + var i = this.length - 1; + this[ i ].properties.push( property ); + this[ i ].properties[ property.name ] = property; // allow access by name as well + + if( property.name.match( /pie-(\d+)-background-size/ ) && property.value ){ + this._private.hasPie = true; + } + + if( property.mapped ){ + this[ i ].mappedProperties.push( property ); + } + + // add to core style if necessary + var currentSelectorIsCore = !this[ i ].selector; + if( currentSelectorIsCore ){ + this._private.coreStyle[ property.name ] = property; + } + } + + return this; // chaining +}; + +// static function +Style.fromJson = function( cy, json ){ + var style = new Style( cy ); + + style.fromJson( json ); + + return style; +}; + +Style.fromString = function( cy, string ){ + return new Style( cy ).fromString( string ); +}; + +[ + _dereq_( './apply' ), + _dereq_( './bypass' ), + _dereq_( './container' ), + _dereq_( './get-for-ele' ), + _dereq_( './json' ), + _dereq_( './string-sheet' ), + _dereq_( './properties' ), + _dereq_( './parse' ) +].forEach( function( props ){ + util.extend( styfn, props ); +} ); + + +Style.types = styfn.types; +Style.properties = styfn.properties; + +module.exports = Style; + +},{"../is":83,"../selector":87,"../util":100,"./apply":88,"./bypass":89,"./container":90,"./get-for-ele":91,"./json":93,"./parse":94,"./properties":95,"./string-sheet":96}],93:[function(_dereq_,module,exports){ +'use strict'; + +var styfn = {}; + +styfn.applyFromJson = function( json ){ + var style = this; + + for( var i = 0; i < json.length; i++ ){ + var context = json[ i ]; + var selector = context.selector; + var props = context.style || context.css; + var names = Object.keys( props ); + + style.selector( selector ); // apply selector + + for( var j = 0; j < names.length; j++ ){ + var name = names[j]; + var value = props[ name ]; + + style.css( name, value ); // apply property + } + } + + return style; +}; + +// accessible cy.style() function +styfn.fromJson = function( json ){ + var style = this; + + style.resetToDefault(); + style.applyFromJson( json ); + + return style; +}; + +// get json from cy.style() api +styfn.json = function(){ + var json = []; + + for( var i = this.defaultLength; i < this.length; i++ ){ + var cxt = this[ i ]; + var selector = cxt.selector; + var props = cxt.properties; + var css = {}; + + for( var j = 0; j < props.length; j++ ){ + var prop = props[ j ]; + css[ prop.name ] = prop.strValue; + } + + json.push( { + selector: !selector ? 'core' : selector.toString(), + style: css + } ); + } + + return json; +}; + +module.exports = styfn; + +},{}],94:[function(_dereq_,module,exports){ +'use strict'; + +var util = _dereq_( '../util' ); +var is = _dereq_( '../is' ); +var math = _dereq_( '../math' ); + +var styfn = {}; + +// a caching layer for property parsing +styfn.parse = function( name, value, propIsBypass, propIsFlat ){ + var self = this; + + // function values can't be cached in all cases, and there isn't much benefit of caching them anyway + if( is.fn( value ) ){ + return self.parseImpl( name, value, propIsBypass, propIsFlat ); + } + + var argHash = [ name, value, propIsBypass, propIsFlat ].join( '$' ); + var propCache = self.propCache = self.propCache || {}; + var ret; + + if( !(ret = propCache[ argHash ]) ){ + ret = propCache[ argHash ] = self.parseImpl( name, value, propIsBypass, propIsFlat ); + } + + // always need a copy since props are mutated later in their lifecycles + ret = util.copy( ret ); + + if( ret ){ + ret.value = util.copy( ret.value ); // because it could be an array, e.g. colour + } + + return ret; +}; + +// parse a property; return null on invalid; return parsed property otherwise +// fields : +// - name : the name of the property +// - value : the parsed, native-typed value of the property +// - strValue : a string value that represents the property value in valid css +// - bypass : true iff the property is a bypass property +var parseImpl = function( name, value, propIsBypass, propIsFlat ){ + var self = this; + + name = util.camel2dash( name ); // make sure the property name is in dash form (e.g. 'property-name' not 'propertyName') + + var property = self.properties[ name ]; + var passedValue = value; + var types = self.types; + + if( !property ){ return null; } // return null on property of unknown name + if( value === undefined || value === null ){ return null; } // can't assign null + + // the property may be an alias + if( property.alias ){ + property = property.pointsTo; + name = property.name; + } + + var valueIsString = is.string( value ); + if( valueIsString ){ // trim the value to make parsing easier + value = value.trim(); + } + + var type = property.type; + if( !type ){ return null; } // no type, no luck + + // check if bypass is null or empty string (i.e. indication to delete bypass property) + if( propIsBypass && (value === '' || value === null) ){ + return { + name: name, + value: value, + bypass: true, + deleteBypass: true + }; + } + + // check if value is a function used as a mapper + if( is.fn( value ) ){ + return { + name: name, + value: value, + strValue: 'fn', + mapped: types.fn, + bypass: propIsBypass + }; + } + + // check if value is mapped + var data, mapData, layoutData, mapLayoutData, scratch, mapScratch; + if( !valueIsString || propIsFlat ){ + // then don't bother to do the expensive regex checks + + } else if( + ( data = new RegExp( types.data.regex ).exec( value ) ) || + ( layoutData = new RegExp( types.layoutData.regex ).exec( value ) ) || + ( scratch = new RegExp( types.scratch.regex ).exec( value ) ) + ){ + if( propIsBypass ){ return false; } // mappers not allowed in bypass + + var mapped; + if( data ){ + mapped = types.data; + } else if( layoutData ){ + mapped = types.layoutData; + } else { + mapped = types.scratch; + } + + data = data || layoutData || scratch; + + return { + name: name, + value: data, + strValue: '' + value, + mapped: mapped, + field: data[1], + bypass: propIsBypass + }; + + } else if( + ( mapData = new RegExp( types.mapData.regex ).exec( value ) ) || + ( mapLayoutData = new RegExp( types.mapLayoutData.regex ).exec( value ) ) || + ( mapScratch = new RegExp( types.mapScratch.regex ).exec( value ) ) + ){ + if( propIsBypass ){ return false; } // mappers not allowed in bypass + if( type.multiple ){ return false; } // impossible to map to num + + var mapped; + if( mapData ){ + mapped = types.mapData; + } else if( mapLayoutData ){ + mapped = types.mapLayoutData; + } else { + mapped = types.mapScratch; + } + + mapData = mapData || mapLayoutData || mapScratch; + + // we can map only if the type is a colour or a number + if( !(type.color || type.number) ){ return false; } + + var valueMin = this.parse( name, mapData[4] ); // parse to validate + if( !valueMin || valueMin.mapped ){ return false; } // can't be invalid or mapped + + var valueMax = this.parse( name, mapData[5] ); // parse to validate + if( !valueMax || valueMax.mapped ){ return false; } // can't be invalid or mapped + + // check if valueMin and valueMax are the same + if( valueMin.value === valueMax.value ){ + return false; // can't make much of a mapper without a range + + } else if( type.color ){ + var c1 = valueMin.value; + var c2 = valueMax.value; + + var same = c1[0] === c2[0] // red + && c1[1] === c2[1] // green + && c1[2] === c2[2] // blue + && ( // optional alpha + c1[3] === c2[3] // same alpha outright + || ( + (c1[3] == null || c1[3] === 1) // full opacity for colour 1? + && + (c2[3] == null || c2[3] === 1) // full opacity for colour 2? + ) + ) + ; + + if( same ){ return false; } // can't make a mapper without a range + } + + return { + name: name, + value: mapData, + strValue: '' + value, + mapped: mapped, + field: mapData[1], + fieldMin: parseFloat( mapData[2] ), // min & max are numeric + fieldMax: parseFloat( mapData[3] ), + valueMin: valueMin.value, + valueMax: valueMax.value, + bypass: propIsBypass + }; + } + + if( type.multiple && propIsFlat !== 'multiple' ){ + var vals; + + if( valueIsString ){ + vals = value.split( /\s+/ ); + } else if( is.array( value ) ){ + vals = value; + } else { + vals = [ value ]; + } + + if( type.evenMultiple && vals.length % 2 !== 0 ){ return null; } + + var valArr = vals.map( function( v ){ + var p = self.parse( name, v, propIsBypass, 'multiple' ); + + if( p.pfValue != null ){ + return p.pfValue; + } else { + return p.value; + } + } ); + + return { + name: name, + value: valArr, + pfValue: valArr, + strValue: valArr.join( ' ' ), + bypass: propIsBypass, + units: type.number && !type.unitless ? type.implicitUnits || 'px' : undefined + }; + } + + // several types also allow enums + var checkEnums = function(){ + for( var i = 0; i < type.enums.length; i++ ){ + var en = type.enums[ i ]; + + if( en === value ){ + return { + name: name, + value: value, + strValue: '' + value, + bypass: propIsBypass + }; + } + } + + return null; + }; + + // check the type and return the appropriate object + if( type.number ){ + var units; + var implicitUnits = 'px'; // not set => px + + if( type.units ){ // use specified units if set + units = type.units; + } + + if( type.implicitUnits ){ + implicitUnits = type.implicitUnits; + } + + if( !type.unitless ){ + if( valueIsString ){ + var unitsRegex = 'px|em' + (type.allowPercent ? '|\\%' : ''); + if( units ){ unitsRegex = units; } // only allow explicit units if so set + var match = value.match( '^(' + util.regex.number + ')(' + unitsRegex + ')?' + '$' ); + + if( match ){ + value = match[1]; + units = match[2] || implicitUnits; + } + + } else if( !units || type.implicitUnits ){ + units = implicitUnits; // implicitly px if unspecified + } + } + + value = parseFloat( value ); + + // if not a number and enums not allowed, then the value is invalid + if( isNaN( value ) && type.enums === undefined ){ + return null; + } + + // check if this number type also accepts special keywords in place of numbers + // (i.e. `left`, `auto`, etc) + if( isNaN( value ) && type.enums !== undefined ){ + value = passedValue; + + return checkEnums(); + } + + // check if value must be an integer + if( type.integer && !is.integer( value ) ){ + return null; + } + + // check value is within range + if( (type.min !== undefined && value < type.min) + || (type.max !== undefined && value > type.max) + ){ + return null; + } + + var ret = { + name: name, + value: value, + strValue: '' + value + (units ? units : ''), + units: units, + bypass: propIsBypass + }; + + // normalise value in pixels + if( type.unitless || (units !== 'px' && units !== 'em') ){ + ret.pfValue = value; + } else { + ret.pfValue = ( units === 'px' || !units ? (value) : (this.getEmSizeInPixels() * value) ); + } + + // normalise value in ms + if( units === 'ms' || units === 's' ){ + ret.pfValue = units === 'ms' ? value : 1000 * value; + } + + // normalise value in rad + if( units === 'deg' || units === 'rad' ){ + ret.pfValue = units === 'rad' ? value : math.deg2rad( value ); + } + + return ret; + + } else if( type.propList ){ + + var props = []; + var propsStr = '' + value; + + if( propsStr === 'none' ){ + // leave empty + + } else { // go over each prop + + var propsSplit = propsStr.split( ',' ); + for( var i = 0; i < propsSplit.length; i++ ){ + var propName = propsSplit[ i ].trim(); + + if( self.properties[ propName ] ){ + props.push( propName ); + } + } + + if( props.length === 0 ){ return null; } + } + + return { + name: name, + value: props, + strValue: props.length === 0 ? 'none' : props.join( ', ' ), + bypass: propIsBypass + }; + + } else if( type.color ){ + var tuple = util.color2tuple( value ); + + if( !tuple ){ return null; } + + return { + name: name, + value: tuple, + strValue: '' + value, + bypass: propIsBypass, + roundValue: true + }; + + } else if( type.regex || type.regexes ){ + + // first check enums + if( type.enums ){ + var enumProp = checkEnums(); + + if( enumProp ){ return enumProp; } + } + + var regexes = type.regexes ? type.regexes : [ type.regex ]; + + for( var i = 0; i < regexes.length; i++ ){ + var regex = new RegExp( regexes[ i ] ); // make a regex from the type string + var m = regex.exec( value ); + + if( m ){ // regex matches + return { + name: name, + value: m, + strValue: '' + value, + bypass: propIsBypass + }; + + } + } + + return null; // didn't match any + + } else if( type.string ){ + // just return + return { + name: name, + value: value, + strValue: '' + value, + bypass: propIsBypass + }; + + } else if( type.enums ){ // check enums last because it's a combo type in others + return checkEnums(); + + } else { + return null; // not a type we can handle + } + +}; +styfn.parseImpl = parseImpl; + +module.exports = styfn; + +},{"../is":83,"../math":85,"../util":100}],95:[function(_dereq_,module,exports){ +'use strict'; + +var util = _dereq_( '../util' ); + +var styfn = {}; + +(function(){ + var number = util.regex.number; + var rgba = util.regex.rgbaNoBackRefs; + var hsla = util.regex.hslaNoBackRefs; + var hex3 = util.regex.hex3; + var hex6 = util.regex.hex6; + var data = function( prefix ){ return '^' + prefix + '\\s*\\(\\s*([\\w\\.]+)\\s*\\)$'; }; + var mapData = function( prefix ){ + var mapArg = number + '|\\w+|' + rgba + '|' + hsla + '|' + hex3 + '|' + hex6; + return '^' + prefix + '\\s*\\(([\\w\\.]+)\\s*\\,\\s*(' + number + ')\\s*\\,\\s*(' + number + ')\\s*,\\s*(' + mapArg + ')\\s*\\,\\s*(' + mapArg + ')\\)$'; + }; + + // each visual style property has a type and needs to be validated according to it + styfn.types = { + time: { number: true, min: 0, units: 's|ms', implicitUnits: 'ms' }, + percent: { number: true, min: 0, max: 100, units: '%', implicitUnits: '%' }, + zeroOneNumber: { number: true, min: 0, max: 1, unitless: true }, + nOneOneNumber: { number: true, min: -1, max: 1, unitless: true }, + nonNegativeInt: { number: true, min: 0, integer: true, unitless: true }, + position: { enums: [ 'parent', 'origin' ] }, + nodeSize: { number: true, min: 0, enums: [ 'label' ] }, + number: { number: true, unitless: true }, + numbers: { number: true, unitless: true, multiple: true }, + size: { number: true, min: 0 }, + bidirectionalSize: { number: true }, // allows negative + bidirectionalSizes: { number: true, multiple: true }, // allows negative + bgSize: { number: true, min: 0, allowPercent: true }, + bgWH: { number: true, min: 0, allowPercent: true, enums: [ 'auto' ] }, + bgPos: { number: true, allowPercent: true }, + bgRepeat: { enums: [ 'repeat', 'repeat-x', 'repeat-y', 'no-repeat' ] }, + bgFit: { enums: [ 'none', 'contain', 'cover' ] }, + bgClip: { enums: [ 'none', 'node' ] }, + color: { color: true }, + bool: { enums: [ 'yes', 'no' ] }, + lineStyle: { enums: [ 'solid', 'dotted', 'dashed' ] }, + borderStyle: { enums: [ 'solid', 'dotted', 'dashed', 'double' ] }, + curveStyle: { enums: [ 'bezier', 'unbundled-bezier', 'haystack', 'segments' ] }, + fontFamily: { regex: '^([\\w- \\"]+(?:\\s*,\\s*[\\w- \\"]+)*)$' }, + fontVariant: { enums: [ 'small-caps', 'normal' ] }, + fontStyle: { enums: [ 'italic', 'normal', 'oblique' ] }, + fontWeight: { enums: [ 'normal', 'bold', 'bolder', 'lighter', '100', '200', '300', '400', '500', '600', '800', '900', 100, 200, 300, 400, 500, 600, 700, 800, 900 ] }, + textDecoration: { enums: [ 'none', 'underline', 'overline', 'line-through' ] }, + textTransform: { enums: [ 'none', 'uppercase', 'lowercase' ] }, + textWrap: { enums: [ 'none', 'wrap' ] }, + textBackgroundShape: { enums: [ 'rectangle', 'roundrectangle' ]}, + nodeShape: { enums: [ 'rectangle', 'roundrectangle', 'ellipse', 'triangle', 'square', 'pentagon', 'hexagon', 'heptagon', 'octagon', 'star', 'diamond', 'vee', 'rhomboid', 'polygon' ] }, + compoundIncludeLabels: { enums: [ 'include', 'exclude' ] }, + arrowShape: { enums: [ 'tee', 'triangle', 'triangle-tee', 'triangle-backcurve', 'half-triangle-overshot', 'vee', 'square', 'circle', 'diamond', 'none' ] }, + arrowFill: { enums: [ 'filled', 'hollow' ] }, + display: { enums: [ 'element', 'none' ] }, + visibility: { enums: [ 'hidden', 'visible' ] }, + valign: { enums: [ 'top', 'center', 'bottom' ] }, + halign: { enums: [ 'left', 'center', 'right' ] }, + text: { string: true }, + data: { mapping: true, regex: data( 'data' ) }, + layoutData: { mapping: true, regex: data( 'layoutData' ) }, + scratch: { mapping: true, regex: data( 'scratch' ) }, + mapData: { mapping: true, regex: mapData( 'mapData' ) }, + mapLayoutData: { mapping: true, regex: mapData( 'mapLayoutData' ) }, + mapScratch: { mapping: true, regex: mapData( 'mapScratch' ) }, + fn: { mapping: true, fn: true }, + url: { regex: '^url\\s*\\(\\s*([^\\s]+)\\s*\\s*\\)|none|(.+)$' }, + propList: { propList: true }, + angle: { number: true, units: 'deg|rad', implicitUnits: 'rad' }, + textRotation: { number: true, units: 'deg|rad', implicitUnits: 'rad', enums: [ 'none', 'autorotate' ] }, + polygonPointList: { number: true, multiple: true, evenMultiple: true, min: -1, max: 1, unitless: true }, + edgeDistances: { enums: ['intersection', 'node-position'] }, + easing: { + regexes: [ + '^(spring)\\s*\\(\\s*(' + number + ')\\s*,\\s*(' + number + ')\\s*\\)$', + '^(cubic-bezier)\\s*\\(\\s*(' + number + ')\\s*,\\s*(' + number + ')\\s*,\\s*(' + number + ')\\s*,\\s*(' + number + ')\\s*\\)$' + ], + enums: [ + 'linear', + 'ease', 'ease-in', 'ease-out', 'ease-in-out', + 'ease-in-sine', 'ease-out-sine', 'ease-in-out-sine', + 'ease-in-quad', 'ease-out-quad', 'ease-in-out-quad', + 'ease-in-cubic', 'ease-out-cubic', 'ease-in-out-cubic', + 'ease-in-quart', 'ease-out-quart', 'ease-in-out-quart', + 'ease-in-quint', 'ease-out-quint', 'ease-in-out-quint', + 'ease-in-expo', 'ease-out-expo', 'ease-in-out-expo', + 'ease-in-circ', 'ease-out-circ', 'ease-in-out-circ' + ] + } + }; + + // define visual style properties + var t = styfn.types; + var props = styfn.properties = [ + // main label + { name: 'label', type: t.text }, + { name: 'text-rotation', type: t.textRotation }, + { name: 'text-margin-x', type: t.bidirectionalSize }, + { name: 'text-margin-y', type: t.bidirectionalSize }, + + // source label + { name: 'source-label', type: t.text }, + { name: 'source-text-rotation', type: t.textRotation }, + { name: 'source-text-margin-x', type: t.bidirectionalSize }, + { name: 'source-text-margin-y', type: t.bidirectionalSize }, + { name: 'source-text-offset', type: t.size }, + + // target label + { name: 'target-label', type: t.text }, + { name: 'target-text-rotation', type: t.textRotation }, + { name: 'target-text-margin-x', type: t.bidirectionalSize }, + { name: 'target-text-margin-y', type: t.bidirectionalSize }, + { name: 'target-text-offset', type: t.size }, + + // common label style + { name: 'text-valign', type: t.valign }, + { name: 'text-halign', type: t.halign }, + { name: 'color', type: t.color }, + { name: 'text-outline-color', type: t.color }, + { name: 'text-outline-width', type: t.size }, + { name: 'text-outline-opacity', type: t.zeroOneNumber }, + { name: 'text-opacity', type: t.zeroOneNumber }, + { name: 'text-background-color', type: t.color }, + { name: 'text-background-margin', type: t.size }, + { name: 'text-background-opacity', type: t.zeroOneNumber }, + { name: 'text-border-opacity', type: t.zeroOneNumber }, + { name: 'text-border-color', type: t.color }, + { name: 'text-border-width', type: t.size }, + { name: 'text-border-style', type: t.borderStyle }, + { name: 'text-background-shape', type: t.textBackgroundShape}, + // { name: 'text-decoration', type: t.textDecoration }, // not supported in canvas + { name: 'text-transform', type: t.textTransform }, + { name: 'text-wrap', type: t.textWrap }, + { name: 'text-max-width', type: t.size }, + { name: 'text-events', type: t.bool }, + { name: 'font-family', type: t.fontFamily }, + { name: 'font-style', type: t.fontStyle }, + // { name: 'font-variant', type: t.fontVariant }, // not useful + { name: 'font-weight', type: t.fontWeight }, + { name: 'font-size', type: t.size }, + { name: 'min-zoomed-font-size', type: t.size }, + + // behaviour + { name: 'events', type: t.bool }, + + // visibility + { name: 'display', type: t.display }, + { name: 'visibility', type: t.visibility }, + { name: 'opacity', type: t.zeroOneNumber }, + { name: 'z-index', type: t.nonNegativeInt }, + + // overlays + { name: 'overlay-padding', type: t.size }, + { name: 'overlay-color', type: t.color }, + { name: 'overlay-opacity', type: t.zeroOneNumber }, + + // shadows + { name: 'shadow-blur', type: t.size }, + { name: 'shadow-color', type: t.color }, + { name: 'shadow-opacity', type: t.zeroOneNumber }, + { name: 'shadow-offset-x', type: t.bidirectionalSize }, + { name: 'shadow-offset-y', type: t.bidirectionalSize }, + + // label shadows + { name: 'text-shadow-blur', type: t.size }, + { name: 'text-shadow-color', type: t.color }, + { name: 'text-shadow-opacity', type: t.zeroOneNumber }, + { name: 'text-shadow-offset-x', type: t.bidirectionalSize }, + { name: 'text-shadow-offset-y', type: t.bidirectionalSize }, + + // transition anis + { name: 'transition-property', type: t.propList }, + { name: 'transition-duration', type: t.time }, + { name: 'transition-delay', type: t.time }, + { name: 'transition-timing-function', type: t.easing }, + + // node body + { name: 'height', type: t.nodeSize }, + { name: 'width', type: t.nodeSize }, + { name: 'shape', type: t.nodeShape }, + { name: 'shape-polygon-points', type: t.polygonPointList }, + { name: 'background-color', type: t.color }, + { name: 'background-opacity', type: t.zeroOneNumber }, + { name: 'background-blacken', type: t.nOneOneNumber }, + { name: 'padding-left', type: t.size }, + { name: 'padding-right', type: t.size }, + { name: 'padding-top', type: t.size }, + { name: 'padding-bottom', type: t.size }, + + // node border + { name: 'border-color', type: t.color }, + { name: 'border-opacity', type: t.zeroOneNumber }, + { name: 'border-width', type: t.size }, + { name: 'border-style', type: t.borderStyle }, + + // node background images + { name: 'background-image', type: t.url }, + { name: 'background-image-opacity', type: t.zeroOneNumber }, + { name: 'background-position-x', type: t.bgPos }, + { name: 'background-position-y', type: t.bgPos }, + { name: 'background-repeat', type: t.bgRepeat }, + { name: 'background-fit', type: t.bgFit }, + { name: 'background-clip', type: t.bgClip }, + { name: 'background-width', type: t.bgWH }, + { name: 'background-height', type: t.bgWH }, + + // compound props + { name: 'position', type: t.position }, + { name: 'compound-sizing-wrt-labels', type: t.compoundIncludeLabels }, + + // edge line + { name: 'line-style', type: t.lineStyle }, + { name: 'line-color', type: t.color }, + { name: 'curve-style', type: t.curveStyle }, + { name: 'haystack-radius', type: t.zeroOneNumber }, + { name: 'control-point-step-size', type: t.size }, + { name: 'control-point-distances', type: t.bidirectionalSizes }, + { name: 'control-point-weights', type: t.numbers }, + { name: 'segment-distances', type: t.bidirectionalSizes }, + { name: 'segment-weights', type: t.numbers }, + { name: 'edge-distances', type: t.edgeDistances }, + + // these are just for the core + { name: 'selection-box-color', type: t.color }, + { name: 'selection-box-opacity', type: t.zeroOneNumber }, + { name: 'selection-box-border-color', type: t.color }, + { name: 'selection-box-border-width', type: t.size }, + { name: 'active-bg-color', type: t.color }, + { name: 'active-bg-opacity', type: t.zeroOneNumber }, + { name: 'active-bg-size', type: t.size }, + { name: 'outside-texture-bg-color', type: t.color }, + { name: 'outside-texture-bg-opacity', type: t.zeroOneNumber } + ]; + + // define aliases + var aliases = styfn.aliases = [ + { name: 'content', pointsTo: 'label' }, + { name: 'control-point-distance', pointsTo: 'control-point-distances' }, + { name: 'control-point-weight', pointsTo: 'control-point-weights' }, + { name: 'edge-text-rotation', pointsTo: 'text-rotation' } + ]; + + // pie backgrounds for nodes + styfn.pieBackgroundN = 16; // because the pie properties are numbered, give access to a constant N (for renderer use) + props.push( { name: 'pie-size', type: t.bgSize } ); + for( var i = 1; i <= styfn.pieBackgroundN; i++ ){ + props.push( { name: 'pie-' + i + '-background-color', type: t.color } ); + props.push( { name: 'pie-' + i + '-background-size', type: t.percent } ); + props.push( { name: 'pie-' + i + '-background-opacity', type: t.zeroOneNumber } ); + } + + // edge arrows + var arrowPrefixes = styfn.arrowPrefixes = [ 'source', 'mid-source', 'target', 'mid-target' ]; + [ + { name: 'arrow-shape', type: t.arrowShape }, + { name: 'arrow-color', type: t.color }, + { name: 'arrow-fill', type: t.arrowFill } + ].forEach( function( prop ){ + arrowPrefixes.forEach( function( prefix ){ + var name = prefix + '-' + prop.name; + var type = prop.type; + + props.push( { name: name, type: type } ); + } ); + }, {} ); + + // list of property names + styfn.propertyNames = props.map( function( p ){ return p.name; } ); + + // allow access of properties by name ( e.g. style.properties.height ) + for( var i = 0; i < props.length; i++ ){ + var prop = props[ i ]; + + props[ prop.name ] = prop; // allow lookup by name + } + + // map aliases + for( var i = 0; i < aliases.length; i++ ){ + var alias = aliases[ i ]; + var pointsToProp = props[ alias.pointsTo ]; + var aliasProp = { + name: alias.name, + alias: true, + pointsTo: pointsToProp + }; + + // add alias prop for parsing + props.push( aliasProp ); + + props[ alias.name ] = aliasProp; // allow lookup by name + } +})(); + +styfn.getDefaultProperty = function( name ){ + return this.getDefaultProperties()[ name ]; +}; + +styfn.getDefaultProperties = util.memoize( function(){ + var rawProps = util.extend( { + 'events': 'yes', + 'text-events': 'no', + 'text-valign': 'top', + 'text-halign': 'center', + 'color': '#000', + 'text-outline-color': '#000', + 'text-outline-width': 0, + 'text-outline-opacity': 1, + 'text-opacity': 1, + 'text-decoration': 'none', + 'text-transform': 'none', + 'text-wrap': 'none', + 'text-max-width': 9999, + 'text-background-color': '#000', + 'text-background-opacity': 0, + 'text-background-margin': 0, + 'text-border-opacity': 0, + 'text-border-width': 0, + 'text-border-style': 'solid', + 'text-border-color': '#000', + 'text-background-shape': 'rectangle', + 'font-family': 'Helvetica Neue, Helvetica, sans-serif', + 'font-style': 'normal', + // 'font-variant': fontVariant, + 'font-weight': 'normal', + 'font-size': 16, + 'min-zoomed-font-size': 0, + 'text-rotation': 'none', + 'source-text-rotation': 'none', + 'target-text-rotation': 'none', + 'visibility': 'visible', + 'display': 'element', + 'opacity': 1, + 'z-index': 0, + 'label': '', + 'text-margin-x': 0, + 'text-margin-y': 0, + 'source-label': '', + 'source-text-offset': 0, + 'source-text-margin-x': 0, + 'source-text-margin-y': 0, + 'target-label': '', + 'target-text-offset': 0, + 'target-text-margin-x': 0, + 'target-text-margin-y': 0, + 'overlay-opacity': 0, + 'overlay-color': '#000', + 'overlay-padding': 10, + 'shadow-opacity': 0, + 'shadow-color': '#000', + 'shadow-blur': 10, + 'shadow-offset-x': 0, + 'shadow-offset-y': 0, + 'text-shadow-opacity': 0, + 'text-shadow-color': '#000', + 'text-shadow-blur': 5, + 'text-shadow-offset-x': 0, + 'text-shadow-offset-y': 0, + 'transition-property': 'none', + 'transition-duration': 0, + 'transition-delay': 0, + 'transition-timing-function': 'linear', + + // node props + 'background-blacken': 0, + 'background-color': '#999', + 'background-opacity': 1, + 'background-image': 'none', + 'background-image-opacity': 1, + 'background-position-x': '50%', + 'background-position-y': '50%', + 'background-repeat': 'no-repeat', + 'background-fit': 'none', + 'background-clip': 'node', + 'background-width': 'auto', + 'background-height': 'auto', + 'border-color': '#000', + 'border-opacity': 1, + 'border-width': 0, + 'border-style': 'solid', + 'height': 30, + 'width': 30, + 'shape': 'ellipse', + 'shape-polygon-points': '-1, -1, 1, -1, 1, 1, -1, 1', + + // compound props + 'padding-top': 0, + 'padding-bottom': 0, + 'padding-left': 0, + 'padding-right': 0, + 'position': 'origin', + 'compound-sizing-wrt-labels': 'include' + }, { + // node pie bg + 'pie-size': '100%' + }, [ + { name: 'pie-{{i}}-background-color', value: 'black' }, + { name: 'pie-{{i}}-background-size', value: '0%' }, + { name: 'pie-{{i}}-background-opacity', value: 1 } + ].reduce( function( css, prop ){ + for( var i = 1; i <= styfn.pieBackgroundN; i++ ){ + var name = prop.name.replace( '{{i}}', i ); + var val = prop.value; + + css[ name ] = val; + } + + return css; + }, {} ), { + // edge props + 'line-style': 'solid', + 'line-color': '#999', + 'control-point-step-size': 40, + 'control-point-weights': 0.5, + 'segment-weights': 0.5, + 'segment-distances': 20, + 'edge-distances': 'intersection', + 'curve-style': 'bezier', + 'haystack-radius': 0 + }, [ + { name: 'arrow-shape', value: 'none' }, + { name: 'arrow-color', value: '#999' }, + { name: 'arrow-fill', value: 'filled' } + ].reduce( function( css, prop ){ + styfn.arrowPrefixes.forEach( function( prefix ){ + var name = prefix + '-' + prop.name; + var val = prop.value; + + css[ name ] = val; + } ); + + return css; + }, {} ) ); + + var parsedProps = {}; + + for( var i = 0; i < this.properties.length; i++ ){ + var prop = this.properties[i]; + + if( prop.pointsTo ){ continue; } + + var name = prop.name; + var val = rawProps[ name ]; + var parsedProp = this.parse( name, val ); + + parsedProps[ name ] = parsedProp; + } + + return parsedProps; +} ); + +styfn.addDefaultStylesheet = function(){ + this + .selector( '$node > node' ) // compound (parent) node properties + .css( { + 'shape': 'rectangle', + 'padding-top': 10, + 'padding-right': 10, + 'padding-left': 10, + 'padding-bottom': 10, + 'background-color': '#eee', + 'border-color': '#ccc', + 'border-width': 1 + } ) + .selector( 'edge' ) // just edge properties + .css( { + 'width': 3, + 'curve-style': 'haystack' + } ) + .selector( ':selected' ) + .css( { + 'background-color': '#0169D9', + 'line-color': '#0169D9', + 'source-arrow-color': '#0169D9', + 'target-arrow-color': '#0169D9', + 'mid-source-arrow-color': '#0169D9', + 'mid-target-arrow-color': '#0169D9' + } ) + .selector( 'node:parent:selected' ) + .css( { + 'background-color': '#CCE1F9', + 'border-color': '#aec8e5' + } ) + .selector( ':active' ) + .css( { + 'overlay-color': 'black', + 'overlay-padding': 10, + 'overlay-opacity': 0.25 + } ) + .selector( 'core' ) // just core properties + .css( { + 'selection-box-color': '#ddd', + 'selection-box-opacity': 0.65, + 'selection-box-border-color': '#aaa', + 'selection-box-border-width': 1, + 'active-bg-color': 'black', + 'active-bg-opacity': 0.15, + 'active-bg-size': 30, + 'outside-texture-bg-color': '#000', + 'outside-texture-bg-opacity': 0.125 + } ) + ; + + this.defaultLength = this.length; +}; + +module.exports = styfn; + +},{"../util":100}],96:[function(_dereq_,module,exports){ +'use strict'; + +var util = _dereq_( '../util' ); +var Selector = _dereq_( '../selector' ); + +var styfn = {}; + +styfn.applyFromString = function( string ){ + var self = this; + var style = this; + var remaining = '' + string; + var selAndBlockStr; + var blockRem; + var propAndValStr; + + // remove comments from the style string + remaining = remaining.replace( /[/][*](\s|.)+?[*][/]/g, '' ); + + function removeSelAndBlockFromRemaining(){ + // remove the parsed selector and block from the remaining text to parse + if( remaining.length > selAndBlockStr.length ){ + remaining = remaining.substr( selAndBlockStr.length ); + } else { + remaining = ''; + } + } + + function removePropAndValFromRem(){ + // remove the parsed property and value from the remaining block text to parse + if( blockRem.length > propAndValStr.length ){ + blockRem = blockRem.substr( propAndValStr.length ); + } else { + blockRem = ''; + } + } + + while( true ){ + var nothingLeftToParse = remaining.match( /^\s*$/ ); + if( nothingLeftToParse ){ break; } + + var selAndBlock = remaining.match( /^\s*((?:.|\s)+?)\s*\{((?:.|\s)+?)\}/ ); + + if( !selAndBlock ){ + util.error( 'Halting stylesheet parsing: String stylesheet contains more to parse but no selector and block found in: ' + remaining ); + break; + } + + selAndBlockStr = selAndBlock[0]; + + // parse the selector + var selectorStr = selAndBlock[1]; + if( selectorStr !== 'core' ){ + var selector = new Selector( selectorStr ); + if( selector._private.invalid ){ + util.error( 'Skipping parsing of block: Invalid selector found in string stylesheet: ' + selectorStr ); + + // skip this selector and block + removeSelAndBlockFromRemaining(); + continue; + } + } + + // parse the block of properties and values + var blockStr = selAndBlock[2]; + var invalidBlock = false; + blockRem = blockStr; + var props = []; + + while( true ){ + var nothingLeftToParse = blockRem.match( /^\s*$/ ); + if( nothingLeftToParse ){ break; } + + var propAndVal = blockRem.match( /^\s*(.+?)\s*:\s*(.+?)\s*;/ ); + + if( !propAndVal ){ + util.error( 'Skipping parsing of block: Invalid formatting of style property and value definitions found in:' + blockStr ); + invalidBlock = true; + break; + } + + propAndValStr = propAndVal[0]; + var propStr = propAndVal[1]; + var valStr = propAndVal[2]; + + var prop = self.properties[ propStr ]; + if( !prop ){ + util.error( 'Skipping property: Invalid property name in: ' + propAndValStr ); + + // skip this property in the block + removePropAndValFromRem(); + continue; + } + + var parsedProp = style.parse( propStr, valStr ); + + if( !parsedProp ){ + util.error( 'Skipping property: Invalid property definition in: ' + propAndValStr ); + + // skip this property in the block + removePropAndValFromRem(); + continue; + } + + props.push( { + name: propStr, + val: valStr + } ); + removePropAndValFromRem(); + } + + if( invalidBlock ){ + removeSelAndBlockFromRemaining(); + break; + } + + // put the parsed block in the style + style.selector( selectorStr ); + for( var i = 0; i < props.length; i++ ){ + var prop = props[ i ]; + style.css( prop.name, prop.val ); + } + + removeSelAndBlockFromRemaining(); + } + + return style; +}; + +styfn.fromString = function( string ){ + var style = this; + + style.resetToDefault(); + style.applyFromString( string ); + + return style; +}; + +module.exports = styfn; + +},{"../selector":87,"../util":100}],97:[function(_dereq_,module,exports){ +'use strict'; + +var is = _dereq_( './is' ); +var util = _dereq_( './util' ); +var Style = _dereq_( './style' ); + +// a dummy stylesheet object that doesn't need a reference to the core +// (useful for init) +var Stylesheet = function(){ + if( !(this instanceof Stylesheet) ){ + return new Stylesheet(); + } + + this.length = 0; +}; + +var sheetfn = Stylesheet.prototype; + +sheetfn.instanceString = function(){ + return 'stylesheet'; +}; + +// just store the selector to be parsed later +sheetfn.selector = function( selector ){ + var i = this.length++; + + this[ i ] = { + selector: selector, + properties: [] + }; + + return this; // chaining +}; + +// just store the property to be parsed later +sheetfn.css = function( name, value ){ + var i = this.length - 1; + + if( is.string( name ) ){ + this[ i ].properties.push( { + name: name, + value: value + } ); + } else if( is.plainObject( name ) ){ + var map = name; + + for( var j = 0; j < Style.properties.length; j++ ){ + var prop = Style.properties[ j ]; + var mapVal = map[ prop.name ]; + + if( mapVal === undefined ){ // also try camel case name + mapVal = map[ util.dash2camel( prop.name ) ]; + } + + if( mapVal !== undefined ){ + var name = prop.name; + var value = mapVal; + + this[ i ].properties.push( { + name: name, + value: value + } ); + } + } + } + + return this; // chaining +}; + +sheetfn.style = sheetfn.css; + +// generate a real style object from the dummy stylesheet +sheetfn.generateStyle = function( cy ){ + var style = new Style( cy ); + + for( var i = 0; i < this.length; i++ ){ + var context = this[ i ]; + var selector = context.selector; + var props = context.properties; + + style.selector( selector ); // apply selector + + for( var j = 0; j < props.length; j++ ){ + var prop = props[ j ]; + + style.css( prop.name, prop.value ); // apply property + } + } + + return style; +}; + +module.exports = Stylesheet; + +},{"./is":83,"./style":92,"./util":100}],98:[function(_dereq_,module,exports){ +/*! Weaver licensed under MIT (https://tldrlegal.com/license/mit-license), copyright Max Franz */ + +// cross-env thread/worker +// NB : uses (heavyweight) processes on nodejs so best not to create too many threads + +'use strict'; + +var window = _dereq_('./window'); +var util = _dereq_('./util'); +var Promise = _dereq_('./promise'); +var Event = _dereq_('./event'); +var define = _dereq_('./define'); +var is = _dereq_('./is'); + +var Thread = function( opts ){ + if( !(this instanceof Thread) ){ + return new Thread( opts ); + } + + var _p = this._private = { + requires: [], + files: [], + queue: null, + pass: [], + disabled: false + }; + + if( is.plainObject(opts) ){ + if( opts.disabled != null ){ + _p.disabled = !!opts.disabled; + } + } + +}; + +var thdfn = Thread.prototype; // short alias + +var stringifyFieldVal = function( val ){ + var valStr = is.fn( val ) ? val.toString() : "JSON.parse('" + JSON.stringify(val) + "')"; + + return valStr; +}; + +// allows for requires with prototypes and subobjs etc +var fnAsRequire = function( fn ){ + var req; + var fnName; + + if( is.object(fn) && fn.fn ){ // manual fn + req = fnAs( fn.fn, fn.name ); + fnName = fn.name; + fn = fn.fn; + } else if( is.fn(fn) ){ // auto fn + req = fn.toString(); + fnName = fn.name; + } else if( is.string(fn) ){ // stringified fn + req = fn; + } else if( is.object(fn) ){ // plain object + if( fn.proto ){ + req = ''; + } else { + req = fn.name + ' = {};'; + } + + fnName = fn.name; + fn = fn.obj; + } + + req += '\n'; + + var protoreq = function( val, subname ){ + if( val.prototype ){ + var protoNonempty = false; + for( var prop in val.prototype ){ protoNonempty = true; break; } // jshint ignore:line + + if( protoNonempty ){ + req += fnAsRequire( { + name: subname, + obj: val, + proto: true + }, val ); + } + } + }; + + // pull in prototype + if( fn.prototype && fnName != null ){ + + for( var name in fn.prototype ){ + var protoStr = ''; + + var val = fn.prototype[ name ]; + var valStr = stringifyFieldVal( val ); + var subname = fnName + '.prototype.' + name; + + protoStr += subname + ' = ' + valStr + ';\n'; + + if( protoStr ){ + req += protoStr; + } + + protoreq( val, subname ); // subobject with prototype + } + + } + + // pull in properties for obj/fns + if( !is.string(fn) ){ for( var name in fn ){ + var propsStr = ''; + + if( fn.hasOwnProperty(name) ){ + var val = fn[ name ]; + var valStr = stringifyFieldVal( val ); + var subname = fnName + '["' + name + '"]'; + + propsStr += subname + ' = ' + valStr + ';\n'; + } + + if( propsStr ){ + req += propsStr; + } + + protoreq( val, subname ); // subobject with prototype + } } + + return req; +}; + +var isPathStr = function( str ){ + return is.string(str) && str.match(/\.js$/); +}; + +util.extend(thdfn, { + + instanceString: function(){ return 'thread'; }, + + require: function( fn, as ){ + var requires = this._private.requires; + + if( isPathStr(fn) ){ + this._private.files.push( fn ); + + return this; + } + + if( as ){ + if( is.fn(fn) ){ + fn = { name: as, fn: fn }; + } else { + fn = { name: as, obj: fn }; + } + } else { + if( is.fn(fn) ){ + if( !fn.name ){ + throw 'The function name could not be automatically determined. Use thread.require( someFunction, "someFunction" )'; + } + + fn = { name: fn.name, fn: fn }; + } + } + + requires.push( fn ); + + return this; // chaining + }, + + pass: function( data ){ + this._private.pass.push( data ); + + return this; // chaining + }, + + run: function( fn, pass ){ // fn used like main() + var self = this; + var _p = this._private; + pass = pass || _p.pass.shift(); + + if( _p.stopped ){ + throw 'Attempted to run a stopped thread! Start a new thread or do not stop the existing thread and reuse it.'; + } + + if( _p.running ){ + return ( _p.queue = _p.queue.then(function(){ // inductive step + return self.run( fn, pass ); + }) ); + } + + var useWW = window != null && !_p.disabled; + var useNode = !window && typeof module !== 'undefined' && !_p.disabled; + + self.trigger('run'); + + var runP = new Promise(function( resolve, reject ){ + + _p.running = true; + + var threadTechAlreadyExists = _p.ran; + + var fnImplStr = is.string( fn ) ? fn : fn.toString(); + + // worker code to exec + var fnStr = '\n' + ( _p.requires.map(function( r ){ + return fnAsRequire( r ); + }) ).concat( _p.files.map(function( f ){ + if( useWW ){ + var wwifyFile = function( file ){ + if( file.match(/^\.\//) || file.match(/^\.\./) ){ + return window.location.origin + window.location.pathname + file; + } else if( file.match(/^\//) ){ + return window.location.origin + '/' + file; + } + return file; + }; + + return 'importScripts("' + wwifyFile(f) + '");'; + } else if( useNode ) { + return 'eval( require("fs").readFileSync("' + f + '", { encoding: "utf8" }) );'; + } else { + throw 'External file `' + f + '` can not be required without any threading technology.'; + } + }) ).concat([ + '( function(){', + 'var ret = (' + fnImplStr + ')(' + JSON.stringify(pass) + ');', + 'if( ret !== undefined ){ resolve(ret); }', // assume if ran fn returns defined value (incl. null), that we want to resolve to it + '} )()\n' + ]).join('\n'); + + // because we've now consumed the requires, empty the list so we don't dupe on next run() + _p.requires = []; + _p.files = []; + + if( useWW ){ + var fnBlob, fnUrl; + + // add normalised thread api functions + if( !threadTechAlreadyExists ){ + var fnPre = fnStr + ''; + + fnStr = [ + 'function _ref_(o){ return eval(o); };', + 'function broadcast(m){ return message(m); };', // alias + 'function message(m){ postMessage(m); };', + 'function listen(fn){', + ' self.addEventListener("message", function(m){ ', + ' if( typeof m === "object" && (m.data.$$eval || m.data === "$$start") ){', + ' } else { ', + ' fn( m.data );', + ' }', + ' });', + '};', + 'self.addEventListener("message", function(m){ if( m.data.$$eval ){ eval( m.data.$$eval ); } });', + 'function resolve(v){ postMessage({ $$resolve: v }); };', + 'function reject(v){ postMessage({ $$reject: v }); };' + ].join('\n'); + + fnStr += fnPre; + + fnBlob = new Blob([ fnStr ], { + type: 'application/javascript' + }); + fnUrl = window.URL.createObjectURL( fnBlob ); + } + // create webworker and let it exec the serialised code + var ww = _p.webworker = _p.webworker || new Worker( fnUrl ); + + if( threadTechAlreadyExists ){ // then just exec new run() code + ww.postMessage({ + $$eval: fnStr + }); + } + + // worker messages => events + var cb; + ww.addEventListener('message', cb = function( m ){ + var isObject = is.object(m) && is.object( m.data ); + + if( isObject && ('$$resolve' in m.data) ){ + ww.removeEventListener('message', cb); // done listening b/c resolve() + + resolve( m.data.$$resolve ); + } else if( isObject && ('$$reject' in m.data) ){ + ww.removeEventListener('message', cb); // done listening b/c reject() + + reject( m.data.$$reject ); + } else { + self.trigger( new Event(m, { type: 'message', message: m.data }) ); + } + }, false); + + if( !threadTechAlreadyExists ){ + ww.postMessage('$$start'); // start up the worker + } + + } else if( useNode ){ + // create a new process + + if( !_p.child ){ + _p.child = ( _dereq_('child_process').fork( _dereq_('path').join(__dirname, 'thread-node-fork') ) ); + } + + var child = _p.child; + + // child process messages => events + var cb; + child.on('message', cb = function( m ){ + if( is.object(m) && ('$$resolve' in m) ){ + child.removeListener('message', cb); // done listening b/c resolve() + + resolve( m.$$resolve ); + } else if( is.object(m) && ('$$reject' in m) ){ + child.removeListener('message', cb); // done listening b/c reject() + + reject( m.$$reject ); + } else { + self.trigger( new Event({}, { type: 'message', message: m }) ); + } + }); + + // ask the child process to eval the worker code + child.send({ + $$eval: fnStr + }); + + } else { // use a fallback mechanism using a timeout + + var promiseResolve = resolve; + var promiseReject = reject; + + var timer = _p.timer = _p.timer || { + + listeners: [], + + exec: function(){ + // as a string so it can't be mangled by minifiers and processors + fnStr = [ + 'function _ref_(o){ return eval(o); };', + 'function broadcast(m){ return message(m); };', + 'function message(m){ self.trigger( new Event({}, { type: "message", message: m }) ); };', + 'function listen(fn){ timer.listeners.push( fn ); };', + 'function resolve(v){ promiseResolve(v); };', + 'function reject(v){ promiseReject(v); };' + ].join('\n') + fnStr; + + // the .run() code + eval( fnStr ); // jshint ignore:line + }, + + message: function( m ){ + var ls = timer.listeners; + + for( var i = 0; i < ls.length; i++ ){ + var fn = ls[i]; + + fn( m ); + } + } + + }; + + timer.exec(); + } + + }).then(function( v ){ + _p.running = false; + _p.ran = true; + + self.trigger('ran'); + + return v; + }); + + if( _p.queue == null ){ + _p.queue = runP; // i.e. first step of inductive promise chain (for queue) + } + + return runP; + }, + + // send the thread a message + message: function( m ){ + var _p = this._private; + + if( _p.webworker ){ + _p.webworker.postMessage( m ); + } + + if( _p.child ){ + _p.child.send( m ); + } + + if( _p.timer ){ + _p.timer.message( m ); + } + + return this; // chaining + }, + + stop: function(){ + var _p = this._private; + + if( _p.webworker ){ + _p.webworker.terminate(); + } + + if( _p.child ){ + _p.child.kill(); + } + + if( _p.timer ){ + // nothing we can do if we've run a timeout + } + + _p.stopped = true; + + return this.trigger('stop'); // chaining + }, + + stopped: function(){ + return this._private.stopped; + } + +}); + +// turns a stringified function into a (re)named function +var fnAs = function( fn, name ){ + var fnStr = fn.toString(); + fnStr = fnStr.replace(/function\s*?\S*?\s*?\(/, 'function ' + name + '('); + + return fnStr; +}; + +var defineFnal = function( opts ){ + opts = opts || {}; + + return function fnalImpl( fn, arg1 ){ + var fnStr = fnAs( fn, '_$_$_' + opts.name ); + + this.require( fnStr ); + + return this.run( [ + 'function( data ){', + ' var origResolve = resolve;', + ' var res = [];', + ' ', + ' resolve = function( val ){', + ' res.push( val );', + ' };', + ' ', + ' var ret = data.' + opts.name + '( _$_$_' + opts.name + ( arguments.length > 1 ? ', ' + JSON.stringify(arg1) : '' ) + ' );', + ' ', + ' resolve = origResolve;', + ' resolve( res.length > 0 ? res : ret );', + '}' + ].join('\n') ); + }; +}; + +util.extend(thdfn, { + reduce: defineFnal({ name: 'reduce' }), + + reduceRight: defineFnal({ name: 'reduceRight' }), + + map: defineFnal({ name: 'map' }) +}); + +// aliases +var fn = thdfn; +fn.promise = fn.run; +fn.terminate = fn.halt = fn.stop; +fn.include = fn.require; + +// pull in event apis +util.extend(thdfn, { + on: define.on(), + one: define.on({ unbindSelfOnTrigger: true }), + off: define.off(), + trigger: define.trigger() +}); + +define.eventAliasesOn( thdfn ); + +module.exports = Thread; + +},{"./define":44,"./event":45,"./is":83,"./promise":86,"./util":100,"./window":107,"child_process":undefined,"path":undefined}],99:[function(_dereq_,module,exports){ +'use strict'; + +var is = _dereq_( '../is' ); + +module.exports = { + // get [r, g, b] from #abc or #aabbcc + hex2tuple: function( hex ){ + if( !(hex.length === 4 || hex.length === 7) || hex[0] !== '#' ){ return; } + + var shortHex = hex.length === 4; + var r, g, b; + var base = 16; + + if( shortHex ){ + r = parseInt( hex[1] + hex[1], base ); + g = parseInt( hex[2] + hex[2], base ); + b = parseInt( hex[3] + hex[3], base ); + } else { + r = parseInt( hex[1] + hex[2], base ); + g = parseInt( hex[3] + hex[4], base ); + b = parseInt( hex[5] + hex[6], base ); + } + + return [ r, g, b ]; + }, + + // get [r, g, b, a] from hsl(0, 0, 0) or hsla(0, 0, 0, 0) + hsl2tuple: function( hsl ){ + var ret; + var h, s, l, a, r, g, b; + function hue2rgb( p, q, t ){ + if( t < 0 ) t += 1; + if( t > 1 ) t -= 1; + if( t < 1 / 6 ) return p + (q - p) * 6 * t; + if( t < 1 / 2 ) return q; + if( t < 2 / 3 ) return p + (q - p) * (2 / 3 - t) * 6; + return p; + } + + var m = new RegExp( '^' + this.regex.hsla + '$' ).exec( hsl ); + if( m ){ + + // get hue + h = parseInt( m[1] ); + if( h < 0 ){ + h = ( 360 - (-1 * h % 360) ) % 360; + } else if( h > 360 ){ + h = h % 360; + } + h /= 360; // normalise on [0, 1] + + s = parseFloat( m[2] ); + if( s < 0 || s > 100 ){ return; } // saturation is [0, 100] + s = s / 100; // normalise on [0, 1] + + l = parseFloat( m[3] ); + if( l < 0 || l > 100 ){ return; } // lightness is [0, 100] + l = l / 100; // normalise on [0, 1] + + a = m[4]; + if( a !== undefined ){ + a = parseFloat( a ); + + if( a < 0 || a > 1 ){ return; } // alpha is [0, 1] + } + + // now, convert to rgb + // code from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript + if( s === 0 ){ + r = g = b = Math.round( l * 255 ); // achromatic + } else { + var q = l < 0.5 ? l * (1 + s) : l + s - l * s; + var p = 2 * l - q; + r = Math.round( 255 * hue2rgb( p, q, h + 1 / 3 ) ); + g = Math.round( 255 * hue2rgb( p, q, h ) ); + b = Math.round( 255 * hue2rgb( p, q, h - 1 / 3 ) ); + } + + ret = [ r, g, b, a ]; + } + + return ret; + }, + + // get [r, g, b, a] from rgb(0, 0, 0) or rgba(0, 0, 0, 0) + rgb2tuple: function( rgb ){ + var ret; + + var m = new RegExp( '^' + this.regex.rgba + '$' ).exec( rgb ); + if( m ){ + ret = []; + + var isPct = []; + for( var i = 1; i <= 3; i++ ){ + var channel = m[ i ]; + + if( channel[ channel.length - 1 ] === '%' ){ + isPct[ i ] = true; + } + channel = parseFloat( channel ); + + if( isPct[ i ] ){ + channel = channel / 100 * 255; // normalise to [0, 255] + } + + if( channel < 0 || channel > 255 ){ return; } // invalid channel value + + ret.push( Math.floor( channel ) ); + } + + var atLeastOneIsPct = isPct[1] || isPct[2] || isPct[3]; + var allArePct = isPct[1] && isPct[2] && isPct[3]; + if( atLeastOneIsPct && !allArePct ){ return; } // must all be percent values if one is + + var alpha = m[4]; + if( alpha !== undefined ){ + alpha = parseFloat( alpha ); + + if( alpha < 0 || alpha > 1 ){ return; } // invalid alpha value + + ret.push( alpha ); + } + } + + return ret; + }, + + colorname2tuple: function( color ){ + return this.colors[ color.toLowerCase() ]; + }, + + color2tuple: function( color ){ + return ( is.array( color ) ? color : null ) + || this.colorname2tuple( color ) + || this.hex2tuple( color ) + || this.rgb2tuple( color ) + || this.hsl2tuple( color ); + }, + + colors: { + // special colour names + transparent: [0, 0, 0, 0], // NB alpha === 0 + + // regular colours + aliceblue: [ 240, 248, 255 ], + antiquewhite: [ 250, 235, 215 ], + aqua: [0, 255, 255 ], + aquamarine: [ 127, 255, 212 ], + azure: [ 240, 255, 255 ], + beige: [ 245, 245, 220 ], + bisque: [ 255, 228, 196 ], + black: [0, 0, 0], + blanchedalmond: [ 255, 235, 205 ], + blue: [0, 0, 255 ], + blueviolet: [ 138, 43, 226 ], + brown: [ 165, 42, 42 ], + burlywood: [ 222, 184, 135 ], + cadetblue: [ 95, 158, 160 ], + chartreuse: [ 127, 255, 0], + chocolate: [ 210, 105, 30 ], + coral: [ 255, 127, 80 ], + cornflowerblue: [ 100, 149, 237 ], + cornsilk: [ 255, 248, 220 ], + crimson: [ 220, 20, 60 ], + cyan: [0, 255, 255 ], + darkblue: [0, 0, 139 ], + darkcyan: [0, 139, 139 ], + darkgoldenrod: [ 184, 134, 11 ], + darkgray: [ 169, 169, 169 ], + darkgreen: [0, 100, 0], + darkgrey: [ 169, 169, 169 ], + darkkhaki: [ 189, 183, 107 ], + darkmagenta: [ 139, 0, 139 ], + darkolivegreen: [ 85, 107, 47 ], + darkorange: [ 255, 140, 0], + darkorchid: [ 153, 50, 204 ], + darkred: [ 139, 0, 0], + darksalmon: [ 233, 150, 122 ], + darkseagreen: [ 143, 188, 143 ], + darkslateblue: [ 72, 61, 139 ], + darkslategray: [ 47, 79, 79 ], + darkslategrey: [ 47, 79, 79 ], + darkturquoise: [0, 206, 209 ], + darkviolet: [ 148, 0, 211 ], + deeppink: [ 255, 20, 147 ], + deepskyblue: [0, 191, 255 ], + dimgray: [ 105, 105, 105 ], + dimgrey: [ 105, 105, 105 ], + dodgerblue: [ 30, 144, 255 ], + firebrick: [ 178, 34, 34 ], + floralwhite: [ 255, 250, 240 ], + forestgreen: [ 34, 139, 34 ], + fuchsia: [ 255, 0, 255 ], + gainsboro: [ 220, 220, 220 ], + ghostwhite: [ 248, 248, 255 ], + gold: [ 255, 215, 0], + goldenrod: [ 218, 165, 32 ], + gray: [ 128, 128, 128 ], + grey: [ 128, 128, 128 ], + green: [0, 128, 0], + greenyellow: [ 173, 255, 47 ], + honeydew: [ 240, 255, 240 ], + hotpink: [ 255, 105, 180 ], + indianred: [ 205, 92, 92 ], + indigo: [ 75, 0, 130 ], + ivory: [ 255, 255, 240 ], + khaki: [ 240, 230, 140 ], + lavender: [ 230, 230, 250 ], + lavenderblush: [ 255, 240, 245 ], + lawngreen: [ 124, 252, 0], + lemonchiffon: [ 255, 250, 205 ], + lightblue: [ 173, 216, 230 ], + lightcoral: [ 240, 128, 128 ], + lightcyan: [ 224, 255, 255 ], + lightgoldenrodyellow: [ 250, 250, 210 ], + lightgray: [ 211, 211, 211 ], + lightgreen: [ 144, 238, 144 ], + lightgrey: [ 211, 211, 211 ], + lightpink: [ 255, 182, 193 ], + lightsalmon: [ 255, 160, 122 ], + lightseagreen: [ 32, 178, 170 ], + lightskyblue: [ 135, 206, 250 ], + lightslategray: [ 119, 136, 153 ], + lightslategrey: [ 119, 136, 153 ], + lightsteelblue: [ 176, 196, 222 ], + lightyellow: [ 255, 255, 224 ], + lime: [0, 255, 0], + limegreen: [ 50, 205, 50 ], + linen: [ 250, 240, 230 ], + magenta: [ 255, 0, 255 ], + maroon: [ 128, 0, 0], + mediumaquamarine: [ 102, 205, 170 ], + mediumblue: [0, 0, 205 ], + mediumorchid: [ 186, 85, 211 ], + mediumpurple: [ 147, 112, 219 ], + mediumseagreen: [ 60, 179, 113 ], + mediumslateblue: [ 123, 104, 238 ], + mediumspringgreen: [0, 250, 154 ], + mediumturquoise: [ 72, 209, 204 ], + mediumvioletred: [ 199, 21, 133 ], + midnightblue: [ 25, 25, 112 ], + mintcream: [ 245, 255, 250 ], + mistyrose: [ 255, 228, 225 ], + moccasin: [ 255, 228, 181 ], + navajowhite: [ 255, 222, 173 ], + navy: [0, 0, 128 ], + oldlace: [ 253, 245, 230 ], + olive: [ 128, 128, 0], + olivedrab: [ 107, 142, 35 ], + orange: [ 255, 165, 0], + orangered: [ 255, 69, 0], + orchid: [ 218, 112, 214 ], + palegoldenrod: [ 238, 232, 170 ], + palegreen: [ 152, 251, 152 ], + paleturquoise: [ 175, 238, 238 ], + palevioletred: [ 219, 112, 147 ], + papayawhip: [ 255, 239, 213 ], + peachpuff: [ 255, 218, 185 ], + peru: [ 205, 133, 63 ], + pink: [ 255, 192, 203 ], + plum: [ 221, 160, 221 ], + powderblue: [ 176, 224, 230 ], + purple: [ 128, 0, 128 ], + red: [ 255, 0, 0], + rosybrown: [ 188, 143, 143 ], + royalblue: [ 65, 105, 225 ], + saddlebrown: [ 139, 69, 19 ], + salmon: [ 250, 128, 114 ], + sandybrown: [ 244, 164, 96 ], + seagreen: [ 46, 139, 87 ], + seashell: [ 255, 245, 238 ], + sienna: [ 160, 82, 45 ], + silver: [ 192, 192, 192 ], + skyblue: [ 135, 206, 235 ], + slateblue: [ 106, 90, 205 ], + slategray: [ 112, 128, 144 ], + slategrey: [ 112, 128, 144 ], + snow: [ 255, 250, 250 ], + springgreen: [0, 255, 127 ], + steelblue: [ 70, 130, 180 ], + tan: [ 210, 180, 140 ], + teal: [0, 128, 128 ], + thistle: [ 216, 191, 216 ], + tomato: [ 255, 99, 71 ], + turquoise: [ 64, 224, 208 ], + violet: [ 238, 130, 238 ], + wheat: [ 245, 222, 179 ], + white: [ 255, 255, 255 ], + whitesmoke: [ 245, 245, 245 ], + yellow: [ 255, 255, 0], + yellowgreen: [ 154, 205, 50 ] + } +}; + +},{"../is":83}],100:[function(_dereq_,module,exports){ +'use strict'; + +/*global console */ + +var is = _dereq_( '../is' ); +var math = _dereq_( '../math' ); + +var util = { + + trueify: function(){ return true; }, + + falsify: function(){ return false; }, + + zeroify: function(){ return 0; }, + + noop: function(){}, + + error: function( msg ){ + /* eslint-disable */ + if( console.error ){ + console.error.apply( console, arguments ); + + if( console.trace ){ console.trace(); } + } else { + console.log.apply( console, arguments ); + + if( console.trace ){ console.trace(); } + } + /* eslint-enable */ + }, + + clone: function( obj ){ + return this.extend( {}, obj ); + }, + + // gets a shallow copy of the argument + copy: function( obj ){ + if( obj == null ){ + return obj; + } if( is.array( obj ) ){ + return obj.slice(); + } else if( is.plainObject( obj ) ){ + return this.clone( obj ); + } else { + return obj; + } + }, + + uuid: function( + a,b // placeholders + ){ + for( // loop :) + b=a=''; // b - result , a - numeric variable + a++<36; // + b+=a*51&52 // if "a" is not 9 or 14 or 19 or 24 + ? // return a random number or 4 + ( + a^15 // if "a" is not 15 + ? // genetate a random number from 0 to 15 + 8^Math.random()* + (a^20?16:4) // unless "a" is 20, in which case a random number from 8 to 11 + : + 4 // otherwise 4 + ).toString(16) + : + '-' // in other cases (if "a" is 9,14,19,24) insert "-" + ); + return b; + } + +}; + +util.makeBoundingBox = math.makeBoundingBox.bind( math ); + +util._staticEmptyObject = {}; + +util.staticEmptyObject = function(){ + return util._staticEmptyObject; +}; + +util.extend = Object.assign != null ? Object.assign : function( tgt ){ + var args = arguments; + + for( var i = 1; i < args.length; i++ ){ + var obj = args[ i ]; + + if( !obj ){ continue; } + + var keys = Object.keys( obj ); + + for( var j = 0; j < keys.length; j++ ){ + var k = keys[j]; + + tgt[ k ] = obj[ k ]; + } + } + + return tgt; +}; + +util.default = function( val, def ){ + if( val === undefined ){ + return def; + } else { + return val; + } +}; + +util.removeFromArray = function( arr, ele, manyCopies ){ + for( var i = arr.length; i >= 0; i-- ){ + if( arr[i] === ele ){ + arr.splice( i, 1 ); + + if( !manyCopies ){ break; } + } + } +}; + +util.clearArray = function( arr ){ + arr.splice( 0, arr.length ); +}; + +util.getPrefixedProperty = function( obj, propName, prefix ){ + if( prefix ){ + propName = this.prependCamel( prefix, propName ); // e.g. (labelWidth, source) => sourceLabelWidth + } + + return obj[ propName ]; +}; + +util.setPrefixedProperty = function( obj, propName, prefix, value ){ + if( prefix ){ + propName = this.prependCamel( prefix, propName ); // e.g. (labelWidth, source) => sourceLabelWidth + } + + obj[ propName ] = value; +}; + +[ + _dereq_( './colors' ), + _dereq_( './maps' ), + { memoize: _dereq_( './memoize' ) }, + _dereq_( './regex' ), + _dereq_( './strings' ), + _dereq_( './timing' ) +].forEach( function( req ){ + util.extend( util, req ); +} ); + +module.exports = util; + +},{"../is":83,"../math":85,"./colors":99,"./maps":101,"./memoize":102,"./regex":103,"./strings":104,"./timing":105}],101:[function(_dereq_,module,exports){ +'use strict'; + +var is = _dereq_( '../is' ); + +module.exports = { + // has anything been set in the map + mapEmpty: function( map ){ + var empty = true; + + if( map != null ){ + return Object.keys( map ).length === 0; + } + + return empty; + }, + + // pushes to the array at the end of a map (map may not be built) + pushMap: function( options ){ + var array = this.getMap( options ); + + if( array == null ){ // if empty, put initial array + this.setMap( this.extend( {}, options, { + value: [ options.value ] + } ) ); + } else { + array.push( options.value ); + } + }, + + // sets the value in a map (map may not be built) + setMap: function( options ){ + var obj = options.map; + var key; + var keys = options.keys; + var l = keys.length; + + for( var i = 0; i < l; i++ ){ + var key = keys[ i ]; + + if( is.plainObject( key ) ){ + this.error( 'Tried to set map with object key' ); + } + + if( i < keys.length - 1 ){ + + // extend the map if necessary + if( obj[ key ] == null ){ + obj[ key ] = {}; + } + + obj = obj[ key ]; + } else { + // set the value + obj[ key ] = options.value; + } + } + }, + + // gets the value in a map even if it's not built in places + getMap: function( options ){ + var obj = options.map; + var keys = options.keys; + var l = keys.length; + + for( var i = 0; i < l; i++ ){ + var key = keys[ i ]; + + if( is.plainObject( key ) ){ + this.error( 'Tried to get map with object key' ); + } + + obj = obj[ key ]; + + if( obj == null ){ + return obj; + } + } + + return obj; + }, + + // deletes the entry in the map + deleteMap: function( options ){ + var obj = options.map; + var keys = options.keys; + var l = keys.length; + var keepChildren = options.keepChildren; + + for( var i = 0; i < l; i++ ){ + var key = keys[ i ]; + + if( is.plainObject( key ) ){ + this.error( 'Tried to delete map with object key' ); + } + + var lastKey = i === options.keys.length - 1; + if( lastKey ){ + + if( keepChildren ){ // then only delete child fields not in keepChildren + var children = Object.keys( obj ); + + for( var j = 0; j < children.length; j++ ){ + var child = children[j]; + + if( !keepChildren[ child ] ){ + obj[ child ] = undefined; + } + } + } else { + obj[ key ] = undefined; + } + + } else { + obj = obj[ key ]; + } + } + } +}; + +},{"../is":83}],102:[function(_dereq_,module,exports){ +'use strict'; + +module.exports = function memoize( fn, keyFn ){ + if( !keyFn ){ + keyFn = function(){ + if( arguments.length === 1 ){ + return arguments[0]; + } else if( arguments.length === 0 ){ + return 'undefined'; + } + + var args = []; + + for( var i = 0; i < arguments.length; i++ ){ + args.push( arguments[ i ] ); + } + + return args.join( '$' ); + }; + } + + var memoizedFn = function(){ + var self = this; + var args = arguments; + var ret; + var k = keyFn.apply( self, args ); + var cache = memoizedFn.cache; + + if( !(ret = cache[ k ]) ){ + ret = cache[ k ] = fn.apply( self, args ); + } + + return ret; + }; + + memoizedFn.cache = {}; + + return memoizedFn; +}; + +},{}],103:[function(_dereq_,module,exports){ +'use strict'; + +var number = '(?:[-+]?(?:(?:\\d+|\\d*\\.\\d+)(?:[Ee][+-]?\\d+)?))'; + +var rgba = 'rgb[a]?\\((' + number + '[%]?)\\s*,\\s*(' + number + '[%]?)\\s*,\\s*(' + number + '[%]?)(?:\\s*,\\s*(' + number + '))?\\)'; +var rgbaNoBackRefs = 'rgb[a]?\\((?:' + number + '[%]?)\\s*,\\s*(?:' + number + '[%]?)\\s*,\\s*(?:' + number + '[%]?)(?:\\s*,\\s*(?:' + number + '))?\\)'; + +var hsla = 'hsl[a]?\\((' + number + ')\\s*,\\s*(' + number + '[%])\\s*,\\s*(' + number + '[%])(?:\\s*,\\s*(' + number + '))?\\)'; +var hslaNoBackRefs = 'hsl[a]?\\((?:' + number + ')\\s*,\\s*(?:' + number + '[%])\\s*,\\s*(?:' + number + '[%])(?:\\s*,\\s*(?:' + number + '))?\\)'; + +var hex3 = '\\#[0-9a-fA-F]{3}'; +var hex6 = '\\#[0-9a-fA-F]{6}'; + +module.exports = { + regex: { + number: number, + rgba: rgba, + rgbaNoBackRefs: rgbaNoBackRefs, + hsla: hsla, + hslaNoBackRefs: hslaNoBackRefs, + hex3: hex3, + hex6: hex6 + } +}; + +},{}],104:[function(_dereq_,module,exports){ +'use strict'; + +var memoize = _dereq_( './memoize' ); +var is = _dereq_( '../is' ); + +module.exports = { + + camel2dash: memoize( function( str ){ + return str.replace( /([A-Z])/g, function( v ){ + return '-' + v.toLowerCase(); + } ); + } ), + + dash2camel: memoize( function( str ){ + return str.replace( /(-\w)/g, function( v ){ + return v[1].toUpperCase(); + } ); + } ), + + prependCamel: memoize( function( prefix, str ){ + return prefix + str[0].toUpperCase() + str.substring(1); + }, function( prefix, str ){ + return prefix + '$' + str; + } ), + + capitalize: function( str ){ + if( is.emptyString( str ) ){ + return str; + } + + return str.charAt( 0 ).toUpperCase() + str.substring( 1 ); + } + +}; + +},{"../is":83,"./memoize":102}],105:[function(_dereq_,module,exports){ +'use strict'; + +var window = _dereq_( '../window' ); +var is = _dereq_( '../is' ); +var performance = window ? window.performance : null; + +var util = {}; + +var raf = !window ? null : ( window.requestAnimationFrame || window.mozRequestAnimationFrame || + window.webkitRequestAnimationFrame || window.msRequestAnimationFrame ); + +raf = raf || function( fn ){ + if( fn ){ + setTimeout( function(){ + fn( pnow() ); + }, 1000 / 60 ); + } +}; + +util.requestAnimationFrame = function( fn ){ + raf( fn ); +}; + +var pnow = performance && performance.now ? function(){ return performance.now(); } : function(){ return Date.now(); }; + +util.performanceNow = pnow; + +// ported lodash throttle function +util.throttle = function( func, wait, options ){ + var leading = true, + trailing = true; + + if( options === false ){ + leading = false; + } else if( is.plainObject( options ) ){ + leading = 'leading' in options ? options.leading : leading; + trailing = 'trailing' in options ? options.trailing : trailing; + } + options = options || {}; + options.leading = leading; + options.maxWait = wait; + options.trailing = trailing; + + return util.debounce( func, wait, options ); +}; + +util.now = function(){ + return Date.now(); +}; + +util.debounce = function( func, wait, options ){ // ported lodash debounce function + var util = this; + var args, + maxTimeoutId, + result, + stamp, + thisArg, + timeoutId, + trailingCall, + lastCalled = 0, + maxWait = false, + trailing = true; + + if( !is.fn( func ) ){ + return; + } + wait = Math.max( 0, wait ) || 0; + if( options === true ){ + var leading = true; + trailing = false; + } else if( is.plainObject( options ) ){ + leading = options.leading; + maxWait = 'maxWait' in options && (Math.max( wait, options.maxWait ) || 0); + trailing = 'trailing' in options ? options.trailing : trailing; + } + var delayed = function(){ + var remaining = wait - (util.now() - stamp); + if( remaining <= 0 ){ + if( maxTimeoutId ){ + clearTimeout( maxTimeoutId ); + } + var isCalled = trailingCall; + maxTimeoutId = timeoutId = trailingCall = undefined; + if( isCalled ){ + lastCalled = util.now(); + result = func.apply( thisArg, args ); + if( !timeoutId && !maxTimeoutId ){ + args = thisArg = null; + } + } + } else { + timeoutId = setTimeout( delayed, remaining ); + } + }; + + var maxDelayed = function(){ + if( timeoutId ){ + clearTimeout( timeoutId ); + } + maxTimeoutId = timeoutId = trailingCall = undefined; + if( trailing || (maxWait !== wait) ){ + lastCalled = util.now(); + result = func.apply( thisArg, args ); + if( !timeoutId && !maxTimeoutId ){ + args = thisArg = null; + } + } + }; + + return function(){ + args = arguments; + stamp = util.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; + + 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 = null; + } + return result; + }; +}; + +module.exports = util; + +},{"../is":83,"../window":107}],106:[function(_dereq_,module,exports){ +module.exports="2.7.8" +},{}],107:[function(_dereq_,module,exports){ +module.exports = ( typeof window === 'undefined' ? null : window ); // eslint-disable-line no-undef + +},{}]},{},[82])(82) +}); + diff --git a/wqflask/wqflask/static/packages/cytoscape/js/src/json2.js b/wqflask/wqflask/static/packages/cytoscape/js/src/json2.js new file mode 100644 index 00000000..c422a6e1 --- /dev/null +++ b/wqflask/wqflask/static/packages/cytoscape/js/src/json2.js @@ -0,0 +1,479 @@ +/* + http://www.JSON.org/json2.js + 2009-09-29 + + Public Domain. + + NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + + See http://www.JSON.org/js.html + + This file creates a global JSON object containing two methods: stringify + and parse. + + JSON.stringify(value, replacer, space) + value any JavaScript value, usually an object or array. + + replacer an optional parameter that determines how object + values are stringified for objects. It can be a + function or an array of strings. + + space an optional parameter that specifies the indentation + of nested structures. If it is omitted, the text will + be packed without extra whitespace. If it is a number, + it will specify the number of spaces to indent at each + level. If it is a string (such as '\t' or ' '), + it contains the characters used to indent at each level. + + This method produces a JSON text from a JavaScript value. + + When an object value is found, if the object contains a toJSON + method, its toJSON method will be called and the result will be + stringified. A toJSON method does not serialize: it returns the + value represented by the name/value pair that should be serialized, + or undefined if nothing should be serialized. The toJSON method + will be passed the key associated with the value, and this will be + bound to the value + + For example, this would serialize Dates as ISO strings. + + Date.prototype.toJSON = function (key) { + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + return this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z'; + }; + + You can provide an optional replacer method. It will be passed the + key and value of each member, with this bound to the containing + object. The value that is returned from your method will be + serialized. If your method returns undefined, then the member will + be excluded from the serialization. + + If the replacer parameter is an array of strings, then it will be + used to select the members to be serialized. It filters the results + such that only members with keys listed in the replacer array are + stringified. + + Values that do not have JSON representations, such as undefined or + functions, will not be serialized. Such values in objects will be + dropped; in arrays they will be replaced with null. You can use + a replacer function to replace those with JSON values. + JSON.stringify(undefined) returns undefined. + + The optional space parameter produces a stringification of the + value that is filled with line breaks and indentation to make it + easier to read. + + If the space parameter is a non-empty string, then that string will + be used for indentation. If the space parameter is a number, then + the indentation will be that many spaces. + + Example: + + text = JSON.stringify(['e', {pluribus: 'unum'}]); + // text is '["e",{"pluribus":"unum"}]' + + + text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); + // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' + + text = JSON.stringify([new Date()], function (key, value) { + return this[key] instanceof Date ? + 'Date(' + this[key] + ')' : value; + }); + // text is '["Date(---current time---)"]' + + + JSON.parse(text, reviver) + This method parses a JSON text to produce an object or array. + It can throw a SyntaxError exception. + + The optional reviver parameter is a function that can filter and + transform the results. It receives each of the keys and values, + and its return value is used instead of the original value. + If it returns what it received, then the structure is not modified. + If it returns undefined then the member is deleted. + + Example: + + // Parse the text. Values that look like ISO date strings will + // be converted to Date objects. + + myData = JSON.parse(text, function (key, value) { + var a; + if (typeof value === 'string') { + a = +/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); + if (a) { + return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], + +a[5], +a[6])); + } + } + return value; + }); + + myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { + var d; + if (typeof value === 'string' && + value.slice(0, 5) === 'Date(' && + value.slice(-1) === ')') { + d = new Date(value.slice(5, -1)); + if (d) { + return d; + } + } + return value; + }); + + + This is a reference implementation. You are free to copy, modify, or + redistribute. + + This code should be minified before deployment. + See http://javascript.crockford.com/jsmin.html + + USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO + NOT CONTROL. +*/ + +/*jslint evil: true, strict: false */ + +/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, + call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, + getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, + lastIndex, length, parse, prototype, push, replace, slice, stringify, + test, toJSON, toString, valueOf +*/ + + +// Create a JSON object only if one does not already exist. We create the +// methods in a closure to avoid creating global variables. + +if (!this.JSON) { + this.JSON = {}; +} + +(function () { + + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + if (typeof Date.prototype.toJSON !== 'function') { + + Date.prototype.toJSON = function (key) { + + return isFinite(this.valueOf()) ? + this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z' : null; + }; + + String.prototype.toJSON = + Number.prototype.toJSON = + Boolean.prototype.toJSON = function (key) { + return this.valueOf(); + }; + } + + var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + gap, + indent, + meta = { // table of character substitutions + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"' : '\\"', + '\\': '\\\\' + }, + rep; + + + function quote(string) { + +// If the string contains no control characters, no quote characters, and no +// backslash characters, then we can safely slap some quotes around it. +// Otherwise we must also replace the offending characters with safe escape +// sequences. + + escapable.lastIndex = 0; + return escapable.test(string) ? + '"' + string.replace(escapable, function (a) { + var c = meta[a]; + return typeof c === 'string' ? c : + '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }) + '"' : + '"' + string + '"'; + } + + + function str(key, holder) { + +// Produce a string from holder[key]. + + var i, // The loop counter. + k, // The member key. + v, // The member value. + length, + mind = gap, + partial, + value = holder[key]; + +// If the value has a toJSON method, call it to obtain a replacement value. + + if (value && typeof value === 'object' && + typeof value.toJSON === 'function') { + value = value.toJSON(key); + } + +// If we were called with a replacer function, then call the replacer to +// obtain a replacement value. + + if (typeof rep === 'function') { + value = rep.call(holder, key, value); + } + +// What happens next depends on the value's type. + + switch (typeof value) { + case 'string': + return quote(value); + + case 'number': + +// JSON numbers must be finite. Encode non-finite numbers as null. + + return isFinite(value) ? String(value) : 'null'; + + case 'boolean': + case 'null': + +// If the value is a boolean or null, convert it to a string. Note: +// typeof null does not produce 'null'. The case is included here in +// the remote chance that this gets fixed someday. + + return String(value); + +// If the type is 'object', we might be dealing with an object or an array or +// null. + + case 'object': + +// Due to a specification blunder in ECMAScript, typeof null is 'object', +// so watch out for that case. + + if (!value) { + return 'null'; + } + +// Make an array to hold the partial results of stringifying this object value. + + gap += indent; + partial = []; + +// Is the value an array? + + if (Object.prototype.toString.apply(value) === '[object Array]') { + +// The value is an array. Stringify every element. Use null as a placeholder +// for non-JSON values. + + length = value.length; + for (i = 0; i < length; i += 1) { + partial[i] = str(i, value) || 'null'; + } + +// Join all of the elements together, separated with commas, and wrap them in +// brackets. + + v = partial.length === 0 ? '[]' : + gap ? '[\n' + gap + + partial.join(',\n' + gap) + '\n' + + mind + ']' : + '[' + partial.join(',') + ']'; + gap = mind; + return v; + } + +// If the replacer is an array, use it to select the members to be stringified. + + if (rep && typeof rep === 'object') { + length = rep.length; + for (i = 0; i < length; i += 1) { + k = rep[i]; + if (typeof k === 'string') { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } else { + +// Otherwise, iterate through all of the keys in the object. + + for (k in value) { + if (Object.hasOwnProperty.call(value, k)) { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } + +// Join all of the member texts together, separated with commas, +// and wrap them in braces. + + v = partial.length === 0 ? '{}' : + gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + + mind + '}' : '{' + partial.join(',') + '}'; + gap = mind; + return v; + } + } + +// If the JSON object does not yet have a stringify method, give it one. + + if (typeof JSON.stringify !== 'function') { + JSON.stringify = function (value, replacer, space) { + +// The stringify method takes a value and an optional replacer, and an optional +// space parameter, and returns a JSON text. The replacer can be a function +// that can replace values, or an array of strings that will select the keys. +// A default replacer method can be provided. Use of the space parameter can +// produce text that is more easily readable. + + var i; + gap = ''; + indent = ''; + +// If the space parameter is a number, make an indent string containing that +// many spaces. + + if (typeof space === 'number') { + for (i = 0; i < space; i += 1) { + indent += ' '; + } + +// If the space parameter is a string, it will be used as the indent string. + + } else if (typeof space === 'string') { + indent = space; + } + +// If there is a replacer, it must be a function or an array. +// Otherwise, throw an error. + + rep = replacer; + if (replacer && typeof replacer !== 'function' && + (typeof replacer !== 'object' || + typeof replacer.length !== 'number')) { + throw new Error('JSON.stringify'); + } + +// Make a fake root object containing our value under the key of ''. +// Return the result of stringifying the value. + + return str('', {'': value}); + }; + } + + +// If the JSON object does not yet have a parse method, give it one. + + if (typeof JSON.parse !== 'function') { + JSON.parse = function (text, reviver) { + +// The parse method takes a text and an optional reviver function, and returns +// a JavaScript value if the text is a valid JSON text. + + var j; + + function walk(holder, key) { + +// The walk method is used to recursively walk the resulting structure so +// that modifications can be made. + + var k, v, value = holder[key]; + if (value && typeof value === 'object') { + for (k in value) { + if (Object.hasOwnProperty.call(value, k)) { + v = walk(value, k); + if (v !== undefined) { + value[k] = v; + } else { + delete value[k]; + } + } + } + } + return reviver.call(holder, key, value); + } + + +// Parsing happens in four stages. In the first stage, we replace certain +// Unicode characters with escape sequences. JavaScript handles many characters +// incorrectly, either silently deleting them, or treating them as line endings. + + cx.lastIndex = 0; + if (cx.test(text)) { + text = text.replace(cx, function (a) { + return '\\u' + + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }); + } + +// In the second stage, we run the text against regular expressions that look +// for non-JSON patterns. We are especially concerned with '()' and 'new' +// because they can cause invocation, and '=' because it can cause mutation. +// But just to be safe, we want to reject all unexpected forms. + +// We split the second stage into 4 regexp operations in order to work around +// crippling inefficiencies in IE's and Safari's regexp engines. First we +// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we +// replace all simple value tokens with ']' characters. Third, we delete all +// open brackets that follow a colon or comma or that begin the text. Finally, +// we look to see that the remaining characters are only whitespace or ']' or +// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. + + if (/^[\],:{}\s]*$/. +test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@'). +replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'). +replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { + +// In the third stage we use the eval function to compile the text into a +// JavaScript structure. The '{' operator is subject to a syntactic ambiguity +// in JavaScript: it can begin a block or an object literal. We wrap the text +// in parens to eliminate the ambiguity. + + j = eval('(' + text + ')'); + +// In the optional fourth stage, we recursively walk the new structure, passing +// each name/value pair to a reviver function for possible transformation. + + return typeof reviver === 'function' ? + walk({'': j}, '') : j; + } + +// If the text is not JSON parseable, then a SyntaxError is thrown. + + throw new SyntaxError('JSON.parse'); + }; + } +}()); diff --git a/wqflask/wqflask/static/packages/cytoscape/swf/CytoscapeWeb.swf b/wqflask/wqflask/static/packages/cytoscape/swf/CytoscapeWeb.swf Binary files differnew file mode 100644 index 00000000..82eabc47 --- /dev/null +++ b/wqflask/wqflask/static/packages/cytoscape/swf/CytoscapeWeb.swf diff --git a/wqflask/wqflask/static/packages/cytoscape/swf/playerProductInstall.swf b/wqflask/wqflask/static/packages/cytoscape/swf/playerProductInstall.swf Binary files differnew file mode 100644 index 00000000..bdc34378 --- /dev/null +++ b/wqflask/wqflask/static/packages/cytoscape/swf/playerProductInstall.swf diff --git a/wqflask/wqflask/templates/base.html b/wqflask/wqflask/templates/base.html index 6af07edc..210c5708 100644 --- a/wqflask/wqflask/templates/base.html +++ b/wqflask/wqflask/templates/base.html @@ -80,9 +80,9 @@ </div> </div> </div> - + <div class="container-fluid" style="background-color: #d5d5d5; height: 95px;"> - + <form method="get" action="/gsearch"> <div class="row"> <select class="form-control col-xs-2" style="width: 170px; margin-top: 15px; margin-left: 10px;" name="type"> @@ -95,68 +95,58 @@ </form> </div> - {% block content %}{% endblock %} + {% block content %} + {% endblock %} - <!-- Footer - ================================================== --> <footer class="footer"> <div class="container"> - <p class="pull-right"><a href="#">Back to top</a></p> - - <p>Launched in 1994 as - <A HREF="http://www.ncbi.nlm.nih.gov/pubmed?term=8043953"> - The Portable Dictionary of the Mouse Genome</A> and in 2001 as WebQTL. - </p> - <p>Operated by - <A HREF="mailto:rwilliams@uthsc.edu">Rob Williams</A>, - <A HREF="mailto:lyan6@uthsc.edu">Lei Yan</A>, - <A HREF="mailto:zachary.a.sloan@gmail.com">Zachary Sloan</A>, and - <A HREF="mailto:acenteno@uthsc.edu" target="_blank">Arthur Centeno</A>. + <p>GeneNetwork is a framework for web based genetics + launched in 1994 as + <a href="http://www.ncbi.nlm.nih.gov/pubmed?term=8043953"> + The Portable Dictionary of the Mouse Genome</a> (previously <a href="https://www.ncbi.nlm.nih.gov/pubmed/15043217">WebQTL</a>). </p> <p> - Designed and coded by <a href="http://penguinpython.com">Sam Ockman</a>, Xiaodong Zhou, - Christian Fernandez, - Ning Liu, Rudi Alberts, Elissa Chesler, Jintao Wang, Kenneth Manly, Robert W. Williams, - and <A HREF="/credit.html">colleagues</A>. + Operated by + <a href="mailto:rwilliams@uthsc.edu">Rob Williams</a>, + <a href="mailto:lyan6@uthsc.edu">Lei Yan</a>, + <a href="mailto:zachary.a.sloan@gmail.com">Zachary Sloan</a>, + <a href="mailto:acenteno@uthsc.edu">Arthur Centeno</a> and + <a href="http://thebird.nl/">Pjotr Prins</a>. </p> - - <p>Built with <a href="http://twitter.github.com/bootstrap/">bootstrap</a>, - <a href="http://coffeescript.org/">coffeescript</a>, - <a href="http://flask.pocoo.org/">flask</a>, - <a href="http://en.wikipedia.org/wiki/Linux">linux</a>, - <a href="http://www.python.org/">python</a> and good intentions. + <p>Published in + <a href="http://joss.theoj.org/papers/10.21105/joss.00025"><img src="https://camo.githubusercontent.com/846b750f582ae8f1d0b4f7e8fee78bed705c88ba/687474703a2f2f6a6f73732e7468656f6a2e6f72672f7061706572732f31302e32313130352f6a6f73732e30303032352f7374617475732e737667" alt="JOSS" data-canonical-src="http://joss.theoj.org/papers/10.21105/joss.00025/status.svg" style="max-width:100%;"></a> </p> - <br /> + <br /> <p>GeneNetwork is supported by:</p> <UL> <LI> - <a target="_blank" href="http://citg.uthsc.edu"> + <a href="http://citg.uthsc.edu"> The UT Center for Integrative and Translational Genomics </A> </li> - <LI><a target="_blank" href="http://www.iniastress.org">NIAAA</A> + <LI><a href="http://www.iniastress.org">NIAAA</A> Integrative Neuroscience Initiative on Alcoholism (U01 AA016662, U01 AA013499, U24 AA013513, U01 AA014425) </li> <LI> - <a target="_blank" - href="http://www.drugabuse.gov/about/organization/Genetics/geneexpression/index.html">NIDA</A>, <a class="smallsize" target="_blank" href="http://www.nimh.nih.gov/">NIMH</A> - , and <a class="smallsize" target="_blank" href="http://www.niaaa.nih.gov/"> + <a + href="https://www.drugabuse.gov/">NIDA</A>, <a class="smallsize" href="http://www.nimh.nih.gov/">NIMH</A> + , and <a class="smallsize" href="http://www.niaaa.nih.gov/"> NIAAA</A> (P20-DA 21131) </li> - <LI>NCI <a target="_blank" href="http://emice.nci.nih.gov/">MMHCC</A> (U01CA105417) and - <a target="_blank" href="http://www.ncrr.nih.gov/">NCRR</A> - <a target="_blank" href="http://www.nbirn.net/TestBeds/Mouse/index.htm">BIRN</A> + <LI>NCI <a href="http://emice.nci.nih.gov/">MMHCC</A> (U01CA105417) and + <a href="https://en.wikipedia.org/wiki/National_Center_for_Research_Resources">NCRR</a> + <a href="https://en.wikipedia.org/wiki/Biomedical_Informatics_Research_Network">BIRN</a> (U24 RR021760) </li> </UL> <!--</p>--> + <p> + Development and source code on <a href="https://github.com/genenetwork/">github</a> with <a href="https://github.com/genenetwork/genenetwork2/issues">issue tracker</a> and <a href="https://github.com/genenetwork/genenetwork2/blob/master/README.md">documentation</a>. Join the <a href="http://listserv.uthsc.edu/mailman/listinfo/genenetwork-dev">mailing list</a> and find us on <a href="https://webchat.freenode.net/">IRC</a> (#genenetwork channel). + {% if version: %} + <p><small>GeneNetwork v{{ version }}</small></p> + {% endif %} - <ul class="footer-links"> - <li><a href="http://listserv.uthsc.edu/mailman/listinfo/genenetwork-dev">Join the mailing list</a></li> - <!--<li><a href="#">Friend us on facebook</a></li>--> - <!--<li><a href="#">Follow us on twitter</a></li>--> - </ul> </div> </footer> diff --git a/wqflask/wqflask/templates/collections/add.html b/wqflask/wqflask/templates/collections/add.html index f4a69423..d45aa015 100644 --- a/wqflask/wqflask/templates/collections/add.html +++ b/wqflask/wqflask/templates/collections/add.html @@ -6,16 +6,6 @@ </div> <div class="modal-body"> <form action="/collections/new" data-validate="parsley" id="add_form"> -<!-- - <fieldset> - <legend>Use your default collection</legend> - <span class="help-block">Choose this if you're in a hurry or don't plan on using the collection again.</span> - <span class="help-block"><em></em>If you are unsure this is probably the option you want.</em></span> - <button type="submit" name="Default" class="btn">Continue</button> - </fieldset> - <hr /> ---> - <input type="hidden" name="traits" value="{{ traits }}" /> <fieldset> <legend>Create a new named collection</legend> @@ -23,9 +13,11 @@ <input type="text" name="new_collection" placeholder="Name of new collection..." data-trigger="change" data-minlength="5" data-maxlength="50"> <span class="help-block">Type the name of the new collection.</span> + {% if uc is not defined %} + <span class="help-block" style="color:red;">This collection will be saved to this computer for 5 days.</span> + {% endif %} <button type="submit" name="create_new" class="btn">Create and add traits</button> </fieldset> - <hr /> <fieldset> <legend>Or add to an existing collection</legend> @@ -33,7 +25,7 @@ <select name="existing_collection" class="form-control"> {% for col in collections %} - <option value="{{ col.id }}">{{ col.name }}</option> + <option value="{{ col.id }}:{{ col.name }}">{{ col.name }}</option> {% endfor %} </select> <br /> diff --git a/wqflask/wqflask/templates/collections/list.html b/wqflask/wqflask/templates/collections/list.html index a26e77ef..23e976e9 100644 --- a/wqflask/wqflask/templates/collections/list.html +++ b/wqflask/wqflask/templates/collections/list.html @@ -26,7 +26,7 @@ {% endif %} </div> - <div id="collections_list"> + <div id="collections_list" style="width:75%;"> <table class="table table-hover table-striped" id='trait_table'> <thead> <tr> diff --git a/wqflask/wqflask/templates/collections/view.html b/wqflask/wqflask/templates/collections/view.html index 68d2886f..8fc5f120 100644 --- a/wqflask/wqflask/templates/collections/view.html +++ b/wqflask/wqflask/templates/collections/view.html @@ -21,64 +21,46 @@ <div class="container"> <div> - <form action="/collections/delete" method="post"> - {% if uc %} - <input type="hidden" name="uc_id" id="uc_id" value="{{ uc.id }}" /> - {% else %} - <input type="hidden" name="collection_name" id="collection_name" value="{{ collection_name }}" /> - {% endif %} - <div class="col-xs-3 controls"> - <input type="submit" class="btn btn-danger" value="Delete this collection" /> - </div> - </form> - <form action="/corr_matrix" method="post"> - {% if uc %} - <input type="hidden" name="uc_id" id="uc_id" value="{{ uc.id }}" /> - {% endif %} - <input type="hidden" name="trait_list" id="trait_list" value= " - {% for this_trait in trait_obs %} - {{ this_trait.name }}:{{ this_trait.dataset.name }}, - {% endfor %}" > - <div class="col-xs-2 controls"> - <input type="submit" class="btn btn-primary" value="Correlation Matrix" /> - </div> - </form> - <form action="/wgcna_setup" method="post"> - {% if uc %} - <input type="hidden" name="uc_id" id="uc_id" value="{{ uc.id }}" /> - {% endif %} - <input type="hidden" name="trait_list" id="trait_list" value= " - {% for this_trait in trait_obs %} - {{ this_trait.name }}:{{ this_trait.dataset.name }}, - {% endfor %}" > - <div class="col-xs-2 controls"> - <input type="submit" class="btn btn-primary" value="WGCNA Analysis" /> - </div> - </form> - <form action="/ctl_setup" method="post"> - {% if uc %} - <input type="hidden" name="uc_id" id="uc_id" value="{{ uc.id }}" /> - {% endif %} - <input type="hidden" name="trait_list" id="trait_list" value= " - {% for this_trait in trait_obs %} - {{ this_trait.name }}:{{ this_trait.dataset.name }}, - {% endfor %}" > - <div class="col-xs-2 controls"> - <input type="submit" class="btn btn-primary" value="CTL Analysis" /> - </div> - </form> - <form action="/heatmap" method="post"> - {% if uc %} - <input type="hidden" name="uc_id" id="uc_id" value="{{ uc.id }}" /> - {% endif %} - <input type="hidden" name="trait_list" id="trait_list" value= " - {% for this_trait in trait_obs %} - {{ this_trait.name }}:{{ this_trait.dataset.name }}, - {% endfor %}" > - <div class="col-xs-2 controls"> - <input type="submit" class="btn btn-primary" value="Heatmap" /> - </div> - </form> + <form id="collection_form" action="/delete" method="post"> + {% if uc %} + <input type="hidden" name="uc_id" id="uc_id" value="{{ uc.id }}" /> + {% endif %} + <input type="hidden" name="collection_name" id="collection_name" value="{{ collection_name }}" /> + <input type="hidden" name="trait_list" id="trait_list" value= " + {% for this_trait in trait_obs %} + {{ this_trait.name }}:{{ this_trait.dataset.name }}, + {% endfor %}" > + <div class="col-xs-3 controls"> + <button id="delete" class="btn btn-danger submit_special" data-url="/collections/delete" title="Delete this collection" > + Delete this collection + </button> + </div> + <div class="col-xs-2 controls"> + <button id="corr_matrix" class="btn btn-primary submit_special" data-url="/corr_matrix" title="Correlation Matrix" > + Correlation Matrix + </button> + </div> + <div class="col-xs-2 controls"> + <button id="network_graph" class="btn btn-primary submit_special" data-url="/network_graph" title="Network Graph" > + Network Graph + </button> + </div> + <div class="col-xs-2 controls"> + <button id="wgcna_setup" class="btn btn-primary submit_special" data-url="/wgcna_setup" title="WGCNA Analysis" > + WGCNA Analysis + </button> + </div> + <div class="col-xs-2 controls"> + <button id="ctl_setup" class="btn btn-primary submit_special" data-url="/ctl_setup" title="CTL Analysis" > + CTL Analysis + </button> + </div> + <div class="col-xs-1 controls"> + <button id="heatmap" class="btn btn-primary submit_special" data-url="/heatmap" title="Heatmap" > + Heatmap + </button> + </div> + </form> </div> <div> @@ -92,53 +74,54 @@ <button class="btn" id="remove" disabled="disabled"><i class="icon-minus-sign"></i> Remove Record</button> <br /> <br /> - <div style="background-color: #eeeeee; border: 1px solid black;"> - <table class="table table-hover table-striped" id='trait_table'> - <thead> - <tr> - <th style="background-color: #eeeeee;"></th> - <th style="background-color: #eeeeee;">Index</th> - <th style="background-color: #eeeeee;">Record</th> - <th style="background-color: #eeeeee;">Description</th> - <th style="background-color: #eeeeee;">Location</th> - <th style="background-color: #eeeeee;">Mean</th> - <th style="background-color: #eeeeee;">Max LRS<a href="http://genenetwork.org//glossary.html#L" target="_blank"><sup style="color:#f00"> ?</sup></a></th> - <th style="background-color: #eeeeee;">Max LRS Location</th> - <th style="background-color: #eeeeee;">Additive Effect<a href="http://genenetwork.org//glossary.html#A" target="_blank"><sup style="color:#f00"> ?</sup></a></th> - </tr> - </thead> - - <tbody> - {% for this_trait in trait_obs %} - <TR id="trait:{{ this_trait.name }}:{{ this_trait.dataset.name }}"> - <TD> - <INPUT TYPE="checkbox" NAME="searchResult" class="checkbox trait_checkbox" - VALUE="{{ data_hmac('{}:{}'.format(this_trait.name, this_trait.dataset.name)) }}"> - </TD> - <TD>{{ loop.index }}</TD> - <TD> - <a href="{{ url_for('show_trait_page', - trait_id = this_trait.name, - dataset = this_trait.dataset.name - )}}"> - {{ this_trait.name }} - </a> - </TD> - - <TD>{{ this_trait.description_display }}</TD> - <TD>{{ this_trait.location_repr }}</TD> - <TD>{{ this_trait.mean }}</TD> - <TD>{{ this_trait.LRS_score_repr }}</TD> - <TD>{{ this_trait.LRS_location_repr }}</TD> - <TD>{{ this_trait.additive }}</TD> - - </TR> - {% endfor %} - </tbody> - - </table> - </div> - <br /> + <div style="background-color: #eeeeee; border: 1px solid black;"> + <table id="trait_table" class="table table-hover table-striped"> + <thead> + <tr> + <th style="background-color: #eeeeee;"></th> + <th style="background-color: #eeeeee;">Index</th> + <th style="background-color: #eeeeee;">Dataset</th> + <th style="background-color: #eeeeee;">Record</th> + <th style="background-color: #eeeeee;">Description</th> + <th style="background-color: #eeeeee;">Location</th> + <th style="background-color: #eeeeee;">Mean</th> + <th style="background-color: #eeeeee;">Max LRS<a href="http://genenetwork.org//glossary.html#L" target="_blank"><sup style="color:#f00"> ?</sup></a></th> + <th style="background-color: #eeeeee;">Max LRS Location</th> + <th style="background-color: #eeeeee;">Additive Effect<a href="http://genenetwork.org//glossary.html#A" target="_blank"><sup style="color:#f00"> ?</sup></a></th> + </tr> + </thead> + + <tbody> + {% for this_trait in trait_obs %} + <TR id="trait:{{ this_trait.name }}:{{ this_trait.dataset.name }}"> + <TD> + <INPUT TYPE="checkbox" NAME="searchResult" class="checkbox trait_checkbox" + VALUE="{{ data_hmac('{}:{}'.format(this_trait.name, this_trait.dataset.name)) }}"> + </TD> + <TD>{{ loop.index }}</TD> + <TD>{{ this_trait.dataset.name }}</TD> + <TD> + <a href="{{ url_for('show_trait_page', + trait_id = this_trait.name, + dataset = this_trait.dataset.name + )}}"> + {{ this_trait.name }} + </a> + </TD> + <TD>{{ this_trait.description_display }}</TD> + <TD>{{ this_trait.location_repr }}</TD> + <TD>{{ '%0.3f' % this_trait.mean|float }}</TD> + <TD>{{ '%0.3f' % this_trait.LRS_score_repr|float }}</TD> + <TD>{{ this_trait.LRS_location_repr }}</TD> + <TD>{{ '%0.3f' % this_trait.additive|float }}</TD> + + </TR> + {% endfor %} + </tbody> + + </table> + </div> + <br /> </div> </div> @@ -175,13 +158,14 @@ { "type": "natural" }, { "type": "natural" }, { "type": "natural" }, + { "type": "natural" }, { "type": "natural", "width": "35%" }, { "type": "natural", "width": "15%" }, { "type": "cust-txt" }, { "type": "natural", - "width": "12%" }, + "width": "9%" }, { "type": "natural", "width": "15%" }, { "type": "natural" } @@ -193,7 +177,7 @@ title: 'collection', fieldBoundary: '"', exportOptions: { - columns: [1, 2, 3, 4, 5, 6, 7, 8] + columns: [1, 2, 3, 4, 5, 6, 7, 8, 9] } } ], @@ -208,6 +192,56 @@ } ); console.timeEnd("Creating table"); + submit_special = function(url) { + $("#collection_form").attr("action", url); + return $("#collection_form").submit(); + }; + + $("#delete").on("click", function() { + url = $(this).data("url") + return submit_special(url) + }); + + $("#corr_matrix").on("click", function() { + traits = $("#trait_table input:checked").map(function() { + return $(this).val(); + }).get(); + $("#trait_list").val(traits) + url = $(this).data("url") + return submit_special(url) + }); + $("#network_graph").on("click", function() { + traits = $("#trait_table input:checked").map(function() { + return $(this).val(); + }).get(); + $("#trait_list").val(traits) + url = $(this).data("url") + return submit_special(url) + }); + $("#wgcna_setup").on("click", function() { + traits = $("#trait_table input:checked").map(function() { + return $(this).val(); + }).get(); + $("#trait_list").val(traits) + url = $(this).data("url") + return submit_special(url) + }); + $("#ctl_setup").on("click", function() { + traits = $("#trait_table input:checked").map(function() { + return $(this).val(); + }).get(); + $("#trait_list").val(traits) + url = $(this).data("url") + return submit_special(url) + }); + $("#heatmap").on("click", function() { + traits = $("#trait_table input:checked").map(function() { + return $(this).val(); + }).get(); + $("#trait_list").val(traits) + url = $(this).data("url") + return submit_special(url) + }); }); </script> diff --git a/wqflask/wqflask/templates/ctl_results.html b/wqflask/wqflask/templates/ctl_results.html index a5cb1c08..00ccecb6 100644 --- a/wqflask/wqflask/templates/ctl_results.html +++ b/wqflask/wqflask/templates/ctl_results.html @@ -4,7 +4,7 @@ {% block content %} <!-- Start of body --> <div class="container"> <h1>CTL Results</h1> - {{(request.form['trait_list'].split(',')|length -1)}} phenotypes as input<br> + {{(request.form['trait_list'].split(',')|length)}} phenotypes as input<br> <h3>Network Figure</h3> <a href="/tmp/{{ results['imgurl1'] }}"> <img alt="Embedded Image" src="data:image/png;base64, diff --git a/wqflask/wqflask/templates/ctl_setup.html b/wqflask/wqflask/templates/ctl_setup.html index 9c0d7bea..a05379a8 100644 --- a/wqflask/wqflask/templates/ctl_setup.html +++ b/wqflask/wqflask/templates/ctl_setup.html @@ -1,65 +1,70 @@ {% extends "base.html" %} -{% block title %}WCGNA analysis{% endblock %} +{% block title %}CTL analysis{% endblock %} {% block content %} <!-- Start of body --> <div class="container"> + {% if request.form['trait_list'].split(",")|length < 2 %} + <div class="alert alert-danger" role="alert"> + <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> + <span class="sr-only">Error:</span> + <h2>Too few traits as input</h2> + Please make sure you select enough traits to perform CTL. Your collection needs to contain at least 2 different traits. You provided {{request.form['trait_list'].split(',')|length}} traits as input. + </div> + {% else %} <h1>CTL analysis parameters</h1> - {{(request.form['trait_list'].split(',')|length -1)}} phenotypes as input + {{(request.form['trait_list'].split(',')|length)}} traits as input -<form action="/ctl_results" method="post" class="form-horizontal"> - <input type="hidden" name="trait_list" id="trait_list" value= "{{request.form['trait_list']}}"> + <form action="/ctl_results" method="post" class="form-horizontal"> + <input type="hidden" name="trait_list" id="trait_list" value= "{{request.form['trait_list']}}"> + <div class="dropdown"> + <label for="Strategy">Strategy</label> + <div class="col-sm-10"> + <select name="strategy" id="strategy"> + <option value="Exact">Exact</option> + <option value="Full">Full</option> + <option value="Pairwise">Pairwise</option> + </select> + </div> + </div> - <div class="dropdown"> - <label for="Strategy">Strategy</label> - <div class="col-sm-10"> - <select name="strategy" id="strategy"> - <option value="Exact">Exact</option> - <option value="Full">Full</option> - <option value="Pairwise">Pairwise</option> - </select> - </div> - </div> + <div class="dropdown"> + <label for="Permutations">Number of permutation (Used when strategy is Full or Pairwise)</label> + <div class="col-sm-10"> + <select name="nperm" id="nperm"> + <option value="100">100</option> + <option value="1000" selected="selected">1000</option> + <option value="10000">10000</option> + </select> + </div> + </div> - <div class="dropdown"> - <label for="Permutations">Number of permutation (Used when strategy is Full or Pairwise)</label> - <div class="col-sm-10"> - <select name="nperm" id="nperm"> - <option value="100">100</option> - <option value="1000" selected="selected">1000</option> - <option value="10000">10000</option> - </select> - </div> - </div> - - <div class="dropdown"> - <label for="Coefficient">Type of correlation coefficient</label> - <div class="col-sm-10"> - <select name="parametric" id="parametric"> - <option value="False">Spearman</option> - <option value="True">Pearson</option> - </select> - </div> - </div> - - - <div class="dropdown"> - <label for="Significance">Significance level</label> - <div class="col-sm-10"> - <select name="significance" id="significance"> - <option value="0.1">0.1</option> - <option value="0.05" selected="selected">0.05</option> - <option value="0.001">0.001</option> - </select> - </div> - </div> - <br> - <div class="form-group"> - <div class="col-sm-10"> - <input type="submit" class="btn btn-primary" value="Run CTL using these settings" /> - </div> - </div> + <div class="dropdown"> + <label for="Coefficient">Type of correlation coefficient</label> + <div class="col-sm-10"> + <select name="parametric" id="parametric"> + <option value="False">Spearman</option> + <option value="True">Pearson</option> + </select> + </div> + </div> + <div class="dropdown"> + <label for="Significance">Significance level</label> + <div class="col-sm-10"> + <select name="significance" id="significance"> + <option value="0.1">0.1</option> + <option value="0.05" selected="selected">0.05</option> + <option value="0.001">0.001</option> + </select> + </div> + </div> + <br> + <div class="form-group"> + <div class="col-sm-10"> + <input type="submit" class="btn btn-primary" value="Run CTL using these settings" /> + </div> + </div> </form> - +{% endif %} </div> {% endblock %} diff --git a/wqflask/wqflask/templates/error.html b/wqflask/wqflask/templates/error.html new file mode 100644 index 00000000..c707a4fc --- /dev/null +++ b/wqflask/wqflask/templates/error.html @@ -0,0 +1,61 @@ +{% extends "base.html" %} +{% block title %}Error: {{message}}{% endblock %} +{% block content %} +<!-- Start of body --> + +<div class="col-md-8"> +<div class="form-group has-error"> + <div class="control-label" for="inputError1"> + + <img src="/static/gif/error/{{ error_image }}"> + + <h1>ERROR</h1> + + <p> + This error is not what we wanted to see. Unfortunately errors + are part of all software systems and we need to resolve this + together. + </p> + <p> + <b>It is important to report this ERROR so we can fix it for everyone</b>. + </p> + + <p> + Report to the GeneNetwork team by recording the steps you take + to reproduce this ERROR. Next to those steps, copy-paste below + stack trace, either as + a <a href="https://github.com/genenetwork/genenetwork2/issues/new">new + issue</a> or E-mail this full page to one of the developers + directly. + </p> + </div> + + <p> + (GeneNetwork error: {{message[:128]}}) + </p> + + <pre> + GeneNetwork v{{ version }} {{ stack[0] }} + {{ message }} (error) + {{ stack[-3] }} + {{ stack[-2] }} + </pre> + + <p> + To check if this already a known issue, search the + <a href="https://github.com/genenetwork/genenetwork2/issues">issue + tracker</a>. + </p> + + <a href="#Stack" class="btn btn-default" data-toggle="collapse">Toggle full stack trace</a> + <div id="Stack" class="collapse"> + <pre> + GeneNetwork v{{ version }} {% for line in stack %} {{ line }} + {% endfor %} + </pre> + </div> +</div> +</div> + + +{% endblock %} diff --git a/wqflask/wqflask/templates/gsearch_gene.html b/wqflask/wqflask/templates/gsearch_gene.html index 70cafcfe..2d970b36 100644 --- a/wqflask/wqflask/templates/gsearch_gene.html +++ b/wqflask/wqflask/templates/gsearch_gene.html @@ -93,7 +93,7 @@ {% block js %} <script language="javascript" type="text/javascript" src="/static/new/javascript/search_results.js"></script> - <script language="javascript" type="text/javascript" src="/static/new/packages/DataTables/js/jquery.dataTables.min.js"></script> + <script language="javascript" type="text/javascript" src="https://cdn.datatables.net/1.10.12/js/jquery.dataTables.min.js"></script> <script language="javascript" type="text/javascript" src="https://cdn.datatables.net/buttons/1.0.0/js/dataTables.buttons.min.js"></script> <script language="javascript" type="text/javascript" src="https://cdn.datatables.net/buttons/1.0.0/js/buttons.html5.min.js"></script> <script language="javascript" type="text/javascript" src="https://cdn.datatables.net/buttons/1.0.0/js/buttons.bootstrap.min.js"></script> @@ -161,7 +161,7 @@ { "type": "natural" }, { "type": "natural", "width": "8%" }, { "type": "natural" }, - { "type": "natural", "width": "5%" }, + { "type": "natural" }, { "type": "natural", "width": "8%" }, { "type": "natural" } ], diff --git a/wqflask/wqflask/templates/gsearch_pheno.html b/wqflask/wqflask/templates/gsearch_pheno.html index 9be0349f..be4981bb 100644 --- a/wqflask/wqflask/templates/gsearch_pheno.html +++ b/wqflask/wqflask/templates/gsearch_pheno.html @@ -52,7 +52,7 @@ <td><a href="{{ url_for('show_trait_page', trait_id = this_trait.name, dataset = this_trait.dataset.name)}}">{{ this_trait.name }}</a></td> <td>{{ this_trait.description_display }}</td> <td>{{ this_trait.authors }}</td> - <td><a href="{{ this_trait.pubmed_link }}">{{ this_trait.pubmed_text }}</a></td> + <td data-order="{{ this_trait.pubmed_text }}"><a href="{{ this_trait.pubmed_link }}">{{ this_trait.pubmed_text }}</a></td> <td align="right">{% if this_trait.LRS_score_repr != "N/A" %}{{ '%0.1f' % this_trait.LRS_score_repr|float }}{% else %}N/A{% endif %}</td> <td align="right">{{ this_trait.LRS_location_repr }}</td> <td align="right">{% if this_trait.additive != "" %}{{ this_trait.additive }}{% else %}N/A{% endif %}</td> @@ -86,7 +86,7 @@ {% block js %} <script language="javascript" type="text/javascript" src="/static/new/javascript/search_results.js"></script> - <script language="javascript" type="text/javascript" src="/static/new/packages/DataTables/js/jquery.dataTables.min.js"></script> + <script language="javascript" type="text/javascript" src="https://cdn.datatables.net/1.10.12/js/jquery.dataTables.min.js"></script> <script language="javascript" type="text/javascript" src="https://cdn.datatables.net/buttons/1.0.0/js/dataTables.buttons.min.js"></script> <script language="javascript" type="text/javascript" src="https://cdn.datatables.net/buttons/1.0.0/js/buttons.html5.min.js"></script> <script language="javascript" type="text/javascript" src="https://cdn.datatables.net/buttons/1.0.0/js/buttons.bootstrap.min.js"></script> diff --git a/wqflask/wqflask/templates/index_page.html b/wqflask/wqflask/templates/index_page.html index dc7e058c..3b96d1e1 100644 --- a/wqflask/wqflask/templates/index_page.html +++ b/wqflask/wqflask/templates/index_page.html @@ -72,7 +72,7 @@ </div> <!-- USER HELP --> - <!--<p >Databases marked with <b>**</b>--> + <!--<p>Databases marked with <b>**</b>--> <!-- suffix are not public yet.<br>--> <!-- Access requires <a href="/account.html" target=--> <!-- "_blank" class="fs14">user login</a>.</p>--> @@ -140,27 +140,26 @@ chromosome 1 between 25 and 30 Mb.</li> <li><b>MEAN=(15 16) LRS=(23 46)</b> in the <b>Combined</b> field finds - highly expressed genes (15 to 16 log2 units) AND with peak <a href="http://www.genenetwork.org/glossary.html#L" target="_blank">LRS</a> + highly expressed genes (15 to 16 log2 units) AND with peak <a href="http://www.genenetwork.org/glossary.html#L">LRS</a> linkage between 23 and 46.</li> - <li><b>RIF=mitochondrial</b> searches RNA databases for <a href="https://en.wikipedia.org/wiki/GeneRIF" target="_blank"> + <li><b>RIF=mitochondrial</b> searches RNA databases for <a href="https://en.wikipedia.org/wiki/GeneRIF"> GeneRIF</a> links.</li> - <li><b>WIKI=nicotine</b> searches <a href="http://www.genenetwork.org/webqtl/main.py?FormID=geneWiki" target="_blank"> + <li><b>WIKI=nicotine</b> searches <a href="http://www.genenetwork.org/webqtl/main.py?FormID=geneWiki"> GeneWiki</a> for genes that you or other users have annotated with the word <i>nicotine</i>.</li> <li><b>GO:0045202</b> searches for synapse-associated genes listed in the - <a href="http://www.godatabase.org/cgi-bin/amigo/go.cgi" target="_blank"> - Gene Ontology</a>.</li> + <a href="http://amigo.geneontology.org/amigo/medial_search?q=GO%3A0045202">Gene Ontology</a>.</li> <li><b>GO:0045202 LRS=(9 99 Chr4 122 155) cisLRS=(9 999 10)</b> - finds synapse-associated genes with <a href="http://www.genenetwork.org/glossary.html#E" target="_blank"> + finds synapse-associated genes with <a href="http://www.genenetwork.org/glossary.html#E"> cis eQTL</a> on Chr 4 from 122 and 155 Mb with LRS scores between 9 and 999.</li> <li><b>RIF=diabetes LRS=(9 999 Chr2 100 105) transLRS=(9 999 10)</b> - finds diabetes-associated transcripts with peak <a href="http://www.genenetwork.org/glossary.html#E" target="_blank"> + finds diabetes-associated transcripts with peak <a href="http://www.genenetwork.org/glossary.html#E"> trans eQTLs</a> on Chr 2 between 100 and 105 Mb with LRS scores between 9 and 999.</li> </ul> @@ -176,7 +175,7 @@ <h3>Thirty minute tour</h3> <p> Take the 30 minute - GeneNetwork <a href="http://www.genenetwork.org/tutorial/WebQTLTour/" target="_blank" class="fs14">tour</a> that includes screen shots and + GeneNetwork <a href="http://www.genenetwork.org/tutorial/WebQTLTour/" class="fs14">tour</a> that includes screen shots and typical steps in the analysis. </p> @@ -187,8 +186,8 @@ and Database fields above. </p> - <p>The <a href="/conditionsofUse.html" target="_blank">conditions</a> - and <a href="/statusandContact.html" target="_blank">contact + <p>The <a href="/conditionsofUse.html">conditions</a> + and <a href="/statusandContact.html">contact </a> pages have information on the status of data sets and advice on their use and citation.</p> @@ -201,25 +200,25 @@ </div> <h3>Websites affiliated with GeneNetwork</h3> <ul> - <li><a href="http://ucscbrowser.genenetwork.org/" target="_blank">Genome + <li><a href="http://ucscbrowser.genenetwork.org/">Genome browser</a> at UTHSC</li> - <li><a href="http://galaxy.genenetwork.org/" target="_blank">Galaxy</a> at + <li><a href="http://galaxy.genenetwork.org/">Galaxy</a> at UTHSC</li> - <li>GeneNetwork 1 at <a href="http://ec2.genenetwork.org/" target="_blank">Amazon + <li>GeneNetwork 1 at <a href="http://ec2.genenetwork.org/">Amazon Cloud (EC2)</a></li> - <li>GeneNetwork 1 Source Code at <a href="http://sourceforge.net/projects/genenetwork/" target="_blank">SourceForge</a></li> + <li>GeneNetwork 1 Source Code at <a href="http://sourceforge.net/projects/genenetwork/">SourceForge</a></li> - <li>GeneNetwork 2 Source Code at <a href="https://github.com/genenetwork/genenetwork2" target="_blank">GitHub</a></li> + <li>GeneNetwork 2 Source Code at <a href="https://github.com/genenetwork/genenetwork2">GitHub</a></li> </ul> <h3>GN1 Mirror and development sites</h3> <ul> - <li><a href="http://www.genenetwork.org/" target="_blank">Main GN1 site at UTHSC</a> (main site)</li> - <li><a href="http://genenetwork.helmholtz-hzi.de/" target="_blank">Germany at the HZI</a></li> - <li><a href="http://genenetwork.memphis.edu/" target="_blank">Memphis at the U of M</a></li> + <li><a href="http://www.genenetwork.org/">Main GN1 site at UTHSC</a> (main site)</li> + <li><a href="http://genenetwork.helmholtz-hzi.de/">Germany at the HZI</a></li> + <li><a href="http://gn2.genenetwork.org/">Memphis at the U of M</a></li> </ul> </section> @@ -256,7 +255,7 @@ <h3>User Guide</h3> <h5>Read the - <a href="http://www.genenetwork.org/index4.html" target="_blank"> + <a href="http://www.genenetwork.org/index4.html"> user guide</a>.</h5> </section>--> diff --git a/wqflask/wqflask/templates/index_page_orig.html b/wqflask/wqflask/templates/index_page_orig.html index 9fba0e31..1694eae5 100755 --- a/wqflask/wqflask/templates/index_page_orig.html +++ b/wqflask/wqflask/templates/index_page_orig.html @@ -1,5 +1,10 @@ {% extends "base.html" %} {% block title %}GeneNetwork{% endblock %} +{% block css %} +<style TYPE="text/css"> + p.interact { display: none; } +</style> +{% endblock %} {% block content %} <!-- Start of body --> @@ -7,15 +12,15 @@ <header class="jumbotron subhead" id="overview"> <div class="container"> <h1>GeneNetwork</h1> - <p class="lead">Open source bioinformatics for systems genetics</p> + <p class="lead">Open source bioinformatics for systems genetics</p> </div> </header> --> <div class="container-fluid"> - + {{ flash_me() }} - + <div class="row" style="width: 1400px !important;"> <div class="col-xs-5"> @@ -90,7 +95,7 @@ <!-- GET ANY HELP --> <div class="form-group"> <label for="btsearch" class="col-xs-1 control-label" style="width: 65px !important;"></label> - <div class="col-xs-10 controls"> + <div class="col-xs-10 controls"> <div class="col-xs-12 controls"> Enter terms, genes, ID numbers in the <b>Search</b> field.<br> Use <b>*</b> or <b>?</b> wildcards (Cyp*a?, synap*).<br> @@ -113,7 +118,7 @@ <div class="col-xs-10 controls"> <div class="col-xs-2 controls" style="width: 100px !important;"> <input id="btsearch" type="submit" class="btn btn-primary form-control" value="Search"> - </div> + </div> </div> </div> @@ -140,34 +145,43 @@ chromosome 1 between 25 and 30 Mb.</li> <li><b>MEAN=(15 16) LRS=(23 46)</b> in the <b>Combined</b> field finds - highly expressed genes (15 to 16 log2 units) AND with peak <a href="http://www.genenetwork.org/glossary.html#L" target="_blank">LRS</a> + highly expressed genes (15 to 16 log2 units) AND with peak <a href="http://www.genenetwork.org/glossary.html#L">LRS</a> linkage between 23 and 46.</li> - <li><b>RIF=mitochondrial</b> searches RNA databases for <a href="https://en.wikipedia.org/wiki/GeneRIF" target="_blank"> + <li><b>RIF=mitochondrial</b> searches RNA databases for <a href="https://en.wikipedia.org/wiki/GeneRIF"> GeneRIF</a> links.</li> - <li><b>WIKI=nicotine</b> searches <a href="http://www.genenetwork.org/webqtl/main.py?FormID=geneWiki" target="_blank"> + <li><b>WIKI=nicotine</b> searches <a href="http://www.genenetwork.org/webqtl/main.py?FormID=geneWiki"> GeneWiki</a> for genes that you or other users have annotated with the word <i>nicotine</i>.</li> <li><b>GO:0045202</b> searches for synapse-associated genes listed in the - <a href="http://www.godatabase.org/cgi-bin/amigo/go.cgi" target="_blank"> + <a href="http://amigo.geneontology.org/amigo/medial_search?q=GO%3A0045202"> Gene Ontology</a>.</li> <li><b>GO:0045202 LRS=(9 99 Chr4 122 155) cisLRS=(9 999 10)</b> - finds synapse-associated genes with <a href="http://www.genenetwork.org/glossary.html#E" target="_blank"> + finds synapse-associated genes with <a href="http://www.genenetwork.org/glossary.html#E"> cis eQTL</a> on Chr 4 from 122 and 155 Mb with LRS scores between 9 and 999.</li> <li><b>RIF=diabetes LRS=(9 999 Chr2 100 105) transLRS=(9 999 10)</b> - finds diabetes-associated transcripts with peak <a href="http://www.genenetwork.org/glossary.html#E" target="_blank"> + finds diabetes-associated transcripts with peak <a href="http://www.genenetwork.org/glossary.html#E"> trans eQTLs</a> on Chr 2 between 100 and 105 Mb with LRS scores between 9 and 999.</li> </ul> </section> </div> + <div style="padding-left:120px" class="col-xs-4" style="width: 600px !important;"> - <!-- + <section id="news-section"> + <div class="page-header"> + <h1>News</h1> + </div> + <div id="tweets"></div> + <div align="right"> + <a href="https://twitter.com/GeneNetwork2">more news items...</a> + </div> + <!-- <section id="tour-info"> <div class="page-header"> <h1>Tour and more info</h1> @@ -176,7 +190,7 @@ <h3>Thirty minute tour</h3> <p> Take the 30 minute - GeneNetwork <a href="http://www.genenetwork.org/tutorial/WebQTLTour/" target="_blank" class="fs14">tour</a> that includes screen shots and + GeneNetwork <a href="http://www.genenetwork.org/tutorial/WebQTLTour/" class="fs14">tour</a> that includes screen shots and typical steps in the analysis. </p> @@ -187,41 +201,44 @@ and Database fields above. </p> - <p>The <a href="/conditionsofUse.html" target="_blank">conditions</a> - and <a href="/statusandContact.html" target="_blank">contact + <p>The <a href="/conditionsofUse.html">conditions</a> + and <a href="/statusandContact.html">contact </a> pages have information on the status of data sets and advice on their use and citation.</p> </section> --> + </section> <section id="websites"> <div class="page-header"> - <h1>Affiliates and mirrors</h1> + <h2>Links</h2> </div> - <h3>Websites affiliated with GeneNetwork</h3> + <h3>GeneNetwork v2:</h3> + <ul> + <li><a href="http://gn2.genenetwork.org/">Main website</a> at UTHSC</li> + <li><a href="http://test-gn2.genenetwork.org/">Testing website</a> at UTHSC</li> + </ul> + <h3>GeneNetwork v1:</h3> <ul> - <li><a href="http://ucscbrowser.genenetwork.org/" target="_blank">Genome + <li><a href="http://www.genenetwork.org/">Main website</a> at UTHSC</li> + <li><a href="http://genenetwork.helmholtz-hzi.de/">Website</a> at the HZI (Germany)</li> + <li><a href="http://ec2.genenetwork.org/">Amazon + Cloud (EC2)</a></li> + </ul> + <h3>Affiliates</h3> + <ul> + <li><a href="http://ucscbrowser.genenetwork.org/">Genome browser</a> at UTHSC</li> - <li><a href="http://galaxy.genenetwork.org/" target="_blank">Galaxy</a> at + <li><a href="http://galaxy.genenetwork.org/">Galaxy</a> at UTHSC</li> - <li>GeneNetwork 1 at <a href="http://ec2.genenetwork.org/" target="_blank">Amazon - Cloud (EC2)</a></li> + </ul> - <li>GeneNetwork 1 Source Code at <a href="http://sourceforge.net/projects/genenetwork/" target="_blank">SourceForge</a></li> - <li>GeneNetwork 2 Source Code at <a href="https://github.com/genenetwork/genenetwork2" target="_blank">GitHub</a></li> - </ul> - <h3>GN1 Mirror and development sites</h3> - <ul> - <li><a href="http://www.genenetwork.org/" target="_blank">Main GN1 site at UTHSC</a> (main site)</li> - <li><a href="http://genenetwork.helmholtz-hzi.de/" target="_blank">Germany at the HZI</a></li> - <li><a href="http://genenetwork.memphis.edu/" target="_blank">Memphis at the U of M</a></li> - </ul> - </section> + </section> <!--<section id="getting-started"> <div class="page-header"> @@ -256,7 +273,7 @@ <h3>User Guide</h3> <h5>Read the - <a href="http://www.genenetwork.org/index4.html" target="_blank"> + <a href="http://www.genenetwork.org/index4.html"> user guide</a>.</h5> </section>--> @@ -272,14 +289,31 @@ <script> function pressed(e) { // Has the enter key been pressed? - if ( (window.event ? event.keyCode : e.which) == 13) { + if ( (window.event ? event.keyCode : e.which) == 13) { // If enter key has been pressed and the search fields are non-empty - // manually submit the <form> - if( event.target.value.trim() != "" ) { + // manually submit the <form> + if( event.target.value.trim() != "" ) { document.forms[1].submit(); } } } </script> + <script type="text/javascript" src="/twitter/js/twitterFetcher_min.js"></script> + + <script type="text/javascript"> + var configProfile = { + "profile": {"screenName": 'GeneNetwork2'}, + "domId": 'tweets', + "maxTweets": 5, + "enableLinks": true, + "showUser": false, + "showTime": true, + "showImages": false, + "lang": 'en' + }; + twitterFetcher.fetch(configProfile); + </script> + + {% endblock %} diff --git a/wqflask/wqflask/templates/marker_regression_gn1.html b/wqflask/wqflask/templates/marker_regression_gn1.html index 33bac1ba..e198f8fe 100644 --- a/wqflask/wqflask/templates/marker_regression_gn1.html +++ b/wqflask/wqflask/templates/marker_regression_gn1.html @@ -15,7 +15,7 @@ <input type="hidden" name="trait_id" value="{{ this_trait.name }}"> <input type="hidden" name="dataset" value="{{ dataset.name }}"> <input type="hidden" name="method" value="{{ mapping_method }}"> - {% for sample in dataset.group.samplelist %} + {% for sample in samples %} <input type="hidden" name="value:{{ sample }}" value="{{ vals[loop.index - 1] }}"> {% endfor %} <input type="hidden" name="maf"> @@ -184,14 +184,16 @@ </div> </form> - <div style="width:48%;"> - {% if selectedChr == -1 %} + {% if selectedChr == -1 %} + <div style="width:{% if 'additive' in trimmed_markers[0] %}50%{% else %}35%{% endif %};"> <h2>Results</h2> + <div id="table_container" style="background-color: #eeeeee; border: 1px solid black;"> <table id="qtl_results" class="table table-hover table-striped"> <thead> <tr> <th></th> - <th>Index</th> + <th>Row</th> + <th>Locus</th> <th>{{ LRS_LOD }}</th> <th>Chr</th> {% if plotScale == "centimorgan" %} @@ -199,7 +201,12 @@ {% else %} <th>Mb</th> {% endif %} - <th>Locus</th> + {% if 'additive' in trimmed_markers[0] %} + <th>Add Eff</th> + {% endif %} + {% if 'dominance' in trimmed_markers[0] %} + <th>Dom Eff</th> + {% endif %} </tr> </thead> <tbody> @@ -211,6 +218,7 @@ value="{{ marker.name }}" checked="checked"> </td> <td align="right">{{ loop.index }}</td> + <td>{{ marker.name }}</td> {% if LRS_LOD == "LOD" %} {% if 'lod_score' in marker %} <td>{{ '%0.2f' | format(marker.lod_score|float) }}</td> @@ -226,13 +234,22 @@ {% endif %} <td>{{marker.chr}}</td> <td>{{ '%0.6f' | format(marker.Mb|float) }}</td> - <td>{{ marker.name }}</td> + {% if 'additive' in marker %} + <td>{{ '%0.3f' | format(marker.additive|float) }}</td> + {% endif %} + {% if 'dominance' in marker %} + <td>{{ '%0.2f' | format(marker.dominance|float) }}</td> + {% endif %} </tr> {% endfor %} </tbody> </table> - {% elif selectedChr > -1 %} + </div> + </div> + {% else %} + <div> <h2>Interval Analyst</h2> + <div id="table_container" style="background-color: #eeeeee; border: 1px solid black;"> <table id="interval_analyst" class="table table-hover table-striped"> <thead> <tr> @@ -251,8 +268,9 @@ {% endfor %} </tbody> </table> - {% endif %} + </div> </div> + {% endif %} </div> <!-- End of body --> @@ -265,9 +283,14 @@ /* This section checks for paths to JS libraries by checking the headers */ list = [ + /* check for static path */ "/static/new/javascript/biodalliance.js", - "http://d3js.org/d3.v3.min.js", "/static/new/js_external/underscore-min.js", + /* check for dalliance JS (see ./etc/default_settings.py) */ + "/dalliance/build/dalliance-all.js", + /* D3 path (FIXME) */ + "http://d3js.org/d3.v3.min.js", + /* datatables path (FIXME) */ "https://cdn.datatables.net/buttons/1.0.0/js/dataTables.buttons.min.js" ]; for (var i = 0; i < list.length; i++) { @@ -280,8 +303,8 @@ }, error: function() { // page does not exist - console.log("Failed to load "+url); - alert("Failed to load Javascript for "+url); + console.log("Failed to load "+this.url); + alert("Failed to load Javascript for "+this.url); } })}; </script> @@ -291,7 +314,7 @@ <script type="text/javascript" src="/static/new/js_external/underscore.string.min.js"></script> <script type="text/javascript" src="/static/new/js_external/d3-tip.min.js"></script> - <script language="javascript" type="text/javascript" src="/static/new/packages/DataTables/js/jquery.dataTables.js"></script> + <script language="javascript" type="text/javascript" src="https://cdn.datatables.net/1.10.12/js/jquery.dataTables.min.js"></script> <script language="javascript" type="text/javascript" src="https://cdn.datatables.net/buttons/1.0.0/js/dataTables.buttons.min.js"></script> <script language="javascript" type="text/javascript" src="https://cdn.datatables.net/buttons/1.0.0/js/buttons.html5.min.js"></script> <script language="javascript" type="text/javascript" src="https://cdn.datatables.net/buttons/1.0.0/js/buttons.bootstrap.min.js"></script> @@ -314,26 +337,35 @@ <script> createTable = function() { console.time("Creating table"); - $('#qtl_results').dataTable( { + $('#qtl_results').DataTable( { "columns": [ - { "type": "natural", "sWidth": "10%", "bSortable": false }, + { "type": "natural", "width": "5%", "bSortable": false }, + { "type": "natural", "width": "6%" }, { "type": "natural" }, { "type": "natural" }, { "type": "natural" }, { "type": "natural" }, - { "type": "natural", "sWidth": "30%"} + { "type": "natural" }, + { "type": "natural" } ], - "order": [[1, "asc"]], + "order": [[1, "asc" ]], "buttons": [ - 'csv' + { + extend: 'csvHtml5', + text: 'Download CSV', + title: 'search_results', + fieldBoundary: '"', + exportOptions: { + columns: [1, 2, 3, 4, 5, 6, 7, 8] + } + } ], "sDom": "RZBtir", "iDisplayLength": -1, - "autoWidth": true, "bDeferRender": true, "bSortClasses": false, - "scrollY": "700px", - "scrollCollapse": true, + "scrollY": true, + "scrollCollapse": false, "paging": false } ); @@ -342,12 +374,24 @@ "targets": 0, "sortable": false }], - "order": [[3, "asc"]], - "sDom": "RZtir", + "order": [[3, "asc" ]], + "buttons": [ + { + extend: 'csvHtml5', + text: 'Download CSV', + title: 'search_results', + fieldBoundary: '"', + exportOptions: { + columns: [1, 2, 3, 4, 5, 6, 7, 8, 9] + } + } + ], + "sDom": "RZBtir", "iDisplayLength": -1, - "autoWidth": true, "bDeferRender": true, "bSortClasses": false, + "scrollY": true, + "scrollCollapse": false, "paging": false } ); }; diff --git a/wqflask/wqflask/templates/network_graph.html b/wqflask/wqflask/templates/network_graph.html new file mode 100644 index 00000000..57426af7 --- /dev/null +++ b/wqflask/wqflask/templates/network_graph.html @@ -0,0 +1,126 @@ +{% extends "base.html" %} +{% block css %} + <link rel="stylesheet" type="text/css" href="/static/new/css/network_graph.css" /> + <link rel="stylesheet" type="text/css" href="/static/packages/cytoscape/css/cytoscape.js-panzoom.css" /> + <link rel="stylesheet" type="text/css" href="http://cdnjs.cloudflare.com/ajax/libs/qtip2/2.2.0/jquery.qtip.css"> + <style> + /* The Cytoscape Web container must have its dimensions set. */ + html, body { height: 100%; width: 100%; padding: 0; margin: 0; } + #cytoscapeweb { width: 70%; height: 70%; } + </style> +{% endblock %} +{% block content %} + + {{ header("Network Graph") }} + + <div class="container-fluid"> + <div class="row" > + <div id="content"> + <div id="secondaryContent" class="col-xs-3"> + <h3> Visualization Options</h3> + <table border="0"> + <tbody> + <tr> + <td> + <button id="reset_graph">Reset Graph</button> + </td> + </tr> + <tr> + <td> + Focus Trait + </td> + </tr> + <tr> + <td> + <select name="focus_select"> + {% for trait in traits %} + <option value="{{ trait.name }}:{{ trait.dataset.name }}">{{ trait.symbol }} ({{ trait.name }})</option> + {% endfor %} + </select> + </td> + </tr> + <tr> + <td colspan="1">Correlation Coefficient</td> + </tr> + <tr> + <td> + <font size="2"><b>0 + +/- 1</b></font> + </td> + </tr> + <tr> + <td> + <input type="range" id="slide" min="0" max="1" value="0" step="0.001" list="corr_range"> + </td> + </tr> + <tr> + <td> + Layouts + </td> + </tr> + <tr> + <td> + <select name="layout_select"> + <option value="circle">Circle</option> + <option value="concentric">Concentric</option> + <option value="cose">Cose</option> + <option value="grid">Grid</option> + <option value="breadthfirst">Breadthfirst</option> + <option value="random">Random</option> + </select> + </td> + </tr> + </tbody> + </table> + <h3> Download</h3> + <table> + <tbody> + <tr> + <td> + <a id="image_link" href="javascript:void(0)"> + <button style="width:100px;height:25px;">Save Image</button> + </a> + </td> + </tr> + <tr> + <td> + <a id="image_link" href="javascript:void(0)"> + <button style="width:100px;height:25px;">Table View</button> + </a> + </td> + </tr> + <tr> + <td> + <a id="image_link" href="javascript:void(0)"> + <button style="width:100px;height:25px;">Save Table</button> + </a> + </td> + </tr> + </tbody> + </table> + </div> + <div id="cytoscapeweb" class="col-xs-9" style="min-height:700px !important;"></div> + </div> + </div> + </div> + + +{% endblock %} + +{% block js %} + + <script> + elements_list = {{ elements | safe }} + </script> + + <script language="javascript" type="text/javascript" src="/static/new/packages/DataTables/js/jquery.js"></script> + <script language="javascript" type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/qtip2/2.2.0/jquery.qtip.js"></script> + <script language="javascript" type="text/javascript" src="/static/packages/underscore/underscore-min.js"></script> + <script language="javascript" type="text/javascript" src="/static/packages/cytoscape/js/min/cytoscape.min.js"></script> + <script language="javascript" type="text/javascript" src="/static/packages/cytoscape/js/min/AC_OETags.min.js"></script> + <script language="javascript" type="text/javascript" src="/static/packages/cytoscape/js/min/json2.min.js"></script> + <script language="javascript" type="text/javascript" src="/static/packages/cytoscape/js/src/cytoscape-panzoom.js"></script> + <script language="javascript" type="text/javascript" src="/static/packages/cytoscape/js/src/cytoscape-qtip.js"></script> + + <script language="javascript" type="text/javascript" src="/static/new/javascript/network_graph.js"></script> +{% endblock %} diff --git a/wqflask/wqflask/templates/new_security/login_user.html b/wqflask/wqflask/templates/new_security/login_user.html index e9dd4ab1..b9f49a61 100644 --- a/wqflask/wqflask/templates/new_security/login_user.html +++ b/wqflask/wqflask/templates/new_security/login_user.html @@ -46,7 +46,8 @@ <div class="form-group"> <label class="col-xs-1 control-label" for="remember"></label> <div style="margin-left:20px;" class="col-xs-4 controls"> - <input id="remember" name="remember" type="checkbox" value="y"> <b>Remember me</b> + <input id="remember" name="remember" type="checkbox" value="y"> <b>Remember me</b><br> + <input id="import_collections" name="import_collections" type="checkbox" value="y"> <b>Import existing collections</b> </div> </div> @@ -99,6 +100,7 @@ label.error,div.error{ } }); }); + </script> {% include "new_security/_scripts.html" %} diff --git a/wqflask/wqflask/templates/search_result_page.html b/wqflask/wqflask/templates/search_result_page.html index 02c97862..523037f8 100644 --- a/wqflask/wqflask/templates/search_result_page.html +++ b/wqflask/wqflask/templates/search_result_page.html @@ -117,12 +117,12 @@ {% elif dataset.type == 'Publish' %} <TD>{{ this_trait.description_display }}</TD> <TD>{{ this_trait.authors }}</TD> - <TD> + <TD data-sort="{{ this_trait.pubmed_text }}"> <a href="{{ this_trait.pubmed_link }}"> {{ this_trait.pubmed_text }} </a> </TD> - <TD>{{ this_trait.LRS_score_repr }}</TD> + <TD>{{ '%0.3f' % this_trait.LRS_score_repr|float }}</TD> <TD>{{ this_trait.LRS_location_repr }}</TD> <TD>{{ '%0.3f' % this_trait.additive|float }}</TD> {% elif dataset.type == 'Geno' %} @@ -161,9 +161,8 @@ {% block js %} <script type="text/javascript" src="/static/new/javascript/search_results.js"></script> - <script language="javascript" type="text/javascript" src="https://cdn.datatables.net/1.10.8/js/jquery.dataTables.min.js"></script> + <script language="javascript" type="text/javascript" src="https://cdn.datatables.net/1.10.12/js/jquery.dataTables.min.js"></script> <script language="javascript" type="text/javascript" src="https://cdn.datatables.net/buttons/1.0.0/js/dataTables.buttons.min.js"></script> - <script language="javascript" type="text/javascript" src="https://cdn.datatables.net/scroller/1.4.1/js/dataTables.scroller.min.js"></script> <script language="javascript" type="text/javascript" src="https://cdn.datatables.net/buttons/1.0.0/js/buttons.html5.min.js"></script> <script language="javascript" type="text/javascript" src="https://cdn.datatables.net/buttons/1.0.0/js/buttons.bootstrap.min.js"></script> <script language="javascript" type="text/javascript" src="/static/new/js_external/jszip.min.js"></script> @@ -171,7 +170,6 @@ <script language="javascript" type="text/javascript" src="/static/new/packages/DataTables/extensions/dataTables.colResize.js"></script> <script language="javascript" type="text/javascript" src="/static/new/packages/DataTables/extensions/dataTables.colReorder.js"></script> <script language="javascript" type="text/javascript" src="/static/new/packages/DataTables/extensions/dataTables.fixedHeader.min.js"></script> - <script language="javascript" type="text/javascript" src="//cdn.datatables.net/fixedcolumns/3.0.4/js/dataTables.fixedColumns.min.js"></script> <script type="text/javascript" charset="utf-8"> function getValue(x) { diff --git a/wqflask/wqflask/templates/show_trait.html b/wqflask/wqflask/templates/show_trait.html index 1890cf3f..59e0185e 100644 --- a/wqflask/wqflask/templates/show_trait.html +++ b/wqflask/wqflask/templates/show_trait.html @@ -254,38 +254,6 @@ } ); {% endif %} - if (Object.keys(js_data.sample_group_types).length > 1) { - $('#stats_table').DataTable( { - "columnDefs": [ - { "orderable": false, "targets": [0, 1, 2, 3] } - ], - "order": [], - "sDom": "tr", - "iDisplayLength": -1, - "autoWidth": false, - "bLengthChange": true, - "bDeferRender": true, - "bSortClasses": false, - "paging": false - } ); - } - else { - $('#stats_table').DataTable( { - "columnDefs": [ - { "orderable": false, "targets": [0, 1] } - ], - "order": [], - "sDom": "tr", - "iDisplayLength": -1, - "autoWidth": false, - "bLengthChange": true, - "bDeferRender": true, - "bSortClasses": false, - "paging": false - } ); - - } - var slider = document.getElementById('p_range_slider'); noUiSlider.create(slider, { start: [-1.0, 1.0], diff --git a/wqflask/wqflask/templates/show_trait_mapping_tools.html b/wqflask/wqflask/templates/show_trait_mapping_tools.html index 3d9c2521..0f293942 100644 --- a/wqflask/wqflask/templates/show_trait_mapping_tools.html +++ b/wqflask/wqflask/templates/show_trait_mapping_tools.html @@ -2,7 +2,7 @@ {% if (use_pylmm_rqtl and dataset.group.species != "human") or use_plink_gemma %} <div class="col-xs-4"> <div class="tabbable"> <!-- Only required for left/right tabs --> - + <ul class="nav nav-pills"> {% if use_pylmm_rqtl and not use_plink_gemma and dataset.group.species != "human" %} <li class="active"> @@ -61,7 +61,7 @@ No </label> </div> - </div> + </div> <!-- <div class="mapping_method_fields form-group"> @@ -75,7 +75,7 @@ <div class="mapping_method_fields form-group"> <label style="text-align:left;" class="col-xs-12 control-label">Display Additive Effect</label> - <div class="col-xs-12 controls" id="display_additive_effect"> + <div class="col-xs-12 controls" id="display_additive_effect"> <label class="radio-inline"> <input type="radio" name="display_additive" id="display_additive" value="yes" checked=""> Yes @@ -90,8 +90,8 @@ <div class="mapping_method_fields form-group"> - <label style="text-align:left;" class="col-xs-12 control-label">Marker Regr.</label> - <div class="col-xs-12 controls"> + <label style="text-align:left;" class="col-xs-3 control-label">Marker<br>Regression</label> + <div style="margin-left: 20px;" class="col-xs-4 controls"> <label class="radio-inline"> <input type="radio" name="manhattan_plot_reaper" value="True"> Yes @@ -146,7 +146,7 @@ <div class="mapping_method_fields form-group"> <label style="text-align:left;" class="col-xs-12 control-label">Manhattan Plot</label> - <div class="col-xs-12 controls"> + <div class="col-xs-12 controls"> <label class="radio-inline"> <input type="radio" name="manhattan_plot_pylmm" value="True"> Yes @@ -167,7 +167,7 @@ </div> </div> <div class="tab-pane" id="rqtl_geno"> - + <div style="margin-top: 20px" class="form-horizontal"> <div class="mapping_method_fields form-group"> <label for="mapping_permutations" class="col-xs-3 control-label">Permutations</label> @@ -226,7 +226,7 @@ <div class="mapping_method_fields form-group"> <label style="text-align:left;" class="col-xs-12 control-label">Pair Scan</label> - <div class="col-xs-12 controls"> + <div class="col-xs-12 controls"> <label class="radio-inline"> <input type="radio" name="pair_scan" value="true"> Yes @@ -240,7 +240,7 @@ <div class="mapping_method_fields form-group"> <label style="text-align:left;" class="col-xs-12 control-label">Manhattan Plot</label> - <div class="col-xs-12 controls"> + <div class="col-xs-12 controls"> <label class="radio-inline"> <input type="radio" name="manhattan_plot_rqtl" value="True"> Yes @@ -272,7 +272,7 @@ </div> </div> </div> - + <div class="form-group"> <label for="plink_compute" class="col-xs-1 control-label"></label> <div style="margin-left:20px;" class="col-xs-4 controls"> @@ -282,7 +282,7 @@ </div> </div> </div> - + <div class="tab-pane" id="gemma"> <div style="padding: 20px" class="form-horizontal"> <div class="mapping_method_fields form-group"> @@ -292,7 +292,7 @@ </div> </div> </div> - + <div class="form-group"> <label for="gemma_compute" class="col-xs-1 control-label"></label> <div style="margin-left:20px;" class="col-xs-4 controls"> @@ -301,12 +301,12 @@ </button> </div> </div> - </div> + </div> {% endif %} </div> </div> </div> - <div class="col-xs-6"> + <div class="col-xs-6"> <dl> <dt>Interval Mapping</dt> <dd>Interval mapping is a process in which the statistical significance of a hypothetical QTL is evaluated at regular points across a chromosome, even in the absence of explicit genotype data at those points.</dd> diff --git a/wqflask/wqflask/templates/show_trait_statistics.html b/wqflask/wqflask/templates/show_trait_statistics.html index 3ee8bdea..8e237868 100644 --- a/wqflask/wqflask/templates/show_trait_statistics.html +++ b/wqflask/wqflask/templates/show_trait_statistics.html @@ -25,8 +25,8 @@ <div class="tab-content"> <div class="tab-pane active" id="stats_tab"> - <div style="padding: 20px" class="form-horizontal"> - <table border="1" id="stats_table" style="width: 300px; float: left;" class="table table-hover table-striped cell-border"></table> + <div style="padding: 20px;" class="form-horizontal"> + <table id="stats_table" style="width: 450px; float: left;" class="table table-hover table-striped table-bordered"></table> </div> </div> <div class="tab-pane" id="histogram_tab"> diff --git a/wqflask/wqflask/templates/wgcna_setup.html b/wqflask/wqflask/templates/wgcna_setup.html index b4a5730d..c5461497 100644 --- a/wqflask/wqflask/templates/wgcna_setup.html +++ b/wqflask/wqflask/templates/wgcna_setup.html @@ -4,49 +4,46 @@ {% block content %} <!-- Start of body --> <h1> WGCNA analysis parameters</h1> <div class="container"> - {% if request.form['trait_list'].split(",")|length <= 4 %} - - <div class="alert alert-danger" role="alert"> - <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> - <span class="sr-only">Error:</span> - <h2> - Too few phenotypes as input - </h2> - Please make sure you select enough phenotypes / genes to perform WGCNA, your collection needs to contain at least 4 different phenotypes. You provided {{request.form['trait_list'].split(',')|length}} phenotypes as input - </div> - {% else %} - <form action="/wgcna_results" method="post" class="form-horizontal"> - <input type="hidden" name="trait_list" id="trait_list" value= "{{request.form['trait_list']}}"> - <div class="form-group"> - <label for="SoftThresholds"> Soft threshold: </label> - <div class="col-sm-10"> - <input type="text" class="form-inline" name="SoftThresholds" id="SoftThresholds" value="1,2,3,4,5,6,7,8,9"> - </div> - </div> - <div class="form-group"> - <label for="MinModuleSize"> Minimum module size: </label> - <div class="col-sm-10"> - <input type="text" class="form-inline" name="MinModuleSize" id="MinModuleSize" value="30"> - </div> - </div> - <div class="form-group"> - <label for="TOMtype"> TOMtype: </label> - <div class="col-sm-10"> - <input type="text" class="form-inline" name="TOMtype" id="TOMtype" value="unsigned"> - </div> - </div> - <div class="form-group"> - <label for="mergeCutHeight"> mergeCutHeight: </label> - <div class="col-sm-10"> - <input type="text" class="form-inline" name="mergeCutHeight" id="mergeCutHeight" value="0.25"> - </div> - </div> - <div class="form-group"> - <div class="col-sm-10"> - <input type="submit" class="btn btn-primary" value="Run WGCNA using these settings" /> - </div> - </div> - </form> - {% endif %} + {% if request.form['trait_list'].split(",")|length < 4 %} + <div class="alert alert-danger" role="alert"> + <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> + <span class="sr-only">Error:</span> + <h2>Too few phenotypes as input</h2> + Please make sure you select enough phenotypes / genes to perform WGCNA. Your collection needs to contain at least 4 different phenotypes. You provided {{request.form['trait_list'].split(',')|length}} phenotypes as input. + </div> + {% else %} + <form action="/wgcna_results" method="post" class="form-horizontal"> + <input type="hidden" name="trait_list" id="trait_list" value= "{{request.form['trait_list']}}"> + <div class="form-group"> + <label for="SoftThresholds"> Soft threshold: </label> + <div class="col-sm-10"> + <input type="text" class="form-inline" name="SoftThresholds" id="SoftThresholds" value="1,2,3,4,5,6,7,8,9"> + </div> + </div> + <div class="form-group"> + <label for="MinModuleSize"> Minimum module size: </label> + <div class="col-sm-10"> + <input type="text" class="form-inline" name="MinModuleSize" id="MinModuleSize" value="30"> + </div> + </div> + <div class="form-group"> + <label for="TOMtype"> TOMtype: </label> + <div class="col-sm-10"> + <input type="text" class="form-inline" name="TOMtype" id="TOMtype" value="unsigned"> + </div> + </div> + <div class="form-group"> + <label for="mergeCutHeight"> mergeCutHeight: </label> + <div class="col-sm-10"> + <input type="text" class="form-inline" name="mergeCutHeight" id="mergeCutHeight" value="0.25"> + </div> + </div> + <div class="form-group"> + <div class="col-sm-10"> + <input type="submit" class="btn btn-primary" value="Run WGCNA using these settings" /> + </div> + </div> + </form> + {% endif %} </div> {% endblock %} diff --git a/wqflask/wqflask/user_manager.py b/wqflask/wqflask/user_manager.py index 4ff3e79c..598af0a6 100644 --- a/wqflask/wqflask/user_manager.py +++ b/wqflask/wqflask/user_manager.py @@ -118,6 +118,20 @@ class AnonUser(object): collection['changed_timestamp'] = datetime.datetime.strptime(collection['changed_timestamp'], '%b %d %Y %I:%M%p') return collections + def import_traits_to_user(self): + collections_list = json.loads(Redis.get(self.key)) + for collection in collections_list: + uc = model.UserCollection() + uc.name = collection['name'] + collection_exists = g.user_session.user_ob.get_collection_by_name(uc.name) + if collection_exists: + continue + else: + uc.user = g.user_session.user_id + uc.members = json.dumps(collection['members']) + db_session.add(uc) + db_session.commit() + def display_num_collections(self): """ Returns the number of collections or a blank string if there are zero. @@ -524,7 +538,14 @@ class LoginUser(object): logger.debug("I will remember you") self.remember_me = True - return self.actual_login(user) + if 'import_collections' in params: + import_col = "true" + else: + import_col = "false" + + #g.cookie_session.import_traits_to_user() + + return self.actual_login(user, import_collections=import_col) else: if user: @@ -534,16 +555,16 @@ class LoginUser(object): return response - def actual_login(self, user, assumed_by=None): + def actual_login(self, user, assumed_by=None, import_collections=None): """The meat of the logging in process""" session_id_signed = self.successful_login(user, assumed_by) flash("Thank you for logging in {}.".format(user.full_name), "alert-success") - response = make_response(redirect(url_for('index_page'))) + print("IMPORT1:", import_collections) + response = make_response(redirect(url_for('index_page', import_collections=import_collections))) if self.remember_me: max_age = self.remember_time else: max_age = None - response.set_cookie(UserSession.cookie_name, session_id_signed, max_age=max_age) return response diff --git a/wqflask/wqflask/views.py b/wqflask/wqflask/views.py index 1f967dc9..289d2dc6 100644 --- a/wqflask/wqflask/views.py +++ b/wqflask/wqflask/views.py @@ -4,6 +4,11 @@ from __future__ import absolute_import, division, print_function +import traceback # for error page +import os # for error gifs +import random # for random error gif +import datetime # for errors +import time # for errors import sys import csv import xlsxwriter @@ -27,7 +32,7 @@ import base64 import array import sqlalchemy from wqflask import app -from flask import g, Response, request, render_template, send_from_directory, jsonify, redirect +from flask import g, Response, request, make_response, render_template, send_from_directory, jsonify, redirect from wqflask import search_results from wqflask import gsearch from wqflask import update_search_results @@ -39,6 +44,7 @@ from wqflask.show_trait import export_trait_data from wqflask.heatmap import heatmap from wqflask.marker_regression import marker_regression from wqflask.marker_regression import marker_regression_gn1 +from wqflask.network_graph import network_graph from wqflask.correlation import show_corr_results from wqflask.correlation_matrix import show_corr_matrix from wqflask.correlation import corr_scatter_plot @@ -47,7 +53,7 @@ from wqflask.ctl import ctl_analysis from utility import webqtlUtil from utility import temp_data -from utility.tools import SQL_URI,TEMPDIR,USE_REDIS,USE_GN_SERVER,GN_SERVER_URL +from utility.tools import SQL_URI,TEMPDIR,USE_REDIS,USE_GN_SERVER,GN_SERVER_URL,GN_VERSION from base import webqtlFormData from base.webqtlConfig import GENERATED_IMAGE_DIR, GENERATED_TEXT_DIR @@ -59,6 +65,8 @@ from wqflask import user_manager from wqflask import collect from wqflask.database import db_session +import werkzeug + import utility.logger logger = utility.logger.getLogger(__name__ ) @@ -83,15 +91,45 @@ def shutdown_session(exception=None): # from wqflask import tracer # tracer.turn_on() +@app.errorhandler(Exception) +def handle_bad_request(e): + err_msg = str(e) + logger.error(err_msg) + logger.error(request.url) + # get the stack trace and send it to the logger + exc_type, exc_value, exc_traceback = sys.exc_info() + logger.error(traceback.format_exc()) + now = datetime.datetime.utcnow() + time_str = now.strftime('%l:%M%p UTC %b %d, %Y') + formatted_lines = [request.url + " ("+time_str+")"]+traceback.format_exc().splitlines() + + # Handle random animations + # Use a cookie to have one animation on refresh + animation = request.cookies.get(err_msg[:32]) + if not animation: + list = [fn for fn in os.listdir("./wqflask/static/gif/error") if fn.endswith(".gif") ] + animation = random.choice(list) + + resp = make_response(render_template("error.html",message=err_msg,stack=formatted_lines,error_image=animation,version=GN_VERSION)) + + # logger.error("Set cookie %s with %s" % (err_msg, animation)) + resp.set_cookie(err_msg[:32],animation) + return resp + @app.route("/") def index_page(): logger.info("Sending index_page") + params = request.args + if 'import_collections' in params: + import_collections = params['import_collections'] + if import_collections == "true": + g.cookie_session.import_traits_to_user() if USE_GN_SERVER: # The menu is generated using GN_SERVER - return render_template("index_page.html", gn_server_url = GN_SERVER_URL) + return render_template("index_page.html", gn_server_url = GN_SERVER_URL, version=GN_VERSION) else: # Old style static menu (OBSOLETE) - return render_template("index_page_orig.html") + return render_template("index_page_orig.html", version=GN_VERSION) @app.route("/tmp/<img_path>") @@ -107,10 +145,14 @@ def tmp_page(img_path): return render_template("show_image.html", img_base64 = bytesarray ) +@app.route("/twitter/<path:filename>") +def twitter_js(filename): + bd_path = app.config['JS_TWITTER_POST_FETCHER'] + return send_from_directory(bd_path, filename) @app.route("/dalliance/<path:filename>") -def bd_files(filename): - bd_path = app.config['BIODALLIANCE_PATH'] +def biodalliance_js(filename): + bd_path = app.config['JS_BIODALLIANCE'] return send_from_directory(bd_path, filename) @@ -401,6 +443,7 @@ def mapping_results_container_page(): @app.route("/marker_regression", methods=('POST',)) def marker_regression_page(): initial_start_vars = request.form + logger.debug("Marker regression called with initial_start_vars:", initial_start_vars.items()) temp_uuid = initial_start_vars['temp_uuid'] wanted = ( 'trait_id', @@ -438,11 +481,11 @@ def marker_regression_page(): 'mapmethod_rqtl_geno', 'mapmodel_rqtl_geno' ) - logger.info("Marker regression called with initial_start_vars:", initial_start_vars) start_vars = {} for key, value in initial_start_vars.iteritems(): if key in wanted or key.startswith(('value:')): start_vars[key] = value + logger.debug("Marker regression called with start_vars:", start_vars) version = "v3" key = "marker_regression:{}:".format(version) + json.dumps(start_vars, sort_keys=True) @@ -556,6 +599,22 @@ def export_pdf(): response.headers["Content-Disposition"] = "attachment; filename=%s"%filename return response +@app.route("/network_graph", methods=('POST',)) +def network_graph_page(): + logger.info("In network_graph, request.form is:", pf(request.form)) + + start_vars = request.form + traits = [trait.strip() for trait in start_vars['trait_list'].split(',')] + if traits[0] != "": + template_vars = network_graph.NetworkGraph(start_vars) + template_vars.js_data = json.dumps(template_vars.js_data, + default=json_default_handler, + indent=" ") + + return render_template("network_graph.html", **template_vars.__dict__) + else: + return render_template("empty_collection.html", **{'tool':'Network Graph'}) + @app.route("/corr_compute", methods=('POST',)) def corr_compute_page(): logger.info("In corr_compute, request.form is:", pf(request.form)) |