diff --git a/README.rst b/README.rst index 75c2986..a8d1a6e 100644 --- a/README.rst +++ b/README.rst @@ -10,9 +10,7 @@ be pasted in it. The idea is that one can (probably...) not be legally entitled to `moderate the pastebin content`_ as they have no way to decrypt it. -It's an Python implementation of the -`zerobin project`_ under the `WTF licence`_. It's easy to -install even if you know nothing about Python. +It's an Python implementation of the `zerobin project`_, created by sebsauvage, under the `WTF licence`_. For now tested with IE9, and the last opera, safari, chrome and FF. @@ -22,7 +20,7 @@ but in short:: pip install zerobin zerobin -0bin runs on Python 2.7 and Python 3.4. +0bin runs on Python 3.7. How it works ============= @@ -74,7 +72,6 @@ Technologies used - Cherrypy_ (server only) - `node.js`_ (for optional command-line tool only) - Known issues ============ diff --git a/zerobin/cmd.py b/zerobin/cmd.py index dd983a2..d7d40b1 100644 --- a/zerobin/cmd.py +++ b/zerobin/cmd.py @@ -31,6 +31,7 @@ def runserver( server="cherrypy", ): + debug = True if version: print("0bin V%s" % settings.VERSION) sys.exit(0) diff --git a/zerobin/routes.py b/zerobin/routes.py index 1031766..6fd5321 100644 --- a/zerobin/routes.py +++ b/zerobin/routes.py @@ -2,6 +2,7 @@ # coding: utf-8 from __future__ import unicode_literals, absolute_import, print_function +import pdb """ Script including controller, rooting, and dependency management. @@ -24,84 +25,90 @@ from datetime import datetime, timedelta # add project dir and libs dir to the PYTHON PATH to ensure they are # importable -from zerobin.utils import (settings, SettingsValidationError, - drop_privileges, dmerge) +from zerobin.utils import settings, SettingsValidationError, drop_privileges, dmerge import bottle -from bottle import (Bottle, run, static_file, view, request) +from bottle import Bottle, run, static_file, view, request from zerobin.paste import Paste app = Bottle() GLOBAL_CONTEXT = { - 'settings': settings, - 'pastes_count': Paste.get_pastes_count(), - 'refresh_counter': datetime.now() + "settings": settings, + "pastes_count": Paste.get_pastes_count(), + "refresh_counter": datetime.now(), } -@app.route('/') -@view('home') +@app.route("/") +@view("home") def index(): return GLOBAL_CONTEXT -@app.route('/faq/') -@view('faq') +@app.route("/faq/") +@view("faq") def faq(): return GLOBAL_CONTEXT -@app.route('/paste/create', method='POST') +@app.route("/paste/create", method="POST") def create_paste(): + try: body = urlparse.parse_qs(request.body.read(int(settings.MAX_SIZE * 1.1))) except ValueError: - return {'status': 'error', 'message': "Wrong data payload."} + return {"status": "error", "message": "Wrong data payload."} try: - - content = "".join(x.decode('utf8') for x in body[b'content']) + content = "".join(x.decode("utf8") for x in body[b"content"]) except (UnicodeDecodeError, KeyError): - return {'status': 'error', - 'message': "Encoding error: the paste couldn't be saved."} + return { + "status": "error", + "message": "Encoding error: the paste couldn't be saved.", + } if '{"iv":' not in content: # reject silently non encrypted content - return {'status': 'error', 'message': "Wrong data payload."} + return {"status": "error", "message": "Wrong data payload."} # check size of the paste. if more than settings return error # without saving paste. prevent from unusual use of the # system. need to be improved if 0 < len(content) < settings.MAX_SIZE: - expiration = body.get(b'expiration', ['burn_after_reading'])[0] - paste = Paste(expiration=expiration.decode('utf8'), content=content, - uuid_length=settings.PASTE_ID_LENGTH) + expiration = body.get(b"expiration", [b"burn_after_reading"])[0] + paste = Paste( + expiration=expiration.decode("utf8"), + content=content, + uuid_length=settings.PASTE_ID_LENGTH, + ) paste.save() # display counter if settings.DISPLAY_COUNTER: - #increment paste counter + # increment paste counter paste.increment_counter() # if refresh time elapsed pick up new counter value now = datetime.now() - timeout = (GLOBAL_CONTEXT['refresh_counter'] - + timedelta(seconds=settings.REFRESH_COUNTER)) + timeout = GLOBAL_CONTEXT["refresh_counter"] + timedelta( + seconds=settings.REFRESH_COUNTER + ) if timeout < now: - GLOBAL_CONTEXT['pastes_count'] = Paste.get_pastes_count() - GLOBAL_CONTEXT['refresh_counter'] = now + GLOBAL_CONTEXT["pastes_count"] = Paste.get_pastes_count() + GLOBAL_CONTEXT["refresh_counter"] = now - return {'status': 'ok', 'paste': paste.uuid} + return {"status": "ok", "paste": paste.uuid} - return {'status': 'error', - 'message': "Serveur error: the paste couldn't be saved. " - "Please try later."} + return { + "status": "error", + "message": "Serveur error: the paste couldn't be saved. " "Please try later.", + } -@app.route('/paste/:paste_id') -@view('paste') +@app.route("/paste/:paste_id") +@view("paste") def display_paste(paste_id): now = datetime.now() @@ -115,9 +122,8 @@ def display_paste(paste_id): # we don't delete the paste because it means it's the redirection # to the paste that happens during the paste creation try: - keep_alive = paste.expiration.split('#')[1] - keep_alive = datetime.strptime(keep_alive, - '%Y-%m-%d %H:%M:%S.%f') + keep_alive = paste.expiration.split("#")[1] + keep_alive = datetime.strptime(keep_alive, "%Y-%m-%d %H:%M:%S.%f") keep_alive = now < keep_alive + timedelta(seconds=10) except IndexError: keep_alive = False @@ -131,35 +137,34 @@ def display_paste(paste_id): except (TypeError, ValueError): return error404(ValueError) - context = {'paste': paste, 'keep_alive': keep_alive} + context = {"paste": paste, "keep_alive": keep_alive} return dmerge(context, GLOBAL_CONTEXT) @app.error(404) -@view('404') +@view("404") def error404(code): return GLOBAL_CONTEXT -@app.route('/static/') +@app.route("/static/") def server_static(filename): return static_file(filename, root=settings.STATIC_FILES_ROOT) -def get_app(debug=None, settings_file='', - compressed_static=None, settings=settings): +def get_app(debug=None, settings_file="", compressed_static=None, settings=settings): """ Return a tuple (settings, app) configured using passed parameters and/or a setting file. """ - settings_file = settings_file or os.environ.get('ZEROBIN_SETTINGS_FILE') + settings_file = settings_file or os.environ.get("ZEROBIN_SETTINGS_FILE") if settings_file: settings.update_with_file(os.path.realpath(settings_file)) if settings.PASTE_ID_LENGTH < 4: - raise SettingsValidationError('PASTE_ID_LENGTH cannot be lower than 4') + raise SettingsValidationError("PASTE_ID_LENGTH cannot be lower than 4") if compressed_static is not None: settings.COMPRESSED_STATIC_FILES = compressed_static diff --git a/zerobin/static/css/style.css b/zerobin/static/css/style.css index 7d19c85..76f3b2b 100644 --- a/zerobin/static/css/style.css +++ b/zerobin/static/css/style.css @@ -1,223 +1,239 @@ +[v-cloak] { + display: none +} + +.noscript { + position: relative; + top: 25%; + border: 25px solid red; +} + /* logo */ - .brand { - font-size: 38px !important; - padding: 0 55px 3px !important; + font-size: 38px !important; + padding: 0 55px 3px !important; - text-shadow: 0 1px 0 rgba(255, 255, 255, .1), 0 0 30px rgba(255, 255, 255, .125); - -webkit-transition: all .2s linear; - -moz-transition: all .2s linear; - -o-transition: all .2s linear; - -ms-transition: all .2s linear; - transition: all .2s linear; + text-shadow: 0 1px 0 rgba(255, 255, 255, .1), 0 0 30px rgba(255, 255, 255, .125); + -webkit-transition: all .2s linear; + -moz-transition: all .2s linear; + -o-transition: all .2s linear; + -ms-transition: all .2s linear; + transition: all .2s linear; } .brand span { - font-size: 48px; - line-height: 0; + font-size: 48px; + line-height: 0; } .brand em { - display: inline; - color: #D40202; - font-size: 27px; + display: inline; + color: #D40202; + font-size: 27px; } .about { - line-height: 13px; - font-style: italic; - text-align: right; - padding-top: 9px; - margin-bottom: 0 !important; + line-height: 13px; + font-style: italic; + text-align: right; + padding-top: 9px; + margin-bottom: 0 !important; } .center { - text-align: center; + text-align: center; } -.about span{ - font-size: 10px; +.about span { + font-size: 10px; } /* body & other stuff */ body { - padding-top: 60px; - padding-bottom: 40px; + padding-top: 60px; + padding-bottom: 40px; } + .sidebar-nav { - padding: 9px 0; + padding: 9px 0; } select { - width: 135px; + width: 135px; } label { - display: inline; - margin-left: 18px; - font-style: italic; - font-size: 11px; - color: #888; + display: inline; + margin-left: 18px; + font-style: italic; + font-size: 11px; + color: #888; } -ul, ol { - padding: 0; - margin: 0; +ul, +ol { + padding: 0; + margin: 0; } li { - margin-left: -9px; + margin-left: -9px; } - p { - margin: 0 0 20px; + margin: 0 0 20px; } .grey { - color: #999; + color: #999; } .nav-list { - padding-right: 0px !important; - font-size: 12px; + padding-right: 0px !important; + font-size: 12px; } blockquote { - width: 630px; - float: left; + width: 630px; + float: left; } h4 p { - float: left; - font-size: 80px; - text-shadow: 1px 3px 1px #DDD, 0 0 4px #333; - -webkit-transition: all 0.2s linear; - -o-transition: all .2s linear; - -ms-transition: all .2s linear; - -moz-transition: all .2s linear; - transition: all .2s linear; - margin-right: 7px; - margin-top: 3px; + float: left; + font-size: 80px; + text-shadow: 1px 3px 1px #DDD, 0 0 4px #333; + -webkit-transition: all 0.2s linear; + -o-transition: all .2s linear; + -ms-transition: all .2s linear; + -moz-transition: all .2s linear; + transition: all .2s linear; + margin-right: 7px; + margin-top: 3px; } h4#pixels-total { - position: relative; - width: 166px; - float: right; - margin: 8px 0 0 0; - padding: 0 0 0 54px; - font-size: 1.1em; - line-height: 1.4; - font-weight: normal; - color: #777; - -webkit-border-top-right-radius: 6px; - -webkit-border-top-left-radius: 20px; - -moz-border-top-right-radius: 6px; - -moz-border-top-left-radius: 20px; - border-top-right-radius: 6px; - border-top-left-radius: 20px; + position: relative; + width: 166px; + float: right; + margin: 8px 0 0 0; + padding: 0 0 0 54px; + font-size: 1.1em; + line-height: 1.4; + font-weight: normal; + color: #777; + -webkit-border-top-right-radius: 6px; + -webkit-border-top-left-radius: 20px; + -moz-border-top-right-radius: 6px; + -moz-border-top-left-radius: 20px; + border-top-right-radius: 6px; + border-top-left-radius: 20px; } .greetings { - clear: both; - margin: 0 auto; - text-align: center; - margin-top: 40px; + clear: both; + margin: 0 auto; + text-align: center; + margin-top: 40px; } .alert .title { - display:block; + display: block; } /* Home */ .btn-group { - float:left; + float: left; } html.file-upload p.file-upload { - float: left; - margin: 22px 0px 0px 21px; - display: none; + float: left; + margin: 22px 0px 0px 21px; + display: none; } html.file-upload p.file-upload { - display:inherit; + display: inherit; } html.no-file-upload p.file-upload { - display:none; + display: none; } - input.btn-upload { - position: relative; - left: -6px; - width: 100px; - z-index: 1; - margin-top: -13px; + position: relative; + left: -6px; + width: 100px; + z-index: 1; + margin-top: -13px; } input.hide-upload { - position: relative; - left: -110px; - -moz-opacity: 0; - filter: alpha(opacity=0); - opacity: 0 ; - z-index: 2; - width: 100px; - margin-top: -20px; - cursor: pointer; - cursor: hand; - height: 49px; + position: relative; + left: -110px; + -moz-opacity: 0; + filter: alpha(opacity=0); + opacity: 0; + z-index: 2; + width: 100px; + margin-top: -20px; + cursor: pointer; + cursor: hand; + height: 49px; } - /* Paste Page */ #paste-content { - background-color: white; - padding:1em; + background-color: white; + padding: 1em; } - #paste-content.linenums { - padding-left:0; + padding-left: 0; } .submit-form { - display:none; + display: none; } .paste-option { - float:right; + float: right; } -a#clip-button.hover{ - cursor:pointer; - text-decoration:underline; +a#clip-button.hover { + cursor: pointer; + text-decoration: underline; } -li.L0, li.L1, li.L2, li.L3, li.L4, -li.L5, li.L6, li.L7, li.L8, li.L9 -{ - list-style-type: decimal; - background: inherit; +li.L0, +li.L1, +li.L2, +li.L3, +li.L4, +li.L5, +li.L6, +li.L7, +li.L8, +li.L9 { + list-style-type: decimal; + background: inherit; } .prettyprint.linenums { -webkit-box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0; - -moz-box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0; - box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0; + -moz-box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0; + box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0; } /* Specify class=linenums on a pre to get line numbering */ ol.linenums { - margin: 0 0 0 55px; /* IE indents via margin-left */ + margin: 0 0 0 55px; + /* IE indents via margin-left */ } + ol.linenums li { color: #bebec5; line-height: 18px; @@ -231,160 +247,154 @@ ol.linenums li { } pre { - font-family: Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, monospace, serif; - line-height: 21px; - font-size: 12px; + font-family: Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, monospace, serif; + line-height: 21px; + font-size: 12px; } .kwd { -color: #66F; + color: #66F; } -.pun, .opn, .clo { -color: #0A0; +.pun, +.opn, +.clo { + color: #0A0; } .lit { -color: #933; + color: #933; } .com { -color: #C0C; + color: #C0C; } - /* Common css */ form { - padding-bottom:3em !important; - padding-right: 17px; + padding-bottom: 3em !important; + padding-right: 17px; } form textarea { - overflow-y:auto; - min-height:250px; + overflow-y: auto; + min-height: 250px; } -button.btn, input[type="submit"].btn { - margin-left: 5px; +button.btn, +input[type="submit"].btn { + margin-left: 5px; } .well { - padding-bottom: 40px; - padding-right: 17px; + padding-bottom: 40px; + padding-right: 17px; } .legal { - margin: 0 auto; - width: 300px; - text-align: center; - margin-top: 30px; + margin: 0 auto; + width: 300px; + text-align: center; + margin-top: 30px; } .btn { - margin-left: 5px; + margin-left: 5px; } -.btn-primary, .btn-danger { - position:relative; - top:-4px; -} - -#alert-template { - display: none; +.btn-primary, +.btn-danger { + position: relative; + top: -4px; } /** Progress bar */ .progress { - display:none; + width: 100%; } .progress .bar { - width: 25%; - text-indent: 10px; - text-align:left; + width: 25%; + text-indent: 10px; + text-align: left; } .lnk-option canvas { - vertical-align:middle; - margin-right:10px; + vertical-align: middle; + margin-right: 10px; } - /* Previous paste list */ .previous-pastes .item { - margin-top:5px; - vertical-align:middle; - line-height:24px; - padding-left:1em; + margin-top: 5px; + vertical-align: middle; + line-height: 24px; + padding-left: 1em; } li.item { - margin-left: -13px; - margin-right: -5px; + margin-left: -13px; + margin-right: -5px; } .previous-pastes canvas { - display:block; - float:left; - margin-right:5px; + display: block; + float: left; + margin-right: 5px; } html.local-storage .no-local-storage { - display:none; + display: none; } html.no-local-storage .local-storage { - display:none; + display: none; } canvas { - border: 1px solid white; -} - -#wrap-content { - display: none; + border: 1px solid white; } .noscript { - text-align: center; - color: red; - font-weight: bold; + text-align: center; + color: red; + font-weight: bold; } #faq dt { - margin:2em 0 1em 0; + margin: 2em 0 1em 0; } #faq p { - margin:1em; + margin: 1em; } #force-coloration { - text-decoration:underline; + text-decoration: underline; } #expiration-tag { - float:right; - margin:1em; - background:grey; - color:white; - font-size:0.8em; - padding:0 1ex; - opacity: 0.5; - filter: alpha(opacity=50); - font-weight:bold; - -webkit-border-radius: 5px; - -moz-border-radius: 5px; - border-radius: 5px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; + float: right; + margin: 1em; + background: grey; + color: white; + font-size: 0.8em; + padding: 0 1ex; + opacity: 0.5; + filter: alpha(opacity=50); + font-weight: bold; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + -moz-background-clip: padding; + -webkit-background-clip: padding-box; + background-clip: padding-box; } #content.hover { - background-color: #eee; -} \ No newline at end of file + background-color: #eee; +} diff --git a/zerobin/static/js/ZeroClipboard.js b/zerobin/static/js/ZeroClipboard.js deleted file mode 100755 index c4b548b..0000000 --- a/zerobin/static/js/ZeroClipboard.js +++ /dev/null @@ -1,311 +0,0 @@ -// Simple Set Clipboard System -// Author: Joseph Huckaby - -var ZeroClipboard = { - - version: "1.0.7", - clients: {}, // registered upload clients on page, indexed by id - moviePath: 'ZeroClipboard.swf', // URL to movie - nextId: 1, // ID of next movie - - $: function(thingy) { - // simple DOM lookup utility function - if (typeof(thingy) == 'string') thingy = document.getElementById(thingy); - if (!thingy.addClass) { - // extend element with a few useful methods - thingy.hide = function() { this.style.display = 'none'; }; - thingy.show = function() { this.style.display = ''; }; - thingy.addClass = function(name) { this.removeClass(name); this.className += ' ' + name; }; - thingy.removeClass = function(name) { - var classes = this.className.split(/\s+/); - var idx = -1; - for (var k = 0; k < classes.length; k++) { - if (classes[k] == name) { idx = k; k = classes.length; } - } - if (idx > -1) { - classes.splice( idx, 1 ); - this.className = classes.join(' '); - } - return this; - }; - thingy.hasClass = function(name) { - return !!this.className.match( new RegExp("\\s*" + name + "\\s*") ); - }; - } - return thingy; - }, - - setMoviePath: function(path) { - // set path to ZeroClipboard.swf - this.moviePath = path; - }, - - dispatch: function(id, eventName, args) { - // receive event from flash movie, send to client - var client = this.clients[id]; - if (client) { - client.receiveEvent(eventName, args); - } - }, - - register: function(id, client) { - // register new client to receive events - this.clients[id] = client; - }, - - getDOMObjectPosition: function(obj, stopObj) { - // get absolute coordinates for dom element - var info = { - left: 0, - top: 0, - width: obj.width ? obj.width : obj.offsetWidth, - height: obj.height ? obj.height : obj.offsetHeight - }; - - while (obj && (obj != stopObj)) { - info.left += obj.offsetLeft; - info.top += obj.offsetTop; - obj = obj.offsetParent; - } - - return info; - }, - - Client: function(elem) { - // constructor for new simple upload client - this.handlers = {}; - - // unique ID - this.id = ZeroClipboard.nextId++; - this.movieId = 'ZeroClipboardMovie_' + this.id; - - // register client with singleton to receive flash events - ZeroClipboard.register(this.id, this); - - // create movie - if (elem) this.glue(elem); - } -}; - -ZeroClipboard.Client.prototype = { - - id: 0, // unique ID for us - ready: false, // whether movie is ready to receive events or not - movie: null, // reference to movie object - clipText: '', // text to copy to clipboard - handCursorEnabled: true, // whether to show hand cursor, or default pointer cursor - cssEffects: true, // enable CSS mouse effects on dom container - handlers: null, // user event handlers - - glue: function(elem, appendElem, stylesToAdd) { - // glue to DOM element - // elem can be ID or actual DOM element object - this.domElement = ZeroClipboard.$(elem); - - // float just above object, or zIndex 99 if dom element isn't set - var zIndex = 99; - if (this.domElement.style.zIndex) { - zIndex = parseInt(this.domElement.style.zIndex, 10) + 1; - } - - if (typeof(appendElem) == 'string') { - appendElem = ZeroClipboard.$(appendElem); - } - else if (typeof(appendElem) == 'undefined') { - appendElem = document.getElementsByTagName('body')[0]; - } - - // find X/Y position of domElement - var box = ZeroClipboard.getDOMObjectPosition(this.domElement, appendElem); - - // create floating DIV above element - this.div = document.createElement('div'); - var style = this.div.style; - style.position = 'absolute'; - style.left = '' + box.left + 'px'; - style.top = '' + box.top + 'px'; - style.width = '' + box.width + 'px'; - style.height = '' + box.height + 'px'; - style.zIndex = zIndex; - - if (typeof(stylesToAdd) == 'object') { - for (addedStyle in stylesToAdd) { - style[addedStyle] = stylesToAdd[addedStyle]; - } - } - - //style.backgroundColor = '#f00'; // debug - - appendElem.appendChild(this.div); - - this.div.innerHTML = this.getHTML( box.width, box.height ); - }, - - getHTML: function(width, height) { - // return HTML for movie - var html = ''; - var flashvars = 'id=' + this.id + - '&width=' + width + - '&height=' + height; - - if (navigator.userAgent.match(/MSIE/)) { - // IE gets an OBJECT tag - var protocol = location.href.match(/^https/i) ? 'https://' : 'http://'; - html += ''; - } - else { - // all other browsers get an EMBED tag - html += ''; - } - return html; - }, - - hide: function() { - // temporarily hide floater offscreen - if (this.div) { - this.div.style.left = '-2000px'; - } - }, - - show: function() { - // show ourselves after a call to hide() - this.reposition(); - }, - - destroy: function() { - // destroy control and floater - if (this.domElement && this.div) { - this.hide(); - this.div.innerHTML = ''; - - var body = document.getElementsByTagName('body')[0]; - try { body.removeChild( this.div ); } catch(e) {;} - - this.domElement = null; - this.div = null; - } - }, - - reposition: function(elem) { - // reposition our floating div, optionally to new container - // warning: container CANNOT change size, only position - if (elem) { - this.domElement = ZeroClipboard.$(elem); - if (!this.domElement) this.hide(); - } - - if (this.domElement && this.div) { - var box = ZeroClipboard.getDOMObjectPosition(this.domElement); - var style = this.div.style; - style.left = '' + box.left + 'px'; - style.top = '' + box.top + 'px'; - } - }, - - setText: function(newText) { - // set text to be copied to clipboard - this.clipText = newText; - if (this.ready) this.movie.setText(newText); - }, - - addEventListener: function(eventName, func) { - // add user event listener for event - // event types: load, queueStart, fileStart, fileComplete, queueComplete, progress, error, cancel - eventName = eventName.toString().toLowerCase().replace(/^on/, ''); - if (!this.handlers[eventName]) this.handlers[eventName] = []; - this.handlers[eventName].push(func); - }, - - setHandCursor: function(enabled) { - // enable hand cursor (true), or default arrow cursor (false) - this.handCursorEnabled = enabled; - if (this.ready) this.movie.setHandCursor(enabled); - }, - - setCSSEffects: function(enabled) { - // enable or disable CSS effects on DOM container - this.cssEffects = !!enabled; - }, - - receiveEvent: function(eventName, args) { - // receive event from flash - eventName = eventName.toString().toLowerCase().replace(/^on/, ''); - - // special behavior for certain events - switch (eventName) { - case 'load': - // movie claims it is ready, but in IE this isn't always the case... - // bug fix: Cannot extend EMBED DOM elements in Firefox, must use traditional function - this.movie = document.getElementById(this.movieId); - if (!this.movie) { - var self = this; - setTimeout( function() { self.receiveEvent('load', null); }, 1 ); - return; - } - - // firefox on pc needs a "kick" in order to set these in certain cases - if (!this.ready && navigator.userAgent.match(/Firefox/) && navigator.userAgent.match(/Windows/)) { - var self = this; - setTimeout( function() { self.receiveEvent('load', null); }, 100 ); - this.ready = true; - return; - } - - this.ready = true; - this.movie.setText( this.clipText ); - this.movie.setHandCursor( this.handCursorEnabled ); - break; - - case 'mouseover': - if (this.domElement && this.cssEffects) { - this.domElement.addClass('hover'); - if (this.recoverActive) this.domElement.addClass('active'); - } - break; - - case 'mouseout': - if (this.domElement && this.cssEffects) { - this.recoverActive = false; - if (this.domElement.hasClass('active')) { - this.domElement.removeClass('active'); - this.recoverActive = true; - } - this.domElement.removeClass('hover'); - } - break; - - case 'mousedown': - if (this.domElement && this.cssEffects) { - this.domElement.addClass('active'); - } - break; - - case 'mouseup': - if (this.domElement && this.cssEffects) { - this.domElement.removeClass('active'); - this.recoverActive = false; - } - break; - } // switch eventName - - if (this.handlers[eventName]) { - for (var idx = 0, len = this.handlers[eventName].length; idx < len; idx++) { - var func = this.handlers[eventName][idx]; - - if (typeof(func) == 'function') { - // actual function reference - func(this, args); - } - else if ((typeof(func) == 'object') && (func.length == 2)) { - // PHP style object + method, i.e. [myObject, 'myMethod'] - func[0][ func[1] ](this, args); - } - else if (typeof(func) == 'string') { - // name of function - window[func](this, args); - } - } // foreach event handler defined - } // user defined handler for event - } - -}; diff --git a/zerobin/static/js/ZeroClipboard.swf b/zerobin/static/js/ZeroClipboard.swf deleted file mode 100755 index 13bf8e3..0000000 Binary files a/zerobin/static/js/ZeroClipboard.swf and /dev/null differ diff --git a/zerobin/static/js/behavior.js b/zerobin/static/js/behavior.js index 169b5e2..a439ee2 100644 --- a/zerobin/static/js/behavior.js +++ b/zerobin/static/js/behavior.js @@ -1,900 +1,814 @@ -/*global sjcl:true, jQuery:true, $:true, lzw:true, zerobin:true, ZeroClipboard:true, vizhash:true, prettyPrint:true, confirm:true */ -; -(function () { - "use strict"; +/*global sjcl:true, jQuery:true, lzw:true, zerobin:true, prettyPrint:true, confirm:true */ - /* Start random number generator seeding ASAP */ - sjcl.random.startCollectors(); - /* Ensure jquery use cache for ajax requests */ - $.ajaxSetup({ - cache: true - }); +/* + This file has been migrated away from jQuery, to Vue. Because of the way the code base used to be, a lot of the operation are still using imperative DOM manipulation + instead of the Vue declarative style. We haven't had the time to rewrite it completly and it's a bit of a mixed bag at the moment +*/ - /** Create a function that create inline callbacks. - We use it to create callbacks for onliners with static arguments - E.G: - $('stuff').hide(function()(console.log(1, 2, 3))) +/* Start random number generator seeding ASAP */ +sjcl.random.startCollectors(); +Vue.options.delimiters = ['{%', '%}']; - Becomes: +// Force focus for textarea (firefox hack) +setTimeout(function () { + document.querySelector('textarea').focus() +}, 100) - $('stuff').hide(mkcb(console.log, 1, 2, 3)) - */ - function mkcb(func) { - var args = arguments; - return function () { - return func.apply(func, Array.prototype.slice.call(args, 1)); - }; +const menu = new Vue({ + el: "#menu-top", + methods: { + formatEmail: (email) => { + /* Parse obfuscaded emails and make them usable */ + return "mailto:" + email.replace('__AT__', '@'); + }, } +}) +const app = new Vue({ - - /*************************** - **** 0bin utilities *** - ***************************/ - - - window.zerobin = { - /** Base64 + compress + encrypt, with callbacks before each operation, - and all of them are executed in a timed continuation to give - a change to the UI to respond. - */ - version: '0.1.1', - encrypt: function (key, content, toBase64Callback, - compressCallback, encryptCallback, doneCallback) { - - setTimeout(function () { - - content = sjcl.codec.utf8String.toBits(content); - if (toBase64Callback) { - toBase64Callback(); - } - - setTimeout(function () { - - content = sjcl.codec.base64.fromBits(content); - if (compressCallback) { - compressCallback(); - } - - setTimeout(function () { - - // content = lzw.compress(content); // Create a bug with JPG - if (encryptCallback) { - encryptCallback(); - } - - setTimeout(function () { - try { - content = sjcl.encrypt(key, content); - } catch (e) { - $('input, textarea, select, button').prop('disabled', false); - zerobin.progressBar('form.well .progress').container.hide(); - - zerobin.message('error', 'Paste could not be encrypted. Aborting.', - 'Error'); - } - if (doneCallback) { - doneCallback(content); - } - }, 250); - - }, 250); - - }, 250); - - }, 250); + el: '#wrap-content', + data: { + previousPastes: [], + downloadLink: {}, + displayBottomToolBar: false, + isUploading: false, + newPaste: { + expiration: '1_day', + content: '', }, - - /** Base64 decoding + uncompress + decrypt, with callbacks before each operation, - and all of them are executed in a timed continuation to give - a change to the UI to respond. - - This is where using a library to fake synchronicity could start to be - useful, this code is starting be difficult to read. If anyone read this - and got a suggestion, by all means, speak your mind. - */ - decrypt: function (key, content, errorCallback, uncompressCallback, - fromBase64Callback, toStringCallback, doneCallback) { - - /* Decrypt */ - setTimeout(function () { - try { - content = sjcl.decrypt(key, content); - if (uncompressCallback) { - uncompressCallback(); - } - - /* Decompress */ - setTimeout(function () { - try { - content = lzw.decompress(content); - if (fromBase64Callback) { - fromBase64Callback(); - } - - /* From base 64 to bits */ - setTimeout(function () { - try { - content = sjcl.codec.base64.toBits(content); - if (toStringCallback) { - toStringCallback(); - } - - /* From bits to string */ - setTimeout(function () { - try { - content = sjcl.codec.utf8String.fromBits(content); - if (doneCallback) { - doneCallback(content); - } - } catch (err) { - errorCallback(err); - } - - }, 250); /* "End of from bits to string" */ - - } catch (err) { - errorCallback(err); - } - - }, 250); /* End of "from base 64 to bits" */ - - } catch (err) { - errorCallback(err); - } - - }, 250); /* End of "decompress" */ - - } catch (err) { - errorCallback(err); - } - - }, 250); /* End of "decrypt" */ - }, - - /** Create a random base64-like string long enought to be suitable as - an encryption key */ - makeKey: function (entropy) { - entropy = Math.ceil(entropy / 6) * 6; /* non-6-multiple produces same-length base64 */ - var key = sjcl.bitArray.clamp( - sjcl.random.randomWords(Math.ceil(entropy / 32), 0), entropy ); - return sjcl.codec.base64.fromBits(key, 0).replace(/\=+$/, '').replace(/\//, '-'); - }, - - getFormatedDate: function (date) { - date = date || new Date(); - return ((date.getMonth() + 1) + '-' + date.getDate() + '-' + date.getFullYear()); - }, - - getFormatedTime: function (date) { - date = date || new Date(); - var h = date.getHours(), - m = date.getMinutes(), - s = date.getSeconds(); - if (h < 10) { - h = "0" + h; - } - if (m < 10) { - m = "0" + m; - } - if (s < 10) { - s = "0" + s; - } - return h + ":" + m + ":" + s; - }, - - numOrdA: function (a, b) { - return (a - b); - }, - - /** Return a reverse sorted list of all the keys in local storage that - are prefixed with with the passed version (default being this lib - version) */ - getLocalStorageKeys: function () { - var version = 'zerobinV0.1'; - var keys = []; - for (var key in localStorage) { - if (key.indexOf(version) !== -1) { - keys.push(key); - } - } - keys.sort(); - keys.reverse(); - return keys; - }, - - /** Get a tinyurl using JSONP */ - getTinyURL: function(longURL, success) { - $.ajax({ - url: 'https://www.googleapis.com/urlshortener/v1/url', - type: 'POST', - contentType: 'application/json', - data: JSON.stringify({ - "longUrl": longURL - }), - processData: false, - dataType: 'json' - }).done(function(data){ - success(data.id); - }); - }, - + messages: [], /** Check for browser support of the named featured. Store the result - and add a class to the html tag with the result */ + and add a class to the html tag with the result */ support: { + + clipboard: (function () { + var val = !!(navigator.clipboard); + document.querySelector('html').classList.add((val ? '' : 'no-') + 'clipboard'); + return val; + })(), + localStorage: (function () { - var val = !! (localStorage); - $('html').addClass((val ? '' : 'no-') + 'local-storage'); + var val = !!(localStorage); + document.querySelector('html').classList.add((val ? '' : 'no-') + 'local-storage'); return val; })(), history: (function () { - var val = !! (window.history && history.pushState); - $('html').addClass((val ? '' : 'no-') + 'history'); + var val = !!(window.history && history.pushState); + document.querySelector('html').classList.add((val ? '' : 'no-') + 'history'); return val; })(), fileUpload: (function () { var w = window; - var val = !! (w.File && w.FileReader && w.FileList && w.Blob); - $('html').addClass((val ? '' : 'no-') + 'file-upload'); + var val = !!(w.File && w.FileReader && w.FileList && w.Blob); + document.querySelector('html').classList.add((val ? '' : 'no-') + 'file-upload'); return val; })() }, - - /** Store the paste of a URL in local storate, with a storage format - version prefix and the paste date as the key */ - storePaste: function (url, date) { - - date = date || new Date(); - date = (date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate() + ' ' + zerobin.getFormatedTime(date)); - - var keys = zerobin.getLocalStorageKeys(); - - if (localStorage.length > 19) { - void localStorage.removeItem(keys[19]); - } - - localStorage.setItem('zerobinV' + zerobin.version + "#" + date, url); + isLoading: false + }, + methods: { + forceLoadPaste: (link) => { + window.location = link; + window.location.reload(); }, - /** Return a list of the previous paste url with the creation date - If the paste is from today, date format should be "at hh:ss", - else it should be "the mm-dd-yyy" - */ - getPreviousPastes: function () { - var pastes = [], - keys = zerobin.getLocalStorageKeys(), - today = zerobin.getFormatedDate(); + handleClone: () => { - $.each(keys, function (i, key) { - var pasteDateTime = key.replace(/^[^#]+#/, ''); - var displayDate = pasteDateTime.match(/^(\d+)-(\d+)-(\d+)\s/); - displayDate = displayDate[2] + '-' + displayDate[3] + '-' + displayDate[1]; - var prefix = 'the '; - if (displayDate === today) { - displayDate = pasteDateTime.split(' ')[1]; - prefix = 'at '; - } - pastes.push({ - displayDate: displayDate, - prefix: prefix, - link: localStorage.getItem(key) - }); + document.querySelector('.submit-form').style.display = "inherit"; + document.querySelector('.paste-form').style.display = "none"; + let content = document.getElementById('content'); + content.value = zerobin.getPasteContent(); + content.dispatchEvent(new Event('change')); + }, + + handleCancelClone: () => { + document.querySelector('.submit-form').style.display = "none"; + document.querySelector('.paste-form').style.display = "inherit"; + }, + + handleUpload: (files) => { + + try { + app.isUploading = true; + zerobin.upload(files); + } catch (e) { + zerobin.message('error', 'Could no upload the file', 'Error'); + } + + app.isUploading = false; + }, + + handleForceColoration: (e) => { + /* Force text coloration when clickin on link */ + + let content = document.getElementById('paste-content'); + content.classList.add('linenums'); + e.target.innerHTML = 'Applying coloration'; + prettyPrint(); + e.target.remove() + + }, + + handleSendByEmail: (e) => { + e.target.href = 'mailto:friend@example.com?body=' + window.location.toString(); + }, + + copyToClipboard: () => { + + var pasteContent = zerobin.getPasteContent(); + let promise; + + if (pasteContent.indexOf("data:image") === 0) { + + promise = fetch(pasteContent).then((res) => { + return res.blob().then(blob => { + return navigator.clipboard.write([ + new ClipboardItem({ + [blob.type]: blob + }) + ]) + }) + }) + + } else { + promise = navigator.clipboard.writeText(pasteContent); + } + + promise.then(function () { + zerobin.message('info', 'The paste is now in your clipboard', '', true); + }, function (err) { + zerobin.message('error', 'The paste could not be copied', '', true); }); - return pastes; }, - /** Return an link object with the URL as href so you can extract host, - protocol, hash, etc. - - This function use a closure to store a
parent for the - because IE requires the link be processed by it's HTML parser - for the URL to be parsed. */ - parseUrl: (function () { - - var div = document.createElement('div'); - div.innerHTML = ""; - - return function (url) { - div.firstChild.href = url; - div.innerHTML = div.innerHTML; - return div.firstChild; - }; - - })(), - - getPasteId: function (url) { - var loc = url ? zerobin.parseUrl(url) : window.location; - return loc.pathname.replace(/\/|paste/g, ''); - }, - - getPasteKey: function (url) { - var loc = url ? zerobin.parseUrl(url) : window.location; - return loc.hash.replace('#', '').replace(/(\?|&).*$/, ''); - }, - - /** Return the paste content stripted from any code coloration */ - getPasteContent: function () { - var copy = ''; - $("#paste-content li").each(function (index) { - copy = copy + $(this).text().replace(/[\u00a0]+/g, ' ') + '\n'; - }); - if (copy == '') { - copy = $("#paste-content").text(); - } - return copy; - }, - - /** Return an approximate estimate the number of bytes in a text */ - count: function (text, options) { - // Set option defaults - var crlf = /(\r?\n|\r)/g; - var whitespace = /(\r?\n|\r|\s+)/g; - options = options || {}; - options.lineBreaks = options.lineBreaks || 1; - - var length = text.length, - nonAscii = length - text.replace(/[\u0100-\uFFFF]/g, '').length, - lineBreaks = length - text.replace(crlf, '').length; - - return length + nonAscii + Math.max(0, options.lineBreaks * (lineBreaks - 1)); - }, - /** Create a message, style it and insert it in the alert box */ - message: function (type, message, title, flush, callback) { - $(window).scrollTop(0); - - if (flush) { - $('.alert-' + type).remove(); - } - - var $message = $('#alert-template').clone().attr('id', null) - .addClass('alert alert-' + type); - $('.message', $message).html(message); - - if (title) { - $('.title', $message).html(title); - } else { - $('.title', $message).remove(); - } - - $message.prependTo($('#main')).show('fadeUp', callback); - }, - - /** Return a progress bar object */ - progressBar: function (selector) { - var $container = $(selector); - var bar = { - container: $container, - elem: $container.find('.bar') - }; - bar.set = function (text, rate) { - bar.elem.text(text).css('width', rate); - }; - return bar; - }, - - /** Return an integer ranking the probability this text is any kind of - source code. */ - isCode: function (text) { - - var code_chars = /[A-Z]{3}[A-Z]+|\.[a-z]|[=:<>{}\[\]$_'"&]| {2}|\t/g; - var comments = /(:?\/\*|)|(\/\/|#)(.*?)\n/g; - var formating = /[-*=_+]{4,}/; - - var total = 0; - var size = 0; - var m = text.match(comments); - if (m) { - total += text.match(comments).length; - } - text = text.replace(comments, ''); - text.replace(formating, ''); - text = text.split('\n'); - for (var i = 0; i < text.length; i++) { - var line = text[i]; - size += line.length; - var match = line.replace(formating, '').match(code_chars); - if (match) { - total += match.length; - } - } - - return total * 1000 / size; - }, - - // prevent defaults - ignoreDrag: function (e) { - e.originalEvent.stopPropagation(); - e.originalEvent.preventDefault(); - }, - - // Handle Drop - handleDrop: function (e) { - e.originalEvent.preventDefault(); - zerobin.upload(e.originalEvent.dataTransfer.files); - $("#content").removeClass('hover'); - }, - - handleDragOver: function (e) { - zerobin.ignoreDrag(e); - $(this).addClass('hover'); - }, - - handleDragLeave: function (e) { - $(this).removeClass('hover'); - }, - - upload: function (files) { - var current_file = files[0]; - var reader = new FileReader(); - if (current_file.type.indexOf('image') == 0) { - reader.onload = function (event) { - var image = new Image(); - image.src = event.target.result; - - image.onload = function() { - var maxWidth = 1024, - maxHeight = 1024, - imageWidth = image.width, - imageHeight = image.height; - - - if (imageWidth > imageHeight) { - if (imageWidth > maxWidth) { - imageHeight *= maxWidth / imageWidth; - imageWidth = maxWidth; - } - } - else { - if (imageHeight > maxHeight) { - imageWidth *= maxHeight / imageHeight; - imageHeight = maxHeight; - } - } - - var canvas = document.createElement('canvas'); - canvas.width = imageWidth; - canvas.height = imageHeight; - image.width = imageWidth; - image.height = imageHeight; - var ctx = canvas.getContext("2d"); - ctx.drawImage(this, 0, 0, imageWidth, imageHeight); - - var paste = canvas.toDataURL(current_file.type); - $('#content').val(paste).trigger('change'); - $('#content').hide(); - $(image).css('max-width', '742px'); - $('#content').after(image); - } - } - reader.readAsDataURL(current_file); - } else { - reader.onload = function (event) { - $('#content').val(event.target.result).trigger('change'); - }; - reader.readAsText(current_file); - } - } - }; - - - /*************************** - **** On document ready *** - ****************************/ - - - $(function () { - /** - On the create paste page: - On click on the send button, compress and encrypt data before - posting it using ajax. Then redirect to the address of the - newly created paste, adding the key in the hash. -*/ - $('.btn-primary').live("click", function (e) { + On the create paste page: + On click on the send button, compress and encrypt data before + posting it using ajax. Then redirect to the address of the + newly created paste, adding the key in the hash. + */ + + encryptAndSendPaste: (e) => { e.preventDefault(); - var paste = $('textarea').val(); + var paste = document.querySelector('textarea').value; if (paste.trim()) { - var $form = $('input, textarea, select, button').prop('disabled', true); + var form = document.querySelectorAll('input, textarea, select, button'); + + form.forEach((node) => node.disabled = true); // set up progress bar var bar = zerobin.progressBar('form.well .progress'); - bar.container.show(); + app.isLoading = true; bar.set('Converting paste to bits...', '25%'); /* Encode, compress, encrypt and send the paste then redirect the user - to the new paste. We ensure a loading animation is updated - during the process by passing callbacks. - */ + to the new paste. We ensure a loading animation is updated + during the process by passing callbacks. + */ try { - var expiration = $('#expiration').val(); var key = zerobin.makeKey(256); zerobin.encrypt(key, paste, - mkcb(bar.set, 'Encoding to base64...', '45%'), - mkcb(bar.set, 'Compressing...', '65%'), - mkcb(bar.set, 'Encrypting...', '85%'), + () => bar.set('Encoding to base64...', '45%'), + () => bar.set('Compressing...', '65%'), + () => bar.set('Encrypting...', '85%'), - /* This block deal with sending the data, redirection or error handling */ - function (content) { + /* This block deals with sending the data, redirection or error handling */ + function (content) { - bar.set('Sending...', '95%'); - var data = { - content: content, - expiration: expiration - }; - var sizebytes = zerobin.count(JSON.stringify(data)); - var oversized = sizebytes > zerobin.max_size; // 100kb - the others header information - var readableFsize = Math.round(sizebytes / 1024); - var readableMaxsize = Math.round(zerobin.max_size / 1024); + bar.set('Sending...', '95%'); + var data = { + content: content, + expiration: app.newPaste.expiration + }; + var sizebytes = zerobin.count(JSON.stringify(data)); + var oversized = sizebytes > zerobin.max_size; // 100kb - the others header information + var readableFsize = Math.round(sizebytes / 1024); + var readableMaxsize = Math.round(zerobin.max_size / 1024); - if (oversized) { - bar.container.hide(); - $form.prop('disabled', false); - zerobin.message('error', ('The encrypted file was ' + readableFsize + - 'KB. You have reached the maximum size limit of ' + readableMaxsize + 'KB.'), - 'Warning!', true); - return; - } - - $.post('/paste/create', data) - .error(function (error) { - $form.prop('disabled', false); - bar.container.hide(); - zerobin.message( - 'error', - 'Paste could not be saved. Please try again later.', - 'Error'); - - }) - .success(function (data) { - bar.set('Redirecting to new paste...', '100%'); - - if (data.status === 'error') { - zerobin.message('error', data.message, 'Error'); - $form.prop('disabled', false); - bar.container.hide(); - } else { - var paste_url = '/paste/' + data.paste + '#' + key; - if (zerobin.support.localStorage) { - zerobin.storePaste(paste_url); - } - window.location = (paste_url); + if (oversized) { + app.isLoading = false + form.forEach((node) => node.disabled = false); + zerobin.message('error', ('The encrypted file was ' + readableFsize + + 'KB. You have reached the maximum size limit of ' + readableMaxsize + 'KB.'), + 'Warning!', true); + return; } + + fetch('/paste/create', { + method: "POST", + body: new URLSearchParams(data) + }).then(function (response) { + if (response.ok) { + bar.set('Redirecting to new paste...', '100%'); + + response.json().then((data) => { + if (data.status === 'error') { + zerobin.message('error', data.message, 'Error'); + form.forEach((node) => node.disabled = false); + app.isLoading = false + } else { + var paste_url = '/paste/' + data.paste + '#' + key; + if (app.support.localStorage) { + zerobin.storePaste(paste_url); + } + window.location = (paste_url); + } + }) + + } else { + form.forEach((node) => node.disabled = false); + app.isLoading = false + zerobin.message( + 'error', + 'Paste could not be saved. Please try again later.', + 'Error'); + } + }).catch(function (error) { + form.forEach((node) => node.disabled = false); + app.isLoading = false + zerobin.message( + 'error', + 'Paste could not be saved. Please try again later.', + 'Error'); + }); + }); - }); } catch (err) { - $form.prop('disabled', false); - bar.container.hide(); + form.forEach((node) => node.disabled = false); + app.isLoading = false zerobin.message('error', 'Paste could not be encrypted. Aborting.', 'Error'); } } + } + } +}) + +/*************************** + **** 0bin utilities *** + ***************************/ + +window.zerobin = { + /** Base64 + compress + encrypt, with callbacks before each operation, + and all of them are executed in a timed continuation to give + a change to the UI to respond. + */ + version: '0.1.1', + encrypt: function (key, content, toBase64Callback, + compressCallback, encryptCallback, doneCallback) { + + setTimeout(function () { + + content = sjcl.codec.utf8String.toBits(content); + if (toBase64Callback) { + toBase64Callback(); + } + + setTimeout(function () { + + content = sjcl.codec.base64.fromBits(content); + if (compressCallback) { + compressCallback(); + } + + setTimeout(function () { + + // content = lzw.compress(content); // Create a bug with JPG + if (encryptCallback) { + encryptCallback(); + } + + setTimeout(function () { + try { + content = sjcl.encrypt(key, content); + } catch (e) { + + document.querySelectorAll('input, textarea, select, button').forEach((node) => node.disabled = true); + + app.isLoading = false; + + zerobin.message('error', 'Paste could not be encrypted. Aborting.', + 'Error'); + } + if (doneCallback) { + doneCallback(content); + } + }, 50); + + }, 50); + + }, 50); + + }, 50); + }, + + /** Base64 decoding + uncompress + decrypt, with callbacks before each operation, + and all of them are executed in a timed continuation to give + a change to the UI to respond. + + This is where using a library to fake synchronicity could start to be + useful, this code is starting be difficult to read. If anyone read this + and got a suggestion, by all means, speak your mind. + */ + decrypt: function (key, content, errorCallback, uncompressCallback, + fromBase64Callback, toStringCallback, doneCallback) { + + /* Decrypt */ + setTimeout(function () { + try { + content = sjcl.decrypt(key, content); + if (uncompressCallback) { + uncompressCallback(); + } + + /* Decompress */ + setTimeout(function () { + try { + content = lzw.decompress(content); + if (fromBase64Callback) { + fromBase64Callback(); + } + + /* From base 64 to bits */ + setTimeout(function () { + try { + content = sjcl.codec.base64.toBits(content); + if (toStringCallback) { + toStringCallback(); + } + + /* From bits to string */ + setTimeout(function () { + try { + content = sjcl.codec.utf8String.fromBits(content); + if (doneCallback) { + doneCallback(content); + } + } catch (err) { + errorCallback(err); + } + + }, 50); /* "End of from bits to string" */ + + } catch (err) { + errorCallback(err); + } + + }, 50); /* End of "from base 64 to bits" */ + + } catch (err) { + errorCallback(err); + } + + }, 50); /* End of "decompress" */ + + } catch (err) { + errorCallback(err); + } + + }, 50); /* End of "decrypt" */ + }, + + /** Create a random base64-like string long enought to be suitable as + an encryption key */ + makeKey: function (entropy) { + entropy = Math.ceil(entropy / 6) * 6; /* non-6-multiple produces same-length base64 */ + var key = sjcl.bitArray.clamp( + sjcl.random.randomWords(Math.ceil(entropy / 32), 0), entropy); + return sjcl.codec.base64.fromBits(key, 0).replace(/\=+$/, '').replace(/\//, '-'); + }, + + getFormatedDate: function (date) { + date = date || new Date(); + return ((date.getMonth() + 1) + '-' + date.getDate() + '-' + date.getFullYear()); + }, + + getFormatedTime: function (date) { + date = date || new Date(); + var h = date.getHours(), + m = date.getMinutes(), + s = date.getSeconds(); + if (h < 10) { + h = "0" + h; + } + if (m < 10) { + m = "0" + m; + } + if (s < 10) { + s = "0" + s; + } + return h + ":" + m + ":" + s; + }, + + numOrdA: function (a, b) { + return (a - b); + }, + + /** Return a reverse sorted list of all the keys in local storage that + are prefixed with with the passed version (default being this lib + version) */ + getLocalStorageKeys: function () { + var version = 'zerobinV0.1'; + var keys = []; + for (var key in localStorage) { + if (key.indexOf(version) !== -1) { + keys.push(key); + } + } + keys.sort(); + keys.reverse(); + return keys; + }, + + /** Store the paste of a URL in local storate, with a storage format + version prefix and the paste date as the key */ + storePaste: function (url, date) { + + date = date || new Date(); + date = (date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate() + ' ' + zerobin.getFormatedTime(date)); + + var keys = zerobin.getLocalStorageKeys(); + + if (localStorage.length > 19) { + void localStorage.removeItem(keys[19]); + } + + localStorage.setItem('zerobinV' + zerobin.version + "#" + date, url); + }, + + /** Return a list of the previous paste url with the creation date + If the paste is from today, date format should be "at hh:ss", + else it should be "the mm-dd-yyy" + */ + getPreviousPastes: function () { + var keys = zerobin.getLocalStorageKeys(), + today = zerobin.getFormatedDate(); + + return keys.map(function (key, i) { + var pasteDateTime = key.replace(/^[^#]+#/, ''); + var displayDate = pasteDateTime.match(/^(\d+)-(\d+)-(\d+)\s/); + displayDate = displayDate[2] + '-' + displayDate[3] + '-' + displayDate[1]; + var prefix = 'the '; + if (displayDate === today) { + displayDate = pasteDateTime.split(' ')[1]; + prefix = 'at '; + } + let link = localStorage.getItem(key); + return { + displayDate: displayDate, + prefix: prefix, + link: link, + isCurrent: link.replace(/#[^#]+/, '') === window.location.pathname + }; }); - /** + }, + + /** Return a link object with the URL as href so you can extract host, + protocol, hash, etc. + + This function use a closure to store a
parent for the + because IE requires the link be processed by it's HTML parser + for the URL to be parsed. */ + parseUrl: (function () { + + var div = document.createElement('div'); + div.innerHTML = ""; + + return function (url) { + div.firstChild.href = url; + div.innerHTML = div.innerHTML; + return div.firstChild; + }; + + })(), + + getPasteId: function (url) { + var loc = url ? zerobin.parseUrl(url) : window.location; + return loc.pathname.replace(/\/|paste/g, ''); + }, + + getPasteKey: function (url) { + var loc = url ? zerobin.parseUrl(url) : window.location; + return loc.hash.replace('#', '').replace(/(\?|&).*$/, ''); + }, + + /** Return the paste content stripted from any code coloration */ + getPasteContent: function () { + var copy = ''; + document.querySelectorAll("#paste-content li").forEach((node) => { + copy = copy + node.textContent.replace(/[\u00a0]+/g, ' ') + '\n'; + + }) + if (copy === '') { + copy = document.querySelector("#paste-content").textContent; + } + return copy; + }, + + /** Return an approximate estimate of the number of bytes in a text */ + count: function (text, options) { + // Set option defaults + var crlf = /(\r?\n|\r)/g; + var whitespace = /(\r?\n|\r|\s+)/g; + options = options || {}; + options.lineBreaks = options.lineBreaks || 1; + + var length = text.length, + nonAscii = length - text.replace(/[\u0100-\uFFFF]/g, '').length, + lineBreaks = length - text.replace(crlf, '').length; + + return length + nonAscii + Math.max(0, options.lineBreaks * (lineBreaks - 1)); + }, + /** Create a message, style it and insert it in the alert box */ + message: function (type, message, title, flush, callback, action) { + window.scrollTo(0, 0); + if (flush) { + app.messages = app.messages.filter((msg) => { + msg.type !== type + }); + } + app.messages.push({ + title: title, + content: message, + type: type, + action: action, + }); + callback && callback() + }, + + /** Return a progress bar object */ + progressBar: function (selector) { + var container = document.querySelector(selector); + var bar = { + container: container, + elem: container.childNodes[0] + }; + bar.set = function (text, rate) { + bar.elem.innerHTML = text; + bar.elem.style.width = rate; + }; + return bar; + }, + + /** Return an integer ranking the probability this text is any kind of + source code. */ + isCode: function (text) { + + var code_chars = /[A-Z]{3}[A-Z]+|\.[a-z]|[=:<>{}\[\]$_'"&]| {2}|\t/g; + var comments = /(:?\/\*|)|(\/\/|#)(.*?)\n/g; + var formating = /[-*=_+]{4,}/; + + var total = 0; + var size = 0; + var m = text.match(comments); + if (m) { + total += text.match(comments).length; + } + text = text.replace(comments, ''); + text.replace(formating, ''); + text = text.split('\n'); + for (var i = 0; i < text.length; i++) { + var line = text[i]; + size += line.length; + var match = line.replace(formating, '').match(code_chars); + if (match) { + total += match.length; + } + } + + return total * 1000 / size; + }, + + // prevent defaults + ignoreDrag: function (e) { + e.stopPropagation(); + e.preventDefault(); + }, + + // Handle Drop + handleDrop: function (e) { + e.preventDefault(); + zerobin.upload(e.dataTransfer.files); + document.getElementById("content").classList.remove("hover"); + }, + + handleDragOver: function (e) { + zerobin.ignoreDrag(e); + document.getElementById("content").classList.add('hover'); + }, + + handleDragLeave: function (e) { + document.getElementById("content").classList.remove("hover"); + }, + + upload: function (files) { + let content = document.getElementById('content'); + var current_file = files[0]; + var reader = new FileReader(); + if (current_file.type.indexOf('image') == 0) { + reader.onload = function (event) { + var image = new Image(); + image.src = event.target.result; + + image.onload = function () { + var maxWidth = 1024, + maxHeight = 1024, + imageWidth = image.width, + imageHeight = image.height; + + if (imageWidth > imageHeight) { + if (imageWidth > maxWidth) { + imageHeight *= maxWidth / imageWidth; + imageWidth = maxWidth; + } + } else { + if (imageHeight > maxHeight) { + imageWidth *= maxHeight / imageHeight; + imageHeight = maxHeight; + } + } + + var canvas = document.createElement('canvas'); + canvas.width = imageWidth; + canvas.height = imageHeight; + image.width = imageWidth; + image.height = imageHeight; + var ctx = canvas.getContext("2d"); + ctx.drawImage(this, 0, 0, imageWidth, imageHeight); + + var paste = canvas.toDataURL(current_file.type); + + content.value = paste; + content.dispatchEvent(new Event('change')); + + image.style.maxWidth = '742px'; + + content.style.display = "none"; + content.after(image); + + } + } + reader.readAsDataURL(current_file); + } else { + reader.onload = function (event) { + content.value = event.target.result + content.dispatchEvent(new Event('change')); + }; + reader.readAsText(current_file); + } + } +}; + +/** DECRYPTION: On the display paste page, decrypt and decompress the paste content, add syntax coloration then setup the copy to clipboard button. Also calculate and set the paste visual hash. */ - var content = $('#paste-content').text().trim(); - var key = zerobin.getPasteKey(); - var error = false; - if (content && key) { +let pasteContent = document.querySelector('#paste-content'); +let content = ''; - /* Load the lib for visual canvas, create one from the paste id and - insert it */ - $.getScript("/static/js/vizhash.min.js").done(function (script, textStatus) { - if (vizhash.supportCanvas) { - var vhash = vizhash.canvasHash(zerobin.getPasteId(), 24, 24); - $('').click(function (e) { - e.preventDefault(); - if (confirm("This picture is unique to your paste so you can identify" + - " it quickly. \n\n Do you want to know more about this?")) { - window.open("https://github.com/sametmax/VizHash.js", "_blank"); - } - }).prependTo('.lnk-option').append(vhash.canvas); +if (pasteContent) { + content = pasteContent.textContent.trim(); +} + +var key = zerobin.getPasteKey(); +var error = false; + +if (content && key) { + + var form = document.querySelectorAll('input, textarea, select, button'); + form.forEach((node) => node.disabled = true); + + var bar = zerobin.progressBar('.well form .progress'); + app.isLoading = true; + bar.set('Decrypting paste...', '25%'); + + zerobin.decrypt(key, content, + + /* On error*/ + function () { + app.isLoading = false; + zerobin.message('error', 'Could not decrypt data (Wrong key ?)', 'Error'); + }, + + /* Update progress bar */ + () => bar.set('Decompressing...', '45%'), + () => bar.set('Base64 decoding...', '65%'), + () => bar.set('From bits to string...', '85%'), + + /* When done */ + function (content) { + + /* Decrypted content goes back to initial container*/ + document.querySelector('#paste-content').innerHTML = content; + + if (content.indexOf('data:image') == 0) { + // Display Image + + let pasteContent = document.querySelector('#paste-content'); + pasteContent.style.display = "none"; + + var img = document.createElement('img') + img.src = content; + img.style.maxWidth = '742px'; + + pasteContent.after(img); + + // Display Download button + document.querySelectorAll('.btn-clone').forEach((node) => node.style.display = "none") + + app.downloadLink = { + name: '0bin_' + document.location.pathname.split('/').pop(), + url: content } - }); - var $form = $('input, textarea, select, button').prop('disabled', true); - - var bar = zerobin.progressBar('.well form .progress'); - bar.container.show(); - bar.set('Decrypting paste...', '25%'); - - zerobin.decrypt(key, content, - - /* On error*/ - function () { - bar.container.hide(); - zerobin.message('error', 'Could not decrypt data (Wrong key ?)', 'Error'); - }, - - /* Update progress bar */ - mkcb(bar.set, 'Decompressing...', '45%'), - mkcb(bar.set, 'Base64 decoding...', '65%'), - mkcb(bar.set, 'From bits to string...', '85%'), - - /* When done */ - function (content) { - - /* Decrypted content goes back to initial container*/ - $('#paste-content').text(content); - - if (content.indexOf('data:image') == 0) { - // Display Image - $('#paste-content').hide(); - var img = $(''); - $(img).attr('src', content); - $(img).css('max-width', '742px'); - $('#paste-content').after(img); - - // Display Download button - $('.btn-clone').hide(); - - var button = $('').attr('href', content); - $(button).attr('download', '0bin_' + document.location.pathname.split('/').pop()); - $(button).addClass('btn'); - $(button).html(' Download'); - $('.btn-clone').after(button); - - } - bar.set('Code coloration...', '95%'); - - /* Add a continuation to let the UI redraw */ - setTimeout(function () { - - /* Setup flash clipboard button */ - ZeroClipboard.setMoviePath('/static/js/ZeroClipboard.swf'); - - var clip = new ZeroClipboard.Client(); - - // Callback to reposition the clibpboad flash animation overlay - var reposition = function () { - clip.reposition(); - }; - - clip.addEventListener('mouseup', function () { - $('#clip-button').text('Copying paste...'); - clip.setText(zerobin.getPasteContent()); - }); - clip.addEventListener('complete', function () { - $('#clip-button').text('Copy to clipboard'); - zerobin.message('info', 'The paste is now in your clipboard', '', - true, reposition); - }); - clip.glue('clip-button'); - - window.onresize = reposition; - - - /* Setup link to get the paste short url*/ - $('#short-url').click(function (e) { - e.preventDefault(); - $('#short-url').text('Loading short url...'); - zerobin.getTinyURL(window.location.toString(), function (tinyurl) { - clip.setText(tinyurl); - $('#copy-success').hide(); - zerobin.message('success', - '' + tinyurl + '', - 'Short url', true, reposition); - $('#short-url').text('Get short url'); - }); - }); - - /* Remap the message close handler to include the clipboard - flash reposition */ - $(".close").die().live('click', function (e) { - e.preventDefault(); - $(this).parent().fadeOut(reposition); - }); - - /** Syntaxic coloration */ - - if (zerobin.isCode(content) > 100) { - $('#paste-content').addClass('linenums'); - prettyPrint(); - } else { - if (content.indexOf('data:image') != 0) { - zerobin.message('info', - "The paste did not seem to be code, so it " + - "was not colorized. " + - "Force coloration", - '', false, reposition); - } - } - - /* Class to switch to paste content style with coloration done */ - $('#paste-content').addClass('done'); - - /* Display result */ - bar.set('Done', '100%'); - bar.container.hide(); - - $form.prop('disabled', false); - content = ''; - - }, 250); - - }); - - } /* End of "DECRYPTION" */ - - /* Synchronize expiration select boxes value */ - $('.paste-option select').live('change', function () { - $('.paste-option select').val($(this).val()); - }); - - - /* Resize Textarea according to content */ - $('#content').elastic(); - - - /* Display bottom paste option buttons when needed */ - $('#content').live('keyup change', function () { - if ($('#content').height() < 400) { - $('.paste-option.down').remove(); - } else { - - if ($('.paste-option').length === 1) { - $('.paste-option').clone().addClass('down').appendTo('form.well'); - } } + bar.set('Code coloration...', '95%'); - }); + /* Add a continuation to let the UI redraw */ + setTimeout(function () { + /** Syntaxic coloration */ - /* Display previous pastes */ - if (zerobin.support.localStorage) { - - var $container = $('.previous-pastes'), - pastes = zerobin.getPreviousPastes(); - - if (pastes.length) { - - $.getScript("/static/js/vizhash.min.js").done(function (script, textStatus) { - - $container.find('.item').remove(); - $.each(zerobin.getPreviousPastes(), function (i, paste) { - - var $li = $('
  • ').appendTo($container); - var $link = $('').attr('href', paste.link) - .text(paste.prefix + paste.displayDate) - .appendTo($li); - - if (vizhash.supportCanvas) { - var pasteId = zerobin.getPasteId(paste.link); - var vhash = vizhash.canvasHash(pasteId, 24, 24).canvas; - $link.prepend($(vhash).addClass('vhash')); - } - - // hightlite the current link and make sure clicking the link - // does redirect to the page - if (paste.link.replace(/#[^#]+/, '') === window.location.pathname) { - $li.addClass('active'); - $link.click(function () { - window.location = $link.attr('href'); - window.location.reload(); + if (zerobin.isCode(content) > 100) { + document.getElementById('paste-content').classList.add('linenums'); + prettyPrint(); + } else { + if (content.indexOf('data:image') != 0) { + zerobin.message('info', + "The paste did not seem to be code, so it " + + "was not colorized. ", + '', false, undefined, { + message: "Force coloration", + callback: app.handleForceColoration }); - } - - }); - - }); - - } - - } - - - /* Event handler for "clone paste" button */ - $('.btn-clone').click(function (e) { - e.preventDefault(); - $('.submit-form').show(); - $('.paste-form').hide(); - $('#content').val(zerobin.getPasteContent()).trigger('change'); - }); - - $('.clone .btn-danger').click(function (e) { - e.preventDefault(); - $('.submit-form').hide(); - $('.paste-form').show(); - }); - - - - /* Upload file using HTML5 File API */ - if (zerobin.support.fileUpload) { - - var $buttonOverlay = $('#file-upload'); - var $button = $('.btn-upload'); - - try { - $button.val('Uploading...'); - $button.prop('disabled', true); - $buttonOverlay.change(function () { - zerobin.upload(this.files); - }); - } catch (e) { - zerobin.message('error', 'Could no upload the file', 'Error'); - $button.val('Upload File'); - $button.prop('disabled', false); - } - - $button.prop('disabled', false); - $button.val('Upload File'); - $buttonOverlay.mouseover(mkcb($(this).css, 'cursor', 'pointer')); - - // Implements drag & drop upload - $('#content').bind('drop', zerobin.handleDrop); - $('#content').bind('dragover', zerobin.handleDragOver); - $('#content').bind('dragleave', zerobin.handleDragLeave); - - - } - - /* Alerts */ - - $(".close").live('click', function (e) { - e.preventDefault(); - $(this).parent().fadeOut(); - }); - - - /* Parse obfuscaded emails and make them usable */ - $('.email-link').each(function (i, elem) { - var $obfuscatedEmail = $(this); - var address = $obfuscatedEmail.attr('title').replace('__AT__', '@'); - var text = $obfuscatedEmail.text().replace('__AT__', '@'); - var $plainTextEmail = $('' + text + ''); - $obfuscatedEmail.replaceWith($plainTextEmail); - - }); - - /* Show the page using javascript. Non js enabled browser will see an - error message */ - $('#wrap-content').each(function (i, elem) { - $(elem).show(); - }); - - /* Remove expired pasted from history */ - if (zerobin.support.history && zerobin.paste_not_found) { - var paste_id = zerobin.getPasteId(); - var keys = zerobin.getLocalStorageKeys(); - $.each(keys, function (i, key) { - if (localStorage[key].indexOf(paste_id) !== -1) { - localStorage.removeItem(key); - return false; + } } - }); + + /* Class to switch to paste content style with coloration done */ + document.getElementById('paste-content').classList.add('done'); + + /* Display result */ + bar.set('Done', '100%'); + app.isLoading = false; + + form.forEach((node) => node.disabled = false); + content = ''; + + }, 100); + + }); + +} /* End of "DECRYPTION" */ + +/* Display bottom paste option buttons when needed */ + +window.onload = function () { + ["keyup", "change"].forEach((event) => { + let content = document.getElementById("content"); + content.addEventListener(event, () => { + let height = parseFloat(getComputedStyle(content, null).height.replace("px", "")) + app.displayBottomToolBar = height > 400; + }) + }) +} + +/* Display previous pastes */ +if (app.support.localStorage) { + app.previousPastes = zerobin.getPreviousPastes(); +} + +/* Upload file using HTML5 File API */ +if (app.support.fileUpload) { + + // Implements drag & drop upload + let content = document.getElementById('content'); + content.addEventListener('drop', zerobin.handleDrop); + content.addEventListener('dragover', zerobin.handleDragOver); + content.addEventListener('dragleave', zerobin.handleDragLeave); + +} + +/* Remove expired pasted from history */ +if (app.support.history && zerobin.paste_not_found) { + var paste_id = zerobin.getPasteId(); + var keys = zerobin.getLocalStorageKeys(); + keys.forEach((key, i) => { + if (localStorage[key].indexOf(paste_id) !== -1) { + localStorage.removeItem(key); + return false; } - - - /* Force text coloration when clickin on link */ - $("#force-coloration").live("click", function (e) { - e.preventDefault(); - $('#paste-content').addClass('linenums'); - $(this).die(e).text('Applying coloration'); - prettyPrint(); - $(this).remove(); - }); - - /* Send the paste by email */ - $('#email-link').click(function(e) { - e.target.href = 'mailto:friend@example.com?body=' + window.location.toString(); - }); - - - }); /* End of "document ready" jquery callback */ - -})(); /* End of self executing function */ + }) +} diff --git a/zerobin/static/js/jquery-1.7.2.min.js b/zerobin/static/js/jquery-1.7.2.min.js deleted file mode 100644 index 16ad06c..0000000 --- a/zerobin/static/js/jquery-1.7.2.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! jQuery v1.7.2 jquery.com | jquery.org/license */ -(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cu(a){if(!cj[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ck||(ck=c.createElement("iframe"),ck.frameBorder=ck.width=ck.height=0),b.appendChild(ck);if(!cl||!ck.createElement)cl=(ck.contentWindow||ck.contentDocument).document,cl.write((f.support.boxModel?"":"")+""),cl.close();d=cl.createElement(a),cl.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ck)}cj[a]=e}return cj[a]}function ct(a,b){var c={};f.each(cp.concat.apply([],cp.slice(0,b)),function(){c[this]=a});return c}function cs(){cq=b}function cr(){setTimeout(cs,0);return cq=f.now()}function ci(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ch(){try{return new a.XMLHttpRequest}catch(b){}}function cb(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g0){if(c!=="border")for(;e=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?+d:j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.2",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){if(typeof c!="string"||!c)return null;var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c
    a",d=p.getElementsByTagName("*"),e=p.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=p.getElementsByTagName("input")[0],b={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:p.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,pixelMargin:!0},f.boxModel=b.boxModel=c.compatMode==="CSS1Compat",i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete p.test}catch(r){b.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent("onclick",function(){b.noCloneEvent=!1}),p.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),i.setAttribute("name","t"),p.appendChild(i),j=c.createDocumentFragment(),j.appendChild(p.lastChild),b.checkClone=j.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,j.removeChild(i),j.appendChild(p);if(p.attachEvent)for(n in{submit:1,change:1,focusin:1})m="on"+n,o=m in p,o||(p.setAttribute(m,"return;"),o=typeof p[m]=="function"),b[n+"Bubbles"]=o;j.removeChild(p),j=g=h=p=i=null,f(function(){var d,e,g,h,i,j,l,m,n,q,r,s,t,u=c.getElementsByTagName("body")[0];!u||(m=1,t="padding:0;margin:0;border:",r="position:absolute;top:0;left:0;width:1px;height:1px;",s=t+"0;visibility:hidden;",n="style='"+r+t+"5px solid #000;",q="
    "+""+"
    ",d=c.createElement("div"),d.style.cssText=s+"width:0;height:0;position:static;top:0;margin-top:"+m+"px",u.insertBefore(d,u.firstChild),p=c.createElement("div"),d.appendChild(p),p.innerHTML="
    t
    ",k=p.getElementsByTagName("td"),o=k[0].offsetHeight===0,k[0].style.display="",k[1].style.display="none",b.reliableHiddenOffsets=o&&k[0].offsetHeight===0,a.getComputedStyle&&(p.innerHTML="",l=c.createElement("div"),l.style.width="0",l.style.marginRight="0",p.style.width="2px",p.appendChild(l),b.reliableMarginRight=(parseInt((a.getComputedStyle(l,null)||{marginRight:0}).marginRight,10)||0)===0),typeof p.style.zoom!="undefined"&&(p.innerHTML="",p.style.width=p.style.padding="1px",p.style.border=0,p.style.overflow="hidden",p.style.display="inline",p.style.zoom=1,b.inlineBlockNeedsLayout=p.offsetWidth===3,p.style.display="block",p.style.overflow="visible",p.innerHTML="
    ",b.shrinkWrapBlocks=p.offsetWidth!==3),p.style.cssText=r+s,p.innerHTML=q,e=p.firstChild,g=e.firstChild,i=e.nextSibling.firstChild.firstChild,j={doesNotAddBorder:g.offsetTop!==5,doesAddBorderForTableAndCells:i.offsetTop===5},g.style.position="fixed",g.style.top="20px",j.fixedPosition=g.offsetTop===20||g.offsetTop===15,g.style.position=g.style.top="",e.style.overflow="hidden",e.style.position="relative",j.subtractsBorderForOverflowNotVisible=g.offsetTop===-5,j.doesNotIncludeMarginInBodyOffset=u.offsetTop!==m,a.getComputedStyle&&(p.style.marginTop="1%",b.pixelMargin=(a.getComputedStyle(p,null)||{marginTop:0}).marginTop!=="1%"),typeof d.style.zoom!="undefined"&&(d.style.zoom=1),u.removeChild(d),l=p=d=null,f.extend(b,j))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e1,null,!1)},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){var d=2;typeof a!="string"&&(c=a,a="fx",d--);if(arguments.length1)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,f.prop,a,b,arguments.length>1)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.type]||f.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.type]||f.valHooks[g.nodeName.toLowerCase()];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h,i=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;i=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/(?:^|\s)hover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function( -a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler,g=p.selector),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;le&&j.push({elem:this,matches:d.slice(e)});for(k=0;k0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));o.match.globalPOS=p;var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

    ";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="
    ";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h0)for(h=g;h=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/]","i"),bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*",""],legend:[1,"
    ","
    "],thead:[1,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],col:[2,"","
    "],area:[1,"",""],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div
    ","
    "]),f.fn.extend({text:function(a){return f.access(this,function(a){return a===b?f.text(this):this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f -.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){return f.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1>");try{for(;d1&&l0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||f.isXMLDoc(a)||!bc.test("<"+a.nodeName+">")?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g,h,i,j=[];b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);for(var k=0,l;(l=a[k])!=null;k++){typeof l=="number"&&(l+="");if(!l)continue;if(typeof l=="string")if(!_.test(l))l=b.createTextNode(l);else{l=l.replace(Y,"<$1>");var m=(Z.exec(l)||["",""])[1].toLowerCase(),n=bg[m]||bg._default,o=n[0],p=b.createElement("div"),q=bh.childNodes,r;b===c?bh.appendChild(p):U(b).appendChild(p),p.innerHTML=n[1]+l+n[2];while(o--)p=p.lastChild;if(!f.support.tbody){var s=$.test(l),t=m==="table"&&!s?p.firstChild&&p.firstChild.childNodes:n[1]===""&&!s?p.childNodes:[];for(i=t.length-1;i>=0;--i)f.nodeName(t[i],"tbody")&&!t[i].childNodes.length&&t[i].parentNode.removeChild(t[i])}!f.support.leadingWhitespace&&X.test(l)&&p.insertBefore(b.createTextNode(X.exec(l)[0]),p.firstChild),l=p.childNodes,p&&(p.parentNode.removeChild(p),q.length>0&&(r=q[q.length-1],r&&r.parentNode&&r.parentNode.removeChild(r)))}var u;if(!f.support.appendChecked)if(l[0]&&typeof (u=l.length)=="number")for(i=0;i1)},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=by(a,"opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bu.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(by)return by(a,c)},swap:function(a,b,c){var d={},e,f;for(f in b)d[f]=a.style[f],a.style[f]=b[f];e=c.call(a);for(f in b)a.style[f]=d[f];return e}}),f.curCSS=f.css,c.defaultView&&c.defaultView.getComputedStyle&&(bz=function(a,b){var c,d,e,g,h=a.style;b=b.replace(br,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b))),!f.support.pixelMargin&&e&&bv.test(b)&&bt.test(c)&&(g=h.width,h.width=c,c=e.width,h.width=g);return c}),c.documentElement.currentStyle&&(bA=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f==null&&g&&(e=g[b])&&(f=e),bt.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),by=bz||bA,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth!==0?bB(a,b,d):f.swap(a,bw,function(){return bB(a,b,d)})},set:function(a,b){return bs.test(b)?b+"px":b}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bq.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bp,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bp.test(g)?g.replace(bp,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){return f.swap(a,{display:"inline-block"},function(){return b?by(a,"margin-right"):a.style.marginRight})}})}),f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)}),f.each({margin:"",padding:"",border:"Width"},function(a,b){f.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bx[d]+b]=e[d]||e[d-2]||e[0];return f}}});var bC=/%20/g,bD=/\[\]$/,bE=/\r?\n/g,bF=/#.*$/,bG=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bH=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bI=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bJ=/^(?:GET|HEAD)$/,bK=/^\/\//,bL=/\?/,bM=/)<[^<]*)*<\/script>/gi,bN=/^(?:select|textarea)/i,bO=/\s+/,bP=/([?&])_=[^&]*/,bQ=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bR=f.fn.load,bS={},bT={},bU,bV,bW=["*/"]+["*"];try{bU=e.href}catch(bX){bU=c.createElement("a"),bU.href="",bU=bU.href}bV=bQ.exec(bU.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bR)return bR.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("
    ").append(c.replace(bM,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bN.test(this.nodeName)||bH.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bE,"\r\n")}}):{name:b.name,value:c.replace(bE,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b$(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b$(a,b);return a},ajaxSettings:{url:bU,isLocal:bI.test(bV[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bW},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bY(bS),ajaxTransport:bY(bT),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?ca(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cb(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bG.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bF,"").replace(bK,bV[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bO),d.crossDomain==null&&(r=bQ.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bV[1]&&r[2]==bV[2]&&(r[3]||(r[1]==="http:"?80:443))==(bV[3]||(bV[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bZ(bS,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bJ.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bL.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bP,"$1_="+x);d.url=y+(y===d.url?(bL.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bW+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bZ(bT,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)b_(g,a[g],c,e);return d.join("&").replace(bC,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cc=f.now(),cd=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cc++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=typeof b.data=="string"&&/^application\/x\-www\-form\-urlencoded/.test(b.contentType);if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(cd.test(b.url)||e&&cd.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(cd,l),b.url===j&&(e&&(k=k.replace(cd,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var ce=a.ActiveXObject?function(){for(var a in cg)cg[a](0,1)}:!1,cf=0,cg;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ch()||ci()}:ch,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,ce&&delete cg[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n);try{m.text=h.responseText}catch(a){}try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cf,ce&&(cg||(cg={},f(a).unload(ce)),cg[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cj={},ck,cl,cm=/^(?:toggle|show|hide)$/,cn=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,co,cp=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cq;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(ct("show",3),a,b,c);for(var g=0,h=this.length;g=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);f.fn[a]=function(e){return f.access(this,function(a,e,g){var h=cy(a);if(g===b)return h?c in h?h[c]:f.support.boxModel&&h.document.documentElement[e]||h.document.body[e]:a[e];h?h.scrollTo(d?f(h).scrollLeft():g,d?g:f(h).scrollTop()):a[e]=g},a,e,arguments.length,null)}}),f.each({Height:"height",Width:"width"},function(a,c){var d="client"+a,e="scroll"+a,g="offset"+a;f.fn["inner"+a]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,c,"padding")):this[c]():null},f.fn["outer"+a]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,c,a?"margin":"border")):this[c]():null},f.fn[c]=function(a){return f.access(this,function(a,c,h){var i,j,k,l;if(f.isWindow(a)){i=a.document,j=i.documentElement[d];return f.support.boxModel&&j||i.body&&i.body[d]||j}if(a.nodeType===9){i=a.documentElement;if(i[d]>=i[e])return i[d];return Math.max(a.body[e],i[e],a.body[g],i[g])}if(h===b){k=f.css(a,c),l=parseFloat(k);return f.isNumeric(l)?l:k}f(a).css(c,h)},c,a,arguments.length,null)}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window); \ No newline at end of file diff --git a/zerobin/static/js/jquery.elastic.source.js b/zerobin/static/js/jquery.elastic.source.js deleted file mode 100644 index 9b1ed2b..0000000 --- a/zerobin/static/js/jquery.elastic.source.js +++ /dev/null @@ -1,162 +0,0 @@ -/** -* @name Elastic -* @descripton Elastic is jQuery plugin that grow and shrink your textareas automatically -* @version 1.6.11 -* @requires jQuery 1.2.6+ -* -* @author Jan Jarfalk -* @author-email jan.jarfalk@unwrongest.com -* @author-website http://www.unwrongest.com -* -* @licence MIT License - http://www.opensource.org/licenses/mit-license.php -*/ - -(function($){ - jQuery.fn.extend({ - elastic: function() { - - // We will create a div clone of the textarea - // by copying these attributes from the textarea to the div. - var mimics = [ - 'paddingTop', - 'paddingRight', - 'paddingBottom', - 'paddingLeft', - 'fontSize', - 'lineHeight', - 'fontFamily', - 'width', - 'fontWeight', - 'border-top-width', - 'border-right-width', - 'border-bottom-width', - 'border-left-width', - 'borderTopStyle', - 'borderTopColor', - 'borderRightStyle', - 'borderRightColor', - 'borderBottomStyle', - 'borderBottomColor', - 'borderLeftStyle', - 'borderLeftColor' - ]; - - return this.each( function() { - - // Elastic only works on textareas - if ( this.type !== 'textarea' ) { - return false; - } - - var $textarea = jQuery(this), - $twin = jQuery('
    ').css({ - 'position' : 'absolute', - 'display' : 'none', - 'word-wrap' : 'break-word', - 'white-space' :'pre-wrap' - }), - lineHeight = parseInt($textarea.css('line-height'),10) || parseInt($textarea.css('font-size'),'10'), - minheight = parseInt($textarea.css('height'),10) || lineHeight*3, - maxheight = parseInt($textarea.css('max-height'),10) || Number.MAX_VALUE, - goalheight = 0; - - // Opera returns max-height of -1 if not set - if (maxheight < 0) { maxheight = Number.MAX_VALUE; } - - // Append the twin to the DOM - // We are going to meassure the height of this, not the textarea. - $twin.appendTo($textarea.parent()); - - // Copy the essential styles (mimics) from the textarea to the twin - var i = mimics.length; - while(i--){ - $twin.css(mimics[i].toString(),$textarea.css(mimics[i].toString())); - } - - // Updates the width of the twin. (solution for textareas with widths in percent) - function setTwinWidth(){ - var curatedWidth = Math.floor(parseInt($textarea.width(),10)); - if($twin.width() !== curatedWidth){ - $twin.css({'width': curatedWidth + 'px'}); - - // Update height of textarea - update(true); - } - } - - // Sets a given height and overflow state on the textarea - function setHeightAndOverflow(height, overflow){ - - var curratedHeight = Math.floor(parseInt(height,10)); - if($textarea.height() !== curratedHeight){ - $textarea.css({'height': curratedHeight + 'px','overflow':overflow}); - } - } - - // This function will update the height of the textarea if necessary - function update(forced) { - - // Get curated content from the textarea. - var textareaContent = $textarea.val().replace(/&/g,'&').replace(/ {2}/g, ' ').replace(/<|>/g, '>').replace(/\n/g, '
    '); - - // Compare curated content with curated twin. - var twinContent = $twin.html().replace(/
    /ig,'
    '); - - if(forced || textareaContent+' ' !== twinContent){ - - // Add an extra white space so new rows are added when you are at the end of a row. - $twin.html(textareaContent+' '); - - // Change textarea height if twin plus the height of one line differs more than 3 pixel from textarea height - if(Math.abs($twin.height() + lineHeight - $textarea.height()) > 3){ - - var goalheight = $twin.height()+lineHeight; - if(goalheight >= maxheight) { - setHeightAndOverflow(maxheight,'auto'); - } else if(goalheight <= minheight) { - setHeightAndOverflow(minheight,'hidden'); - } else { - setHeightAndOverflow(goalheight,'hidden'); - } - - } - - } - - } - - // Hide scrollbars - $textarea.css({'overflow':'hidden'}); - - // Update textarea size on keyup, change, cut and paste - $textarea.bind('keyup change cut paste', function(){ - update(); - }); - - // Update width of twin if browser or textarea is resized (solution for textareas with widths in percent) - $(window).bind('resize', setTwinWidth); - $textarea.bind('resize', setTwinWidth); - $textarea.bind('update', update); - - // Compact textarea on blur - $textarea.bind('blur',function(){ - if($twin.height() < maxheight){ - if($twin.height() > minheight) { - $textarea.height($twin.height()); - } else { - $textarea.height(minheight); - } - } - }); - - // And this line is to catch the browser paste event - $textarea.bind('input paste',function(e){ setTimeout( update, 250); }); - - // Run update once when elastic is initialized - update(); - - }); - - } - }); -})(jQuery); \ No newline at end of file diff --git a/zerobin/static/js/vizhash.min.js b/zerobin/static/js/vizhash.min.js deleted file mode 100644 index 1c4c076..0000000 --- a/zerobin/static/js/vizhash.min.js +++ /dev/null @@ -1,2 +0,0 @@ -var hexcase=0;var b64pad="";function hex_md5(a){return rstr2hex(rstr_md5(str2rstr_utf8(a)))}function rstr_md5(a){return binl2rstr(binl_md5(rstr2binl(a),a.length*8))}function rstr2hex(c){try{hexcase}catch(g){hexcase=0}var f=hexcase?"0123456789ABCDEF":"0123456789abcdef";var b="";var a;for(var d=0;d>>4)&15)+f.charAt(a&15)}return b}function str2rstr_utf8(c){var b="";var d=-1;var a,e;while(++d>>6)&31),128|(a&63))}else{if(a<=65535){b+=String.fromCharCode(224|((a>>>12)&15),128|((a>>>6)&63),128|(a&63))}else{if(a<=2097151){b+=String.fromCharCode(240|((a>>>18)&7),128|((a>>>12)&63),128|((a>>>6)&63),128|(a&63))}}}}}return b}function rstr2binl(b){var a=Array(b.length>>2);for(var c=0;c>5]|=(b.charCodeAt(c/8)&255)<<(c%32)}return a}function binl2rstr(b){var a="";for(var c=0;c>5]>>>(c%32))&255)}return a}function binl_md5(p,k){p[k>>5]|=128<<((k)%32);p[(((k+64)>>>9)<<4)+14]=k;var o=1732584193;var n=-271733879;var m=-1732584194;var l=271733878;for(var g=0;g>16)+(d>>16)+(c>>16);return(b<<16)|(c&65535)}function bit_rol(a,b){return(a<>>(32-b))}function hex_sha1(a){return rstr2hex(rstr_sha1(str2rstr_utf8(a)))}function rstr_sha1(a){return binb2rstr(binb_sha1(rstr2binb(a),a.length*8))}function rstr2binb(b){var a=Array(b.length>>2);for(var c=0;c>5]|=(b.charCodeAt(c/8)&255)<<(24-c%32)}return a}function binb2rstr(b){var a="";for(var c=0;c>5]>>>(24-c%32))&255)}return a}function binb_sha1(v,o){v[o>>5]|=128<<(24-o%32);v[((o+64>>9)<<4)+15]=o;var y=Array(80);var u=1732584193;var s=-271733879;var r=-1732584194;var q=271733878;var p=-1009589776;for(var l=0;l256||p>256){throw"Max image size is 256 x 256"}var g={hash:vizhash.textHash(o)},k=g.hash.intArray,f=vizhash.color(k.next(),k.next(),k.next());a=g.width=a||80;p=g.height=p||80;var c=g.canvas=vizhash.createCanvas(a,p);var b=g.context=c.getContext("2d");function n(){var r=k.next();return a*r/256}function j(){var r=k.next();return p*r/256}function m(t,A,w,s,H,z){var F=A-s/2,E=w-H/2,D=0.5522848;var v=(s/2)*D,r=(H/2)*D,G=F+s,C=E+H,B=F+s/2,u=E+H/2;t.beginPath();t.moveTo(F,u);t.bezierCurveTo(F,u-r,B-v,E,B,E);t.bezierCurveTo(B+v,E,G,u-r,G,u);t.bezierCurveTo(G,u+r,B+v,C,B,C);t.bezierCurveTo(B-v,C,F,u+r,F,u);t.fillStyle=z.toString();t.fill();t.closePath()}function q(t,u,r){t.beginPath();for(var s=0;s= 0 && Math.floor(n) === n && isFinite(val) + } + + function isPromise (val) { + return ( + isDef(val) && + typeof val.then === 'function' && + typeof val.catch === 'function' + ) + } + + /** + * Convert a value to a string that is actually rendered. + */ + function toString (val) { + return val == null + ? '' + : Array.isArray(val) || (isPlainObject(val) && val.toString === _toString) + ? JSON.stringify(val, null, 2) + : String(val) + } + + /** + * Convert an input value to a number for persistence. + * If the conversion fails, return original string. + */ + function toNumber (val) { + var n = parseFloat(val); + return isNaN(n) ? val : n + } + + /** + * Make a map and return a function for checking if a key + * is in that map. + */ + function makeMap ( + str, + expectsLowerCase + ) { + var map = Object.create(null); + var list = str.split(','); + for (var i = 0; i < list.length; i++) { + map[list[i]] = true; + } + return expectsLowerCase + ? function (val) { return map[val.toLowerCase()]; } + : function (val) { return map[val]; } + } + + /** + * Check if a tag is a built-in tag. + */ + var isBuiltInTag = makeMap('slot,component', true); + + /** + * Check if an attribute is a reserved attribute. + */ + var isReservedAttribute = makeMap('key,ref,slot,slot-scope,is'); + + /** + * Remove an item from an array. + */ + function remove (arr, item) { + if (arr.length) { + var index = arr.indexOf(item); + if (index > -1) { + return arr.splice(index, 1) + } + } + } + + /** + * Check whether an object has the property. + */ + var hasOwnProperty = Object.prototype.hasOwnProperty; + function hasOwn (obj, key) { + return hasOwnProperty.call(obj, key) + } + + /** + * Create a cached version of a pure function. + */ + function cached (fn) { + var cache = Object.create(null); + return (function cachedFn (str) { + var hit = cache[str]; + return hit || (cache[str] = fn(str)) + }) + } + + /** + * Camelize a hyphen-delimited string. + */ + var camelizeRE = /-(\w)/g; + var camelize = cached(function (str) { + return str.replace(camelizeRE, function (_, c) { return c ? c.toUpperCase() : ''; }) + }); + + /** + * Capitalize a string. + */ + var capitalize = cached(function (str) { + return str.charAt(0).toUpperCase() + str.slice(1) + }); + + /** + * Hyphenate a camelCase string. + */ + var hyphenateRE = /\B([A-Z])/g; + var hyphenate = cached(function (str) { + return str.replace(hyphenateRE, '-$1').toLowerCase() + }); + + /** + * Simple bind polyfill for environments that do not support it, + * e.g., PhantomJS 1.x. Technically, we don't need this anymore + * since native bind is now performant enough in most browsers. + * But removing it would mean breaking code that was able to run in + * PhantomJS 1.x, so this must be kept for backward compatibility. + */ + + /* istanbul ignore next */ + function polyfillBind (fn, ctx) { + function boundFn (a) { + var l = arguments.length; + return l + ? l > 1 + ? fn.apply(ctx, arguments) + : fn.call(ctx, a) + : fn.call(ctx) + } + + boundFn._length = fn.length; + return boundFn + } + + function nativeBind (fn, ctx) { + return fn.bind(ctx) + } + + var bind = Function.prototype.bind + ? nativeBind + : polyfillBind; + + /** + * Convert an Array-like object to a real Array. + */ + function toArray (list, start) { + start = start || 0; + var i = list.length - start; + var ret = new Array(i); + while (i--) { + ret[i] = list[i + start]; + } + return ret + } + + /** + * Mix properties into target object. + */ + function extend (to, _from) { + for (var key in _from) { + to[key] = _from[key]; + } + return to + } + + /** + * Merge an Array of Objects into a single Object. + */ + function toObject (arr) { + var res = {}; + for (var i = 0; i < arr.length; i++) { + if (arr[i]) { + extend(res, arr[i]); + } + } + return res + } + + /* eslint-disable no-unused-vars */ + + /** + * Perform no operation. + * Stubbing args to make Flow happy without leaving useless transpiled code + * with ...rest (https://flow.org/blog/2017/05/07/Strict-Function-Call-Arity/). + */ + function noop (a, b, c) {} + + /** + * Always return false. + */ + var no = function (a, b, c) { return false; }; + + /* eslint-enable no-unused-vars */ + + /** + * Return the same value. + */ + var identity = function (_) { return _; }; + + /** + * Generate a string containing static keys from compiler modules. + */ + function genStaticKeys (modules) { + return modules.reduce(function (keys, m) { + return keys.concat(m.staticKeys || []) + }, []).join(',') + } + + /** + * Check if two values are loosely equal - that is, + * if they are plain objects, do they have the same shape? + */ + function looseEqual (a, b) { + if (a === b) { return true } + var isObjectA = isObject(a); + var isObjectB = isObject(b); + if (isObjectA && isObjectB) { + try { + var isArrayA = Array.isArray(a); + var isArrayB = Array.isArray(b); + if (isArrayA && isArrayB) { + return a.length === b.length && a.every(function (e, i) { + return looseEqual(e, b[i]) + }) + } else if (a instanceof Date && b instanceof Date) { + return a.getTime() === b.getTime() + } else if (!isArrayA && !isArrayB) { + var keysA = Object.keys(a); + var keysB = Object.keys(b); + return keysA.length === keysB.length && keysA.every(function (key) { + return looseEqual(a[key], b[key]) + }) + } else { + /* istanbul ignore next */ + return false + } + } catch (e) { + /* istanbul ignore next */ + return false + } + } else if (!isObjectA && !isObjectB) { + return String(a) === String(b) + } else { + return false + } + } + + /** + * Return the first index at which a loosely equal value can be + * found in the array (if value is a plain object, the array must + * contain an object of the same shape), or -1 if it is not present. + */ + function looseIndexOf (arr, val) { + for (var i = 0; i < arr.length; i++) { + if (looseEqual(arr[i], val)) { return i } + } + return -1 + } + + /** + * Ensure a function is called only once. + */ + function once (fn) { + var called = false; + return function () { + if (!called) { + called = true; + fn.apply(this, arguments); + } + } + } + + var SSR_ATTR = 'data-server-rendered'; + + var ASSET_TYPES = [ + 'component', + 'directive', + 'filter' + ]; + + var LIFECYCLE_HOOKS = [ + 'beforeCreate', + 'created', + 'beforeMount', + 'mounted', + 'beforeUpdate', + 'updated', + 'beforeDestroy', + 'destroyed', + 'activated', + 'deactivated', + 'errorCaptured', + 'serverPrefetch' + ]; + + /* */ + + + + var config = ({ + /** + * Option merge strategies (used in core/util/options) + */ + // $flow-disable-line + optionMergeStrategies: Object.create(null), + + /** + * Whether to suppress warnings. + */ + silent: false, + + /** + * Show production mode tip message on boot? + */ + productionTip: "development" !== 'production', + + /** + * Whether to enable devtools + */ + devtools: "development" !== 'production', + + /** + * Whether to record perf + */ + performance: false, + + /** + * Error handler for watcher errors + */ + errorHandler: null, + + /** + * Warn handler for watcher warns + */ + warnHandler: null, + + /** + * Ignore certain custom elements + */ + ignoredElements: [], + + /** + * Custom user key aliases for v-on + */ + // $flow-disable-line + keyCodes: Object.create(null), + + /** + * Check if a tag is reserved so that it cannot be registered as a + * component. This is platform-dependent and may be overwritten. + */ + isReservedTag: no, + + /** + * Check if an attribute is reserved so that it cannot be used as a component + * prop. This is platform-dependent and may be overwritten. + */ + isReservedAttr: no, + + /** + * Check if a tag is an unknown element. + * Platform-dependent. + */ + isUnknownElement: no, + + /** + * Get the namespace of an element + */ + getTagNamespace: noop, + + /** + * Parse the real tag name for the specific platform. + */ + parsePlatformTagName: identity, + + /** + * Check if an attribute must be bound using property, e.g. value + * Platform-dependent. + */ + mustUseProp: no, + + /** + * Perform updates asynchronously. Intended to be used by Vue Test Utils + * This will significantly reduce performance if set to false. + */ + async: true, + + /** + * Exposed for legacy reasons + */ + _lifecycleHooks: LIFECYCLE_HOOKS + }); + + /* */ + + /** + * unicode letters used for parsing html tags, component names and property paths. + * using https://www.w3.org/TR/html53/semantics-scripting.html#potentialcustomelementname + * skipping \u10000-\uEFFFF due to it freezing up PhantomJS + */ + var unicodeRegExp = /a-zA-Z\u00B7\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u037D\u037F-\u1FFF\u200C-\u200D\u203F-\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD/; + + /** + * Check if a string starts with $ or _ + */ + function isReserved (str) { + var c = (str + '').charCodeAt(0); + return c === 0x24 || c === 0x5F + } + + /** + * Define a property. + */ + function def (obj, key, val, enumerable) { + Object.defineProperty(obj, key, { + value: val, + enumerable: !!enumerable, + writable: true, + configurable: true + }); + } + + /** + * Parse simple path. + */ + var bailRE = new RegExp(("[^" + (unicodeRegExp.source) + ".$_\\d]")); + function parsePath (path) { + if (bailRE.test(path)) { + return + } + var segments = path.split('.'); + return function (obj) { + for (var i = 0; i < segments.length; i++) { + if (!obj) { return } + obj = obj[segments[i]]; + } + return obj + } + } + + /* */ + + // can we use __proto__? + var hasProto = '__proto__' in {}; + + // Browser environment sniffing + var inBrowser = typeof window !== 'undefined'; + var inWeex = typeof WXEnvironment !== 'undefined' && !!WXEnvironment.platform; + var weexPlatform = inWeex && WXEnvironment.platform.toLowerCase(); + var UA = inBrowser && window.navigator.userAgent.toLowerCase(); + var isIE = UA && /msie|trident/.test(UA); + var isIE9 = UA && UA.indexOf('msie 9.0') > 0; + var isEdge = UA && UA.indexOf('edge/') > 0; + var isAndroid = (UA && UA.indexOf('android') > 0) || (weexPlatform === 'android'); + var isIOS = (UA && /iphone|ipad|ipod|ios/.test(UA)) || (weexPlatform === 'ios'); + var isChrome = UA && /chrome\/\d+/.test(UA) && !isEdge; + var isPhantomJS = UA && /phantomjs/.test(UA); + var isFF = UA && UA.match(/firefox\/(\d+)/); + + // Firefox has a "watch" function on Object.prototype... + var nativeWatch = ({}).watch; + + var supportsPassive = false; + if (inBrowser) { + try { + var opts = {}; + Object.defineProperty(opts, 'passive', ({ + get: function get () { + /* istanbul ignore next */ + supportsPassive = true; + } + })); // https://github.com/facebook/flow/issues/285 + window.addEventListener('test-passive', null, opts); + } catch (e) {} + } + + // this needs to be lazy-evaled because vue may be required before + // vue-server-renderer can set VUE_ENV + var _isServer; + var isServerRendering = function () { + if (_isServer === undefined) { + /* istanbul ignore if */ + if (!inBrowser && !inWeex && typeof global !== 'undefined') { + // detect presence of vue-server-renderer and avoid + // Webpack shimming the process + _isServer = global['process'] && global['process'].env.VUE_ENV === 'server'; + } else { + _isServer = false; + } + } + return _isServer + }; + + // detect devtools + var devtools = inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__; + + /* istanbul ignore next */ + function isNative (Ctor) { + return typeof Ctor === 'function' && /native code/.test(Ctor.toString()) + } + + var hasSymbol = + typeof Symbol !== 'undefined' && isNative(Symbol) && + typeof Reflect !== 'undefined' && isNative(Reflect.ownKeys); + + var _Set; + /* istanbul ignore if */ // $flow-disable-line + if (typeof Set !== 'undefined' && isNative(Set)) { + // use native Set when available. + _Set = Set; + } else { + // a non-standard Set polyfill that only works with primitive keys. + _Set = /*@__PURE__*/(function () { + function Set () { + this.set = Object.create(null); + } + Set.prototype.has = function has (key) { + return this.set[key] === true + }; + Set.prototype.add = function add (key) { + this.set[key] = true; + }; + Set.prototype.clear = function clear () { + this.set = Object.create(null); + }; + + return Set; + }()); + } + + /* */ + + var warn = noop; + var tip = noop; + var generateComponentTrace = (noop); // work around flow check + var formatComponentName = (noop); + + { + var hasConsole = typeof console !== 'undefined'; + var classifyRE = /(?:^|[-_])(\w)/g; + var classify = function (str) { return str + .replace(classifyRE, function (c) { return c.toUpperCase(); }) + .replace(/[-_]/g, ''); }; + + warn = function (msg, vm) { + var trace = vm ? generateComponentTrace(vm) : ''; + + if (config.warnHandler) { + config.warnHandler.call(null, msg, vm, trace); + } else if (hasConsole && (!config.silent)) { + console.error(("[Vue warn]: " + msg + trace)); + } + }; + + tip = function (msg, vm) { + if (hasConsole && (!config.silent)) { + console.warn("[Vue tip]: " + msg + ( + vm ? generateComponentTrace(vm) : '' + )); + } + }; + + formatComponentName = function (vm, includeFile) { + if (vm.$root === vm) { + return '' + } + var options = typeof vm === 'function' && vm.cid != null + ? vm.options + : vm._isVue + ? vm.$options || vm.constructor.options + : vm; + var name = options.name || options._componentTag; + var file = options.__file; + if (!name && file) { + var match = file.match(/([^/\\]+)\.vue$/); + name = match && match[1]; + } + + return ( + (name ? ("<" + (classify(name)) + ">") : "") + + (file && includeFile !== false ? (" at " + file) : '') + ) + }; + + var repeat = function (str, n) { + var res = ''; + while (n) { + if (n % 2 === 1) { res += str; } + if (n > 1) { str += str; } + n >>= 1; + } + return res + }; + + generateComponentTrace = function (vm) { + if (vm._isVue && vm.$parent) { + var tree = []; + var currentRecursiveSequence = 0; + while (vm) { + if (tree.length > 0) { + var last = tree[tree.length - 1]; + if (last.constructor === vm.constructor) { + currentRecursiveSequence++; + vm = vm.$parent; + continue + } else if (currentRecursiveSequence > 0) { + tree[tree.length - 1] = [last, currentRecursiveSequence]; + currentRecursiveSequence = 0; + } + } + tree.push(vm); + vm = vm.$parent; + } + return '\n\nfound in\n\n' + tree + .map(function (vm, i) { return ("" + (i === 0 ? '---> ' : repeat(' ', 5 + i * 2)) + (Array.isArray(vm) + ? ((formatComponentName(vm[0])) + "... (" + (vm[1]) + " recursive calls)") + : formatComponentName(vm))); }) + .join('\n') + } else { + return ("\n\n(found in " + (formatComponentName(vm)) + ")") + } + }; + } + + /* */ + + var uid = 0; + + /** + * A dep is an observable that can have multiple + * directives subscribing to it. + */ + var Dep = function Dep () { + this.id = uid++; + this.subs = []; + }; + + Dep.prototype.addSub = function addSub (sub) { + this.subs.push(sub); + }; + + Dep.prototype.removeSub = function removeSub (sub) { + remove(this.subs, sub); + }; + + Dep.prototype.depend = function depend () { + if (Dep.target) { + Dep.target.addDep(this); + } + }; + + Dep.prototype.notify = function notify () { + // stabilize the subscriber list first + var subs = this.subs.slice(); + if (!config.async) { + // subs aren't sorted in scheduler if not running async + // we need to sort them now to make sure they fire in correct + // order + subs.sort(function (a, b) { return a.id - b.id; }); + } + for (var i = 0, l = subs.length; i < l; i++) { + subs[i].update(); + } + }; + + // The current target watcher being evaluated. + // This is globally unique because only one watcher + // can be evaluated at a time. + Dep.target = null; + var targetStack = []; + + function pushTarget (target) { + targetStack.push(target); + Dep.target = target; + } + + function popTarget () { + targetStack.pop(); + Dep.target = targetStack[targetStack.length - 1]; + } + + /* */ + + var VNode = function VNode ( + tag, + data, + children, + text, + elm, + context, + componentOptions, + asyncFactory + ) { + this.tag = tag; + this.data = data; + this.children = children; + this.text = text; + this.elm = elm; + this.ns = undefined; + this.context = context; + this.fnContext = undefined; + this.fnOptions = undefined; + this.fnScopeId = undefined; + this.key = data && data.key; + this.componentOptions = componentOptions; + this.componentInstance = undefined; + this.parent = undefined; + this.raw = false; + this.isStatic = false; + this.isRootInsert = true; + this.isComment = false; + this.isCloned = false; + this.isOnce = false; + this.asyncFactory = asyncFactory; + this.asyncMeta = undefined; + this.isAsyncPlaceholder = false; + }; + + var prototypeAccessors = { child: { configurable: true } }; + + // DEPRECATED: alias for componentInstance for backwards compat. + /* istanbul ignore next */ + prototypeAccessors.child.get = function () { + return this.componentInstance + }; + + Object.defineProperties( VNode.prototype, prototypeAccessors ); + + var createEmptyVNode = function (text) { + if ( text === void 0 ) text = ''; + + var node = new VNode(); + node.text = text; + node.isComment = true; + return node + }; + + function createTextVNode (val) { + return new VNode(undefined, undefined, undefined, String(val)) + } + + // optimized shallow clone + // used for static nodes and slot nodes because they may be reused across + // multiple renders, cloning them avoids errors when DOM manipulations rely + // on their elm reference. + function cloneVNode (vnode) { + var cloned = new VNode( + vnode.tag, + vnode.data, + // #7975 + // clone children array to avoid mutating original in case of cloning + // a child. + vnode.children && vnode.children.slice(), + vnode.text, + vnode.elm, + vnode.context, + vnode.componentOptions, + vnode.asyncFactory + ); + cloned.ns = vnode.ns; + cloned.isStatic = vnode.isStatic; + cloned.key = vnode.key; + cloned.isComment = vnode.isComment; + cloned.fnContext = vnode.fnContext; + cloned.fnOptions = vnode.fnOptions; + cloned.fnScopeId = vnode.fnScopeId; + cloned.asyncMeta = vnode.asyncMeta; + cloned.isCloned = true; + return cloned + } + + /* + * not type checking this file because flow doesn't play well with + * dynamically accessing methods on Array prototype + */ + + var arrayProto = Array.prototype; + var arrayMethods = Object.create(arrayProto); + + var methodsToPatch = [ + 'push', + 'pop', + 'shift', + 'unshift', + 'splice', + 'sort', + 'reverse' + ]; + + /** + * Intercept mutating methods and emit events + */ + methodsToPatch.forEach(function (method) { + // cache original method + var original = arrayProto[method]; + def(arrayMethods, method, function mutator () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + var result = original.apply(this, args); + var ob = this.__ob__; + var inserted; + switch (method) { + case 'push': + case 'unshift': + inserted = args; + break + case 'splice': + inserted = args.slice(2); + break + } + if (inserted) { ob.observeArray(inserted); } + // notify change + ob.dep.notify(); + return result + }); + }); + + /* */ + + var arrayKeys = Object.getOwnPropertyNames(arrayMethods); + + /** + * In some cases we may want to disable observation inside a component's + * update computation. + */ + var shouldObserve = true; + + function toggleObserving (value) { + shouldObserve = value; + } + + /** + * Observer class that is attached to each observed + * object. Once attached, the observer converts the target + * object's property keys into getter/setters that + * collect dependencies and dispatch updates. + */ + var Observer = function Observer (value) { + this.value = value; + this.dep = new Dep(); + this.vmCount = 0; + def(value, '__ob__', this); + if (Array.isArray(value)) { + if (hasProto) { + protoAugment(value, arrayMethods); + } else { + copyAugment(value, arrayMethods, arrayKeys); + } + this.observeArray(value); + } else { + this.walk(value); + } + }; + + /** + * Walk through all properties and convert them into + * getter/setters. This method should only be called when + * value type is Object. + */ + Observer.prototype.walk = function walk (obj) { + var keys = Object.keys(obj); + for (var i = 0; i < keys.length; i++) { + defineReactive$$1(obj, keys[i]); + } + }; + + /** + * Observe a list of Array items. + */ + Observer.prototype.observeArray = function observeArray (items) { + for (var i = 0, l = items.length; i < l; i++) { + observe(items[i]); + } + }; + + // helpers + + /** + * Augment a target Object or Array by intercepting + * the prototype chain using __proto__ + */ + function protoAugment (target, src) { + /* eslint-disable no-proto */ + target.__proto__ = src; + /* eslint-enable no-proto */ + } + + /** + * Augment a target Object or Array by defining + * hidden properties. + */ + /* istanbul ignore next */ + function copyAugment (target, src, keys) { + for (var i = 0, l = keys.length; i < l; i++) { + var key = keys[i]; + def(target, key, src[key]); + } + } + + /** + * Attempt to create an observer instance for a value, + * returns the new observer if successfully observed, + * or the existing observer if the value already has one. + */ + function observe (value, asRootData) { + if (!isObject(value) || value instanceof VNode) { + return + } + var ob; + if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) { + ob = value.__ob__; + } else if ( + shouldObserve && + !isServerRendering() && + (Array.isArray(value) || isPlainObject(value)) && + Object.isExtensible(value) && + !value._isVue + ) { + ob = new Observer(value); + } + if (asRootData && ob) { + ob.vmCount++; + } + return ob + } + + /** + * Define a reactive property on an Object. + */ + function defineReactive$$1 ( + obj, + key, + val, + customSetter, + shallow + ) { + var dep = new Dep(); + + var property = Object.getOwnPropertyDescriptor(obj, key); + if (property && property.configurable === false) { + return + } + + // cater for pre-defined getter/setters + var getter = property && property.get; + var setter = property && property.set; + if ((!getter || setter) && arguments.length === 2) { + val = obj[key]; + } + + var childOb = !shallow && observe(val); + Object.defineProperty(obj, key, { + enumerable: true, + configurable: true, + get: function reactiveGetter () { + var value = getter ? getter.call(obj) : val; + if (Dep.target) { + dep.depend(); + if (childOb) { + childOb.dep.depend(); + if (Array.isArray(value)) { + dependArray(value); + } + } + } + return value + }, + set: function reactiveSetter (newVal) { + var value = getter ? getter.call(obj) : val; + /* eslint-disable no-self-compare */ + if (newVal === value || (newVal !== newVal && value !== value)) { + return + } + /* eslint-enable no-self-compare */ + if (customSetter) { + customSetter(); + } + // #7981: for accessor properties without setter + if (getter && !setter) { return } + if (setter) { + setter.call(obj, newVal); + } else { + val = newVal; + } + childOb = !shallow && observe(newVal); + dep.notify(); + } + }); + } + + /** + * Set a property on an object. Adds the new property and + * triggers change notification if the property doesn't + * already exist. + */ + function set (target, key, val) { + if (isUndef(target) || isPrimitive(target) + ) { + warn(("Cannot set reactive property on undefined, null, or primitive value: " + ((target)))); + } + if (Array.isArray(target) && isValidArrayIndex(key)) { + target.length = Math.max(target.length, key); + target.splice(key, 1, val); + return val + } + if (key in target && !(key in Object.prototype)) { + target[key] = val; + return val + } + var ob = (target).__ob__; + if (target._isVue || (ob && ob.vmCount)) { + warn( + 'Avoid adding reactive properties to a Vue instance or its root $data ' + + 'at runtime - declare it upfront in the data option.' + ); + return val + } + if (!ob) { + target[key] = val; + return val + } + defineReactive$$1(ob.value, key, val); + ob.dep.notify(); + return val + } + + /** + * Delete a property and trigger change if necessary. + */ + function del (target, key) { + if (isUndef(target) || isPrimitive(target) + ) { + warn(("Cannot delete reactive property on undefined, null, or primitive value: " + ((target)))); + } + if (Array.isArray(target) && isValidArrayIndex(key)) { + target.splice(key, 1); + return + } + var ob = (target).__ob__; + if (target._isVue || (ob && ob.vmCount)) { + warn( + 'Avoid deleting properties on a Vue instance or its root $data ' + + '- just set it to null.' + ); + return + } + if (!hasOwn(target, key)) { + return + } + delete target[key]; + if (!ob) { + return + } + ob.dep.notify(); + } + + /** + * Collect dependencies on array elements when the array is touched, since + * we cannot intercept array element access like property getters. + */ + function dependArray (value) { + for (var e = (void 0), i = 0, l = value.length; i < l; i++) { + e = value[i]; + e && e.__ob__ && e.__ob__.dep.depend(); + if (Array.isArray(e)) { + dependArray(e); + } + } + } + + /* */ + + /** + * Option overwriting strategies are functions that handle + * how to merge a parent option value and a child option + * value into the final value. + */ + var strats = config.optionMergeStrategies; + + /** + * Options with restrictions + */ + { + strats.el = strats.propsData = function (parent, child, vm, key) { + if (!vm) { + warn( + "option \"" + key + "\" can only be used during instance " + + 'creation with the `new` keyword.' + ); + } + return defaultStrat(parent, child) + }; + } + + /** + * Helper that recursively merges two data objects together. + */ + function mergeData (to, from) { + if (!from) { return to } + var key, toVal, fromVal; + + var keys = hasSymbol + ? Reflect.ownKeys(from) + : Object.keys(from); + + for (var i = 0; i < keys.length; i++) { + key = keys[i]; + // in case the object is already observed... + if (key === '__ob__') { continue } + toVal = to[key]; + fromVal = from[key]; + if (!hasOwn(to, key)) { + set(to, key, fromVal); + } else if ( + toVal !== fromVal && + isPlainObject(toVal) && + isPlainObject(fromVal) + ) { + mergeData(toVal, fromVal); + } + } + return to + } + + /** + * Data + */ + function mergeDataOrFn ( + parentVal, + childVal, + vm + ) { + if (!vm) { + // in a Vue.extend merge, both should be functions + if (!childVal) { + return parentVal + } + if (!parentVal) { + return childVal + } + // when parentVal & childVal are both present, + // we need to return a function that returns the + // merged result of both functions... no need to + // check if parentVal is a function here because + // it has to be a function to pass previous merges. + return function mergedDataFn () { + return mergeData( + typeof childVal === 'function' ? childVal.call(this, this) : childVal, + typeof parentVal === 'function' ? parentVal.call(this, this) : parentVal + ) + } + } else { + return function mergedInstanceDataFn () { + // instance merge + var instanceData = typeof childVal === 'function' + ? childVal.call(vm, vm) + : childVal; + var defaultData = typeof parentVal === 'function' + ? parentVal.call(vm, vm) + : parentVal; + if (instanceData) { + return mergeData(instanceData, defaultData) + } else { + return defaultData + } + } + } + } + + strats.data = function ( + parentVal, + childVal, + vm + ) { + if (!vm) { + if (childVal && typeof childVal !== 'function') { + warn( + 'The "data" option should be a function ' + + 'that returns a per-instance value in component ' + + 'definitions.', + vm + ); + + return parentVal + } + return mergeDataOrFn(parentVal, childVal) + } + + return mergeDataOrFn(parentVal, childVal, vm) + }; + + /** + * Hooks and props are merged as arrays. + */ + function mergeHook ( + parentVal, + childVal + ) { + var res = childVal + ? parentVal + ? parentVal.concat(childVal) + : Array.isArray(childVal) + ? childVal + : [childVal] + : parentVal; + return res + ? dedupeHooks(res) + : res + } + + function dedupeHooks (hooks) { + var res = []; + for (var i = 0; i < hooks.length; i++) { + if (res.indexOf(hooks[i]) === -1) { + res.push(hooks[i]); + } + } + return res + } + + LIFECYCLE_HOOKS.forEach(function (hook) { + strats[hook] = mergeHook; + }); + + /** + * Assets + * + * When a vm is present (instance creation), we need to do + * a three-way merge between constructor options, instance + * options and parent options. + */ + function mergeAssets ( + parentVal, + childVal, + vm, + key + ) { + var res = Object.create(parentVal || null); + if (childVal) { + assertObjectType(key, childVal, vm); + return extend(res, childVal) + } else { + return res + } + } + + ASSET_TYPES.forEach(function (type) { + strats[type + 's'] = mergeAssets; + }); + + /** + * Watchers. + * + * Watchers hashes should not overwrite one + * another, so we merge them as arrays. + */ + strats.watch = function ( + parentVal, + childVal, + vm, + key + ) { + // work around Firefox's Object.prototype.watch... + if (parentVal === nativeWatch) { parentVal = undefined; } + if (childVal === nativeWatch) { childVal = undefined; } + /* istanbul ignore if */ + if (!childVal) { return Object.create(parentVal || null) } + { + assertObjectType(key, childVal, vm); + } + if (!parentVal) { return childVal } + var ret = {}; + extend(ret, parentVal); + for (var key$1 in childVal) { + var parent = ret[key$1]; + var child = childVal[key$1]; + if (parent && !Array.isArray(parent)) { + parent = [parent]; + } + ret[key$1] = parent + ? parent.concat(child) + : Array.isArray(child) ? child : [child]; + } + return ret + }; + + /** + * Other object hashes. + */ + strats.props = + strats.methods = + strats.inject = + strats.computed = function ( + parentVal, + childVal, + vm, + key + ) { + if (childVal && "development" !== 'production') { + assertObjectType(key, childVal, vm); + } + if (!parentVal) { return childVal } + var ret = Object.create(null); + extend(ret, parentVal); + if (childVal) { extend(ret, childVal); } + return ret + }; + strats.provide = mergeDataOrFn; + + /** + * Default strategy. + */ + var defaultStrat = function (parentVal, childVal) { + return childVal === undefined + ? parentVal + : childVal + }; + + /** + * Validate component names + */ + function checkComponents (options) { + for (var key in options.components) { + validateComponentName(key); + } + } + + function validateComponentName (name) { + if (!new RegExp(("^[a-zA-Z][\\-\\.0-9_" + (unicodeRegExp.source) + "]*$")).test(name)) { + warn( + 'Invalid component name: "' + name + '". Component names ' + + 'should conform to valid custom element name in html5 specification.' + ); + } + if (isBuiltInTag(name) || config.isReservedTag(name)) { + warn( + 'Do not use built-in or reserved HTML elements as component ' + + 'id: ' + name + ); + } + } + + /** + * Ensure all props option syntax are normalized into the + * Object-based format. + */ + function normalizeProps (options, vm) { + var props = options.props; + if (!props) { return } + var res = {}; + var i, val, name; + if (Array.isArray(props)) { + i = props.length; + while (i--) { + val = props[i]; + if (typeof val === 'string') { + name = camelize(val); + res[name] = { type: null }; + } else { + warn('props must be strings when using array syntax.'); + } + } + } else if (isPlainObject(props)) { + for (var key in props) { + val = props[key]; + name = camelize(key); + res[name] = isPlainObject(val) + ? val + : { type: val }; + } + } else { + warn( + "Invalid value for option \"props\": expected an Array or an Object, " + + "but got " + (toRawType(props)) + ".", + vm + ); + } + options.props = res; + } + + /** + * Normalize all injections into Object-based format + */ + function normalizeInject (options, vm) { + var inject = options.inject; + if (!inject) { return } + var normalized = options.inject = {}; + if (Array.isArray(inject)) { + for (var i = 0; i < inject.length; i++) { + normalized[inject[i]] = { from: inject[i] }; + } + } else if (isPlainObject(inject)) { + for (var key in inject) { + var val = inject[key]; + normalized[key] = isPlainObject(val) + ? extend({ from: key }, val) + : { from: val }; + } + } else { + warn( + "Invalid value for option \"inject\": expected an Array or an Object, " + + "but got " + (toRawType(inject)) + ".", + vm + ); + } + } + + /** + * Normalize raw function directives into object format. + */ + function normalizeDirectives (options) { + var dirs = options.directives; + if (dirs) { + for (var key in dirs) { + var def$$1 = dirs[key]; + if (typeof def$$1 === 'function') { + dirs[key] = { bind: def$$1, update: def$$1 }; + } + } + } + } + + function assertObjectType (name, value, vm) { + if (!isPlainObject(value)) { + warn( + "Invalid value for option \"" + name + "\": expected an Object, " + + "but got " + (toRawType(value)) + ".", + vm + ); + } + } + + /** + * Merge two option objects into a new one. + * Core utility used in both instantiation and inheritance. + */ + function mergeOptions ( + parent, + child, + vm + ) { + { + checkComponents(child); + } + + if (typeof child === 'function') { + child = child.options; + } + + normalizeProps(child, vm); + normalizeInject(child, vm); + normalizeDirectives(child); + + // Apply extends and mixins on the child options, + // but only if it is a raw options object that isn't + // the result of another mergeOptions call. + // Only merged options has the _base property. + if (!child._base) { + if (child.extends) { + parent = mergeOptions(parent, child.extends, vm); + } + if (child.mixins) { + for (var i = 0, l = child.mixins.length; i < l; i++) { + parent = mergeOptions(parent, child.mixins[i], vm); + } + } + } + + var options = {}; + var key; + for (key in parent) { + mergeField(key); + } + for (key in child) { + if (!hasOwn(parent, key)) { + mergeField(key); + } + } + function mergeField (key) { + var strat = strats[key] || defaultStrat; + options[key] = strat(parent[key], child[key], vm, key); + } + return options + } + + /** + * Resolve an asset. + * This function is used because child instances need access + * to assets defined in its ancestor chain. + */ + function resolveAsset ( + options, + type, + id, + warnMissing + ) { + /* istanbul ignore if */ + if (typeof id !== 'string') { + return + } + var assets = options[type]; + // check local registration variations first + if (hasOwn(assets, id)) { return assets[id] } + var camelizedId = camelize(id); + if (hasOwn(assets, camelizedId)) { return assets[camelizedId] } + var PascalCaseId = capitalize(camelizedId); + if (hasOwn(assets, PascalCaseId)) { return assets[PascalCaseId] } + // fallback to prototype chain + var res = assets[id] || assets[camelizedId] || assets[PascalCaseId]; + if (warnMissing && !res) { + warn( + 'Failed to resolve ' + type.slice(0, -1) + ': ' + id, + options + ); + } + return res + } + + /* */ + + + + function validateProp ( + key, + propOptions, + propsData, + vm + ) { + var prop = propOptions[key]; + var absent = !hasOwn(propsData, key); + var value = propsData[key]; + // boolean casting + var booleanIndex = getTypeIndex(Boolean, prop.type); + if (booleanIndex > -1) { + if (absent && !hasOwn(prop, 'default')) { + value = false; + } else if (value === '' || value === hyphenate(key)) { + // only cast empty string / same name to boolean if + // boolean has higher priority + var stringIndex = getTypeIndex(String, prop.type); + if (stringIndex < 0 || booleanIndex < stringIndex) { + value = true; + } + } + } + // check default value + if (value === undefined) { + value = getPropDefaultValue(vm, prop, key); + // since the default value is a fresh copy, + // make sure to observe it. + var prevShouldObserve = shouldObserve; + toggleObserving(true); + observe(value); + toggleObserving(prevShouldObserve); + } + { + assertProp(prop, key, value, vm, absent); + } + return value + } + + /** + * Get the default value of a prop. + */ + function getPropDefaultValue (vm, prop, key) { + // no default, return undefined + if (!hasOwn(prop, 'default')) { + return undefined + } + var def = prop.default; + // warn against non-factory defaults for Object & Array + if (isObject(def)) { + warn( + 'Invalid default value for prop "' + key + '": ' + + 'Props with type Object/Array must use a factory function ' + + 'to return the default value.', + vm + ); + } + // the raw prop value was also undefined from previous render, + // return previous default value to avoid unnecessary watcher trigger + if (vm && vm.$options.propsData && + vm.$options.propsData[key] === undefined && + vm._props[key] !== undefined + ) { + return vm._props[key] + } + // call factory function for non-Function types + // a value is Function if its prototype is function even across different execution context + return typeof def === 'function' && getType(prop.type) !== 'Function' + ? def.call(vm) + : def + } + + /** + * Assert whether a prop is valid. + */ + function assertProp ( + prop, + name, + value, + vm, + absent + ) { + if (prop.required && absent) { + warn( + 'Missing required prop: "' + name + '"', + vm + ); + return + } + if (value == null && !prop.required) { + return + } + var type = prop.type; + var valid = !type || type === true; + var expectedTypes = []; + if (type) { + if (!Array.isArray(type)) { + type = [type]; + } + for (var i = 0; i < type.length && !valid; i++) { + var assertedType = assertType(value, type[i]); + expectedTypes.push(assertedType.expectedType || ''); + valid = assertedType.valid; + } + } + + if (!valid) { + warn( + getInvalidTypeMessage(name, value, expectedTypes), + vm + ); + return + } + var validator = prop.validator; + if (validator) { + if (!validator(value)) { + warn( + 'Invalid prop: custom validator check failed for prop "' + name + '".', + vm + ); + } + } + } + + var simpleCheckRE = /^(String|Number|Boolean|Function|Symbol)$/; + + function assertType (value, type) { + var valid; + var expectedType = getType(type); + if (simpleCheckRE.test(expectedType)) { + var t = typeof value; + valid = t === expectedType.toLowerCase(); + // for primitive wrapper objects + if (!valid && t === 'object') { + valid = value instanceof type; + } + } else if (expectedType === 'Object') { + valid = isPlainObject(value); + } else if (expectedType === 'Array') { + valid = Array.isArray(value); + } else { + valid = value instanceof type; + } + return { + valid: valid, + expectedType: expectedType + } + } + + /** + * Use function string name to check built-in types, + * because a simple equality check will fail when running + * across different vms / iframes. + */ + function getType (fn) { + var match = fn && fn.toString().match(/^\s*function (\w+)/); + return match ? match[1] : '' + } + + function isSameType (a, b) { + return getType(a) === getType(b) + } + + function getTypeIndex (type, expectedTypes) { + if (!Array.isArray(expectedTypes)) { + return isSameType(expectedTypes, type) ? 0 : -1 + } + for (var i = 0, len = expectedTypes.length; i < len; i++) { + if (isSameType(expectedTypes[i], type)) { + return i + } + } + return -1 + } + + function getInvalidTypeMessage (name, value, expectedTypes) { + var message = "Invalid prop: type check failed for prop \"" + name + "\"." + + " Expected " + (expectedTypes.map(capitalize).join(', ')); + var expectedType = expectedTypes[0]; + var receivedType = toRawType(value); + var expectedValue = styleValue(value, expectedType); + var receivedValue = styleValue(value, receivedType); + // check if we need to specify expected value + if (expectedTypes.length === 1 && + isExplicable(expectedType) && + !isBoolean(expectedType, receivedType)) { + message += " with value " + expectedValue; + } + message += ", got " + receivedType + " "; + // check if we need to specify received value + if (isExplicable(receivedType)) { + message += "with value " + receivedValue + "."; + } + return message + } + + function styleValue (value, type) { + if (type === 'String') { + return ("\"" + value + "\"") + } else if (type === 'Number') { + return ("" + (Number(value))) + } else { + return ("" + value) + } + } + + function isExplicable (value) { + var explicitTypes = ['string', 'number', 'boolean']; + return explicitTypes.some(function (elem) { return value.toLowerCase() === elem; }) + } + + function isBoolean () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + return args.some(function (elem) { return elem.toLowerCase() === 'boolean'; }) + } + + /* */ + + function handleError (err, vm, info) { + // Deactivate deps tracking while processing error handler to avoid possible infinite rendering. + // See: https://github.com/vuejs/vuex/issues/1505 + pushTarget(); + try { + if (vm) { + var cur = vm; + while ((cur = cur.$parent)) { + var hooks = cur.$options.errorCaptured; + if (hooks) { + for (var i = 0; i < hooks.length; i++) { + try { + var capture = hooks[i].call(cur, err, vm, info) === false; + if (capture) { return } + } catch (e) { + globalHandleError(e, cur, 'errorCaptured hook'); + } + } + } + } + } + globalHandleError(err, vm, info); + } finally { + popTarget(); + } + } + + function invokeWithErrorHandling ( + handler, + context, + args, + vm, + info + ) { + var res; + try { + res = args ? handler.apply(context, args) : handler.call(context); + if (res && !res._isVue && isPromise(res) && !res._handled) { + res.catch(function (e) { return handleError(e, vm, info + " (Promise/async)"); }); + // issue #9511 + // avoid catch triggering multiple times when nested calls + res._handled = true; + } + } catch (e) { + handleError(e, vm, info); + } + return res + } + + function globalHandleError (err, vm, info) { + if (config.errorHandler) { + try { + return config.errorHandler.call(null, err, vm, info) + } catch (e) { + // if the user intentionally throws the original error in the handler, + // do not log it twice + if (e !== err) { + logError(e, null, 'config.errorHandler'); + } + } + } + logError(err, vm, info); + } + + function logError (err, vm, info) { + { + warn(("Error in " + info + ": \"" + (err.toString()) + "\""), vm); + } + /* istanbul ignore else */ + if ((inBrowser || inWeex) && typeof console !== 'undefined') { + console.error(err); + } else { + throw err + } + } + + /* */ + + var isUsingMicroTask = false; + + var callbacks = []; + var pending = false; + + function flushCallbacks () { + pending = false; + var copies = callbacks.slice(0); + callbacks.length = 0; + for (var i = 0; i < copies.length; i++) { + copies[i](); + } + } + + // Here we have async deferring wrappers using microtasks. + // In 2.5 we used (macro) tasks (in combination with microtasks). + // However, it has subtle problems when state is changed right before repaint + // (e.g. #6813, out-in transitions). + // Also, using (macro) tasks in event handler would cause some weird behaviors + // that cannot be circumvented (e.g. #7109, #7153, #7546, #7834, #8109). + // So we now use microtasks everywhere, again. + // A major drawback of this tradeoff is that there are some scenarios + // where microtasks have too high a priority and fire in between supposedly + // sequential events (e.g. #4521, #6690, which have workarounds) + // or even between bubbling of the same event (#6566). + var timerFunc; + + // The nextTick behavior leverages the microtask queue, which can be accessed + // via either native Promise.then or MutationObserver. + // MutationObserver has wider support, however it is seriously bugged in + // UIWebView in iOS >= 9.3.3 when triggered in touch event handlers. It + // completely stops working after triggering a few times... so, if native + // Promise is available, we will use it: + /* istanbul ignore next, $flow-disable-line */ + if (typeof Promise !== 'undefined' && isNative(Promise)) { + var p = Promise.resolve(); + timerFunc = function () { + p.then(flushCallbacks); + // In problematic UIWebViews, Promise.then doesn't completely break, but + // it can get stuck in a weird state where callbacks are pushed into the + // microtask queue but the queue isn't being flushed, until the browser + // needs to do some other work, e.g. handle a timer. Therefore we can + // "force" the microtask queue to be flushed by adding an empty timer. + if (isIOS) { setTimeout(noop); } + }; + isUsingMicroTask = true; + } else if (!isIE && typeof MutationObserver !== 'undefined' && ( + isNative(MutationObserver) || + // PhantomJS and iOS 7.x + MutationObserver.toString() === '[object MutationObserverConstructor]' + )) { + // Use MutationObserver where native Promise is not available, + // e.g. PhantomJS, iOS7, Android 4.4 + // (#6466 MutationObserver is unreliable in IE11) + var counter = 1; + var observer = new MutationObserver(flushCallbacks); + var textNode = document.createTextNode(String(counter)); + observer.observe(textNode, { + characterData: true + }); + timerFunc = function () { + counter = (counter + 1) % 2; + textNode.data = String(counter); + }; + isUsingMicroTask = true; + } else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) { + // Fallback to setImmediate. + // Technically it leverages the (macro) task queue, + // but it is still a better choice than setTimeout. + timerFunc = function () { + setImmediate(flushCallbacks); + }; + } else { + // Fallback to setTimeout. + timerFunc = function () { + setTimeout(flushCallbacks, 0); + }; + } + + function nextTick (cb, ctx) { + var _resolve; + callbacks.push(function () { + if (cb) { + try { + cb.call(ctx); + } catch (e) { + handleError(e, ctx, 'nextTick'); + } + } else if (_resolve) { + _resolve(ctx); + } + }); + if (!pending) { + pending = true; + timerFunc(); + } + // $flow-disable-line + if (!cb && typeof Promise !== 'undefined') { + return new Promise(function (resolve) { + _resolve = resolve; + }) + } + } + + /* */ + + var mark; + var measure; + + { + var perf = inBrowser && window.performance; + /* istanbul ignore if */ + if ( + perf && + perf.mark && + perf.measure && + perf.clearMarks && + perf.clearMeasures + ) { + mark = function (tag) { return perf.mark(tag); }; + measure = function (name, startTag, endTag) { + perf.measure(name, startTag, endTag); + perf.clearMarks(startTag); + perf.clearMarks(endTag); + // perf.clearMeasures(name) + }; + } + } + + /* not type checking this file because flow doesn't play well with Proxy */ + + var initProxy; + + { + var allowedGlobals = makeMap( + 'Infinity,undefined,NaN,isFinite,isNaN,' + + 'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' + + 'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,' + + 'require' // for Webpack/Browserify + ); + + var warnNonPresent = function (target, key) { + warn( + "Property or method \"" + key + "\" is not defined on the instance but " + + 'referenced during render. Make sure that this property is reactive, ' + + 'either in the data option, or for class-based components, by ' + + 'initializing the property. ' + + 'See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.', + target + ); + }; + + var warnReservedPrefix = function (target, key) { + warn( + "Property \"" + key + "\" must be accessed with \"$data." + key + "\" because " + + 'properties starting with "$" or "_" are not proxied in the Vue instance to ' + + 'prevent conflicts with Vue internals. ' + + 'See: https://vuejs.org/v2/api/#data', + target + ); + }; + + var hasProxy = + typeof Proxy !== 'undefined' && isNative(Proxy); + + if (hasProxy) { + var isBuiltInModifier = makeMap('stop,prevent,self,ctrl,shift,alt,meta,exact'); + config.keyCodes = new Proxy(config.keyCodes, { + set: function set (target, key, value) { + if (isBuiltInModifier(key)) { + warn(("Avoid overwriting built-in modifier in config.keyCodes: ." + key)); + return false + } else { + target[key] = value; + return true + } + } + }); + } + + var hasHandler = { + has: function has (target, key) { + var has = key in target; + var isAllowed = allowedGlobals(key) || + (typeof key === 'string' && key.charAt(0) === '_' && !(key in target.$data)); + if (!has && !isAllowed) { + if (key in target.$data) { warnReservedPrefix(target, key); } + else { warnNonPresent(target, key); } + } + return has || !isAllowed + } + }; + + var getHandler = { + get: function get (target, key) { + if (typeof key === 'string' && !(key in target)) { + if (key in target.$data) { warnReservedPrefix(target, key); } + else { warnNonPresent(target, key); } + } + return target[key] + } + }; + + initProxy = function initProxy (vm) { + if (hasProxy) { + // determine which proxy handler to use + var options = vm.$options; + var handlers = options.render && options.render._withStripped + ? getHandler + : hasHandler; + vm._renderProxy = new Proxy(vm, handlers); + } else { + vm._renderProxy = vm; + } + }; + } + + /* */ + + var seenObjects = new _Set(); + + /** + * Recursively traverse an object to evoke all converted + * getters, so that every nested property inside the object + * is collected as a "deep" dependency. + */ + function traverse (val) { + _traverse(val, seenObjects); + seenObjects.clear(); + } + + function _traverse (val, seen) { + var i, keys; + var isA = Array.isArray(val); + if ((!isA && !isObject(val)) || Object.isFrozen(val) || val instanceof VNode) { + return + } + if (val.__ob__) { + var depId = val.__ob__.dep.id; + if (seen.has(depId)) { + return + } + seen.add(depId); + } + if (isA) { + i = val.length; + while (i--) { _traverse(val[i], seen); } + } else { + keys = Object.keys(val); + i = keys.length; + while (i--) { _traverse(val[keys[i]], seen); } + } + } + + /* */ + + var normalizeEvent = cached(function (name) { + var passive = name.charAt(0) === '&'; + name = passive ? name.slice(1) : name; + var once$$1 = name.charAt(0) === '~'; // Prefixed last, checked first + name = once$$1 ? name.slice(1) : name; + var capture = name.charAt(0) === '!'; + name = capture ? name.slice(1) : name; + return { + name: name, + once: once$$1, + capture: capture, + passive: passive + } + }); + + function createFnInvoker (fns, vm) { + function invoker () { + var arguments$1 = arguments; + + var fns = invoker.fns; + if (Array.isArray(fns)) { + var cloned = fns.slice(); + for (var i = 0; i < cloned.length; i++) { + invokeWithErrorHandling(cloned[i], null, arguments$1, vm, "v-on handler"); + } + } else { + // return handler return value for single handlers + return invokeWithErrorHandling(fns, null, arguments, vm, "v-on handler") + } + } + invoker.fns = fns; + return invoker + } + + function updateListeners ( + on, + oldOn, + add, + remove$$1, + createOnceHandler, + vm + ) { + var name, def$$1, cur, old, event; + for (name in on) { + def$$1 = cur = on[name]; + old = oldOn[name]; + event = normalizeEvent(name); + if (isUndef(cur)) { + warn( + "Invalid handler for event \"" + (event.name) + "\": got " + String(cur), + vm + ); + } else if (isUndef(old)) { + if (isUndef(cur.fns)) { + cur = on[name] = createFnInvoker(cur, vm); + } + if (isTrue(event.once)) { + cur = on[name] = createOnceHandler(event.name, cur, event.capture); + } + add(event.name, cur, event.capture, event.passive, event.params); + } else if (cur !== old) { + old.fns = cur; + on[name] = old; + } + } + for (name in oldOn) { + if (isUndef(on[name])) { + event = normalizeEvent(name); + remove$$1(event.name, oldOn[name], event.capture); + } + } + } + + /* */ + + function mergeVNodeHook (def, hookKey, hook) { + if (def instanceof VNode) { + def = def.data.hook || (def.data.hook = {}); + } + var invoker; + var oldHook = def[hookKey]; + + function wrappedHook () { + hook.apply(this, arguments); + // important: remove merged hook to ensure it's called only once + // and prevent memory leak + remove(invoker.fns, wrappedHook); + } + + if (isUndef(oldHook)) { + // no existing hook + invoker = createFnInvoker([wrappedHook]); + } else { + /* istanbul ignore if */ + if (isDef(oldHook.fns) && isTrue(oldHook.merged)) { + // already a merged invoker + invoker = oldHook; + invoker.fns.push(wrappedHook); + } else { + // existing plain hook + invoker = createFnInvoker([oldHook, wrappedHook]); + } + } + + invoker.merged = true; + def[hookKey] = invoker; + } + + /* */ + + function extractPropsFromVNodeData ( + data, + Ctor, + tag + ) { + // we are only extracting raw values here. + // validation and default values are handled in the child + // component itself. + var propOptions = Ctor.options.props; + if (isUndef(propOptions)) { + return + } + var res = {}; + var attrs = data.attrs; + var props = data.props; + if (isDef(attrs) || isDef(props)) { + for (var key in propOptions) { + var altKey = hyphenate(key); + { + var keyInLowerCase = key.toLowerCase(); + if ( + key !== keyInLowerCase && + attrs && hasOwn(attrs, keyInLowerCase) + ) { + tip( + "Prop \"" + keyInLowerCase + "\" is passed to component " + + (formatComponentName(tag || Ctor)) + ", but the declared prop name is" + + " \"" + key + "\". " + + "Note that HTML attributes are case-insensitive and camelCased " + + "props need to use their kebab-case equivalents when using in-DOM " + + "templates. You should probably use \"" + altKey + "\" instead of \"" + key + "\"." + ); + } + } + checkProp(res, props, key, altKey, true) || + checkProp(res, attrs, key, altKey, false); + } + } + return res + } + + function checkProp ( + res, + hash, + key, + altKey, + preserve + ) { + if (isDef(hash)) { + if (hasOwn(hash, key)) { + res[key] = hash[key]; + if (!preserve) { + delete hash[key]; + } + return true + } else if (hasOwn(hash, altKey)) { + res[key] = hash[altKey]; + if (!preserve) { + delete hash[altKey]; + } + return true + } + } + return false + } + + /* */ + + // The template compiler attempts to minimize the need for normalization by + // statically analyzing the template at compile time. + // + // For plain HTML markup, normalization can be completely skipped because the + // generated render function is guaranteed to return Array. There are + // two cases where extra normalization is needed: + + // 1. When the children contains components - because a functional component + // may return an Array instead of a single root. In this case, just a simple + // normalization is needed - if any child is an Array, we flatten the whole + // thing with Array.prototype.concat. It is guaranteed to be only 1-level deep + // because functional components already normalize their own children. + function simpleNormalizeChildren (children) { + for (var i = 0; i < children.length; i++) { + if (Array.isArray(children[i])) { + return Array.prototype.concat.apply([], children) + } + } + return children + } + + // 2. When the children contains constructs that always generated nested Arrays, + // e.g.