Ticket #1170: 1170-p3.diff
File 1170-p3.diff, 296.8 KB (added by warner, at 2010-08-31T19:57:07Z) |
---|
-
src/allmydata/immutable/downloader/finder.py
diff --git a/src/allmydata/immutable/downloader/finder.py b/src/allmydata/immutable/downloader/finder.py index fa6204c..e008ec1 100644
a b class ShareFinder: 137 137 peerid=idlib.shortnodeid_b2a(peerid), 138 138 level=log.NOISY, umid="Io7pyg") 139 139 time_sent = now() 140 d_ev = self._download_status.add_dyhb_ sent(peerid, time_sent)140 d_ev = self._download_status.add_dyhb_request(peerid, time_sent) 141 141 # TODO: get the timer from a Server object, it knows best 142 142 self.overdue_timers[req] = reactor.callLater(self.OVERDUE_TIMEOUT, 143 143 self.overdue, req) … … class ShareFinder: 223 223 eventually(self.share_consumer.got_shares, shares) 224 224 225 225 def _got_error(self, f, peerid, req, d_ev, lp): 226 d_ev. finished("error",now())226 d_ev.error(now()) 227 227 self.log(format="got error from [%(peerid)s]", 228 228 peerid=idlib.shortnodeid_b2a(peerid), failure=f, 229 229 level=log.UNUSUAL, parent=lp, umid="zUKdCw") -
src/allmydata/immutable/downloader/node.py
diff --git a/src/allmydata/immutable/downloader/node.py b/src/allmydata/immutable/downloader/node.py index 33c16cf..0666216 100644
a b class DownloadNode: 72 72 # things to track callers that want data 73 73 74 74 # _segment_requests can have duplicates 75 self._segment_requests = [] # (segnum, d, cancel_handle, logparent)75 self._segment_requests = [] # (segnum, d, cancel_handle, seg_ev, lp) 76 76 self._active_segment = None # a SegmentFetcher, with .segnum 77 77 78 78 self._segsize_observers = observer.OneShotObserverList() … … class DownloadNode: 119 119 # things called by outside callers, via CiphertextFileNode. get_segment() 120 120 # may also be called by Segmentation. 121 121 122 def read(self, consumer, offset =0, size=None, read_ev=None):122 def read(self, consumer, offset, size, read_ev): 123 123 """I am the main entry point, from which FileNode.read() can get 124 124 data. I feed the consumer with the desired range of ciphertext. I 125 125 return a Deferred that fires (with the consumer) when the read is 126 126 finished. 127 127 128 128 Note that there is no notion of a 'file pointer': each call to read() 129 uses an independent offset= value.""" 130 # for concurrent operations: each gets its own Segmentation manager 131 if size is None: 132 size = self._verifycap.size 133 # clip size so offset+size does not go past EOF 134 size = min(size, self._verifycap.size-offset) 135 if read_ev is None: 136 read_ev = self._download_status.add_read_event(offset, size, now()) 129 uses an independent offset= value. 130 """ 131 assert size is not None 132 assert read_ev is not None 137 133 138 134 lp = log.msg(format="imm Node(%(si)s).read(%(offset)d, %(size)d)", 139 135 si=base32.b2a(self._verifycap.storage_index)[:8], … … class DownloadNode: 143 139 sp = self._history.stats_provider 144 140 sp.count("downloader.files_downloaded", 1) # really read() calls 145 141 sp.count("downloader.bytes_downloaded", size) 142 # for concurrent operations, each read() gets its own Segmentation 143 # manager 146 144 s = Segmentation(self, offset, size, consumer, read_ev, lp) 145 147 146 # this raises an interesting question: what segments to fetch? if 148 147 # offset=0, always fetch the first segment, and then allow 149 148 # Segmentation to be responsible for pulling the subsequent ones if … … class DownloadNode: 181 180 si=base32.b2a(self._verifycap.storage_index)[:8], 182 181 segnum=segnum, 183 182 level=log.OPERATIONAL, parent=logparent, umid="UKFjDQ") 184 se lf._download_status.add_segment_request(segnum, now())183 seg_ev = self._download_status.add_segment_request(segnum, now()) 185 184 d = defer.Deferred() 186 185 c = Cancel(self._cancel_request) 187 self._segment_requests.append( (segnum, d, c, lp) )186 self._segment_requests.append( (segnum, d, c, seg_ev, lp) ) 188 187 self._start_new_segment() 189 188 return (d, c) 190 189 … … class DownloadNode: 208 207 209 208 def _start_new_segment(self): 210 209 if self._active_segment is None and self._segment_requests: 211 segnum = self._segment_requests[0][0]210 (segnum, d, c, seg_ev, lp) = self._segment_requests[0] 212 211 k = self._verifycap.needed_shares 213 lp = self._segment_requests[0][3]214 212 log.msg(format="%(node)s._start_new_segment: segnum=%(segnum)d", 215 213 node=repr(self), segnum=segnum, 216 214 level=log.NOISY, parent=lp, umid="wAlnHQ") 217 215 self._active_segment = fetcher = SegmentFetcher(self, segnum, k, lp) 216 seg_ev.activate(now()) 218 217 active_shares = [s for s in self._shares if s.is_alive()] 219 218 fetcher.add_shares(active_shares) # this triggers the loop 220 219 … … class DownloadNode: 378 377 def fetch_failed(self, sf, f): 379 378 assert sf is self._active_segment 380 379 # deliver error upwards 381 for (d,c) in self._extract_requests(sf.segnum): 380 for (d,c,seg_ev) in self._extract_requests(sf.segnum): 381 seg_ev.error(now()) 382 382 eventually(self._deliver, d, c, f) 383 383 self._active_segment = None 384 384 self._start_new_segment() … … class DownloadNode: 387 387 d = defer.maybeDeferred(self._decode_blocks, segnum, blocks) 388 388 d.addCallback(self._check_ciphertext_hash, segnum) 389 389 def _deliver(result): 390 ds = self._download_status391 if isinstance(result, Failure):392 ds.add_segment_error(segnum, now())393 else:394 (offset, segment, decodetime) = result395 ds.add_segment_delivery(segnum, now(),396 offset, len(segment), decodetime)397 390 log.msg(format="delivering segment(%(segnum)d)", 398 391 segnum=segnum, 399 392 level=log.OPERATIONAL, parent=self._lp, 400 393 umid="j60Ojg") 401 for (d,c) in self._extract_requests(segnum): 402 eventually(self._deliver, d, c, result) 394 when = now() 395 if isinstance(result, Failure): 396 # this catches failures in decode or ciphertext hash 397 for (d,c,seg_ev) in self._extract_requests(segnum): 398 seg_ev.error(when) 399 eventually(self._deliver, d, c, result) 400 else: 401 (offset, segment, decodetime) = result 402 for (d,c,seg_ev) in self._extract_requests(segnum): 403 # when we have two requests for the same segment, the 404 # second one will not be "activated" before the data is 405 # delivered, so to allow the status-reporting code to see 406 # consistent behavior, we activate them all now. The 407 # SegmentEvent will ignore duplicate activate() calls. 408 # Note that this will result in an infinite "receive 409 # speed" for the second request. 410 seg_ev.activate(when) 411 seg_ev.deliver(when, offset, len(segment), decodetime) 412 eventually(self._deliver, d, c, result) 403 413 self._active_segment = None 404 414 self._start_new_segment() 405 415 d.addBoth(_deliver) 406 d.addErrback(lambda f: 407 log.err("unhandled error during process_blocks", 408 failure=f, level=log.WEIRD, 409 parent=self._lp, umid="MkEsCg")) 416 d.addErrback(log.err, "unhandled error during process_blocks", 417 level=log.WEIRD, parent=self._lp, umid="MkEsCg") 410 418 411 419 def _decode_blocks(self, segnum, blocks): 412 420 tail = (segnum == self.num_segments-1) … … class DownloadNode: 474 482 def _extract_requests(self, segnum): 475 483 """Remove matching requests and return their (d,c) tuples so that the 476 484 caller can retire them.""" 477 retire = [(d,c) for (segnum0, d, c, lp) in self._segment_requests 485 retire = [(d,c,seg_ev) 486 for (segnum0,d,c,seg_ev,lp) in self._segment_requests 478 487 if segnum0 == segnum] 479 488 self._segment_requests = [t for t in self._segment_requests 480 489 if t[0] != segnum] … … class DownloadNode: 483 492 def _cancel_request(self, c): 484 493 self._segment_requests = [t for t in self._segment_requests 485 494 if t[2] != c] 486 segnums = [segnum for (segnum,d,c, lp) in self._segment_requests]495 segnums = [segnum for (segnum,d,c,seg_ev,lp) in self._segment_requests] 487 496 # self._active_segment might be None in rare circumstances, so make 488 497 # sure we tolerate it 489 498 if self._active_segment and self._active_segment.segnum not in segnums: -
src/allmydata/immutable/downloader/segmentation.py
diff --git a/src/allmydata/immutable/downloader/segmentation.py b/src/allmydata/immutable/downloader/segmentation.py index 7c9f5cf..84dddbe 100644
a b class Segmentation: 123 123 # the consumer might call our .pauseProducing() inside that write() 124 124 # call, setting self._hungry=False 125 125 self._read_ev.update(len(desired_data), 0, 0) 126 # note: filenode.DecryptingConsumer is responsible for calling 127 # _read_ev.update with how much decrypt_time was consumed 126 128 self._maybe_fetch_next() 127 129 128 130 def _retry_bad_segment(self, f): -
src/allmydata/immutable/downloader/share.py
diff --git a/src/allmydata/immutable/downloader/share.py b/src/allmydata/immutable/downloader/share.py index 78cce8e..6179ff9 100644
a b class Share: 727 727 share=repr(self), 728 728 start=start, length=length, 729 729 level=log.NOISY, parent=self._lp, umid="sgVAyA") 730 req_ev = ds.add_request_sent(self._peerid, self._shnum,731 start, length, now())730 block_ev = ds.add_block_request(self._peerid, self._shnum, 731 start, length, now()) 732 732 d = self._send_request(start, length) 733 d.addCallback(self._got_data, start, length, req_ev, lp)734 d.addErrback(self._got_error, start, length, req_ev, lp)733 d.addCallback(self._got_data, start, length, block_ev, lp) 734 d.addErrback(self._got_error, start, length, block_ev, lp) 735 735 d.addCallback(self._trigger_loop) 736 736 d.addErrback(lambda f: 737 737 log.err(format="unhandled error during send_request", … … class Share: 741 741 def _send_request(self, start, length): 742 742 return self._rref.callRemote("read", start, length) 743 743 744 def _got_data(self, data, start, length, req_ev, lp):745 req_ev.finished(len(data), now())744 def _got_data(self, data, start, length, block_ev, lp): 745 block_ev.finished(len(data), now()) 746 746 if not self._alive: 747 747 return 748 748 log.msg(format="%(share)s._got_data [%(start)d:+%(length)d] -> %(datalen)d", … … class Share: 784 784 # the wanted/needed span is only "wanted" for the first pass. Once 785 785 # the offset table arrives, it's all "needed". 786 786 787 def _got_error(self, f, start, length, req_ev, lp):788 req_ev.finished("error",now())787 def _got_error(self, f, start, length, block_ev, lp): 788 block_ev.error(now()) 789 789 log.msg(format="error requesting %(start)d+%(length)d" 790 790 " from %(server)s for si %(si)s", 791 791 start=start, length=length, -
src/allmydata/immutable/downloader/status.py
diff --git a/src/allmydata/immutable/downloader/status.py b/src/allmydata/immutable/downloader/status.py index 3970ca1..dfaa27a 100644
a b import itertools 3 3 from zope.interface import implements 4 4 from allmydata.interfaces import IDownloadStatus 5 5 6 class RequestEvent: 7 def __init__(self, download_status, tag): 8 self._download_status = download_status 9 self._tag = tag 10 def finished(self, received, when): 11 self._download_status.add_request_finished(self._tag, received, when) 6 class ReadEvent: 7 def __init__(self, ev, ds): 8 self._ev = ev 9 self._ds = ds 10 def update(self, bytes, decrypttime, pausetime): 11 self._ev["bytes_returned"] += bytes 12 self._ev["decrypt_time"] += decrypttime 13 self._ev["paused_time"] += pausetime 14 def finished(self, finishtime): 15 self._ev["finish_time"] = finishtime 16 self._ds.update_last_timestamp(finishtime) 17 18 class SegmentEvent: 19 def __init__(self, ev, ds): 20 self._ev = ev 21 self._ds = ds 22 def activate(self, when): 23 if self._ev["active_time"] is None: 24 self._ev["active_time"] = when 25 def deliver(self, when, start, length, decodetime): 26 assert self._ev["active_time"] is not None 27 self._ev["finish_time"] = when 28 self._ev["success"] = True 29 self._ev["decode_time"] = decodetime 30 self._ev["segment_start"] = start 31 self._ev["segment_length"] = length 32 self._ds.update_last_timestamp(when) 33 def error(self, when): 34 self._ev["finish_time"] = when 35 self._ev["success"] = False 36 self._ds.update_last_timestamp(when) 12 37 13 38 class DYHBEvent: 14 def __init__(self, download_status, tag): 15 self._download_status = download_status 16 self._tag = tag 39 def __init__(self, ev, ds): 40 self._ev = ev 41 self._ds = ds 42 def error(self, when): 43 self._ev["finish_time"] = when 44 self._ev["success"] = False 45 self._ds.update_last_timestamp(when) 17 46 def finished(self, shnums, when): 18 self._download_status.add_dyhb_finished(self._tag, shnums, when) 47 self._ev["finish_time"] = when 48 self._ev["success"] = True 49 self._ev["response_shnums"] = shnums 50 self._ds.update_last_timestamp(when) 51 52 class BlockRequestEvent: 53 def __init__(self, ev, ds): 54 self._ev = ev 55 self._ds = ds 56 def finished(self, received, when): 57 self._ev["finish_time"] = when 58 self._ev["success"] = True 59 self._ev["response_length"] = received 60 self._ds.update_last_timestamp(when) 61 def error(self, when): 62 self._ev["finish_time"] = when 63 self._ev["success"] = False 64 self._ds.update_last_timestamp(when) 19 65 20 class ReadEvent:21 def __init__(self, download_status, tag):22 self._download_status = download_status23 self._tag = tag24 def update(self, bytes, decrypttime, pausetime):25 self._download_status.update_read_event(self._tag, bytes,26 decrypttime, pausetime)27 def finished(self, finishtime):28 self._download_status.finish_read_event(self._tag, finishtime)29 66 30 67 class DownloadStatus: 31 68 # There is one DownloadStatus for each CiphertextFileNode. The status … … class DownloadStatus: 38 75 self.size = size 39 76 self.counter = self.statusid_counter.next() 40 77 self.helper = False 41 self.started = None42 # self.dyhb_requests tracks "do you have a share" requests and43 # responses. It maps serverid to a tuple of:44 # send time45 # tuple of response shnums (None if response hasn't arrived, "error")46 # response time (None if response hasn't arrived yet)47 self.dyhb_requests = {}48 49 # self.requests tracks share-data requests and responses. It maps50 # serverid to a tuple of:51 # shnum,52 # start,length, (of data requested)53 # send time54 # response length (None if reponse hasn't arrived yet, or "error")55 # response time (None if response hasn't arrived)56 self.requests = {}57 58 # self.segment_events tracks segment requests and delivery. It is a59 # list of:60 # type ("request", "delivery", "error")61 # segment number62 # event time63 # segment start (file offset of first byte, None except in "delivery")64 # segment length (only in "delivery")65 # time spent in decode (only in "delivery")66 self.segment_events = []67 78 68 # self.read_events tracks read() requests. It is a list of: 79 self.first_timestamp = None 80 self.last_timestamp = None 81 82 # all four of these _events lists are sorted by start_time, because 83 # they are strictly append-only (some elements are later mutated in 84 # place, but none are removed or inserted in the middle). 85 86 # self.read_events tracks read() requests. It is a list of dicts, 87 # each with the following keys: 69 88 # start,length (of data requested) 70 # requesttime71 # finish 72 # bytes 73 # time spent in decrypt (None for ciphertext-only reads)74 # time spent paused89 # start_time 90 # finish_time (None until finished) 91 # bytes_returned (starts at 0, grows as segments are delivered) 92 # decrypt_time (time spent in decrypt, None for ciphertext-only reads) 93 # paused_time (time spent paused by client via pauseProducing) 75 94 self.read_events = [] 76 95 96 # self.segment_events tracks segment requests and their resolution. 97 # It is a list of dicts: 98 # segment_number 99 # start_time 100 # active_time (None until work has begun) 101 # decode_time (time spent in decode, None until delievered) 102 # finish_time (None until resolved) 103 # success (None until resolved, then boolean) 104 # segment_start (file offset of first byte, None until delivered) 105 # segment_length (None until delivered) 106 self.segment_events = [] 107 108 # self.dyhb_requests tracks "do you have a share" requests and 109 # responses. It is a list of dicts: 110 # serverid (binary) 111 # start_time 112 # success (None until resolved, then boolean) 113 # response_shnums (tuple, None until successful) 114 # finish_time (None until resolved) 115 self.dyhb_requests = [] 116 117 # self.block_requests tracks share-data requests and responses. It is 118 # a list of dicts: 119 # serverid (binary), 120 # shnum, 121 # start,length, (of data requested) 122 # start_time 123 # finish_time (None until resolved) 124 # success (None until resolved, then bool) 125 # response_length (None until success) 126 self.block_requests = [] 127 77 128 self.known_shares = [] # (serverid, shnum) 78 129 self.problems = [] 79 130 80 131 81 def add_dyhb_sent(self, serverid, when): 82 r = (when, None, None) 83 if serverid not in self.dyhb_requests: 84 self.dyhb_requests[serverid] = [] 85 self.dyhb_requests[serverid].append(r) 86 tag = (serverid, len(self.dyhb_requests[serverid])-1) 87 return DYHBEvent(self, tag) 88 89 def add_dyhb_finished(self, tag, shnums, when): 90 # received="error" on error, else tuple(shnums) 91 (serverid, index) = tag 92 r = self.dyhb_requests[serverid][index] 93 (sent, _, _) = r 94 r = (sent, shnums, when) 95 self.dyhb_requests[serverid][index] = r 96 97 def add_request_sent(self, serverid, shnum, start, length, when): 98 r = (shnum, start, length, when, None, None) 99 if serverid not in self.requests: 100 self.requests[serverid] = [] 101 self.requests[serverid].append(r) 102 tag = (serverid, len(self.requests[serverid])-1) 103 return RequestEvent(self, tag) 104 105 def add_request_finished(self, tag, received, when): 106 # received="error" on error, else len(data) 107 (serverid, index) = tag 108 r = self.requests[serverid][index] 109 (shnum, start, length, sent, _, _) = r 110 r = (shnum, start, length, sent, received, when) 111 self.requests[serverid][index] = r 132 def add_read_event(self, start, length, when): 133 if self.first_timestamp is None: 134 self.first_timestamp = when 135 r = { "start": start, 136 "length": length, 137 "start_time": when, 138 "finish_time": None, 139 "bytes_returned": 0, 140 "decrypt_time": 0, 141 "paused_time": 0, 142 } 143 self.read_events.append(r) 144 return ReadEvent(r, self) 112 145 113 146 def add_segment_request(self, segnum, when): 114 if self.started is None: 115 self.started = when 116 r = ("request", segnum, when, None, None, None) 117 self.segment_events.append(r) 118 def add_segment_delivery(self, segnum, when, start, length, decodetime): 119 r = ("delivery", segnum, when, start, length, decodetime) 120 self.segment_events.append(r) 121 def add_segment_error(self, segnum, when): 122 r = ("error", segnum, when, None, None, None) 147 if self.first_timestamp is None: 148 self.first_timestamp = when 149 r = { "segment_number": segnum, 150 "start_time": when, 151 "active_time": None, 152 "finish_time": None, 153 "success": None, 154 "decode_time": None, 155 "segment_start": None, 156 "segment_length": None, 157 } 123 158 self.segment_events.append(r) 124 125 def add_read_event(self, start, length, when): 126 if self.started is None: 127 self.started = when 128 r = (start, length, when, None, 0, 0, 0) 129 self.read_events.append(r) 130 tag = len(self.read_events)-1 131 return ReadEvent(self, tag) 132 def update_read_event(self, tag, bytes_d, decrypt_d, paused_d): 133 r = self.read_events[tag] 134 (start, length, requesttime, finishtime, bytes, decrypt, paused) = r 135 bytes += bytes_d 136 decrypt += decrypt_d 137 paused += paused_d 138 r = (start, length, requesttime, finishtime, bytes, decrypt, paused) 139 self.read_events[tag] = r 140 def finish_read_event(self, tag, finishtime): 141 r = self.read_events[tag] 142 (start, length, requesttime, _, bytes, decrypt, paused) = r 143 r = (start, length, requesttime, finishtime, bytes, decrypt, paused) 144 self.read_events[tag] = r 159 return SegmentEvent(r, self) 160 161 def add_dyhb_request(self, serverid, when): 162 r = { "serverid": serverid, 163 "start_time": when, 164 "success": None, 165 "response_shnums": None, 166 "finish_time": None, 167 } 168 self.dyhb_requests.append(r) 169 return DYHBEvent(r, self) 170 171 def add_block_request(self, serverid, shnum, start, length, when): 172 r = { "serverid": serverid, 173 "shnum": shnum, 174 "start": start, 175 "length": length, 176 "start_time": when, 177 "finish_time": None, 178 "success": None, 179 "response_length": None, 180 } 181 self.block_requests.append(r) 182 return BlockRequestEvent(r, self) 183 184 def update_last_timestamp(self, when): 185 if self.last_timestamp is None or when > self.last_timestamp: 186 self.last_timestamp = when 145 187 146 188 def add_known_share(self, serverid, shnum): 147 189 self.known_shares.append( (serverid, shnum) ) … … class DownloadStatus: 160 202 # mention all outstanding segment requests 161 203 outstanding = set() 162 204 errorful = set() 163 for s_ev in self.segment_events: 164 (etype, segnum, when, segstart, seglen, decodetime) = s_ev 165 if etype == "request": 166 outstanding.add(segnum) 167 elif etype == "delivery": 168 outstanding.remove(segnum) 169 else: # "error" 170 outstanding.remove(segnum) 171 errorful.add(segnum) 205 outstanding = set([s_ev["segment_number"] 206 for s_ev in self.segment_events 207 if s_ev["finish_time"] is None]) 208 errorful = set([s_ev["segment_number"] 209 for s_ev in self.segment_events 210 if s_ev["success"] is False]) 172 211 def join(segnums): 173 212 if len(segnums) == 1: 174 213 return "segment %s" % list(segnums)[0] … … class DownloadStatus: 191 230 return 0.0 192 231 total_outstanding, total_received = 0, 0 193 232 for r_ev in self.read_events: 194 (start, length, ign1, finishtime, bytes, ign2, ign3) = r_ev 195 if finishtime is None: 196 total_outstanding += length 197 total_received += bytes 233 if r_ev["finish_time"] is None: 234 total_outstanding += r_ev["length"] 235 total_received += r_ev["bytes_returned"] 198 236 # else ignore completed requests 199 237 if not total_outstanding: 200 238 return 1.0 … … class DownloadStatus: 205 243 def get_active(self): 206 244 return False # TODO 207 245 def get_started(self): 208 return self. started246 return self.first_timestamp 209 247 def get_results(self): 210 248 return None # TODO -
src/allmydata/immutable/filenode.py
diff --git a/src/allmydata/immutable/filenode.py b/src/allmydata/immutable/filenode.py index ed3785b..2a0eae1 100644
a b class CiphertextFileNode: 55 55 return a Deferred that fires (with the consumer) when the read is 56 56 finished.""" 57 57 self._maybe_create_download_node() 58 actual_size = size59 if actual_size is None:60 actual_size = self._verifycap.size - offset61 read_ev = self._download_status.add_read_event(offset, actual_size,62 58 if size is None: 59 size = self._verifycap.size 60 # clip size so offset+size does not go past EOF 61 size = min(size, self._verifycap.size-offset) 62 read_ev = self._download_status.add_read_event(offset, size, now()) 63 63 if IDownloadStatusHandlingConsumer.providedBy(consumer): 64 64 consumer.set_download_status_read_event(read_ev) 65 65 return self._node.read(consumer, offset, size, read_ev) … … class DecryptingConsumer: 177 177 178 178 def __init__(self, consumer, readkey, offset): 179 179 self._consumer = consumer 180 self._read_ev ent= None180 self._read_ev = None 181 181 # TODO: pycryptopp CTR-mode needs random-access operations: I want 182 182 # either a=AES(readkey, offset) or better yet both of: 183 183 # a=AES(readkey, offset=0) … … class DecryptingConsumer: 190 190 self._decryptor.process("\x00"*offset_small) 191 191 192 192 def set_download_status_read_event(self, read_ev): 193 self._read_ev ent= read_ev193 self._read_ev = read_ev 194 194 195 195 def registerProducer(self, producer, streaming): 196 196 # this passes through, so the real consumer can flow-control the real … … class DecryptingConsumer: 203 203 def write(self, ciphertext): 204 204 started = now() 205 205 plaintext = self._decryptor.process(ciphertext) 206 if self._read_ev ent:206 if self._read_ev: 207 207 elapsed = now() - started 208 self._read_ev ent.update(0, elapsed, 0)208 self._read_ev.update(0, elapsed, 0) 209 209 self._consumer.write(plaintext) 210 210 211 211 class ImmutableFileNode: -
src/allmydata/test/test_download.py
diff --git a/src/allmydata/test/test_download.py b/src/allmydata/test/test_download.py index 40f0d62..fc84fa2 100644
a b class Status(unittest.TestCase): 1222 1222 now = 12345.1 1223 1223 ds = DownloadStatus("si-1", 123) 1224 1224 self.failUnlessEqual(ds.get_status(), "idle") 1225 ds.add_segment_request(0, now)1225 ev0 = ds.add_segment_request(0, now) 1226 1226 self.failUnlessEqual(ds.get_status(), "fetching segment 0") 1227 ds.add_segment_delivery(0, now+1, 0, 1000, 2.0) 1227 ev0.activate(now+0.5) 1228 ev0.deliver(now+1, 0, 1000, 2.0) 1228 1229 self.failUnlessEqual(ds.get_status(), "idle") 1229 ds.add_segment_request(2, now+2)1230 ds.add_segment_request(1, now+2)1230 ev2 = ds.add_segment_request(2, now+2) 1231 ev1 = ds.add_segment_request(1, now+2) 1231 1232 self.failUnlessEqual(ds.get_status(), "fetching segments 1,2") 1232 ds.add_segment_error(1,now+3)1233 ev1.error(now+3) 1233 1234 self.failUnlessEqual(ds.get_status(), 1234 1235 "fetching segment 2; errors on segment 1") 1236 del ev2 # hush pyflakes 1235 1237 1236 1238 def test_progress(self): 1237 1239 now = 12345.1 -
src/allmydata/test/test_web.py
diff --git a/src/allmydata/test/test_web.py b/src/allmydata/test/test_web.py index f68e98d..cc9be0d 100644
a b from allmydata.nodemaker import NodeMaker 19 19 from allmydata.unknown import UnknownNode 20 20 from allmydata.web import status, common 21 21 from allmydata.scripts.debug import CorruptShareOptions, corrupt_share 22 from allmydata.util import fileutil, base32 22 from allmydata.util import fileutil, base32, hashutil 23 23 from allmydata.util.consumer import download_to_data 24 24 from allmydata.util.netstring import split_netstring 25 25 from allmydata.util.encodingutil import to_str … … def build_one_ds(): 78 78 ds = DownloadStatus("storage_index", 1234) 79 79 now = time.time() 80 80 81 ds.add_segment_request(0, now) 82 # segnum, when, start,len, decodetime 83 ds.add_segment_delivery(0, now+1, 0, 100, 0.5) 84 ds.add_segment_request(1, now+2) 85 ds.add_segment_error(1, now+3) 81 serverid_a = hashutil.tagged_hash("foo", "serverid_a")[:20] 82 serverid_b = hashutil.tagged_hash("foo", "serverid_b")[:20] 83 storage_index = hashutil.storage_index_hash("SI") 84 e0 = ds.add_segment_request(0, now) 85 e0.activate(now+0.5) 86 e0.deliver(now+1, 0, 100, 0.5) # when, start,len, decodetime 87 e1 = ds.add_segment_request(1, now+2) 88 e1.error(now+3) 86 89 # two outstanding requests 87 ds.add_segment_request(2, now+4) 88 ds.add_segment_request(3, now+5) 90 e2 = ds.add_segment_request(2, now+4) 91 e3 = ds.add_segment_request(3, now+5) 92 del e2,e3 # hush pyflakes 89 93 90 # simulate a segment which gets delivered faster than a system clock tick (ticket #1166) 91 ds.add_segment_request(4, now) 92 ds.add_segment_delivery(4, now, 0, 140, 0.5) 94 # simulate a segment which gets delivered faster than a system clock tick 95 # (ticket #1166) 96 e = ds.add_segment_request(4, now) 97 e.activate(now) 98 e.deliver(now, 0, 140, 0.5) 93 99 94 e = ds.add_dyhb_ sent("serverid_a", now)100 e = ds.add_dyhb_request(serverid_a, now) 95 101 e.finished([1,2], now+1) 96 e = ds.add_dyhb_ sent("serverid_b", now+2) # left unfinished102 e = ds.add_dyhb_request(serverid_b, now+2) # left unfinished 97 103 98 104 e = ds.add_read_event(0, 120, now) 99 105 e.update(60, 0.5, 0.1) # bytes, decrypttime, pausetime 100 106 e.finished(now+1) 101 107 e = ds.add_read_event(120, 30, now+2) # left unfinished 102 108 103 e = ds.add_ request_sent("serverid_a", 1, 100, 20, now)109 e = ds.add_block_request(serverid_a, 1, 100, 20, now) 104 110 e.finished(20, now+1) 105 e = ds.add_ request_sent("serverid_a", 1, 120, 30, now+1) # left unfinished111 e = ds.add_block_request(serverid_a, 1, 120, 30, now+1) # left unfinished 106 112 107 113 # make sure that add_read_event() can come first too 108 ds1 = DownloadStatus( "storage_index", 1234)114 ds1 = DownloadStatus(storage_index, 1234) 109 115 e = ds1.add_read_event(0, 120, now) 110 116 e.update(60, 0.5, 0.1) # bytes, decrypttime, pausetime 111 117 e.finished(now+1) … … class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi 554 560 def _check_dl(res): 555 561 self.failUnless("File Download Status" in res, res) 556 562 d.addCallback(_check_dl) 557 d.addCallback(lambda res: self.GET("/status/down-%d ?t=json" % dl_num))563 d.addCallback(lambda res: self.GET("/status/down-%d/event_json" % dl_num)) 558 564 def _check_dl_json(res): 559 565 data = simplejson.loads(res) 560 566 self.failUnless(isinstance(data, dict)) 567 # this data comes from build_one_ds() above 568 self.failUnlessEqual(set(data["serverids"].values()), 569 set(["phwr", "cmpu"])) 570 self.failUnlessEqual(len(data["segment"]), 5) 571 self.failUnlessEqual(len(data["read"]), 2) 561 572 d.addCallback(_check_dl_json) 562 573 d.addCallback(lambda res: self.GET("/status/up-%d" % ul_num)) 563 574 def _check_ul(res): -
new file src/allmydata/web/download-status-timeline.xhtml
diff --git a/src/allmydata/web/download-status-timeline.xhtml b/src/allmydata/web/download-status-timeline.xhtml new file mode 100644 index 0000000..abc7145
- + 1 <html xmlns:n="http://nevow.com/ns/nevow/0.1"> 2 <head> 3 <title>AllMyData - Tahoe - File Download Status Timeline</title> 4 <link href="/tahoe_css" rel="stylesheet" type="text/css"/> 5 <link href="/webform_css" rel="stylesheet" type="text/css"/> 6 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 7 <script type="text/javascript" src="/jquery.js"></script> 8 <script type="text/javascript" src="/protovis-r3.2.js"></script> 9 <script type="text/javascript" src="/download_status_timeline.js"></script> 10 </head> 11 <body> 12 13 <h1>File Download Status</h1> 14 15 <ul> 16 <li>Started: <span n:render="started"/></li> 17 <li>Storage Index: <span n:render="si"/></li> 18 <li>Helper?: <span n:render="helper"/></li> 19 <li>Total Size: <span n:render="total_size"/></li> 20 <li>Progress: <span n:render="progress"/></li> 21 <li>Status: <span n:render="status"/></li> 22 </ul> 23 24 25 <div style=""> 26 <div id="overview" style="float:right;width:166px;height:100px; border: 1px solid #ddd">overview</div> 27 <div id="timeline" style="width:600px;border: 1px solid #aaa">Timeline</div> 28 </div> 29 30 <div>Return to the <a href="/">Welcome Page</a></div> 31 32 </body> 33 </html> -
src/allmydata/web/download-status.xhtml
diff --git a/src/allmydata/web/download-status.xhtml b/src/allmydata/web/download-status.xhtml index 30abfca..b3560ed 100644
a b 16 16 <li>Total Size: <span n:render="total_size"/></li> 17 17 <li>Progress: <span n:render="progress"/></li> 18 18 <li>Status: <span n:render="status"/></li> 19 <li><span n:render="timeline_link"/></li> 19 20 </ul> 20 21 21 22 <div n:render="events"></div> -
new file src/allmydata/web/download_status_timeline.js
diff --git a/src/allmydata/web/download_status_timeline.js b/src/allmydata/web/download_status_timeline.js new file mode 100644 index 0000000..ca48eb1
- + 1 2 $(function() { 3 4 function onDataReceived(data) { 5 var bounds = { min: data.bounds.min, 6 max: data.bounds.max 7 }; 8 //bounds.max = data.dyhb[data.dyhb.length-1].finish_time; 9 var duration = bounds.max - bounds.min; 10 var WIDTH = 600; 11 var vis = new pv.Panel().canvas("timeline").margin(30); 12 13 var dyhb_top = 0; 14 var read_top = dyhb_top + 30*data.dyhb[data.dyhb.length-1].row+60; 15 var segment_top = read_top + 30*data.read[data.read.length-1].row+60; 16 var block_top = segment_top + 30*data.segment[data.segment.length-1].row+60; 17 var block_row_to_y = {}; 18 var row_y=0; 19 for (var group=0; group < data.block_rownums.length; group++) { 20 for (var row=0; row < data.block_rownums[group]; row++) { 21 block_row_to_y[group+"-"+row] = row_y; 22 row_y += 10; 23 } 24 row_y += 5; 25 } 26 27 var height = block_top + row_y; 28 var kx = bounds.min; 29 var ky = 1; 30 var x = pv.Scale.linear(bounds.min, bounds.max).range(0, WIDTH-40); 31 var relx = pv.Scale.linear(0, duration).range(0, WIDTH-40); 32 //var y = pv.Scale.linear(-ky,ky).range(0, height); 33 //x.nice(); relx.nice(); 34 35 /* add the invisible panel now, at the bottom of the stack, so that 36 it won't steal mouseover events and prevent tooltips from 37 working. */ 38 vis.add(pv.Panel) 39 .events("all") 40 .event("mousedown", pv.Behavior.pan()) 41 .event("mousewheel", pv.Behavior.zoom()) 42 .event("pan", transform) 43 .event("zoom", transform) 44 ; 45 46 vis.anchor("top").top(-20).add(pv.Label).text("DYHB Requests"); 47 48 vis.add(pv.Bar) 49 .data(data.dyhb) 50 .height(20) 51 .top(function (d) {return 30*d.row;}) 52 .left(function(d){return x(d.start_time);}) 53 .width(function(d){return x(d.finish_time)-x(d.start_time);}) 54 .title(function(d){return "shnums: "+d.response_shnums;}) 55 .fillStyle(function(d){return data.server_info[d.serverid].color;}) 56 .strokeStyle("black").lineWidth(1); 57 58 vis.add(pv.Rule) 59 .data(data.dyhb) 60 .top(function(d){return 30*d.row + 20/2;}) 61 .left(0).width(0) 62 .strokeStyle("#888") 63 .anchor("left").add(pv.Label) 64 .text(function(d){return d.serverid.slice(0,4);}); 65 66 /* we use a function for data=relx.ticks() here instead of 67 simply .data(relx.ticks()) so that it will be recalculated when 68 the scales change (by pan/zoom) */ 69 var xaxis = vis.add(pv.Rule) 70 .data(function() {return relx.ticks();}) 71 .strokeStyle("#ccc") 72 .left(relx) 73 .anchor("bottom").add(pv.Label) 74 .text(function(d){return relx.tickFormat(d)+"s";}); 75 76 var read = vis.add(pv.Panel).top(read_top); 77 read.anchor("top").top(-20).add(pv.Label).text("read() requests"); 78 79 read.add(pv.Bar) 80 .data(data.read) 81 .height(20) 82 .top(function (d) {return 30*d.row;}) 83 .left(function(d){return x(d.start_time);}) 84 .width(function(d){return x(d.finish_time)-x(d.start_time);}) 85 .title(function(d){return "read(start="+d.start+", len="+d.length+") -> "+d.bytes_returned+" bytes";}) 86 .fillStyle("red") 87 .strokeStyle("black").lineWidth(1); 88 89 var segment = vis.add(pv.Panel).top(segment_top); 90 segment.anchor("top").top(-20).add(pv.Label).text("segment() requests"); 91 92 segment.add(pv.Bar) 93 .data(data.segment) 94 .height(20) 95 .top(function (d) {return 30*d.row;}) 96 .left(function(d){return x(d.start_time);}) 97 .width(function(d){return x(d.finish_time)-x(d.start_time);}) 98 .title(function(d){return "seg"+d.segment_number+" ["+d.segment_start+":+"+d.segment_length+"] (took "+(d.finish_time-d.start_time)+")";}) 99 .fillStyle(function(d){if (d.success) return "#c0ffc0"; 100 else return "#ffc0c0";}) 101 .strokeStyle("black").lineWidth(1); 102 103 var block = vis.add(pv.Panel).top(block_top); 104 block.anchor("top").top(-20).add(pv.Label).text("block() requests"); 105 106 var shnum_colors = pv.Colors.category10(); 107 block.add(pv.Bar) 108 .data(data.block) 109 .height(10) 110 .top(function (d) {return block_row_to_y[d.row[0]+"-"+d.row[1]];}) 111 .left(function(d){return x(d.start_time);}) 112 .width(function(d){return x(d.finish_time)-x(d.start_time);}) 113 .title(function(d){return "sh"+d.shnum+"-on-"+d.serverid.slice(0,4)+" ["+d.start+":+"+d.length+"] -> "+d.response_length;}) 114 .fillStyle(function(d){return data.server_info[d.serverid].color;}) 115 .strokeStyle(function(d){return shnum_colors(d.shnum).color;}) 116 .lineWidth(function(d) 117 {if (d.response_length > 100) return 3; 118 else return 1; 119 }) 120 ; 121 122 123 vis.height(height); 124 125 function transform() { 126 var t0= this.transform(); 127 var t = this.transform().invert(); 128 // when t.x=0 and t.k=1.0, left should be bounds.min 129 x.domain(bounds.min + (t.x/WIDTH)*duration, 130 bounds.min + t.k*duration + (t.x/WIDTH)*duration); 131 relx.domain(0 + t.x/WIDTH*duration, 132 t.k*duration + (t.x/WIDTH)*duration); 133 vis.render(); 134 } 135 136 vis.render(); 137 } 138 139 $.ajax({url: "event_json", 140 method: 'GET', 141 dataType: 'json', 142 success: onDataReceived }); 143 }); 144 -
new file src/allmydata/web/jquery.js
diff --git a/src/allmydata/web/jquery.js b/src/allmydata/web/jquery.js new file mode 100644 index 0000000..9263574
- + 1 /*! 2 * jQuery JavaScript Library v1.3.2 3 * http://jquery.com/ 4 * 5 * Copyright (c) 2009 John Resig 6 * Dual licensed under the MIT and GPL licenses. 7 * http://docs.jquery.com/License 8 * 9 * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009) 10 * Revision: 6246 11 */ 12 (function(){ 13 14 var 15 // Will speed up references to window, and allows munging its name. 16 window = this, 17 // Will speed up references to undefined, and allows munging its name. 18 undefined, 19 // Map over jQuery in case of overwrite 20 _jQuery = window.jQuery, 21 // Map over the $ in case of overwrite 22 _$ = window.$, 23 24 jQuery = window.jQuery = window.$ = function( selector, context ) { 25 // The jQuery object is actually just the init constructor 'enhanced' 26 return new jQuery.fn.init( selector, context ); 27 }, 28 29 // A simple way to check for HTML strings or ID strings 30 // (both of which we optimize for) 31 quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/, 32 // Is it a simple selector 33 isSimple = /^.[^:#\[\.,]*$/; 34 35 jQuery.fn = jQuery.prototype = { 36 init: function( selector, context ) { 37 // Make sure that a selection was provided 38 selector = selector || document; 39 40 // Handle $(DOMElement) 41 if ( selector.nodeType ) { 42 this[0] = selector; 43 this.length = 1; 44 this.context = selector; 45 return this; 46 } 47 // Handle HTML strings 48 if ( typeof selector === "string" ) { 49 // Are we dealing with HTML string or an ID? 50 var match = quickExpr.exec( selector ); 51 52 // Verify a match, and that no context was specified for #id 53 if ( match && (match[1] || !context) ) { 54 55 // HANDLE: $(html) -> $(array) 56 if ( match[1] ) 57 selector = jQuery.clean( [ match[1] ], context ); 58 59 // HANDLE: $("#id") 60 else { 61 var elem = document.getElementById( match[3] ); 62 63 // Handle the case where IE and Opera return items 64 // by name instead of ID 65 if ( elem && elem.id != match[3] ) 66 return jQuery().find( selector ); 67 68 // Otherwise, we inject the element directly into the jQuery object 69 var ret = jQuery( elem || [] ); 70 ret.context = document; 71 ret.selector = selector; 72 return ret; 73 } 74 75 // HANDLE: $(expr, [context]) 76 // (which is just equivalent to: $(content).find(expr) 77 } else 78 return jQuery( context ).find( selector ); 79 80 // HANDLE: $(function) 81 // Shortcut for document ready 82 } else if ( jQuery.isFunction( selector ) ) 83 return jQuery( document ).ready( selector ); 84 85 // Make sure that old selector state is passed along 86 if ( selector.selector && selector.context ) { 87 this.selector = selector.selector; 88 this.context = selector.context; 89 } 90 91 return this.setArray(jQuery.isArray( selector ) ? 92 selector : 93 jQuery.makeArray(selector)); 94 }, 95 96 // Start with an empty selector 97 selector: "", 98 99 // The current version of jQuery being used 100 jquery: "1.3.2", 101 102 // The number of elements contained in the matched element set 103 size: function() { 104 return this.length; 105 }, 106 107 // Get the Nth element in the matched element set OR 108 // Get the whole matched element set as a clean array 109 get: function( num ) { 110 return num === undefined ? 111 112 // Return a 'clean' array 113 Array.prototype.slice.call( this ) : 114 115 // Return just the object 116 this[ num ]; 117 }, 118 119 // Take an array of elements and push it onto the stack 120 // (returning the new matched element set) 121 pushStack: function( elems, name, selector ) { 122 // Build a new jQuery matched element set 123 var ret = jQuery( elems ); 124 125 // Add the old object onto the stack (as a reference) 126 ret.prevObject = this; 127 128 ret.context = this.context; 129 130 if ( name === "find" ) 131 ret.selector = this.selector + (this.selector ? " " : "") + selector; 132 else if ( name ) 133 ret.selector = this.selector + "." + name + "(" + selector + ")"; 134 135 // Return the newly-formed element set 136 return ret; 137 }, 138 139 // Force the current matched set of elements to become 140 // the specified array of elements (destroying the stack in the process) 141 // You should use pushStack() in order to do this, but maintain the stack 142 setArray: function( elems ) { 143 // Resetting the length to 0, then using the native Array push 144 // is a super-fast way to populate an object with array-like properties 145 this.length = 0; 146 Array.prototype.push.apply( this, elems ); 147 148 return this; 149 }, 150 151 // Execute a callback for every element in the matched set. 152 // (You can seed the arguments with an array of args, but this is 153 // only used internally.) 154 each: function( callback, args ) { 155 return jQuery.each( this, callback, args ); 156 }, 157 158 // Determine the position of an element within 159 // the matched set of elements 160 index: function( elem ) { 161 // Locate the position of the desired element 162 return jQuery.inArray( 163 // If it receives a jQuery object, the first element is used 164 elem && elem.jquery ? elem[0] : elem 165 , this ); 166 }, 167 168 attr: function( name, value, type ) { 169 var options = name; 170 171 // Look for the case where we're accessing a style value 172 if ( typeof name === "string" ) 173 if ( value === undefined ) 174 return this[0] && jQuery[ type || "attr" ]( this[0], name ); 175 176 else { 177 options = {}; 178 options[ name ] = value; 179 } 180 181 // Check to see if we're setting style values 182 return this.each(function(i){ 183 // Set all the styles 184 for ( name in options ) 185 jQuery.attr( 186 type ? 187 this.style : 188 this, 189 name, jQuery.prop( this, options[ name ], type, i, name ) 190 ); 191 }); 192 }, 193 194 css: function( key, value ) { 195 // ignore negative width and height values 196 if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 ) 197 value = undefined; 198 return this.attr( key, value, "curCSS" ); 199 }, 200 201 text: function( text ) { 202 if ( typeof text !== "object" && text != null ) 203 return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) ); 204 205 var ret = ""; 206 207 jQuery.each( text || this, function(){ 208 jQuery.each( this.childNodes, function(){ 209 if ( this.nodeType != 8 ) 210 ret += this.nodeType != 1 ? 211 this.nodeValue : 212 jQuery.fn.text( [ this ] ); 213 }); 214 }); 215 216 return ret; 217 }, 218 219 wrapAll: function( html ) { 220 if ( this[0] ) { 221 // The elements to wrap the target around 222 var wrap = jQuery( html, this[0].ownerDocument ).clone(); 223 224 if ( this[0].parentNode ) 225 wrap.insertBefore( this[0] ); 226 227 wrap.map(function(){ 228 var elem = this; 229 230 while ( elem.firstChild ) 231 elem = elem.firstChild; 232 233 return elem; 234 }).append(this); 235 } 236 237 return this; 238 }, 239 240 wrapInner: function( html ) { 241 return this.each(function(){ 242 jQuery( this ).contents().wrapAll( html ); 243 }); 244 }, 245 246 wrap: function( html ) { 247 return this.each(function(){ 248 jQuery( this ).wrapAll( html ); 249 }); 250 }, 251 252 append: function() { 253 return this.domManip(arguments, true, function(elem){ 254 if (this.nodeType == 1) 255 this.appendChild( elem ); 256 }); 257 }, 258 259 prepend: function() { 260 return this.domManip(arguments, true, function(elem){ 261 if (this.nodeType == 1) 262 this.insertBefore( elem, this.firstChild ); 263 }); 264 }, 265 266 before: function() { 267 return this.domManip(arguments, false, function(elem){ 268 this.parentNode.insertBefore( elem, this ); 269 }); 270 }, 271 272 after: function() { 273 return this.domManip(arguments, false, function(elem){ 274 this.parentNode.insertBefore( elem, this.nextSibling ); 275 }); 276 }, 277 278 end: function() { 279 return this.prevObject || jQuery( [] ); 280 }, 281 282 // For internal use only. 283 // Behaves like an Array's method, not like a jQuery method. 284 push: [].push, 285 sort: [].sort, 286 splice: [].splice, 287 288 find: function( selector ) { 289 if ( this.length === 1 ) { 290 var ret = this.pushStack( [], "find", selector ); 291 ret.length = 0; 292 jQuery.find( selector, this[0], ret ); 293 return ret; 294 } else { 295 return this.pushStack( jQuery.unique(jQuery.map(this, function(elem){ 296 return jQuery.find( selector, elem ); 297 })), "find", selector ); 298 } 299 }, 300 301 clone: function( events ) { 302 // Do the clone 303 var ret = this.map(function(){ 304 if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) { 305 // IE copies events bound via attachEvent when 306 // using cloneNode. Calling detachEvent on the 307 // clone will also remove the events from the orignal 308 // In order to get around this, we use innerHTML. 309 // Unfortunately, this means some modifications to 310 // attributes in IE that are actually only stored 311 // as properties will not be copied (such as the 312 // the name attribute on an input). 313 var html = this.outerHTML; 314 if ( !html ) { 315 var div = this.ownerDocument.createElement("div"); 316 div.appendChild( this.cloneNode(true) ); 317 html = div.innerHTML; 318 } 319 320 return jQuery.clean([html.replace(/ jQuery\d+="(?:\d+|null)"/g, "").replace(/^\s*/, "")])[0]; 321 } else 322 return this.cloneNode(true); 323 }); 324 325 // Copy the events from the original to the clone 326 if ( events === true ) { 327 var orig = this.find("*").andSelf(), i = 0; 328 329 ret.find("*").andSelf().each(function(){ 330 if ( this.nodeName !== orig[i].nodeName ) 331 return; 332 333 var events = jQuery.data( orig[i], "events" ); 334 335 for ( var type in events ) { 336 for ( var handler in events[ type ] ) { 337 jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data ); 338 } 339 } 340 341 i++; 342 }); 343 } 344 345 // Return the cloned set 346 return ret; 347 }, 348 349 filter: function( selector ) { 350 return this.pushStack( 351 jQuery.isFunction( selector ) && 352 jQuery.grep(this, function(elem, i){ 353 return selector.call( elem, i ); 354 }) || 355 356 jQuery.multiFilter( selector, jQuery.grep(this, function(elem){ 357 return elem.nodeType === 1; 358 }) ), "filter", selector ); 359 }, 360 361 closest: function( selector ) { 362 var pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null, 363 closer = 0; 364 365 return this.map(function(){ 366 var cur = this; 367 while ( cur && cur.ownerDocument ) { 368 if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) ) { 369 jQuery.data(cur, "closest", closer); 370 return cur; 371 } 372 cur = cur.parentNode; 373 closer++; 374 } 375 }); 376 }, 377 378 not: function( selector ) { 379 if ( typeof selector === "string" ) 380 // test special case where just one selector is passed in 381 if ( isSimple.test( selector ) ) 382 return this.pushStack( jQuery.multiFilter( selector, this, true ), "not", selector ); 383 else 384 selector = jQuery.multiFilter( selector, this ); 385 386 var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType; 387 return this.filter(function() { 388 return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector; 389 }); 390 }, 391 392 add: function( selector ) { 393 return this.pushStack( jQuery.unique( jQuery.merge( 394 this.get(), 395 typeof selector === "string" ? 396 jQuery( selector ) : 397 jQuery.makeArray( selector ) 398 ))); 399 }, 400 401 is: function( selector ) { 402 return !!selector && jQuery.multiFilter( selector, this ).length > 0; 403 }, 404 405 hasClass: function( selector ) { 406 return !!selector && this.is( "." + selector ); 407 }, 408 409 val: function( value ) { 410 if ( value === undefined ) { 411 var elem = this[0]; 412 413 if ( elem ) { 414 if( jQuery.nodeName( elem, 'option' ) ) 415 return (elem.attributes.value || {}).specified ? elem.value : elem.text; 416 417 // We need to handle select boxes special 418 if ( jQuery.nodeName( elem, "select" ) ) { 419 var index = elem.selectedIndex, 420 values = [], 421 options = elem.options, 422 one = elem.type == "select-one"; 423 424 // Nothing was selected 425 if ( index < 0 ) 426 return null; 427 428 // Loop through all the selected options 429 for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { 430 var option = options[ i ]; 431 432 if ( option.selected ) { 433 // Get the specifc value for the option 434 value = jQuery(option).val(); 435 436 // We don't need an array for one selects 437 if ( one ) 438 return value; 439 440 // Multi-Selects return an array 441 values.push( value ); 442 } 443 } 444 445 return values; 446 } 447 448 // Everything else, we just grab the value 449 return (elem.value || "").replace(/\r/g, ""); 450 451 } 452 453 return undefined; 454 } 455 456 if ( typeof value === "number" ) 457 value += ''; 458 459 return this.each(function(){ 460 if ( this.nodeType != 1 ) 461 return; 462 463 if ( jQuery.isArray(value) && /radio|checkbox/.test( this.type ) ) 464 this.checked = (jQuery.inArray(this.value, value) >= 0 || 465 jQuery.inArray(this.name, value) >= 0); 466 467 else if ( jQuery.nodeName( this, "select" ) ) { 468 var values = jQuery.makeArray(value); 469 470 jQuery( "option", this ).each(function(){ 471 this.selected = (jQuery.inArray( this.value, values ) >= 0 || 472 jQuery.inArray( this.text, values ) >= 0); 473 }); 474 475 if ( !values.length ) 476 this.selectedIndex = -1; 477 478 } else 479 this.value = value; 480 }); 481 }, 482 483 html: function( value ) { 484 return value === undefined ? 485 (this[0] ? 486 this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g, "") : 487 null) : 488 this.empty().append( value ); 489 }, 490 491 replaceWith: function( value ) { 492 return this.after( value ).remove(); 493 }, 494 495 eq: function( i ) { 496 return this.slice( i, +i + 1 ); 497 }, 498 499 slice: function() { 500 return this.pushStack( Array.prototype.slice.apply( this, arguments ), 501 "slice", Array.prototype.slice.call(arguments).join(",") ); 502 }, 503 504 map: function( callback ) { 505 return this.pushStack( jQuery.map(this, function(elem, i){ 506 return callback.call( elem, i, elem ); 507 })); 508 }, 509 510 andSelf: function() { 511 return this.add( this.prevObject ); 512 }, 513 514 domManip: function( args, table, callback ) { 515 if ( this[0] ) { 516 var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(), 517 scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ), 518 first = fragment.firstChild; 519 520 if ( first ) 521 for ( var i = 0, l = this.length; i < l; i++ ) 522 callback.call( root(this[i], first), this.length > 1 || i > 0 ? 523 fragment.cloneNode(true) : fragment ); 524 525 if ( scripts ) 526 jQuery.each( scripts, evalScript ); 527 } 528 529 return this; 530 531 function root( elem, cur ) { 532 return table && jQuery.nodeName(elem, "table") && jQuery.nodeName(cur, "tr") ? 533 (elem.getElementsByTagName("tbody")[0] || 534 elem.appendChild(elem.ownerDocument.createElement("tbody"))) : 535 elem; 536 } 537 } 538 }; 539 540 // Give the init function the jQuery prototype for later instantiation 541 jQuery.fn.init.prototype = jQuery.fn; 542 543 function evalScript( i, elem ) { 544 if ( elem.src ) 545 jQuery.ajax({ 546 url: elem.src, 547 async: false, 548 dataType: "script" 549 }); 550 551 else 552 jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" ); 553 554 if ( elem.parentNode ) 555 elem.parentNode.removeChild( elem ); 556 } 557 558 function now(){ 559 return +new Date; 560 } 561 562 jQuery.extend = jQuery.fn.extend = function() { 563 // copy reference to target object 564 var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options; 565 566 // Handle a deep copy situation 567 if ( typeof target === "boolean" ) { 568 deep = target; 569 target = arguments[1] || {}; 570 // skip the boolean and the target 571 i = 2; 572 } 573 574 // Handle case when target is a string or something (possible in deep copy) 575 if ( typeof target !== "object" && !jQuery.isFunction(target) ) 576 target = {}; 577 578 // extend jQuery itself if only one argument is passed 579 if ( length == i ) { 580 target = this; 581 --i; 582 } 583 584 for ( ; i < length; i++ ) 585 // Only deal with non-null/undefined values 586 if ( (options = arguments[ i ]) != null ) 587 // Extend the base object 588 for ( var name in options ) { 589 var src = target[ name ], copy = options[ name ]; 590 591 // Prevent never-ending loop 592 if ( target === copy ) 593 continue; 594 595 // Recurse if we're merging object values 596 if ( deep && copy && typeof copy === "object" && !copy.nodeType ) 597 target[ name ] = jQuery.extend( deep, 598 // Never move original objects, clone them 599 src || ( copy.length != null ? [ ] : { } ) 600 , copy ); 601 602 // Don't bring in undefined values 603 else if ( copy !== undefined ) 604 target[ name ] = copy; 605 606 } 607 608 // Return the modified object 609 return target; 610 }; 611 612 // exclude the following css properties to add px 613 var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i, 614 // cache defaultView 615 defaultView = document.defaultView || {}, 616 toString = Object.prototype.toString; 617 618 jQuery.extend({ 619 noConflict: function( deep ) { 620 window.$ = _$; 621 622 if ( deep ) 623 window.jQuery = _jQuery; 624 625 return jQuery; 626 }, 627 628 // See test/unit/core.js for details concerning isFunction. 629 // Since version 1.3, DOM methods and functions like alert 630 // aren't supported. They return false on IE (#2968). 631 isFunction: function( obj ) { 632 return toString.call(obj) === "[object Function]"; 633 }, 634 635 isArray: function( obj ) { 636 return toString.call(obj) === "[object Array]"; 637 }, 638 639 // check if an element is in a (or is an) XML document 640 isXMLDoc: function( elem ) { 641 return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" || 642 !!elem.ownerDocument && jQuery.isXMLDoc( elem.ownerDocument ); 643 }, 644 645 // Evalulates a script in a global context 646 globalEval: function( data ) { 647 if ( data && /\S/.test(data) ) { 648 // Inspired by code by Andrea Giammarchi 649 // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html 650 var head = document.getElementsByTagName("head")[0] || document.documentElement, 651 script = document.createElement("script"); 652 653 script.type = "text/javascript"; 654 if ( jQuery.support.scriptEval ) 655 script.appendChild( document.createTextNode( data ) ); 656 else 657 script.text = data; 658 659 // Use insertBefore instead of appendChild to circumvent an IE6 bug. 660 // This arises when a base node is used (#2709). 661 head.insertBefore( script, head.firstChild ); 662 head.removeChild( script ); 663 } 664 }, 665 666 nodeName: function( elem, name ) { 667 return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase(); 668 }, 669 670 // args is for internal usage only 671 each: function( object, callback, args ) { 672 var name, i = 0, length = object.length; 673 674 if ( args ) { 675 if ( length === undefined ) { 676 for ( name in object ) 677 if ( callback.apply( object[ name ], args ) === false ) 678 break; 679 } else 680 for ( ; i < length; ) 681 if ( callback.apply( object[ i++ ], args ) === false ) 682 break; 683 684 // A special, fast, case for the most common use of each 685 } else { 686 if ( length === undefined ) { 687 for ( name in object ) 688 if ( callback.call( object[ name ], name, object[ name ] ) === false ) 689 break; 690 } else 691 for ( var value = object[0]; 692 i < length && callback.call( value, i, value ) !== false; value = object[++i] ){} 693 } 694 695 return object; 696 }, 697 698 prop: function( elem, value, type, i, name ) { 699 // Handle executable functions 700 if ( jQuery.isFunction( value ) ) 701 value = value.call( elem, i ); 702 703 // Handle passing in a number to a CSS property 704 return typeof value === "number" && type == "curCSS" && !exclude.test( name ) ? 705 value + "px" : 706 value; 707 }, 708 709 className: { 710 // internal only, use addClass("class") 711 add: function( elem, classNames ) { 712 jQuery.each((classNames || "").split(/\s+/), function(i, className){ 713 if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) ) 714 elem.className += (elem.className ? " " : "") + className; 715 }); 716 }, 717 718 // internal only, use removeClass("class") 719 remove: function( elem, classNames ) { 720 if (elem.nodeType == 1) 721 elem.className = classNames !== undefined ? 722 jQuery.grep(elem.className.split(/\s+/), function(className){ 723 return !jQuery.className.has( classNames, className ); 724 }).join(" ") : 725 ""; 726 }, 727 728 // internal only, use hasClass("class") 729 has: function( elem, className ) { 730 return elem && jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1; 731 } 732 }, 733 734 // A method for quickly swapping in/out CSS properties to get correct calculations 735 swap: function( elem, options, callback ) { 736 var old = {}; 737 // Remember the old values, and insert the new ones 738 for ( var name in options ) { 739 old[ name ] = elem.style[ name ]; 740 elem.style[ name ] = options[ name ]; 741 } 742 743 callback.call( elem ); 744 745 // Revert the old values 746 for ( var name in options ) 747 elem.style[ name ] = old[ name ]; 748 }, 749 750 css: function( elem, name, force, extra ) { 751 if ( name == "width" || name == "height" ) { 752 var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ]; 753 754 function getWH() { 755 val = name == "width" ? elem.offsetWidth : elem.offsetHeight; 756 757 if ( extra === "border" ) 758 return; 759 760 jQuery.each( which, function() { 761 if ( !extra ) 762 val -= parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0; 763 if ( extra === "margin" ) 764 val += parseFloat(jQuery.curCSS( elem, "margin" + this, true)) || 0; 765 else 766 val -= parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0; 767 }); 768 } 769 770 if ( elem.offsetWidth !== 0 ) 771 getWH(); 772 else 773 jQuery.swap( elem, props, getWH ); 774 775 return Math.max(0, Math.round(val)); 776 } 777 778 return jQuery.curCSS( elem, name, force ); 779 }, 780 781 curCSS: function( elem, name, force ) { 782 var ret, style = elem.style; 783 784 // We need to handle opacity special in IE 785 if ( name == "opacity" && !jQuery.support.opacity ) { 786 ret = jQuery.attr( style, "opacity" ); 787 788 return ret == "" ? 789 "1" : 790 ret; 791 } 792 793 // Make sure we're using the right name for getting the float value 794 if ( name.match( /float/i ) ) 795 name = styleFloat; 796 797 if ( !force && style && style[ name ] ) 798 ret = style[ name ]; 799 800 else if ( defaultView.getComputedStyle ) { 801 802 // Only "float" is needed here 803 if ( name.match( /float/i ) ) 804 name = "float"; 805 806 name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase(); 807 808 var computedStyle = defaultView.getComputedStyle( elem, null ); 809 810 if ( computedStyle ) 811 ret = computedStyle.getPropertyValue( name ); 812 813 // We should always get a number back from opacity 814 if ( name == "opacity" && ret == "" ) 815 ret = "1"; 816 817 } else if ( elem.currentStyle ) { 818 var camelCase = name.replace(/\-(\w)/g, function(all, letter){ 819 return letter.toUpperCase(); 820 }); 821 822 ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ]; 823 824 // From the awesome hack by Dean Edwards 825 // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 826 827 // If we're not dealing with a regular pixel number 828 // but a number that has a weird ending, we need to convert it to pixels 829 if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) { 830 // Remember the original values 831 var left = style.left, rsLeft = elem.runtimeStyle.left; 832 833 // Put in the new values to get a computed value out 834 elem.runtimeStyle.left = elem.currentStyle.left; 835 style.left = ret || 0; 836 ret = style.pixelLeft + "px"; 837 838 // Revert the changed values 839 style.left = left; 840 elem.runtimeStyle.left = rsLeft; 841 } 842 } 843 844 return ret; 845 }, 846 847 clean: function( elems, context, fragment ) { 848 context = context || document; 849 850 // !context.createElement fails in IE with an error but returns typeof 'object' 851 if ( typeof context.createElement === "undefined" ) 852 context = context.ownerDocument || context[0] && context[0].ownerDocument || document; 853 854 // If a single string is passed in and it's a single tag 855 // just do a createElement and skip the rest 856 if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) { 857 var match = /^<(\w+)\s*\/?>$/.exec(elems[0]); 858 if ( match ) 859 return [ context.createElement( match[1] ) ]; 860 } 861 862 var ret = [], scripts = [], div = context.createElement("div"); 863 864 jQuery.each(elems, function(i, elem){ 865 if ( typeof elem === "number" ) 866 elem += ''; 867 868 if ( !elem ) 869 return; 870 871 // Convert html string into DOM nodes 872 if ( typeof elem === "string" ) { 873 // Fix "XHTML"-style tags in all browsers 874 elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){ 875 return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ? 876 all : 877 front + "></" + tag + ">"; 878 }); 879 880 // Trim whitespace, otherwise indexOf won't work as expected 881 var tags = elem.replace(/^\s+/, "").substring(0, 10).toLowerCase(); 882 883 var wrap = 884 // option or optgroup 885 !tags.indexOf("<opt") && 886 [ 1, "<select multiple='multiple'>", "</select>" ] || 887 888 !tags.indexOf("<leg") && 889 [ 1, "<fieldset>", "</fieldset>" ] || 890 891 tags.match(/^<(thead|tbody|tfoot|colg|cap)/) && 892 [ 1, "<table>", "</table>" ] || 893 894 !tags.indexOf("<tr") && 895 [ 2, "<table><tbody>", "</tbody></table>" ] || 896 897 // <thead> matched above 898 (!tags.indexOf("<td") || !tags.indexOf("<th")) && 899 [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] || 900 901 !tags.indexOf("<col") && 902 [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] || 903 904 // IE can't serialize <link> and <script> tags normally 905 !jQuery.support.htmlSerialize && 906 [ 1, "div<div>", "</div>" ] || 907 908 [ 0, "", "" ]; 909 910 // Go to html and back, then peel off extra wrappers 911 div.innerHTML = wrap[1] + elem + wrap[2]; 912 913 // Move to the right depth 914 while ( wrap[0]-- ) 915 div = div.lastChild; 916 917 // Remove IE's autoinserted <tbody> from table fragments 918 if ( !jQuery.support.tbody ) { 919 920 // String was a <table>, *may* have spurious <tbody> 921 var hasBody = /<tbody/i.test(elem), 922 tbody = !tags.indexOf("<table") && !hasBody ? 923 div.firstChild && div.firstChild.childNodes : 924 925 // String was a bare <thead> or <tfoot> 926 wrap[1] == "<table>" && !hasBody ? 927 div.childNodes : 928 []; 929 930 for ( var j = tbody.length - 1; j >= 0 ; --j ) 931 if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) 932 tbody[ j ].parentNode.removeChild( tbody[ j ] ); 933 934 } 935 936 // IE completely kills leading whitespace when innerHTML is used 937 if ( !jQuery.support.leadingWhitespace && /^\s/.test( elem ) ) 938 div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild ); 939 940 elem = jQuery.makeArray( div.childNodes ); 941 } 942 943 if ( elem.nodeType ) 944 ret.push( elem ); 945 else 946 ret = jQuery.merge( ret, elem ); 947 948 }); 949 950 if ( fragment ) { 951 for ( var i = 0; ret[i]; i++ ) { 952 if ( jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) { 953 scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] ); 954 } else { 955 if ( ret[i].nodeType === 1 ) 956 ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) ); 957 fragment.appendChild( ret[i] ); 958 } 959 } 960 961 return scripts; 962 } 963 964 return ret; 965 }, 966 967 attr: function( elem, name, value ) { 968 // don't set attributes on text and comment nodes 969 if (!elem || elem.nodeType == 3 || elem.nodeType == 8) 970 return undefined; 971 972 var notxml = !jQuery.isXMLDoc( elem ), 973 // Whether we are setting (or getting) 974 set = value !== undefined; 975 976 // Try to normalize/fix the name 977 name = notxml && jQuery.props[ name ] || name; 978 979 // Only do all the following if this is a node (faster for style) 980 // IE elem.getAttribute passes even for style 981 if ( elem.tagName ) { 982 983 // These attributes require special treatment 984 var special = /href|src|style/.test( name ); 985 986 // Safari mis-reports the default selected property of a hidden option 987 // Accessing the parent's selectedIndex property fixes it 988 if ( name == "selected" && elem.parentNode ) 989 elem.parentNode.selectedIndex; 990 991 // If applicable, access the attribute via the DOM 0 way 992 if ( name in elem && notxml && !special ) { 993 if ( set ){ 994 // We can't allow the type property to be changed (since it causes problems in IE) 995 if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode ) 996 throw "type property can't be changed"; 997 998 elem[ name ] = value; 999 } 1000 1001 // browsers index elements by id/name on forms, give priority to attributes. 1002 if( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) 1003 return elem.getAttributeNode( name ).nodeValue; 1004 1005 // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set 1006 // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ 1007 if ( name == "tabIndex" ) { 1008 var attributeNode = elem.getAttributeNode( "tabIndex" ); 1009 return attributeNode && attributeNode.specified 1010 ? attributeNode.value 1011 : elem.nodeName.match(/(button|input|object|select|textarea)/i) 1012 ? 0 1013 : elem.nodeName.match(/^(a|area)$/i) && elem.href 1014 ? 0 1015 : undefined; 1016 } 1017 1018 return elem[ name ]; 1019 } 1020 1021 if ( !jQuery.support.style && notxml && name == "style" ) 1022 return jQuery.attr( elem.style, "cssText", value ); 1023 1024 if ( set ) 1025 // convert the value to a string (all browsers do this but IE) see #1070 1026 elem.setAttribute( name, "" + value ); 1027 1028 var attr = !jQuery.support.hrefNormalized && notxml && special 1029 // Some attributes require a special call on IE 1030 ? elem.getAttribute( name, 2 ) 1031 : elem.getAttribute( name ); 1032 1033 // Non-existent attributes return null, we normalize to undefined 1034 return attr === null ? undefined : attr; 1035 } 1036 1037 // elem is actually elem.style ... set the style 1038 1039 // IE uses filters for opacity 1040 if ( !jQuery.support.opacity && name == "opacity" ) { 1041 if ( set ) { 1042 // IE has trouble with opacity if it does not have layout 1043 // Force it by setting the zoom level 1044 elem.zoom = 1; 1045 1046 // Set the alpha filter to set the opacity 1047 elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) + 1048 (parseInt( value ) + '' == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")"); 1049 } 1050 1051 return elem.filter && elem.filter.indexOf("opacity=") >= 0 ? 1052 (parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100) + '': 1053 ""; 1054 } 1055 1056 name = name.replace(/-([a-z])/ig, function(all, letter){ 1057 return letter.toUpperCase(); 1058 }); 1059 1060 if ( set ) 1061 elem[ name ] = value; 1062 1063 return elem[ name ]; 1064 }, 1065 1066 trim: function( text ) { 1067 return (text || "").replace( /^\s+|\s+$/g, "" ); 1068 }, 1069 1070 makeArray: function( array ) { 1071 var ret = []; 1072 1073 if( array != null ){ 1074 var i = array.length; 1075 // The window, strings (and functions) also have 'length' 1076 if( i == null || typeof array === "string" || jQuery.isFunction(array) || array.setInterval ) 1077 ret[0] = array; 1078 else 1079 while( i ) 1080 ret[--i] = array[i]; 1081 } 1082 1083 return ret; 1084 }, 1085 1086 inArray: function( elem, array ) { 1087 for ( var i = 0, length = array.length; i < length; i++ ) 1088 // Use === because on IE, window == document 1089 if ( array[ i ] === elem ) 1090 return i; 1091 1092 return -1; 1093 }, 1094 1095 merge: function( first, second ) { 1096 // We have to loop this way because IE & Opera overwrite the length 1097 // expando of getElementsByTagName 1098 var i = 0, elem, pos = first.length; 1099 // Also, we need to make sure that the correct elements are being returned 1100 // (IE returns comment nodes in a '*' query) 1101 if ( !jQuery.support.getAll ) { 1102 while ( (elem = second[ i++ ]) != null ) 1103 if ( elem.nodeType != 8 ) 1104 first[ pos++ ] = elem; 1105 1106 } else 1107 while ( (elem = second[ i++ ]) != null ) 1108 first[ pos++ ] = elem; 1109 1110 return first; 1111 }, 1112 1113 unique: function( array ) { 1114 var ret = [], done = {}; 1115 1116 try { 1117 1118 for ( var i = 0, length = array.length; i < length; i++ ) { 1119 var id = jQuery.data( array[ i ] ); 1120 1121 if ( !done[ id ] ) { 1122 done[ id ] = true; 1123 ret.push( array[ i ] ); 1124 } 1125 } 1126 1127 } catch( e ) { 1128 ret = array; 1129 } 1130 1131 return ret; 1132 }, 1133 1134 grep: function( elems, callback, inv ) { 1135 var ret = []; 1136 1137 // Go through the array, only saving the items 1138 // that pass the validator function 1139 for ( var i = 0, length = elems.length; i < length; i++ ) 1140 if ( !inv != !callback( elems[ i ], i ) ) 1141 ret.push( elems[ i ] ); 1142 1143 return ret; 1144 }, 1145 1146 map: function( elems, callback ) { 1147 var ret = []; 1148 1149 // Go through the array, translating each of the items to their 1150 // new value (or values). 1151 for ( var i = 0, length = elems.length; i < length; i++ ) { 1152 var value = callback( elems[ i ], i ); 1153 1154 if ( value != null ) 1155 ret[ ret.length ] = value; 1156 } 1157 1158 return ret.concat.apply( [], ret ); 1159 } 1160 }); 1161 1162 // Use of jQuery.browser is deprecated. 1163 // It's included for backwards compatibility and plugins, 1164 // although they should work to migrate away. 1165 1166 var userAgent = navigator.userAgent.toLowerCase(); 1167 1168 // Figure out what browser is being used 1169 jQuery.browser = { 1170 version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1], 1171 safari: /webkit/.test( userAgent ), 1172 opera: /opera/.test( userAgent ), 1173 msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ), 1174 mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent ) 1175 }; 1176 1177 jQuery.each({ 1178 parent: function(elem){return elem.parentNode;}, 1179 parents: function(elem){return jQuery.dir(elem,"parentNode");}, 1180 next: function(elem){return jQuery.nth(elem,2,"nextSibling");}, 1181 prev: function(elem){return jQuery.nth(elem,2,"previousSibling");}, 1182 nextAll: function(elem){return jQuery.dir(elem,"nextSibling");}, 1183 prevAll: function(elem){return jQuery.dir(elem,"previousSibling");}, 1184 siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);}, 1185 children: function(elem){return jQuery.sibling(elem.firstChild);}, 1186 contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);} 1187 }, function(name, fn){ 1188 jQuery.fn[ name ] = function( selector ) { 1189 var ret = jQuery.map( this, fn ); 1190 1191 if ( selector && typeof selector == "string" ) 1192 ret = jQuery.multiFilter( selector, ret ); 1193 1194 return this.pushStack( jQuery.unique( ret ), name, selector ); 1195 }; 1196 }); 1197 1198 jQuery.each({ 1199 appendTo: "append", 1200 prependTo: "prepend", 1201 insertBefore: "before", 1202 insertAfter: "after", 1203 replaceAll: "replaceWith" 1204 }, function(name, original){ 1205 jQuery.fn[ name ] = function( selector ) { 1206 var ret = [], insert = jQuery( selector ); 1207 1208 for ( var i = 0, l = insert.length; i < l; i++ ) { 1209 var elems = (i > 0 ? this.clone(true) : this).get(); 1210 jQuery.fn[ original ].apply( jQuery(insert[i]), elems ); 1211 ret = ret.concat( elems ); 1212 } 1213 1214 return this.pushStack( ret, name, selector ); 1215 }; 1216 }); 1217 1218 jQuery.each({ 1219 removeAttr: function( name ) { 1220 jQuery.attr( this, name, "" ); 1221 if (this.nodeType == 1) 1222 this.removeAttribute( name ); 1223 }, 1224 1225 addClass: function( classNames ) { 1226 jQuery.className.add( this, classNames ); 1227 }, 1228 1229 removeClass: function( classNames ) { 1230 jQuery.className.remove( this, classNames ); 1231 }, 1232 1233 toggleClass: function( classNames, state ) { 1234 if( typeof state !== "boolean" ) 1235 state = !jQuery.className.has( this, classNames ); 1236 jQuery.className[ state ? "add" : "remove" ]( this, classNames ); 1237 }, 1238 1239 remove: function( selector ) { 1240 if ( !selector || jQuery.filter( selector, [ this ] ).length ) { 1241 // Prevent memory leaks 1242 jQuery( "*", this ).add([this]).each(function(){ 1243 jQuery.event.remove(this); 1244 jQuery.removeData(this); 1245 }); 1246 if (this.parentNode) 1247 this.parentNode.removeChild( this ); 1248 } 1249 }, 1250 1251 empty: function() { 1252 // Remove element nodes and prevent memory leaks 1253 jQuery(this).children().remove(); 1254 1255 // Remove any remaining nodes 1256 while ( this.firstChild ) 1257 this.removeChild( this.firstChild ); 1258 } 1259 }, function(name, fn){ 1260 jQuery.fn[ name ] = function(){ 1261 return this.each( fn, arguments ); 1262 }; 1263 }); 1264 1265 // Helper function used by the dimensions and offset modules 1266 function num(elem, prop) { 1267 return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0; 1268 } 1269 var expando = "jQuery" + now(), uuid = 0, windowData = {}; 1270 1271 jQuery.extend({ 1272 cache: {}, 1273 1274 data: function( elem, name, data ) { 1275 elem = elem == window ? 1276 windowData : 1277 elem; 1278 1279 var id = elem[ expando ]; 1280 1281 // Compute a unique ID for the element 1282 if ( !id ) 1283 id = elem[ expando ] = ++uuid; 1284 1285 // Only generate the data cache if we're 1286 // trying to access or manipulate it 1287 if ( name && !jQuery.cache[ id ] ) 1288 jQuery.cache[ id ] = {}; 1289 1290 // Prevent overriding the named cache with undefined values 1291 if ( data !== undefined ) 1292 jQuery.cache[ id ][ name ] = data; 1293 1294 // Return the named cache data, or the ID for the element 1295 return name ? 1296 jQuery.cache[ id ][ name ] : 1297 id; 1298 }, 1299 1300 removeData: function( elem, name ) { 1301 elem = elem == window ? 1302 windowData : 1303 elem; 1304 1305 var id = elem[ expando ]; 1306 1307 // If we want to remove a specific section of the element's data 1308 if ( name ) { 1309 if ( jQuery.cache[ id ] ) { 1310 // Remove the section of cache data 1311 delete jQuery.cache[ id ][ name ]; 1312 1313 // If we've removed all the data, remove the element's cache 1314 name = ""; 1315 1316 for ( name in jQuery.cache[ id ] ) 1317 break; 1318 1319 if ( !name ) 1320 jQuery.removeData( elem ); 1321 } 1322 1323 // Otherwise, we want to remove all of the element's data 1324 } else { 1325 // Clean up the element expando 1326 try { 1327 delete elem[ expando ]; 1328 } catch(e){ 1329 // IE has trouble directly removing the expando 1330 // but it's ok with using removeAttribute 1331 if ( elem.removeAttribute ) 1332 elem.removeAttribute( expando ); 1333 } 1334 1335 // Completely remove the data cache 1336 delete jQuery.cache[ id ]; 1337 } 1338 }, 1339 queue: function( elem, type, data ) { 1340 if ( elem ){ 1341 1342 type = (type || "fx") + "queue"; 1343 1344 var q = jQuery.data( elem, type ); 1345 1346 if ( !q || jQuery.isArray(data) ) 1347 q = jQuery.data( elem, type, jQuery.makeArray(data) ); 1348 else if( data ) 1349 q.push( data ); 1350 1351 } 1352 return q; 1353 }, 1354 1355 dequeue: function( elem, type ){ 1356 var queue = jQuery.queue( elem, type ), 1357 fn = queue.shift(); 1358 1359 if( !type || type === "fx" ) 1360 fn = queue[0]; 1361 1362 if( fn !== undefined ) 1363 fn.call(elem); 1364 } 1365 }); 1366 1367 jQuery.fn.extend({ 1368 data: function( key, value ){ 1369 var parts = key.split("."); 1370 parts[1] = parts[1] ? "." + parts[1] : ""; 1371 1372 if ( value === undefined ) { 1373 var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); 1374 1375 if ( data === undefined && this.length ) 1376 data = jQuery.data( this[0], key ); 1377 1378 return data === undefined && parts[1] ? 1379 this.data( parts[0] ) : 1380 data; 1381 } else 1382 return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){ 1383 jQuery.data( this, key, value ); 1384 }); 1385 }, 1386 1387 removeData: function( key ){ 1388 return this.each(function(){ 1389 jQuery.removeData( this, key ); 1390 }); 1391 }, 1392 queue: function(type, data){ 1393 if ( typeof type !== "string" ) { 1394 data = type; 1395 type = "fx"; 1396 } 1397 1398 if ( data === undefined ) 1399 return jQuery.queue( this[0], type ); 1400 1401 return this.each(function(){ 1402 var queue = jQuery.queue( this, type, data ); 1403 1404 if( type == "fx" && queue.length == 1 ) 1405 queue[0].call(this); 1406 }); 1407 }, 1408 dequeue: function(type){ 1409 return this.each(function(){ 1410 jQuery.dequeue( this, type ); 1411 }); 1412 } 1413 });/*! 1414 * Sizzle CSS Selector Engine - v0.9.3 1415 * Copyright 2009, The Dojo Foundation 1416 * Released under the MIT, BSD, and GPL Licenses. 1417 * More information: http://sizzlejs.com/ 1418 */ 1419 (function(){ 1420 1421 var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g, 1422 done = 0, 1423 toString = Object.prototype.toString; 1424 1425 var Sizzle = function(selector, context, results, seed) { 1426 results = results || []; 1427 context = context || document; 1428 1429 if ( context.nodeType !== 1 && context.nodeType !== 9 ) 1430 return []; 1431 1432 if ( !selector || typeof selector !== "string" ) { 1433 return results; 1434 } 1435 1436 var parts = [], m, set, checkSet, check, mode, extra, prune = true; 1437 1438 // Reset the position of the chunker regexp (start from head) 1439 chunker.lastIndex = 0; 1440 1441 while ( (m = chunker.exec(selector)) !== null ) { 1442 parts.push( m[1] ); 1443 1444 if ( m[2] ) { 1445 extra = RegExp.rightContext; 1446 break; 1447 } 1448 } 1449 1450 if ( parts.length > 1 && origPOS.exec( selector ) ) { 1451 if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { 1452 set = posProcess( parts[0] + parts[1], context ); 1453 } else { 1454 set = Expr.relative[ parts[0] ] ? 1455 [ context ] : 1456 Sizzle( parts.shift(), context ); 1457 1458 while ( parts.length ) { 1459 selector = parts.shift(); 1460 1461 if ( Expr.relative[ selector ] ) 1462 selector += parts.shift(); 1463 1464 set = posProcess( selector, set ); 1465 } 1466 } 1467 } else { 1468 var ret = seed ? 1469 { expr: parts.pop(), set: makeArray(seed) } : 1470 Sizzle.find( parts.pop(), parts.length === 1 && context.parentNode ? context.parentNode : context, isXML(context) ); 1471 set = Sizzle.filter( ret.expr, ret.set ); 1472 1473 if ( parts.length > 0 ) { 1474 checkSet = makeArray(set); 1475 } else { 1476 prune = false; 1477 } 1478 1479 while ( parts.length ) { 1480 var cur = parts.pop(), pop = cur; 1481 1482 if ( !Expr.relative[ cur ] ) { 1483 cur = ""; 1484 } else { 1485 pop = parts.pop(); 1486 } 1487 1488 if ( pop == null ) { 1489 pop = context; 1490 } 1491 1492 Expr.relative[ cur ]( checkSet, pop, isXML(context) ); 1493 } 1494 } 1495 1496 if ( !checkSet ) { 1497 checkSet = set; 1498 } 1499 1500 if ( !checkSet ) { 1501 throw "Syntax error, unrecognized expression: " + (cur || selector); 1502 } 1503 1504 if ( toString.call(checkSet) === "[object Array]" ) { 1505 if ( !prune ) { 1506 results.push.apply( results, checkSet ); 1507 } else if ( context.nodeType === 1 ) { 1508 for ( var i = 0; checkSet[i] != null; i++ ) { 1509 if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) { 1510 results.push( set[i] ); 1511 } 1512 } 1513 } else { 1514 for ( var i = 0; checkSet[i] != null; i++ ) { 1515 if ( checkSet[i] && checkSet[i].nodeType === 1 ) { 1516 results.push( set[i] ); 1517 } 1518 } 1519 } 1520 } else { 1521 makeArray( checkSet, results ); 1522 } 1523 1524 if ( extra ) { 1525 Sizzle( extra, context, results, seed ); 1526 1527 if ( sortOrder ) { 1528 hasDuplicate = false; 1529 results.sort(sortOrder); 1530 1531 if ( hasDuplicate ) { 1532 for ( var i = 1; i < results.length; i++ ) { 1533 if ( results[i] === results[i-1] ) { 1534 results.splice(i--, 1); 1535 } 1536 } 1537 } 1538 } 1539 } 1540 1541 return results; 1542 }; 1543 1544 Sizzle.matches = function(expr, set){ 1545 return Sizzle(expr, null, null, set); 1546 }; 1547 1548 Sizzle.find = function(expr, context, isXML){ 1549 var set, match; 1550 1551 if ( !expr ) { 1552 return []; 1553 } 1554 1555 for ( var i = 0, l = Expr.order.length; i < l; i++ ) { 1556 var type = Expr.order[i], match; 1557 1558 if ( (match = Expr.match[ type ].exec( expr )) ) { 1559 var left = RegExp.leftContext; 1560 1561 if ( left.substr( left.length - 1 ) !== "\\" ) { 1562 match[1] = (match[1] || "").replace(/\\/g, ""); 1563 set = Expr.find[ type ]( match, context, isXML ); 1564 if ( set != null ) { 1565 expr = expr.replace( Expr.match[ type ], "" ); 1566 break; 1567 } 1568 } 1569 } 1570 } 1571 1572 if ( !set ) { 1573 set = context.getElementsByTagName("*"); 1574 } 1575 1576 return {set: set, expr: expr}; 1577 }; 1578 1579 Sizzle.filter = function(expr, set, inplace, not){ 1580 var old = expr, result = [], curLoop = set, match, anyFound, 1581 isXMLFilter = set && set[0] && isXML(set[0]); 1582 1583 while ( expr && set.length ) { 1584 for ( var type in Expr.filter ) { 1585 if ( (match = Expr.match[ type ].exec( expr )) != null ) { 1586 var filter = Expr.filter[ type ], found, item; 1587 anyFound = false; 1588 1589 if ( curLoop == result ) { 1590 result = []; 1591 } 1592 1593 if ( Expr.preFilter[ type ] ) { 1594 match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); 1595 1596 if ( !match ) { 1597 anyFound = found = true; 1598 } else if ( match === true ) { 1599 continue; 1600 } 1601 } 1602 1603 if ( match ) { 1604 for ( var i = 0; (item = curLoop[i]) != null; i++ ) { 1605 if ( item ) { 1606 found = filter( item, match, i, curLoop ); 1607 var pass = not ^ !!found; 1608 1609 if ( inplace && found != null ) { 1610 if ( pass ) { 1611 anyFound = true; 1612 } else { 1613 curLoop[i] = false; 1614 } 1615 } else if ( pass ) { 1616 result.push( item ); 1617 anyFound = true; 1618 } 1619 } 1620 } 1621 } 1622 1623 if ( found !== undefined ) { 1624 if ( !inplace ) { 1625 curLoop = result; 1626 } 1627 1628 expr = expr.replace( Expr.match[ type ], "" ); 1629 1630 if ( !anyFound ) { 1631 return []; 1632 } 1633 1634 break; 1635 } 1636 } 1637 } 1638 1639 // Improper expression 1640 if ( expr == old ) { 1641 if ( anyFound == null ) { 1642 throw "Syntax error, unrecognized expression: " + expr; 1643 } else { 1644 break; 1645 } 1646 } 1647 1648 old = expr; 1649 } 1650 1651 return curLoop; 1652 }; 1653 1654 var Expr = Sizzle.selectors = { 1655 order: [ "ID", "NAME", "TAG" ], 1656 match: { 1657 ID: /#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/, 1658 CLASS: /\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/, 1659 NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/, 1660 ATTR: /\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/, 1661 TAG: /^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/, 1662 CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/, 1663 POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/, 1664 PSEUDO: /:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/ 1665 }, 1666 attrMap: { 1667 "class": "className", 1668 "for": "htmlFor" 1669 }, 1670 attrHandle: { 1671 href: function(elem){ 1672 return elem.getAttribute("href"); 1673 } 1674 }, 1675 relative: { 1676 "+": function(checkSet, part, isXML){ 1677 var isPartStr = typeof part === "string", 1678 isTag = isPartStr && !/\W/.test(part), 1679 isPartStrNotTag = isPartStr && !isTag; 1680 1681 if ( isTag && !isXML ) { 1682 part = part.toUpperCase(); 1683 } 1684 1685 for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { 1686 if ( (elem = checkSet[i]) ) { 1687 while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} 1688 1689 checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ? 1690 elem || false : 1691 elem === part; 1692 } 1693 } 1694 1695 if ( isPartStrNotTag ) { 1696 Sizzle.filter( part, checkSet, true ); 1697 } 1698 }, 1699 ">": function(checkSet, part, isXML){ 1700 var isPartStr = typeof part === "string"; 1701 1702 if ( isPartStr && !/\W/.test(part) ) { 1703 part = isXML ? part : part.toUpperCase(); 1704 1705 for ( var i = 0, l = checkSet.length; i < l; i++ ) { 1706 var elem = checkSet[i]; 1707 if ( elem ) { 1708 var parent = elem.parentNode; 1709 checkSet[i] = parent.nodeName === part ? parent : false; 1710 } 1711 } 1712 } else { 1713 for ( var i = 0, l = checkSet.length; i < l; i++ ) { 1714 var elem = checkSet[i]; 1715 if ( elem ) { 1716 checkSet[i] = isPartStr ? 1717 elem.parentNode : 1718 elem.parentNode === part; 1719 } 1720 } 1721 1722 if ( isPartStr ) { 1723 Sizzle.filter( part, checkSet, true ); 1724 } 1725 } 1726 }, 1727 "": function(checkSet, part, isXML){ 1728 var doneName = done++, checkFn = dirCheck; 1729 1730 if ( !part.match(/\W/) ) { 1731 var nodeCheck = part = isXML ? part : part.toUpperCase(); 1732 checkFn = dirNodeCheck; 1733 } 1734 1735 checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML); 1736 }, 1737 "~": function(checkSet, part, isXML){ 1738 var doneName = done++, checkFn = dirCheck; 1739 1740 if ( typeof part === "string" && !part.match(/\W/) ) { 1741 var nodeCheck = part = isXML ? part : part.toUpperCase(); 1742 checkFn = dirNodeCheck; 1743 } 1744 1745 checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML); 1746 } 1747 }, 1748 find: { 1749 ID: function(match, context, isXML){ 1750 if ( typeof context.getElementById !== "undefined" && !isXML ) { 1751 var m = context.getElementById(match[1]); 1752 return m ? [m] : []; 1753 } 1754 }, 1755 NAME: function(match, context, isXML){ 1756 if ( typeof context.getElementsByName !== "undefined" ) { 1757 var ret = [], results = context.getElementsByName(match[1]); 1758 1759 for ( var i = 0, l = results.length; i < l; i++ ) { 1760 if ( results[i].getAttribute("name") === match[1] ) { 1761 ret.push( results[i] ); 1762 } 1763 } 1764 1765 return ret.length === 0 ? null : ret; 1766 } 1767 }, 1768 TAG: function(match, context){ 1769 return context.getElementsByTagName(match[1]); 1770 } 1771 }, 1772 preFilter: { 1773 CLASS: function(match, curLoop, inplace, result, not, isXML){ 1774 match = " " + match[1].replace(/\\/g, "") + " "; 1775 1776 if ( isXML ) { 1777 return match; 1778 } 1779 1780 for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { 1781 if ( elem ) { 1782 if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) { 1783 if ( !inplace ) 1784 result.push( elem ); 1785 } else if ( inplace ) { 1786 curLoop[i] = false; 1787 } 1788 } 1789 } 1790 1791 return false; 1792 }, 1793 ID: function(match){ 1794 return match[1].replace(/\\/g, ""); 1795 }, 1796 TAG: function(match, curLoop){ 1797 for ( var i = 0; curLoop[i] === false; i++ ){} 1798 return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase(); 1799 }, 1800 CHILD: function(match){ 1801 if ( match[1] == "nth" ) { 1802 // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' 1803 var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec( 1804 match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" || 1805 !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); 1806 1807 // calculate the numbers (first)n+(last) including if they are negative 1808 match[2] = (test[1] + (test[2] || 1)) - 0; 1809 match[3] = test[3] - 0; 1810 } 1811 1812 // TODO: Move to normal caching system 1813 match[0] = done++; 1814 1815 return match; 1816 }, 1817 ATTR: function(match, curLoop, inplace, result, not, isXML){ 1818 var name = match[1].replace(/\\/g, ""); 1819 1820 if ( !isXML && Expr.attrMap[name] ) { 1821 match[1] = Expr.attrMap[name]; 1822 } 1823 1824 if ( match[2] === "~=" ) { 1825 match[4] = " " + match[4] + " "; 1826 } 1827 1828 return match; 1829 }, 1830 PSEUDO: function(match, curLoop, inplace, result, not){ 1831 if ( match[1] === "not" ) { 1832 // If we're dealing with a complex expression, or a simple one 1833 if ( match[3].match(chunker).length > 1 || /^\w/.test(match[3]) ) { 1834 match[3] = Sizzle(match[3], null, null, curLoop); 1835 } else { 1836 var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); 1837 if ( !inplace ) { 1838 result.push.apply( result, ret ); 1839 } 1840 return false; 1841 } 1842 } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { 1843 return true; 1844 } 1845 1846 return match; 1847 }, 1848 POS: function(match){ 1849 match.unshift( true ); 1850 return match; 1851 } 1852 }, 1853 filters: { 1854 enabled: function(elem){ 1855 return elem.disabled === false && elem.type !== "hidden"; 1856 }, 1857 disabled: function(elem){ 1858 return elem.disabled === true; 1859 }, 1860 checked: function(elem){ 1861 return elem.checked === true; 1862 }, 1863 selected: function(elem){ 1864 // Accessing this property makes selected-by-default 1865 // options in Safari work properly 1866 elem.parentNode.selectedIndex; 1867 return elem.selected === true; 1868 }, 1869 parent: function(elem){ 1870 return !!elem.firstChild; 1871 }, 1872 empty: function(elem){ 1873 return !elem.firstChild; 1874 }, 1875 has: function(elem, i, match){ 1876 return !!Sizzle( match[3], elem ).length; 1877 }, 1878 header: function(elem){ 1879 return /h\d/i.test( elem.nodeName ); 1880 }, 1881 text: function(elem){ 1882 return "text" === elem.type; 1883 }, 1884 radio: function(elem){ 1885 return "radio" === elem.type; 1886 }, 1887 checkbox: function(elem){ 1888 return "checkbox" === elem.type; 1889 }, 1890 file: function(elem){ 1891 return "file" === elem.type; 1892 }, 1893 password: function(elem){ 1894 return "password" === elem.type; 1895 }, 1896 submit: function(elem){ 1897 return "submit" === elem.type; 1898 }, 1899 image: function(elem){ 1900 return "image" === elem.type; 1901 }, 1902 reset: function(elem){ 1903 return "reset" === elem.type; 1904 }, 1905 button: function(elem){ 1906 return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON"; 1907 }, 1908 input: function(elem){ 1909 return /input|select|textarea|button/i.test(elem.nodeName); 1910 } 1911 }, 1912 setFilters: { 1913 first: function(elem, i){ 1914 return i === 0; 1915 }, 1916 last: function(elem, i, match, array){ 1917 return i === array.length - 1; 1918 }, 1919 even: function(elem, i){ 1920 return i % 2 === 0; 1921 }, 1922 odd: function(elem, i){ 1923 return i % 2 === 1; 1924 }, 1925 lt: function(elem, i, match){ 1926 return i < match[3] - 0; 1927 }, 1928 gt: function(elem, i, match){ 1929 return i > match[3] - 0; 1930 }, 1931 nth: function(elem, i, match){ 1932 return match[3] - 0 == i; 1933 }, 1934 eq: function(elem, i, match){ 1935 return match[3] - 0 == i; 1936 } 1937 }, 1938 filter: { 1939 PSEUDO: function(elem, match, i, array){ 1940 var name = match[1], filter = Expr.filters[ name ]; 1941 1942 if ( filter ) { 1943 return filter( elem, i, match, array ); 1944 } else if ( name === "contains" ) { 1945 return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0; 1946 } else if ( name === "not" ) { 1947 var not = match[3]; 1948 1949 for ( var i = 0, l = not.length; i < l; i++ ) { 1950 if ( not[i] === elem ) { 1951 return false; 1952 } 1953 } 1954 1955 return true; 1956 } 1957 }, 1958 CHILD: function(elem, match){ 1959 var type = match[1], node = elem; 1960 switch (type) { 1961 case 'only': 1962 case 'first': 1963 while (node = node.previousSibling) { 1964 if ( node.nodeType === 1 ) return false; 1965 } 1966 if ( type == 'first') return true; 1967 node = elem; 1968 case 'last': 1969 while (node = node.nextSibling) { 1970 if ( node.nodeType === 1 ) return false; 1971 } 1972 return true; 1973 case 'nth': 1974 var first = match[2], last = match[3]; 1975 1976 if ( first == 1 && last == 0 ) { 1977 return true; 1978 } 1979 1980 var doneName = match[0], 1981 parent = elem.parentNode; 1982 1983 if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { 1984 var count = 0; 1985 for ( node = parent.firstChild; node; node = node.nextSibling ) { 1986 if ( node.nodeType === 1 ) { 1987 node.nodeIndex = ++count; 1988 } 1989 } 1990 parent.sizcache = doneName; 1991 } 1992 1993 var diff = elem.nodeIndex - last; 1994 if ( first == 0 ) { 1995 return diff == 0; 1996 } else { 1997 return ( diff % first == 0 && diff / first >= 0 ); 1998 } 1999 } 2000 }, 2001 ID: function(elem, match){ 2002 return elem.nodeType === 1 && elem.getAttribute("id") === match; 2003 }, 2004 TAG: function(elem, match){ 2005 return (match === "*" && elem.nodeType === 1) || elem.nodeName === match; 2006 }, 2007 CLASS: function(elem, match){ 2008 return (" " + (elem.className || elem.getAttribute("class")) + " ") 2009 .indexOf( match ) > -1; 2010 }, 2011 ATTR: function(elem, match){ 2012 var name = match[1], 2013 result = Expr.attrHandle[ name ] ? 2014 Expr.attrHandle[ name ]( elem ) : 2015 elem[ name ] != null ? 2016 elem[ name ] : 2017 elem.getAttribute( name ), 2018 value = result + "", 2019 type = match[2], 2020 check = match[4]; 2021 2022 return result == null ? 2023 type === "!=" : 2024 type === "=" ? 2025 value === check : 2026 type === "*=" ? 2027 value.indexOf(check) >= 0 : 2028 type === "~=" ? 2029 (" " + value + " ").indexOf(check) >= 0 : 2030 !check ? 2031 value && result !== false : 2032 type === "!=" ? 2033 value != check : 2034 type === "^=" ? 2035 value.indexOf(check) === 0 : 2036 type === "$=" ? 2037 value.substr(value.length - check.length) === check : 2038 type === "|=" ? 2039 value === check || value.substr(0, check.length + 1) === check + "-" : 2040 false; 2041 }, 2042 POS: function(elem, match, i, array){ 2043 var name = match[2], filter = Expr.setFilters[ name ]; 2044 2045 if ( filter ) { 2046 return filter( elem, i, match, array ); 2047 } 2048 } 2049 } 2050 }; 2051 2052 var origPOS = Expr.match.POS; 2053 2054 for ( var type in Expr.match ) { 2055 Expr.match[ type ] = RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source ); 2056 } 2057 2058 var makeArray = function(array, results) { 2059 array = Array.prototype.slice.call( array ); 2060 2061 if ( results ) { 2062 results.push.apply( results, array ); 2063 return results; 2064 } 2065 2066 return array; 2067 }; 2068 2069 // Perform a simple check to determine if the browser is capable of 2070 // converting a NodeList to an array using builtin methods. 2071 try { 2072 Array.prototype.slice.call( document.documentElement.childNodes ); 2073 2074 // Provide a fallback method if it does not work 2075 } catch(e){ 2076 makeArray = function(array, results) { 2077 var ret = results || []; 2078 2079 if ( toString.call(array) === "[object Array]" ) { 2080 Array.prototype.push.apply( ret, array ); 2081 } else { 2082 if ( typeof array.length === "number" ) { 2083 for ( var i = 0, l = array.length; i < l; i++ ) { 2084 ret.push( array[i] ); 2085 } 2086 } else { 2087 for ( var i = 0; array[i]; i++ ) { 2088 ret.push( array[i] ); 2089 } 2090 } 2091 } 2092 2093 return ret; 2094 }; 2095 } 2096 2097 var sortOrder; 2098 2099 if ( document.documentElement.compareDocumentPosition ) { 2100 sortOrder = function( a, b ) { 2101 var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1; 2102 if ( ret === 0 ) { 2103 hasDuplicate = true; 2104 } 2105 return ret; 2106 }; 2107 } else if ( "sourceIndex" in document.documentElement ) { 2108 sortOrder = function( a, b ) { 2109 var ret = a.sourceIndex - b.sourceIndex; 2110 if ( ret === 0 ) { 2111 hasDuplicate = true; 2112 } 2113 return ret; 2114 }; 2115 } else if ( document.createRange ) { 2116 sortOrder = function( a, b ) { 2117 var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange(); 2118 aRange.selectNode(a); 2119 aRange.collapse(true); 2120 bRange.selectNode(b); 2121 bRange.collapse(true); 2122 var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange); 2123 if ( ret === 0 ) { 2124 hasDuplicate = true; 2125 } 2126 return ret; 2127 }; 2128 } 2129 2130 // Check to see if the browser returns elements by name when 2131 // querying by getElementById (and provide a workaround) 2132 (function(){ 2133 // We're going to inject a fake input element with a specified name 2134 var form = document.createElement("form"), 2135 id = "script" + (new Date).getTime(); 2136 form.innerHTML = "<input name='" + id + "'/>"; 2137 2138 // Inject it into the root element, check its status, and remove it quickly 2139 var root = document.documentElement; 2140 root.insertBefore( form, root.firstChild ); 2141 2142 // The workaround has to do additional checks after a getElementById 2143 // Which slows things down for other browsers (hence the branching) 2144 if ( !!document.getElementById( id ) ) { 2145 Expr.find.ID = function(match, context, isXML){ 2146 if ( typeof context.getElementById !== "undefined" && !isXML ) { 2147 var m = context.getElementById(match[1]); 2148 return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : []; 2149 } 2150 }; 2151 2152 Expr.filter.ID = function(elem, match){ 2153 var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); 2154 return elem.nodeType === 1 && node && node.nodeValue === match; 2155 }; 2156 } 2157 2158 root.removeChild( form ); 2159 })(); 2160 2161 (function(){ 2162 // Check to see if the browser returns only elements 2163 // when doing getElementsByTagName("*") 2164 2165 // Create a fake element 2166 var div = document.createElement("div"); 2167 div.appendChild( document.createComment("") ); 2168 2169 // Make sure no comments are found 2170 if ( div.getElementsByTagName("*").length > 0 ) { 2171 Expr.find.TAG = function(match, context){ 2172 var results = context.getElementsByTagName(match[1]); 2173 2174 // Filter out possible comments 2175 if ( match[1] === "*" ) { 2176 var tmp = []; 2177 2178 for ( var i = 0; results[i]; i++ ) { 2179 if ( results[i].nodeType === 1 ) { 2180 tmp.push( results[i] ); 2181 } 2182 } 2183 2184 results = tmp; 2185 } 2186 2187 return results; 2188 }; 2189 } 2190 2191 // Check to see if an attribute returns normalized href attributes 2192 div.innerHTML = "<a href='#'></a>"; 2193 if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && 2194 div.firstChild.getAttribute("href") !== "#" ) { 2195 Expr.attrHandle.href = function(elem){ 2196 return elem.getAttribute("href", 2); 2197 }; 2198 } 2199 })(); 2200 2201 if ( document.querySelectorAll ) (function(){ 2202 var oldSizzle = Sizzle, div = document.createElement("div"); 2203 div.innerHTML = "<p class='TEST'></p>"; 2204 2205 // Safari can't handle uppercase or unicode characters when 2206 // in quirks mode. 2207 if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { 2208 return; 2209 } 2210 2211 Sizzle = function(query, context, extra, seed){ 2212 context = context || document; 2213 2214 // Only use querySelectorAll on non-XML documents 2215 // (ID selectors don't work in non-HTML documents) 2216 if ( !seed && context.nodeType === 9 && !isXML(context) ) { 2217 try { 2218 return makeArray( context.querySelectorAll(query), extra ); 2219 } catch(e){} 2220 } 2221 2222 return oldSizzle(query, context, extra, seed); 2223 }; 2224 2225 Sizzle.find = oldSizzle.find; 2226 Sizzle.filter = oldSizzle.filter; 2227 Sizzle.selectors = oldSizzle.selectors; 2228 Sizzle.matches = oldSizzle.matches; 2229 })(); 2230 2231 if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) (function(){ 2232 var div = document.createElement("div"); 2233 div.innerHTML = "<div class='test e'></div><div class='test'></div>"; 2234 2235 // Opera can't find a second classname (in 9.6) 2236 if ( div.getElementsByClassName("e").length === 0 ) 2237 return; 2238 2239 // Safari caches class attributes, doesn't catch changes (in 3.2) 2240 div.lastChild.className = "e"; 2241 2242 if ( div.getElementsByClassName("e").length === 1 ) 2243 return; 2244 2245 Expr.order.splice(1, 0, "CLASS"); 2246 Expr.find.CLASS = function(match, context, isXML) { 2247 if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { 2248 return context.getElementsByClassName(match[1]); 2249 } 2250 }; 2251 })(); 2252 2253 function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { 2254 var sibDir = dir == "previousSibling" && !isXML; 2255 for ( var i = 0, l = checkSet.length; i < l; i++ ) { 2256 var elem = checkSet[i]; 2257 if ( elem ) { 2258 if ( sibDir && elem.nodeType === 1 ){ 2259 elem.sizcache = doneName; 2260 elem.sizset = i; 2261 } 2262 elem = elem[dir]; 2263 var match = false; 2264 2265 while ( elem ) { 2266 if ( elem.sizcache === doneName ) { 2267 match = checkSet[elem.sizset]; 2268 break; 2269 } 2270 2271 if ( elem.nodeType === 1 && !isXML ){ 2272 elem.sizcache = doneName; 2273 elem.sizset = i; 2274 } 2275 2276 if ( elem.nodeName === cur ) { 2277 match = elem; 2278 break; 2279 } 2280 2281 elem = elem[dir]; 2282 } 2283 2284 checkSet[i] = match; 2285 } 2286 } 2287 } 2288 2289 function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { 2290 var sibDir = dir == "previousSibling" && !isXML; 2291 for ( var i = 0, l = checkSet.length; i < l; i++ ) { 2292 var elem = checkSet[i]; 2293 if ( elem ) { 2294 if ( sibDir && elem.nodeType === 1 ) { 2295 elem.sizcache = doneName; 2296 elem.sizset = i; 2297 } 2298 elem = elem[dir]; 2299 var match = false; 2300 2301 while ( elem ) { 2302 if ( elem.sizcache === doneName ) { 2303 match = checkSet[elem.sizset]; 2304 break; 2305 } 2306 2307 if ( elem.nodeType === 1 ) { 2308 if ( !isXML ) { 2309 elem.sizcache = doneName; 2310 elem.sizset = i; 2311 } 2312 if ( typeof cur !== "string" ) { 2313 if ( elem === cur ) { 2314 match = true; 2315 break; 2316 } 2317 2318 } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { 2319 match = elem; 2320 break; 2321 } 2322 } 2323 2324 elem = elem[dir]; 2325 } 2326 2327 checkSet[i] = match; 2328 } 2329 } 2330 } 2331 2332 var contains = document.compareDocumentPosition ? function(a, b){ 2333 return a.compareDocumentPosition(b) & 16; 2334 } : function(a, b){ 2335 return a !== b && (a.contains ? a.contains(b) : true); 2336 }; 2337 2338 var isXML = function(elem){ 2339 return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" || 2340 !!elem.ownerDocument && isXML( elem.ownerDocument ); 2341 }; 2342 2343 var posProcess = function(selector, context){ 2344 var tmpSet = [], later = "", match, 2345 root = context.nodeType ? [context] : context; 2346 2347 // Position selectors must be done after the filter 2348 // And so must :not(positional) so we move all PSEUDOs to the end 2349 while ( (match = Expr.match.PSEUDO.exec( selector )) ) { 2350 later += match[0]; 2351 selector = selector.replace( Expr.match.PSEUDO, "" ); 2352 } 2353 2354 selector = Expr.relative[selector] ? selector + "*" : selector; 2355 2356 for ( var i = 0, l = root.length; i < l; i++ ) { 2357 Sizzle( selector, root[i], tmpSet ); 2358 } 2359 2360 return Sizzle.filter( later, tmpSet ); 2361 }; 2362 2363 // EXPOSE 2364 jQuery.find = Sizzle; 2365 jQuery.filter = Sizzle.filter; 2366 jQuery.expr = Sizzle.selectors; 2367 jQuery.expr[":"] = jQuery.expr.filters; 2368 2369 Sizzle.selectors.filters.hidden = function(elem){ 2370 return elem.offsetWidth === 0 || elem.offsetHeight === 0; 2371 }; 2372 2373 Sizzle.selectors.filters.visible = function(elem){ 2374 return elem.offsetWidth > 0 || elem.offsetHeight > 0; 2375 }; 2376 2377 Sizzle.selectors.filters.animated = function(elem){ 2378 return jQuery.grep(jQuery.timers, function(fn){ 2379 return elem === fn.elem; 2380 }).length; 2381 }; 2382 2383 jQuery.multiFilter = function( expr, elems, not ) { 2384 if ( not ) { 2385 expr = ":not(" + expr + ")"; 2386 } 2387 2388 return Sizzle.matches(expr, elems); 2389 }; 2390 2391 jQuery.dir = function( elem, dir ){ 2392 var matched = [], cur = elem[dir]; 2393 while ( cur && cur != document ) { 2394 if ( cur.nodeType == 1 ) 2395 matched.push( cur ); 2396 cur = cur[dir]; 2397 } 2398 return matched; 2399 }; 2400 2401 jQuery.nth = function(cur, result, dir, elem){ 2402 result = result || 1; 2403 var num = 0; 2404 2405 for ( ; cur; cur = cur[dir] ) 2406 if ( cur.nodeType == 1 && ++num == result ) 2407 break; 2408 2409 return cur; 2410 }; 2411 2412 jQuery.sibling = function(n, elem){ 2413 var r = []; 2414 2415 for ( ; n; n = n.nextSibling ) { 2416 if ( n.nodeType == 1 && n != elem ) 2417 r.push( n ); 2418 } 2419 2420 return r; 2421 }; 2422 2423 return; 2424 2425 window.Sizzle = Sizzle; 2426 2427 })(); 2428 /* 2429 * A number of helper functions used for managing events. 2430 * Many of the ideas behind this code originated from 2431 * Dean Edwards' addEvent library. 2432 */ 2433 jQuery.event = { 2434 2435 // Bind an event to an element 2436 // Original by Dean Edwards 2437 add: function(elem, types, handler, data) { 2438 if ( elem.nodeType == 3 || elem.nodeType == 8 ) 2439 return; 2440 2441 // For whatever reason, IE has trouble passing the window object 2442 // around, causing it to be cloned in the process 2443 if ( elem.setInterval && elem != window ) 2444 elem = window; 2445 2446 // Make sure that the function being executed has a unique ID 2447 if ( !handler.guid ) 2448 handler.guid = this.guid++; 2449 2450 // if data is passed, bind to handler 2451 if ( data !== undefined ) { 2452 // Create temporary function pointer to original handler 2453 var fn = handler; 2454 2455 // Create unique handler function, wrapped around original handler 2456 handler = this.proxy( fn ); 2457 2458 // Store data in unique handler 2459 handler.data = data; 2460 } 2461 2462 // Init the element's event structure 2463 var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}), 2464 handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){ 2465 // Handle the second event of a trigger and when 2466 // an event is called after a page has unloaded 2467 return typeof jQuery !== "undefined" && !jQuery.event.triggered ? 2468 jQuery.event.handle.apply(arguments.callee.elem, arguments) : 2469 undefined; 2470 }); 2471 // Add elem as a property of the handle function 2472 // This is to prevent a memory leak with non-native 2473 // event in IE. 2474 handle.elem = elem; 2475 2476 // Handle multiple events separated by a space 2477 // jQuery(...).bind("mouseover mouseout", fn); 2478 jQuery.each(types.split(/\s+/), function(index, type) { 2479 // Namespaced event handlers 2480 var namespaces = type.split("."); 2481 type = namespaces.shift(); 2482 handler.type = namespaces.slice().sort().join("."); 2483 2484 // Get the current list of functions bound to this event 2485 var handlers = events[type]; 2486 2487 if ( jQuery.event.specialAll[type] ) 2488 jQuery.event.specialAll[type].setup.call(elem, data, namespaces); 2489 2490 // Init the event handler queue 2491 if (!handlers) { 2492 handlers = events[type] = {}; 2493 2494 // Check for a special event handler 2495 // Only use addEventListener/attachEvent if the special 2496 // events handler returns false 2497 if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem, data, namespaces) === false ) { 2498 // Bind the global event handler to the element 2499 if (elem.addEventListener) 2500 elem.addEventListener(type, handle, false); 2501 else if (elem.attachEvent) 2502 elem.attachEvent("on" + type, handle); 2503 } 2504 } 2505 2506 // Add the function to the element's handler list 2507 handlers[handler.guid] = handler; 2508 2509 // Keep track of which events have been used, for global triggering 2510 jQuery.event.global[type] = true; 2511 }); 2512 2513 // Nullify elem to prevent memory leaks in IE 2514 elem = null; 2515 }, 2516 2517 guid: 1, 2518 global: {}, 2519 2520 // Detach an event or set of events from an element 2521 remove: function(elem, types, handler) { 2522 // don't do events on text and comment nodes 2523 if ( elem.nodeType == 3 || elem.nodeType == 8 ) 2524 return; 2525 2526 var events = jQuery.data(elem, "events"), ret, index; 2527 2528 if ( events ) { 2529 // Unbind all events for the element 2530 if ( types === undefined || (typeof types === "string" && types.charAt(0) == ".") ) 2531 for ( var type in events ) 2532 this.remove( elem, type + (types || "") ); 2533 else { 2534 // types is actually an event object here 2535 if ( types.type ) { 2536 handler = types.handler; 2537 types = types.type; 2538 } 2539 2540 // Handle multiple events seperated by a space 2541 // jQuery(...).unbind("mouseover mouseout", fn); 2542 jQuery.each(types.split(/\s+/), function(index, type){ 2543 // Namespaced event handlers 2544 var namespaces = type.split("."); 2545 type = namespaces.shift(); 2546 var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)"); 2547 2548 if ( events[type] ) { 2549 // remove the given handler for the given type 2550 if ( handler ) 2551 delete events[type][handler.guid]; 2552 2553 // remove all handlers for the given type 2554 else 2555 for ( var handle in events[type] ) 2556 // Handle the removal of namespaced events 2557 if ( namespace.test(events[type][handle].type) ) 2558 delete events[type][handle]; 2559 2560 if ( jQuery.event.specialAll[type] ) 2561 jQuery.event.specialAll[type].teardown.call(elem, namespaces); 2562 2563 // remove generic event handler if no more handlers exist 2564 for ( ret in events[type] ) break; 2565 if ( !ret ) { 2566 if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem, namespaces) === false ) { 2567 if (elem.removeEventListener) 2568 elem.removeEventListener(type, jQuery.data(elem, "handle"), false); 2569 else if (elem.detachEvent) 2570 elem.detachEvent("on" + type, jQuery.data(elem, "handle")); 2571 } 2572 ret = null; 2573 delete events[type]; 2574 } 2575 } 2576 }); 2577 } 2578 2579 // Remove the expando if it's no longer used 2580 for ( ret in events ) break; 2581 if ( !ret ) { 2582 var handle = jQuery.data( elem, "handle" ); 2583 if ( handle ) handle.elem = null; 2584 jQuery.removeData( elem, "events" ); 2585 jQuery.removeData( elem, "handle" ); 2586 } 2587 } 2588 }, 2589 2590 // bubbling is internal 2591 trigger: function( event, data, elem, bubbling ) { 2592 // Event object or event type 2593 var type = event.type || event; 2594 2595 if( !bubbling ){ 2596 event = typeof event === "object" ? 2597 // jQuery.Event object 2598 event[expando] ? event : 2599 // Object literal 2600 jQuery.extend( jQuery.Event(type), event ) : 2601 // Just the event type (string) 2602 jQuery.Event(type); 2603 2604 if ( type.indexOf("!") >= 0 ) { 2605 event.type = type = type.slice(0, -1); 2606 event.exclusive = true; 2607 } 2608 2609 // Handle a global trigger 2610 if ( !elem ) { 2611 // Don't bubble custom events when global (to avoid too much overhead) 2612 event.stopPropagation(); 2613 // Only trigger if we've ever bound an event for it 2614 if ( this.global[type] ) 2615 jQuery.each( jQuery.cache, function(){ 2616 if ( this.events && this.events[type] ) 2617 jQuery.event.trigger( event, data, this.handle.elem ); 2618 }); 2619 } 2620 2621 // Handle triggering a single element 2622 2623 // don't do events on text and comment nodes 2624 if ( !elem || elem.nodeType == 3 || elem.nodeType == 8 ) 2625 return undefined; 2626 2627 // Clean up in case it is reused 2628 event.result = undefined; 2629 event.target = elem; 2630 2631 // Clone the incoming data, if any 2632 data = jQuery.makeArray(data); 2633 data.unshift( event ); 2634 } 2635 2636 event.currentTarget = elem; 2637 2638 // Trigger the event, it is assumed that "handle" is a function 2639 var handle = jQuery.data(elem, "handle"); 2640 if ( handle ) 2641 handle.apply( elem, data ); 2642 2643 // Handle triggering native .onfoo handlers (and on links since we don't call .click() for links) 2644 if ( (!elem[type] || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false ) 2645 event.result = false; 2646 2647 // Trigger the native events (except for clicks on links) 2648 if ( !bubbling && elem[type] && !event.isDefaultPrevented() && !(jQuery.nodeName(elem, 'a') && type == "click") ) { 2649 this.triggered = true; 2650 try { 2651 elem[ type ](); 2652 // prevent IE from throwing an error for some hidden elements 2653 } catch (e) {} 2654 } 2655 2656 this.triggered = false; 2657 2658 if ( !event.isPropagationStopped() ) { 2659 var parent = elem.parentNode || elem.ownerDocument; 2660 if ( parent ) 2661 jQuery.event.trigger(event, data, parent, true); 2662 } 2663 }, 2664 2665 handle: function(event) { 2666 // returned undefined or false 2667 var all, handlers; 2668 2669 event = arguments[0] = jQuery.event.fix( event || window.event ); 2670 event.currentTarget = this; 2671 2672 // Namespaced event handlers 2673 var namespaces = event.type.split("."); 2674 event.type = namespaces.shift(); 2675 2676 // Cache this now, all = true means, any handler 2677 all = !namespaces.length && !event.exclusive; 2678 2679 var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)"); 2680 2681 handlers = ( jQuery.data(this, "events") || {} )[event.type]; 2682 2683 for ( var j in handlers ) { 2684 var handler = handlers[j]; 2685 2686 // Filter the functions by class 2687 if ( all || namespace.test(handler.type) ) { 2688 // Pass in a reference to the handler function itself 2689 // So that we can later remove it 2690 event.handler = handler; 2691 event.data = handler.data; 2692 2693 var ret = handler.apply(this, arguments); 2694 2695 if( ret !== undefined ){ 2696 event.result = ret; 2697 if ( ret === false ) { 2698 event.preventDefault(); 2699 event.stopPropagation(); 2700 } 2701 } 2702 2703 if( event.isImmediatePropagationStopped() ) 2704 break; 2705 2706 } 2707 } 2708 }, 2709 2710 props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "), 2711 2712 fix: function(event) { 2713 if ( event[expando] ) 2714 return event; 2715 2716 // store a copy of the original event object 2717 // and "clone" to set read-only properties 2718 var originalEvent = event; 2719 event = jQuery.Event( originalEvent ); 2720 2721 for ( var i = this.props.length, prop; i; ){ 2722 prop = this.props[ --i ]; 2723 event[ prop ] = originalEvent[ prop ]; 2724 } 2725 2726 // Fix target property, if necessary 2727 if ( !event.target ) 2728 event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either 2729 2730 // check if target is a textnode (safari) 2731 if ( event.target.nodeType == 3 ) 2732 event.target = event.target.parentNode; 2733 2734 // Add relatedTarget, if necessary 2735 if ( !event.relatedTarget && event.fromElement ) 2736 event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement; 2737 2738 // Calculate pageX/Y if missing and clientX/Y available 2739 if ( event.pageX == null && event.clientX != null ) { 2740 var doc = document.documentElement, body = document.body; 2741 event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0); 2742 event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0); 2743 } 2744 2745 // Add which for key events 2746 if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) ) 2747 event.which = event.charCode || event.keyCode; 2748 2749 // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) 2750 if ( !event.metaKey && event.ctrlKey ) 2751 event.metaKey = event.ctrlKey; 2752 2753 // Add which for click: 1 == left; 2 == middle; 3 == right 2754 // Note: button is not normalized, so don't use it 2755 if ( !event.which && event.button ) 2756 event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); 2757 2758 return event; 2759 }, 2760 2761 proxy: function( fn, proxy ){ 2762 proxy = proxy || function(){ return fn.apply(this, arguments); }; 2763 // Set the guid of unique handler to the same of original handler, so it can be removed 2764 proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++; 2765 // So proxy can be declared as an argument 2766 return proxy; 2767 }, 2768 2769 special: { 2770 ready: { 2771 // Make sure the ready event is setup 2772 setup: bindReady, 2773 teardown: function() {} 2774 } 2775 }, 2776 2777 specialAll: { 2778 live: { 2779 setup: function( selector, namespaces ){ 2780 jQuery.event.add( this, namespaces[0], liveHandler ); 2781 }, 2782 teardown: function( namespaces ){ 2783 if ( namespaces.length ) { 2784 var remove = 0, name = RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)"); 2785 2786 jQuery.each( (jQuery.data(this, "events").live || {}), function(){ 2787 if ( name.test(this.type) ) 2788 remove++; 2789 }); 2790 2791 if ( remove < 1 ) 2792 jQuery.event.remove( this, namespaces[0], liveHandler ); 2793 } 2794 } 2795 } 2796 } 2797 }; 2798 2799 jQuery.Event = function( src ){ 2800 // Allow instantiation without the 'new' keyword 2801 if( !this.preventDefault ) 2802 return new jQuery.Event(src); 2803 2804 // Event object 2805 if( src && src.type ){ 2806 this.originalEvent = src; 2807 this.type = src.type; 2808 // Event type 2809 }else 2810 this.type = src; 2811 2812 // timeStamp is buggy for some events on Firefox(#3843) 2813 // So we won't rely on the native value 2814 this.timeStamp = now(); 2815 2816 // Mark it as fixed 2817 this[expando] = true; 2818 }; 2819 2820 function returnFalse(){ 2821 return false; 2822 } 2823 function returnTrue(){ 2824 return true; 2825 } 2826 2827 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding 2828 // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html 2829 jQuery.Event.prototype = { 2830 preventDefault: function() { 2831 this.isDefaultPrevented = returnTrue; 2832 2833 var e = this.originalEvent; 2834 if( !e ) 2835 return; 2836 // if preventDefault exists run it on the original event 2837 if (e.preventDefault) 2838 e.preventDefault(); 2839 // otherwise set the returnValue property of the original event to false (IE) 2840 e.returnValue = false; 2841 }, 2842 stopPropagation: function() { 2843 this.isPropagationStopped = returnTrue; 2844 2845 var e = this.originalEvent; 2846 if( !e ) 2847 return; 2848 // if stopPropagation exists run it on the original event 2849 if (e.stopPropagation) 2850 e.stopPropagation(); 2851 // otherwise set the cancelBubble property of the original event to true (IE) 2852 e.cancelBubble = true; 2853 }, 2854 stopImmediatePropagation:function(){ 2855 this.isImmediatePropagationStopped = returnTrue; 2856 this.stopPropagation(); 2857 }, 2858 isDefaultPrevented: returnFalse, 2859 isPropagationStopped: returnFalse, 2860 isImmediatePropagationStopped: returnFalse 2861 }; 2862 // Checks if an event happened on an element within another element 2863 // Used in jQuery.event.special.mouseenter and mouseleave handlers 2864 var withinElement = function(event) { 2865 // Check if mouse(over|out) are still within the same parent element 2866 var parent = event.relatedTarget; 2867 // Traverse up the tree 2868 while ( parent && parent != this ) 2869 try { parent = parent.parentNode; } 2870 catch(e) { parent = this; } 2871 2872 if( parent != this ){ 2873 // set the correct event type 2874 event.type = event.data; 2875 // handle event if we actually just moused on to a non sub-element 2876 jQuery.event.handle.apply( this, arguments ); 2877 } 2878 }; 2879 2880 jQuery.each({ 2881 mouseover: 'mouseenter', 2882 mouseout: 'mouseleave' 2883 }, function( orig, fix ){ 2884 jQuery.event.special[ fix ] = { 2885 setup: function(){ 2886 jQuery.event.add( this, orig, withinElement, fix ); 2887 }, 2888 teardown: function(){ 2889 jQuery.event.remove( this, orig, withinElement ); 2890 } 2891 }; 2892 }); 2893 2894 jQuery.fn.extend({ 2895 bind: function( type, data, fn ) { 2896 return type == "unload" ? this.one(type, data, fn) : this.each(function(){ 2897 jQuery.event.add( this, type, fn || data, fn && data ); 2898 }); 2899 }, 2900 2901 one: function( type, data, fn ) { 2902 var one = jQuery.event.proxy( fn || data, function(event) { 2903 jQuery(this).unbind(event, one); 2904 return (fn || data).apply( this, arguments ); 2905 }); 2906 return this.each(function(){ 2907 jQuery.event.add( this, type, one, fn && data); 2908 }); 2909 }, 2910 2911 unbind: function( type, fn ) { 2912 return this.each(function(){ 2913 jQuery.event.remove( this, type, fn ); 2914 }); 2915 }, 2916 2917 trigger: function( type, data ) { 2918 return this.each(function(){ 2919 jQuery.event.trigger( type, data, this ); 2920 }); 2921 }, 2922 2923 triggerHandler: function( type, data ) { 2924 if( this[0] ){ 2925 var event = jQuery.Event(type); 2926 event.preventDefault(); 2927 event.stopPropagation(); 2928 jQuery.event.trigger( event, data, this[0] ); 2929 return event.result; 2930 } 2931 }, 2932 2933 toggle: function( fn ) { 2934 // Save reference to arguments for access in closure 2935 var args = arguments, i = 1; 2936 2937 // link all the functions, so any of them can unbind this click handler 2938 while( i < args.length ) 2939 jQuery.event.proxy( fn, args[i++] ); 2940 2941 return this.click( jQuery.event.proxy( fn, function(event) { 2942 // Figure out which function to execute 2943 this.lastToggle = ( this.lastToggle || 0 ) % i; 2944 2945 // Make sure that clicks stop 2946 event.preventDefault(); 2947 2948 // and execute the function 2949 return args[ this.lastToggle++ ].apply( this, arguments ) || false; 2950 })); 2951 }, 2952 2953 hover: function(fnOver, fnOut) { 2954 return this.mouseenter(fnOver).mouseleave(fnOut); 2955 }, 2956 2957 ready: function(fn) { 2958 // Attach the listeners 2959 bindReady(); 2960 2961 // If the DOM is already ready 2962 if ( jQuery.isReady ) 2963 // Execute the function immediately 2964 fn.call( document, jQuery ); 2965 2966 // Otherwise, remember the function for later 2967 else 2968 // Add the function to the wait list 2969 jQuery.readyList.push( fn ); 2970 2971 return this; 2972 }, 2973 2974 live: function( type, fn ){ 2975 var proxy = jQuery.event.proxy( fn ); 2976 proxy.guid += this.selector + type; 2977 2978 jQuery(document).bind( liveConvert(type, this.selector), this.selector, proxy ); 2979 2980 return this; 2981 }, 2982 2983 die: function( type, fn ){ 2984 jQuery(document).unbind( liveConvert(type, this.selector), fn ? { guid: fn.guid + this.selector + type } : null ); 2985 return this; 2986 } 2987 }); 2988 2989 function liveHandler( event ){ 2990 var check = RegExp("(^|\\.)" + event.type + "(\\.|$)"), 2991 stop = true, 2992 elems = []; 2993 2994 jQuery.each(jQuery.data(this, "events").live || [], function(i, fn){ 2995 if ( check.test(fn.type) ) { 2996 var elem = jQuery(event.target).closest(fn.data)[0]; 2997 if ( elem ) 2998 elems.push({ elem: elem, fn: fn }); 2999 } 3000 }); 3001 3002 elems.sort(function(a,b) { 3003 return jQuery.data(a.elem, "closest") - jQuery.data(b.elem, "closest"); 3004 }); 3005 3006 jQuery.each(elems, function(){ 3007 if ( this.fn.call(this.elem, event, this.fn.data) === false ) 3008 return (stop = false); 3009 }); 3010 3011 return stop; 3012 } 3013 3014 function liveConvert(type, selector){ 3015 return ["live", type, selector.replace(/\./g, "`").replace(/ /g, "|")].join("."); 3016 } 3017 3018 jQuery.extend({ 3019 isReady: false, 3020 readyList: [], 3021 // Handle when the DOM is ready 3022 ready: function() { 3023 // Make sure that the DOM is not already loaded 3024 if ( !jQuery.isReady ) { 3025 // Remember that the DOM is ready 3026 jQuery.isReady = true; 3027 3028 // If there are functions bound, to execute 3029 if ( jQuery.readyList ) { 3030 // Execute all of them 3031 jQuery.each( jQuery.readyList, function(){ 3032 this.call( document, jQuery ); 3033 }); 3034 3035 // Reset the list of functions 3036 jQuery.readyList = null; 3037 } 3038 3039 // Trigger any bound ready events 3040 jQuery(document).triggerHandler("ready"); 3041 } 3042 } 3043 }); 3044 3045 var readyBound = false; 3046 3047 function bindReady(){ 3048 if ( readyBound ) return; 3049 readyBound = true; 3050 3051 // Mozilla, Opera and webkit nightlies currently support this event 3052 if ( document.addEventListener ) { 3053 // Use the handy event callback 3054 document.addEventListener( "DOMContentLoaded", function(){ 3055 document.removeEventListener( "DOMContentLoaded", arguments.callee, false ); 3056 jQuery.ready(); 3057 }, false ); 3058 3059 // If IE event model is used 3060 } else if ( document.attachEvent ) { 3061 // ensure firing before onload, 3062 // maybe late but safe also for iframes 3063 document.attachEvent("onreadystatechange", function(){ 3064 if ( document.readyState === "complete" ) { 3065 document.detachEvent( "onreadystatechange", arguments.callee ); 3066 jQuery.ready(); 3067 } 3068 }); 3069 3070 // If IE and not an iframe 3071 // continually check to see if the document is ready 3072 if ( document.documentElement.doScroll && window == window.top ) (function(){ 3073 if ( jQuery.isReady ) return; 3074 3075 try { 3076 // If IE is used, use the trick by Diego Perini 3077 // http://javascript.nwbox.com/IEContentLoaded/ 3078 document.documentElement.doScroll("left"); 3079 } catch( error ) { 3080 setTimeout( arguments.callee, 0 ); 3081 return; 3082 } 3083 3084 // and execute any waiting functions 3085 jQuery.ready(); 3086 })(); 3087 } 3088 3089 // A fallback to window.onload, that will always work 3090 jQuery.event.add( window, "load", jQuery.ready ); 3091 } 3092 3093 jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," + 3094 "mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave," + 3095 "change,select,submit,keydown,keypress,keyup,error").split(","), function(i, name){ 3096 3097 // Handle event binding 3098 jQuery.fn[name] = function(fn){ 3099 return fn ? this.bind(name, fn) : this.trigger(name); 3100 }; 3101 }); 3102 3103 // Prevent memory leaks in IE 3104 // And prevent errors on refresh with events like mouseover in other browsers 3105 // Window isn't included so as not to unbind existing unload events 3106 jQuery( window ).bind( 'unload', function(){ 3107 for ( var id in jQuery.cache ) 3108 // Skip the window 3109 if ( id != 1 && jQuery.cache[ id ].handle ) 3110 jQuery.event.remove( jQuery.cache[ id ].handle.elem ); 3111 }); 3112 (function(){ 3113 3114 jQuery.support = {}; 3115 3116 var root = document.documentElement, 3117 script = document.createElement("script"), 3118 div = document.createElement("div"), 3119 id = "script" + (new Date).getTime(); 3120 3121 div.style.display = "none"; 3122 div.innerHTML = ' <link/><table></table><a href="/a" style="color:red;float:left;opacity:.5;">a</a><select><option>text</option></select><object><param/></object>'; 3123 3124 var all = div.getElementsByTagName("*"), 3125 a = div.getElementsByTagName("a")[0]; 3126 3127 // Can't get basic test support 3128 if ( !all || !all.length || !a ) { 3129 return; 3130 } 3131 3132 jQuery.support = { 3133 // IE strips leading whitespace when .innerHTML is used 3134 leadingWhitespace: div.firstChild.nodeType == 3, 3135 3136 // Make sure that tbody elements aren't automatically inserted 3137 // IE will insert them into empty tables 3138 tbody: !div.getElementsByTagName("tbody").length, 3139 3140 // Make sure that you can get all elements in an <object> element 3141 // IE 7 always returns no results 3142 objectAll: !!div.getElementsByTagName("object")[0] 3143 .getElementsByTagName("*").length, 3144 3145 // Make sure that link elements get serialized correctly by innerHTML 3146 // This requires a wrapper element in IE 3147 htmlSerialize: !!div.getElementsByTagName("link").length, 3148 3149 // Get the style information from getAttribute 3150 // (IE uses .cssText insted) 3151 style: /red/.test( a.getAttribute("style") ), 3152 3153 // Make sure that URLs aren't manipulated 3154 // (IE normalizes it by default) 3155 hrefNormalized: a.getAttribute("href") === "/a", 3156 3157 // Make sure that element opacity exists 3158 // (IE uses filter instead) 3159 opacity: a.style.opacity === "0.5", 3160 3161 // Verify style float existence 3162 // (IE uses styleFloat instead of cssFloat) 3163 cssFloat: !!a.style.cssFloat, 3164 3165 // Will be defined later 3166 scriptEval: false, 3167 noCloneEvent: true, 3168 boxModel: null 3169 }; 3170 3171 script.type = "text/javascript"; 3172 try { 3173 script.appendChild( document.createTextNode( "window." + id + "=1;" ) ); 3174 } catch(e){} 3175 3176 root.insertBefore( script, root.firstChild ); 3177 3178 // Make sure that the execution of code works by injecting a script 3179 // tag with appendChild/createTextNode 3180 // (IE doesn't support this, fails, and uses .text instead) 3181 if ( window[ id ] ) { 3182 jQuery.support.scriptEval = true; 3183 delete window[ id ]; 3184 } 3185 3186 root.removeChild( script ); 3187 3188 if ( div.attachEvent && div.fireEvent ) { 3189 div.attachEvent("onclick", function(){ 3190 // Cloning a node shouldn't copy over any 3191 // bound event handlers (IE does this) 3192 jQuery.support.noCloneEvent = false; 3193 div.detachEvent("onclick", arguments.callee); 3194 }); 3195 div.cloneNode(true).fireEvent("onclick"); 3196 } 3197 3198 // Figure out if the W3C box model works as expected 3199 // document.body must exist before we can do this 3200 jQuery(function(){ 3201 var div = document.createElement("div"); 3202 div.style.width = div.style.paddingLeft = "1px"; 3203 3204 document.body.appendChild( div ); 3205 jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2; 3206 document.body.removeChild( div ).style.display = 'none'; 3207 }); 3208 })(); 3209 3210 var styleFloat = jQuery.support.cssFloat ? "cssFloat" : "styleFloat"; 3211 3212 jQuery.props = { 3213 "for": "htmlFor", 3214 "class": "className", 3215 "float": styleFloat, 3216 cssFloat: styleFloat, 3217 styleFloat: styleFloat, 3218 readonly: "readOnly", 3219 maxlength: "maxLength", 3220 cellspacing: "cellSpacing", 3221 rowspan: "rowSpan", 3222 tabindex: "tabIndex" 3223 }; 3224 jQuery.fn.extend({ 3225 // Keep a copy of the old load 3226 _load: jQuery.fn.load, 3227 3228 load: function( url, params, callback ) { 3229 if ( typeof url !== "string" ) 3230 return this._load( url ); 3231 3232 var off = url.indexOf(" "); 3233 if ( off >= 0 ) { 3234 var selector = url.slice(off, url.length); 3235 url = url.slice(0, off); 3236 } 3237 3238 // Default to a GET request 3239 var type = "GET"; 3240 3241 // If the second parameter was provided 3242 if ( params ) 3243 // If it's a function 3244 if ( jQuery.isFunction( params ) ) { 3245 // We assume that it's the callback 3246 callback = params; 3247 params = null; 3248 3249 // Otherwise, build a param string 3250 } else if( typeof params === "object" ) { 3251 params = jQuery.param( params ); 3252 type = "POST"; 3253 } 3254 3255 var self = this; 3256 3257 // Request the remote document 3258 jQuery.ajax({ 3259 url: url, 3260 type: type, 3261 dataType: "html", 3262 data: params, 3263 complete: function(res, status){ 3264 // If successful, inject the HTML into all the matched elements 3265 if ( status == "success" || status == "notmodified" ) 3266 // See if a selector was specified 3267 self.html( selector ? 3268 // Create a dummy div to hold the results 3269 jQuery("<div/>") 3270 // inject the contents of the document in, removing the scripts 3271 // to avoid any 'Permission Denied' errors in IE 3272 .append(res.responseText.replace(/<script(.|\s)*?\/script>/g, "")) 3273 3274 // Locate the specified elements 3275 .find(selector) : 3276 3277 // If not, just inject the full result 3278 res.responseText ); 3279 3280 if( callback ) 3281 self.each( callback, [res.responseText, status, res] ); 3282 } 3283 }); 3284 return this; 3285 }, 3286 3287 serialize: function() { 3288 return jQuery.param(this.serializeArray()); 3289 }, 3290 serializeArray: function() { 3291 return this.map(function(){ 3292 return this.elements ? jQuery.makeArray(this.elements) : this; 3293 }) 3294 .filter(function(){ 3295 return this.name && !this.disabled && 3296 (this.checked || /select|textarea/i.test(this.nodeName) || 3297 /text|hidden|password|search/i.test(this.type)); 3298 }) 3299 .map(function(i, elem){ 3300 var val = jQuery(this).val(); 3301 return val == null ? null : 3302 jQuery.isArray(val) ? 3303 jQuery.map( val, function(val, i){ 3304 return {name: elem.name, value: val}; 3305 }) : 3306 {name: elem.name, value: val}; 3307 }).get(); 3308 } 3309 }); 3310 3311 // Attach a bunch of functions for handling common AJAX events 3312 jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){ 3313 jQuery.fn[o] = function(f){ 3314 return this.bind(o, f); 3315 }; 3316 }); 3317 3318 var jsc = now(); 3319 3320 jQuery.extend({ 3321 3322 get: function( url, data, callback, type ) { 3323 // shift arguments if data argument was ommited 3324 if ( jQuery.isFunction( data ) ) { 3325 callback = data; 3326 data = null; 3327 } 3328 3329 return jQuery.ajax({ 3330 type: "GET", 3331 url: url, 3332 data: data, 3333 success: callback, 3334 dataType: type 3335 }); 3336 }, 3337 3338 getScript: function( url, callback ) { 3339 return jQuery.get(url, null, callback, "script"); 3340 }, 3341 3342 getJSON: function( url, data, callback ) { 3343 return jQuery.get(url, data, callback, "json"); 3344 }, 3345 3346 post: function( url, data, callback, type ) { 3347 if ( jQuery.isFunction( data ) ) { 3348 callback = data; 3349 data = {}; 3350 } 3351 3352 return jQuery.ajax({ 3353 type: "POST", 3354 url: url, 3355 data: data, 3356 success: callback, 3357 dataType: type 3358 }); 3359 }, 3360 3361 ajaxSetup: function( settings ) { 3362 jQuery.extend( jQuery.ajaxSettings, settings ); 3363 }, 3364 3365 ajaxSettings: { 3366 url: location.href, 3367 global: true, 3368 type: "GET", 3369 contentType: "application/x-www-form-urlencoded", 3370 processData: true, 3371 async: true, 3372 /* 3373 timeout: 0, 3374 data: null, 3375 username: null, 3376 password: null, 3377 */ 3378 // Create the request object; Microsoft failed to properly 3379 // implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available 3380 // This function can be overriden by calling jQuery.ajaxSetup 3381 xhr:function(){ 3382 return window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest(); 3383 }, 3384 accepts: { 3385 xml: "application/xml, text/xml", 3386 html: "text/html", 3387 script: "text/javascript, application/javascript", 3388 json: "application/json, text/javascript", 3389 text: "text/plain", 3390 _default: "*/*" 3391 } 3392 }, 3393 3394 // Last-Modified header cache for next request 3395 lastModified: {}, 3396 3397 ajax: function( s ) { 3398 // Extend the settings, but re-extend 's' so that it can be 3399 // checked again later (in the test suite, specifically) 3400 s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s)); 3401 3402 var jsonp, jsre = /=\?(&|$)/g, status, data, 3403 type = s.type.toUpperCase(); 3404 3405 // convert data if not already a string 3406 if ( s.data && s.processData && typeof s.data !== "string" ) 3407 s.data = jQuery.param(s.data); 3408 3409 // Handle JSONP Parameter Callbacks 3410 if ( s.dataType == "jsonp" ) { 3411 if ( type == "GET" ) { 3412 if ( !s.url.match(jsre) ) 3413 s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?"; 3414 } else if ( !s.data || !s.data.match(jsre) ) 3415 s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?"; 3416 s.dataType = "json"; 3417 } 3418 3419 // Build temporary JSONP function 3420 if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) { 3421 jsonp = "jsonp" + jsc++; 3422 3423 // Replace the =? sequence both in the query string and the data 3424 if ( s.data ) 3425 s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1"); 3426 s.url = s.url.replace(jsre, "=" + jsonp + "$1"); 3427 3428 // We need to make sure 3429 // that a JSONP style response is executed properly 3430 s.dataType = "script"; 3431 3432 // Handle JSONP-style loading 3433 window[ jsonp ] = function(tmp){ 3434 data = tmp; 3435 success(); 3436 complete(); 3437 // Garbage collect 3438 window[ jsonp ] = undefined; 3439 try{ delete window[ jsonp ]; } catch(e){} 3440 if ( head ) 3441 head.removeChild( script ); 3442 }; 3443 } 3444 3445 if ( s.dataType == "script" && s.cache == null ) 3446 s.cache = false; 3447 3448 if ( s.cache === false && type == "GET" ) { 3449 var ts = now(); 3450 // try replacing _= if it is there 3451 var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2"); 3452 // if nothing was replaced, add timestamp to the end 3453 s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : ""); 3454 } 3455 3456 // If data is available, append data to url for get requests 3457 if ( s.data && type == "GET" ) { 3458 s.url += (s.url.match(/\?/) ? "&" : "?") + s.data; 3459 3460 // IE likes to send both get and post data, prevent this 3461 s.data = null; 3462 } 3463 3464 // Watch for a new set of requests 3465 if ( s.global && ! jQuery.active++ ) 3466 jQuery.event.trigger( "ajaxStart" ); 3467 3468 // Matches an absolute URL, and saves the domain 3469 var parts = /^(\w+:)?\/\/([^\/?#]+)/.exec( s.url ); 3470 3471 // If we're requesting a remote document 3472 // and trying to load JSON or Script with a GET 3473 if ( s.dataType == "script" && type == "GET" && parts 3474 && ( parts[1] && parts[1] != location.protocol || parts[2] != location.host )){ 3475 3476 var head = document.getElementsByTagName("head")[0]; 3477 var script = document.createElement("script"); 3478 script.src = s.url; 3479 if (s.scriptCharset) 3480 script.charset = s.scriptCharset; 3481 3482 // Handle Script loading 3483 if ( !jsonp ) { 3484 var done = false; 3485 3486 // Attach handlers for all browsers 3487 script.onload = script.onreadystatechange = function(){ 3488 if ( !done && (!this.readyState || 3489 this.readyState == "loaded" || this.readyState == "complete") ) { 3490 done = true; 3491 success(); 3492 complete(); 3493 3494 // Handle memory leak in IE 3495 script.onload = script.onreadystatechange = null; 3496 head.removeChild( script ); 3497 } 3498 }; 3499 } 3500 3501 head.appendChild(script); 3502 3503 // We handle everything using the script element injection 3504 return undefined; 3505 } 3506 3507 var requestDone = false; 3508 3509 // Create the request object 3510 var xhr = s.xhr(); 3511 3512 // Open the socket 3513 // Passing null username, generates a login popup on Opera (#2865) 3514 if( s.username ) 3515 xhr.open(type, s.url, s.async, s.username, s.password); 3516 else 3517 xhr.open(type, s.url, s.async); 3518 3519 // Need an extra try/catch for cross domain requests in Firefox 3 3520 try { 3521 // Set the correct header, if data is being sent 3522 if ( s.data ) 3523 xhr.setRequestHeader("Content-Type", s.contentType); 3524 3525 // Set the If-Modified-Since header, if ifModified mode. 3526 if ( s.ifModified ) 3527 xhr.setRequestHeader("If-Modified-Since", 3528 jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" ); 3529 3530 // Set header so the called script knows that it's an XMLHttpRequest 3531 xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); 3532 3533 // Set the Accepts header for the server, depending on the dataType 3534 xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ? 3535 s.accepts[ s.dataType ] + ", */*" : 3536 s.accepts._default ); 3537 } catch(e){} 3538 3539 // Allow custom headers/mimetypes and early abort 3540 if ( s.beforeSend && s.beforeSend(xhr, s) === false ) { 3541 // Handle the global AJAX counter 3542 if ( s.global && ! --jQuery.active ) 3543 jQuery.event.trigger( "ajaxStop" ); 3544 // close opended socket 3545 xhr.abort(); 3546 return false; 3547 } 3548 3549 if ( s.global ) 3550 jQuery.event.trigger("ajaxSend", [xhr, s]); 3551 3552 // Wait for a response to come back 3553 var onreadystatechange = function(isTimeout){ 3554 // The request was aborted, clear the interval and decrement jQuery.active 3555 if (xhr.readyState == 0) { 3556 if (ival) { 3557 // clear poll interval 3558 clearInterval(ival); 3559 ival = null; 3560 // Handle the global AJAX counter 3561 if ( s.global && ! --jQuery.active ) 3562 jQuery.event.trigger( "ajaxStop" ); 3563 } 3564 // The transfer is complete and the data is available, or the request timed out 3565 } else if ( !requestDone && xhr && (xhr.readyState == 4 || isTimeout == "timeout") ) { 3566 requestDone = true; 3567 3568 // clear poll interval 3569 if (ival) { 3570 clearInterval(ival); 3571 ival = null; 3572 } 3573 3574 status = isTimeout == "timeout" ? "timeout" : 3575 !jQuery.httpSuccess( xhr ) ? "error" : 3576 s.ifModified && jQuery.httpNotModified( xhr, s.url ) ? "notmodified" : 3577 "success"; 3578 3579 if ( status == "success" ) { 3580 // Watch for, and catch, XML document parse errors 3581 try { 3582 // process the data (runs the xml through httpData regardless of callback) 3583 data = jQuery.httpData( xhr, s.dataType, s ); 3584 } catch(e) { 3585 status = "parsererror"; 3586 } 3587 } 3588 3589 // Make sure that the request was successful or notmodified 3590 if ( status == "success" ) { 3591 // Cache Last-Modified header, if ifModified mode. 3592 var modRes; 3593 try { 3594 modRes = xhr.getResponseHeader("Last-Modified"); 3595 } catch(e) {} // swallow exception thrown by FF if header is not available 3596 3597 if ( s.ifModified && modRes ) 3598 jQuery.lastModified[s.url] = modRes; 3599 3600 // JSONP handles its own success callback 3601 if ( !jsonp ) 3602 success(); 3603 } else 3604 jQuery.handleError(s, xhr, status); 3605 3606 // Fire the complete handlers 3607 complete(); 3608 3609 if ( isTimeout ) 3610 xhr.abort(); 3611 3612 // Stop memory leaks 3613 if ( s.async ) 3614 xhr = null; 3615 } 3616 }; 3617 3618 if ( s.async ) { 3619 // don't attach the handler to the request, just poll it instead 3620 var ival = setInterval(onreadystatechange, 13); 3621 3622 // Timeout checker 3623 if ( s.timeout > 0 ) 3624 setTimeout(function(){ 3625 // Check to see if the request is still happening 3626 if ( xhr && !requestDone ) 3627 onreadystatechange( "timeout" ); 3628 }, s.timeout); 3629 } 3630 3631 // Send the data 3632 try { 3633 xhr.send(s.data); 3634 } catch(e) { 3635 jQuery.handleError(s, xhr, null, e); 3636 } 3637 3638 // firefox 1.5 doesn't fire statechange for sync requests 3639 if ( !s.async ) 3640 onreadystatechange(); 3641 3642 function success(){ 3643 // If a local callback was specified, fire it and pass it the data 3644 if ( s.success ) 3645 s.success( data, status ); 3646 3647 // Fire the global callback 3648 if ( s.global ) 3649 jQuery.event.trigger( "ajaxSuccess", [xhr, s] ); 3650 } 3651 3652 function complete(){ 3653 // Process result 3654 if ( s.complete ) 3655 s.complete(xhr, status); 3656 3657 // The request was completed 3658 if ( s.global ) 3659 jQuery.event.trigger( "ajaxComplete", [xhr, s] ); 3660 3661 // Handle the global AJAX counter 3662 if ( s.global && ! --jQuery.active ) 3663 jQuery.event.trigger( "ajaxStop" ); 3664 } 3665 3666 // return XMLHttpRequest to allow aborting the request etc. 3667 return xhr; 3668 }, 3669 3670 handleError: function( s, xhr, status, e ) { 3671 // If a local callback was specified, fire it 3672 if ( s.error ) s.error( xhr, status, e ); 3673 3674 // Fire the global callback 3675 if ( s.global ) 3676 jQuery.event.trigger( "ajaxError", [xhr, s, e] ); 3677 }, 3678 3679 // Counter for holding the number of active queries 3680 active: 0, 3681 3682 // Determines if an XMLHttpRequest was successful or not 3683 httpSuccess: function( xhr ) { 3684 try { 3685 // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450 3686 return !xhr.status && location.protocol == "file:" || 3687 ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status == 304 || xhr.status == 1223; 3688 } catch(e){} 3689 return false; 3690 }, 3691 3692 // Determines if an XMLHttpRequest returns NotModified 3693 httpNotModified: function( xhr, url ) { 3694 try { 3695 var xhrRes = xhr.getResponseHeader("Last-Modified"); 3696 3697 // Firefox always returns 200. check Last-Modified date 3698 return xhr.status == 304 || xhrRes == jQuery.lastModified[url]; 3699 } catch(e){} 3700 return false; 3701 }, 3702 3703 httpData: function( xhr, type, s ) { 3704 var ct = xhr.getResponseHeader("content-type"), 3705 xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0, 3706 data = xml ? xhr.responseXML : xhr.responseText; 3707 3708 if ( xml && data.documentElement.tagName == "parsererror" ) 3709 throw "parsererror"; 3710 3711 // Allow a pre-filtering function to sanitize the response 3712 // s != null is checked to keep backwards compatibility 3713 if( s && s.dataFilter ) 3714 data = s.dataFilter( data, type ); 3715 3716 // The filter can actually parse the response 3717 if( typeof data === "string" ){ 3718 3719 // If the type is "script", eval it in global context 3720 if ( type == "script" ) 3721 jQuery.globalEval( data ); 3722 3723 // Get the JavaScript object, if JSON is used. 3724 if ( type == "json" ) 3725 data = window["eval"]("(" + data + ")"); 3726 } 3727 3728 return data; 3729 }, 3730 3731 // Serialize an array of form elements or a set of 3732 // key/values into a query string 3733 param: function( a ) { 3734 var s = [ ]; 3735 3736 function add( key, value ){ 3737 s[ s.length ] = encodeURIComponent(key) + '=' + encodeURIComponent(value); 3738 }; 3739 3740 // If an array was passed in, assume that it is an array 3741 // of form elements 3742 if ( jQuery.isArray(a) || a.jquery ) 3743 // Serialize the form elements 3744 jQuery.each( a, function(){ 3745 add( this.name, this.value ); 3746 }); 3747 3748 // Otherwise, assume that it's an object of key/value pairs 3749 else 3750 // Serialize the key/values 3751 for ( var j in a ) 3752 // If the value is an array then the key names need to be repeated 3753 if ( jQuery.isArray(a[j]) ) 3754 jQuery.each( a[j], function(){ 3755 add( j, this ); 3756 }); 3757 else 3758 add( j, jQuery.isFunction(a[j]) ? a[j]() : a[j] ); 3759 3760 // Return the resulting serialization 3761 return s.join("&").replace(/%20/g, "+"); 3762 } 3763 3764 }); 3765 var elemdisplay = {}, 3766 timerId, 3767 fxAttrs = [ 3768 // height animations 3769 [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ], 3770 // width animations 3771 [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ], 3772 // opacity animations 3773 [ "opacity" ] 3774 ]; 3775 3776 function genFx( type, num ){ 3777 var obj = {}; 3778 jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function(){ 3779 obj[ this ] = type; 3780 }); 3781 return obj; 3782 } 3783 3784 jQuery.fn.extend({ 3785 show: function(speed,callback){ 3786 if ( speed ) { 3787 return this.animate( genFx("show", 3), speed, callback); 3788 } else { 3789 for ( var i = 0, l = this.length; i < l; i++ ){ 3790 var old = jQuery.data(this[i], "olddisplay"); 3791 3792 this[i].style.display = old || ""; 3793 3794 if ( jQuery.css(this[i], "display") === "none" ) { 3795 var tagName = this[i].tagName, display; 3796 3797 if ( elemdisplay[ tagName ] ) { 3798 display = elemdisplay[ tagName ]; 3799 } else { 3800 var elem = jQuery("<" + tagName + " />").appendTo("body"); 3801 3802 display = elem.css("display"); 3803 if ( display === "none" ) 3804 display = "block"; 3805 3806 elem.remove(); 3807 3808 elemdisplay[ tagName ] = display; 3809 } 3810 3811 jQuery.data(this[i], "olddisplay", display); 3812 } 3813 } 3814 3815 // Set the display of the elements in a second loop 3816 // to avoid the constant reflow 3817 for ( var i = 0, l = this.length; i < l; i++ ){ 3818 this[i].style.display = jQuery.data(this[i], "olddisplay") || ""; 3819 } 3820 3821 return this; 3822 } 3823 }, 3824 3825 hide: function(speed,callback){ 3826 if ( speed ) { 3827 return this.animate( genFx("hide", 3), speed, callback); 3828 } else { 3829 for ( var i = 0, l = this.length; i < l; i++ ){ 3830 var old = jQuery.data(this[i], "olddisplay"); 3831 if ( !old && old !== "none" ) 3832 jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display")); 3833 } 3834 3835 // Set the display of the elements in a second loop 3836 // to avoid the constant reflow 3837 for ( var i = 0, l = this.length; i < l; i++ ){ 3838 this[i].style.display = "none"; 3839 } 3840 3841 return this; 3842 } 3843 }, 3844 3845 // Save the old toggle function 3846 _toggle: jQuery.fn.toggle, 3847 3848 toggle: function( fn, fn2 ){ 3849 var bool = typeof fn === "boolean"; 3850 3851 return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ? 3852 this._toggle.apply( this, arguments ) : 3853 fn == null || bool ? 3854 this.each(function(){ 3855 var state = bool ? fn : jQuery(this).is(":hidden"); 3856 jQuery(this)[ state ? "show" : "hide" ](); 3857 }) : 3858 this.animate(genFx("toggle", 3), fn, fn2); 3859 }, 3860 3861 fadeTo: function(speed,to,callback){ 3862 return this.animate({opacity: to}, speed, callback); 3863 }, 3864 3865 animate: function( prop, speed, easing, callback ) { 3866 var optall = jQuery.speed(speed, easing, callback); 3867 3868 return this[ optall.queue === false ? "each" : "queue" ](function(){ 3869 3870 var opt = jQuery.extend({}, optall), p, 3871 hidden = this.nodeType == 1 && jQuery(this).is(":hidden"), 3872 self = this; 3873 3874 for ( p in prop ) { 3875 if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden ) 3876 return opt.complete.call(this); 3877 3878 if ( ( p == "height" || p == "width" ) && this.style ) { 3879 // Store display property 3880 opt.display = jQuery.css(this, "display"); 3881 3882 // Make sure that nothing sneaks out 3883 opt.overflow = this.style.overflow; 3884 } 3885 } 3886 3887 if ( opt.overflow != null ) 3888 this.style.overflow = "hidden"; 3889 3890 opt.curAnim = jQuery.extend({}, prop); 3891 3892 jQuery.each( prop, function(name, val){ 3893 var e = new jQuery.fx( self, opt, name ); 3894 3895 if ( /toggle|show|hide/.test(val) ) 3896 e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop ); 3897 else { 3898 var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/), 3899 start = e.cur(true) || 0; 3900 3901 if ( parts ) { 3902 var end = parseFloat(parts[2]), 3903 unit = parts[3] || "px"; 3904 3905 // We need to compute starting value 3906 if ( unit != "px" ) { 3907 self.style[ name ] = (end || 1) + unit; 3908 start = ((end || 1) / e.cur(true)) * start; 3909 self.style[ name ] = start + unit; 3910 } 3911 3912 // If a +=/-= token was provided, we're doing a relative animation 3913 if ( parts[1] ) 3914 end = ((parts[1] == "-=" ? -1 : 1) * end) + start; 3915 3916 e.custom( start, end, unit ); 3917 } else 3918 e.custom( start, val, "" ); 3919 } 3920 }); 3921 3922 // For JS strict compliance 3923 return true; 3924 }); 3925 }, 3926 3927 stop: function(clearQueue, gotoEnd){ 3928 var timers = jQuery.timers; 3929 3930 if (clearQueue) 3931 this.queue([]); 3932 3933 this.each(function(){ 3934 // go in reverse order so anything added to the queue during the loop is ignored 3935 for ( var i = timers.length - 1; i >= 0; i-- ) 3936 if ( timers[i].elem == this ) { 3937 if (gotoEnd) 3938 // force the next step to be the last 3939 timers[i](true); 3940 timers.splice(i, 1); 3941 } 3942 }); 3943 3944 // start the next in the queue if the last step wasn't forced 3945 if (!gotoEnd) 3946 this.dequeue(); 3947 3948 return this; 3949 } 3950 3951 }); 3952 3953 // Generate shortcuts for custom animations 3954 jQuery.each({ 3955 slideDown: genFx("show", 1), 3956 slideUp: genFx("hide", 1), 3957 slideToggle: genFx("toggle", 1), 3958 fadeIn: { opacity: "show" }, 3959 fadeOut: { opacity: "hide" } 3960 }, function( name, props ){ 3961 jQuery.fn[ name ] = function( speed, callback ){ 3962 return this.animate( props, speed, callback ); 3963 }; 3964 }); 3965 3966 jQuery.extend({ 3967 3968 speed: function(speed, easing, fn) { 3969 var opt = typeof speed === "object" ? speed : { 3970 complete: fn || !fn && easing || 3971 jQuery.isFunction( speed ) && speed, 3972 duration: speed, 3973 easing: fn && easing || easing && !jQuery.isFunction(easing) && easing 3974 }; 3975 3976 opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration : 3977 jQuery.fx.speeds[opt.duration] || jQuery.fx.speeds._default; 3978 3979 // Queueing 3980 opt.old = opt.complete; 3981 opt.complete = function(){ 3982 if ( opt.queue !== false ) 3983 jQuery(this).dequeue(); 3984 if ( jQuery.isFunction( opt.old ) ) 3985 opt.old.call( this ); 3986 }; 3987 3988 return opt; 3989 }, 3990 3991 easing: { 3992 linear: function( p, n, firstNum, diff ) { 3993 return firstNum + diff * p; 3994 }, 3995 swing: function( p, n, firstNum, diff ) { 3996 return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum; 3997 } 3998 }, 3999 4000 timers: [], 4001 4002 fx: function( elem, options, prop ){ 4003 this.options = options; 4004 this.elem = elem; 4005 this.prop = prop; 4006 4007 if ( !options.orig ) 4008 options.orig = {}; 4009 } 4010 4011 }); 4012 4013 jQuery.fx.prototype = { 4014 4015 // Simple function for setting a style value 4016 update: function(){ 4017 if ( this.options.step ) 4018 this.options.step.call( this.elem, this.now, this ); 4019 4020 (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this ); 4021 4022 // Set display property to block for height/width animations 4023 if ( ( this.prop == "height" || this.prop == "width" ) && this.elem.style ) 4024 this.elem.style.display = "block"; 4025 }, 4026 4027 // Get the current size 4028 cur: function(force){ 4029 if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) ) 4030 return this.elem[ this.prop ]; 4031 4032 var r = parseFloat(jQuery.css(this.elem, this.prop, force)); 4033 return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0; 4034 }, 4035 4036 // Start an animation from one number to another 4037 custom: function(from, to, unit){ 4038 this.startTime = now(); 4039 this.start = from; 4040 this.end = to; 4041 this.unit = unit || this.unit || "px"; 4042 this.now = this.start; 4043 this.pos = this.state = 0; 4044 4045 var self = this; 4046 function t(gotoEnd){ 4047 return self.step(gotoEnd); 4048 } 4049 4050 t.elem = this.elem; 4051 4052 if ( t() && jQuery.timers.push(t) && !timerId ) { 4053 timerId = setInterval(function(){ 4054 var timers = jQuery.timers; 4055 4056 for ( var i = 0; i < timers.length; i++ ) 4057 if ( !timers[i]() ) 4058 timers.splice(i--, 1); 4059 4060 if ( !timers.length ) { 4061 clearInterval( timerId ); 4062 timerId = undefined; 4063 } 4064 }, 13); 4065 } 4066 }, 4067 4068 // Simple 'show' function 4069 show: function(){ 4070 // Remember where we started, so that we can go back to it later 4071 this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop ); 4072 this.options.show = true; 4073 4074 // Begin the animation 4075 // Make sure that we start at a small width/height to avoid any 4076 // flash of content 4077 this.custom(this.prop == "width" || this.prop == "height" ? 1 : 0, this.cur()); 4078 4079 // Start by showing the element 4080 jQuery(this.elem).show(); 4081 }, 4082 4083 // Simple 'hide' function 4084 hide: function(){ 4085 // Remember where we started, so that we can go back to it later 4086 this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop ); 4087 this.options.hide = true; 4088 4089 // Begin the animation 4090 this.custom(this.cur(), 0); 4091 }, 4092 4093 // Each step of an animation 4094 step: function(gotoEnd){ 4095 var t = now(); 4096 4097 if ( gotoEnd || t >= this.options.duration + this.startTime ) { 4098 this.now = this.end; 4099 this.pos = this.state = 1; 4100 this.update(); 4101 4102 this.options.curAnim[ this.prop ] = true; 4103 4104 var done = true; 4105 for ( var i in this.options.curAnim ) 4106 if ( this.options.curAnim[i] !== true ) 4107 done = false; 4108 4109 if ( done ) { 4110 if ( this.options.display != null ) { 4111 // Reset the overflow 4112 this.elem.style.overflow = this.options.overflow; 4113 4114 // Reset the display 4115 this.elem.style.display = this.options.display; 4116 if ( jQuery.css(this.elem, "display") == "none" ) 4117 this.elem.style.display = "block"; 4118 } 4119 4120 // Hide the element if the "hide" operation was done 4121 if ( this.options.hide ) 4122 jQuery(this.elem).hide(); 4123 4124 // Reset the properties, if the item has been hidden or shown 4125 if ( this.options.hide || this.options.show ) 4126 for ( var p in this.options.curAnim ) 4127 jQuery.attr(this.elem.style, p, this.options.orig[p]); 4128 4129 // Execute the complete function 4130 this.options.complete.call( this.elem ); 4131 } 4132 4133 return false; 4134 } else { 4135 var n = t - this.startTime; 4136 this.state = n / this.options.duration; 4137 4138 // Perform the easing function, defaults to swing 4139 this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration); 4140 this.now = this.start + ((this.end - this.start) * this.pos); 4141 4142 // Perform the next step of the animation 4143 this.update(); 4144 } 4145 4146 return true; 4147 } 4148 4149 }; 4150 4151 jQuery.extend( jQuery.fx, { 4152 speeds:{ 4153 slow: 600, 4154 fast: 200, 4155 // Default speed 4156 _default: 400 4157 }, 4158 step: { 4159 4160 opacity: function(fx){ 4161 jQuery.attr(fx.elem.style, "opacity", fx.now); 4162 }, 4163 4164 _default: function(fx){ 4165 if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) 4166 fx.elem.style[ fx.prop ] = fx.now + fx.unit; 4167 else 4168 fx.elem[ fx.prop ] = fx.now; 4169 } 4170 } 4171 }); 4172 if ( document.documentElement["getBoundingClientRect"] ) 4173 jQuery.fn.offset = function() { 4174 if ( !this[0] ) return { top: 0, left: 0 }; 4175 if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] ); 4176 var box = this[0].getBoundingClientRect(), doc = this[0].ownerDocument, body = doc.body, docElem = doc.documentElement, 4177 clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0, 4178 top = box.top + (self.pageYOffset || jQuery.boxModel && docElem.scrollTop || body.scrollTop ) - clientTop, 4179 left = box.left + (self.pageXOffset || jQuery.boxModel && docElem.scrollLeft || body.scrollLeft) - clientLeft; 4180 return { top: top, left: left }; 4181 }; 4182 else 4183 jQuery.fn.offset = function() { 4184 if ( !this[0] ) return { top: 0, left: 0 }; 4185 if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] ); 4186 jQuery.offset.initialized || jQuery.offset.initialize(); 4187 4188 var elem = this[0], offsetParent = elem.offsetParent, prevOffsetParent = elem, 4189 doc = elem.ownerDocument, computedStyle, docElem = doc.documentElement, 4190 body = doc.body, defaultView = doc.defaultView, 4191 prevComputedStyle = defaultView.getComputedStyle(elem, null), 4192 top = elem.offsetTop, left = elem.offsetLeft; 4193 4194 while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) { 4195 computedStyle = defaultView.getComputedStyle(elem, null); 4196 top -= elem.scrollTop, left -= elem.scrollLeft; 4197 if ( elem === offsetParent ) { 4198 top += elem.offsetTop, left += elem.offsetLeft; 4199 if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && /^t(able|d|h)$/i.test(elem.tagName)) ) 4200 top += parseInt( computedStyle.borderTopWidth, 10) || 0, 4201 left += parseInt( computedStyle.borderLeftWidth, 10) || 0; 4202 prevOffsetParent = offsetParent, offsetParent = elem.offsetParent; 4203 } 4204 if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) 4205 top += parseInt( computedStyle.borderTopWidth, 10) || 0, 4206 left += parseInt( computedStyle.borderLeftWidth, 10) || 0; 4207 prevComputedStyle = computedStyle; 4208 } 4209 4210 if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) 4211 top += body.offsetTop, 4212 left += body.offsetLeft; 4213 4214 if ( prevComputedStyle.position === "fixed" ) 4215 top += Math.max(docElem.scrollTop, body.scrollTop), 4216 left += Math.max(docElem.scrollLeft, body.scrollLeft); 4217 4218 return { top: top, left: left }; 4219 }; 4220 4221 jQuery.offset = { 4222 initialize: function() { 4223 if ( this.initialized ) return; 4224 var body = document.body, container = document.createElement('div'), innerDiv, checkDiv, table, td, rules, prop, bodyMarginTop = body.style.marginTop, 4225 html = '<div style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;"><div></div></div><table style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;" cellpadding="0" cellspacing="0"><tr><td></td></tr></table>'; 4226 4227 rules = { position: 'absolute', top: 0, left: 0, margin: 0, border: 0, width: '1px', height: '1px', visibility: 'hidden' }; 4228 for ( prop in rules ) container.style[prop] = rules[prop]; 4229 4230 container.innerHTML = html; 4231 body.insertBefore(container, body.firstChild); 4232 innerDiv = container.firstChild, checkDiv = innerDiv.firstChild, td = innerDiv.nextSibling.firstChild.firstChild; 4233 4234 this.doesNotAddBorder = (checkDiv.offsetTop !== 5); 4235 this.doesAddBorderForTableAndCells = (td.offsetTop === 5); 4236 4237 innerDiv.style.overflow = 'hidden', innerDiv.style.position = 'relative'; 4238 this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5); 4239 4240 body.style.marginTop = '1px'; 4241 this.doesNotIncludeMarginInBodyOffset = (body.offsetTop === 0); 4242 body.style.marginTop = bodyMarginTop; 4243 4244 body.removeChild(container); 4245 this.initialized = true; 4246 }, 4247 4248 bodyOffset: function(body) { 4249 jQuery.offset.initialized || jQuery.offset.initialize(); 4250 var top = body.offsetTop, left = body.offsetLeft; 4251 if ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) 4252 top += parseInt( jQuery.curCSS(body, 'marginTop', true), 10 ) || 0, 4253 left += parseInt( jQuery.curCSS(body, 'marginLeft', true), 10 ) || 0; 4254 return { top: top, left: left }; 4255 } 4256 }; 4257 4258 4259 jQuery.fn.extend({ 4260 position: function() { 4261 var left = 0, top = 0, results; 4262 4263 if ( this[0] ) { 4264 // Get *real* offsetParent 4265 var offsetParent = this.offsetParent(), 4266 4267 // Get correct offsets 4268 offset = this.offset(), 4269 parentOffset = /^body|html$/i.test(offsetParent[0].tagName) ? { top: 0, left: 0 } : offsetParent.offset(); 4270 4271 // Subtract element margins 4272 // note: when an element has margin: auto the offsetLeft and marginLeft 4273 // are the same in Safari causing offset.left to incorrectly be 0 4274 offset.top -= num( this, 'marginTop' ); 4275 offset.left -= num( this, 'marginLeft' ); 4276 4277 // Add offsetParent borders 4278 parentOffset.top += num( offsetParent, 'borderTopWidth' ); 4279 parentOffset.left += num( offsetParent, 'borderLeftWidth' ); 4280 4281 // Subtract the two offsets 4282 results = { 4283 top: offset.top - parentOffset.top, 4284 left: offset.left - parentOffset.left 4285 }; 4286 } 4287 4288 return results; 4289 }, 4290 4291 offsetParent: function() { 4292 var offsetParent = this[0].offsetParent || document.body; 4293 while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && jQuery.css(offsetParent, 'position') == 'static') ) 4294 offsetParent = offsetParent.offsetParent; 4295 return jQuery(offsetParent); 4296 } 4297 }); 4298 4299 4300 // Create scrollLeft and scrollTop methods 4301 jQuery.each( ['Left', 'Top'], function(i, name) { 4302 var method = 'scroll' + name; 4303 4304 jQuery.fn[ method ] = function(val) { 4305 if (!this[0]) return null; 4306 4307 return val !== undefined ? 4308 4309 // Set the scroll offset 4310 this.each(function() { 4311 this == window || this == document ? 4312 window.scrollTo( 4313 !i ? val : jQuery(window).scrollLeft(), 4314 i ? val : jQuery(window).scrollTop() 4315 ) : 4316 this[ method ] = val; 4317 }) : 4318 4319 // Return the scroll offset 4320 this[0] == window || this[0] == document ? 4321 self[ i ? 'pageYOffset' : 'pageXOffset' ] || 4322 jQuery.boxModel && document.documentElement[ method ] || 4323 document.body[ method ] : 4324 this[0][ method ]; 4325 }; 4326 }); 4327 // Create innerHeight, innerWidth, outerHeight and outerWidth methods 4328 jQuery.each([ "Height", "Width" ], function(i, name){ 4329 4330 var tl = i ? "Left" : "Top", // top or left 4331 br = i ? "Right" : "Bottom", // bottom or right 4332 lower = name.toLowerCase(); 4333 4334 // innerHeight and innerWidth 4335 jQuery.fn["inner" + name] = function(){ 4336 return this[0] ? 4337 jQuery.css( this[0], lower, false, "padding" ) : 4338 null; 4339 }; 4340 4341 // outerHeight and outerWidth 4342 jQuery.fn["outer" + name] = function(margin) { 4343 return this[0] ? 4344 jQuery.css( this[0], lower, false, margin ? "margin" : "border" ) : 4345 null; 4346 }; 4347 4348 var type = name.toLowerCase(); 4349 4350 jQuery.fn[ type ] = function( size ) { 4351 // Get window width or height 4352 return this[0] == window ? 4353 // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode 4354 document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] || 4355 document.body[ "client" + name ] : 4356 4357 // Get document width or height 4358 this[0] == document ? 4359 // Either scroll[Width/Height] or offset[Width/Height], whichever is greater 4360 Math.max( 4361 document.documentElement["client" + name], 4362 document.body["scroll" + name], document.documentElement["scroll" + name], 4363 document.body["offset" + name], document.documentElement["offset" + name] 4364 ) : 4365 4366 // Get or set width or height on the element 4367 size === undefined ? 4368 // Get width or height on the element 4369 (this.length ? jQuery.css( this[0], type ) : null) : 4370 4371 // Set the width or height on the element (default to pixels if value is unitless) 4372 this.css( type, typeof size === "string" ? size : size + "px" ); 4373 }; 4374 4375 }); 4376 })(); -
new file src/allmydata/web/protovis-r3.2.js
diff --git a/src/allmydata/web/protovis-r3.2.js b/src/allmydata/web/protovis-r3.2.js new file mode 100644 index 0000000..95bb3be
- + 1 // fba9dc2 2 var a;if(!Array.prototype.map)Array.prototype.map=function(b,c){for(var d=this.length,f=new Array(d),g=0;g<d;g++)if(g in this)f[g]=b.call(c,this[g],g,this);return f};if(!Array.prototype.filter)Array.prototype.filter=function(b,c){for(var d=this.length,f=[],g=0;g<d;g++)if(g in this){var h=this[g];b.call(c,h,g,this)&&f.push(h)}return f};if(!Array.prototype.forEach)Array.prototype.forEach=function(b,c){for(var d=this.length>>>0,f=0;f<d;f++)f in this&&b.call(c,this[f],f,this)}; 3 if(!Array.prototype.reduce)Array.prototype.reduce=function(b,c){var d=this.length;if(!d&&arguments.length==1)throw new Error("reduce: empty array, no initial value");var f=0;if(arguments.length<2)for(;;){if(f in this){c=this[f++];break}if(++f>=d)throw new Error("reduce: no values, no initial value");}for(;f<d;f++)if(f in this)c=b(c,this[f],f,this);return c};var pv={};pv.version={major:3,minor:2};pv.identity=function(b){return b};pv.index=function(){return this.index};pv.child=function(){return this.childIndex}; 4 pv.parent=function(){return this.parent.index};pv.extend=function(b){function c(){}c.prototype=b.prototype||b;return new c}; 5 try{eval("pv.parse = function(x) x;")}catch(e){pv.parse=function(b){for(var c=new RegExp("function\\s*(\\b\\w+)?\\s*\\([^)]*\\)\\s*","mg"),d,f,g=0,h="";d=c.exec(b);){d=d.index+d[0].length;if(b.charAt(d)!="{"){h+=b.substring(g,d)+"{return ";g=d;for(var i=0;i>=0&&d<b.length;d++){var j=b.charAt(d);switch(j){case '"':case "'":for(;++d<b.length&&(f=b.charAt(d))!=j;)f=="\\"&&d++;break;case "[":case "(":i++;break;case "]":case ")":i--;break;case ";":case ",":i==0&&i--;break}}h+=pv.parse(b.substring(g,--d))+ 6 ";}";g=d}c.lastIndex=d}h+=b.substring(g);return h}}pv.css=function(b,c){return window.getComputedStyle?window.getComputedStyle(b,null).getPropertyValue(c):b.currentStyle[c]};pv.error=function(b){typeof console=="undefined"?alert(b):console.error(b)};pv.listen=function(b,c,d){d=pv.listener(d);return b.addEventListener?b.addEventListener(c,d,false):b.attachEvent("on"+c,d)};pv.listener=function(b){return b.$listener||(b.$listener=function(c){try{pv.event=c;return b.call(this,c)}finally{delete pv.event}})}; 7 pv.ancestor=function(b,c){for(;c;){if(c==b)return true;c=c.parentNode}return false};pv.id=function(){var b=1;return function(){return b++}}();pv.functor=function(b){return typeof b=="function"?b:function(){return b}};pv.listen(window,"load",function(){for(pv.$={i:0,x:document.getElementsByTagName("script")};pv.$.i<pv.$.x.length;pv.$.i++){pv.$.s=pv.$.x[pv.$.i];if(pv.$.s.type=="text/javascript+protovis")try{window.eval(pv.parse(pv.$.s.text))}catch(b){pv.error(b)}}delete pv.$});pv.Format={}; 8 pv.Format.re=function(b){return b.replace(/[\\\^\$\*\+\?\[\]\(\)\.\{\}]/g,"\\$&")};pv.Format.pad=function(b,c,d){c=c-String(d).length;return c<1?d:(new Array(c+1)).join(b)+d}; 9 pv.Format.date=function(b){function c(f){return b.replace(/%[a-zA-Z0-9]/g,function(g){switch(g){case "%a":return["Sun","Mon","Tue","Wed","Thu","Fri","Sat"][f.getDay()];case "%A":return["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"][f.getDay()];case "%h":case "%b":return["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"][f.getMonth()];case "%B":return["January","February","March","April","May","June","July","August","September","October","November","December"][f.getMonth()]; 10 case "%c":return f.toLocaleString();case "%C":return d("0",2,Math.floor(f.getFullYear()/100)%100);case "%d":return d("0",2,f.getDate());case "%x":case "%D":return d("0",2,f.getMonth()+1)+"/"+d("0",2,f.getDate())+"/"+d("0",2,f.getFullYear()%100);case "%e":return d(" ",2,f.getDate());case "%H":return d("0",2,f.getHours());case "%I":return(g=f.getHours()%12)?d("0",2,g):12;case "%m":return d("0",2,f.getMonth()+1);case "%M":return d("0",2,f.getMinutes());case "%n":return"\n";case "%p":return f.getHours()< 11 12?"AM":"PM";case "%T":case "%X":case "%r":g=f.getHours()%12;return(g?d("0",2,g):12)+":"+d("0",2,f.getMinutes())+":"+d("0",2,f.getSeconds())+" "+(f.getHours()<12?"AM":"PM");case "%R":return d("0",2,f.getHours())+":"+d("0",2,f.getMinutes());case "%S":return d("0",2,f.getSeconds());case "%Q":return d("0",3,f.getMilliseconds());case "%t":return"\t";case "%u":return(g=f.getDay())?g:1;case "%w":return f.getDay();case "%y":return d("0",2,f.getFullYear()%100);case "%Y":return f.getFullYear();case "%%":return"%"}return g})} 12 var d=pv.Format.pad;c.format=c;c.parse=function(f){var g=1970,h=0,i=1,j=0,l=0,k=0,q=[function(){}],o=pv.Format.re(b).replace(/%[a-zA-Z0-9]/g,function(n){switch(n){case "%b":q.push(function(m){h={Jan:0,Feb:1,Mar:2,Apr:3,May:4,Jun:5,Jul:6,Aug:7,Sep:8,Oct:9,Nov:10,Dec:11}[m]});return"([A-Za-z]+)";case "%h":case "%B":q.push(function(m){h={January:0,February:1,March:2,April:3,May:4,June:5,July:6,August:7,September:8,October:9,November:10,December:11}[m]});return"([A-Za-z]+)";case "%e":case "%d":q.push(function(m){i= 13 m});return"([0-9]+)";case "%I":case "%H":q.push(function(m){j=m});return"([0-9]+)";case "%m":q.push(function(m){h=m-1});return"([0-9]+)";case "%M":q.push(function(m){l=m});return"([0-9]+)";case "%p":q.push(function(m){if(j==12){if(m=="am")j=0}else if(m=="pm")j=Number(j)+12});return"(am|pm)";case "%S":q.push(function(m){k=m});return"([0-9]+)";case "%y":q.push(function(m){m=Number(m);g=m+(0<=m&&m<69?2E3:m>=69&&m<100?1900:0)});return"([0-9]+)";case "%Y":q.push(function(m){g=m});return"([0-9]+)";case "%%":q.push(function(){}); 14 return"%"}return n});(f=f.match(o))&&f.forEach(function(n,m){q[m](n)});return new Date(g,h,i,j,l,k)};return c}; 15 pv.Format.time=function(b){function c(f){f=Number(f);switch(b){case "short":if(f>=31536E6)return(f/31536E6).toFixed(1)+" years";else if(f>=6048E5)return(f/6048E5).toFixed(1)+" weeks";else if(f>=864E5)return(f/864E5).toFixed(1)+" days";else if(f>=36E5)return(f/36E5).toFixed(1)+" hours";else if(f>=6E4)return(f/6E4).toFixed(1)+" minutes";return(f/1E3).toFixed(1)+" seconds";case "long":var g=[],h=f%36E5/6E4>>0;g.push(d("0",2,f%6E4/1E3>>0));if(f>=36E5){var i=f%864E5/36E5>>0;g.push(d("0",2,h));if(f>=864E5){g.push(d("0", 16 2,i));g.push(Math.floor(f/864E5).toFixed())}else g.push(i.toFixed())}else g.push(h.toFixed());return g.reverse().join(":")}}var d=pv.Format.pad;c.format=c;c.parse=function(f){switch(b){case "short":for(var g=/([0-9,.]+)\s*([a-z]+)/g,h,i=0;h=g.exec(f);){var j=parseFloat(h[0].replace(",","")),l=0;switch(h[2].toLowerCase()){case "year":case "years":l=31536E6;break;case "week":case "weeks":l=6048E5;break;case "day":case "days":l=864E5;break;case "hour":case "hours":l=36E5;break;case "minute":case "minutes":l= 17 6E4;break;case "second":case "seconds":l=1E3;break}i+=j*l}return i;case "long":h=f.replace(",","").split(":").reverse();i=0;if(h.length)i+=parseFloat(h[0])*1E3;if(h.length>1)i+=parseFloat(h[1])*6E4;if(h.length>2)i+=parseFloat(h[2])*36E5;if(h.length>3)i+=parseFloat(h[3])*864E5;return i}};return c}; 18 pv.Format.number=function(){function b(n){if(Infinity>h)n=Math.round(n*i)/i;var m=String(Math.abs(n)).split("."),r=m[0];n=n<0?"-":"";if(r.length>d)r=r.substring(r.length-d);if(k&&r.length<c)r=n+(new Array(c-r.length+1)).join(j)+r;if(r.length>3)r=r.replace(/\B(?=(?:\d{3})+(?!\d))/g,o);if(!k&&r.length<f)r=(new Array(f-r.length+1)).join(j)+n+r;m[0]=r;r=m[1]||"";if(r.length<g)m[1]=r+(new Array(g-r.length+1)).join(l);return m.join(q)}var c=0,d=Infinity,f=0,g=0,h=0,i=1,j="0",l="0",k=true,q=".",o=",";b.format= 19 b;b.parse=function(n){var m=pv.Format.re;n=String(n).replace(new RegExp("^("+m(j)+")*"),"").replace(new RegExp("("+m(l)+")*$"),"").split(q);m=n[0].replace(new RegExp(m(o),"g"),"");if(m.length>d)m=m.substring(m.length-d);n=n[1]?Number("0."+n[1]):0;if(Infinity>h)n=Math.round(n*i)/i;return Math.round(m)+n};b.integerDigits=function(n,m){if(arguments.length){c=Number(n);d=arguments.length>1?Number(m):c;f=c+Math.floor(c/3)*o.length;return this}return[c,d]};b.fractionDigits=function(n,m){if(arguments.length){g= 20 Number(n);h=arguments.length>1?Number(m):g;i=Math.pow(10,h);return this}return[g,h]};b.integerPad=function(n){if(arguments.length){j=String(n);k=/\d/.test(j);return this}return j};b.fractionPad=function(n){if(arguments.length){l=String(n);return this}return l};b.decimal=function(n){if(arguments.length){q=String(n);return this}return q};b.group=function(n){if(arguments.length){o=n?String(n):"";f=c+Math.floor(c/3)*o.length;return this}return o};return b}; 21 pv.map=function(b,c){var d={};return c?b.map(function(f,g){d.index=g;return c.call(d,f)}):b.slice()};pv.repeat=function(b,c){if(arguments.length==1)c=2;return pv.blend(pv.range(c).map(function(){return b}))};pv.cross=function(b,c){for(var d=[],f=0,g=b.length,h=c.length;f<g;f++)for(var i=0,j=b[f];i<h;i++)d.push([j,c[i]]);return d};pv.blend=function(b){return Array.prototype.concat.apply([],b)}; 22 pv.transpose=function(b){var c=b.length,d=pv.max(b,function(i){return i.length});if(d>c){b.length=d;for(var f=c;f<d;f++)b[f]=new Array(c);for(f=0;f<c;f++)for(var g=f+1;g<d;g++){var h=b[f][g];b[f][g]=b[g][f];b[g][f]=h}}else{for(f=0;f<d;f++)b[f].length=c;for(f=0;f<c;f++)for(g=0;g<f;g++){h=b[f][g];b[f][g]=b[g][f];b[g][f]=h}}b.length=d;for(f=0;f<d;f++)b[f].length=c;return b};pv.normalize=function(b,c){b=pv.map(b,c);c=pv.sum(b);for(var d=0;d<b.length;d++)b[d]/=c;return b}; 23 pv.permute=function(b,c,d){if(!d)d=pv.identity;var f=new Array(c.length),g={};c.forEach(function(h,i){g.index=h;f[i]=d.call(g,b[h])});return f};pv.numerate=function(b,c){if(!c)c=pv.identity;var d={},f={};b.forEach(function(g,h){f.index=h;d[c.call(f,g)]=h});return d};pv.uniq=function(b,c){if(!c)c=pv.identity;var d={},f=[],g={},h;b.forEach(function(i,j){g.index=j;h=c.call(g,i);h in d||(d[h]=f.push(h))});return f};pv.naturalOrder=function(b,c){return b<c?-1:b>c?1:0}; 24 pv.reverseOrder=function(b,c){return c<b?-1:c>b?1:0};pv.search=function(b,c,d){if(!d)d=pv.identity;for(var f=0,g=b.length-1;f<=g;){var h=f+g>>1,i=d(b[h]);if(i<c)f=h+1;else if(i>c)g=h-1;else return h}return-f-1};pv.search.index=function(b,c,d){b=pv.search(b,c,d);return b<0?-b-1:b}; 25 pv.range=function(b,c,d){if(arguments.length==1){c=b;b=0}if(d==undefined)d=1;if((c-b)/d==Infinity)throw new Error("range must be finite");var f=[],g=0,h;if(d<0)for(;(h=b+d*g++)>c;)f.push(h);else for(;(h=b+d*g++)<c;)f.push(h);return f};pv.random=function(b,c,d){if(arguments.length==1){c=b;b=0}if(d==undefined)d=1;return d?Math.floor(Math.random()*(c-b)/d)*d+b:Math.random()*(c-b)+b}; 26 pv.sum=function(b,c){var d={};return b.reduce(c?function(f,g,h){d.index=h;return f+c.call(d,g)}:function(f,g){return f+g},0)};pv.max=function(b,c){if(c==pv.index)return b.length-1;return Math.max.apply(null,c?pv.map(b,c):b)};pv.max.index=function(b,c){if(!b.length)return-1;if(c==pv.index)return b.length-1;if(!c)c=pv.identity;for(var d=0,f=-Infinity,g={},h=0;h<b.length;h++){g.index=h;var i=c.call(g,b[h]);if(i>f){f=i;d=h}}return d}; 27 pv.min=function(b,c){if(c==pv.index)return 0;return Math.min.apply(null,c?pv.map(b,c):b)};pv.min.index=function(b,c){if(!b.length)return-1;if(c==pv.index)return 0;if(!c)c=pv.identity;for(var d=0,f=Infinity,g={},h=0;h<b.length;h++){g.index=h;var i=c.call(g,b[h]);if(i<f){f=i;d=h}}return d};pv.mean=function(b,c){return pv.sum(b,c)/b.length}; 28 pv.median=function(b,c){if(c==pv.index)return(b.length-1)/2;b=pv.map(b,c).sort(pv.naturalOrder);if(b.length%2)return b[Math.floor(b.length/2)];c=b.length/2;return(b[c-1]+b[c])/2};pv.variance=function(b,c){if(b.length<1)return NaN;if(b.length==1)return 0;var d=pv.mean(b,c),f=0,g={};if(!c)c=pv.identity;for(var h=0;h<b.length;h++){g.index=h;var i=c.call(g,b[h])-d;f+=i*i}return f};pv.deviation=function(b,c){return Math.sqrt(pv.variance(b,c)/(b.length-1))};pv.log=function(b,c){return Math.log(b)/Math.log(c)}; 29 pv.logSymmetric=function(b,c){return b==0?0:b<0?-pv.log(-b,c):pv.log(b,c)};pv.logAdjusted=function(b,c){if(!isFinite(b))return b;var d=b<0;if(b<c)b+=(c-b)/c;return d?-pv.log(b,c):pv.log(b,c)};pv.logFloor=function(b,c){return b>0?Math.pow(c,Math.floor(pv.log(b,c))):-Math.pow(c,-Math.floor(-pv.log(-b,c)))};pv.logCeil=function(b,c){return b>0?Math.pow(c,Math.ceil(pv.log(b,c))):-Math.pow(c,-Math.ceil(-pv.log(-b,c)))}; 30 (function(){var b=Math.PI/180,c=180/Math.PI;pv.radians=function(d){return b*d};pv.degrees=function(d){return c*d}})();pv.keys=function(b){var c=[];for(var d in b)c.push(d);return c};pv.entries=function(b){var c=[];for(var d in b)c.push({key:d,value:b[d]});return c};pv.values=function(b){var c=[];for(var d in b)c.push(b[d]);return c};pv.dict=function(b,c){for(var d={},f={},g=0;g<b.length;g++)if(g in b){var h=b[g];f.index=g;d[h]=c.call(f,h)}return d};pv.dom=function(b){return new pv.Dom(b)}; 31 pv.Dom=function(b){this.$map=b};pv.Dom.prototype.$leaf=function(b){return typeof b!="object"};pv.Dom.prototype.leaf=function(b){if(arguments.length){this.$leaf=b;return this}return this.$leaf};pv.Dom.prototype.root=function(b){function c(g){var h=new pv.Dom.Node;for(var i in g){var j=g[i];h.appendChild(d(j)?new pv.Dom.Node(j):c(j)).nodeName=i}return h}var d=this.$leaf,f=c(this.$map);f.nodeName=b;return f};pv.Dom.prototype.nodes=function(){return this.root().nodes()}; 32 pv.Dom.Node=function(b){this.nodeValue=b;this.childNodes=[]};a=pv.Dom.Node.prototype;a.parentNode=null;a.firstChild=null;a.lastChild=null;a.previousSibling=null;a.nextSibling=null; 33 a.removeChild=function(b){var c=this.childNodes.indexOf(b);if(c==-1)throw new Error("child not found");this.childNodes.splice(c,1);if(b.previousSibling)b.previousSibling.nextSibling=b.nextSibling;else this.firstChild=b.nextSibling;if(b.nextSibling)b.nextSibling.previousSibling=b.previousSibling;else this.lastChild=b.previousSibling;delete b.nextSibling;delete b.previousSibling;delete b.parentNode;return b}; 34 a.appendChild=function(b){b.parentNode&&b.parentNode.removeChild(b);b.parentNode=this;if(b.previousSibling=this.lastChild)this.lastChild.nextSibling=b;else this.firstChild=b;this.lastChild=b;this.childNodes.push(b);return b}; 35 a.insertBefore=function(b,c){if(!c)return this.appendChild(b);var d=this.childNodes.indexOf(c);if(d==-1)throw new Error("child not found");b.parentNode&&b.parentNode.removeChild(b);b.parentNode=this;b.nextSibling=c;if(b.previousSibling=c.previousSibling)c.previousSibling.nextSibling=b;else{if(c==this.lastChild)this.lastChild=b;this.firstChild=b}this.childNodes.splice(d,0,b);return b}; 36 a.replaceChild=function(b,c){var d=this.childNodes.indexOf(c);if(d==-1)throw new Error("child not found");b.parentNode&&b.parentNode.removeChild(b);b.parentNode=this;b.nextSibling=c.nextSibling;if(b.previousSibling=c.previousSibling)c.previousSibling.nextSibling=b;else this.firstChild=b;if(c.nextSibling)c.nextSibling.previousSibling=b;else this.lastChild=b;this.childNodes[d]=b;return c};a.visitBefore=function(b){function c(d,f){b(d,f);for(d=d.firstChild;d;d=d.nextSibling)c(d,f+1)}c(this,0)}; 37 a.visitAfter=function(b){function c(d,f){for(var g=d.firstChild;g;g=g.nextSibling)c(g,f+1);b(d,f)}c(this,0)};a.sort=function(b){if(this.firstChild){this.childNodes.sort(b);var c=this.firstChild=this.childNodes[0],d;delete c.previousSibling;for(var f=1;f<this.childNodes.length;f++){c.sort(b);d=this.childNodes[f];d.previousSibling=c;c=c.nextSibling=d}this.lastChild=c;delete c.nextSibling;c.sort(b)}return this}; 38 a.reverse=function(){var b=[];this.visitAfter(function(c){for(;c.lastChild;)b.push(c.removeChild(c.lastChild));for(var d;d=b.pop();)c.insertBefore(d,c.firstChild)});return this};a.nodes=function(){function b(d){c.push(d);d.childNodes.forEach(b)}var c=[];b(this,c);return c}; 39 a.toggle=function(b){if(b)return this.toggled?this.visitBefore(function(d){d.toggled&&d.toggle()}):this.visitAfter(function(d){d.toggled||d.toggle()});b=this;if(b.toggled){for(var c;c=b.toggled.pop();)b.appendChild(c);delete b.toggled}else if(b.lastChild)for(b.toggled=[];b.lastChild;)b.toggled.push(b.removeChild(b.lastChild))};pv.nodes=function(b){for(var c=new pv.Dom.Node,d=0;d<b.length;d++)c.appendChild(new pv.Dom.Node(b[d]));return c.nodes()};pv.tree=function(b){return new pv.Tree(b)}; 40 pv.Tree=function(b){this.array=b};pv.Tree.prototype.keys=function(b){this.k=b;return this};pv.Tree.prototype.value=function(b){this.v=b;return this};pv.Tree.prototype.map=function(){for(var b={},c={},d=0;d<this.array.length;d++){c.index=d;for(var f=this.array[d],g=this.k.call(c,f),h=b,i=0;i<g.length-1;i++)h=h[g[i]]||(h[g[i]]={});h[g[i]]=this.v?this.v.call(c,f):f}return b};pv.nest=function(b){return new pv.Nest(b)};pv.Nest=function(b){this.array=b;this.keys=[]};a=pv.Nest.prototype; 41 a.key=function(b){this.keys.push(b);return this};a.sortKeys=function(b){this.keys[this.keys.length-1].order=b||pv.naturalOrder;return this};a.sortValues=function(b){this.order=b||pv.naturalOrder;return this};a.map=function(){for(var b={},c=[],d,f=0;f<this.array.length;f++){var g=this.array[f],h=b;for(d=0;d<this.keys.length-1;d++){var i=this.keys[d](g);h[i]||(h[i]={});h=h[i]}i=this.keys[d](g);if(!h[i]){d=[];c.push(d);h[i]=d}h[i].push(g)}if(this.order)for(d=0;d<c.length;d++)c[d].sort(this.order);return b}; 42 a.entries=function(){function b(d){var f=[];for(var g in d){var h=d[g];f.push({key:g,values:h instanceof Array?h:b(h)})}return f}function c(d,f){var g=this.keys[f].order;g&&d.sort(function(i,j){return g(i.key,j.key)});if(++f<this.keys.length)for(var h=0;h<d.length;h++)c.call(this,d[h].values,f);return d}return c.call(this,b(this.map()),0)};a.rollup=function(b){function c(d){for(var f in d){var g=d[f];if(g instanceof Array)d[f]=b(g);else c(g)}return d}return c(this.map())};pv.flatten=function(b){return new pv.Flatten(b)}; 43 pv.Flatten=function(b){this.map=b;this.keys=[]};pv.Flatten.prototype.key=function(b,c){this.keys.push({name:b,value:c});delete this.$leaf;return this};pv.Flatten.prototype.leaf=function(b){this.keys.length=0;this.$leaf=b;return this}; 44 pv.Flatten.prototype.array=function(){function b(i,j){if(j<f.length-1)for(var l in i){d.push(l);b(i[l],j+1);d.pop()}else c.push(d.concat(i))}var c=[],d=[],f=this.keys,g=this.$leaf;if(g){function h(i,j){if(g(i))c.push({keys:d.slice(),value:i});else for(var l in i){d.push(l);h(i[l],j+1);d.pop()}}h(this.map,0);return c}b(this.map,0);return c.map(function(i){for(var j={},l=0;l<f.length;l++){var k=f[l],q=i[l];j[k.name]=k.value?k.value.call(null,q):q}return j})}; 45 pv.vector=function(b,c){return new pv.Vector(b,c)};pv.Vector=function(b,c){this.x=b;this.y=c};a=pv.Vector.prototype;a.perp=function(){return new pv.Vector(-this.y,this.x)};a.norm=function(){var b=this.length();return this.times(b?1/b:1)};a.length=function(){return Math.sqrt(this.x*this.x+this.y*this.y)};a.times=function(b){return new pv.Vector(this.x*b,this.y*b)};a.plus=function(b,c){return arguments.length==1?new pv.Vector(this.x+b.x,this.y+b.y):new pv.Vector(this.x+b,this.y+c)}; 46 a.minus=function(b,c){return arguments.length==1?new pv.Vector(this.x-b.x,this.y-b.y):new pv.Vector(this.x-b,this.y-c)};a.dot=function(b,c){return arguments.length==1?this.x*b.x+this.y*b.y:this.x*b+this.y*c};pv.Transform=function(){};pv.Transform.prototype={k:1,x:0,y:0};pv.Transform.identity=new pv.Transform;pv.Transform.prototype.translate=function(b,c){var d=new pv.Transform;d.k=this.k;d.x=this.k*b+this.x;d.y=this.k*c+this.y;return d}; 47 pv.Transform.prototype.scale=function(b){var c=new pv.Transform;c.k=this.k*b;c.x=this.x;c.y=this.y;return c};pv.Transform.prototype.invert=function(){var b=new pv.Transform,c=1/this.k;b.k=c;b.x=-this.x*c;b.y=-this.y*c;return b};pv.Transform.prototype.times=function(b){var c=new pv.Transform;c.k=this.k*b.k;c.x=this.k*b.x+this.x;c.y=this.k*b.y+this.y;return c};pv.Scale=function(){}; 48 pv.Scale.interpolator=function(b,c){if(typeof b=="number")return function(d){return d*(c-b)+b};b=pv.color(b).rgb();c=pv.color(c).rgb();return function(d){var f=b.a*(1-d)+c.a*d;if(f<1.0E-5)f=0;return b.a==0?pv.rgb(c.r,c.g,c.b,f):c.a==0?pv.rgb(b.r,b.g,b.b,f):pv.rgb(Math.round(b.r*(1-d)+c.r*d),Math.round(b.g*(1-d)+c.g*d),Math.round(b.b*(1-d)+c.b*d),f)}}; 49 pv.Scale.quantitative=function(){function b(o){return new Date(o)}function c(o){var n=pv.search(d,o);if(n<0)n=-n-2;n=Math.max(0,Math.min(h.length-1,n));return h[n]((l(o)-f[n])/(f[n+1]-f[n]))}var d=[0,1],f=[0,1],g=[0,1],h=[pv.identity],i=Number,j=false,l=pv.identity,k=pv.identity,q=String;c.transform=function(o,n){l=function(m){return j?-o(-m):o(m)};k=function(m){return j?-n(-m):n(m)};f=d.map(l);return this};c.domain=function(o,n,m){if(arguments.length){var r;if(o instanceof Array){if(arguments.length< 50 2)n=pv.identity;if(arguments.length<3)m=n;r=o.length&&n(o[0]);d=o.length?[pv.min(o,n),pv.max(o,m)]:[]}else{r=o;d=Array.prototype.slice.call(arguments).map(Number)}if(d.length){if(d.length==1)d=[d[0],d[0]]}else d=[-Infinity,Infinity];j=(d[0]||d[d.length-1])<0;f=d.map(l);i=r instanceof Date?b:Number;return this}return d.map(i)};c.range=function(){if(arguments.length){g=Array.prototype.slice.call(arguments);if(g.length){if(g.length==1)g=[g[0],g[0]]}else g=[-Infinity,Infinity];h=[];for(var o=0;o<g.length- 51 1;o++)h.push(pv.Scale.interpolator(g[o],g[o+1]));return this}return g};c.invert=function(o){var n=pv.search(g,o);if(n<0)n=-n-2;n=Math.max(0,Math.min(h.length-1,n));return i(k(f[n]+(o-g[n])/(g[n+1]-g[n])*(f[n+1]-f[n])))};c.ticks=function(o){var n=d[0],m=d[d.length-1],r=m<n,s=r?m:n;m=r?n:m;var u=m-s;if(!u||!isFinite(u)){if(i==b)q=pv.Format.date("%x");return[i(s)]}if(i==b){function x(w,y){switch(y){case 31536E6:w.setMonth(0);case 2592E6:w.setDate(1);case 6048E5:y==6048E5&&w.setDate(w.getDate()-w.getDay()); 52 case 864E5:w.setHours(0);case 36E5:w.setMinutes(0);case 6E4:w.setSeconds(0);case 1E3:w.setMilliseconds(0)}}var t,p,v=1;if(u>=94608E6){n=31536E6;t="%Y";p=function(w){w.setFullYear(w.getFullYear()+v)}}else if(u>=7776E6){n=2592E6;t="%m/%Y";p=function(w){w.setMonth(w.getMonth()+v)}}else if(u>=18144E5){n=6048E5;t="%m/%d";p=function(w){w.setDate(w.getDate()+7*v)}}else if(u>=2592E5){n=864E5;t="%m/%d";p=function(w){w.setDate(w.getDate()+v)}}else if(u>=108E5){n=36E5;t="%I:%M %p";p=function(w){w.setHours(w.getHours()+ 53 v)}}else if(u>=18E4){n=6E4;t="%I:%M %p";p=function(w){w.setMinutes(w.getMinutes()+v)}}else if(u>=3E3){n=1E3;t="%I:%M:%S";p=function(w){w.setSeconds(w.getSeconds()+v)}}else{n=1;t="%S.%Qs";p=function(w){w.setTime(w.getTime()+v)}}q=pv.Format.date(t);s=new Date(s);t=[];x(s,n);u=u/n;if(u>10)switch(n){case 36E5:v=u>20?6:3;s.setHours(Math.floor(s.getHours()/v)*v);break;case 2592E6:v=3;s.setMonth(Math.floor(s.getMonth()/v)*v);break;case 6E4:v=u>30?15:u>15?10:5;s.setMinutes(Math.floor(s.getMinutes()/v)*v); 54 break;case 1E3:v=u>90?15:u>60?10:5;s.setSeconds(Math.floor(s.getSeconds()/v)*v);break;case 1:v=u>1E3?250:u>200?100:u>100?50:u>50?25:5;s.setMilliseconds(Math.floor(s.getMilliseconds()/v)*v);break;default:v=pv.logCeil(u/15,10);if(u/v<2)v/=5;else if(u/v<5)v/=2;s.setFullYear(Math.floor(s.getFullYear()/v)*v);break}for(;;){p(s);if(s>m)break;t.push(new Date(s))}return r?t.reverse():t}arguments.length||(o=10);v=pv.logFloor(u/o,10);n=o/(u/v);if(n<=0.15)v*=10;else if(n<=0.35)v*=5;else if(n<=0.75)v*=2;n=Math.ceil(s/ 55 v)*v;m=Math.floor(m/v)*v;q=pv.Format.number().fractionDigits(Math.max(0,-Math.floor(pv.log(v,10)+0.01)));m=pv.range(n,m+v,v);return r?m.reverse():m};c.tickFormat=function(o){return q(o)};c.nice=function(){if(d.length!=2)return this;var o=d[0],n=d[d.length-1],m=n<o,r=m?n:o;o=m?o:n;n=o-r;if(!n||!isFinite(n))return this;n=Math.pow(10,Math.round(Math.log(n)/Math.log(10))-1);d=[Math.floor(r/n)*n,Math.ceil(o/n)*n];m&&d.reverse();f=d.map(l);return this};c.by=function(o){function n(){return c(o.apply(this, 56 arguments))}for(var m in c)n[m]=c[m];return n};c.domain.apply(c,arguments);return c};pv.Scale.linear=function(){var b=pv.Scale.quantitative();b.domain.apply(b,arguments);return b}; 57 pv.Scale.log=function(){var b=pv.Scale.quantitative(1,10),c,d,f=function(h){return Math.log(h)/d},g=function(h){return Math.pow(c,h)};b.ticks=function(){var h=b.domain(),i=h[0]<0,j=Math.floor(i?-f(-h[0]):f(h[0])),l=Math.ceil(i?-f(-h[1]):f(h[1])),k=[];if(i)for(k.push(-g(-j));j++<l;)for(i=c-1;i>0;i--)k.push(-g(-j)*i);else{for(;j<l;j++)for(i=1;i<c;i++)k.push(g(j)*i);k.push(g(j))}for(j=0;k[j]<h[0];j++);for(l=k.length;k[l-1]>h[1];l--);return k.slice(j,l)};b.tickFormat=function(h){return h.toPrecision(1)}; 58 b.nice=function(){var h=b.domain();return b.domain(pv.logFloor(h[0],c),pv.logCeil(h[1],c))};b.base=function(h){if(arguments.length){c=Number(h);d=Math.log(c);b.transform(f,g);return this}return c};b.domain.apply(b,arguments);return b.base(10)};pv.Scale.root=function(){var b=pv.Scale.quantitative();b.power=function(c){if(arguments.length){var d=Number(c),f=1/d;b.transform(function(g){return Math.pow(g,f)},function(g){return Math.pow(g,d)});return this}return d};b.domain.apply(b,arguments);return b.power(2)}; 59 pv.Scale.ordinal=function(){function b(g){g in d||(d[g]=c.push(g)-1);return f[d[g]%f.length]}var c=[],d={},f=[];b.domain=function(g,h){if(arguments.length){g=g instanceof Array?arguments.length>1?pv.map(g,h):g:Array.prototype.slice.call(arguments);c=[];for(var i={},j=0;j<g.length;j++){var l=g[j];if(!(l in i)){i[l]=true;c.push(l)}}d=pv.numerate(c);return this}return c};b.range=function(g,h){if(arguments.length){f=g instanceof Array?arguments.length>1?pv.map(g,h):g:Array.prototype.slice.call(arguments); 60 if(typeof f[0]=="string")f=f.map(pv.color);return this}return f};b.split=function(g,h){var i=(h-g)/this.domain().length;f=pv.range(g+i/2,h,i);return this};b.splitFlush=function(g,h){var i=this.domain().length,j=(h-g)/(i-1);f=i==1?[(g+h)/2]:pv.range(g,h+j/2,j);return this};b.splitBanded=function(g,h,i){if(arguments.length<3)i=1;if(i<0){var j=this.domain().length;j=(h-g- -i*j)/(j+1);f=pv.range(g+j,h,j-i);f.band=-i}else{j=(h-g)/(this.domain().length+(1-i));f=pv.range(g+j*(1-i),h,j);f.band=j*i}return this}; 61 b.by=function(g){function h(){return b(g.apply(this,arguments))}for(var i in b)h[i]=b[i];return h};b.domain.apply(b,arguments);return b}; 62 pv.Scale.quantile=function(){function b(i){return h(Math.max(0,Math.min(d,pv.search.index(f,i)-1))/d)}var c=-1,d=-1,f=[],g=[],h=pv.Scale.linear();b.quantiles=function(i){if(arguments.length){c=Number(i);if(c<0){f=[g[0]].concat(g);d=g.length-1}else{f=[];f[0]=g[0];for(var j=1;j<=c;j++)f[j]=g[~~(j*(g.length-1)/c)];d=c-1}return this}return f};b.domain=function(i,j){if(arguments.length){g=i instanceof Array?pv.map(i,j):Array.prototype.slice.call(arguments);g.sort(pv.naturalOrder);b.quantiles(c);return this}return g}; 63 b.range=function(){if(arguments.length){h.range.apply(h,arguments);return this}return h.range()};b.by=function(i){function j(){return b(i.apply(this,arguments))}for(var l in b)j[l]=b[l];return j};b.domain.apply(b,arguments);return b}; 64 pv.histogram=function(b,c){var d=true;return{bins:function(f){var g=pv.map(b,c),h=[];arguments.length||(f=pv.Scale.linear(g).ticks());for(var i=0;i<f.length-1;i++){var j=h[i]=[];j.x=f[i];j.dx=f[i+1]-f[i];j.y=0}for(i=0;i<g.length;i++){j=pv.search.index(f,g[i])-1;j=h[Math.max(0,Math.min(h.length-1,j))];j.y++;j.push(b[i])}if(!d)for(i=0;i<h.length;i++)h[i].y/=g.length;return h},frequency:function(f){if(arguments.length){d=Boolean(f);return this}return d}}}; 65 pv.color=function(b){if(b.rgb)return b.rgb();var c=/([a-z]+)\((.*)\)/i.exec(b);if(c){var d=c[2].split(","),f=1;switch(c[1]){case "hsla":case "rgba":f=parseFloat(d[3]);if(!f)return pv.Color.transparent;break}switch(c[1]){case "hsla":case "hsl":b=parseFloat(d[0]);var g=parseFloat(d[1])/100;d=parseFloat(d[2])/100;return(new pv.Color.Hsl(b,g,d,f)).rgb();case "rgba":case "rgb":function h(l){var k=parseFloat(l);return l[l.length-1]=="%"?Math.round(k*2.55):k}g=h(d[0]);var i=h(d[1]),j=h(d[2]);return pv.rgb(g, 66 i,j,f)}}if(f=pv.Color.names[b])return f;if(b.charAt(0)=="#"){if(b.length==4){g=b.charAt(1);g+=g;i=b.charAt(2);i+=i;j=b.charAt(3);j+=j}else if(b.length==7){g=b.substring(1,3);i=b.substring(3,5);j=b.substring(5,7)}return pv.rgb(parseInt(g,16),parseInt(i,16),parseInt(j,16),1)}return new pv.Color(b,1)};pv.Color=function(b,c){this.color=b;this.opacity=c};pv.Color.prototype.brighter=function(b){return this.rgb().brighter(b)};pv.Color.prototype.darker=function(b){return this.rgb().darker(b)}; 67 pv.rgb=function(b,c,d,f){return new pv.Color.Rgb(b,c,d,arguments.length==4?f:1)};pv.Color.Rgb=function(b,c,d,f){pv.Color.call(this,f?"rgb("+b+","+c+","+d+")":"none",f);this.r=b;this.g=c;this.b=d;this.a=f};pv.Color.Rgb.prototype=pv.extend(pv.Color);a=pv.Color.Rgb.prototype;a.red=function(b){return pv.rgb(b,this.g,this.b,this.a)};a.green=function(b){return pv.rgb(this.r,b,this.b,this.a)};a.blue=function(b){return pv.rgb(this.r,this.g,b,this.a)}; 68 a.alpha=function(b){return pv.rgb(this.r,this.g,this.b,b)};a.rgb=function(){return this};a.brighter=function(b){b=Math.pow(0.7,arguments.length?b:1);var c=this.r,d=this.g,f=this.b;if(!c&&!d&&!f)return pv.rgb(30,30,30,this.a);if(c&&c<30)c=30;if(d&&d<30)d=30;if(f&&f<30)f=30;return pv.rgb(Math.min(255,Math.floor(c/b)),Math.min(255,Math.floor(d/b)),Math.min(255,Math.floor(f/b)),this.a)}; 69 a.darker=function(b){b=Math.pow(0.7,arguments.length?b:1);return pv.rgb(Math.max(0,Math.floor(b*this.r)),Math.max(0,Math.floor(b*this.g)),Math.max(0,Math.floor(b*this.b)),this.a)};pv.hsl=function(b,c,d,f){return new pv.Color.Hsl(b,c,d,arguments.length==4?f:1)};pv.Color.Hsl=function(b,c,d,f){pv.Color.call(this,"hsl("+b+","+c*100+"%,"+d*100+"%)",f);this.h=b;this.s=c;this.l=d;this.a=f};pv.Color.Hsl.prototype=pv.extend(pv.Color);a=pv.Color.Hsl.prototype; 70 a.hue=function(b){return pv.hsl(b,this.s,this.l,this.a)};a.saturation=function(b){return pv.hsl(this.h,b,this.l,this.a)};a.lightness=function(b){return pv.hsl(this.h,this.s,b,this.a)};a.alpha=function(b){return pv.hsl(this.h,this.s,this.l,b)}; 71 a.rgb=function(){function b(j){if(j>360)j-=360;else if(j<0)j+=360;if(j<60)return i+(h-i)*j/60;if(j<180)return h;if(j<240)return i+(h-i)*(240-j)/60;return i}function c(j){return Math.round(b(j)*255)}var d=this.h,f=this.s,g=this.l;d%=360;if(d<0)d+=360;f=Math.max(0,Math.min(f,1));g=Math.max(0,Math.min(g,1));var h=g<=0.5?g*(1+f):g+f-g*f,i=2*g-h;return pv.rgb(c(d+120),c(d),c(d-120),this.a)}; 72 pv.Color.names={aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400", 73 darkgrey:"#a9a9a9",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc", 74 ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000",greenyellow:"#adff2f",grey:"#808080",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgreen:"#90ee90",lightgrey:"#d3d3d3",lightpink:"#ffb6c1",lightsalmon:"#ffa07a", 75 lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370db",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1", 76 moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#db7093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57", 77 seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32",transparent:pv.Color.transparent=pv.rgb(0,0,0,0)};(function(){var b=pv.Color.names;for(var c in b)b[c]=pv.color(b[c])})(); 78 pv.colors=function(){var b=pv.Scale.ordinal();b.range.apply(b,arguments);return b};pv.Colors={};pv.Colors.category10=function(){var b=pv.colors("#1f77b4","#ff7f0e","#2ca02c","#d62728","#9467bd","#8c564b","#e377c2","#7f7f7f","#bcbd22","#17becf");b.domain.apply(b,arguments);return b}; 79 pv.Colors.category20=function(){var b=pv.colors("#1f77b4","#aec7e8","#ff7f0e","#ffbb78","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5","#8c564b","#c49c94","#e377c2","#f7b6d2","#7f7f7f","#c7c7c7","#bcbd22","#dbdb8d","#17becf","#9edae5");b.domain.apply(b,arguments);return b}; 80 pv.Colors.category19=function(){var b=pv.colors("#9c9ede","#7375b5","#4a5584","#cedb9c","#b5cf6b","#8ca252","#637939","#e7cb94","#e7ba52","#bd9e39","#8c6d31","#e7969c","#d6616b","#ad494a","#843c39","#de9ed6","#ce6dbd","#a55194","#7b4173");b.domain.apply(b,arguments);return b};pv.ramp=function(){var b=pv.Scale.linear();b.range.apply(b,arguments);return b}; 81 pv.Scene=pv.SvgScene={svg:"http://www.w3.org/2000/svg",xmlns:"http://www.w3.org/2000/xmlns",xlink:"http://www.w3.org/1999/xlink",xhtml:"http://www.w3.org/1999/xhtml",scale:1,events:["DOMMouseScroll","mousewheel","mousedown","mouseup","mouseover","mouseout","mousemove","click","dblclick"],implicit:{svg:{"shape-rendering":"auto","pointer-events":"painted",x:0,y:0,dy:0,"text-anchor":"start",transform:"translate(0,0)",fill:"none","fill-opacity":1,stroke:"none","stroke-opacity":1,"stroke-width":1.5,"stroke-linejoin":"miter"}, 82 css:{font:"10px sans-serif"}}};pv.SvgScene.updateAll=function(b){if(b.length&&b[0].reverse&&b.type!="line"&&b.type!="area"){for(var c=pv.extend(b),d=0,f=b.length-1;f>=0;d++,f--)c[d]=b[f];b=c}this.removeSiblings(this[b.type](b))};pv.SvgScene.create=function(b){return document.createElementNS(this.svg,b)}; 83 pv.SvgScene.expect=function(b,c,d,f){if(b){if(b.tagName=="a")b=b.firstChild;if(b.tagName!=c){c=this.create(c);b.parentNode.replaceChild(c,b);b=c}}else b=this.create(c);for(var g in d){c=d[g];if(c==this.implicit.svg[g])c=null;c==null?b.removeAttribute(g):b.setAttribute(g,c)}for(g in f){c=f[g];if(c==this.implicit.css[g])c=null;if(c==null)b.style.removeProperty(g);else b.style[g]=c}return b}; 84 pv.SvgScene.append=function(b,c,d){b.$scene={scenes:c,index:d};b=this.title(b,c[d]);b.parentNode||c.$g.appendChild(b);return b.nextSibling};pv.SvgScene.title=function(b,c){var d=b.parentNode;if(d&&d.tagName!="a")d=null;if(c.title){if(!d){d=this.create("a");b.parentNode&&b.parentNode.replaceChild(d,b);d.appendChild(b)}d.setAttributeNS(this.xlink,"title",c.title);return d}d&&d.parentNode.replaceChild(b,d);return b}; 85 pv.SvgScene.dispatch=pv.listener(function(b){var c=b.target.$scene;if(c){var d=b.type;switch(d){case "DOMMouseScroll":d="mousewheel";b.wheel=-480*b.detail;break;case "mousewheel":b.wheel=(window.opera?12:1)*b.wheelDelta;break}pv.Mark.dispatch(d,c.scenes,c.index)&&b.preventDefault()}});pv.SvgScene.removeSiblings=function(b){for(;b;){var c=b.nextSibling;b.parentNode.removeChild(b);b=c}};pv.SvgScene.undefined=function(){}; 86 pv.SvgScene.pathBasis=function(){function b(f,g,h,i,j){return{x:f[0]*g.left+f[1]*h.left+f[2]*i.left+f[3]*j.left,y:f[0]*g.top+f[1]*h.top+f[2]*i.top+f[3]*j.top}}var c=[[1/6,2/3,1/6,0],[0,2/3,1/3,0],[0,1/3,2/3,0],[0,1/6,2/3,1/6]],d=function(f,g,h,i){var j=b(c[1],f,g,h,i),l=b(c[2],f,g,h,i);f=b(c[3],f,g,h,i);return"C"+j.x+","+j.y+","+l.x+","+l.y+","+f.x+","+f.y};d.segment=function(f,g,h,i){var j=b(c[0],f,g,h,i),l=b(c[1],f,g,h,i),k=b(c[2],f,g,h,i);f=b(c[3],f,g,h,i);return"M"+j.x+","+j.y+"C"+l.x+","+l.y+ 87 ","+k.x+","+k.y+","+f.x+","+f.y};return d}();pv.SvgScene.curveBasis=function(b){if(b.length<=2)return"";var c="",d=b[0],f=d,g=d,h=b[1];c+=this.pathBasis(d,f,g,h);for(var i=2;i<b.length;i++){d=f;f=g;g=h;h=b[i];c+=this.pathBasis(d,f,g,h)}c+=this.pathBasis(f,g,h,h);c+=this.pathBasis(g,h,h,h);return c}; 88 pv.SvgScene.curveBasisSegments=function(b){if(b.length<=2)return"";var c=[],d=b[0],f=d,g=d,h=b[1],i=this.pathBasis.segment(d,f,g,h);d=f;f=g;g=h;h=b[2];c.push(i+this.pathBasis(d,f,g,h));for(i=3;i<b.length;i++){d=f;f=g;g=h;h=b[i];c.push(this.pathBasis.segment(d,f,g,h))}c.push(this.pathBasis.segment(f,g,h,h)+this.pathBasis(g,h,h,h));return c}; 89 pv.SvgScene.curveHermite=function(b,c){if(c.length<1||b.length!=c.length&&b.length!=c.length+2)return"";var d=b.length!=c.length,f="",g=b[0],h=b[1],i=c[0],j=i,l=1;if(d){f+="Q"+(h.left-i.x*2/3)+","+(h.top-i.y*2/3)+","+h.left+","+h.top;g=b[1];l=2}if(c.length>1){j=c[1];h=b[l];l++;f+="C"+(g.left+i.x)+","+(g.top+i.y)+","+(h.left-j.x)+","+(h.top-j.y)+","+h.left+","+h.top;for(g=2;g<c.length;g++,l++){h=b[l];j=c[g];f+="S"+(h.left-j.x)+","+(h.top-j.y)+","+h.left+","+h.top}}if(d){b=b[l];f+="Q"+(h.left+j.x*2/ 90 3)+","+(h.top+j.y*2/3)+","+b.left+","+b.top}return f}; 91 pv.SvgScene.curveHermiteSegments=function(b,c){if(c.length<1||b.length!=c.length&&b.length!=c.length+2)return[];var d=b.length!=c.length,f=[],g=b[0],h=g,i=c[0],j=i,l=1;if(d){h=b[1];f.push("M"+g.left+","+g.top+"Q"+(h.left-j.x*2/3)+","+(h.top-j.y*2/3)+","+h.left+","+h.top);l=2}for(var k=1;k<c.length;k++,l++){g=h;i=j;h=b[l];j=c[k];f.push("M"+g.left+","+g.top+"C"+(g.left+i.x)+","+(g.top+i.y)+","+(h.left-j.x)+","+(h.top-j.y)+","+h.left+","+h.top)}if(d){b=b[l];f.push("M"+h.left+","+h.top+"Q"+(h.left+j.x* 92 2/3)+","+(h.top+j.y*2/3)+","+b.left+","+b.top)}return f};pv.SvgScene.cardinalTangents=function(b,c){var d=[];c=(1-c)/2;for(var f=b[0],g=b[1],h=b[2],i=3;i<b.length;i++){d.push({x:c*(h.left-f.left),y:c*(h.top-f.top)});f=g;g=h;h=b[i]}d.push({x:c*(h.left-f.left),y:c*(h.top-f.top)});return d};pv.SvgScene.curveCardinal=function(b,c){if(b.length<=2)return"";return this.curveHermite(b,this.cardinalTangents(b,c))}; 93 pv.SvgScene.curveCardinalSegments=function(b,c){if(b.length<=2)return"";return this.curveHermiteSegments(b,this.cardinalTangents(b,c))}; 94 pv.SvgScene.monotoneTangents=function(b){var c=[],d=[],f=[],g=[],h=0;for(h=0;h<b.length-1;h++)d[h]=(b[h+1].top-b[h].top)/(b[h+1].left-b[h].left);f[0]=d[0];g[0]=b[1].left-b[0].left;for(h=1;h<b.length-1;h++){f[h]=(d[h-1]+d[h])/2;g[h]=(b[h+1].left-b[h-1].left)/2}f[h]=d[h-1];g[h]=b[h].left-b[h-1].left;for(h=0;h<b.length-1;h++)if(d[h]==0){f[h]=0;f[h+1]=0}for(h=0;h<b.length-1;h++)if(!(Math.abs(f[h])<1.0E-5||Math.abs(f[h+1])<1.0E-5)){var i=f[h]/d[h],j=f[h+1]/d[h],l=i*i+j*j;if(l>9){l=3/Math.sqrt(l);f[h]= 95 l*i*d[h];f[h+1]=l*j*d[h]}}for(h=0;h<b.length;h++){d=1+f[h]*f[h];c.push({x:g[h]/3/d,y:f[h]*g[h]/3/d})}return c};pv.SvgScene.curveMonotone=function(b){if(b.length<=2)return"";return this.curveHermite(b,this.monotoneTangents(b))};pv.SvgScene.curveMonotoneSegments=function(b){if(b.length<=2)return"";return this.curveHermiteSegments(b,this.monotoneTangents(b))}; 96 pv.SvgScene.area=function(b){function c(o,n){for(var m=[],r=[],s=n;o<=s;o++,n--){var u=b[o],x=b[n];u=u.left+","+u.top;x=x.left+x.width+","+(x.top+x.height);if(o<s){var t=b[o+1],p=b[n-1];switch(g.interpolate){case "step-before":u+="V"+t.top;x+="H"+(p.left+p.width);break;case "step-after":u+="H"+t.left;x+="V"+(p.top+p.height);break}}m.push(u);r.push(x)}return m.concat(r).join("L")}function d(o,n){for(var m=[],r=[],s=n;o<=s;o++,n--){var u=b[n];m.push(b[o]);r.push({left:u.left+u.width,top:u.top+u.height})}if(g.interpolate== 97 "basis"){o=pv.SvgScene.curveBasis(m);n=pv.SvgScene.curveBasis(r)}else if(g.interpolate=="cardinal"){o=pv.SvgScene.curveCardinal(m,g.tension);n=pv.SvgScene.curveCardinal(r,g.tension)}else{o=pv.SvgScene.curveMonotone(m);n=pv.SvgScene.curveMonotone(r)}return m[0].left+","+m[0].top+o+"L"+r[0].left+","+r[0].top+n}var f=b.$g.firstChild;if(!b.length)return f;var g=b[0];if(g.segmented)return this.areaSegment(b);if(!g.visible)return f;var h=g.fillStyle,i=g.strokeStyle;if(!h.opacity&&!i.opacity)return f;for(var j= 98 [],l,k=0;k<b.length;k++){l=b[k];if(l.width||l.height){for(var q=k+1;q<b.length;q++){l=b[q];if(!l.width&&!l.height)break}k&&g.interpolate!="step-after"&&k--;q<b.length&&g.interpolate!="step-before"&&q++;j.push((q-k>2&&(g.interpolate=="basis"||g.interpolate=="cardinal"||g.interpolate=="monotone")?d:c)(k,q-1));k=q-1}}if(!j.length)return f;f=this.expect(f,"path",{"shape-rendering":g.antialias?null:"crispEdges","pointer-events":g.events,cursor:g.cursor,d:"M"+j.join("ZM")+"Z",fill:h.color,"fill-opacity":h.opacity|| 99 null,stroke:i.color,"stroke-opacity":i.opacity||null,"stroke-width":i.opacity?g.lineWidth/this.scale:null});return this.append(f,b,0)}; 100 pv.SvgScene.areaSegment=function(b){var c=b.$g.firstChild,d=b[0],f,g;if(d.interpolate=="basis"||d.interpolate=="cardinal"||d.interpolate=="monotone"){f=[];g=[];for(var h=0,i=b.length;h<i;h++){var j=b[i-h-1];f.push(b[h]);g.push({left:j.left+j.width,top:j.top+j.height})}if(d.interpolate=="basis"){f=this.curveBasisSegments(f);g=this.curveBasisSegments(g)}else if(d.interpolate=="cardinal"){f=this.curveCardinalSegments(f,d.tension);g=this.curveCardinalSegments(g,d.tension)}else{f=this.curveMonotoneSegments(f); 101 g=this.curveMonotoneSegments(g)}}h=0;for(i=b.length-1;h<i;h++){d=b[h];var l=b[h+1];if(d.visible&&l.visible){var k=d.fillStyle,q=d.strokeStyle;if(k.opacity||q.opacity){if(f){j=f[h];l="L"+g[i-h-1].substr(1);j=j+l+"Z"}else{var o=d;j=l;switch(d.interpolate){case "step-before":o=l;break;case "step-after":j=d;break}j="M"+d.left+","+o.top+"L"+l.left+","+j.top+"L"+(l.left+l.width)+","+(j.top+j.height)+"L"+(d.left+d.width)+","+(o.top+o.height)+"Z"}c=this.expect(c,"path",{"shape-rendering":d.antialias?null: 102 "crispEdges","pointer-events":d.events,cursor:d.cursor,d:j,fill:k.color,"fill-opacity":k.opacity||null,stroke:q.color,"stroke-opacity":q.opacity||null,"stroke-width":q.opacity?d.lineWidth/this.scale:null});c=this.append(c,b,h)}}}return c}; 103 pv.SvgScene.bar=function(b){for(var c=b.$g.firstChild,d=0;d<b.length;d++){var f=b[d];if(f.visible){var g=f.fillStyle,h=f.strokeStyle;if(g.opacity||h.opacity){c=this.expect(c,"rect",{"shape-rendering":f.antialias?null:"crispEdges","pointer-events":f.events,cursor:f.cursor,x:f.left,y:f.top,width:Math.max(1.0E-10,f.width),height:Math.max(1.0E-10,f.height),fill:g.color,"fill-opacity":g.opacity||null,stroke:h.color,"stroke-opacity":h.opacity||null,"stroke-width":h.opacity?f.lineWidth/this.scale:null}); 104 c=this.append(c,b,d)}}}return c}; 105 pv.SvgScene.dot=function(b){for(var c=b.$g.firstChild,d=0;d<b.length;d++){var f=b[d];if(f.visible){var g=f.fillStyle,h=f.strokeStyle;if(g.opacity||h.opacity){var i=f.radius,j=null;switch(f.shape){case "cross":j="M"+-i+","+-i+"L"+i+","+i+"M"+i+","+-i+"L"+-i+","+i;break;case "triangle":j=i;var l=i*1.1547;j="M0,"+j+"L"+l+","+-j+" "+-l+","+-j+"Z";break;case "diamond":i*=Math.SQRT2;j="M0,"+-i+"L"+i+",0 0,"+i+" "+-i+",0Z";break;case "square":j="M"+-i+","+-i+"L"+i+","+-i+" "+i+","+i+" "+-i+","+i+"Z";break; 106 case "tick":j="M0,0L0,"+-f.size;break;case "bar":j="M0,"+f.size/2+"L0,"+-(f.size/2);break}g={"shape-rendering":f.antialias?null:"crispEdges","pointer-events":f.events,cursor:f.cursor,fill:g.color,"fill-opacity":g.opacity||null,stroke:h.color,"stroke-opacity":h.opacity||null,"stroke-width":h.opacity?f.lineWidth/this.scale:null};if(j){g.transform="translate("+f.left+","+f.top+")";if(f.angle)g.transform+=" rotate("+180*f.angle/Math.PI+")";g.d=j;c=this.expect(c,"path",g)}else{g.cx=f.left;g.cy=f.top;g.r= 107 i;c=this.expect(c,"circle",g)}c=this.append(c,b,d)}}}return c}; 108 pv.SvgScene.image=function(b){for(var c=b.$g.firstChild,d=0;d<b.length;d++){var f=b[d];if(f.visible){c=this.fill(c,b,d);if(f.image){c=this.expect(c,"foreignObject",{cursor:f.cursor,x:f.left,y:f.top,width:f.width,height:f.height});var g=c.firstChild||c.appendChild(document.createElementNS(this.xhtml,"canvas"));g.$scene={scenes:b,index:d};g.style.width=f.width;g.style.height=f.height;g.width=f.imageWidth;g.height=f.imageHeight;g.getContext("2d").putImageData(f.image,0,0)}else{c=this.expect(c,"image", 109 {preserveAspectRatio:"none",cursor:f.cursor,x:f.left,y:f.top,width:f.width,height:f.height});c.setAttributeNS(this.xlink,"href",f.url)}c=this.append(c,b,d);c=this.stroke(c,b,d)}}return c}; 110 pv.SvgScene.label=function(b){for(var c=b.$g.firstChild,d=0;d<b.length;d++){var f=b[d];if(f.visible){var g=f.textStyle;if(g.opacity&&f.text){var h=0,i=0,j=0,l="start";switch(f.textBaseline){case "middle":j=".35em";break;case "top":j=".71em";i=f.textMargin;break;case "bottom":i="-"+f.textMargin;break}switch(f.textAlign){case "right":l="end";h="-"+f.textMargin;break;case "center":l="middle";break;case "left":h=f.textMargin;break}c=this.expect(c,"text",{"pointer-events":f.events,cursor:f.cursor,x:h, 111 y:i,dy:j,transform:"translate("+f.left+","+f.top+")"+(f.textAngle?" rotate("+180*f.textAngle/Math.PI+")":"")+(this.scale!=1?" scale("+1/this.scale+")":""),fill:g.color,"fill-opacity":g.opacity||null,"text-anchor":l},{font:f.font,"text-shadow":f.textShadow,"text-decoration":f.textDecoration});if(c.firstChild)c.firstChild.nodeValue=f.text;else c.appendChild(document.createTextNode(f.text));c=this.append(c,b,d)}}}return c}; 112 pv.SvgScene.line=function(b){var c=b.$g.firstChild;if(b.length<2)return c;var d=b[0];if(d.segmented)return this.lineSegment(b);if(!d.visible)return c;var f=d.fillStyle,g=d.strokeStyle;if(!f.opacity&&!g.opacity)return c;var h="M"+d.left+","+d.top;if(b.length>2&&(d.interpolate=="basis"||d.interpolate=="cardinal"||d.interpolate=="monotone"))switch(d.interpolate){case "basis":h+=this.curveBasis(b);break;case "cardinal":h+=this.curveCardinal(b,d.tension);break;case "monotone":h+=this.curveMonotone(b); 113 break}else for(var i=1;i<b.length;i++)h+=this.pathSegment(b[i-1],b[i]);c=this.expect(c,"path",{"shape-rendering":d.antialias?null:"crispEdges","pointer-events":d.events,cursor:d.cursor,d:h,fill:f.color,"fill-opacity":f.opacity||null,stroke:g.color,"stroke-opacity":g.opacity||null,"stroke-width":g.opacity?d.lineWidth/this.scale:null,"stroke-linejoin":d.lineJoin});return this.append(c,b,0)}; 114 pv.SvgScene.lineSegment=function(b){var c=b.$g.firstChild,d=b[0],f;switch(d.interpolate){case "basis":f=this.curveBasisSegments(b);break;case "cardinal":f=this.curveCardinalSegments(b,d.tension);break;case "monotone":f=this.curveMonotoneSegments(b);break}d=0;for(var g=b.length-1;d<g;d++){var h=b[d],i=b[d+1];if(h.visible&&i.visible){var j=h.strokeStyle,l=pv.Color.transparent;if(j.opacity){if(h.interpolate=="linear"&&h.lineJoin=="miter"){l=j;j=pv.Color.transparent;i=this.pathJoin(b[d-1],h,i,b[d+2])}else i= 115 f?f[d]:"M"+h.left+","+h.top+this.pathSegment(h,i);c=this.expect(c,"path",{"shape-rendering":h.antialias?null:"crispEdges","pointer-events":h.events,cursor:h.cursor,d:i,fill:l.color,"fill-opacity":l.opacity||null,stroke:j.color,"stroke-opacity":j.opacity||null,"stroke-width":j.opacity?h.lineWidth/this.scale:null,"stroke-linejoin":h.lineJoin});c=this.append(c,b,d)}}}return c}; 116 pv.SvgScene.pathSegment=function(b,c){var d=1;switch(b.interpolate){case "polar-reverse":d=0;case "polar":var f=c.left-b.left,g=c.top-b.top;b=1-b.eccentricity;f=Math.sqrt(f*f+g*g)/(2*b);if(b<=0||b>1)break;return"A"+f+","+f+" 0 0,"+d+" "+c.left+","+c.top;case "step-before":return"V"+c.top+"H"+c.left;case "step-after":return"H"+c.left+"V"+c.top}return"L"+c.left+","+c.top};pv.SvgScene.lineIntersect=function(b,c,d,f){return b.plus(c.times(d.minus(b).dot(f.perp())/c.dot(f.perp())))}; 117 pv.SvgScene.pathJoin=function(b,c,d,f){var g=pv.vector(c.left,c.top);d=pv.vector(d.left,d.top);var h=d.minus(g),i=h.perp().norm(),j=i.times(c.lineWidth/(2*this.scale));c=g.plus(j);var l=d.plus(j),k=d.minus(j);j=g.minus(j);if(b&&b.visible){b=g.minus(b.left,b.top).perp().norm().plus(i);j=this.lineIntersect(g,b,j,h);c=this.lineIntersect(g,b,c,h)}if(f&&f.visible){f=pv.vector(f.left,f.top).minus(d).perp().norm().plus(i);k=this.lineIntersect(d,f,k,h);l=this.lineIntersect(d,f,l,h)}return"M"+c.x+","+c.y+ 118 "L"+l.x+","+l.y+" "+k.x+","+k.y+" "+j.x+","+j.y}; 119 pv.SvgScene.panel=function(b){for(var c=b.$g,d=c&&c.firstChild,f=0;f<b.length;f++){var g=b[f];if(g.visible){if(!b.parent){g.canvas.style.display="inline-block";if(c&&c.parentNode!=g.canvas)d=(c=g.canvas.firstChild)&&c.firstChild;if(!c){c=g.canvas.appendChild(this.create("svg"));c.setAttribute("font-size","10px");c.setAttribute("font-family","sans-serif");c.setAttribute("fill","none");c.setAttribute("stroke","none");c.setAttribute("stroke-width",1.5);for(var h=0;h<this.events.length;h++)c.addEventListener(this.events[h], 120 this.dispatch,false);d=c.firstChild}b.$g=c;c.setAttribute("width",g.width+g.left+g.right);c.setAttribute("height",g.height+g.top+g.bottom)}if(g.overflow=="hidden"){h=pv.id().toString(36);var i=this.expect(d,"g",{"clip-path":"url(#"+h+")"});i.parentNode||c.appendChild(i);b.$g=c=i;d=i.firstChild;d=this.expect(d,"clipPath",{id:h});h=d.firstChild||d.appendChild(this.create("rect"));h.setAttribute("x",g.left);h.setAttribute("y",g.top);h.setAttribute("width",g.width);h.setAttribute("height",g.height);d.parentNode|| 121 c.appendChild(d);d=d.nextSibling}d=this.fill(d,b,f);var j=this.scale,l=g.transform,k=g.left+l.x,q=g.top+l.y;this.scale*=l.k;for(h=0;h<g.children.length;h++){g.children[h].$g=d=this.expect(d,"g",{transform:"translate("+k+","+q+")"+(l.k!=1?" scale("+l.k+")":"")});this.updateAll(g.children[h]);d.parentNode||c.appendChild(d);d=d.nextSibling}this.scale=j;d=this.stroke(d,b,f);if(g.overflow=="hidden"){b.$g=c=i.parentNode;d=i.nextSibling}}}return d}; 122 pv.SvgScene.fill=function(b,c,d){var f=c[d],g=f.fillStyle;if(g.opacity||f.events=="all"){b=this.expect(b,"rect",{"shape-rendering":f.antialias?null:"crispEdges","pointer-events":f.events,cursor:f.cursor,x:f.left,y:f.top,width:f.width,height:f.height,fill:g.color,"fill-opacity":g.opacity,stroke:null});b=this.append(b,c,d)}return b}; 123 pv.SvgScene.stroke=function(b,c,d){var f=c[d],g=f.strokeStyle;if(g.opacity||f.events=="all"){b=this.expect(b,"rect",{"shape-rendering":f.antialias?null:"crispEdges","pointer-events":f.events=="all"?"stroke":f.events,cursor:f.cursor,x:f.left,y:f.top,width:Math.max(1.0E-10,f.width),height:Math.max(1.0E-10,f.height),fill:null,stroke:g.color,"stroke-opacity":g.opacity,"stroke-width":f.lineWidth/this.scale});b=this.append(b,c,d)}return b}; 124 pv.SvgScene.rule=function(b){for(var c=b.$g.firstChild,d=0;d<b.length;d++){var f=b[d];if(f.visible){var g=f.strokeStyle;if(g.opacity){c=this.expect(c,"line",{"shape-rendering":f.antialias?null:"crispEdges","pointer-events":f.events,cursor:f.cursor,x1:f.left,y1:f.top,x2:f.left+f.width,y2:f.top+f.height,stroke:g.color,"stroke-opacity":g.opacity,"stroke-width":f.lineWidth/this.scale});c=this.append(c,b,d)}}}return c}; 125 pv.SvgScene.wedge=function(b){for(var c=b.$g.firstChild,d=0;d<b.length;d++){var f=b[d];if(f.visible){var g=f.fillStyle,h=f.strokeStyle;if(g.opacity||h.opacity){var i=f.innerRadius,j=f.outerRadius,l=Math.abs(f.angle);if(l>=2*Math.PI)i=i?"M0,"+j+"A"+j+","+j+" 0 1,1 0,"+-j+"A"+j+","+j+" 0 1,1 0,"+j+"M0,"+i+"A"+i+","+i+" 0 1,1 0,"+-i+"A"+i+","+i+" 0 1,1 0,"+i+"Z":"M0,"+j+"A"+j+","+j+" 0 1,1 0,"+-j+"A"+j+","+j+" 0 1,1 0,"+j+"Z";else{var k=Math.min(f.startAngle,f.endAngle),q=Math.max(f.startAngle,f.endAngle), 126 o=Math.cos(k),n=Math.cos(q);k=Math.sin(k);q=Math.sin(q);i=i?"M"+j*o+","+j*k+"A"+j+","+j+" 0 "+(l<Math.PI?"0":"1")+",1 "+j*n+","+j*q+"L"+i*n+","+i*q+"A"+i+","+i+" 0 "+(l<Math.PI?"0":"1")+",0 "+i*o+","+i*k+"Z":"M"+j*o+","+j*k+"A"+j+","+j+" 0 "+(l<Math.PI?"0":"1")+",1 "+j*n+","+j*q+"L0,0Z"}c=this.expect(c,"path",{"shape-rendering":f.antialias?null:"crispEdges","pointer-events":f.events,cursor:f.cursor,transform:"translate("+f.left+","+f.top+")",d:i,fill:g.color,"fill-rule":"evenodd","fill-opacity":g.opacity|| 127 null,stroke:h.color,"stroke-opacity":h.opacity||null,"stroke-width":h.opacity?f.lineWidth/this.scale:null});c=this.append(c,b,d)}}}return c};pv.Mark=function(){this.$properties=[];this.$handlers={}};pv.Mark.prototype.properties={};pv.Mark.cast={};pv.Mark.prototype.property=function(b,c){if(!this.hasOwnProperty("properties"))this.properties=pv.extend(this.properties);this.properties[b]=true;pv.Mark.prototype.propertyMethod(b,false,pv.Mark.cast[b]=c);return this}; 128 pv.Mark.prototype.propertyMethod=function(b,c,d){d||(d=pv.Mark.cast[b]);this[b]=function(f){if(c&&this.scene){var g=this.scene.defs;if(arguments.length){g[b]={id:f==null?0:pv.id(),value:f!=null&&d?d(f):f};return this}return g[b]?g[b].value:null}if(arguments.length){g=!c<<1|typeof f=="function";this.propertyValue(b,g&1&&d?function(){var h=f.apply(this,arguments);return h!=null?d(h):null}:f!=null&&d?d(f):f).type=g;return this}return this.instance()[b]}}; 129 pv.Mark.prototype.propertyValue=function(b,c){var d=this.$properties;c={name:b,id:pv.id(),value:c};for(var f=0;f<d.length;f++)if(d[f].name==b){d.splice(f,1);break}d.push(c);return c};pv.Mark.prototype.property("data").property("visible",Boolean).property("left",Number).property("right",Number).property("top",Number).property("bottom",Number).property("cursor",String).property("title",String).property("reverse",Boolean).property("antialias",Boolean).property("events",String);a=pv.Mark.prototype; 130 a.childIndex=-1;a.index=-1;a.scale=1;a.defaults=(new pv.Mark).data(function(b){return[b]}).visible(true).antialias(true).events("painted");a.extend=function(b){this.proto=b;return this};a.add=function(b){return this.parent.add(b).extend(this)};a.def=function(b,c){this.propertyMethod(b,true);return this[b](arguments.length>1?c:null)}; 131 a.anchor=function(b){function c(g){for(var h=d,i=[];!(f=h.scene);){g=g.parent;i.push({index:g.index,childIndex:h.childIndex});h=h.parent}for(;i.length;){g=i.pop();f=f[g.index].children[g.childIndex]}if(d.hasOwnProperty("index")){i=pv.extend(f[d.index]);i.right=i.top=i.left=i.bottom=0;return[i]}return f}var d=this,f;b||(b="center");return(new pv.Anchor(this)).name(b).def("$mark.anchor",function(){f=this.scene.target=c(this)}).data(function(){return f.map(function(g){return g.data})}).visible(function(){return f[this.index].visible}).left(function(){var g= 132 f[this.index],h=g.width||0;switch(this.name()){case "bottom":case "top":case "center":return g.left+h/2;case "left":return null}return g.left+h}).top(function(){var g=f[this.index],h=g.height||0;switch(this.name()){case "left":case "right":case "center":return g.top+h/2;case "top":return null}return g.top+h}).right(function(){var g=f[this.index];return this.name()=="left"?g.right+(g.width||0):null}).bottom(function(){var g=f[this.index];return this.name()=="top"?g.bottom+(g.height||0):null}).textAlign(function(){switch(this.name()){case "bottom":case "top":case "center":return"center"; 133 case "right":return"right"}return"left"}).textBaseline(function(){switch(this.name()){case "right":case "left":case "center":return"middle";case "top":return"top"}return"bottom"})};a.anchorTarget=function(){return this.proto.anchorTarget()};a.margin=function(b){return this.left(b).right(b).top(b).bottom(b)};a.instance=function(b){var c=this.scene||this.parent.instance(-1).children[this.childIndex],d=!arguments.length||this.hasOwnProperty("index")?this.index:b;return c[d<0?c.length-1:d]};a.first=function(){return this.scene[0]}; 134 a.last=function(){return this.scene[this.scene.length-1]};a.sibling=function(){return this.index==0?null:this.scene[this.index-1]};a.cousin=function(){var b=this.parent;return(b=b&&b.sibling())&&b.children?b.children[this.childIndex][this.index]:null}; 135 a.render=function(){function b(i,j,l){i.scale=l;if(j<g.length){f.unshift(null);if(i.hasOwnProperty("index"))c(i,j,l);else{for(var k=0,q=i.scene.length;k<q;k++){i.index=k;c(i,j,l)}delete i.index}f.shift()}else{i.build();pv.Scene.scale=l;pv.Scene.updateAll(i.scene)}delete i.scale}function c(i,j,l){var k=i.scene[i.index],q;if(k.visible){var o=g[j],n=i.children[o];for(q=0;q<o;q++)i.children[q].scene=k.children[q];f[0]=k.data;if(n.scene)b(n,j+1,l*k.transform.k);else{n.scene=k.children[o];b(n,j+1,l*k.transform.k); 136 delete n.scene}for(q=0;q<o;q++)delete i.children[q].scene}}var d=this.parent,f=pv.Mark.stack;if(d&&!this.root.scene)this.root.render();else{for(var g=[],h=this;h.parent;h=h.parent)g.unshift(h.childIndex);for(this.bind();d&&!d.hasOwnProperty("index");)d=d.parent;this.context(d?d.scene:undefined,d?d.index:-1,function(){b(this.root,0,1)})}};pv.Mark.stack=[];a=pv.Mark.prototype; 137 a.bind=function(){function b(j){do for(var l=j.$properties,k=l.length-1;k>=0;k--){var q=l[k];if(!(q.name in c)){c[q.name]=q;switch(q.name){case "data":f=q;break;case "visible":g=q;break;default:d[q.type].push(q);break}}}while(j=j.proto)}var c={},d=[[],[],[],[]],f,g;b(this);b(this.defaults);d[1].reverse();d[3].reverse();var h=this;do for(var i in h.properties)i in c||d[2].push(c[i]={name:i,type:2,value:null});while(h=h.proto);h=d[0].concat(d[1]);for(i=0;i<h.length;i++)this.propertyMethod(h[i].name, 138 true);this.binds={properties:c,data:f,defs:h,required:[g],optional:pv.blend(d)}}; 139 a.build=function(){var b=this.scene,c=pv.Mark.stack;if(!b){b=this.scene=[];b.mark=this;b.type=this.type;b.childIndex=this.childIndex;if(this.parent){b.parent=this.parent.scene;b.parentIndex=this.parent.index}}if(this.binds.defs.length){var d=b.defs;if(!d)b.defs=d={};for(var f=0;f<this.binds.defs.length;f++){var g=this.binds.defs[f],h=d[g.name];if(!h||g.id>h.id)d[g.name]={id:0,value:g.type&1?g.value.apply(this,c):g.value}}}d=this.binds.data;d=d.type&1?d.value.apply(this,c):d.value;c.unshift(null); 140 b.length=d.length;for(f=0;f<d.length;f++){pv.Mark.prototype.index=this.index=f;(g=b[f])||(b[f]=g={});g.data=c[0]=d[f];this.buildInstance(g)}pv.Mark.prototype.index=-1;delete this.index;c.shift();return this};a.buildProperties=function(b,c){for(var d=0,f=c.length;d<f;d++){var g=c[d],h=g.value;switch(g.type){case 0:case 1:h=this.scene.defs[g.name].value;break;case 3:h=h.apply(this,pv.Mark.stack);break}b[g.name]=h}}; 141 a.buildInstance=function(b){this.buildProperties(b,this.binds.required);if(b.visible){this.buildProperties(b,this.binds.optional);this.buildImplied(b)}}; 142 a.buildImplied=function(b){var c=b.left,d=b.right,f=b.top,g=b.bottom,h=this.properties,i=h.width?b.width:0,j=h.height?b.height:0,l=this.parent?this.parent.width():i+c+d;if(i==null)i=l-(d=d||0)-(c=c||0);else if(d==null)d=l-i-(c=c||0);else if(c==null)c=l-i-(d=d||0);l=this.parent?this.parent.height():j+f+g;if(j==null)j=l-(f=f||0)-(g=g||0);else if(g==null)g=l-j-(f=f||0);else if(f==null)f=l-j-(g=g||0);b.left=c;b.right=d;b.top=f;b.bottom=g;if(h.width)b.width=i;if(h.height)b.height=j;if(h.textStyle&&!b.textStyle)b.textStyle= 143 pv.Color.transparent;if(h.fillStyle&&!b.fillStyle)b.fillStyle=pv.Color.transparent;if(h.strokeStyle&&!b.strokeStyle)b.strokeStyle=pv.Color.transparent}; 144 a.mouse=function(){var b=pv.event.pageX||0,c=pv.event.pageY||0,d=this.root.canvas();do{b-=d.offsetLeft;c-=d.offsetTop}while(d=d.offsetParent);d=pv.Transform.identity;var f=this.properties.transform?this:this.parent,g=[];do g.push(f);while(f=f.parent);for(;f=g.pop();)d=d.translate(f.left(),f.top()).times(f.transform());d=d.invert();return pv.vector(b*d.k+d.x,c*d.k+d.y)};a.event=function(b,c){this.$handlers[b]=pv.functor(c);return this}; 145 a.context=function(b,c,d){function f(k,q){pv.Mark.scene=k;h.index=q;if(k){var o=k.mark,n=o,m=[];do{m.push(n);i.push(k[q].data);n.index=q;n.scene=k;q=k.parentIndex;k=k.parent}while(n=n.parent);k=m.length-1;for(q=1;k>0;k--){n=m[k];n.scale=q;q*=n.scene[n.index].transform.k}if(o.children){k=0;for(m=o.children.length;k<m;k++){n=o.children[k];n.scene=o.scene[o.index].children[k];n.scale=q}}}}function g(k){if(k){k=k.mark;var q;if(k.children)for(var o=0,n=k.children.length;o<n;o++){q=k.children[o];delete q.scene; 146 delete q.scale}q=k;do{i.pop();if(q.parent){delete q.scene;delete q.scale}delete q.index}while(q=q.parent)}}var h=pv.Mark.prototype,i=pv.Mark.stack,j=pv.Mark.scene,l=h.index;g(j,l);f(b,c);try{d.apply(this,i)}finally{g(b,c);f(j,l)}};pv.Mark.dispatch=function(b,c,d){var f=c.mark,g=c.parent,h=f.$handlers[b];if(!h)return g&&pv.Mark.dispatch(b,g,c.parentIndex);f.context(c,d,function(){(f=h.apply(f,pv.Mark.stack))&&f.render&&f.render()});return true}; 147 pv.Anchor=function(b){pv.Mark.call(this);this.target=b;this.parent=b.parent};pv.Anchor.prototype=pv.extend(pv.Mark).property("name",String);pv.Anchor.prototype.anchorTarget=function(){return this.target};pv.Area=function(){pv.Mark.call(this)}; 148 pv.Area.prototype=pv.extend(pv.Mark).property("width",Number).property("height",Number).property("lineWidth",Number).property("strokeStyle",pv.color).property("fillStyle",pv.color).property("segmented",Boolean).property("interpolate",String).property("tension",Number);pv.Area.prototype.type="area";pv.Area.prototype.defaults=(new pv.Area).extend(pv.Mark.prototype.defaults).lineWidth(1.5).fillStyle(pv.Colors.category20().by(pv.parent)).interpolate("linear").tension(0.7); 149 pv.Area.prototype.buildImplied=function(b){if(b.height==null)b.height=0;if(b.width==null)b.width=0;pv.Mark.prototype.buildImplied.call(this,b)};pv.Area.fixed={lineWidth:1,lineJoin:1,strokeStyle:1,fillStyle:1,segmented:1,interpolate:1,tension:1}; 150 pv.Area.prototype.bind=function(){pv.Mark.prototype.bind.call(this);var b=this.binds,c=b.required;b=b.optional;for(var d=0,f=b.length;d<f;d++){var g=b[d];g.fixed=g.name in pv.Area.fixed;if(g.name=="segmented"){c.push(g);b.splice(d,1);d--;f--}}this.binds.$required=c;this.binds.$optional=b}; 151 pv.Area.prototype.buildInstance=function(b){var c=this.binds;if(this.index){var d=c.fixed;if(!d){d=c.fixed=[];function f(i){return!i.fixed||(d.push(i),false)}c.required=c.required.filter(f);if(!this.scene[0].segmented)c.optional=c.optional.filter(f)}c=0;for(var g=d.length;c<g;c++){var h=d[c].name;b[h]=this.scene[0][h]}}else{c.required=c.$required;c.optional=c.$optional;c.fixed=null}pv.Mark.prototype.buildInstance.call(this,b)}; 152 pv.Area.prototype.anchor=function(b){var c;return pv.Mark.prototype.anchor.call(this,b).def("$area.anchor",function(){c=this.scene.target}).interpolate(function(){return c[this.index].interpolate}).eccentricity(function(){return c[this.index].eccentricity}).tension(function(){return c[this.index].tension})};pv.Bar=function(){pv.Mark.call(this)}; 153 pv.Bar.prototype=pv.extend(pv.Mark).property("width",Number).property("height",Number).property("lineWidth",Number).property("strokeStyle",pv.color).property("fillStyle",pv.color);pv.Bar.prototype.type="bar";pv.Bar.prototype.defaults=(new pv.Bar).extend(pv.Mark.prototype.defaults).lineWidth(1.5).fillStyle(pv.Colors.category20().by(pv.parent));pv.Dot=function(){pv.Mark.call(this)}; 154 pv.Dot.prototype=pv.extend(pv.Mark).property("size",Number).property("radius",Number).property("shape",String).property("angle",Number).property("lineWidth",Number).property("strokeStyle",pv.color).property("fillStyle",pv.color);pv.Dot.prototype.type="dot";pv.Dot.prototype.defaults=(new pv.Dot).extend(pv.Mark.prototype.defaults).size(20).shape("circle").lineWidth(1.5).strokeStyle(pv.Colors.category10().by(pv.parent)); 155 pv.Dot.prototype.anchor=function(b){var c;return pv.Mark.prototype.anchor.call(this,b).def("$wedge.anchor",function(){c=this.scene.target}).left(function(){var d=c[this.index];switch(this.name()){case "bottom":case "top":case "center":return d.left;case "left":return null}return d.left+d.radius}).right(function(){var d=c[this.index];return this.name()=="left"?d.right+d.radius:null}).top(function(){var d=c[this.index];switch(this.name()){case "left":case "right":case "center":return d.top;case "top":return null}return d.top+ 156 d.radius}).bottom(function(){var d=c[this.index];return this.name()=="top"?d.bottom+d.radius:null}).textAlign(function(){switch(this.name()){case "left":return"right";case "bottom":case "top":case "center":return"center"}return"left"}).textBaseline(function(){switch(this.name()){case "right":case "left":case "center":return"middle";case "bottom":return"top"}return"bottom"})}; 157 pv.Dot.prototype.buildImplied=function(b){if(b.radius==null)b.radius=Math.sqrt(b.size);else if(b.size==null)b.size=b.radius*b.radius;pv.Mark.prototype.buildImplied.call(this,b)};pv.Label=function(){pv.Mark.call(this)}; 158 pv.Label.prototype=pv.extend(pv.Mark).property("text",String).property("font",String).property("textAngle",Number).property("textStyle",pv.color).property("textAlign",String).property("textBaseline",String).property("textMargin",Number).property("textDecoration",String).property("textShadow",String);pv.Label.prototype.type="label";pv.Label.prototype.defaults=(new pv.Label).extend(pv.Mark.prototype.defaults).events("none").text(pv.identity).font("10px sans-serif").textAngle(0).textStyle("black").textAlign("left").textBaseline("bottom").textMargin(3); 159 pv.Line=function(){pv.Mark.call(this)};pv.Line.prototype=pv.extend(pv.Mark).property("lineWidth",Number).property("lineJoin",String).property("strokeStyle",pv.color).property("fillStyle",pv.color).property("segmented",Boolean).property("interpolate",String).property("eccentricity",Number).property("tension",Number);a=pv.Line.prototype;a.type="line";a.defaults=(new pv.Line).extend(pv.Mark.prototype.defaults).lineJoin("miter").lineWidth(1.5).strokeStyle(pv.Colors.category10().by(pv.parent)).interpolate("linear").eccentricity(0).tension(0.7); 160 a.bind=pv.Area.prototype.bind;a.buildInstance=pv.Area.prototype.buildInstance;a.anchor=function(b){return pv.Area.prototype.anchor.call(this,b).textAlign(function(){switch(this.name()){case "left":return"right";case "bottom":case "top":case "center":return"center";case "right":return"left"}}).textBaseline(function(){switch(this.name()){case "right":case "left":case "center":return"middle";case "top":return"bottom";case "bottom":return"top"}})};pv.Rule=function(){pv.Mark.call(this)}; 161 pv.Rule.prototype=pv.extend(pv.Mark).property("width",Number).property("height",Number).property("lineWidth",Number).property("strokeStyle",pv.color);pv.Rule.prototype.type="rule";pv.Rule.prototype.defaults=(new pv.Rule).extend(pv.Mark.prototype.defaults).lineWidth(1).strokeStyle("black").antialias(false);pv.Rule.prototype.anchor=pv.Line.prototype.anchor; 162 pv.Rule.prototype.buildImplied=function(b){var c=b.left,d=b.right;if(b.width!=null||c==null&&d==null||d!=null&&c!=null)b.height=0;else b.width=0;pv.Mark.prototype.buildImplied.call(this,b)};pv.Panel=function(){pv.Bar.call(this);this.children=[];this.root=this;this.$dom=pv.$&&pv.$.s};pv.Panel.prototype=pv.extend(pv.Bar).property("transform").property("overflow",String).property("canvas",function(b){return typeof b=="string"?document.getElementById(b):b});a=pv.Panel.prototype;a.type="panel"; 163 a.defaults=(new pv.Panel).extend(pv.Bar.prototype.defaults).fillStyle(null).overflow("visible");a.anchor=function(b){b=pv.Bar.prototype.anchor.call(this,b);b.parent=this;return b};a.add=function(b){b=new b;b.parent=this;b.root=this.root;b.childIndex=this.children.length;this.children.push(b);return b};a.bind=function(){pv.Mark.prototype.bind.call(this);for(var b=0;b<this.children.length;b++)this.children[b].bind()}; 164 a.buildInstance=function(b){pv.Bar.prototype.buildInstance.call(this,b);if(b.visible){if(!b.children)b.children=[];var c=this.scale*b.transform.k,d,f=this.children.length;pv.Mark.prototype.index=-1;for(var g=0;g<f;g++){d=this.children[g];d.scene=b.children[g];d.scale=c;d.build()}for(g=0;g<f;g++){d=this.children[g];b.children[g]=d.scene;delete d.scene;delete d.scale}b.children.length=f}}; 165 a.buildImplied=function(b){if(!this.parent){var c=b.canvas;if(c){if(c.$panel!=this)for(c.$panel=this;c.lastChild;)c.removeChild(c.lastChild);var d;if(b.width==null){d=parseFloat(pv.css(c,"width"));b.width=d-b.left-b.right}if(b.height==null){d=parseFloat(pv.css(c,"height"));b.height=d-b.top-b.bottom}}else{d=this.$canvas||(this.$canvas=[]);if(!(c=d[this.index])){c=d[this.index]=document.createElement("span");if(this.$dom)this.$dom.parentNode.insertBefore(c,this.$dom);else{for(d=document.body;d.lastChild&& 166 d.lastChild.tagName;)d=d.lastChild;if(d!=document.body)d=d.parentNode;d.appendChild(c)}}}b.canvas=c}if(!b.transform)b.transform=pv.Transform.identity;pv.Mark.prototype.buildImplied.call(this,b)};pv.Image=function(){pv.Bar.call(this)};pv.Image.prototype=pv.extend(pv.Bar).property("url",String).property("imageWidth",Number).property("imageHeight",Number);a=pv.Image.prototype;a.type="image";a.defaults=(new pv.Image).extend(pv.Bar.prototype.defaults).fillStyle(null); 167 a.image=function(b){this.$image=function(){var c=b.apply(this,arguments);return c==null?pv.Color.transparent:typeof c=="string"?pv.color(c):c};return this};a.bind=function(){pv.Bar.prototype.bind.call(this);var b=this.binds,c=this;do b.image=c.$image;while(!b.image&&(c=c.proto))}; 168 a.buildImplied=function(b){pv.Bar.prototype.buildImplied.call(this,b);if(b.visible){if(b.imageWidth==null)b.imageWidth=b.width;if(b.imageHeight==null)b.imageHeight=b.height;if(b.url==null&&this.binds.image){var c=this.$canvas||(this.$canvas=document.createElement("canvas")),d=c.getContext("2d"),f=b.imageWidth,g=b.imageHeight,h=pv.Mark.stack;c.width=f;c.height=g;b=(b.image=d.createImageData(f,g)).data;h.unshift(null,null);for(d=c=0;c<g;c++){h[1]=c;for(var i=0;i<f;i++){h[0]=i;var j=this.binds.image.apply(this, 169 h);b[d++]=j.r;b[d++]=j.g;b[d++]=j.b;b[d++]=255*j.a}}h.splice(0,2)}}};pv.Wedge=function(){pv.Mark.call(this)};pv.Wedge.prototype=pv.extend(pv.Mark).property("startAngle",Number).property("endAngle",Number).property("angle",Number).property("innerRadius",Number).property("outerRadius",Number).property("lineWidth",Number).property("strokeStyle",pv.color).property("fillStyle",pv.color);a=pv.Wedge.prototype;a.type="wedge"; 170 a.defaults=(new pv.Wedge).extend(pv.Mark.prototype.defaults).startAngle(function(){var b=this.sibling();return b?b.endAngle:-Math.PI/2}).innerRadius(0).lineWidth(1.5).strokeStyle(null).fillStyle(pv.Colors.category20().by(pv.index));a.midRadius=function(){return(this.innerRadius()+this.outerRadius())/2};a.midAngle=function(){return(this.startAngle()+this.endAngle())/2}; 171 a.anchor=function(b){function c(h){return h.innerRadius||h.angle<2*Math.PI}function d(h){return(h.innerRadius+h.outerRadius)/2}function f(h){return(h.startAngle+h.endAngle)/2}var g;return pv.Mark.prototype.anchor.call(this,b).def("$wedge.anchor",function(){g=this.scene.target}).left(function(){var h=g[this.index];if(c(h))switch(this.name()){case "outer":return h.left+h.outerRadius*Math.cos(f(h));case "inner":return h.left+h.innerRadius*Math.cos(f(h));case "start":return h.left+d(h)*Math.cos(h.startAngle); 172 case "center":return h.left+d(h)*Math.cos(f(h));case "end":return h.left+d(h)*Math.cos(h.endAngle)}return h.left}).top(function(){var h=g[this.index];if(c(h))switch(this.name()){case "outer":return h.top+h.outerRadius*Math.sin(f(h));case "inner":return h.top+h.innerRadius*Math.sin(f(h));case "start":return h.top+d(h)*Math.sin(h.startAngle);case "center":return h.top+d(h)*Math.sin(f(h));case "end":return h.top+d(h)*Math.sin(h.endAngle)}return h.top}).textAlign(function(){var h=g[this.index];if(c(h))switch(this.name()){case "outer":return pv.Wedge.upright(f(h))? 173 "right":"left";case "inner":return pv.Wedge.upright(f(h))?"left":"right"}return"center"}).textBaseline(function(){var h=g[this.index];if(c(h))switch(this.name()){case "start":return pv.Wedge.upright(h.startAngle)?"top":"bottom";case "end":return pv.Wedge.upright(h.endAngle)?"bottom":"top"}return"middle"}).textAngle(function(){var h=g[this.index],i=0;if(c(h))switch(this.name()){case "center":case "inner":case "outer":i=f(h);break;case "start":i=h.startAngle;break;case "end":i=h.endAngle;break}return pv.Wedge.upright(i)? 174 i:i+Math.PI})};pv.Wedge.upright=function(b){b%=2*Math.PI;b=b<0?2*Math.PI+b:b;return b<Math.PI/2||b>=3*Math.PI/2};pv.Wedge.prototype.buildImplied=function(b){if(b.angle==null)b.angle=b.endAngle-b.startAngle;else if(b.endAngle==null)b.endAngle=b.startAngle+b.angle;pv.Mark.prototype.buildImplied.call(this,b)};pv.simulation=function(b){return new pv.Simulation(b)};pv.Simulation=function(b){for(var c=0;c<b.length;c++)this.particle(b[c])};a=pv.Simulation.prototype; 175 a.particle=function(b){b.next=this.particles;if(isNaN(b.px))b.px=b.x;if(isNaN(b.py))b.py=b.y;if(isNaN(b.fx))b.fx=0;if(isNaN(b.fy))b.fy=0;this.particles=b;return this};a.force=function(b){b.next=this.forces;this.forces=b;return this};a.constraint=function(b){b.next=this.constraints;this.constraints=b;return this}; 176 a.stabilize=function(b){var c;arguments.length||(b=3);for(var d=0;d<b;d++){var f=new pv.Quadtree(this.particles);for(c=this.constraints;c;c=c.next)c.apply(this.particles,f)}for(c=this.particles;c;c=c.next){c.px=c.x;c.py=c.y}return this}; 177 a.step=function(){var b;for(b=this.particles;b;b=b.next){var c=b.px,d=b.py;b.px=b.x;b.py=b.y;b.x+=b.vx=b.x-c+b.fx;b.y+=b.vy=b.y-d+b.fy}c=new pv.Quadtree(this.particles);for(b=this.constraints;b;b=b.next)b.apply(this.particles,c);for(b=this.particles;b;b=b.next)b.fx=b.fy=0;for(b=this.forces;b;b=b.next)b.apply(this.particles,c)}; 178 pv.Quadtree=function(b){function c(k,q,o,n,m,r){if(!(isNaN(q.x)||isNaN(q.y)))if(k.leaf)if(k.p){if(!(Math.abs(k.p.x-q.x)+Math.abs(k.p.y-q.y)<0.01)){var s=k.p;k.p=null;d(k,s,o,n,m,r)}d(k,q,o,n,m,r)}else k.p=q;else d(k,q,o,n,m,r)}function d(k,q,o,n,m,r){var s=(o+m)*0.5,u=(n+r)*0.5,x=q.x>=s,t=q.y>=u;k.leaf=false;switch((t<<1)+x){case 0:k=k.c1||(k.c1=new pv.Quadtree.Node);break;case 1:k=k.c2||(k.c2=new pv.Quadtree.Node);break;case 2:k=k.c3||(k.c3=new pv.Quadtree.Node);break;case 3:k=k.c4||(k.c4=new pv.Quadtree.Node); 179 break}if(x)o=s;else m=s;if(t)n=u;else r=u;c(k,q,o,n,m,r)}var f,g=Number.POSITIVE_INFINITY,h=g,i=Number.NEGATIVE_INFINITY,j=i;for(f=b;f;f=f.next){if(f.x<g)g=f.x;if(f.y<h)h=f.y;if(f.x>i)i=f.x;if(f.y>j)j=f.y}f=i-g;var l=j-h;if(f>l)j=h+f;else i=g+l;this.xMin=g;this.yMin=h;this.xMax=i;this.yMax=j;this.root=new pv.Quadtree.Node;for(f=b;f;f=f.next)c(this.root,f,g,h,i,j)};pv.Quadtree.Node=function(){this.leaf=true;this.p=this.c4=this.c3=this.c2=this.c1=null};pv.Force={}; 180 pv.Force.charge=function(b){function c(k){function q(m){c(m);k.cn+=m.cn;o+=m.cn*m.cx;n+=m.cn*m.cy}var o=0,n=0;k.cn=0;if(!k.leaf){k.c1&&q(k.c1);k.c2&&q(k.c2);k.c3&&q(k.c3);k.c4&&q(k.c4)}if(k.p){k.cn+=b;o+=b*k.p.x;n+=b*k.p.y}k.cx=o/k.cn;k.cy=n/k.cn}function d(k,q,o,n,m,r){var s=k.cx-q.x,u=k.cy-q.y,x=1/Math.sqrt(s*s+u*u);if(k.leaf&&k.p!=q||(m-o)*x<j){if(!(x<i)){if(x>g)x=g;k=k.cn*x*x*x;s=s*k;u=u*k;q.fx+=s;q.fy+=u}}else if(!k.leaf){var t=(o+m)*0.5,p=(n+r)*0.5;k.c1&&d(k.c1,q,o,n,t,p);k.c2&&d(k.c2,q,t,n, 181 m,p);k.c3&&d(k.c3,q,o,p,t,r);k.c4&&d(k.c4,q,t,p,m,r);if(!(x<i)){if(x>g)x=g;if(k.p&&k.p!=q){k=b*x*x*x;s=s*k;u=u*k;q.fx+=s;q.fy+=u}}}}var f=2,g=1/f,h=500,i=1/h,j=0.9,l={};arguments.length||(b=-40);l.constant=function(k){if(arguments.length){b=Number(k);return l}return b};l.domain=function(k,q){if(arguments.length){f=Number(k);g=1/f;h=Number(q);i=1/h;return l}return[f,h]};l.theta=function(k){if(arguments.length){j=Number(k);return l}return j};l.apply=function(k,q){c(q.root);for(k=k;k;k=k.next)d(q.root, 182 k,q.xMin,q.yMin,q.xMax,q.yMax)};return l};pv.Force.drag=function(b){var c={};arguments.length||(b=0.1);c.constant=function(d){if(arguments.length){b=d;return c}return b};c.apply=function(d){if(b)for(d=d;d;d=d.next){d.fx-=b*d.vx;d.fy-=b*d.vy}};return c}; 183 pv.Force.spring=function(b){var c=0.1,d=20,f,g,h={};arguments.length||(b=0.1);h.links=function(i){if(arguments.length){f=i;g=i.map(function(j){return 1/Math.sqrt(Math.max(j.sourceNode.linkDegree,j.targetNode.linkDegree))});return h}return f};h.constant=function(i){if(arguments.length){b=Number(i);return h}return b};h.damping=function(i){if(arguments.length){c=Number(i);return h}return c};h.length=function(i){if(arguments.length){d=Number(i);return h}return d};h.apply=function(){for(var i=0;i<f.length;i++){var j= 184 f[i].sourceNode,l=f[i].targetNode,k=j.x-l.x,q=j.y-l.y,o=Math.sqrt(k*k+q*q),n=o?1/o:1;n=(b*g[i]*(o-d)+c*g[i]*(k*(j.vx-l.vx)+q*(j.vy-l.vy))*n)*n;k=-n*(o?k:0.01*(0.5-Math.random()));q=-n*(o?q:0.01*(0.5-Math.random()));j.fx+=k;j.fy+=q;l.fx-=k;l.fy-=q}};return h};pv.Constraint={}; 185 pv.Constraint.collision=function(b){function c(k,q,o,n,m,r){if(!k.leaf){var s=(o+m)*0.5,u=(n+r)*0.5,x=u<j,t=s>g,p=s<i;if(u>h){k.c1&&t&&c(k.c1,q,o,n,s,u);k.c2&&p&&c(k.c2,q,s,n,m,u)}if(x){k.c3&&t&&c(k.c3,q,o,u,s,r);k.c4&&p&&c(k.c4,q,s,u,m,r)}}if(k.p&&k.p!=q){o=q.x-k.p.x;n=q.y-k.p.y;m=Math.sqrt(o*o+n*n);r=f+b(k.p);if(m<r){m=(m-r)/m*0.5;o*=m;n*=m;q.x-=o;q.y-=n;k.p.x+=o;k.p.y+=n}}}var d=1,f,g,h,i,j,l={};arguments.length||(f=10);l.repeat=function(k){if(arguments.length){d=Number(k);return l}return d};l.apply= 186 function(k,q){var o,n,m=-Infinity;for(o=k;o;o=o.next){n=b(o);if(n>m)m=n}for(var r=0;r<d;r++)for(o=k;o;o=o.next){n=(f=b(o))+m;g=o.x-n;i=o.x+n;h=o.y-n;j=o.y+n;c(q.root,o,q.xMin,q.yMin,q.xMax,q.yMax)}};return l};pv.Constraint.position=function(b){var c=1,d={};arguments.length||(b=function(f){return f.fix});d.alpha=function(f){if(arguments.length){c=Number(f);return d}return c};d.apply=function(f){for(f=f;f;f=f.next){var g=b(f);if(g){f.x+=(g.x-f.x)*c;f.y+=(g.y-f.y)*c;f.fx=f.fy=f.vx=f.vy=0}}};return d}; 187 pv.Constraint.bound=function(){var b={},c,d;b.x=function(f,g){if(arguments.length){c={min:Math.min(f,g),max:Math.max(f,g)};return this}return c};b.y=function(f,g){if(arguments.length){d={min:Math.min(f,g),max:Math.max(f,g)};return this}return d};b.apply=function(f){if(c)for(var g=f;g;g=g.next)g.x=g.x<c.min?c.min:g.x>c.max?c.max:g.x;if(d)for(g=f;g;g=g.next)g.y=g.y<d.min?d.min:g.y>d.max?d.max:g.y};return b};pv.Layout=function(){pv.Panel.call(this)};pv.Layout.prototype=pv.extend(pv.Panel); 188 pv.Layout.prototype.property=function(b,c){if(!this.hasOwnProperty("properties"))this.properties=pv.extend(this.properties);this.properties[b]=true;this.propertyMethod(b,false,pv.Mark.cast[b]=c);return this}; 189 pv.Layout.Network=function(){pv.Layout.call(this);var b=this;this.$id=pv.id();(this.node=(new pv.Mark).data(function(){return b.nodes()}).strokeStyle("#1f77b4").fillStyle("#fff").left(function(c){return c.x}).top(function(c){return c.y})).parent=this;this.link=(new pv.Mark).extend(this.node).data(function(c){return[c.sourceNode,c.targetNode]}).fillStyle(null).lineWidth(function(c,d){return d.linkValue*1.5}).strokeStyle("rgba(0,0,0,.2)");this.link.add=function(c){return b.add(pv.Panel).data(function(){return b.links()}).add(c).extend(this)}; 190 (this.label=(new pv.Mark).extend(this.node).textMargin(7).textBaseline("middle").text(function(c){return c.nodeName||c.nodeValue}).textAngle(function(c){c=c.midAngle;return pv.Wedge.upright(c)?c:c+Math.PI}).textAlign(function(c){return pv.Wedge.upright(c.midAngle)?"left":"right"})).parent=this}; 191 pv.Layout.Network.prototype=pv.extend(pv.Layout).property("nodes",function(b){return b.map(function(c,d){if(typeof c!="object")c={nodeValue:c};c.index=d;c.linkDegree=0;return c})}).property("links",function(b){return b.map(function(c){if(isNaN(c.linkValue))c.linkValue=isNaN(c.value)?1:c.value;return c})});pv.Layout.Network.prototype.reset=function(){this.$id=pv.id();return this}; 192 pv.Layout.Network.prototype.buildProperties=function(b,c){if((b.$id||0)<this.$id)pv.Layout.prototype.buildProperties.call(this,b,c)};pv.Layout.Network.prototype.buildImplied=function(b){pv.Layout.prototype.buildImplied.call(this,b);if(b.$id>=this.$id)return true;b.$id=this.$id;b.links.forEach(function(c){var d=c.linkValue;(c.sourceNode||(c.sourceNode=b.nodes[c.source])).linkDegree+=d;(c.targetNode||(c.targetNode=b.nodes[c.target])).linkDegree+=d})}; 193 pv.Layout.Hierarchy=function(){pv.Layout.Network.call(this);this.link.strokeStyle("#ccc")};pv.Layout.Hierarchy.prototype=pv.extend(pv.Layout.Network);pv.Layout.Hierarchy.prototype.buildImplied=function(b){if(!b.links)b.links=pv.Layout.Hierarchy.links.call(this);pv.Layout.Network.prototype.buildImplied.call(this,b)};pv.Layout.Hierarchy.links=function(){return this.nodes().filter(function(b){return b.parentNode}).map(function(b){return{sourceNode:b,targetNode:b.parentNode,linkValue:1}})}; 194 pv.Layout.Hierarchy.NodeLink={buildImplied:function(b){function c(m){return m.parentNode?m.depth*(o-q)+q:0}function d(m){return m.parentNode?(m.breadth-0.25)*2*Math.PI:0}function f(m){switch(i){case "left":return m.depth*l;case "right":return l-m.depth*l;case "top":return m.breadth*l;case "bottom":return l-m.breadth*l;case "radial":return l/2+c(m)*Math.cos(m.midAngle)}}function g(m){switch(i){case "left":return m.breadth*k;case "right":return k-m.breadth*k;case "top":return m.depth*k;case "bottom":return k- 195 m.depth*k;case "radial":return k/2+c(m)*Math.sin(m.midAngle)}}var h=b.nodes,i=b.orient,j=/^(top|bottom)$/.test(i),l=b.width,k=b.height;if(i=="radial"){var q=b.innerRadius,o=b.outerRadius;if(q==null)q=0;if(o==null)o=Math.min(l,k)/2}for(b=0;b<h.length;b++){var n=h[b];n.midAngle=i=="radial"?d(n):j?Math.PI/2:0;n.x=f(n);n.y=g(n);if(n.firstChild)n.midAngle+=Math.PI}}}; 196 pv.Layout.Hierarchy.Fill={constructor:function(){this.node.strokeStyle("#fff").fillStyle("#ccc").width(function(b){return b.dx}).height(function(b){return b.dy}).innerRadius(function(b){return b.innerRadius}).outerRadius(function(b){return b.outerRadius}).startAngle(function(b){return b.startAngle}).angle(function(b){return b.angle});this.label.textAlign("center").left(function(b){return b.x+b.dx/2}).top(function(b){return b.y+b.dy/2});delete this.link},buildImplied:function(b){function c(p,v){return(p+ 197 v)/(1+v)}function d(p){switch(o){case "left":return c(p.minDepth,s)*m;case "right":return(1-c(p.maxDepth,s))*m;case "top":return p.minBreadth*m;case "bottom":return(1-p.maxBreadth)*m;case "radial":return m/2}}function f(p){switch(o){case "left":return p.minBreadth*r;case "right":return(1-p.maxBreadth)*r;case "top":return c(p.minDepth,s)*r;case "bottom":return(1-c(p.maxDepth,s))*r;case "radial":return r/2}}function g(p){switch(o){case "left":case "right":return(p.maxDepth-p.minDepth)/(1+s)*m;case "top":case "bottom":return(p.maxBreadth- 198 p.minBreadth)*m;case "radial":return p.parentNode?(p.innerRadius+p.outerRadius)*Math.cos(p.midAngle):0}}function h(p){switch(o){case "left":case "right":return(p.maxBreadth-p.minBreadth)*r;case "top":case "bottom":return(p.maxDepth-p.minDepth)/(1+s)*r;case "radial":return p.parentNode?(p.innerRadius+p.outerRadius)*Math.sin(p.midAngle):0}}function i(p){return Math.max(0,c(p.minDepth,s/2))*(x-u)+u}function j(p){return c(p.maxDepth,s/2)*(x-u)+u}function l(p){return(p.parentNode?p.minBreadth-0.25:0)* 199 2*Math.PI}function k(p){return(p.parentNode?p.maxBreadth-p.minBreadth:1)*2*Math.PI}var q=b.nodes,o=b.orient,n=/^(top|bottom)$/.test(o),m=b.width,r=b.height,s=-q[0].minDepth;if(o=="radial"){var u=b.innerRadius,x=b.outerRadius;if(u==null)u=0;if(u)s*=2;if(x==null)x=Math.min(m,r)/2}for(b=0;b<q.length;b++){var t=q[b];t.x=d(t);t.y=f(t);if(o=="radial"){t.innerRadius=i(t);t.outerRadius=j(t);t.startAngle=l(t);t.angle=k(t);t.midAngle=t.startAngle+t.angle/2}else t.midAngle=n?-Math.PI/2:0;t.dx=g(t);t.dy=h(t)}}}; 200 pv.Layout.Grid=function(){pv.Layout.call(this);var b=this;(this.cell=(new pv.Mark).data(function(){return b.scene[b.index].$grid}).width(function(){return b.width()/b.cols()}).height(function(){return b.height()/b.rows()}).left(function(){return this.width()*(this.index%b.cols())}).top(function(){return this.height()*Math.floor(this.index/b.cols())})).parent=this};pv.Layout.Grid.prototype=pv.extend(pv.Layout).property("rows").property("cols");pv.Layout.Grid.prototype.defaults=(new pv.Layout.Grid).extend(pv.Layout.prototype.defaults).rows(1).cols(1); 201 pv.Layout.Grid.prototype.buildImplied=function(b){pv.Layout.prototype.buildImplied.call(this,b);var c=b.rows,d=b.cols;if(typeof d=="object")c=pv.transpose(d);if(typeof c=="object"){b.$grid=pv.blend(c);b.rows=c.length;b.cols=c[0]?c[0].length:0}else b.$grid=pv.repeat([b.data],c*d)}; 202 pv.Layout.Stack=function(){function b(i){return function(){return f[i](this.parent.index,this.index)}}pv.Layout.call(this);var c=this,d=function(){return null},f={t:d,l:d,r:d,b:d,w:d,h:d},g,h=c.buildImplied;this.buildImplied=function(i){h.call(this,i);var j=i.layers,l=j.length,k,q=i.orient,o=/^(top|bottom)\b/.test(q),n=this.parent[o?"height":"width"](),m=[],r=[],s=[],u=pv.Mark.stack,x={parent:{parent:this}};u.unshift(null);g=[];for(var t=0;t<l;t++){s[t]=[];r[t]=[];x.parent.index=t;u[0]=j[t];g[t]= 203 this.$values.apply(x.parent,u);if(!t)k=g[t].length;u.unshift(null);for(var p=0;p<k;p++){u[0]=g[t][p];x.index=p;t||(m[p]=this.$x.apply(x,u));s[t][p]=this.$y.apply(x,u)}u.shift()}u.shift();switch(i.order){case "inside-out":var v=s.map(function(A){return pv.max.index(A)});x=pv.range(l).sort(function(A,D){return v[A]-v[D]});j=s.map(function(A){return pv.sum(A)});var w=u=0,y=[],z=[];for(t=0;t<l;t++){p=x[t];if(u<w){u+=j[p];y.push(p)}else{w+=j[p];z.push(p)}}j=z.reverse().concat(y);break;case "reverse":j= 204 pv.range(l-1,-1,-1);break;default:j=pv.range(l);break}switch(i.offset){case "silohouette":for(p=0;p<k;p++){for(t=x=0;t<l;t++)x+=s[t][p];r[j[0]][p]=(n-x)/2}break;case "wiggle":for(t=x=0;t<l;t++)x+=s[t][0];r[j[0]][0]=x=(n-x)/2;for(p=1;p<k;p++){u=n=0;w=m[p]-m[p-1];for(t=0;t<l;t++)n+=s[t][p];for(t=0;t<l;t++){y=(s[j[t]][p]-s[j[t]][p-1])/(2*w);for(i=0;i<t;i++)y+=(s[j[i]][p]-s[j[i]][p-1])/w;u+=y*s[j[t]][p]}r[j[0]][p]=x-=n?u/n*w:0}break;case "expand":for(p=0;p<k;p++){for(t=i=r[j[0]][p]=0;t<l;t++)i+=s[t][p]; 205 if(i){i=n/i;for(t=0;t<l;t++)s[t][p]*=i}else{i=n/l;for(t=0;t<l;t++)s[t][p]=i}}break;default:for(p=0;p<k;p++)r[j[0]][p]=0;break}for(p=0;p<k;p++){x=r[j[0]][p];for(t=1;t<l;t++){x+=s[j[t-1]][p];r[j[t]][p]=x}}t=q.indexOf("-");l=o?"h":"w";o=t<0?o?"l":"b":q.charAt(t+1);q=q.charAt(0);for(var C in f)f[C]=d;f[o]=function(A,D){return m[D]};f[q]=function(A,D){return r[A][D]};f[l]=function(A,D){return s[A][D]}};this.layer=(new pv.Mark).data(function(){return g[this.parent.index]}).top(b("t")).left(b("l")).right(b("r")).bottom(b("b")).width(b("w")).height(b("h")); 206 this.layer.add=function(i){return c.add(pv.Panel).data(function(){return c.layers()}).add(i).extend(this)}};pv.Layout.Stack.prototype=pv.extend(pv.Layout).property("orient",String).property("offset",String).property("order",String).property("layers");a=pv.Layout.Stack.prototype;a.defaults=(new pv.Layout.Stack).extend(pv.Layout.prototype.defaults).orient("bottom-left").offset("zero").layers([[]]);a.$x=pv.Layout.Stack.prototype.$y=function(){return 0};a.x=function(b){this.$x=pv.functor(b);return this}; 207 a.y=function(b){this.$y=pv.functor(b);return this};a.$values=pv.identity;a.values=function(b){this.$values=pv.functor(b);return this}; 208 pv.Layout.Treemap=function(){pv.Layout.Hierarchy.call(this);this.node.strokeStyle("#fff").fillStyle("rgba(31, 119, 180, .25)").width(function(b){return b.dx}).height(function(b){return b.dy});this.label.visible(function(b){return!b.firstChild}).left(function(b){return b.x+b.dx/2}).top(function(b){return b.y+b.dy/2}).textAlign("center").textAngle(function(b){return b.dx>b.dy?0:-Math.PI/2});(this.leaf=(new pv.Mark).extend(this.node).fillStyle(null).strokeStyle(null).visible(function(b){return!b.firstChild})).parent= 209 this;delete this.link};pv.Layout.Treemap.prototype=pv.extend(pv.Layout.Hierarchy).property("round",Boolean).property("paddingLeft",Number).property("paddingRight",Number).property("paddingTop",Number).property("paddingBottom",Number).property("mode",String).property("order",String);a=pv.Layout.Treemap.prototype;a.defaults=(new pv.Layout.Treemap).extend(pv.Layout.Hierarchy.prototype.defaults).mode("squarify").order("ascending");a.padding=function(b){return this.paddingLeft(b).paddingRight(b).paddingTop(b).paddingBottom(b)}; 210 a.$size=function(b){return Number(b.nodeValue)};a.size=function(b){this.$size=pv.functor(b);return this}; 211 a.buildImplied=function(b){function c(r,s,u,x,t,p,v){for(var w=0,y=0;w<r.length;w++){var z=r[w];if(u){z.x=x+y;z.y=t;y+=z.dx=n(p*z.size/s);z.dy=v}else{z.x=x;z.y=t+y;z.dx=p;y+=z.dy=n(v*z.size/s)}}if(z)if(u)z.dx+=p-y;else z.dy+=v-y}function d(r,s){for(var u=-Infinity,x=Infinity,t=0,p=0;p<r.length;p++){var v=r[p].size;if(v<x)x=v;if(v>u)u=v;t+=v}t*=t;s*=s;return Math.max(s*u/t,t/(s*x))}function f(r,s){function u(A){var D=p==y,G=pv.sum(A,o),E=y?n(G/y):0;c(A,G,D,x,t,D?p:E,D?E:v);if(D){t+=E;v-=E}else{x+= 212 E;p-=E}y=Math.min(p,v);return D}var x=r.x+j,t=r.y+k,p=r.dx-j-l,v=r.dy-k-q;if(m!="squarify")c(r.childNodes,r.size,m=="slice"?true:m=="dice"?false:s&1,x,t,p,v);else{var w=[];s=Infinity;var y=Math.min(p,v),z=p*v/r.size;if(!(r.size<=0)){r.visitBefore(function(A){A.size*=z});for(r=r.childNodes.slice();r.length;){var C=r[r.length-1];if(C.size){w.push(C);z=d(w,y);if(z<=s){r.pop();s=z}else{w.pop();u(w);w.length=0;s=Infinity}}else r.pop()}if(u(w))for(s=0;s<w.length;s++)w[s].dy+=v;else for(s=0;s<w.length;s++)w[s].dx+= 213 p}}}if(!pv.Layout.Hierarchy.prototype.buildImplied.call(this,b)){var g=this,h=b.nodes[0],i=pv.Mark.stack,j=b.paddingLeft,l=b.paddingRight,k=b.paddingTop,q=b.paddingBottom,o=function(r){return r.size},n=b.round?Math.round:Number,m=b.mode;i.unshift(null);h.visitAfter(function(r,s){r.depth=s;r.x=r.y=r.dx=r.dy=0;r.size=r.firstChild?pv.sum(r.childNodes,function(u){return u.size}):g.$size.apply(g,(i[0]=r,i))});i.shift();switch(b.order){case "ascending":h.sort(function(r,s){return r.size-s.size});break; 214 case "descending":h.sort(function(r,s){return s.size-r.size});break;case "reverse":h.reverse();break}h.x=0;h.y=0;h.dx=b.width;h.dy=b.height;h.visitBefore(f)}};pv.Layout.Tree=function(){pv.Layout.Hierarchy.call(this)};pv.Layout.Tree.prototype=pv.extend(pv.Layout.Hierarchy).property("group",Number).property("breadth",Number).property("depth",Number).property("orient",String);pv.Layout.Tree.prototype.defaults=(new pv.Layout.Tree).extend(pv.Layout.Hierarchy.prototype.defaults).group(1).breadth(15).depth(60).orient("top"); 215 pv.Layout.Tree.prototype.buildImplied=function(b){function c(p){var v,w,y;if(p.firstChild){v=p.firstChild;w=p.lastChild;for(var z=y=v;z;z=z.nextSibling){c(z);y=f(z,y)}j(p);w=0.5*(v.prelim+w.prelim);if(v=p.previousSibling){p.prelim=v.prelim+k(p.depth,true);p.mod=p.prelim-w}else p.prelim=w}else if(v=p.previousSibling)p.prelim=v.prelim+k(p.depth,true)}function d(p,v,w){p.breadth=p.prelim+v;v+=p.mod;for(p=p.firstChild;p;p=p.nextSibling)d(p,v,w)}function f(p,v){var w=p.previousSibling;if(w){var y=p,z= 216 p,C=w;w=p.parentNode.firstChild;var A=y.mod,D=z.mod,G=C.mod,E=w.mod;C=h(C);for(y=g(y);C&&y;){C=C;y=y;w=g(w);z=h(z);z.ancestor=p;var B=C.prelim+G-(y.prelim+A)+k(C.depth,false);if(B>0){i(l(C,p,v),p,B);A+=B;D+=B}G+=C.mod;A+=y.mod;E+=w.mod;D+=z.mod;C=h(C);y=g(y)}if(C&&!h(z)){z.thread=C;z.mod+=G-D}if(y&&!g(w)){w.thread=y;w.mod+=A-E;v=p}}return v}function g(p){return p.firstChild||p.thread}function h(p){return p.lastChild||p.thread}function i(p,v,w){var y=v.number-p.number;v.change-=w/y;v.shift+=w;p.change+= 217 w/y;v.prelim+=w;v.mod+=w}function j(p){var v=0,w=0;for(p=p.lastChild;p;p=p.previousSibling){p.prelim+=v;p.mod+=v;w+=p.change;v+=p.shift+w}}function l(p,v,w){return p.ancestor.parentNode==v.parentNode?p.ancestor:w}function k(p,v){return(v?1:u+1)/(m=="radial"?p:1)}function q(p){return m=="radial"?p.breadth/r:0}function o(p){switch(m){case "left":return p.depth;case "right":return x-p.depth;case "top":case "bottom":return p.breadth+x/2;case "radial":return x/2+p.depth*Math.cos(q(p))}}function n(p){switch(m){case "left":case "right":return p.breadth+ 218 t/2;case "top":return p.depth;case "bottom":return t-p.depth;case "radial":return t/2+p.depth*Math.sin(q(p))}}if(!pv.Layout.Hierarchy.prototype.buildImplied.call(this,b)){var m=b.orient,r=b.depth,s=b.breadth,u=b.group,x=b.width,t=b.height;b=b.nodes[0];b.visitAfter(function(p,v){p.ancestor=p;p.prelim=0;p.mod=0;p.change=0;p.shift=0;p.number=p.previousSibling?p.previousSibling.number+1:0;p.depth=v});c(b);d(b,-b.prelim,0);b.visitAfter(function(p){p.breadth*=s;p.depth*=r;p.midAngle=q(p);p.x=o(p);p.y=n(p); 219 if(p.firstChild)p.midAngle+=Math.PI;delete p.breadth;delete p.depth;delete p.ancestor;delete p.prelim;delete p.mod;delete p.change;delete p.shift;delete p.number;delete p.thread})}};pv.Layout.Indent=function(){pv.Layout.Hierarchy.call(this);this.link.interpolate("step-after")};pv.Layout.Indent.prototype=pv.extend(pv.Layout.Hierarchy).property("depth",Number).property("breadth",Number);pv.Layout.Indent.prototype.defaults=(new pv.Layout.Indent).extend(pv.Layout.Hierarchy.prototype.defaults).depth(15).breadth(15); 220 pv.Layout.Indent.prototype.buildImplied=function(b){function c(i,j,l){i.x=g+l++*f;i.y=h+j++*d;i.midAngle=0;for(i=i.firstChild;i;i=i.nextSibling)j=c(i,j,l);return j}if(!pv.Layout.Hierarchy.prototype.buildImplied.call(this,b)){var d=b.breadth,f=b.depth,g=0,h=0;c(b.nodes[0],1,1)}};pv.Layout.Pack=function(){pv.Layout.Hierarchy.call(this);this.node.radius(function(b){return b.radius}).strokeStyle("rgb(31, 119, 180)").fillStyle("rgba(31, 119, 180, .25)");this.label.textAlign("center");delete this.link}; 221 pv.Layout.Pack.prototype=pv.extend(pv.Layout.Hierarchy).property("spacing",Number).property("order",String);pv.Layout.Pack.prototype.defaults=(new pv.Layout.Pack).extend(pv.Layout.Hierarchy.prototype.defaults).spacing(1).order("ascending");pv.Layout.Pack.prototype.$radius=function(){return 1};pv.Layout.Pack.prototype.size=function(b){this.$radius=typeof b=="function"?function(){return Math.sqrt(b.apply(this,arguments))}:(b=Math.sqrt(b),function(){return b});return this}; 222 pv.Layout.Pack.prototype.buildImplied=function(b){function c(o){var n=pv.Mark.stack;n.unshift(null);for(var m=0,r=o.length;m<r;m++){var s=o[m];if(!s.firstChild)s.radius=i.$radius.apply(i,(n[0]=s,n))}n.shift()}function d(o){var n=[];for(o=o.firstChild;o;o=o.nextSibling){if(o.firstChild)o.radius=d(o);o.n=o.p=o;n.push(o)}switch(b.order){case "ascending":n.sort(function(m,r){return m.radius-r.radius});break;case "descending":n.sort(function(m,r){return r.radius-m.radius});break;case "reverse":n.reverse(); 223 break}return f(n)}function f(o){function n(B){u=Math.min(B.x-B.radius,u);x=Math.max(B.x+B.radius,x);t=Math.min(B.y-B.radius,t);p=Math.max(B.y+B.radius,p)}function m(B,F){var H=B.n;B.n=F;F.p=B;F.n=H;H.p=F}function r(B,F){B.n=F;F.p=B}function s(B,F){var H=F.x-B.x,I=F.y-B.y;B=B.radius+F.radius;return B*B-H*H-I*I>0.0010}var u=Infinity,x=-Infinity,t=Infinity,p=-Infinity,v,w,y,z,C;v=o[0];v.x=-v.radius;v.y=0;n(v);if(o.length>1){w=o[1];w.x=w.radius;w.y=0;n(w);if(o.length>2){y=o[2];g(v,w,y);n(y);m(v,y);v.p= 224 y;m(y,w);w=v.n;for(var A=3;A<o.length;A++){g(v,w,y=o[A]);var D=0,G=1,E=1;for(z=w.n;z!=w;z=z.n,G++)if(s(z,y)){D=1;break}if(D==1)for(C=v.p;C!=z.p;C=C.p,E++)if(s(C,y)){if(E<G){D=-1;z=C}break}if(D==0){m(v,y);w=y;n(y)}else if(D>0){r(v,z);w=z;A--}else if(D<0){r(z,w);v=z;A--}}}}v=(u+x)/2;w=(t+p)/2;for(A=y=0;A<o.length;A++){z=o[A];z.x-=v;z.y-=w;y=Math.max(y,z.radius+Math.sqrt(z.x*z.x+z.y*z.y))}return y+b.spacing}function g(o,n,m){var r=n.radius+m.radius,s=o.radius+m.radius,u=n.x-o.x;n=n.y-o.y;var x=Math.sqrt(u* 225 u+n*n),t=(s*s+x*x-r*r)/(2*s*x);r=Math.acos(t);t=t*s;s=Math.sin(r)*s;u/=x;n/=x;m.x=o.x+t*u+s*n;m.y=o.y+t*n-s*u}function h(o,n,m,r){for(var s=o.firstChild;s;s=s.nextSibling){s.x+=o.x;s.y+=o.y;h(s,n,m,r)}o.x=n+r*o.x;o.y=m+r*o.y;o.radius*=r}if(!pv.Layout.Hierarchy.prototype.buildImplied.call(this,b)){var i=this,j=b.nodes,l=j[0];c(j);l.x=0;l.y=0;l.radius=d(l);j=this.width();var k=this.height(),q=1/Math.max(2*l.radius/j,2*l.radius/k);h(l,j/2,k/2,q)}}; 226 pv.Layout.Force=function(){pv.Layout.Network.call(this);this.link.lineWidth(function(b,c){return Math.sqrt(c.linkValue)*1.5});this.label.textAlign("center")}; 227 pv.Layout.Force.prototype=pv.extend(pv.Layout.Network).property("bound",Boolean).property("iterations",Number).property("dragConstant",Number).property("chargeConstant",Number).property("chargeMinDistance",Number).property("chargeMaxDistance",Number).property("chargeTheta",Number).property("springConstant",Number).property("springDamping",Number).property("springLength",Number);pv.Layout.Force.prototype.defaults=(new pv.Layout.Force).extend(pv.Layout.Network.prototype.defaults).dragConstant(0.1).chargeConstant(-40).chargeMinDistance(2).chargeMaxDistance(500).chargeTheta(0.9).springConstant(0.1).springDamping(0.3).springLength(20); 228 pv.Layout.Force.prototype.buildImplied=function(b){function c(q){return q.fix?1:q.vx*q.vx+q.vy*q.vy}if(pv.Layout.Network.prototype.buildImplied.call(this,b)){if(b=b.$force){b.next=this.binds.$force;this.binds.$force=b}}else{for(var d=this,f=b.nodes,g=b.links,h=b.iterations,i=b.width,j=b.height,l=0,k;l<f.length;l++){k=f[l];if(isNaN(k.x))k.x=i/2+40*Math.random()-20;if(isNaN(k.y))k.y=j/2+40*Math.random()-20}k=pv.simulation(f);k.force(pv.Force.drag(b.dragConstant));k.force(pv.Force.charge(b.chargeConstant).domain(b.chargeMinDistance, 229 b.chargeMaxDistance).theta(b.chargeTheta));k.force(pv.Force.spring(b.springConstant).damping(b.springDamping).length(b.springLength).links(g));k.constraint(pv.Constraint.position());b.bound&&k.constraint(pv.Constraint.bound().x(6,i-6).y(6,j-6));if(h==null){k.step();k.step();b.$force=this.binds.$force={next:this.binds.$force,nodes:f,min:1.0E-4*(g.length+1),sim:k};if(!this.$timer)this.$timer=setInterval(function(){for(var q=false,o=d.binds.$force;o;o=o.next)if(pv.max(o.nodes,c)>o.min){o.sim.step(); 230 q=true}q&&d.render()},42)}else for(l=0;l<h;l++)k.step()}};pv.Layout.Cluster=function(){pv.Layout.Hierarchy.call(this);var b,c=this.buildImplied;this.buildImplied=function(d){c.call(this,d);b=/^(top|bottom)$/.test(d.orient)?"step-before":/^(left|right)$/.test(d.orient)?"step-after":"linear"};this.link.interpolate(function(){return b})}; 231 pv.Layout.Cluster.prototype=pv.extend(pv.Layout.Hierarchy).property("group",Number).property("orient",String).property("innerRadius",Number).property("outerRadius",Number);pv.Layout.Cluster.prototype.defaults=(new pv.Layout.Cluster).extend(pv.Layout.Hierarchy.prototype.defaults).group(0).orient("top"); 232 pv.Layout.Cluster.prototype.buildImplied=function(b){if(!pv.Layout.Hierarchy.prototype.buildImplied.call(this,b)){var c=b.nodes[0],d=b.group,f,g,h=0,i=0.5-d/2,j=undefined;c.visitAfter(function(l){if(l.firstChild)l.depth=1+pv.max(l.childNodes,function(k){return k.depth});else{if(d&&j!=l.parentNode){j=l.parentNode;h+=d}h++;l.depth=0}});f=1/h;g=1/c.depth;j=undefined;c.visitAfter(function(l){if(l.firstChild)l.breadth=pv.mean(l.childNodes,function(k){return k.breadth});else{if(d&&j!=l.parentNode){j=l.parentNode; 233 i+=d}l.breadth=f*i++}l.depth=1-l.depth*g});c.visitAfter(function(l){l.minBreadth=l.firstChild?l.firstChild.minBreadth:l.breadth-f/2;l.maxBreadth=l.firstChild?l.lastChild.maxBreadth:l.breadth+f/2});c.visitBefore(function(l){l.minDepth=l.parentNode?l.parentNode.maxDepth:0;l.maxDepth=l.parentNode?l.depth+c.depth:l.minDepth+2*c.depth});c.minDepth=-g;pv.Layout.Hierarchy.NodeLink.buildImplied.call(this,b)}};pv.Layout.Cluster.Fill=function(){pv.Layout.Cluster.call(this);pv.Layout.Hierarchy.Fill.constructor.call(this)}; 234 pv.Layout.Cluster.Fill.prototype=pv.extend(pv.Layout.Cluster);pv.Layout.Cluster.Fill.prototype.buildImplied=function(b){pv.Layout.Cluster.prototype.buildImplied.call(this,b)||pv.Layout.Hierarchy.Fill.buildImplied.call(this,b)};pv.Layout.Partition=function(){pv.Layout.Hierarchy.call(this)};pv.Layout.Partition.prototype=pv.extend(pv.Layout.Hierarchy).property("order",String).property("orient",String).property("innerRadius",Number).property("outerRadius",Number); 235 pv.Layout.Partition.prototype.defaults=(new pv.Layout.Partition).extend(pv.Layout.Hierarchy.prototype.defaults).orient("top");pv.Layout.Partition.prototype.$size=function(){return 1};pv.Layout.Partition.prototype.size=function(b){this.$size=b;return this}; 236 pv.Layout.Partition.prototype.buildImplied=function(b){if(!pv.Layout.Hierarchy.prototype.buildImplied.call(this,b)){var c=this,d=b.nodes[0],f=pv.Mark.stack,g=0;f.unshift(null);d.visitAfter(function(i,j){if(j>g)g=j;i.size=i.firstChild?pv.sum(i.childNodes,function(l){return l.size}):c.$size.apply(c,(f[0]=i,f))});f.shift();switch(b.order){case "ascending":d.sort(function(i,j){return i.size-j.size});break;case "descending":d.sort(function(i,j){return j.size-i.size});break}var h=1/g;d.minBreadth=0;d.breadth= 237 0.5;d.maxBreadth=1;d.visitBefore(function(i){for(var j=i.minBreadth,l=i.maxBreadth-j,k=i.firstChild;k;k=k.nextSibling){k.minBreadth=j;k.maxBreadth=j+=k.size/i.size*l;k.breadth=(j+k.minBreadth)/2}});d.visitAfter(function(i,j){i.minDepth=(j-1)*h;i.maxDepth=i.depth=j*h});pv.Layout.Hierarchy.NodeLink.buildImplied.call(this,b)}};pv.Layout.Partition.Fill=function(){pv.Layout.Partition.call(this);pv.Layout.Hierarchy.Fill.constructor.call(this)};pv.Layout.Partition.Fill.prototype=pv.extend(pv.Layout.Partition); 238 pv.Layout.Partition.Fill.prototype.buildImplied=function(b){pv.Layout.Partition.prototype.buildImplied.call(this,b)||pv.Layout.Hierarchy.Fill.buildImplied.call(this,b)};pv.Layout.Arc=function(){pv.Layout.Network.call(this);var b,c,d,f=this.buildImplied;this.buildImplied=function(g){f.call(this,g);c=g.directed;b=g.orient=="radial"?"linear":"polar";d=g.orient=="right"||g.orient=="top"};this.link.data(function(g){var h=g.sourceNode;g=g.targetNode;return d!=(c||h.breadth<g.breadth)?[h,g]:[g,h]}).interpolate(function(){return b})}; 239 pv.Layout.Arc.prototype=pv.extend(pv.Layout.Network).property("orient",String).property("directed",Boolean);pv.Layout.Arc.prototype.defaults=(new pv.Layout.Arc).extend(pv.Layout.Network.prototype.defaults).orient("bottom");pv.Layout.Arc.prototype.sort=function(b){this.$sort=b;return this}; 240 pv.Layout.Arc.prototype.buildImplied=function(b){function c(m){switch(h){case "top":return-Math.PI/2;case "bottom":return Math.PI/2;case "left":return Math.PI;case "right":return 0;case "radial":return(m-0.25)*2*Math.PI}}function d(m){switch(h){case "top":case "bottom":return m*l;case "left":return 0;case "right":return l;case "radial":return l/2+q*Math.cos(c(m))}}function f(m){switch(h){case "top":return 0;case "bottom":return k;case "left":case "right":return m*k;case "radial":return k/2+q*Math.sin(c(m))}} 241 if(!pv.Layout.Network.prototype.buildImplied.call(this,b)){var g=b.nodes,h=b.orient,i=this.$sort,j=pv.range(g.length),l=b.width,k=b.height,q=Math.min(l,k)/2;i&&j.sort(function(m,r){return i(g[m],g[r])});for(b=0;b<g.length;b++){var o=g[j[b]],n=o.breadth=(b+0.5)/g.length;o.x=d(n);o.y=f(n);o.midAngle=c(n)}}}; 242 pv.Layout.Horizon=function(){pv.Layout.call(this);var b=this,c,d,f,g,h,i,j=this.buildImplied;this.buildImplied=function(l){j.call(this,l);c=l.bands;d=l.mode;f=Math.round((d=="color"?0.5:1)*l.height);g=l.backgroundStyle;h=pv.ramp(g,l.negativeStyle).domain(0,c);i=pv.ramp(g,l.positiveStyle).domain(0,c)};c=(new pv.Panel).data(function(){return pv.range(c*2)}).overflow("hidden").height(function(){return f}).top(function(l){return d=="color"?(l&1)*f:0}).fillStyle(function(l){return l?null:g});this.band= 243 (new pv.Mark).top(function(l,k){return d=="mirror"&&k&1?(k+1>>1)*f:null}).bottom(function(l,k){return d=="mirror"?k&1?null:(k+1>>1)*-f:(k&1||-1)*(k+1>>1)*f}).fillStyle(function(l,k){return(k&1?h:i)((k>>1)+1)});this.band.add=function(l){return b.add(pv.Panel).extend(c).add(l).extend(this)}};pv.Layout.Horizon.prototype=pv.extend(pv.Layout).property("bands",Number).property("mode",String).property("backgroundStyle",pv.color).property("positiveStyle",pv.color).property("negativeStyle",pv.color); 244 pv.Layout.Horizon.prototype.defaults=(new pv.Layout.Horizon).extend(pv.Layout.prototype.defaults).bands(2).mode("offset").backgroundStyle("white").positiveStyle("#1f77b4").negativeStyle("#d62728"); 245 pv.Layout.Rollup=function(){pv.Layout.Network.call(this);var b=this,c,d,f=b.buildImplied;this.buildImplied=function(g){f.call(this,g);c=g.$rollup.nodes;d=g.$rollup.links};this.node.data(function(){return c}).size(function(g){return g.nodes.length*20});this.link.interpolate("polar").eccentricity(0.8);this.link.add=function(g){return b.add(pv.Panel).data(function(){return d}).add(g).extend(this)}};pv.Layout.Rollup.prototype=pv.extend(pv.Layout.Network).property("directed",Boolean); 246 pv.Layout.Rollup.prototype.x=function(b){this.$x=pv.functor(b);return this};pv.Layout.Rollup.prototype.y=function(b){this.$y=pv.functor(b);return this}; 247 pv.Layout.Rollup.prototype.buildImplied=function(b){function c(r){return i[r]+","+j[r]}if(!pv.Layout.Network.prototype.buildImplied.call(this,b)){var d=b.nodes,f=b.links,g=b.directed,h=d.length,i=[],j=[],l=0,k={},q={},o=pv.Mark.stack,n={parent:this};o.unshift(null);for(var m=0;m<h;m++){n.index=m;o[0]=d[m];i[m]=this.$x.apply(n,o);j[m]=this.$y.apply(n,o)}o.shift();for(m=0;m<d.length;m++){h=c(m);o=k[h];if(!o){o=k[h]=pv.extend(d[m]);o.index=l++;o.x=i[m];o.y=j[m];o.nodes=[]}o.nodes.push(d[m])}for(m=0;m< 248 f.length;m++){l=f[m].targetNode;d=k[c(f[m].sourceNode.index)];l=k[c(l.index)];h=!g&&d.index>l.index?l.index+","+d.index:d.index+","+l.index;(o=q[h])||(o=q[h]={sourceNode:d,targetNode:l,linkValue:0,links:[]});o.links.push(f[m]);o.linkValue+=f[m].linkValue}b.$rollup={nodes:pv.values(k),links:pv.values(q)}}}; 249 pv.Layout.Matrix=function(){pv.Layout.Network.call(this);var b,c,d,f,g,h=this.buildImplied;this.buildImplied=function(i){h.call(this,i);b=i.nodes.length;c=i.width/b;d=i.height/b;f=i.$matrix.labels;g=i.$matrix.pairs};this.link.data(function(){return g}).left(function(){return c*(this.index%b)}).top(function(){return d*Math.floor(this.index/b)}).width(function(){return c}).height(function(){return d}).lineWidth(1.5).strokeStyle("#fff").fillStyle(function(i){return i.linkValue?"#555":"#eee"}).parent= 250 this;delete this.link.add;this.label.data(function(){return f}).left(function(){return this.index&1?c*((this.index>>1)+0.5):null}).top(function(){return this.index&1?null:d*((this.index>>1)+0.5)}).textMargin(4).textAlign(function(){return this.index&1?"left":"right"}).textAngle(function(){return this.index&1?-Math.PI/2:0});delete this.node};pv.Layout.Matrix.prototype=pv.extend(pv.Layout.Network).property("directed",Boolean);pv.Layout.Matrix.prototype.sort=function(b){this.$sort=b;return this}; 251 pv.Layout.Matrix.prototype.buildImplied=function(b){if(!pv.Layout.Network.prototype.buildImplied.call(this,b)){var c=b.nodes,d=b.links,f=this.$sort,g=c.length,h=pv.range(g),i=[],j=[],l={};b.$matrix={labels:i,pairs:j};f&&h.sort(function(m,r){return f(c[m],c[r])});for(var k=0;k<g;k++)for(var q=0;q<g;q++){var o=h[k],n=h[q];j.push(l[o+"."+n]={row:k,col:q,sourceNode:c[o],targetNode:c[n],linkValue:0})}for(k=0;k<g;k++){o=h[k];i.push(c[o],c[o])}for(k=0;k<d.length;k++){i=d[k];g=i.sourceNode.index;h=i.targetNode.index; 252 i=i.linkValue;l[g+"."+h].linkValue+=i;b.directed||(l[h+"."+g].linkValue+=i)}}}; 253 pv.Layout.Bullet=function(){pv.Layout.call(this);var b=this,c=b.buildImplied,d=b.x=pv.Scale.linear(),f,g,h,i,j;this.buildImplied=function(l){c.call(this,j=l);f=l.orient;g=/^left|right$/.test(f);h=pv.ramp("#bbb","#eee").domain(0,Math.max(1,j.ranges.length-1));i=pv.ramp("steelblue","lightsteelblue").domain(0,Math.max(1,j.measures.length-1))};(this.range=new pv.Mark).data(function(){return j.ranges}).reverse(true).left(function(){return f=="left"?0:null}).top(function(){return f=="top"?0:null}).right(function(){return f== 254 "right"?0:null}).bottom(function(){return f=="bottom"?0:null}).width(function(l){return g?d(l):null}).height(function(l){return g?null:d(l)}).fillStyle(function(){return h(this.index)}).antialias(false).parent=b;(this.measure=new pv.Mark).extend(this.range).data(function(){return j.measures}).left(function(){return f=="left"?0:g?null:this.parent.width()/3.25}).top(function(){return f=="top"?0:g?this.parent.height()/3.25:null}).right(function(){return f=="right"?0:g?null:this.parent.width()/3.25}).bottom(function(){return f== 255 "bottom"?0:g?this.parent.height()/3.25:null}).fillStyle(function(){return i(this.index)}).parent=b;(this.marker=new pv.Mark).data(function(){return j.markers}).left(function(l){return f=="left"?d(l):g?null:this.parent.width()/2}).top(function(l){return f=="top"?d(l):g?this.parent.height()/2:null}).right(function(l){return f=="right"?d(l):null}).bottom(function(l){return f=="bottom"?d(l):null}).strokeStyle("black").shape("bar").angle(function(){return g?0:Math.PI/2}).parent=b;(this.tick=new pv.Mark).data(function(){return d.ticks(7)}).left(function(l){return f== 256 "left"?d(l):null}).top(function(l){return f=="top"?d(l):null}).right(function(l){return f=="right"?d(l):g?null:-6}).bottom(function(l){return f=="bottom"?d(l):g?-8:null}).height(function(){return g?6:null}).width(function(){return g?null:6}).parent=b};pv.Layout.Bullet.prototype=pv.extend(pv.Layout).property("orient",String).property("ranges").property("markers").property("measures").property("maximum",Number);pv.Layout.Bullet.prototype.defaults=(new pv.Layout.Bullet).extend(pv.Layout.prototype.defaults).orient("left").ranges([]).markers([]).measures([]); 257 pv.Layout.Bullet.prototype.buildImplied=function(b){pv.Layout.prototype.buildImplied.call(this,b);var c=this.parent[/^left|right$/.test(b.orient)?"width":"height"]();b.maximum=b.maximum||pv.max([].concat(b.ranges,b.markers,b.measures));this.x.domain(0,b.maximum).range(0,c)};pv.Behavior={}; 258 pv.Behavior.drag=function(){function b(l){g=this.index;f=this.scene;var k=this.mouse();i=((h=l).fix=pv.vector(l.x,l.y)).minus(k);j={x:this.parent.width()-(l.dx||0),y:this.parent.height()-(l.dy||0)};f.mark.context(f,g,function(){this.render()});pv.Mark.dispatch("dragstart",f,g)}function c(){if(f){f.mark.context(f,g,function(){var l=this.mouse();h.x=h.fix.x=Math.max(0,Math.min(i.x+l.x,j.x));h.y=h.fix.y=Math.max(0,Math.min(i.y+l.y,j.y));this.render()});pv.Mark.dispatch("drag",f,g)}}function d(){if(f){h.fix= 259 null;f.mark.context(f,g,function(){this.render()});pv.Mark.dispatch("dragend",f,g);f=null}}var f,g,h,i,j;pv.listen(window,"mousemove",c);pv.listen(window,"mouseup",d);return b}; 260 pv.Behavior.point=function(b){function c(k,q){k=k[q];q={cost:Infinity};for(var o=0,n=k.visible&&k.children.length;o<n;o++){var m=k.children[o],r=m.mark,s;if(r.type=="panel"){r.scene=m;for(var u=0,x=m.length;u<x;u++){r.index=u;s=c(m,u);if(s.cost<q.cost)q=s}delete r.scene;delete r.index}else if(r.$handlers.point){r=r.mouse();u=0;for(x=m.length;u<x;u++){var t=m[u];s=r.x-t.left-(t.width||0)/2;t=r.y-t.top-(t.height||0)/2;var p=i*s*s+j*t*t;if(p<q.cost){q.distance=s*s+t*t;q.cost=p;q.scene=m;q.index=u}}}}return q} 261 function d(){var k=c(this.scene,this.index);if(k.cost==Infinity||k.distance>l)k=null;if(g){if(k&&g.scene==k.scene&&g.index==k.index)return;pv.Mark.dispatch("unpoint",g.scene,g.index)}if(g=k){pv.Mark.dispatch("point",k.scene,k.index);pv.listen(this.root.canvas(),"mouseout",f)}}function f(k){if(g&&!pv.ancestor(this,k.relatedTarget)){pv.Mark.dispatch("unpoint",g.scene,g.index);g=null}}var g,h=null,i=1,j=1,l=arguments.length?b*b:900;d.collapse=function(k){if(arguments.length){h=String(k);switch(h){case "y":i= 262 1;j=0;break;case "x":i=0;j=1;break;default:j=i=1;break}return d}return h};return d}; 263 pv.Behavior.select=function(){function b(j){g=this.index;f=this.scene;i=this.mouse();h=j;h.x=i.x;h.y=i.y;h.dx=h.dy=0;pv.Mark.dispatch("selectstart",f,g)}function c(){if(f){f.mark.context(f,g,function(){var j=this.mouse();h.x=Math.max(0,Math.min(i.x,j.x));h.y=Math.max(0,Math.min(i.y,j.y));h.dx=Math.min(this.width(),Math.max(j.x,i.x))-h.x;h.dy=Math.min(this.height(),Math.max(j.y,i.y))-h.y;this.render()});pv.Mark.dispatch("select",f,g)}}function d(){if(f){pv.Mark.dispatch("selectend",f,g);f=null}}var f, 264 g,h,i;pv.listen(window,"mousemove",c);pv.listen(window,"mouseup",d);return b}; 265 pv.Behavior.resize=function(b){function c(l){h=this.index;g=this.scene;j=this.mouse();i=l;switch(b){case "left":j.x=i.x+i.dx;break;case "right":j.x=i.x;break;case "top":j.y=i.y+i.dy;break;case "bottom":j.y=i.y;break}pv.Mark.dispatch("resizestart",g,h)}function d(){if(g){g.mark.context(g,h,function(){var l=this.mouse();i.x=Math.max(0,Math.min(j.x,l.x));i.y=Math.max(0,Math.min(j.y,l.y));i.dx=Math.min(this.parent.width(),Math.max(l.x,j.x))-i.x;i.dy=Math.min(this.parent.height(),Math.max(l.y,j.y))-i.y; 266 this.render()});pv.Mark.dispatch("resize",g,h)}}function f(){if(g){pv.Mark.dispatch("resizeend",g,h);g=null}}var g,h,i,j;pv.listen(window,"mousemove",d);pv.listen(window,"mouseup",f);return c}; 267 pv.Behavior.pan=function(){function b(){g=this.index;f=this.scene;i=pv.vector(pv.event.pageX,pv.event.pageY);h=this.transform();j=1/(h.k*this.scale);if(l)l={x:(1-h.k)*this.width(),y:(1-h.k)*this.height()}}function c(){if(f){f.mark.context(f,g,function(){var k=h.translate((pv.event.pageX-i.x)*j,(pv.event.pageY-i.y)*j);if(l){k.x=Math.max(l.x,Math.min(0,k.x));k.y=Math.max(l.y,Math.min(0,k.y))}this.transform(k).render()});pv.Mark.dispatch("pan",f,g)}}function d(){f=null}var f,g,h,i,j,l;b.bound=function(k){if(arguments.length){l= 268 Boolean(k);return this}return Boolean(l)};pv.listen(window,"mousemove",c);pv.listen(window,"mouseup",d);return b}; 269 pv.Behavior.zoom=function(b){function c(){var f=this.mouse(),g=pv.event.wheel*b;f=this.transform().translate(f.x,f.y).scale(g<0?1E3/(1E3-g):(1E3+g)/1E3).translate(-f.x,-f.y);if(d){f.k=Math.max(1,f.k);f.x=Math.max((1-f.k)*this.width(),Math.min(0,f.x));f.y=Math.max((1-f.k)*this.height(),Math.min(0,f.y))}this.transform(f).render();pv.Mark.dispatch("zoom",this.scene,this.index)}var d;arguments.length||(b=1/48);c.bound=function(f){if(arguments.length){d=Boolean(f);return this}return Boolean(d)};return c}; 270 pv.Geo=function(){}; 271 pv.Geo.projections={mercator:{project:function(b){return{x:b.lng/180,y:b.lat>85?1:b.lat<-85?-1:Math.log(Math.tan(Math.PI/4+pv.radians(b.lat)/2))/Math.PI}},invert:function(b){return{lng:b.x*180,lat:pv.degrees(2*Math.atan(Math.exp(b.y*Math.PI))-Math.PI/2)}}},"gall-peters":{project:function(b){return{x:b.lng/180,y:Math.sin(pv.radians(b.lat))}},invert:function(b){return{lng:b.x*180,lat:pv.degrees(Math.asin(b.y))}}},sinusoidal:{project:function(b){return{x:pv.radians(b.lng)*Math.cos(pv.radians(b.lat))/Math.PI, 272 y:b.lat/90}},invert:function(b){return{lng:pv.degrees(b.x*Math.PI/Math.cos(b.y*Math.PI/2)),lat:b.y*90}}},aitoff:{project:function(b){var c=pv.radians(b.lng);b=pv.radians(b.lat);var d=Math.acos(Math.cos(b)*Math.cos(c/2));return{x:2*(d?Math.cos(b)*Math.sin(c/2)*d/Math.sin(d):0)/Math.PI,y:2*(d?Math.sin(b)*d/Math.sin(d):0)/Math.PI}},invert:function(b){var c=b.y*Math.PI/2;return{lng:pv.degrees(b.x*Math.PI/2/Math.cos(c)),lat:pv.degrees(c)}}},hammer:{project:function(b){var c=pv.radians(b.lng);b=pv.radians(b.lat); 273 var d=Math.sqrt(1+Math.cos(b)*Math.cos(c/2));return{x:2*Math.SQRT2*Math.cos(b)*Math.sin(c/2)/d/3,y:Math.SQRT2*Math.sin(b)/d/1.5}},invert:function(b){var c=b.x*3;b=b.y*1.5;var d=Math.sqrt(1-c*c/16-b*b/4);return{lng:pv.degrees(2*Math.atan2(d*c,2*(2*d*d-1))),lat:pv.degrees(Math.asin(d*b))}}},identity:{project:function(b){return{x:b.lng/180,y:b.lat/90}},invert:function(b){return{lng:b.x*180,lat:b.y*90}}}}; 274 pv.Geo.scale=function(b){function c(m){if(!o||m.lng!=o.lng||m.lat!=o.lat){o=m;m=d(m);n={x:l(m.x),y:k(m.y)}}return n}function d(m){return j.project({lng:m.lng-q.lng,lat:m.lat})}function f(m){m=j.invert(m);m.lng+=q.lng;return m}var g={x:0,y:0},h={x:1,y:1},i=[],j=pv.Geo.projections.identity,l=pv.Scale.linear(-1,1).range(0,1),k=pv.Scale.linear(-1,1).range(1,0),q={lng:0,lat:0},o,n;c.x=function(m){return c(m).x};c.y=function(m){return c(m).y};c.ticks={lng:function(m){var r;if(i.length>1){var s=pv.Scale.linear(); 275 if(m==undefined)m=10;r=s.domain(i,function(u){return u.lat}).ticks(m);m=s.domain(i,function(u){return u.lng}).ticks(m)}else{r=pv.range(-80,81,10);m=pv.range(-180,181,10)}return m.map(function(u){return r.map(function(x){return{lat:x,lng:u}})})},lat:function(m){return pv.transpose(c.ticks.lng(m))}};c.invert=function(m){return f({x:l.invert(m.x),y:k.invert(m.y)})};c.domain=function(m,r){if(arguments.length){i=m instanceof Array?arguments.length>1?pv.map(m,r):m:Array.prototype.slice.call(arguments); 276 if(i.length>1){var s=i.map(function(x){return x.lng}),u=i.map(function(x){return x.lat});q={lng:(pv.max(s)+pv.min(s))/2,lat:(pv.max(u)+pv.min(u))/2};s=i.map(d);l.domain(s,function(x){return x.x});k.domain(s,function(x){return x.y})}else{q={lng:0,lat:0};l.domain(-1,1);k.domain(-1,1)}o=null;return this}return i};c.range=function(m,r){if(arguments.length){if(typeof m=="object"){g={x:Number(m.x),y:Number(m.y)};h={x:Number(r.x),y:Number(r.y)}}else{g={x:0,y:0};h={x:Number(m),y:Number(r)}}l.range(g.x,h.x); 277 k.range(h.y,g.y);o=null;return this}return[g,h]};c.projection=function(m){if(arguments.length){j=typeof m=="string"?pv.Geo.projections[m]||pv.Geo.projections.identity:m;return this.domain(i)}return m};c.by=function(m){function r(){return c(m.apply(this,arguments))}for(var s in c)r[s]=c[s];return r};arguments.length&&c.projection(b);return c}; -
src/allmydata/web/root.py
diff --git a/src/allmydata/web/root.py b/src/allmydata/web/root.py index 3af15d9..fe15a8f 100644
a b class Root(rend.Page): 164 164 self.child_named = FileHandler(client) 165 165 self.child_status = status.Status(client.get_history()) 166 166 self.child_statistics = status.Statistics(client.stats_provider) 167 def f(name): 168 return nevow_File(resource_filename('allmydata.web', name)) 169 self.putChild("jquery.js", f("jquery.js")) 170 self.putChild("download_status_timeline.js", f("download_status_timeline.js")) 171 self.putChild("protovis-r3.2.js", f("protovis-r3.2.js")) 167 172 168 173 def child_helper_status(self, ctx): 169 174 # the Helper isn't attached until after the Tub starts, so this child -
src/allmydata/web/status.py
diff --git a/src/allmydata/web/status.py b/src/allmydata/web/status.py index 9f96f1d..5d28bbe 100644
a b class DownloadResultsRendererMixin(RateAndTimeMixin): 331 331 d.addCallback(_render) 332 332 return d 333 333 334 def tfmt(when): 335 #return when * 1000.0 # stupid JS timestamps 336 return "%.6f" % when 337 # the timeline markers represent UTC. To make these events line up, we 338 # must supply the "Z" suffix. 339 #return "%.2f" % (1000*when) 340 t = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(when)) 341 fract = "%.6f" % (when % 1.0) 342 if fract.startswith("0."): 343 fract = fract[2:] 344 return t+"."+fract+"Z" 345 334 346 class DownloadStatusPage(DownloadResultsRendererMixin, rend.Page): 335 347 docFactory = getxmlfile("download-status.xhtml") 336 348 … … class DownloadStatusPage(DownloadResultsRendererMixin, rend.Page): 338 350 rend.Page.__init__(self, data) 339 351 self.download_status = data 340 352 353 def child_timeline(self, ctx): 354 return DownloadStatusTimelinePage(self.download_status) 355 341 356 def download_results(self): 342 357 return defer.maybeDeferred(self.download_status.get_results) 343 358 344 359 def relative_time(self, t): 345 360 if t is None: 346 361 return t 347 if self.download_status. startedis not None:348 return t - self.download_status. started362 if self.download_status.first_timestamp is not None: 363 return t - self.download_status.first_timestamp 349 364 return t 350 365 def short_relative_time(self, t): 351 366 t = self.relative_time(t) … … class DownloadStatusPage(DownloadResultsRendererMixin, rend.Page): 353 368 return "" 354 369 return "+%.6fs" % t 355 370 356 def renderHTTP(self, ctx): 357 req = inevow.IRequest(ctx) 358 t = get_arg(req, "t") 359 if t == "json": 360 return self.json(req) 361 return rend.Page.renderHTTP(self, ctx) 362 363 def json(self, req): 364 req.setHeader("content-type", "text/plain") 365 data = {} 366 dyhb_events = [] 367 for serverid,requests in self.download_status.dyhb_requests.iteritems(): 368 for req in requests: 369 dyhb_events.append( (base32.b2a(serverid),) + req ) 370 dyhb_events.sort(key=lambda req: req[1]) 371 data["dyhb"] = dyhb_events 372 request_events = [] 373 for serverid,requests in self.download_status.requests.iteritems(): 374 for req in requests: 375 request_events.append( (base32.b2a(serverid),) + req ) 376 request_events.sort(key=lambda req: (req[4],req[1])) 377 data["requests"] = request_events 378 data["segment"] = self.download_status.segment_events 379 data["read"] = self.download_status.read_events 371 def _find_overlap(self, events, start_key, end_key): 372 # given a list of event dicts, return a new list in which each event 373 # has an extra "row" key (an int, starting at 0). This is a hint to 374 # our JS frontend about how to overlap the parts of the graph it is 375 # drawing. 376 377 # we must always make a copy, since we're going to be adding "row" 378 # keys and don't want to change the original objects. If we're 379 # stringifying serverids, we'll also be changing the serverid keys. 380 new_events = [] 381 rows = [] 382 for ev in events: 383 ev = ev.copy() 384 if "serverid" in ev: 385 ev["serverid"] = base32.b2a(ev["serverid"]) 386 # find an empty slot in the rows 387 free_slot = None 388 for row,finished in enumerate(rows): 389 if finished is not None: 390 if ev[start_key] > finished: 391 free_slot = row 392 break 393 if free_slot is None: 394 free_slot = len(rows) 395 rows.append(ev[end_key]) 396 else: 397 rows[free_slot] = ev[end_key] 398 ev["row"] = free_slot 399 new_events.append(ev) 400 return new_events 401 402 def _find_overlap_requests(self, events): 403 """We compute a three-element 'row tuple' for each event: (serverid, 404 shnum, row). All elements are ints. The first is a mapping from 405 serverid to group number, the second is a mapping from shnum to 406 subgroup number. The third is a row within the subgroup. 407 408 We also return a list of lists of rowcounts, so renderers can decide 409 how much vertical space to give to each row. 410 """ 411 412 serverid_to_group = {} 413 groupnum_to_rows = {} # maps groupnum to a table of rows. Each table 414 # is a list with an element for each row number 415 # (int starting from 0) that contains a 416 # finish_time, indicating that the row is empty 417 # beyond that time. If finish_time is None, it 418 # indicate a response that has not yet 419 # completed, so the row cannot be reused. 420 new_events = [] 421 for ev in events: 422 # DownloadStatus promises to give us events in temporal order 423 ev = ev.copy() 424 ev["serverid"] = base32.b2a(ev["serverid"]) 425 if ev["serverid"] not in serverid_to_group: 426 groupnum = len(serverid_to_group) 427 serverid_to_group[ev["serverid"]] = groupnum 428 groupnum = serverid_to_group[ev["serverid"]] 429 if groupnum not in groupnum_to_rows: 430 groupnum_to_rows[groupnum] = [] 431 rows = groupnum_to_rows[groupnum] 432 # find an empty slot in the rows 433 free_slot = None 434 for row,finished in enumerate(rows): 435 if finished is not None: 436 if ev["start_time"] > finished: 437 free_slot = row 438 break 439 if free_slot is None: 440 free_slot = len(rows) 441 rows.append(ev["finish_time"]) 442 else: 443 rows[free_slot] = ev["finish_time"] 444 ev["row"] = (groupnum, free_slot) 445 new_events.append(ev) 446 # maybe also return serverid_to_group, groupnum_to_rows, and some 447 # indication of the highest finish_time 448 # 449 # actually, return the highest rownum for each groupnum 450 highest_rownums = [len(groupnum_to_rows[groupnum]) 451 for groupnum in range(len(serverid_to_group))] 452 return new_events, highest_rownums 453 454 def child_timeline_parameters(self, ctx): 455 ds = self.download_status 456 d = { "start": tfmt(ds.started), 457 "end": tfmt(ds.started+2.0), 458 } 459 return simplejson.dumps(d, indent=1) + "\n" 460 461 def child_event_json(self, ctx): 462 inevow.IRequest(ctx).setHeader("content-type", "text/plain") 463 data = { } # this will be returned to the GET 464 ds = self.download_status 465 466 data["read"] = self._find_overlap(ds.read_events, 467 "start_time", "finish_time") 468 data["segment"] = self._find_overlap(ds.segment_events, 469 "start_time", "finish_time") 470 data["dyhb"] = self._find_overlap(ds.dyhb_requests, 471 "start_time", "finish_time") 472 data["block"],data["block_rownums"] = self._find_overlap_requests(ds.block_requests) 473 474 servernums = {} 475 serverid_strings = {} 476 for d_ev in data["dyhb"]: 477 if d_ev["serverid"] not in servernums: 478 servernum = len(servernums) 479 servernums[d_ev["serverid"]] = servernum 480 #title= "%s: %s" % ( ",".join([str(shnum) for shnum in shnums])) 481 serverid_strings[servernum] = d_ev["serverid"][:4] 482 data["server_info"] = dict([(serverid, {"num": servernums[serverid], 483 "color": self.color(base32.a2b(serverid)), 484 "short": serverid_strings[servernum], 485 }) 486 for serverid in servernums.keys()]) 487 data["num_serverids"] = len(serverid_strings) 488 data["serverids"] = serverid_strings; 489 data["bounds"] = {"min": ds.first_timestamp, 490 "max": ds.last_timestamp, 491 } 492 # for testing 493 ## data["bounds"]["max"] = tfmt(max([d_ev["finish_time"] 494 ## for d_ev in data["dyhb"] 495 ## if d_ev["finish_time"] is not None] 496 ## )) 380 497 return simplejson.dumps(data, indent=1) + "\n" 381 498 499 def render_timeline_link(self, ctx, data): 500 from nevow import url 501 return T.a(href=url.URL.fromContext(ctx).child("timeline"))["timeline"] 502 503 def _rate_and_time(self, bytes, seconds): 504 time_s = self.render_time(None, seconds) 505 if seconds != 0: 506 rate = self.render_rate(None, 1.0 * bytes / seconds) 507 return T.span(title=rate)[time_s] 508 return T.span[time_s] 509 382 510 def render_events(self, ctx, data): 383 511 if not self.download_status.storage_index: 384 512 return … … class DownloadStatusPage(DownloadResultsRendererMixin, rend.Page): 388 516 t = T.table(class_="status-download-events") 389 517 t[T.tr[T.td["serverid"], T.td["sent"], T.td["received"], 390 518 T.td["shnums"], T.td["RTT"]]] 391 dyhb_events = [] 392 for serverid,requests in self.download_status.dyhb_requests.iteritems(): 393 for req in requests: 394 dyhb_events.append( (serverid,) + req ) 395 dyhb_events.sort(key=lambda req: req[1]) 396 for d_ev in dyhb_events: 397 (serverid, sent, shnums, received) = d_ev 519 for d_ev in self.download_status.dyhb_requests: 520 serverid = d_ev["serverid"] 521 sent = d_ev["start_time"] 522 shnums = d_ev["response_shnums"] 523 received = d_ev["finish_time"] 398 524 serverid_s = idlib.shortnodeid_b2a(serverid) 399 525 rtt = None 400 526 if received is not None: … … class DownloadStatusPage(DownloadResultsRendererMixin, rend.Page): 413 539 T.td["time"], T.td["decrypttime"], T.td["pausedtime"], 414 540 T.td["speed"]]] 415 541 for r_ev in self.download_status.read_events: 416 (start, length, requesttime, finishtime, bytes, decrypt, paused) = r_ev 417 if finishtime is not None: 418 rtt = finishtime - requesttime - paused 542 start = r_ev["start"] 543 length = r_ev["length"] 544 bytes = r_ev["bytes_returned"] 545 decrypt_time = "" 546 if bytes: 547 decrypt_time = self._rate_and_time(bytes, r_ev["decrypt_time"]) 548 speed, rtt = "","" 549 if r_ev["finish_time"] is not None: 550 rtt = r_ev["finish_time"] - r_ev["start_time"] - r_ev["paused_time"] 419 551 speed = self.render_rate(None, compute_rate(bytes, rtt)) 420 552 rtt = self.render_time(None, rtt) 421 decrypt = self.render_time(None, decrypt) 422 paused = self.render_time(None, paused) 423 else: 424 speed, rtt, decrypt, paused = "","","","" 553 paused = self.render_time(None, r_ev["paused_time"]) 554 425 555 t[T.tr[T.td["[%d:+%d]" % (start, length)], 426 T.td[srt(requesttime)], T.td[srt(finishtime)], 427 T.td[bytes], T.td[rtt], T.td[decrypt], T.td[paused], 556 T.td[srt(r_ev["start_time"])], T.td[srt(r_ev["finish_time"])], 557 T.td[bytes], T.td[rtt], 558 T.td[decrypt_time], T.td[paused], 428 559 T.td[speed], 429 560 ]] 430 561 l["Read Events:", t] 431 562 432 563 t = T.table(class_="status-download-events") 433 t[T.tr[T.td["type"], T.td["segnum"], T.td["when"], T.td["range"], 564 t[T.tr[T.td["segnum"], T.td["start"], T.td["active"], T.td["finish"], 565 T.td["range"], 434 566 T.td["decodetime"], T.td["segtime"], T.td["speed"]]] 435 reqtime = (None, None)436 567 for s_ev in self.download_status.segment_events: 437 (etype, segnum, when, segstart, seglen, decodetime) = s_ev 438 if etype == "request": 439 t[T.tr[T.td["request"], T.td["seg%d" % segnum], 440 T.td[srt(when)]]] 441 reqtime = (segnum, when) 442 elif etype == "delivery": 443 if reqtime[0] == segnum: 444 segtime = when - reqtime[1] 568 range_s = "" 569 segtime_s = "" 570 speed = "" 571 decode_time = "" 572 if s_ev["finish_time"] is not None: 573 if s_ev["success"]: 574 segtime = s_ev["finish_time"] - s_ev["active_time"] 575 segtime_s = self.render_time(None, segtime) 576 seglen = s_ev["segment_length"] 577 range_s = "[%d:+%d]" % (s_ev["segment_start"], seglen) 445 578 speed = self.render_rate(None, compute_rate(seglen, segtime)) 446 segtime = self.render_time(None, segtime)579 decode_time = self._rate_and_time(seglen, s_ev["decode_time"]) 447 580 else: 448 segtime, speed = "", "" 449 t[T.tr[T.td["delivery"], T.td["seg%d" % segnum], 450 T.td[srt(when)], 451 T.td["[%d:+%d]" % (segstart, seglen)], 452 T.td[self.render_time(None,decodetime)], 453 T.td[segtime], T.td[speed]]] 454 elif etype == "error": 455 t[T.tr[T.td["error"], T.td["seg%d" % segnum]]] 581 # error 582 range_s = "error" 583 else: 584 # not finished yet 585 pass 586 587 t[T.tr[T.td["seg%d" % s_ev["segment_number"]], 588 T.td[srt(s_ev["start_time"])], 589 T.td[srt(s_ev["active_time"])], 590 T.td[srt(s_ev["finish_time"])], 591 T.td[range_s], 592 T.td[decode_time], 593 T.td[segtime_s], T.td[speed]]] 456 594 l["Segment Events:", t] 457 595 458 596 t = T.table(border="1") 459 597 t[T.tr[T.td["serverid"], T.td["shnum"], T.td["range"], 460 T.td["txtime"], T.td["rxtime"], T.td["received"], T.td["RTT"]]] 461 reqtime = (None, None) 462 request_events = [] 463 for serverid,requests in self.download_status.requests.iteritems(): 464 for req in requests: 465 request_events.append( (serverid,) + req ) 466 request_events.sort(key=lambda req: (req[4],req[1])) 467 for r_ev in request_events: 468 (peerid, shnum, start, length, sent, receivedlen, received) = r_ev 598 T.td["txtime"], T.td["rxtime"], 599 T.td["received"], T.td["RTT"]]] 600 for r_ev in self.download_status.block_requests: 469 601 rtt = None 470 if received is not None: 471 rtt = received - sent 472 peerid_s = idlib.shortnodeid_b2a(peerid) 473 t[T.tr(style="background: %s" % self.color(peerid))[ 474 T.td[peerid_s], T.td[shnum], 475 T.td["[%d:+%d]" % (start, length)], 476 T.td[srt(sent)], T.td[srt(received)], T.td[receivedlen], 602 if r_ev["finish_time"] is not None: 603 rtt = r_ev["finish_time"] - r_ev["start_time"] 604 serverid_s = idlib.shortnodeid_b2a(r_ev["serverid"]) 605 t[T.tr(style="background: %s" % self.color(r_ev["serverid"]))[ 606 T.td[serverid_s], T.td[r_ev["shnum"]], 607 T.td["[%d:+%d]" % (r_ev["start"], r_ev["length"])], 608 T.td[srt(r_ev["start_time"])], T.td[srt(r_ev["finish_time"])], 609 T.td[r_ev["response_length"] or ""], 477 610 T.td[self.render_time(None, rtt)], 478 611 ]] 479 612 l["Requests:", t] … … class DownloadStatusPage(DownloadResultsRendererMixin, rend.Page): 524 657 def render_status(self, ctx, data): 525 658 return data.get_status() 526 659 660 class DownloadStatusTimelinePage(rend.Page): 661 docFactory = getxmlfile("download-status-timeline.xhtml") 662 663 def render_started(self, ctx, data): 664 TIME_FORMAT = "%H:%M:%S %d-%b-%Y" 665 started_s = time.strftime(TIME_FORMAT, 666 time.localtime(data.get_started())) 667 return started_s + " (%s)" % data.get_started() 668 669 def render_si(self, ctx, data): 670 si_s = base32.b2a_or_none(data.get_storage_index()) 671 if si_s is None: 672 si_s = "(None)" 673 return si_s 674 675 def render_helper(self, ctx, data): 676 return {True: "Yes", 677 False: "No"}[data.using_helper()] 678 679 def render_total_size(self, ctx, data): 680 size = data.get_size() 681 if size is None: 682 return "(unknown)" 683 return size 684 685 def render_progress(self, ctx, data): 686 progress = data.get_progress() 687 # TODO: make an ascii-art bar 688 return "%.1f%%" % (100.0 * progress) 689 690 def render_status(self, ctx, data): 691 return data.get_status() 692 527 693 class RetrieveStatusPage(rend.Page, RateAndTimeMixin): 528 694 docFactory = getxmlfile("retrieve-status.xhtml") 529 695 -
new file viz-notes.org
diff --git a/viz-notes.org b/viz-notes.org new file mode 100644 index 0000000..1ae033d
- + 1 2 * layout 3 ** read() requests 4 - possibly overlapping: code should find minimum number of rows 5 ** segment events (request/delivery/error) 6 - also possibly overlapping, use minimum rows 7 - might be nice to show which is active at any given time 8 ** DYHB queries+responses 9 - completely overlapping, use exactly one row per server 10 ** server block-read requests (send/receive/error) 11 - use one cluster per server 12 - lots of overlapping reads 13 - within a cluster, use lowest available row 14 - 3-tuple Y axis: (serverid, shnum, overlaps) 15 ** ideally, tahoe should serve raw data and let JS do the sorting 16 - but my JS is not that good 17 - maybe just provide a hint: include a row number in each event, which 18 tells you how to overlap them 19 - multiple parts, joined with "-", use as JS dict keys 20 21 * a graph that shows Y=segment-offset, X=start/finish time 22 23 * a scatter plot that shows segnum-tree-height versus finish-start 24 - a local download showed segments that needed a lot of hash nodes taking 25 way more time than others