").append( jQuery.parseHTML( responseText ) ).find( selector ) :
+
+ // Otherwise use the full result
+ responseText );
+
+ }).complete( callback && function( jqXHR, status ) {
+ self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
+ });
+ }
+
+ return this;
+};
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ){
+ jQuery.fn[ type ] = function( fn ){
+ return this.on( type, fn );
+ };
+});
+
+jQuery.extend({
+
+ // Counter for holding the number of active queries
+ active: 0,
+
+ // Last-Modified header cache for next request
+ lastModified: {},
+ etag: {},
+
+ ajaxSettings: {
+ url: ajaxLocation,
+ type: "GET",
+ isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
+ global: true,
+ processData: true,
+ async: true,
+ contentType: "application/x-www-form-urlencoded; charset=UTF-8",
+ /*
+ timeout: 0,
+ data: null,
+ dataType: null,
+ username: null,
+ password: null,
+ cache: null,
+ throws: false,
+ traditional: false,
+ headers: {},
+ */
+
+ accepts: {
+ "*": allTypes,
+ text: "text/plain",
+ html: "text/html",
+ xml: "application/xml, text/xml",
+ json: "application/json, text/javascript"
+ },
+
+ contents: {
+ xml: /xml/,
+ html: /html/,
+ json: /json/
+ },
+
+ responseFields: {
+ xml: "responseXML",
+ text: "responseText",
+ json: "responseJSON"
+ },
+
+ // Data converters
+ // Keys separate source (or catchall "*") and destination types with a single space
+ converters: {
+
+ // Convert anything to text
+ "* text": String,
+
+ // Text to html (true = no transformation)
+ "text html": true,
+
+ // Evaluate text as a json expression
+ "text json": jQuery.parseJSON,
+
+ // Parse text as xml
+ "text xml": jQuery.parseXML
+ },
+
+ // For options that shouldn't be deep extended:
+ // you can add your own custom options here if
+ // and when you create one that shouldn't be
+ // deep extended (see ajaxExtend)
+ flatOptions: {
+ url: true,
+ context: true
+ }
+ },
+
+ // Creates a full fledged settings object into target
+ // with both ajaxSettings and settings fields.
+ // If target is omitted, writes into ajaxSettings.
+ ajaxSetup: function( target, settings ) {
+ return settings ?
+
+ // Building a settings object
+ ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
+
+ // Extending ajaxSettings
+ ajaxExtend( jQuery.ajaxSettings, target );
+ },
+
+ ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
+ ajaxTransport: addToPrefiltersOrTransports( transports ),
+
+ // Main method
+ ajax: function( url, options ) {
+
+ // If url is an object, simulate pre-1.5 signature
+ if ( typeof url === "object" ) {
+ options = url;
+ url = undefined;
+ }
+
+ // Force options to be an object
+ options = options || {};
+
+ var // Cross-domain detection vars
+ parts,
+ // Loop variable
+ i,
+ // URL without anti-cache param
+ cacheURL,
+ // Response headers as string
+ responseHeadersString,
+ // timeout handle
+ timeoutTimer,
+
+ // To know if global events are to be dispatched
+ fireGlobals,
+
+ transport,
+ // Response headers
+ responseHeaders,
+ // Create the final options object
+ s = jQuery.ajaxSetup( {}, options ),
+ // Callbacks context
+ callbackContext = s.context || s,
+ // Context for global events is callbackContext if it is a DOM node or jQuery collection
+ globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?
+ jQuery( callbackContext ) :
+ jQuery.event,
+ // Deferreds
+ deferred = jQuery.Deferred(),
+ completeDeferred = jQuery.Callbacks("once memory"),
+ // Status-dependent callbacks
+ statusCode = s.statusCode || {},
+ // Headers (they are sent all at once)
+ requestHeaders = {},
+ requestHeadersNames = {},
+ // The jqXHR state
+ state = 0,
+ // Default abort message
+ strAbort = "canceled",
+ // Fake xhr
+ jqXHR = {
+ readyState: 0,
+
+ // Builds headers hashtable if needed
+ getResponseHeader: function( key ) {
+ var match;
+ if ( state === 2 ) {
+ if ( !responseHeaders ) {
+ responseHeaders = {};
+ while ( (match = rheaders.exec( responseHeadersString )) ) {
+ responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
+ }
+ }
+ match = responseHeaders[ key.toLowerCase() ];
+ }
+ return match == null ? null : match;
+ },
+
+ // Raw string
+ getAllResponseHeaders: function() {
+ return state === 2 ? responseHeadersString : null;
+ },
+
+ // Caches the header
+ setRequestHeader: function( name, value ) {
+ var lname = name.toLowerCase();
+ if ( !state ) {
+ name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
+ requestHeaders[ name ] = value;
+ }
+ return this;
+ },
+
+ // Overrides response content-type header
+ overrideMimeType: function( type ) {
+ if ( !state ) {
+ s.mimeType = type;
+ }
+ return this;
+ },
+
+ // Status-dependent callbacks
+ statusCode: function( map ) {
+ var code;
+ if ( map ) {
+ if ( state < 2 ) {
+ for ( code in map ) {
+ // Lazy-add the new callback in a way that preserves old ones
+ statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
+ }
+ } else {
+ // Execute the appropriate callbacks
+ jqXHR.always( map[ jqXHR.status ] );
+ }
+ }
+ return this;
+ },
+
+ // Cancel the request
+ abort: function( statusText ) {
+ var finalText = statusText || strAbort;
+ if ( transport ) {
+ transport.abort( finalText );
+ }
+ done( 0, finalText );
+ return this;
+ }
+ };
+
+ // Attach deferreds
+ deferred.promise( jqXHR ).complete = completeDeferred.add;
+ jqXHR.success = jqXHR.done;
+ jqXHR.error = jqXHR.fail;
+
+ // Remove hash character (#7531: and string promotion)
+ // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
+ // Handle falsy url in the settings object (#10093: consistency with old signature)
+ // We also use the url parameter if available
+ s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
+
+ // Alias method option to type as per ticket #12004
+ s.type = options.method || options.type || s.method || s.type;
+
+ // Extract dataTypes list
+ s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( core_rnotwhite ) || [""];
+
+ // A cross-domain request is in order when we have a protocol:host:port mismatch
+ if ( s.crossDomain == null ) {
+ parts = rurl.exec( s.url.toLowerCase() );
+ s.crossDomain = !!( parts &&
+ ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
+ ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !==
+ ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) )
+ );
+ }
+
+ // Convert data if not already a string
+ if ( s.data && s.processData && typeof s.data !== "string" ) {
+ s.data = jQuery.param( s.data, s.traditional );
+ }
+
+ // Apply prefilters
+ inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
+
+ // If request was aborted inside a prefilter, stop there
+ if ( state === 2 ) {
+ return jqXHR;
+ }
+
+ // We can fire global events as of now if asked to
+ fireGlobals = s.global;
+
+ // Watch for a new set of requests
+ if ( fireGlobals && jQuery.active++ === 0 ) {
+ jQuery.event.trigger("ajaxStart");
+ }
+
+ // Uppercase the type
+ s.type = s.type.toUpperCase();
+
+ // Determine if request has content
+ s.hasContent = !rnoContent.test( s.type );
+
+ // Save the URL in case we're toying with the If-Modified-Since
+ // and/or If-None-Match header later on
+ cacheURL = s.url;
+
+ // More options handling for requests with no content
+ if ( !s.hasContent ) {
+
+ // If data is available, append data to url
+ if ( s.data ) {
+ cacheURL = ( s.url += ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
+ // #9682: remove data so that it's not used in an eventual retry
+ delete s.data;
+ }
+
+ // Add anti-cache in url if needed
+ if ( s.cache === false ) {
+ s.url = rts.test( cacheURL ) ?
+
+ // If there is already a '_' parameter, set its value
+ cacheURL.replace( rts, "$1_=" + ajax_nonce++ ) :
+
+ // Otherwise add one to the end
+ cacheURL + ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ajax_nonce++;
+ }
+ }
+
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+ if ( jQuery.lastModified[ cacheURL ] ) {
+ jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
+ }
+ if ( jQuery.etag[ cacheURL ] ) {
+ jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
+ }
+ }
+
+ // Set the correct header, if data is being sent
+ if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
+ jqXHR.setRequestHeader( "Content-Type", s.contentType );
+ }
+
+ // Set the Accepts header for the server, depending on the dataType
+ jqXHR.setRequestHeader(
+ "Accept",
+ s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
+ s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
+ s.accepts[ "*" ]
+ );
+
+ // Check for headers option
+ for ( i in s.headers ) {
+ jqXHR.setRequestHeader( i, s.headers[ i ] );
+ }
+
+ // Allow custom headers/mimetypes and early abort
+ if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
+ // Abort if not done already and return
+ return jqXHR.abort();
+ }
+
+ // aborting is no longer a cancellation
+ strAbort = "abort";
+
+ // Install callbacks on deferreds
+ for ( i in { success: 1, error: 1, complete: 1 } ) {
+ jqXHR[ i ]( s[ i ] );
+ }
+
+ // Get transport
+ transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
+
+ // If no transport, we auto-abort
+ if ( !transport ) {
+ done( -1, "No Transport" );
+ } else {
+ jqXHR.readyState = 1;
+
+ // Send global event
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
+ }
+ // Timeout
+ if ( s.async && s.timeout > 0 ) {
+ timeoutTimer = setTimeout(function() {
+ jqXHR.abort("timeout");
+ }, s.timeout );
+ }
+
+ try {
+ state = 1;
+ transport.send( requestHeaders, done );
+ } catch ( e ) {
+ // Propagate exception as error if not done
+ if ( state < 2 ) {
+ done( -1, e );
+ // Simply rethrow otherwise
+ } else {
+ throw e;
+ }
+ }
+ }
+
+ // Callback for when everything is done
+ function done( status, nativeStatusText, responses, headers ) {
+ var isSuccess, success, error, response, modified,
+ statusText = nativeStatusText;
+
+ // Called once
+ if ( state === 2 ) {
+ return;
+ }
+
+ // State is "done" now
+ state = 2;
+
+ // Clear timeout if it exists
+ if ( timeoutTimer ) {
+ clearTimeout( timeoutTimer );
+ }
+
+ // Dereference transport for early garbage collection
+ // (no matter how long the jqXHR object will be used)
+ transport = undefined;
+
+ // Cache response headers
+ responseHeadersString = headers || "";
+
+ // Set readyState
+ jqXHR.readyState = status > 0 ? 4 : 0;
+
+ // Determine if successful
+ isSuccess = status >= 200 && status < 300 || status === 304;
+
+ // Get response data
+ if ( responses ) {
+ response = ajaxHandleResponses( s, jqXHR, responses );
+ }
+
+ // Convert no matter what (that way responseXXX fields are always set)
+ response = ajaxConvert( s, response, jqXHR, isSuccess );
+
+ // If successful, handle type chaining
+ if ( isSuccess ) {
+
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+ modified = jqXHR.getResponseHeader("Last-Modified");
+ if ( modified ) {
+ jQuery.lastModified[ cacheURL ] = modified;
+ }
+ modified = jqXHR.getResponseHeader("etag");
+ if ( modified ) {
+ jQuery.etag[ cacheURL ] = modified;
+ }
+ }
+
+ // if no content
+ if ( status === 204 || s.type === "HEAD" ) {
+ statusText = "nocontent";
+
+ // if not modified
+ } else if ( status === 304 ) {
+ statusText = "notmodified";
+
+ // If we have data, let's convert it
+ } else {
+ statusText = response.state;
+ success = response.data;
+ error = response.error;
+ isSuccess = !error;
+ }
+ } else {
+ // We extract error from statusText
+ // then normalize statusText and status for non-aborts
+ error = statusText;
+ if ( status || !statusText ) {
+ statusText = "error";
+ if ( status < 0 ) {
+ status = 0;
+ }
+ }
+ }
+
+ // Set data for the fake xhr object
+ jqXHR.status = status;
+ jqXHR.statusText = ( nativeStatusText || statusText ) + "";
+
+ // Success/Error
+ if ( isSuccess ) {
+ deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
+ } else {
+ deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
+ }
+
+ // Status-dependent callbacks
+ jqXHR.statusCode( statusCode );
+ statusCode = undefined;
+
+ if ( fireGlobals ) {
+ globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
+ [ jqXHR, s, isSuccess ? success : error ] );
+ }
+
+ // Complete
+ completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
+
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
+ // Handle the global AJAX counter
+ if ( !( --jQuery.active ) ) {
+ jQuery.event.trigger("ajaxStop");
+ }
+ }
+ }
+
+ return jqXHR;
+ },
+
+ getJSON: function( url, data, callback ) {
+ return jQuery.get( url, data, callback, "json" );
+ },
+
+ getScript: function( url, callback ) {
+ return jQuery.get( url, undefined, callback, "script" );
+ }
+});
+
+jQuery.each( [ "get", "post" ], function( i, method ) {
+ jQuery[ method ] = function( url, data, callback, type ) {
+ // shift arguments if data argument was omitted
+ if ( jQuery.isFunction( data ) ) {
+ type = type || callback;
+ callback = data;
+ data = undefined;
+ }
+
+ return jQuery.ajax({
+ url: url,
+ type: method,
+ dataType: type,
+ data: data,
+ success: callback
+ });
+ };
+});
+
+/* Handles responses to an ajax request:
+ * - finds the right dataType (mediates between content-type and expected dataType)
+ * - returns the corresponding response
+ */
+function ajaxHandleResponses( s, jqXHR, responses ) {
+ var firstDataType, ct, finalDataType, type,
+ contents = s.contents,
+ dataTypes = s.dataTypes;
+
+ // Remove auto dataType and get content-type in the process
+ while( dataTypes[ 0 ] === "*" ) {
+ dataTypes.shift();
+ if ( ct === undefined ) {
+ ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
+ }
+ }
+
+ // Check if we're dealing with a known content-type
+ if ( ct ) {
+ for ( type in contents ) {
+ if ( contents[ type ] && contents[ type ].test( ct ) ) {
+ dataTypes.unshift( type );
+ break;
+ }
+ }
+ }
+
+ // Check to see if we have a response for the expected dataType
+ if ( dataTypes[ 0 ] in responses ) {
+ finalDataType = dataTypes[ 0 ];
+ } else {
+ // Try convertible dataTypes
+ for ( type in responses ) {
+ if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
+ finalDataType = type;
+ break;
+ }
+ if ( !firstDataType ) {
+ firstDataType = type;
+ }
+ }
+ // Or just use first one
+ finalDataType = finalDataType || firstDataType;
+ }
+
+ // If we found a dataType
+ // We add the dataType to the list if needed
+ // and return the corresponding response
+ if ( finalDataType ) {
+ if ( finalDataType !== dataTypes[ 0 ] ) {
+ dataTypes.unshift( finalDataType );
+ }
+ return responses[ finalDataType ];
+ }
+}
+
+/* Chain conversions given the request and the original response
+ * Also sets the responseXXX fields on the jqXHR instance
+ */
+function ajaxConvert( s, response, jqXHR, isSuccess ) {
+ var conv2, current, conv, tmp, prev,
+ converters = {},
+ // Work with a copy of dataTypes in case we need to modify it for conversion
+ dataTypes = s.dataTypes.slice();
+
+ // Create converters map with lowercased keys
+ if ( dataTypes[ 1 ] ) {
+ for ( conv in s.converters ) {
+ converters[ conv.toLowerCase() ] = s.converters[ conv ];
+ }
+ }
+
+ current = dataTypes.shift();
+
+ // Convert to each sequential dataType
+ while ( current ) {
+
+ if ( s.responseFields[ current ] ) {
+ jqXHR[ s.responseFields[ current ] ] = response;
+ }
+
+ // Apply the dataFilter if provided
+ if ( !prev && isSuccess && s.dataFilter ) {
+ response = s.dataFilter( response, s.dataType );
+ }
+
+ prev = current;
+ current = dataTypes.shift();
+
+ if ( current ) {
+
+ // There's only work to do if current dataType is non-auto
+ if ( current === "*" ) {
+
+ current = prev;
+
+ // Convert response if prev dataType is non-auto and differs from current
+ } else if ( prev !== "*" && prev !== current ) {
+
+ // Seek a direct converter
+ conv = converters[ prev + " " + current ] || converters[ "* " + current ];
+
+ // If none found, seek a pair
+ if ( !conv ) {
+ for ( conv2 in converters ) {
+
+ // If conv2 outputs current
+ tmp = conv2.split( " " );
+ if ( tmp[ 1 ] === current ) {
+
+ // If prev can be converted to accepted input
+ conv = converters[ prev + " " + tmp[ 0 ] ] ||
+ converters[ "* " + tmp[ 0 ] ];
+ if ( conv ) {
+ // Condense equivalence converters
+ if ( conv === true ) {
+ conv = converters[ conv2 ];
+
+ // Otherwise, insert the intermediate dataType
+ } else if ( converters[ conv2 ] !== true ) {
+ current = tmp[ 0 ];
+ dataTypes.unshift( tmp[ 1 ] );
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ // Apply converter (if not an equivalence)
+ if ( conv !== true ) {
+
+ // Unless errors are allowed to bubble, catch and return them
+ if ( conv && s[ "throws" ] ) {
+ response = conv( response );
+ } else {
+ try {
+ response = conv( response );
+ } catch ( e ) {
+ return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return { state: "success", data: response };
+}
+// Install script dataType
+jQuery.ajaxSetup({
+ accepts: {
+ script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
+ },
+ contents: {
+ script: /(?:java|ecma)script/
+ },
+ converters: {
+ "text script": function( text ) {
+ jQuery.globalEval( text );
+ return text;
+ }
+ }
+});
+
+// Handle cache's special case and global
+jQuery.ajaxPrefilter( "script", function( s ) {
+ if ( s.cache === undefined ) {
+ s.cache = false;
+ }
+ if ( s.crossDomain ) {
+ s.type = "GET";
+ s.global = false;
+ }
+});
+
+// Bind script tag hack transport
+jQuery.ajaxTransport( "script", function(s) {
+
+ // This transport only deals with cross domain requests
+ if ( s.crossDomain ) {
+
+ var script,
+ head = document.head || jQuery("head")[0] || document.documentElement;
+
+ return {
+
+ send: function( _, callback ) {
+
+ script = document.createElement("script");
+
+ script.async = true;
+
+ if ( s.scriptCharset ) {
+ script.charset = s.scriptCharset;
+ }
+
+ script.src = s.url;
+
+ // Attach handlers for all browsers
+ script.onload = script.onreadystatechange = function( _, isAbort ) {
+
+ if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
+
+ // Handle memory leak in IE
+ script.onload = script.onreadystatechange = null;
+
+ // Remove the script
+ if ( script.parentNode ) {
+ script.parentNode.removeChild( script );
+ }
+
+ // Dereference the script
+ script = null;
+
+ // Callback if not abort
+ if ( !isAbort ) {
+ callback( 200, "success" );
+ }
+ }
+ };
+
+ // Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending
+ // Use native DOM manipulation to avoid our domManip AJAX trickery
+ head.insertBefore( script, head.firstChild );
+ },
+
+ abort: function() {
+ if ( script ) {
+ script.onload( undefined, true );
+ }
+ }
+ };
+ }
+});
+var oldCallbacks = [],
+ rjsonp = /(=)\?(?=&|$)|\?\?/;
+
+// Default jsonp settings
+jQuery.ajaxSetup({
+ jsonp: "callback",
+ jsonpCallback: function() {
+ var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( ajax_nonce++ ) );
+ this[ callback ] = true;
+ return callback;
+ }
+});
+
+// Detect, normalize options and install callbacks for jsonp requests
+jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
+
+ var callbackName, overwritten, responseContainer,
+ jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
+ "url" :
+ typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
+ );
+
+ // Handle iff the expected data type is "jsonp" or we have a parameter to set
+ if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
+
+ // Get callback name, remembering preexisting value associated with it
+ callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
+ s.jsonpCallback() :
+ s.jsonpCallback;
+
+ // Insert callback into url or form data
+ if ( jsonProp ) {
+ s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
+ } else if ( s.jsonp !== false ) {
+ s.url += ( ajax_rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
+ }
+
+ // Use data converter to retrieve json after script execution
+ s.converters["script json"] = function() {
+ if ( !responseContainer ) {
+ jQuery.error( callbackName + " was not called" );
+ }
+ return responseContainer[ 0 ];
+ };
+
+ // force json dataType
+ s.dataTypes[ 0 ] = "json";
+
+ // Install callback
+ overwritten = window[ callbackName ];
+ window[ callbackName ] = function() {
+ responseContainer = arguments;
+ };
+
+ // Clean-up function (fires after converters)
+ jqXHR.always(function() {
+ // Restore preexisting value
+ window[ callbackName ] = overwritten;
+
+ // Save back as free
+ if ( s[ callbackName ] ) {
+ // make sure that re-using the options doesn't screw things around
+ s.jsonpCallback = originalSettings.jsonpCallback;
+
+ // save the callback name for future use
+ oldCallbacks.push( callbackName );
+ }
+
+ // Call if it was a function and we have a response
+ if ( responseContainer && jQuery.isFunction( overwritten ) ) {
+ overwritten( responseContainer[ 0 ] );
+ }
+
+ responseContainer = overwritten = undefined;
+ });
+
+ // Delegate to script
+ return "script";
+ }
+});
+var xhrCallbacks, xhrSupported,
+ xhrId = 0,
+ // #5280: Internet Explorer will keep connections alive if we don't abort on unload
+ xhrOnUnloadAbort = window.ActiveXObject && function() {
+ // Abort all pending requests
+ var key;
+ for ( key in xhrCallbacks ) {
+ xhrCallbacks[ key ]( undefined, true );
+ }
+ };
+
+// Functions to create xhrs
+function createStandardXHR() {
+ try {
+ return new window.XMLHttpRequest();
+ } catch( e ) {}
+}
+
+function createActiveXHR() {
+ try {
+ return new window.ActiveXObject("Microsoft.XMLHTTP");
+ } catch( e ) {}
+}
+
+// Create the request object
+// (This is still attached to ajaxSettings for backward compatibility)
+jQuery.ajaxSettings.xhr = window.ActiveXObject ?
+ /* Microsoft failed to properly
+ * implement the XMLHttpRequest in IE7 (can't request local files),
+ * so we use the ActiveXObject when it is available
+ * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
+ * we need a fallback.
+ */
+ function() {
+ return !this.isLocal && createStandardXHR() || createActiveXHR();
+ } :
+ // For all other browsers, use the standard XMLHttpRequest object
+ createStandardXHR;
+
+// Determine support properties
+xhrSupported = jQuery.ajaxSettings.xhr();
+jQuery.support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
+xhrSupported = jQuery.support.ajax = !!xhrSupported;
+
+// Create transport if the browser can provide an xhr
+if ( xhrSupported ) {
+
+ jQuery.ajaxTransport(function( s ) {
+ // Cross domain only allowed if supported through XMLHttpRequest
+ if ( !s.crossDomain || jQuery.support.cors ) {
+
+ var callback;
+
+ return {
+ send: function( headers, complete ) {
+
+ // Get a new xhr
+ var handle, i,
+ xhr = s.xhr();
+
+ // Open the socket
+ // Passing null username, generates a login popup on Opera (#2865)
+ if ( s.username ) {
+ xhr.open( s.type, s.url, s.async, s.username, s.password );
+ } else {
+ xhr.open( s.type, s.url, s.async );
+ }
+
+ // Apply custom fields if provided
+ if ( s.xhrFields ) {
+ for ( i in s.xhrFields ) {
+ xhr[ i ] = s.xhrFields[ i ];
+ }
+ }
+
+ // Override mime type if needed
+ if ( s.mimeType && xhr.overrideMimeType ) {
+ xhr.overrideMimeType( s.mimeType );
+ }
+
+ // X-Requested-With header
+ // For cross-domain requests, seeing as conditions for a preflight are
+ // akin to a jigsaw puzzle, we simply never set it to be sure.
+ // (it can always be set on a per-request basis or even using ajaxSetup)
+ // For same-domain requests, won't change header if already provided.
+ if ( !s.crossDomain && !headers["X-Requested-With"] ) {
+ headers["X-Requested-With"] = "XMLHttpRequest";
+ }
+
+ // Need an extra try/catch for cross domain requests in Firefox 3
+ try {
+ for ( i in headers ) {
+ xhr.setRequestHeader( i, headers[ i ] );
+ }
+ } catch( err ) {}
+
+ // Do send the request
+ // This may raise an exception which is actually
+ // handled in jQuery.ajax (so no try/catch here)
+ xhr.send( ( s.hasContent && s.data ) || null );
+
+ // Listener
+ callback = function( _, isAbort ) {
+ var status, responseHeaders, statusText, responses;
+
+ // Firefox throws exceptions when accessing properties
+ // of an xhr when a network error occurred
+ // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
+ try {
+
+ // Was never called and is aborted or complete
+ if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
+
+ // Only called once
+ callback = undefined;
+
+ // Do not keep as active anymore
+ if ( handle ) {
+ xhr.onreadystatechange = jQuery.noop;
+ if ( xhrOnUnloadAbort ) {
+ delete xhrCallbacks[ handle ];
+ }
+ }
+
+ // If it's an abort
+ if ( isAbort ) {
+ // Abort it manually if needed
+ if ( xhr.readyState !== 4 ) {
+ xhr.abort();
+ }
+ } else {
+ responses = {};
+ status = xhr.status;
+ responseHeaders = xhr.getAllResponseHeaders();
+
+ // When requesting binary data, IE6-9 will throw an exception
+ // on any attempt to access responseText (#11426)
+ if ( typeof xhr.responseText === "string" ) {
+ responses.text = xhr.responseText;
+ }
+
+ // Firefox throws an exception when accessing
+ // statusText for faulty cross-domain requests
+ try {
+ statusText = xhr.statusText;
+ } catch( e ) {
+ // We normalize with Webkit giving an empty statusText
+ statusText = "";
+ }
+
+ // Filter status for non standard behaviors
+
+ // If the request is local and we have data: assume a success
+ // (success with no data won't get notified, that's the best we
+ // can do given current implementations)
+ if ( !status && s.isLocal && !s.crossDomain ) {
+ status = responses.text ? 200 : 404;
+ // IE - #1450: sometimes returns 1223 when it should be 204
+ } else if ( status === 1223 ) {
+ status = 204;
+ }
+ }
+ }
+ } catch( firefoxAccessException ) {
+ if ( !isAbort ) {
+ complete( -1, firefoxAccessException );
+ }
+ }
+
+ // Call complete if needed
+ if ( responses ) {
+ complete( status, statusText, responses, responseHeaders );
+ }
+ };
+
+ if ( !s.async ) {
+ // if we're in sync mode we fire the callback
+ callback();
+ } else if ( xhr.readyState === 4 ) {
+ // (IE6 & IE7) if it's in cache and has been
+ // retrieved directly we need to fire the callback
+ setTimeout( callback );
+ } else {
+ handle = ++xhrId;
+ if ( xhrOnUnloadAbort ) {
+ // Create the active xhrs callbacks list if needed
+ // and attach the unload handler
+ if ( !xhrCallbacks ) {
+ xhrCallbacks = {};
+ jQuery( window ).unload( xhrOnUnloadAbort );
+ }
+ // Add to list of active xhrs callbacks
+ xhrCallbacks[ handle ] = callback;
+ }
+ xhr.onreadystatechange = callback;
+ }
+ },
+
+ abort: function() {
+ if ( callback ) {
+ callback( undefined, true );
+ }
+ }
+ };
+ }
+ });
+}
+var fxNow, timerId,
+ rfxtypes = /^(?:toggle|show|hide)$/,
+ rfxnum = new RegExp( "^(?:([+-])=|)(" + core_pnum + ")([a-z%]*)$", "i" ),
+ rrun = /queueHooks$/,
+ animationPrefilters = [ defaultPrefilter ],
+ tweeners = {
+ "*": [function( prop, value ) {
+ var tween = this.createTween( prop, value ),
+ target = tween.cur(),
+ parts = rfxnum.exec( value ),
+ unit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
+
+ // Starting value computation is required for potential unit mismatches
+ start = ( jQuery.cssNumber[ prop ] || unit !== "px" && +target ) &&
+ rfxnum.exec( jQuery.css( tween.elem, prop ) ),
+ scale = 1,
+ maxIterations = 20;
+
+ if ( start && start[ 3 ] !== unit ) {
+ // Trust units reported by jQuery.css
+ unit = unit || start[ 3 ];
+
+ // Make sure we update the tween properties later on
+ parts = parts || [];
+
+ // Iteratively approximate from a nonzero starting point
+ start = +target || 1;
+
+ do {
+ // If previous iteration zeroed out, double until we get *something*
+ // Use a string for doubling factor so we don't accidentally see scale as unchanged below
+ scale = scale || ".5";
+
+ // Adjust and apply
+ start = start / scale;
+ jQuery.style( tween.elem, prop, start + unit );
+
+ // Update scale, tolerating zero or NaN from tween.cur()
+ // And breaking the loop if scale is unchanged or perfect, or if we've just had enough
+ } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
+ }
+
+ // Update tween properties
+ if ( parts ) {
+ start = tween.start = +start || +target || 0;
+ tween.unit = unit;
+ // If a +=/-= token was provided, we're doing a relative animation
+ tween.end = parts[ 1 ] ?
+ start + ( parts[ 1 ] + 1 ) * parts[ 2 ] :
+ +parts[ 2 ];
+ }
+
+ return tween;
+ }]
+ };
+
+// Animations created synchronously will run synchronously
+function createFxNow() {
+ setTimeout(function() {
+ fxNow = undefined;
+ });
+ return ( fxNow = jQuery.now() );
+}
+
+function createTween( value, prop, animation ) {
+ var tween,
+ collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
+ index = 0,
+ length = collection.length;
+ for ( ; index < length; index++ ) {
+ if ( (tween = collection[ index ].call( animation, prop, value )) ) {
+
+ // we're done with this property
+ return tween;
+ }
+ }
+}
+
+function Animation( elem, properties, options ) {
+ var result,
+ stopped,
+ index = 0,
+ length = animationPrefilters.length,
+ deferred = jQuery.Deferred().always( function() {
+ // don't match elem in the :animated selector
+ delete tick.elem;
+ }),
+ tick = function() {
+ if ( stopped ) {
+ return false;
+ }
+ var currentTime = fxNow || createFxNow(),
+ remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
+ // archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
+ temp = remaining / animation.duration || 0,
+ percent = 1 - temp,
+ index = 0,
+ length = animation.tweens.length;
+
+ for ( ; index < length ; index++ ) {
+ animation.tweens[ index ].run( percent );
+ }
+
+ deferred.notifyWith( elem, [ animation, percent, remaining ]);
+
+ if ( percent < 1 && length ) {
+ return remaining;
+ } else {
+ deferred.resolveWith( elem, [ animation ] );
+ return false;
+ }
+ },
+ animation = deferred.promise({
+ elem: elem,
+ props: jQuery.extend( {}, properties ),
+ opts: jQuery.extend( true, { specialEasing: {} }, options ),
+ originalProperties: properties,
+ originalOptions: options,
+ startTime: fxNow || createFxNow(),
+ duration: options.duration,
+ tweens: [],
+ createTween: function( prop, end ) {
+ var tween = jQuery.Tween( elem, animation.opts, prop, end,
+ animation.opts.specialEasing[ prop ] || animation.opts.easing );
+ animation.tweens.push( tween );
+ return tween;
+ },
+ stop: function( gotoEnd ) {
+ var index = 0,
+ // if we are going to the end, we want to run all the tweens
+ // otherwise we skip this part
+ length = gotoEnd ? animation.tweens.length : 0;
+ if ( stopped ) {
+ return this;
+ }
+ stopped = true;
+ for ( ; index < length ; index++ ) {
+ animation.tweens[ index ].run( 1 );
+ }
+
+ // resolve when we played the last frame
+ // otherwise, reject
+ if ( gotoEnd ) {
+ deferred.resolveWith( elem, [ animation, gotoEnd ] );
+ } else {
+ deferred.rejectWith( elem, [ animation, gotoEnd ] );
+ }
+ return this;
+ }
+ }),
+ props = animation.props;
+
+ propFilter( props, animation.opts.specialEasing );
+
+ for ( ; index < length ; index++ ) {
+ result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
+ if ( result ) {
+ return result;
+ }
+ }
+
+ jQuery.map( props, createTween, animation );
+
+ if ( jQuery.isFunction( animation.opts.start ) ) {
+ animation.opts.start.call( elem, animation );
+ }
+
+ jQuery.fx.timer(
+ jQuery.extend( tick, {
+ elem: elem,
+ anim: animation,
+ queue: animation.opts.queue
+ })
+ );
+
+ // attach callbacks from options
+ return animation.progress( animation.opts.progress )
+ .done( animation.opts.done, animation.opts.complete )
+ .fail( animation.opts.fail )
+ .always( animation.opts.always );
+}
+
+function propFilter( props, specialEasing ) {
+ var index, name, easing, value, hooks;
+
+ // camelCase, specialEasing and expand cssHook pass
+ for ( index in props ) {
+ name = jQuery.camelCase( index );
+ easing = specialEasing[ name ];
+ value = props[ index ];
+ if ( jQuery.isArray( value ) ) {
+ easing = value[ 1 ];
+ value = props[ index ] = value[ 0 ];
+ }
+
+ if ( index !== name ) {
+ props[ name ] = value;
+ delete props[ index ];
+ }
+
+ hooks = jQuery.cssHooks[ name ];
+ if ( hooks && "expand" in hooks ) {
+ value = hooks.expand( value );
+ delete props[ name ];
+
+ // not quite $.extend, this wont overwrite keys already present.
+ // also - reusing 'index' from above because we have the correct "name"
+ for ( index in value ) {
+ if ( !( index in props ) ) {
+ props[ index ] = value[ index ];
+ specialEasing[ index ] = easing;
+ }
+ }
+ } else {
+ specialEasing[ name ] = easing;
+ }
+ }
+}
+
+jQuery.Animation = jQuery.extend( Animation, {
+
+ tweener: function( props, callback ) {
+ if ( jQuery.isFunction( props ) ) {
+ callback = props;
+ props = [ "*" ];
+ } else {
+ props = props.split(" ");
+ }
+
+ var prop,
+ index = 0,
+ length = props.length;
+
+ for ( ; index < length ; index++ ) {
+ prop = props[ index ];
+ tweeners[ prop ] = tweeners[ prop ] || [];
+ tweeners[ prop ].unshift( callback );
+ }
+ },
+
+ prefilter: function( callback, prepend ) {
+ if ( prepend ) {
+ animationPrefilters.unshift( callback );
+ } else {
+ animationPrefilters.push( callback );
+ }
+ }
+});
+
+function defaultPrefilter( elem, props, opts ) {
+ /* jshint validthis: true */
+ var prop, value, toggle, tween, hooks, oldfire,
+ anim = this,
+ orig = {},
+ style = elem.style,
+ hidden = elem.nodeType && isHidden( elem ),
+ dataShow = jQuery._data( elem, "fxshow" );
+
+ // handle queue: false promises
+ if ( !opts.queue ) {
+ hooks = jQuery._queueHooks( elem, "fx" );
+ if ( hooks.unqueued == null ) {
+ hooks.unqueued = 0;
+ oldfire = hooks.empty.fire;
+ hooks.empty.fire = function() {
+ if ( !hooks.unqueued ) {
+ oldfire();
+ }
+ };
+ }
+ hooks.unqueued++;
+
+ anim.always(function() {
+ // doing this makes sure that the complete handler will be called
+ // before this completes
+ anim.always(function() {
+ hooks.unqueued--;
+ if ( !jQuery.queue( elem, "fx" ).length ) {
+ hooks.empty.fire();
+ }
+ });
+ });
+ }
+
+ // height/width overflow pass
+ if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
+ // Make sure that nothing sneaks out
+ // Record all 3 overflow attributes because IE does not
+ // change the overflow attribute when overflowX and
+ // overflowY are set to the same value
+ opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
+
+ // Set display property to inline-block for height/width
+ // animations on inline elements that are having width/height animated
+ if ( jQuery.css( elem, "display" ) === "inline" &&
+ jQuery.css( elem, "float" ) === "none" ) {
+
+ // inline-level elements accept inline-block;
+ // block-level elements need to be inline with layout
+ if ( !jQuery.support.inlineBlockNeedsLayout || css_defaultDisplay( elem.nodeName ) === "inline" ) {
+ style.display = "inline-block";
+
+ } else {
+ style.zoom = 1;
+ }
+ }
+ }
+
+ if ( opts.overflow ) {
+ style.overflow = "hidden";
+ if ( !jQuery.support.shrinkWrapBlocks ) {
+ anim.always(function() {
+ style.overflow = opts.overflow[ 0 ];
+ style.overflowX = opts.overflow[ 1 ];
+ style.overflowY = opts.overflow[ 2 ];
+ });
+ }
+ }
+
+
+ // show/hide pass
+ for ( prop in props ) {
+ value = props[ prop ];
+ if ( rfxtypes.exec( value ) ) {
+ delete props[ prop ];
+ toggle = toggle || value === "toggle";
+ if ( value === ( hidden ? "hide" : "show" ) ) {
+ continue;
+ }
+ orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
+ }
+ }
+
+ if ( !jQuery.isEmptyObject( orig ) ) {
+ if ( dataShow ) {
+ if ( "hidden" in dataShow ) {
+ hidden = dataShow.hidden;
+ }
+ } else {
+ dataShow = jQuery._data( elem, "fxshow", {} );
+ }
+
+ // store state if its toggle - enables .stop().toggle() to "reverse"
+ if ( toggle ) {
+ dataShow.hidden = !hidden;
+ }
+ if ( hidden ) {
+ jQuery( elem ).show();
+ } else {
+ anim.done(function() {
+ jQuery( elem ).hide();
+ });
+ }
+ anim.done(function() {
+ var prop;
+ jQuery._removeData( elem, "fxshow" );
+ for ( prop in orig ) {
+ jQuery.style( elem, prop, orig[ prop ] );
+ }
+ });
+ for ( prop in orig ) {
+ tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
+
+ if ( !( prop in dataShow ) ) {
+ dataShow[ prop ] = tween.start;
+ if ( hidden ) {
+ tween.end = tween.start;
+ tween.start = prop === "width" || prop === "height" ? 1 : 0;
+ }
+ }
+ }
+ }
+}
+
+function Tween( elem, options, prop, end, easing ) {
+ return new Tween.prototype.init( elem, options, prop, end, easing );
+}
+jQuery.Tween = Tween;
+
+Tween.prototype = {
+ constructor: Tween,
+ init: function( elem, options, prop, end, easing, unit ) {
+ this.elem = elem;
+ this.prop = prop;
+ this.easing = easing || "swing";
+ this.options = options;
+ this.start = this.now = this.cur();
+ this.end = end;
+ this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
+ },
+ cur: function() {
+ var hooks = Tween.propHooks[ this.prop ];
+
+ return hooks && hooks.get ?
+ hooks.get( this ) :
+ Tween.propHooks._default.get( this );
+ },
+ run: function( percent ) {
+ var eased,
+ hooks = Tween.propHooks[ this.prop ];
+
+ if ( this.options.duration ) {
+ this.pos = eased = jQuery.easing[ this.easing ](
+ percent, this.options.duration * percent, 0, 1, this.options.duration
+ );
+ } else {
+ this.pos = eased = percent;
+ }
+ this.now = ( this.end - this.start ) * eased + this.start;
+
+ if ( this.options.step ) {
+ this.options.step.call( this.elem, this.now, this );
+ }
+
+ if ( hooks && hooks.set ) {
+ hooks.set( this );
+ } else {
+ Tween.propHooks._default.set( this );
+ }
+ return this;
+ }
+};
+
+Tween.prototype.init.prototype = Tween.prototype;
+
+Tween.propHooks = {
+ _default: {
+ get: function( tween ) {
+ var result;
+
+ if ( tween.elem[ tween.prop ] != null &&
+ (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
+ return tween.elem[ tween.prop ];
+ }
+
+ // passing an empty string as a 3rd parameter to .css will automatically
+ // attempt a parseFloat and fallback to a string if the parse fails
+ // so, simple values such as "10px" are parsed to Float.
+ // complex values such as "rotate(1rad)" are returned as is.
+ result = jQuery.css( tween.elem, tween.prop, "" );
+ // Empty strings, null, undefined and "auto" are converted to 0.
+ return !result || result === "auto" ? 0 : result;
+ },
+ set: function( tween ) {
+ // use step hook for back compat - use cssHook if its there - use .style if its
+ // available and use plain properties where available
+ if ( jQuery.fx.step[ tween.prop ] ) {
+ jQuery.fx.step[ tween.prop ]( tween );
+ } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
+ jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
+ } else {
+ tween.elem[ tween.prop ] = tween.now;
+ }
+ }
+ }
+};
+
+// Support: IE <=9
+// Panic based approach to setting things on disconnected nodes
+
+Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
+ set: function( tween ) {
+ if ( tween.elem.nodeType && tween.elem.parentNode ) {
+ tween.elem[ tween.prop ] = tween.now;
+ }
+ }
+};
+
+jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
+ var cssFn = jQuery.fn[ name ];
+ jQuery.fn[ name ] = function( speed, easing, callback ) {
+ return speed == null || typeof speed === "boolean" ?
+ cssFn.apply( this, arguments ) :
+ this.animate( genFx( name, true ), speed, easing, callback );
+ };
+});
+
+jQuery.fn.extend({
+ fadeTo: function( speed, to, easing, callback ) {
+
+ // show any hidden elements after setting opacity to 0
+ return this.filter( isHidden ).css( "opacity", 0 ).show()
+
+ // animate to the value specified
+ .end().animate({ opacity: to }, speed, easing, callback );
+ },
+ animate: function( prop, speed, easing, callback ) {
+ var empty = jQuery.isEmptyObject( prop ),
+ optall = jQuery.speed( speed, easing, callback ),
+ doAnimation = function() {
+ // Operate on a copy of prop so per-property easing won't be lost
+ var anim = Animation( this, jQuery.extend( {}, prop ), optall );
+
+ // Empty animations, or finishing resolves immediately
+ if ( empty || jQuery._data( this, "finish" ) ) {
+ anim.stop( true );
+ }
+ };
+ doAnimation.finish = doAnimation;
+
+ return empty || optall.queue === false ?
+ this.each( doAnimation ) :
+ this.queue( optall.queue, doAnimation );
+ },
+ stop: function( type, clearQueue, gotoEnd ) {
+ var stopQueue = function( hooks ) {
+ var stop = hooks.stop;
+ delete hooks.stop;
+ stop( gotoEnd );
+ };
+
+ if ( typeof type !== "string" ) {
+ gotoEnd = clearQueue;
+ clearQueue = type;
+ type = undefined;
+ }
+ if ( clearQueue && type !== false ) {
+ this.queue( type || "fx", [] );
+ }
+
+ return this.each(function() {
+ var dequeue = true,
+ index = type != null && type + "queueHooks",
+ timers = jQuery.timers,
+ data = jQuery._data( this );
+
+ if ( index ) {
+ if ( data[ index ] && data[ index ].stop ) {
+ stopQueue( data[ index ] );
+ }
+ } else {
+ for ( index in data ) {
+ if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
+ stopQueue( data[ index ] );
+ }
+ }
+ }
+
+ for ( index = timers.length; index--; ) {
+ if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
+ timers[ index ].anim.stop( gotoEnd );
+ dequeue = false;
+ timers.splice( index, 1 );
+ }
+ }
+
+ // start the next in the queue if the last step wasn't forced
+ // timers currently will call their complete callbacks, which will dequeue
+ // but only if they were gotoEnd
+ if ( dequeue || !gotoEnd ) {
+ jQuery.dequeue( this, type );
+ }
+ });
+ },
+ finish: function( type ) {
+ if ( type !== false ) {
+ type = type || "fx";
+ }
+ return this.each(function() {
+ var index,
+ data = jQuery._data( this ),
+ queue = data[ type + "queue" ],
+ hooks = data[ type + "queueHooks" ],
+ timers = jQuery.timers,
+ length = queue ? queue.length : 0;
+
+ // enable finishing flag on private data
+ data.finish = true;
+
+ // empty the queue first
+ jQuery.queue( this, type, [] );
+
+ if ( hooks && hooks.stop ) {
+ hooks.stop.call( this, true );
+ }
+
+ // look for any active animations, and finish them
+ for ( index = timers.length; index--; ) {
+ if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
+ timers[ index ].anim.stop( true );
+ timers.splice( index, 1 );
+ }
+ }
+
+ // look for any animations in the old queue and finish them
+ for ( index = 0; index < length; index++ ) {
+ if ( queue[ index ] && queue[ index ].finish ) {
+ queue[ index ].finish.call( this );
+ }
+ }
+
+ // turn off finishing flag
+ delete data.finish;
+ });
+ }
+});
+
+// Generate parameters to create a standard animation
+function genFx( type, includeWidth ) {
+ var which,
+ attrs = { height: type },
+ i = 0;
+
+ // if we include width, step value is 1 to do all cssExpand values,
+ // if we don't include width, step value is 2 to skip over Left and Right
+ includeWidth = includeWidth? 1 : 0;
+ for( ; i < 4 ; i += 2 - includeWidth ) {
+ which = cssExpand[ i ];
+ attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
+ }
+
+ if ( includeWidth ) {
+ attrs.opacity = attrs.width = type;
+ }
+
+ return attrs;
+}
+
+// Generate shortcuts for custom animations
+jQuery.each({
+ slideDown: genFx("show"),
+ slideUp: genFx("hide"),
+ slideToggle: genFx("toggle"),
+ fadeIn: { opacity: "show" },
+ fadeOut: { opacity: "hide" },
+ fadeToggle: { opacity: "toggle" }
+}, function( name, props ) {
+ jQuery.fn[ name ] = function( speed, easing, callback ) {
+ return this.animate( props, speed, easing, callback );
+ };
+});
+
+jQuery.speed = function( speed, easing, fn ) {
+ var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
+ complete: fn || !fn && easing ||
+ jQuery.isFunction( speed ) && speed,
+ duration: speed,
+ easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
+ };
+
+ opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
+ opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
+
+ // normalize opt.queue - true/undefined/null -> "fx"
+ if ( opt.queue == null || opt.queue === true ) {
+ opt.queue = "fx";
+ }
+
+ // Queueing
+ opt.old = opt.complete;
+
+ opt.complete = function() {
+ if ( jQuery.isFunction( opt.old ) ) {
+ opt.old.call( this );
+ }
+
+ if ( opt.queue ) {
+ jQuery.dequeue( this, opt.queue );
+ }
+ };
+
+ return opt;
+};
+
+jQuery.easing = {
+ linear: function( p ) {
+ return p;
+ },
+ swing: function( p ) {
+ return 0.5 - Math.cos( p*Math.PI ) / 2;
+ }
+};
+
+jQuery.timers = [];
+jQuery.fx = Tween.prototype.init;
+jQuery.fx.tick = function() {
+ var timer,
+ timers = jQuery.timers,
+ i = 0;
+
+ fxNow = jQuery.now();
+
+ for ( ; i < timers.length; i++ ) {
+ timer = timers[ i ];
+ // Checks the timer has not already been removed
+ if ( !timer() && timers[ i ] === timer ) {
+ timers.splice( i--, 1 );
+ }
+ }
+
+ if ( !timers.length ) {
+ jQuery.fx.stop();
+ }
+ fxNow = undefined;
+};
+
+jQuery.fx.timer = function( timer ) {
+ if ( timer() && jQuery.timers.push( timer ) ) {
+ jQuery.fx.start();
+ }
+};
+
+jQuery.fx.interval = 13;
+
+jQuery.fx.start = function() {
+ if ( !timerId ) {
+ timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
+ }
+};
+
+jQuery.fx.stop = function() {
+ clearInterval( timerId );
+ timerId = null;
+};
+
+jQuery.fx.speeds = {
+ slow: 600,
+ fast: 200,
+ // Default speed
+ _default: 400
+};
+
+// Back Compat <1.8 extension point
+jQuery.fx.step = {};
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+ jQuery.expr.filters.animated = function( elem ) {
+ return jQuery.grep(jQuery.timers, function( fn ) {
+ return elem === fn.elem;
+ }).length;
+ };
+}
+jQuery.fn.offset = function( options ) {
+ if ( arguments.length ) {
+ return options === undefined ?
+ this :
+ this.each(function( i ) {
+ jQuery.offset.setOffset( this, options, i );
+ });
+ }
+
+ var docElem, win,
+ box = { top: 0, left: 0 },
+ elem = this[ 0 ],
+ doc = elem && elem.ownerDocument;
+
+ if ( !doc ) {
+ return;
+ }
+
+ docElem = doc.documentElement;
+
+ // Make sure it's not a disconnected DOM node
+ if ( !jQuery.contains( docElem, elem ) ) {
+ return box;
+ }
+
+ // If we don't have gBCR, just use 0,0 rather than error
+ // BlackBerry 5, iOS 3 (original iPhone)
+ if ( typeof elem.getBoundingClientRect !== core_strundefined ) {
+ box = elem.getBoundingClientRect();
+ }
+ win = getWindow( doc );
+ return {
+ top: box.top + ( win.pageYOffset || docElem.scrollTop ) - ( docElem.clientTop || 0 ),
+ left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
+ };
+};
+
+jQuery.offset = {
+
+ setOffset: function( elem, options, i ) {
+ var position = jQuery.css( elem, "position" );
+
+ // set position first, in-case top/left are set even on static elem
+ if ( position === "static" ) {
+ elem.style.position = "relative";
+ }
+
+ var curElem = jQuery( elem ),
+ curOffset = curElem.offset(),
+ curCSSTop = jQuery.css( elem, "top" ),
+ curCSSLeft = jQuery.css( elem, "left" ),
+ calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1,
+ props = {}, curPosition = {}, curTop, curLeft;
+
+ // need to be able to calculate position if either top or left is auto and position is either absolute or fixed
+ if ( calculatePosition ) {
+ curPosition = curElem.position();
+ curTop = curPosition.top;
+ curLeft = curPosition.left;
+ } else {
+ curTop = parseFloat( curCSSTop ) || 0;
+ curLeft = parseFloat( curCSSLeft ) || 0;
+ }
+
+ if ( jQuery.isFunction( options ) ) {
+ options = options.call( elem, i, curOffset );
+ }
+
+ if ( options.top != null ) {
+ props.top = ( options.top - curOffset.top ) + curTop;
+ }
+ if ( options.left != null ) {
+ props.left = ( options.left - curOffset.left ) + curLeft;
+ }
+
+ if ( "using" in options ) {
+ options.using.call( elem, props );
+ } else {
+ curElem.css( props );
+ }
+ }
+};
+
+
+jQuery.fn.extend({
+
+ position: function() {
+ if ( !this[ 0 ] ) {
+ return;
+ }
+
+ var offsetParent, offset,
+ parentOffset = { top: 0, left: 0 },
+ elem = this[ 0 ];
+
+ // fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent
+ if ( jQuery.css( elem, "position" ) === "fixed" ) {
+ // we assume that getBoundingClientRect is available when computed position is fixed
+ offset = elem.getBoundingClientRect();
+ } else {
+ // Get *real* offsetParent
+ offsetParent = this.offsetParent();
+
+ // Get correct offsets
+ offset = this.offset();
+ if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
+ parentOffset = offsetParent.offset();
+ }
+
+ // Add offsetParent borders
+ parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
+ parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
+ }
+
+ // Subtract parent offsets and element margins
+ // note: when an element has margin: auto the offsetLeft and marginLeft
+ // are the same in Safari causing offset.left to incorrectly be 0
+ return {
+ top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
+ left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true)
+ };
+ },
+
+ offsetParent: function() {
+ return this.map(function() {
+ var offsetParent = this.offsetParent || docElem;
+ while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position") === "static" ) ) {
+ offsetParent = offsetParent.offsetParent;
+ }
+ return offsetParent || docElem;
+ });
+ }
+});
+
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( {scrollLeft: "pageXOffset", scrollTop: "pageYOffset"}, function( method, prop ) {
+ var top = /Y/.test( prop );
+
+ jQuery.fn[ method ] = function( val ) {
+ return jQuery.access( this, function( elem, method, val ) {
+ var win = getWindow( elem );
+
+ if ( val === undefined ) {
+ return win ? (prop in win) ? win[ prop ] :
+ win.document.documentElement[ method ] :
+ elem[ method ];
+ }
+
+ if ( win ) {
+ win.scrollTo(
+ !top ? val : jQuery( win ).scrollLeft(),
+ top ? val : jQuery( win ).scrollTop()
+ );
+
+ } else {
+ elem[ method ] = val;
+ }
+ }, method, val, arguments.length, null );
+ };
+});
+
+function getWindow( elem ) {
+ return jQuery.isWindow( elem ) ?
+ elem :
+ elem.nodeType === 9 ?
+ elem.defaultView || elem.parentWindow :
+ false;
+}
+// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
+jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
+ jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
+ // margin is only for outerHeight, outerWidth
+ jQuery.fn[ funcName ] = function( margin, value ) {
+ var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
+ extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
+
+ return jQuery.access( this, function( elem, type, value ) {
+ var doc;
+
+ if ( jQuery.isWindow( elem ) ) {
+ // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
+ // isn't a whole lot we can do. See pull request at this URL for discussion:
+ // https://github.com/jquery/jquery/pull/764
+ return elem.document.documentElement[ "client" + name ];
+ }
+
+ // Get document width or height
+ if ( elem.nodeType === 9 ) {
+ doc = elem.documentElement;
+
+ // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
+ // unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
+ return Math.max(
+ elem.body[ "scroll" + name ], doc[ "scroll" + name ],
+ elem.body[ "offset" + name ], doc[ "offset" + name ],
+ doc[ "client" + name ]
+ );
+ }
+
+ return value === undefined ?
+ // Get width or height on the element, requesting but not forcing parseFloat
+ jQuery.css( elem, type, extra ) :
+
+ // Set width or height on the element
+ jQuery.style( elem, type, value, extra );
+ }, type, chainable ? margin : undefined, chainable, null );
+ };
+ });
+});
+// Limit scope pollution from any deprecated API
+// (function() {
+
+// The number of elements contained in the matched element set
+jQuery.fn.size = function() {
+ return this.length;
+};
+
+jQuery.fn.andSelf = jQuery.fn.addBack;
+
+// })();
+if ( typeof module === "object" && module && typeof module.exports === "object" ) {
+ // Expose jQuery as module.exports in loaders that implement the Node
+ // module pattern (including browserify). Do not create the global, since
+ // the user will be storing it themselves locally, and globals are frowned
+ // upon in the Node module world.
+ module.exports = jQuery;
+} else {
+ // Otherwise expose jQuery to the global object as usual
+ window.jQuery = window.$ = jQuery;
+
+ // Register as a named AMD module, since jQuery can be concatenated with other
+ // files that may use define, but not via a proper concatenation script that
+ // understands anonymous AMD modules. A named AMD is safest and most robust
+ // way to register. Lowercase jquery is used because AMD module names are
+ // derived from file names, and jQuery is normally delivered in a lowercase
+ // file name. Do this after creating the global so that if an AMD module wants
+ // to call noConflict to hide this version of jQuery, it will work.
+ if ( typeof define === "function" && define.amd ) {
+ define( "jquery", [], function () { return jQuery; } );
+ }
+}
+
+})( window );
diff --git a/features/ids-authentication-artifacts/ids-authentication-analytics/dashboard/TotalTokensBarChart_v2_1.0.0/total-tokens-v2/js/main.js b/features/ids-authentication-artifacts/ids-authentication-analytics/dashboard/TotalTokensBarChart_v2_1.0.0/total-tokens-v2/js/main.js
new file mode 100644
index 0000000..5896e8c
--- /dev/null
+++ b/features/ids-authentication-artifacts/ids-authentication-analytics/dashboard/TotalTokensBarChart_v2_1.0.0/total-tokens-v2/js/main.js
@@ -0,0 +1,102 @@
+var view = {
+ id: "chart-0",
+ schema: [{
+ "metadata": {
+ "names": ["Day", "Type", "Count"],
+ "types": ["ordinal", "ordinal", "linear"]
+ }
+ }],
+ chartConfig: {
+ x : "Day",
+ charts : [{type: "bar", y : "Count", color: "Type", mode:"group"}],
+ barGap: 0.1,
+ tooltip: {"enabled":true, "color":"#e5f2ff", "type":"symbol", "content":["Day","Type","Count"], "label":true },
+ maxLength: 240,
+ width: $('#canvas').width(),
+ height: $('#canvas').height(),
+ padding: { "top": 60, "left": 60, "bottom": 80, "right": 100 },
+ colorScale : [CLR_USSD, CLR_SMS, CLR_MSISDN],
+ xAxisAngle:true
+ },
+ callbacks: [{
+ type: "click",
+ callback: function() {
+ //wso2gadgets.load("chart-1");
+ // alert("Clicked on bar chart of chart-0. You can implement your own callback handler for this.");
+ }
+ }],
+ subscriptions: [{
+ topic: "subscriber",
+ callback: function(topic, data, subscriberData) {
+ wso2.gadgets.controls.showGadget();
+ var filter = {
+ timeFrom : data["timeFrom"],
+ timeTo : data["timeTo"],
+ operator : data["operator"],
+ appID : data["appID"]
+ };
+ $('#modalPopup').modal('hide');
+ $( document ).ready(function() {
+ urlAppend(filter);
+ });
+ var SERVER_URL = "/portal/apis/telcoanalytics";
+ var client = new TelcoAnalyticsClient().init(SERVER_URL);
+ client.getTotalTokens_v2(filter, function (response) {
+ var results = JSON.parse(response.message);
+ wso2gadgets.onDataReady(results);
+ }, function (msg) {
+
+ });
+ wso2.gadgets.state.setGadgetState(filter);
+ }
+ }],
+ data: function() {
+ var filter = {};
+
+ var SERVER_URL = "/portal/apis/telcoanalytics";
+ var client = new TelcoAnalyticsClient().init(SERVER_URL);
+ wso2.gadgets.state.getGadgetState(function(filter) {
+ wso2.gadgets.controls.showGadget();
+ client.getTotalTokens_v2(filter || {}, function (response) {
+ var results = JSON.parse(response.message);
+ wso2gadgets.onDataReady(results);
+ $( document ).ready(function() {
+ urlAppend(filter);
+ });
+ }, function (msg) {
+
+ });
+ });
+ }
+};
+
+
+function urlAppend(filter){
+ if(filter==undefined){
+ filter={};
+ }
+ $("#downloadpdf").attr("href","/portal/apis/report" + "?type=9&timeFrom=" + filter["timeFrom"]
+ + "&timeTo=" + filter["timeTo"] + "&operator=" + filter["operator"]
+ + "&appID=" + filter["appID"]+"&extra=OFFNET&download=pdf");
+ $("#downloadxl").attr("href","/portal/apis/report" + "?type=9&timeFrom=" + filter["timeFrom"]
+ + "&timeTo=" + filter["timeTo"] + "&operator=" + filter["operator"]
+ + "&appID=" + filter["appID"]+"&extra=OFFNET&download=xl");
+
+}
+
+$(function() {
+ try {
+ wso2gadgets.init("#canvas",view);
+ wso2gadgets.load("chart-0");
+ } catch (e) {
+ console.error(e);
+ }
+});
+
+gadgets.HubSettings.onConnect = function() {
+ if (view.subscriptions) {
+ view.subscriptions.forEach(function(subscription) {
+ gadgets.Hub.subscribe(subscription.topic, subscription.callback);
+ });
+ }
+};
diff --git a/features/ids-authentication-artifacts/ids-authentication-analytics/dashboard/TotalTokensBarChart_v2_1.0.0/total-tokens-v2/js/main2.js b/features/ids-authentication-artifacts/ids-authentication-analytics/dashboard/TotalTokensBarChart_v2_1.0.0/total-tokens-v2/js/main2.js
new file mode 100644
index 0000000..1ea25aa
--- /dev/null
+++ b/features/ids-authentication-artifacts/ids-authentication-analytics/dashboard/TotalTokensBarChart_v2_1.0.0/total-tokens-v2/js/main2.js
@@ -0,0 +1,69 @@
+var view = {
+ id: "chart-0",
+ schema: [{
+ "metadata": {
+ "names": ["timestamp", "key", "value"],
+ "types": ["time", "linear", "linear"]
+ }
+ }],
+ chartConfig: {
+ x: "key",
+ charts: [{ type: "bar", y: "value" }],
+ padding: { "top": 20, "left": 50, "bottom": 20, "right": 80 },
+ range: false,
+ height: 300,
+ rangeColor: COLOR_BLUE
+ },
+ callbacks: [{
+ type: "click",
+ callback: function() {
+ commons.load("chart-1");
+ }
+ }],
+ subscriptions: [{
+ topic: "range-selected",
+ callback: function(topic, data, subscriberData) {
+ //do some stuff
+ }
+ }],
+ data: function() {
+ var stream = "sensorStream:1.0.0";
+ subscribe(stream.split(":")[0], stream.split(":")[1],
+ '10', "carbon.super",
+ onRealTimeEventSuccessRecieval, onRealTimeEventErrorRecieval,
+ "localhost",
+ "9443",
+ 'WEBSOCKET',
+ "SECURED"
+ );
+
+ }
+};
+
+$(function() {
+ try {
+ wso2gadgets.init("#canvas", view, "chart-0");
+ // var view = wso2gadgets.load("chart-0");
+ } catch (e) {
+ // alert(e);
+ console.error(e);
+ }
+
+ $("#next").click(function() {
+ wso2gadgets.load("chart-1");
+ });
+
+ $("#prev").click(function() {
+ wso2gadgets.load("chart-0");
+ });
+
+});
+
+function onRealTimeEventSuccessRecieval(streamId,data) {
+ console.log(data);
+ wso2gadgets.onDataReady(data,"append");
+};
+
+function onRealTimeEventErrorRecieval(error) {
+ wso2gadgets.onError(error);
+};
\ No newline at end of file
diff --git a/features/ids-authentication-artifacts/ids-authentication-analytics/dashboard/TotalTokensBarChart_v2_1.0.0/total-tokens-v2/js/outputAdapterUiLibrary.js b/features/ids-authentication-artifacts/ids-authentication-analytics/dashboard/TotalTokensBarChart_v2_1.0.0/total-tokens-v2/js/outputAdapterUiLibrary.js
new file mode 100644
index 0000000..1b8d839
--- /dev/null
+++ b/features/ids-authentication-artifacts/ids-authentication-analytics/dashboard/TotalTokensBarChart_v2_1.0.0/total-tokens-v2/js/outputAdapterUiLibrary.js
@@ -0,0 +1,276 @@
+/*
+ *
+ *
+ * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *
+ */
+
+var CONSTANTS = {
+ webAppName: 'outputui',
+ urlSeperator: '/',
+ urlGetParameter : '?lastUpdatedTime=',
+ tenantUrlAttribute: 't',
+ urlUnsecureTransportHttp : 'http://',
+ urlUnsecureTransportWebsocket : 'ws://',
+ urlSecureTransportWebsocket : 'wss://',
+ urlSecureTransportHttp : 'https://',
+ colon : ':',
+ defaultIntervalTime : 10 * 1000,
+ defaultUserDomain : 'carbon.super',
+ defaultHostName : 'localhost',
+ defaultNonsecurePortNumber : '9763',
+ defaultSecurePortNumber : '9443',
+ defaultMode : 'AUTO',
+ processModeHTTP : 'HTTP',
+ processModeWebSocket : 'WEBSOCKET',
+ processModeAuto : 'AUTO',
+ domain : 'carbon.super',
+ numThousand : 1000,
+ websocketTimeAppender : 400,
+ secureMode : 'SECURED'
+};
+
+
+var websocket = null;
+var webSocketUrl;
+var httpUrl;
+var cepHostName;
+var cepPortNumber;
+var isErrorOccured = false;
+var lastUpdatedtime = -1;
+var polingInterval;
+var stream;
+var streamVersion;
+var firstPollingAttempt;
+var processMode;
+var onSuccessFunction;
+var onErrorFunction;
+var userDomainUrl = "";
+var terminateWebsocketInstance = false;
+var pollingContinue = true;
+var transportToBeUsedHttp;
+var transportToBeUsedWebsocket;
+
+function subscribe(streamName,version,intervalTime,domain,
+ listeningFuncSuccessData,listeningFuncErrorData,cepHost,cepPort,mode,secureMode){
+
+ stopPollingProcesses();
+ stream = streamName;
+ streamVersion = version;
+ onSuccessFunction = listeningFuncSuccessData;
+ onErrorFunction = listeningFuncErrorData;
+
+ if(secureMode == CONSTANTS.secureMode){
+ transportToBeUsedHttp = CONSTANTS.urlSecureTransportHttp;
+ transportToBeUsedWebsocket = CONSTANTS.urlSecureTransportWebsocket;
+ } else {
+ transportToBeUsedHttp = CONSTANTS.urlUnsecureTransportHttp;
+ transportToBeUsedWebsocket = CONSTANTS.urlUnsecureTransportWebsocket;
+ }
+
+ if(intervalTime == null || intervalTime == ""){
+ polingInterval = CONSTANTS.defaultIntervalTime;
+ } else{
+ polingInterval = intervalTime * CONSTANTS.numThousand;
+ }
+
+ if(domain == null || domain == ""){
+ domain = CONSTANTS.defaultUserDomain;
+ }
+
+ if(cepHost == null || cepHost == ""){
+ cepHostName = CONSTANTS.defaultHostName;
+ } else{
+ cepHostName = cepHost;
+ }
+
+ if(cepPort == null || cepPort == ""){
+ if(secureMode == CONSTANTS.secureMode){
+ cepPortNumber = CONSTANTS.defaultSecurePortNumber;
+ } else{
+ cepPortNumber = CONSTANTS.defaultNonsecurePortNumber;
+ }
+ } else{
+ cepPortNumber = cepPort;
+ }
+
+ if(mode == null || mode == ""){
+ processMode = CONSTANTS.defaultMode;
+ } else{
+ processMode = mode;
+ }
+
+ if(domain != CONSTANTS.domain){
+ userDomainUrl = CONSTANTS.tenantUrlAttribute + CONSTANTS.urlSeperator + domain + CONSTANTS.urlSeperator;
+
+ }
+ webSocketUrl = transportToBeUsedWebsocket + cepHostName + CONSTANTS.colon + cepPortNumber +
+ CONSTANTS.urlSeperator + CONSTANTS.webAppName+ CONSTANTS.urlSeperator + userDomainUrl + stream +
+ CONSTANTS.urlSeperator + streamVersion;
+
+ if(processMode == CONSTANTS.processModeHTTP){
+ firstPollingAttempt = true;
+ pollingContinue = true;
+ startPoll();
+ } else{
+ initializeWebSocket(webSocketUrl);
+ }
+}
+
+
+/**
+ * Initializing Web Socket
+ */
+function initializeWebSocket(webSocketUrl){
+ websocket = new WebSocket(webSocketUrl);
+ websocket.onopen = webSocketOnOpen;
+ websocket.onmessage = webSocketOnMessage;
+ websocket.onclose = webSocketOnClose;
+ websocket.onerror = webSocketOnError;
+}
+
+/**
+ * Web socket On Open
+ */
+
+var webSocketOnOpen = function () {
+ // alert("Successfully connected to "+webSocketUrl);
+ //onErrorFunction("Successfully connected to URL:" + webSocketUrl + "\n");
+};
+
+
+/**
+ * On server sends a message
+ */
+var webSocketOnMessage = function (evt) {
+ var event = evt.data;
+ var array = JSON.parse(event);
+ constructPayload(array);
+};
+
+/**
+ * On server close
+ */
+var webSocketOnClose =function (e) {
+
+ if(isErrorOccured){
+ if(processMode != CONSTANTS.processModeWebSocket){
+ firstPollingAttempt = true;
+ pollingContinue = true;
+ startPoll();
+ }
+ } else{
+ if(!terminateWebsocketInstance){
+ waitForSocketConnection(websocket);
+ } else{
+ terminateWebsocketInstance = false;
+ }
+
+ }
+};
+
+/**
+ * On server Error
+ */
+var webSocketOnError = function (err) {
+ var error = "Error: Cannot connect to Websocket URL:" + webSocketUrl + " .Hence closing the connection!";
+
+ onErrorFunction(error);
+ isErrorOccured = true;
+
+};
+
+/**
+ * Gracefully increments the connection retry
+ */
+var waitTime = CONSTANTS.numThousand;
+function waitForSocketConnection(socket, callback){
+ setTimeout(
+ function () {
+ if (socket.readyState === 1) {
+ initializeWebSocket(webSocketUrl);
+ console.log("Connection is made");
+ if(callback != null){
+ callback();
+ }
+ return;
+ } else {
+ websocket = new WebSocket(webSocketUrl);
+ waitTime += CONSTANTS.websocketTimeAppender;
+ waitForSocketConnection(websocket, callback);
+ }
+ }, waitTime);
+}
+
+/**
+ * Polling to retrieve events from http request periodically
+ */
+function startPoll(){
+
+ (function poll(){
+ setTimeout(function(){
+ httpUrl = transportToBeUsedHttp + cepHostName + CONSTANTS.colon + cepPortNumber + CONSTANTS.urlSeperator
+ + CONSTANTS.webAppName + CONSTANTS.urlSeperator + userDomainUrl + stream + CONSTANTS.urlSeperator +
+ streamVersion + CONSTANTS.urlGetParameter + lastUpdatedtime;
+
+ $.getJSON(httpUrl, function(responseText) {
+ if(firstPollingAttempt){
+ /*var data = $("textarea#idConsole").val();
+ $("textarea#idConsole").val(data + "Successfully connected to HTTP.");*/
+ firstPollingAttempt = false;
+ }
+
+ var eventList = $.parseJSON(responseText.events);
+ if(eventList.length != 0){
+ lastUpdatedtime = responseText.lastEventTime;
+ for(var i=0;i
= N) return EOF; // special case: end of file
+ if (eol) return eol = false, EOL; // special case: end of line
+
+ // special case: quotes
+ var j = I, c;
+ if (text.charCodeAt(j) === 34) {
+ var i = j;
+ while (i++ < N) {
+ if (text.charCodeAt(i) === 34) {
+ if (text.charCodeAt(i + 1) !== 34) break;
+ ++i;
+ }
+ }
+ I = i + 2;
+ c = text.charCodeAt(i + 1);
+ if (c === 13) {
+ eol = true;
+ if (text.charCodeAt(i + 2) === 10) ++I;
+ } else if (c === 10) {
+ eol = true;
+ }
+ return text.slice(j + 1, i).replace(/""/g, "\"");
+ }
+
+ // common case: find next delimiter or newline
+ while (I < N) {
+ var k = 1;
+ c = text.charCodeAt(I++);
+ if (c === 10) eol = true; // \n
+ else if (c === 13) { eol = true; if (text.charCodeAt(I) === 10) ++I, ++k; } // \r|\r\n
+ else if (c !== delimiterCode) continue;
+ return text.slice(j, I - k);
+ }
+
+ // special case: last token before EOF
+ return text.slice(j);
+ }
+
+ while ((t = token()) !== EOF) {
+ var a = [];
+ while (t !== EOL && t !== EOF) {
+ a.push(t);
+ t = token();
+ }
+ if (f && (a = f(a, n++)) == null) continue;
+ rows.push(a);
+ }
+
+ return rows;
+ }
+
+ this.format = function(rows, columns) {
+ if (columns == null) columns = inferColumns(rows);
+ return [columns.map(formatValue).join(delimiter)].concat(rows.map(function(row) {
+ return columns.map(function(column) {
+ return formatValue(row[column]);
+ }).join(delimiter);
+ })).join("\n");
+ };
+
+ this.formatRows = function(rows) {
+ return rows.map(formatRow).join("\n");
+ };
+
+ function formatRow(row) {
+ return row.map(formatValue).join(delimiter);
+ }
+
+ function formatValue(text) {
+ return reFormat.test(text) ? "\"" + text.replace(/\"/g, "\"\"") + "\"" : text;
+ }
+ }
+
+ dsv.prototype = Dsv.prototype;
+
+ var csv = dsv(",");
+ var tsv = dsv("\t");
+
+ var version = "0.1.14";
+
+ exports.version = version;
+ exports.dsv = dsv;
+ exports.csv = csv;
+ exports.tsv = tsv;
+
+}));
+},{}],4:[function(require,module,exports){
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
+ typeof define === 'function' && define.amd ? define('d3-format', ['exports'], factory) :
+ factory((global.d3_format = {}));
+}(this, function (exports) { 'use strict';
+
+ // Computes the decimal coefficient and exponent of the specified number x with
+ // significant digits p, where x is positive and p is in [1, 21] or undefined.
+ // For example, formatDecimal(1.23) returns ["123", 0].
+ function formatDecimal(x, p) {
+ if ((i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0) return null; // NaN, ±Infinity
+ var i, coefficient = x.slice(0, i);
+
+ // The string returned by toExponential either has the form \d\.\d+e[-+]\d+
+ // (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3).
+ return [
+ coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient,
+ +x.slice(i + 1)
+ ];
+ };
+
+ function exponent(x) {
+ return x = formatDecimal(Math.abs(x)), x ? x[1] : NaN;
+ };
+
+ function formatGroup(grouping, thousands) {
+ return function(value, width) {
+ var i = value.length,
+ t = [],
+ j = 0,
+ g = grouping[0],
+ length = 0;
+
+ while (i > 0 && g > 0) {
+ if (length + g + 1 > width) g = Math.max(1, width - length);
+ t.push(value.substring(i -= g, i + g));
+ if ((length += g + 1) > width) break;
+ g = grouping[j = (j + 1) % grouping.length];
+ }
+
+ return t.reverse().join(thousands);
+ };
+ };
+
+ var prefixExponent;
+
+ function formatPrefixAuto(x, p) {
+ var d = formatDecimal(x, p);
+ if (!d) return x + "";
+ var coefficient = d[0],
+ exponent = d[1],
+ i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1,
+ n = coefficient.length;
+ return i === n ? coefficient
+ : i > n ? coefficient + new Array(i - n + 1).join("0")
+ : i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i)
+ : "0." + new Array(1 - i).join("0") + formatDecimal(x, Math.max(0, p + i - 1))[0]; // less than 1y!
+ };
+
+ function formatRounded(x, p) {
+ var d = formatDecimal(x, p);
+ if (!d) return x + "";
+ var coefficient = d[0],
+ exponent = d[1];
+ return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient
+ : coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1)
+ : coefficient + new Array(exponent - coefficient.length + 2).join("0");
+ };
+
+ function formatDefault(x, p) {
+ x = x.toPrecision(p);
+
+ out: for (var n = x.length, i = 1, i0 = -1, i1; i < n; ++i) {
+ switch (x[i]) {
+ case ".": i0 = i1 = i; break;
+ case "0": if (i0 === 0) i0 = i; i1 = i; break;
+ case "e": break out;
+ default: if (i0 > 0) i0 = 0; break;
+ }
+ }
+
+ return i0 > 0 ? x.slice(0, i0) + x.slice(i1 + 1) : x;
+ };
+
+ var formatTypes = {
+ "": formatDefault,
+ "%": function(x, p) { return (x * 100).toFixed(p); },
+ "b": function(x) { return Math.round(x).toString(2); },
+ "c": function(x) { return x + ""; },
+ "d": function(x) { return Math.round(x).toString(10); },
+ "e": function(x, p) { return x.toExponential(p); },
+ "f": function(x, p) { return x.toFixed(p); },
+ "g": function(x, p) { return x.toPrecision(p); },
+ "o": function(x) { return Math.round(x).toString(8); },
+ "p": function(x, p) { return formatRounded(x * 100, p); },
+ "r": formatRounded,
+ "s": formatPrefixAuto,
+ "X": function(x) { return Math.round(x).toString(16).toUpperCase(); },
+ "x": function(x) { return Math.round(x).toString(16); }
+ };
+
+ // [[fill]align][sign][symbol][0][width][,][.precision][type]
+ var re = /^(?:(.)?([<>=^]))?([+\-\( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?([a-z%])?$/i;
+
+ function formatSpecifier(specifier) {
+ return new FormatSpecifier(specifier);
+ };
+
+ function FormatSpecifier(specifier) {
+ if (!(match = re.exec(specifier))) throw new Error("invalid format: " + specifier);
+
+ var match,
+ fill = match[1] || " ",
+ align = match[2] || ">",
+ sign = match[3] || "-",
+ symbol = match[4] || "",
+ zero = !!match[5],
+ width = match[6] && +match[6],
+ comma = !!match[7],
+ precision = match[8] && +match[8].slice(1),
+ type = match[9] || "";
+
+ // The "n" type is an alias for ",g".
+ if (type === "n") comma = true, type = "g";
+
+ // Map invalid types to the default format.
+ else if (!formatTypes[type]) type = "";
+
+ // If zero fill is specified, padding goes after sign and before digits.
+ if (zero || (fill === "0" && align === "=")) zero = true, fill = "0", align = "=";
+
+ this.fill = fill;
+ this.align = align;
+ this.sign = sign;
+ this.symbol = symbol;
+ this.zero = zero;
+ this.width = width;
+ this.comma = comma;
+ this.precision = precision;
+ this.type = type;
+ }
+
+ FormatSpecifier.prototype.toString = function() {
+ return this.fill
+ + this.align
+ + this.sign
+ + this.symbol
+ + (this.zero ? "0" : "")
+ + (this.width == null ? "" : Math.max(1, this.width | 0))
+ + (this.comma ? "," : "")
+ + (this.precision == null ? "" : "." + Math.max(0, this.precision | 0))
+ + this.type;
+ };
+
+ var prefixes = ["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];
+
+ function identity(x) {
+ return x;
+ }
+
+ function locale(locale) {
+ var group = locale.grouping && locale.thousands ? formatGroup(locale.grouping, locale.thousands) : identity,
+ currency = locale.currency,
+ decimal = locale.decimal;
+
+ function format(specifier) {
+ specifier = formatSpecifier(specifier);
+
+ var fill = specifier.fill,
+ align = specifier.align,
+ sign = specifier.sign,
+ symbol = specifier.symbol,
+ zero = specifier.zero,
+ width = specifier.width,
+ comma = specifier.comma,
+ precision = specifier.precision,
+ type = specifier.type;
+
+ // Compute the prefix and suffix.
+ // For SI-prefix, the suffix is lazily computed.
+ var prefix = symbol === "$" ? currency[0] : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "",
+ suffix = symbol === "$" ? currency[1] : /[%p]/.test(type) ? "%" : "";
+
+ // What format function should we use?
+ // Is this an integer type?
+ // Can this type generate exponential notation?
+ var formatType = formatTypes[type],
+ maybeSuffix = !type || /[defgprs%]/.test(type);
+
+ // Set the default precision if not specified,
+ // or clamp the specified precision to the supported range.
+ // For significant precision, it must be in [1, 21].
+ // For fixed precision, it must be in [0, 20].
+ precision = precision == null ? (type ? 6 : 12)
+ : /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision))
+ : Math.max(0, Math.min(20, precision));
+
+ return function(value) {
+ var valuePrefix = prefix,
+ valueSuffix = suffix;
+
+ if (type === "c") {
+ valueSuffix = formatType(value) + valueSuffix;
+ value = "";
+ } else {
+ value = +value;
+
+ // Convert negative to positive, and compute the prefix.
+ // Note that -0 is not less than 0, but 1 / -0 is!
+ var valueNegative = (value < 0 || 1 / value < 0) && (value *= -1, true);
+
+ // Perform the initial formatting.
+ value = formatType(value, precision);
+
+ // If the original value was negative, it may be rounded to zero during
+ // formatting; treat this as (positive) zero.
+ if (valueNegative) {
+ var i = -1, n = value.length, c;
+ valueNegative = false;
+ while (++i < n) {
+ if (c = value.charCodeAt(i), (48 < c && c < 58)
+ || (type === "x" && 96 < c && c < 103)
+ || (type === "X" && 64 < c && c < 71)) {
+ valueNegative = true;
+ break;
+ }
+ }
+ }
+
+ // Compute the prefix and suffix.
+ valuePrefix = (valueNegative ? (sign === "(" ? sign : "-") : sign === "-" || sign === "(" ? "" : sign) + valuePrefix;
+ valueSuffix = valueSuffix + (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + (valueNegative && sign === "(" ? ")" : "");
+
+ // Break the formatted value into the integer “value” part that can be
+ // grouped, and fractional or exponential “suffix” part that is not.
+ if (maybeSuffix) {
+ var i = -1, n = value.length, c;
+ while (++i < n) {
+ if (c = value.charCodeAt(i), 48 > c || c > 57) {
+ valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix;
+ value = value.slice(0, i);
+ break;
+ }
+ }
+ }
+ }
+
+ // If the fill character is not "0", grouping is applied before padding.
+ if (comma && !zero) value = group(value, Infinity);
+
+ // Compute the padding.
+ var length = valuePrefix.length + value.length + valueSuffix.length,
+ padding = length < width ? new Array(width - length + 1).join(fill) : "";
+
+ // If the fill character is "0", grouping is applied after padding.
+ if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = "";
+
+ // Reconstruct the final output based on the desired alignment.
+ switch (align) {
+ case "<": return valuePrefix + value + valueSuffix + padding;
+ case "=": return valuePrefix + padding + value + valueSuffix;
+ case "^": return padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length);
+ }
+ return padding + valuePrefix + value + valueSuffix;
+ };
+ }
+
+ function formatPrefix(specifier, value) {
+ var f = format((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)),
+ e = Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3,
+ k = Math.pow(10, -e),
+ prefix = prefixes[8 + e / 3];
+ return function(value) {
+ return f(k * value) + prefix;
+ };
+ }
+
+ return {
+ format: format,
+ formatPrefix: formatPrefix
+ };
+ };
+
+ var defaultLocale = locale({
+ decimal: ".",
+ thousands: ",",
+ grouping: [3],
+ currency: ["$", ""]
+ });
+
+ var caES = locale({
+ decimal: ",",
+ thousands: ".",
+ grouping: [3],
+ currency: ["", "\xa0€"]
+ });
+
+ var csCZ = locale({
+ decimal: ",",
+ thousands: "\xa0",
+ grouping: [3],
+ currency: ["", "\xa0Kč"],
+ });
+
+ var deCH = locale({
+ decimal: ",",
+ thousands: "'",
+ grouping: [3],
+ currency: ["", "\xa0CHF"]
+ });
+
+ var deDE = locale({
+ decimal: ",",
+ thousands: ".",
+ grouping: [3],
+ currency: ["", "\xa0€"]
+ });
+
+ var enCA = locale({
+ decimal: ".",
+ thousands: ",",
+ grouping: [3],
+ currency: ["$", ""]
+ });
+
+ var enGB = locale({
+ decimal: ".",
+ thousands: ",",
+ grouping: [3],
+ currency: ["£", ""]
+ });
+
+ var esES = locale({
+ decimal: ",",
+ thousands: ".",
+ grouping: [3],
+ currency: ["", "\xa0€"]
+ });
+
+ var fiFI = locale({
+ decimal: ",",
+ thousands: "\xa0",
+ grouping: [3],
+ currency: ["", "\xa0€"]
+ });
+
+ var frCA = locale({
+ decimal: ",",
+ thousands: "\xa0",
+ grouping: [3],
+ currency: ["", "$"]
+ });
+
+ var frFR = locale({
+ decimal: ",",
+ thousands: ".",
+ grouping: [3],
+ currency: ["", "\xa0€"]
+ });
+
+ var heIL = locale({
+ decimal: ".",
+ thousands: ",",
+ grouping: [3],
+ currency: ["₪", ""]
+ });
+
+ var huHU = locale({
+ decimal: ",",
+ thousands: "\xa0",
+ grouping: [3],
+ currency: ["", "\xa0Ft"]
+ });
+
+ var itIT = locale({
+ decimal: ",",
+ thousands: ".",
+ grouping: [3],
+ currency: ["€", ""]
+ });
+
+ var jaJP = locale({
+ decimal: ".",
+ thousands: ",",
+ grouping: [3],
+ currency: ["", "円"]
+ });
+
+ var koKR = locale({
+ decimal: ".",
+ thousands: ",",
+ grouping: [3],
+ currency: ["₩", ""]
+ });
+
+ var mkMK = locale({
+ decimal: ",",
+ thousands: ".",
+ grouping: [3],
+ currency: ["", "\xa0ден."]
+ });
+
+ var nlNL = locale({
+ decimal: ",",
+ thousands: ".",
+ grouping: [3],
+ currency: ["€\xa0", ""]
+ });
+
+ var plPL = locale({
+ decimal: ",",
+ thousands: ".",
+ grouping: [3],
+ currency: ["", "zł"]
+ });
+
+ var ptBR = locale({
+ decimal: ",",
+ thousands: ".",
+ grouping: [3],
+ currency: ["R$", ""]
+ });
+
+ var ruRU = locale({
+ decimal: ",",
+ thousands: "\xa0",
+ grouping: [3],
+ currency: ["", "\xa0руб."]
+ });
+
+ var svSE = locale({
+ decimal: ",",
+ thousands: "\xa0",
+ grouping: [3],
+ currency: ["", "SEK"]
+ });
+
+ var zhCN = locale({
+ decimal: ".",
+ thousands: ",",
+ grouping: [3],
+ currency: ["¥", ""]
+ });
+
+ function precisionFixed(step) {
+ return Math.max(0, -exponent(Math.abs(step)));
+ };
+
+ function precisionPrefix(step, value) {
+ return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3 - exponent(Math.abs(step)));
+ };
+
+ function precisionRound(step, max) {
+ step = Math.abs(step), max = Math.abs(max) - step;
+ return Math.max(0, exponent(max) - exponent(step)) + 1;
+ };
+
+ var format = defaultLocale.format;
+ var formatPrefix = defaultLocale.formatPrefix;
+
+ var version = "0.4.2";
+
+ exports.version = version;
+ exports.format = format;
+ exports.formatPrefix = formatPrefix;
+ exports.locale = locale;
+ exports.localeCaEs = caES;
+ exports.localeCsCz = csCZ;
+ exports.localeDeCh = deCH;
+ exports.localeDeDe = deDE;
+ exports.localeEnCa = enCA;
+ exports.localeEnGb = enGB;
+ exports.localeEnUs = defaultLocale;
+ exports.localeEsEs = esES;
+ exports.localeFiFi = fiFI;
+ exports.localeFrCa = frCA;
+ exports.localeFrFr = frFR;
+ exports.localeHeIl = heIL;
+ exports.localeHuHu = huHU;
+ exports.localeItIt = itIT;
+ exports.localeJaJp = jaJP;
+ exports.localeKoKr = koKR;
+ exports.localeMkMk = mkMK;
+ exports.localeNlNl = nlNL;
+ exports.localePlPl = plPL;
+ exports.localePtBr = ptBR;
+ exports.localeRuRu = ruRU;
+ exports.localeSvSe = svSE;
+ exports.localeZhCn = zhCN;
+ exports.formatSpecifier = formatSpecifier;
+ exports.precisionFixed = precisionFixed;
+ exports.precisionPrefix = precisionPrefix;
+ exports.precisionRound = precisionRound;
+
+}));
+},{}],5:[function(require,module,exports){
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-time')) :
+ typeof define === 'function' && define.amd ? define('d3-time-format', ['exports', 'd3-time'], factory) :
+ factory((global.d3_time_format = {}),global.d3_time);
+}(this, function (exports,d3Time) { 'use strict';
+
+ function localDate(d) {
+ if (0 <= d.y && d.y < 100) {
+ var date = new Date(-1, d.m, d.d, d.H, d.M, d.S, d.L);
+ date.setFullYear(d.y);
+ return date;
+ }
+ return new Date(d.y, d.m, d.d, d.H, d.M, d.S, d.L);
+ }
+
+ function utcDate(d) {
+ if (0 <= d.y && d.y < 100) {
+ var date = new Date(Date.UTC(-1, d.m, d.d, d.H, d.M, d.S, d.L));
+ date.setUTCFullYear(d.y);
+ return date;
+ }
+ return new Date(Date.UTC(d.y, d.m, d.d, d.H, d.M, d.S, d.L));
+ }
+
+ function newYear(y) {
+ return {y: y, m: 0, d: 1, H: 0, M: 0, S: 0, L: 0};
+ }
+
+ function locale$1(locale) {
+ var locale_dateTime = locale.dateTime,
+ locale_date = locale.date,
+ locale_time = locale.time,
+ locale_periods = locale.periods,
+ locale_weekdays = locale.days,
+ locale_shortWeekdays = locale.shortDays,
+ locale_months = locale.months,
+ locale_shortMonths = locale.shortMonths;
+
+ var periodRe = formatRe(locale_periods),
+ periodLookup = formatLookup(locale_periods),
+ weekdayRe = formatRe(locale_weekdays),
+ weekdayLookup = formatLookup(locale_weekdays),
+ shortWeekdayRe = formatRe(locale_shortWeekdays),
+ shortWeekdayLookup = formatLookup(locale_shortWeekdays),
+ monthRe = formatRe(locale_months),
+ monthLookup = formatLookup(locale_months),
+ shortMonthRe = formatRe(locale_shortMonths),
+ shortMonthLookup = formatLookup(locale_shortMonths);
+
+ var formats = {
+ "a": formatShortWeekday,
+ "A": formatWeekday,
+ "b": formatShortMonth,
+ "B": formatMonth,
+ "c": null,
+ "d": formatDayOfMonth,
+ "e": formatDayOfMonth,
+ "H": formatHour24,
+ "I": formatHour12,
+ "j": formatDayOfYear,
+ "L": formatMilliseconds,
+ "m": formatMonthNumber,
+ "M": formatMinutes,
+ "p": formatPeriod,
+ "S": formatSeconds,
+ "U": formatWeekNumberSunday,
+ "w": formatWeekdayNumber,
+ "W": formatWeekNumberMonday,
+ "x": null,
+ "X": null,
+ "y": formatYear,
+ "Y": formatFullYear,
+ "Z": formatZone,
+ "%": formatLiteralPercent
+ };
+
+ var utcFormats = {
+ "a": formatUTCShortWeekday,
+ "A": formatUTCWeekday,
+ "b": formatUTCShortMonth,
+ "B": formatUTCMonth,
+ "c": null,
+ "d": formatUTCDayOfMonth,
+ "e": formatUTCDayOfMonth,
+ "H": formatUTCHour24,
+ "I": formatUTCHour12,
+ "j": formatUTCDayOfYear,
+ "L": formatUTCMilliseconds,
+ "m": formatUTCMonthNumber,
+ "M": formatUTCMinutes,
+ "p": formatUTCPeriod,
+ "S": formatUTCSeconds,
+ "U": formatUTCWeekNumberSunday,
+ "w": formatUTCWeekdayNumber,
+ "W": formatUTCWeekNumberMonday,
+ "x": null,
+ "X": null,
+ "y": formatUTCYear,
+ "Y": formatUTCFullYear,
+ "Z": formatUTCZone,
+ "%": formatLiteralPercent
+ };
+
+ var parses = {
+ "a": parseShortWeekday,
+ "A": parseWeekday,
+ "b": parseShortMonth,
+ "B": parseMonth,
+ "c": parseLocaleDateTime,
+ "d": parseDayOfMonth,
+ "e": parseDayOfMonth,
+ "H": parseHour24,
+ "I": parseHour24,
+ "j": parseDayOfYear,
+ "L": parseMilliseconds,
+ "m": parseMonthNumber,
+ "M": parseMinutes,
+ "p": parsePeriod,
+ "S": parseSeconds,
+ "U": parseWeekNumberSunday,
+ "w": parseWeekdayNumber,
+ "W": parseWeekNumberMonday,
+ "x": parseLocaleDate,
+ "X": parseLocaleTime,
+ "y": parseYear,
+ "Y": parseFullYear,
+ "Z": parseZone,
+ "%": parseLiteralPercent
+ };
+
+ // These recursive directive definitions must be deferred.
+ formats.x = newFormat(locale_date, formats);
+ formats.X = newFormat(locale_time, formats);
+ formats.c = newFormat(locale_dateTime, formats);
+ utcFormats.x = newFormat(locale_date, utcFormats);
+ utcFormats.X = newFormat(locale_time, utcFormats);
+ utcFormats.c = newFormat(locale_dateTime, utcFormats);
+
+ function newFormat(specifier, formats) {
+ return function(date) {
+ var string = [],
+ i = -1,
+ j = 0,
+ n = specifier.length,
+ c,
+ pad,
+ format;
+
+ if (!(date instanceof Date)) date = new Date(+date);
+
+ while (++i < n) {
+ if (specifier.charCodeAt(i) === 37) {
+ string.push(specifier.slice(j, i));
+ if ((pad = pads[c = specifier.charAt(++i)]) != null) c = specifier.charAt(++i);
+ else pad = c === "e" ? " " : "0";
+ if (format = formats[c]) c = format(date, pad);
+ string.push(c);
+ j = i + 1;
+ }
+ }
+
+ string.push(specifier.slice(j, i));
+ return string.join("");
+ };
+ }
+
+ function newParse(specifier, newDate) {
+ return function(string) {
+ var d = newYear(1900),
+ i = parseSpecifier(d, specifier, string += "", 0);
+ if (i != string.length) return null;
+
+ // The am-pm flag is 0 for AM, and 1 for PM.
+ if ("p" in d) d.H = d.H % 12 + d.p * 12;
+
+ // Convert day-of-week and week-of-year to day-of-year.
+ if ("W" in d || "U" in d) {
+ if (!("w" in d)) d.w = "W" in d ? 1 : 0;
+ var day = "Z" in d ? utcDate(newYear(d.y)).getUTCDay() : newDate(newYear(d.y)).getDay();
+ d.m = 0;
+ d.d = "W" in d ? (d.w + 6) % 7 + d.W * 7 - (day + 5) % 7 : d.w + d.U * 7 - (day + 6) % 7;
+ }
+
+ // If a time zone is specified, all fields are interpreted as UTC and then
+ // offset according to the specified time zone.
+ if ("Z" in d) {
+ d.H += d.Z / 100 | 0;
+ d.M += d.Z % 100;
+ return utcDate(d);
+ }
+
+ // Otherwise, all fields are in local time.
+ return newDate(d);
+ };
+ }
+
+ function parseSpecifier(d, specifier, string, j) {
+ var i = 0,
+ n = specifier.length,
+ m = string.length,
+ c,
+ parse;
+
+ while (i < n) {
+ if (j >= m) return -1;
+ c = specifier.charCodeAt(i++);
+ if (c === 37) {
+ c = specifier.charAt(i++);
+ parse = parses[c in pads ? specifier.charAt(i++) : c];
+ if (!parse || ((j = parse(d, string, j)) < 0)) return -1;
+ } else if (c != string.charCodeAt(j++)) {
+ return -1;
+ }
+ }
+
+ return j;
+ }
+
+ function parsePeriod(d, string, i) {
+ var n = periodRe.exec(string.slice(i));
+ return n ? (d.p = periodLookup[n[0].toLowerCase()], i + n[0].length) : -1;
+ }
+
+ function parseShortWeekday(d, string, i) {
+ var n = shortWeekdayRe.exec(string.slice(i));
+ return n ? (d.w = shortWeekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1;
+ }
+
+ function parseWeekday(d, string, i) {
+ var n = weekdayRe.exec(string.slice(i));
+ return n ? (d.w = weekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1;
+ }
+
+ function parseShortMonth(d, string, i) {
+ var n = shortMonthRe.exec(string.slice(i));
+ return n ? (d.m = shortMonthLookup[n[0].toLowerCase()], i + n[0].length) : -1;
+ }
+
+ function parseMonth(d, string, i) {
+ var n = monthRe.exec(string.slice(i));
+ return n ? (d.m = monthLookup[n[0].toLowerCase()], i + n[0].length) : -1;
+ }
+
+ function parseLocaleDateTime(d, string, i) {
+ return parseSpecifier(d, locale_dateTime, string, i);
+ }
+
+ function parseLocaleDate(d, string, i) {
+ return parseSpecifier(d, locale_date, string, i);
+ }
+
+ function parseLocaleTime(d, string, i) {
+ return parseSpecifier(d, locale_time, string, i);
+ }
+
+ function formatShortWeekday(d) {
+ return locale_shortWeekdays[d.getDay()];
+ }
+
+ function formatWeekday(d) {
+ return locale_weekdays[d.getDay()];
+ }
+
+ function formatShortMonth(d) {
+ return locale_shortMonths[d.getMonth()];
+ }
+
+ function formatMonth(d) {
+ return locale_months[d.getMonth()];
+ }
+
+ function formatPeriod(d) {
+ return locale_periods[+(d.getHours() >= 12)];
+ }
+
+ function formatUTCShortWeekday(d) {
+ return locale_shortWeekdays[d.getUTCDay()];
+ }
+
+ function formatUTCWeekday(d) {
+ return locale_weekdays[d.getUTCDay()];
+ }
+
+ function formatUTCShortMonth(d) {
+ return locale_shortMonths[d.getUTCMonth()];
+ }
+
+ function formatUTCMonth(d) {
+ return locale_months[d.getUTCMonth()];
+ }
+
+ function formatUTCPeriod(d) {
+ return locale_periods[+(d.getUTCHours() >= 12)];
+ }
+
+ return {
+ format: function(specifier) {
+ var f = newFormat(specifier += "", formats);
+ f.parse = newParse(specifier, localDate);
+ f.toString = function() { return specifier; };
+ return f;
+ },
+ utcFormat: function(specifier) {
+ var f = newFormat(specifier += "", utcFormats);
+ f.parse = newParse(specifier, utcDate);
+ f.toString = function() { return specifier; };
+ return f;
+ }
+ };
+ };
+
+ var pads = {"-": "", "_": " ", "0": "0"};
+ var numberRe = /^\s*\d+/;
+ var percentRe = /^%/;
+ var requoteRe = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
+ function pad(value, fill, width) {
+ var sign = value < 0 ? "-" : "",
+ string = (sign ? -value : value) + "",
+ length = string.length;
+ return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string);
+ }
+
+ function requote(s) {
+ return s.replace(requoteRe, "\\$&");
+ }
+
+ function formatRe(names) {
+ return new RegExp("^(?:" + names.map(requote).join("|") + ")", "i");
+ }
+
+ function formatLookup(names) {
+ var map = {}, i = -1, n = names.length;
+ while (++i < n) map[names[i].toLowerCase()] = i;
+ return map;
+ }
+
+ function parseWeekdayNumber(d, string, i) {
+ var n = numberRe.exec(string.slice(i, i + 1));
+ return n ? (d.w = +n[0], i + n[0].length) : -1;
+ }
+
+ function parseWeekNumberSunday(d, string, i) {
+ var n = numberRe.exec(string.slice(i));
+ return n ? (d.U = +n[0], i + n[0].length) : -1;
+ }
+
+ function parseWeekNumberMonday(d, string, i) {
+ var n = numberRe.exec(string.slice(i));
+ return n ? (d.W = +n[0], i + n[0].length) : -1;
+ }
+
+ function parseFullYear(d, string, i) {
+ var n = numberRe.exec(string.slice(i, i + 4));
+ return n ? (d.y = +n[0], i + n[0].length) : -1;
+ }
+
+ function parseYear(d, string, i) {
+ var n = numberRe.exec(string.slice(i, i + 2));
+ return n ? (d.y = +n[0] + (+n[0] > 68 ? 1900 : 2000), i + n[0].length) : -1;
+ }
+
+ function parseZone(d, string, i) {
+ var n = /^(Z)|([+-]\d\d)(?:\:?(\d\d))?/.exec(string.slice(i, i + 6));
+ return n ? (d.Z = n[1] ? 0 : -(n[2] + (n[3] || "00")), i + n[0].length) : -1;
+ }
+
+ function parseMonthNumber(d, string, i) {
+ var n = numberRe.exec(string.slice(i, i + 2));
+ return n ? (d.m = n[0] - 1, i + n[0].length) : -1;
+ }
+
+ function parseDayOfMonth(d, string, i) {
+ var n = numberRe.exec(string.slice(i, i + 2));
+ return n ? (d.d = +n[0], i + n[0].length) : -1;
+ }
+
+ function parseDayOfYear(d, string, i) {
+ var n = numberRe.exec(string.slice(i, i + 3));
+ return n ? (d.m = 0, d.d = +n[0], i + n[0].length) : -1;
+ }
+
+ function parseHour24(d, string, i) {
+ var n = numberRe.exec(string.slice(i, i + 2));
+ return n ? (d.H = +n[0], i + n[0].length) : -1;
+ }
+
+ function parseMinutes(d, string, i) {
+ var n = numberRe.exec(string.slice(i, i + 2));
+ return n ? (d.M = +n[0], i + n[0].length) : -1;
+ }
+
+ function parseSeconds(d, string, i) {
+ var n = numberRe.exec(string.slice(i, i + 2));
+ return n ? (d.S = +n[0], i + n[0].length) : -1;
+ }
+
+ function parseMilliseconds(d, string, i) {
+ var n = numberRe.exec(string.slice(i, i + 3));
+ return n ? (d.L = +n[0], i + n[0].length) : -1;
+ }
+
+ function parseLiteralPercent(d, string, i) {
+ var n = percentRe.exec(string.slice(i, i + 1));
+ return n ? i + n[0].length : -1;
+ }
+
+ function formatDayOfMonth(d, p) {
+ return pad(d.getDate(), p, 2);
+ }
+
+ function formatHour24(d, p) {
+ return pad(d.getHours(), p, 2);
+ }
+
+ function formatHour12(d, p) {
+ return pad(d.getHours() % 12 || 12, p, 2);
+ }
+
+ function formatDayOfYear(d, p) {
+ return pad(1 + d3Time.day.count(d3Time.year(d), d), p, 3);
+ }
+
+ function formatMilliseconds(d, p) {
+ return pad(d.getMilliseconds(), p, 3);
+ }
+
+ function formatMonthNumber(d, p) {
+ return pad(d.getMonth() + 1, p, 2);
+ }
+
+ function formatMinutes(d, p) {
+ return pad(d.getMinutes(), p, 2);
+ }
+
+ function formatSeconds(d, p) {
+ return pad(d.getSeconds(), p, 2);
+ }
+
+ function formatWeekNumberSunday(d, p) {
+ return pad(d3Time.sunday.count(d3Time.year(d), d), p, 2);
+ }
+
+ function formatWeekdayNumber(d) {
+ return d.getDay();
+ }
+
+ function formatWeekNumberMonday(d, p) {
+ return pad(d3Time.monday.count(d3Time.year(d), d), p, 2);
+ }
+
+ function formatYear(d, p) {
+ return pad(d.getFullYear() % 100, p, 2);
+ }
+
+ function formatFullYear(d, p) {
+ return pad(d.getFullYear() % 10000, p, 4);
+ }
+
+ function formatZone(d) {
+ var z = d.getTimezoneOffset();
+ return (z > 0 ? "-" : (z *= -1, "+"))
+ + pad(z / 60 | 0, "0", 2)
+ + pad(z % 60, "0", 2);
+ }
+
+ function formatUTCDayOfMonth(d, p) {
+ return pad(d.getUTCDate(), p, 2);
+ }
+
+ function formatUTCHour24(d, p) {
+ return pad(d.getUTCHours(), p, 2);
+ }
+
+ function formatUTCHour12(d, p) {
+ return pad(d.getUTCHours() % 12 || 12, p, 2);
+ }
+
+ function formatUTCDayOfYear(d, p) {
+ return pad(1 + d3Time.utcDay.count(d3Time.utcYear(d), d), p, 3);
+ }
+
+ function formatUTCMilliseconds(d, p) {
+ return pad(d.getUTCMilliseconds(), p, 3);
+ }
+
+ function formatUTCMonthNumber(d, p) {
+ return pad(d.getUTCMonth() + 1, p, 2);
+ }
+
+ function formatUTCMinutes(d, p) {
+ return pad(d.getUTCMinutes(), p, 2);
+ }
+
+ function formatUTCSeconds(d, p) {
+ return pad(d.getUTCSeconds(), p, 2);
+ }
+
+ function formatUTCWeekNumberSunday(d, p) {
+ return pad(d3Time.utcSunday.count(d3Time.utcYear(d), d), p, 2);
+ }
+
+ function formatUTCWeekdayNumber(d) {
+ return d.getUTCDay();
+ }
+
+ function formatUTCWeekNumberMonday(d, p) {
+ return pad(d3Time.utcMonday.count(d3Time.utcYear(d), d), p, 2);
+ }
+
+ function formatUTCYear(d, p) {
+ return pad(d.getUTCFullYear() % 100, p, 2);
+ }
+
+ function formatUTCFullYear(d, p) {
+ return pad(d.getUTCFullYear() % 10000, p, 4);
+ }
+
+ function formatUTCZone() {
+ return "+0000";
+ }
+
+ function formatLiteralPercent() {
+ return "%";
+ }
+
+ var locale = locale$1({
+ dateTime: "%a %b %e %X %Y",
+ date: "%m/%d/%Y",
+ time: "%H:%M:%S",
+ periods: ["AM", "PM"],
+ days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
+ shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
+ months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
+ shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
+ });
+
+ var caES = locale$1({
+ dateTime: "%A, %e de %B de %Y, %X",
+ date: "%d/%m/%Y",
+ time: "%H:%M:%S",
+ periods: ["AM", "PM"],
+ days: ["diumenge", "dilluns", "dimarts", "dimecres", "dijous", "divendres", "dissabte"],
+ shortDays: ["dg.", "dl.", "dt.", "dc.", "dj.", "dv.", "ds."],
+ months: ["gener", "febrer", "març", "abril", "maig", "juny", "juliol", "agost", "setembre", "octubre", "novembre", "desembre"],
+ shortMonths: ["gen.", "febr.", "març", "abr.", "maig", "juny", "jul.", "ag.", "set.", "oct.", "nov.", "des."]
+ });
+
+ var deCH = locale$1({
+ dateTime: "%A, der %e. %B %Y, %X",
+ date: "%d.%m.%Y",
+ time: "%H:%M:%S",
+ periods: ["AM", "PM"], // unused
+ days: ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"],
+ shortDays: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"],
+ months: ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"],
+ shortMonths: ["Jan", "Feb", "Mrz", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"]
+ });
+
+ var deDE = locale$1({
+ dateTime: "%A, der %e. %B %Y, %X",
+ date: "%d.%m.%Y",
+ time: "%H:%M:%S",
+ periods: ["AM", "PM"], // unused
+ days: ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"],
+ shortDays: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"],
+ months: ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"],
+ shortMonths: ["Jan", "Feb", "Mrz", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"]
+ });
+
+ var enCA = locale$1({
+ dateTime: "%a %b %e %X %Y",
+ date: "%Y-%m-%d",
+ time: "%H:%M:%S",
+ periods: ["AM", "PM"],
+ days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
+ shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
+ months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
+ shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
+ });
+
+ var enGB = locale$1({
+ dateTime: "%a %e %b %X %Y",
+ date: "%d/%m/%Y",
+ time: "%H:%M:%S",
+ periods: ["AM", "PM"],
+ days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
+ shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
+ months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
+ shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
+ });
+
+ var esES = locale$1({
+ dateTime: "%A, %e de %B de %Y, %X",
+ date: "%d/%m/%Y",
+ time: "%H:%M:%S",
+ periods: ["AM", "PM"],
+ days: ["domingo", "lunes", "martes", "miércoles", "jueves", "viernes", "sábado"],
+ shortDays: ["dom", "lun", "mar", "mié", "jue", "vie", "sáb"],
+ months: ["enero", "febrero", "marzo", "abril", "mayo", "junio", "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre"],
+ shortMonths: ["ene", "feb", "mar", "abr", "may", "jun", "jul", "ago", "sep", "oct", "nov", "dic"]
+ });
+
+ var fiFI = locale$1({
+ dateTime: "%A, %-d. %Bta %Y klo %X",
+ date: "%-d.%-m.%Y",
+ time: "%H:%M:%S",
+ periods: ["a.m.", "p.m."],
+ days: ["sunnuntai", "maanantai", "tiistai", "keskiviikko", "torstai", "perjantai", "lauantai"],
+ shortDays: ["Su", "Ma", "Ti", "Ke", "To", "Pe", "La"],
+ months: ["tammikuu", "helmikuu", "maaliskuu", "huhtikuu", "toukokuu", "kesäkuu", "heinäkuu", "elokuu", "syyskuu", "lokakuu", "marraskuu", "joulukuu"],
+ shortMonths: ["Tammi", "Helmi", "Maalis", "Huhti", "Touko", "Kesä", "Heinä", "Elo", "Syys", "Loka", "Marras", "Joulu"]
+ });
+
+ var frCA = locale$1({
+ dateTime: "%a %e %b %Y %X",
+ date: "%Y-%m-%d",
+ time: "%H:%M:%S",
+ periods: ["", ""],
+ days: ["dimanche", "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi"],
+ shortDays: ["dim", "lun", "mar", "mer", "jeu", "ven", "sam"],
+ months: ["janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre"],
+ shortMonths: ["jan", "fév", "mar", "avr", "mai", "jui", "jul", "aoû", "sep", "oct", "nov", "déc"]
+ });
+
+ var frFR = locale$1({
+ dateTime: "%A, le %e %B %Y, %X",
+ date: "%d/%m/%Y",
+ time: "%H:%M:%S",
+ periods: ["AM", "PM"], // unused
+ days: ["dimanche", "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi"],
+ shortDays: ["dim.", "lun.", "mar.", "mer.", "jeu.", "ven.", "sam."],
+ months: ["janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre"],
+ shortMonths: ["janv.", "févr.", "mars", "avr.", "mai", "juin", "juil.", "août", "sept.", "oct.", "nov.", "déc."]
+ });
+
+ var heIL = locale$1({
+ dateTime: "%A, %e ב%B %Y %X",
+ date: "%d.%m.%Y",
+ time: "%H:%M:%S",
+ periods: ["AM", "PM"],
+ days: ["ראשון", "שני", "שלישי", "רביעי", "חמישי", "שישי", "שבת"],
+ shortDays: ["א׳", "ב׳", "ג׳", "ד׳", "ה׳", "ו׳", "ש׳"],
+ months: ["ינואר", "פברואר", "מרץ", "אפריל", "מאי", "יוני", "יולי", "אוגוסט", "ספטמבר", "אוקטובר", "נובמבר", "דצמבר"],
+ shortMonths: ["ינו׳", "פבר׳", "מרץ", "אפר׳", "מאי", "יוני", "יולי", "אוג׳", "ספט׳", "אוק׳", "נוב׳", "דצמ׳"]
+ });
+
+ var huHU = locale$1({
+ dateTime: "%Y. %B %-e., %A %X",
+ date: "%Y. %m. %d.",
+ time: "%H:%M:%S",
+ periods: ["de.", "du."], // unused
+ days: ["vasárnap", "hétfő", "kedd", "szerda", "csütörtök", "péntek", "szombat"],
+ shortDays: ["V", "H", "K", "Sze", "Cs", "P", "Szo"],
+ months: ["január", "február", "március", "április", "május", "június", "július", "augusztus", "szeptember", "október", "november", "december"],
+ shortMonths: ["jan.", "feb.", "már.", "ápr.", "máj.", "jún.", "júl.", "aug.", "szept.", "okt.", "nov.", "dec."]
+ });
+
+ var itIT = locale$1({
+ dateTime: "%A %e %B %Y, %X",
+ date: "%d/%m/%Y",
+ time: "%H:%M:%S",
+ periods: ["AM", "PM"], // unused
+ days: ["Domenica", "Lunedì", "Martedì", "Mercoledì", "Giovedì", "Venerdì", "Sabato"],
+ shortDays: ["Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab"],
+ months: ["Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre"],
+ shortMonths: ["Gen", "Feb", "Mar", "Apr", "Mag", "Giu", "Lug", "Ago", "Set", "Ott", "Nov", "Dic"]
+ });
+
+ var jaJP = locale$1({
+ dateTime: "%Y %b %e %a %X",
+ date: "%Y/%m/%d",
+ time: "%H:%M:%S",
+ periods: ["AM", "PM"],
+ days: ["日曜日", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日"],
+ shortDays: ["日", "月", "火", "水", "木", "金", "土"],
+ months: ["睦月", "如月", "弥生", "卯月", "皐月", "水無月", "文月", "葉月", "長月", "神無月", "霜月", "師走"],
+ shortMonths: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"]
+ });
+
+ var koKR = locale$1({
+ dateTime: "%Y/%m/%d %a %X",
+ date: "%Y/%m/%d",
+ time: "%H:%M:%S",
+ periods: ["오전", "오후"],
+ days: ["일요일", "월요일", "화요일", "수요일", "목요일", "금요일", "토요일"],
+ shortDays: ["일", "월", "화", "수", "목", "금", "토"],
+ months: ["1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월"],
+ shortMonths: ["1월", "2월", "3월", "4���", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월"]
+ });
+
+ var mkMK = locale$1({
+ dateTime: "%A, %e %B %Y г. %X",
+ date: "%d.%m.%Y",
+ time: "%H:%M:%S",
+ periods: ["AM", "PM"],
+ days: ["недела", "понеделник", "вторник", "среда", "четврток", "петок", "сабота"],
+ shortDays: ["нед", "пон", "вто", "сре", "чет", "пет", "саб"],
+ months: ["јануари", "февруари", "март", "април", "мај", "јуни", "јули", "август", "септември", "октомври", "ноември", "декември"],
+ shortMonths: ["јан", "фев", "мар", "апр", "мај", "јун", "јул", "авг", "сеп", "окт", "ное", "дек"]
+ });
+
+ var nlNL = locale$1({
+ dateTime: "%a %e %B %Y %T",
+ date: "%d-%m-%Y",
+ time: "%H:%M:%S",
+ periods: ["AM", "PM"], // unused
+ days: ["zondag", "maandag", "dinsdag", "woensdag", "donderdag", "vrijdag", "zaterdag"],
+ shortDays: ["zo", "ma", "di", "wo", "do", "vr", "za"],
+ months: ["januari", "februari", "maart", "april", "mei", "juni", "juli", "augustus", "september", "oktober", "november", "december"],
+ shortMonths: ["jan", "feb", "mrt", "apr", "mei", "jun", "jul", "aug", "sep", "okt", "nov", "dec"]
+ });
+
+ var plPL = locale$1({
+ dateTime: "%A, %e %B %Y, %X",
+ date: "%d/%m/%Y",
+ time: "%H:%M:%S",
+ periods: ["AM", "PM"], // unused
+ days: ["Niedziela", "Poniedziałek", "Wtorek", "Środa", "Czwartek", "Pi��tek", "Sobota"],
+ shortDays: ["Niedz.", "Pon.", "Wt.", "Śr.", "Czw.", "Pt.", "Sob."],
+ months: ["Styczeń", "Luty", "Marzec", "Kwiecień", "Maj", "Czerwiec", "Lipiec", "Sierpień", "Wrzesień", "Październik", "Listopad", "Grudzień"],
+ shortMonths: ["Stycz.", "Luty", "Marz.", "Kwie.", "Maj", "Czerw.", "Lipc.", "Sierp.", "Wrz.", "Paźdz.", "Listop.", "Grudz."]/* In Polish language abbraviated months are not commonly used so there is a dispute about the proper abbraviations. */
+ });
+
+ var ptBR = locale$1({
+ dateTime: "%A, %e de %B de %Y. %X",
+ date: "%d/%m/%Y",
+ time: "%H:%M:%S",
+ periods: ["AM", "PM"],
+ days: ["Domingo", "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado"],
+ shortDays: ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb"],
+ months: ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"],
+ shortMonths: ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"]
+ });
+
+ var ruRU = locale$1({
+ dateTime: "%A, %e %B %Y г. %X",
+ date: "%d.%m.%Y",
+ time: "%H:%M:%S",
+ periods: ["AM", "PM"],
+ days: ["воскресенье", "понедельник", "вторник", "среда", "четверг", "пятница", "суббота"],
+ shortDays: ["вс", "пн", "вт", "ср", "чт", "пт", "сб"],
+ months: ["января", "февраля", "марта", "апреля", "мая", "июня", "июля", "августа", "сентября", "октября", "ноября", "декабря"],
+ shortMonths: ["янв", "фев", "мар", "апр", "май", "июн", "июл", "авг", "сен", "окт", "ноя", "дек"]
+ });
+
+ var svSE = locale$1({
+ dateTime: "%A den %d %B %Y %X",
+ date: "%Y-%m-%d",
+ time: "%H:%M:%S",
+ periods: ["fm", "em"],
+ days: ["Söndag", "Måndag", "Tisdag", "Onsdag", "Torsdag", "Fredag", "Lördag"],
+ shortDays: ["Sön", "Mån", "Tis", "Ons", "Tor", "Fre", "Lör"],
+ months: ["Januari", "Februari", "Mars", "April", "Maj", "Juni", "Juli", "Augusti", "September", "Oktober", "November", "December"],
+ shortMonths: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"]
+ });
+
+ var zhCN = locale$1({
+ dateTime: "%a %b %e %X %Y",
+ date: "%Y/%-m/%-d",
+ time: "%H:%M:%S",
+ periods: ["上午", "下午"],
+ days: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],
+ shortDays: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],
+ months: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
+ shortMonths: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"]
+ });
+
+ var isoSpecifier = "%Y-%m-%dT%H:%M:%S.%LZ";
+
+ function formatIsoNative(date) {
+ return date.toISOString();
+ }
+
+ formatIsoNative.parse = function(string) {
+ var date = new Date(string);
+ return isNaN(date) ? null : date;
+ };
+
+ formatIsoNative.toString = function() {
+ return isoSpecifier;
+ };
+
+ var formatIso = Date.prototype.toISOString && +new Date("2000-01-01T00:00:00.000Z")
+ ? formatIsoNative
+ : locale.utcFormat(isoSpecifier);
+
+ var format = locale.format;
+ var utcFormat = locale.utcFormat;
+
+ var version = "0.2.1";
+
+ exports.version = version;
+ exports.format = format;
+ exports.utcFormat = utcFormat;
+ exports.locale = locale$1;
+ exports.localeCaEs = caES;
+ exports.localeDeCh = deCH;
+ exports.localeDeDe = deDE;
+ exports.localeEnCa = enCA;
+ exports.localeEnGb = enGB;
+ exports.localeEnUs = locale;
+ exports.localeEsEs = esES;
+ exports.localeFiFi = fiFI;
+ exports.localeFrCa = frCA;
+ exports.localeFrFr = frFR;
+ exports.localeHeIl = heIL;
+ exports.localeHuHu = huHU;
+ exports.localeItIt = itIT;
+ exports.localeJaJp = jaJP;
+ exports.localeKoKr = koKR;
+ exports.localeMkMk = mkMK;
+ exports.localeNlNl = nlNL;
+ exports.localePlPl = plPL;
+ exports.localePtBr = ptBR;
+ exports.localeRuRu = ruRU;
+ exports.localeSvSe = svSE;
+ exports.localeZhCn = zhCN;
+ exports.isoFormat = formatIso;
+
+}));
+},{"d3-time":6}],6:[function(require,module,exports){
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
+ typeof define === 'function' && define.amd ? define('d3-time', ['exports'], factory) :
+ factory((global.d3_time = {}));
+}(this, function (exports) { 'use strict';
+
+ var t0 = new Date;
+ var t1 = new Date;
+ function newInterval(floori, offseti, count, field) {
+
+ function interval(date) {
+ return floori(date = new Date(+date)), date;
+ }
+
+ interval.floor = interval;
+
+ interval.round = function(date) {
+ var d0 = new Date(+date),
+ d1 = new Date(date - 1);
+ floori(d0), floori(d1), offseti(d1, 1);
+ return date - d0 < d1 - date ? d0 : d1;
+ };
+
+ interval.ceil = function(date) {
+ return floori(date = new Date(date - 1)), offseti(date, 1), date;
+ };
+
+ interval.offset = function(date, step) {
+ return offseti(date = new Date(+date), step == null ? 1 : Math.floor(step)), date;
+ };
+
+ interval.range = function(start, stop, step) {
+ var range = [];
+ start = new Date(start - 1);
+ stop = new Date(+stop);
+ step = step == null ? 1 : Math.floor(step);
+ if (!(start < stop) || !(step > 0)) return range; // also handles Invalid Date
+ offseti(start, 1), floori(start);
+ if (start < stop) range.push(new Date(+start));
+ while (offseti(start, step), floori(start), start < stop) range.push(new Date(+start));
+ return range;
+ };
+
+ interval.filter = function(test) {
+ return newInterval(function(date) {
+ while (floori(date), !test(date)) date.setTime(date - 1);
+ }, function(date, step) {
+ while (--step >= 0) while (offseti(date, 1), !test(date));
+ });
+ };
+
+ if (count) {
+ interval.count = function(start, end) {
+ t0.setTime(+start), t1.setTime(+end);
+ floori(t0), floori(t1);
+ return Math.floor(count(t0, t1));
+ };
+
+ interval.every = function(step) {
+ step = Math.floor(step);
+ return !isFinite(step) || !(step > 0) ? null
+ : !(step > 1) ? interval
+ : interval.filter(field
+ ? function(d) { return field(d) % step === 0; }
+ : function(d) { return interval.count(0, d) % step === 0; });
+ };
+ }
+
+ return interval;
+ };
+
+ var millisecond = newInterval(function() {
+ // noop
+ }, function(date, step) {
+ date.setTime(+date + step);
+ }, function(start, end) {
+ return end - start;
+ });
+
+ // An optimized implementation for this simple case.
+ millisecond.every = function(k) {
+ k = Math.floor(k);
+ if (!isFinite(k) || !(k > 0)) return null;
+ if (!(k > 1)) return millisecond;
+ return newInterval(function(date) {
+ date.setTime(Math.floor(date / k) * k);
+ }, function(date, step) {
+ date.setTime(+date + step * k);
+ }, function(start, end) {
+ return (end - start) / k;
+ });
+ };
+
+ var second = newInterval(function(date) {
+ date.setMilliseconds(0);
+ }, function(date, step) {
+ date.setTime(+date + step * 1e3);
+ }, function(start, end) {
+ return (end - start) / 1e3;
+ }, function(date) {
+ return date.getSeconds();
+ });
+
+ var minute = newInterval(function(date) {
+ date.setSeconds(0, 0);
+ }, function(date, step) {
+ date.setTime(+date + step * 6e4);
+ }, function(start, end) {
+ return (end - start) / 6e4;
+ }, function(date) {
+ return date.getMinutes();
+ });
+
+ var hour = newInterval(function(date) {
+ date.setMinutes(0, 0, 0);
+ }, function(date, step) {
+ date.setTime(+date + step * 36e5);
+ }, function(start, end) {
+ return (end - start) / 36e5;
+ }, function(date) {
+ return date.getHours();
+ });
+
+ var day = newInterval(function(date) {
+ date.setHours(0, 0, 0, 0);
+ }, function(date, step) {
+ date.setDate(date.getDate() + step);
+ }, function(start, end) {
+ return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * 6e4) / 864e5;
+ }, function(date) {
+ return date.getDate() - 1;
+ });
+
+ function weekday(i) {
+ return newInterval(function(date) {
+ date.setHours(0, 0, 0, 0);
+ date.setDate(date.getDate() - (date.getDay() + 7 - i) % 7);
+ }, function(date, step) {
+ date.setDate(date.getDate() + step * 7);
+ }, function(start, end) {
+ return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * 6e4) / 6048e5;
+ });
+ }
+
+ var sunday = weekday(0);
+ var monday = weekday(1);
+ var tuesday = weekday(2);
+ var wednesday = weekday(3);
+ var thursday = weekday(4);
+ var friday = weekday(5);
+ var saturday = weekday(6);
+
+ var month = newInterval(function(date) {
+ date.setHours(0, 0, 0, 0);
+ date.setDate(1);
+ }, function(date, step) {
+ date.setMonth(date.getMonth() + step);
+ }, function(start, end) {
+ return end.getMonth() - start.getMonth() + (end.getFullYear() - start.getFullYear()) * 12;
+ }, function(date) {
+ return date.getMonth();
+ });
+
+ var year = newInterval(function(date) {
+ date.setHours(0, 0, 0, 0);
+ date.setMonth(0, 1);
+ }, function(date, step) {
+ date.setFullYear(date.getFullYear() + step);
+ }, function(start, end) {
+ return end.getFullYear() - start.getFullYear();
+ }, function(date) {
+ return date.getFullYear();
+ });
+
+ var utcSecond = newInterval(function(date) {
+ date.setUTCMilliseconds(0);
+ }, function(date, step) {
+ date.setTime(+date + step * 1e3);
+ }, function(start, end) {
+ return (end - start) / 1e3;
+ }, function(date) {
+ return date.getUTCSeconds();
+ });
+
+ var utcMinute = newInterval(function(date) {
+ date.setUTCSeconds(0, 0);
+ }, function(date, step) {
+ date.setTime(+date + step * 6e4);
+ }, function(start, end) {
+ return (end - start) / 6e4;
+ }, function(date) {
+ return date.getUTCMinutes();
+ });
+
+ var utcHour = newInterval(function(date) {
+ date.setUTCMinutes(0, 0, 0);
+ }, function(date, step) {
+ date.setTime(+date + step * 36e5);
+ }, function(start, end) {
+ return (end - start) / 36e5;
+ }, function(date) {
+ return date.getUTCHours();
+ });
+
+ var utcDay = newInterval(function(date) {
+ date.setUTCHours(0, 0, 0, 0);
+ }, function(date, step) {
+ date.setUTCDate(date.getUTCDate() + step);
+ }, function(start, end) {
+ return (end - start) / 864e5;
+ }, function(date) {
+ return date.getUTCDate() - 1;
+ });
+
+ function utcWeekday(i) {
+ return newInterval(function(date) {
+ date.setUTCHours(0, 0, 0, 0);
+ date.setUTCDate(date.getUTCDate() - (date.getUTCDay() + 7 - i) % 7);
+ }, function(date, step) {
+ date.setUTCDate(date.getUTCDate() + step * 7);
+ }, function(start, end) {
+ return (end - start) / 6048e5;
+ });
+ }
+
+ var utcSunday = utcWeekday(0);
+ var utcMonday = utcWeekday(1);
+ var utcTuesday = utcWeekday(2);
+ var utcWednesday = utcWeekday(3);
+ var utcThursday = utcWeekday(4);
+ var utcFriday = utcWeekday(5);
+ var utcSaturday = utcWeekday(6);
+
+ var utcMonth = newInterval(function(date) {
+ date.setUTCHours(0, 0, 0, 0);
+ date.setUTCDate(1);
+ }, function(date, step) {
+ date.setUTCMonth(date.getUTCMonth() + step);
+ }, function(start, end) {
+ return end.getUTCMonth() - start.getUTCMonth() + (end.getUTCFullYear() - start.getUTCFullYear()) * 12;
+ }, function(date) {
+ return date.getUTCMonth();
+ });
+
+ var utcYear = newInterval(function(date) {
+ date.setUTCHours(0, 0, 0, 0);
+ date.setUTCMonth(0, 1);
+ }, function(date, step) {
+ date.setUTCFullYear(date.getUTCFullYear() + step);
+ }, function(start, end) {
+ return end.getUTCFullYear() - start.getUTCFullYear();
+ }, function(date) {
+ return date.getUTCFullYear();
+ });
+
+ var milliseconds = millisecond.range;
+ var seconds = second.range;
+ var minutes = minute.range;
+ var hours = hour.range;
+ var days = day.range;
+ var sundays = sunday.range;
+ var mondays = monday.range;
+ var tuesdays = tuesday.range;
+ var wednesdays = wednesday.range;
+ var thursdays = thursday.range;
+ var fridays = friday.range;
+ var saturdays = saturday.range;
+ var weeks = sunday.range;
+ var months = month.range;
+ var years = year.range;
+
+ var utcMillisecond = millisecond;
+ var utcMilliseconds = milliseconds;
+ var utcSeconds = utcSecond.range;
+ var utcMinutes = utcMinute.range;
+ var utcHours = utcHour.range;
+ var utcDays = utcDay.range;
+ var utcSundays = utcSunday.range;
+ var utcMondays = utcMonday.range;
+ var utcTuesdays = utcTuesday.range;
+ var utcWednesdays = utcWednesday.range;
+ var utcThursdays = utcThursday.range;
+ var utcFridays = utcFriday.range;
+ var utcSaturdays = utcSaturday.range;
+ var utcWeeks = utcSunday.range;
+ var utcMonths = utcMonth.range;
+ var utcYears = utcYear.range;
+
+ var version = "0.1.1";
+
+ exports.version = version;
+ exports.milliseconds = milliseconds;
+ exports.seconds = seconds;
+ exports.minutes = minutes;
+ exports.hours = hours;
+ exports.days = days;
+ exports.sundays = sundays;
+ exports.mondays = mondays;
+ exports.tuesdays = tuesdays;
+ exports.wednesdays = wednesdays;
+ exports.thursdays = thursdays;
+ exports.fridays = fridays;
+ exports.saturdays = saturdays;
+ exports.weeks = weeks;
+ exports.months = months;
+ exports.years = years;
+ exports.utcMillisecond = utcMillisecond;
+ exports.utcMilliseconds = utcMilliseconds;
+ exports.utcSeconds = utcSeconds;
+ exports.utcMinutes = utcMinutes;
+ exports.utcHours = utcHours;
+ exports.utcDays = utcDays;
+ exports.utcSundays = utcSundays;
+ exports.utcMondays = utcMondays;
+ exports.utcTuesdays = utcTuesdays;
+ exports.utcWednesdays = utcWednesdays;
+ exports.utcThursdays = utcThursdays;
+ exports.utcFridays = utcFridays;
+ exports.utcSaturdays = utcSaturdays;
+ exports.utcWeeks = utcWeeks;
+ exports.utcMonths = utcMonths;
+ exports.utcYears = utcYears;
+ exports.millisecond = millisecond;
+ exports.second = second;
+ exports.minute = minute;
+ exports.hour = hour;
+ exports.day = day;
+ exports.sunday = sunday;
+ exports.monday = monday;
+ exports.tuesday = tuesday;
+ exports.wednesday = wednesday;
+ exports.thursday = thursday;
+ exports.friday = friday;
+ exports.saturday = saturday;
+ exports.week = sunday;
+ exports.month = month;
+ exports.year = year;
+ exports.utcSecond = utcSecond;
+ exports.utcMinute = utcMinute;
+ exports.utcHour = utcHour;
+ exports.utcDay = utcDay;
+ exports.utcSunday = utcSunday;
+ exports.utcMonday = utcMonday;
+ exports.utcTuesday = utcTuesday;
+ exports.utcWednesday = utcWednesday;
+ exports.utcThursday = utcThursday;
+ exports.utcFriday = utcFriday;
+ exports.utcSaturday = utcSaturday;
+ exports.utcWeek = utcSunday;
+ exports.utcMonth = utcMonth;
+ exports.utcYear = utcYear;
+ exports.interval = newInterval;
+
+}));
+},{}],7:[function(require,module,exports){
+var util = require('./util'),
+ time = require('./time'),
+ utc = time.utc;
+
+var u = module.exports;
+
+u.$year = util.$func('year', time.year.unit);
+u.$month = util.$func('month', time.months.unit);
+u.$date = util.$func('date', time.dates.unit);
+u.$day = util.$func('day', time.weekdays.unit);
+u.$hour = util.$func('hour', time.hours.unit);
+u.$minute = util.$func('minute', time.minutes.unit);
+u.$second = util.$func('second', time.seconds.unit);
+
+u.$utcYear = util.$func('utcYear', utc.year.unit);
+u.$utcMonth = util.$func('utcMonth', utc.months.unit);
+u.$utcDate = util.$func('utcDate', utc.dates.unit);
+u.$utcDay = util.$func('utcDay', utc.weekdays.unit);
+u.$utcHour = util.$func('utcHour', utc.hours.unit);
+u.$utcMinute = util.$func('utcMinute', utc.minutes.unit);
+u.$utcSecond = util.$func('utcSecond', utc.seconds.unit);
+
+},{"./time":29,"./util":30}],8:[function(require,module,exports){
+var util = require('../util'),
+ Measures = require('./measures'),
+ Collector = require('./collector');
+
+function Aggregator() {
+ this._cells = {};
+ this._aggr = [];
+ this._stream = false;
+}
+
+var Flags = Aggregator.Flags = {
+ ADD_CELL: 1,
+ MOD_CELL: 2
+};
+
+var proto = Aggregator.prototype;
+
+// Parameters
+
+proto.stream = function(v) {
+ if (v == null) return this._stream;
+ this._stream = !!v;
+ this._aggr = [];
+ return this;
+};
+
+// key accessor to use for streaming removes
+proto.key = function(key) {
+ if (key == null) return this._key;
+ this._key = util.$(key);
+ return this;
+};
+
+// Input: array of objects of the form
+// {name: string, get: function}
+proto.groupby = function(dims) {
+ this._dims = util.array(dims).map(function(d, i) {
+ d = util.isString(d) ? {name: d, get: util.$(d)}
+ : util.isFunction(d) ? {name: util.name(d) || d.name || ('_' + i), get: d}
+ : (d.name && util.isFunction(d.get)) ? d : null;
+ if (d == null) throw 'Invalid groupby argument: ' + d;
+ return d;
+ });
+ return this.clear();
+};
+
+// Input: array of objects of the form
+// {name: string, ops: [string, ...]}
+proto.summarize = function(fields) {
+ fields = summarize_args(fields);
+ this._count = true;
+ var aggr = (this._aggr = []),
+ m, f, i, j, op, as, get;
+
+ for (i=0; i 0) {
+ // consolidate collector values
+ if (cell.collect) {
+ cell.data.values();
+ }
+ // update tuple properties
+ for (i=0; i 0) {
+ m[a[i]] -= 1;
+ } else {
+ x[j++] = a[i];
+ }
+ }
+ } else if (k) {
+ // has unique key field, so use that
+ m = util.toMap(r, k);
+ for (i=0, j=0, n=a.length; i 1 ? this.dev / (this.valid-1) : 0',
+ req: ['mean'], idx: 1
+ }),
+ 'variancep': measure({
+ name: 'variancep',
+ set: 'this.valid > 1 ? this.dev / this.valid : 0',
+ req: ['variance'], idx: 2
+ }),
+ 'stdev': measure({
+ name: 'stdev',
+ set: 'this.valid > 1 ? Math.sqrt(this.dev / (this.valid-1)) : 0',
+ req: ['variance'], idx: 2
+ }),
+ 'stdevp': measure({
+ name: 'stdevp',
+ set: 'this.valid > 1 ? Math.sqrt(this.dev / this.valid) : 0',
+ req: ['variance'], idx: 2
+ }),
+ 'median': measure({
+ name: 'median',
+ set: 'cell.data.q2(this.get)',
+ req: ['values'], idx: 3
+ }),
+ 'q1': measure({
+ name: 'q1',
+ set: 'cell.data.q1(this.get)',
+ req: ['values'], idx: 3
+ }),
+ 'q3': measure({
+ name: 'q3',
+ set: 'cell.data.q3(this.get)',
+ req: ['values'], idx: 3
+ }),
+ 'distinct': measure({
+ name: 'distinct',
+ set: 'this.distinct(cell.data.values(), this.get)',
+ req: ['values'], idx: 3
+ }),
+ 'argmin': measure({
+ name: 'argmin',
+ add: 'if (v < this.min) this.argmin = t;',
+ rem: 'if (v <= this.min) this.argmin = null;',
+ set: 'this.argmin = this.argmin || cell.data.argmin(this.get)',
+ req: ['min'], str: ['values'], idx: 3
+ }),
+ 'argmax': measure({
+ name: 'argmax',
+ add: 'if (v > this.max) this.argmax = t;',
+ rem: 'if (v >= this.max) this.argmax = null;',
+ set: 'this.argmax = this.argmax || cell.data.argmax(this.get)',
+ req: ['max'], str: ['values'], idx: 3
+ }),
+ 'min': measure({
+ name: 'min',
+ init: 'this.min = +Infinity;',
+ add: 'if (v < this.min) this.min = v;',
+ rem: 'if (v <= this.min) this.min = NaN;',
+ set: 'this.min = (isNaN(this.min) ? cell.data.min(this.get) : this.min)',
+ str: ['values'], idx: 4
+ }),
+ 'max': measure({
+ name: 'max',
+ init: 'this.max = -Infinity;',
+ add: 'if (v > this.max) this.max = v;',
+ rem: 'if (v >= this.max) this.max = NaN;',
+ set: 'this.max = (isNaN(this.max) ? cell.data.max(this.get) : this.max)',
+ str: ['values'], idx: 4
+ }),
+ 'modeskew': measure({
+ name: 'modeskew',
+ set: 'this.dev===0 ? 0 : (this.mean - cell.data.q2(this.get)) / Math.sqrt(this.dev/(this.valid-1))',
+ req: ['mean', 'stdev', 'median'], idx: 5
+ })
+};
+
+function measure(base) {
+ return function(out) {
+ var m = util.extend({init:'', add:'', rem:'', idx:0}, base);
+ m.out = out || base.name;
+ return m;
+ };
+}
+
+function resolve(agg, stream) {
+ function collect(m, a) {
+ function helper(r) { if (!m[r]) collect(m, m[r] = types[r]()); }
+ if (a.req) a.req.forEach(helper);
+ if (stream && a.str) a.str.forEach(helper);
+ return m;
+ }
+ var map = agg.reduce(
+ collect,
+ agg.reduce(function(m, a) { return (m[a.name] = a, m); }, {})
+ );
+ return util.vals(map).sort(function(a, b) { return a.idx - b.idx; });
+}
+
+function create(agg, stream, accessor, mutator) {
+ var all = resolve(agg, stream),
+ ctr = 'this.cell = cell; this.tuple = t; this.valid = 0; this.missing = 0;',
+ add = 'if (v==null) this.missing++; if (!this.isValid(v)) return; ++this.valid;',
+ rem = 'if (v==null) this.missing--; if (!this.isValid(v)) return; --this.valid;',
+ set = 'var t = this.tuple; var cell = this.cell;';
+
+ all.forEach(function(a) {
+ if (a.idx < 0) {
+ ctr = a.init + ctr;
+ add = a.add + add;
+ rem = a.rem + rem;
+ } else {
+ ctr += a.init;
+ add += a.add;
+ rem += a.rem;
+ }
+ });
+ agg.slice()
+ .sort(function(a, b) { return a.idx - b.idx; })
+ .forEach(function(a) {
+ set += 'this.assign(t,\''+a.out+'\','+a.set+');';
+ });
+ set += 'return t;';
+
+ /* jshint evil: true */
+ ctr = Function('cell', 't', ctr);
+ ctr.prototype.assign = mutator;
+ ctr.prototype.add = Function('t', 'var v = this.get(t);' + add);
+ ctr.prototype.rem = Function('t', 'var v = this.get(t);' + rem);
+ ctr.prototype.set = Function(set);
+ ctr.prototype.get = accessor;
+ ctr.prototype.distinct = require('../stats').count.distinct;
+ ctr.prototype.isValid = util.isValid;
+ ctr.fields = agg.map(util.$('out'));
+ return ctr;
+}
+
+types.create = create;
+module.exports = types;
+
+},{"../stats":27,"../util":30}],12:[function(require,module,exports){
+var util = require('../util'),
+ time = require('../time'),
+ EPSILON = 1e-15;
+
+function bins(opt) {
+ if (!opt) { throw Error("Missing binning options."); }
+
+ // determine range
+ var maxb = opt.maxbins || 15,
+ base = opt.base || 10,
+ logb = Math.log(base),
+ div = opt.div || [5, 2],
+ min = opt.min,
+ max = opt.max,
+ span = max - min,
+ step, level, minstep, precision, v, i, eps;
+
+ if (opt.step) {
+ // if step size is explicitly given, use that
+ step = opt.step;
+ } else if (opt.steps) {
+ // if provided, limit choice to acceptable step sizes
+ step = opt.steps[Math.min(
+ opt.steps.length - 1,
+ bisect(opt.steps, span/maxb, 0, opt.steps.length)
+ )];
+ } else {
+ // else use span to determine step size
+ level = Math.ceil(Math.log(maxb) / logb);
+ minstep = opt.minstep || 0;
+ step = Math.max(
+ minstep,
+ Math.pow(base, Math.round(Math.log(span) / logb) - level)
+ );
+
+ // increase step size if too many bins
+ while (Math.ceil(span/step) > maxb) { step *= base; }
+
+ // decrease step size if allowed
+ for (i=0; i= minstep && span / v <= maxb) step = v;
+ }
+ }
+
+ // update precision, min and max
+ v = Math.log(step);
+ precision = v >= 0 ? 0 : ~~(-v / logb) + 1;
+ eps = Math.pow(base, -precision - 1);
+ min = Math.min(min, Math.floor(min / step + eps) * step);
+ max = Math.ceil(max / step) * step;
+
+ return {
+ start: min,
+ stop: max,
+ step: step,
+ unit: {precision: precision},
+ value: value,
+ index: index
+ };
+}
+
+function bisect(a, x, lo, hi) {
+ while (lo < hi) {
+ var mid = lo + hi >>> 1;
+ if (util.cmp(a[mid], x) < 0) { lo = mid + 1; }
+ else { hi = mid; }
+ }
+ return lo;
+}
+
+function value(v) {
+ return this.step * Math.floor(v / this.step + EPSILON);
+}
+
+function index(v) {
+ return Math.floor((v - this.start) / this.step + EPSILON);
+}
+
+function date_value(v) {
+ return this.unit.date(value.call(this, v));
+}
+
+function date_index(v) {
+ return index.call(this, this.unit.unit(v));
+}
+
+bins.date = function(opt) {
+ if (!opt) { throw Error("Missing date binning options."); }
+
+ // find time step, then bin
+ var units = opt.utc ? time.utc : time,
+ dmin = opt.min,
+ dmax = opt.max,
+ maxb = opt.maxbins || 20,
+ minb = opt.minbins || 4,
+ span = (+dmax) - (+dmin),
+ unit = opt.unit ? units[opt.unit] : units.find(span, minb, maxb),
+ spec = bins({
+ min: unit.min != null ? unit.min : unit.unit(dmin),
+ max: unit.max != null ? unit.max : unit.unit(dmax),
+ maxbins: maxb,
+ minstep: unit.minstep,
+ steps: unit.step
+ });
+
+ spec.unit = unit;
+ spec.index = date_index;
+ if (!opt.raw) spec.value = date_value;
+ return spec;
+};
+
+module.exports = bins;
+
+},{"../time":29,"../util":30}],13:[function(require,module,exports){
+var bins = require('./bins'),
+ gen = require('../generate'),
+ type = require('../import/type'),
+ util = require('../util'),
+ stats = require('../stats');
+
+var qtype = {
+ 'integer': 1,
+ 'number': 1,
+ 'date': 1
+};
+
+function $bin(values, f, opt) {
+ opt = options(values, f, opt);
+ var b = spec(opt);
+ return !b ? (opt.accessor || util.identity) :
+ util.$func('bin', b.unit.unit ?
+ function(x) { return b.value(b.unit.unit(x)); } :
+ function(x) { return b.value(x); }
+ )(opt.accessor);
+}
+
+function histogram(values, f, opt) {
+ opt = options(values, f, opt);
+ var b = spec(opt);
+ return b ?
+ numerical(values, opt.accessor, b) :
+ categorical(values, opt.accessor, opt && opt.sort);
+}
+
+function spec(opt) {
+ var t = opt.type, b = null;
+ if (t == null || qtype[t]) {
+ if (t === 'integer' && opt.minstep == null) opt.minstep = 1;
+ b = (t === 'date') ? bins.date(opt) : bins(opt);
+ }
+ return b;
+}
+
+function options() {
+ var a = arguments,
+ i = 0,
+ values = util.isArray(a[i]) ? a[i++] : null,
+ f = util.isFunction(a[i]) || util.isString(a[i]) ? util.$(a[i++]) : null,
+ opt = util.extend({}, a[i]);
+
+ if (values) {
+ opt.type = opt.type || type(values, f);
+ if (qtype[opt.type]) {
+ var ext = stats.extent(values, f);
+ opt = util.extend({min: ext[0], max: ext[1]}, opt);
+ }
+ }
+ if (f) { opt.accessor = f; }
+ return opt;
+}
+
+function numerical(values, f, b) {
+ var h = gen.range(b.start, b.stop + b.step/2, b.step)
+ .map(function(v) { return {value: b.value(v), count: 0}; });
+
+ for (var i=0, v, j; i= h.length || !isFinite(j)) continue;
+ h[j].count += 1;
+ }
+ }
+ h.bins = b;
+ return h;
+}
+
+function categorical(values, f, sort) {
+ var u = stats.unique(values, f),
+ c = stats.count.map(values, f);
+ return u.map(function(k) { return {value: k, count: c[k]}; })
+ .sort(util.comparator(sort ? '-count' : '+value'));
+}
+
+module.exports = {
+ $bin: $bin,
+ histogram: histogram
+};
+
+},{"../generate":16,"../import/type":25,"../stats":27,"../util":30,"./bins":12}],14:[function(require,module,exports){
+var util = require('./util'),
+ type = require('./import/type'),
+ stats = require('./stats'),
+ template = require('./template');
+
+module.exports = {
+ table: formatTable, // format a data table
+ summary: formatSummary // format a data table summary
+};
+
+var FMT = {
+ 'date': '|time:"%m/%d/%Y %H:%M:%S"',
+ 'number': '|number:".4f"',
+ 'integer': '|number:"d"'
+};
+
+var POS = {
+ 'number': 'left',
+ 'integer': 'left'
+};
+
+function formatTable(data, opt) {
+ opt = util.extend({separator:' ', minwidth: 8, maxwidth: 15}, opt);
+ var fields = opt.fields || util.keys(data[0]),
+ types = type.all(data);
+
+ if (opt.start || opt.limit) {
+ var a = opt.start || 0,
+ b = opt.limit ? a + opt.limit : data.length;
+ data = data.slice(a, b);
+ }
+
+ // determine char width of fields
+ var lens = fields.map(function(name) {
+ var format = FMT[types[name]] || '',
+ t = template('{{' + name + format + '}}'),
+ l = stats.max(data, function(x) { return t(x).length; });
+ l = Math.max(Math.min(name.length, opt.minwidth), l);
+ return opt.maxwidth > 0 ? Math.min(l, opt.maxwidth) : l;
+ });
+
+ // print header row
+ var head = fields.map(function(name, i) {
+ return util.truncate(util.pad(name, lens[i], 'center'), lens[i]);
+ }).join(opt.separator);
+
+ // build template function for each row
+ var tmpl = template(fields.map(function(name, i) {
+ return '{{' +
+ name +
+ (FMT[types[name]] || '') +
+ ('|pad:' + lens[i] + ',' + (POS[types[name]] || 'right')) +
+ ('|truncate:' + lens[i]) +
+ '}}';
+ }).join(opt.separator));
+
+ // print table
+ return head + "\n" + data.map(tmpl).join('\n');
+}
+
+function formatSummary(s) {
+ s = s ? s.__summary__ ? s : stats.summary(s) : this;
+ var str = [], i, n;
+ for (i=0, n=s.length; i 4 && 'locale' + (
+ l[0].toUpperCase() + l[1].toLowerCase() +
+ l[3].toUpperCase() + l[4].toLowerCase()
+ );
+}
+
+function numberLocale(l) {
+ var f = util.isString(l) ? d3_numberF[localeRef(l)] : d3_numberF.locale(l);
+ if (f == null) throw Error('Unrecognized locale: ' + l);
+ numberF = f;
+}
+
+function timeLocale(l) {
+ var f = util.isString(l) ? d3_timeF[localeRef(l)] : d3_timeF.locale(l);
+ if (f == null) throw Error('Unrecognized locale: ' + l);
+ timeF = f;
+ monthFull = monthAbbr = dayFull = dayAbbr = null;
+}
+
+// -- Number Formatting ----
+
+var e10 = Math.sqrt(50),
+ e5 = Math.sqrt(10),
+ e2 = Math.sqrt(2);
+
+function linearRange(domain, count) {
+ if (!domain.length) domain = [0];
+ if (count == null) count = 10;
+
+ var start = domain[0],
+ stop = domain[domain.length - 1];
+
+ if (stop < start) { error = stop; stop = start; start = error; }
+
+ var span = (stop - start) || (count = 1, start || stop || 1),
+ step = Math.pow(10, Math.floor(Math.log(span / count) / Math.LN10)),
+ error = span / count / step;
+
+ // Filter ticks to get closer to the desired count.
+ if (error >= e10) step *= 10;
+ else if (error >= e5) step *= 5;
+ else if (error >= e2) step *= 2;
+
+ // Round start and stop values to step interval.
+ return [
+ Math.ceil(start / step) * step,
+ Math.floor(stop / step) * step + step / 2, // inclusive
+ step
+ ];
+}
+
+function trimZero(f, decimal) {
+ return function(x) {
+ var s = f(x),
+ n = s.indexOf(decimal);
+ if (n < 0) return s;
+
+ var idx = rightmostDigit(s, n),
+ end = idx < s.length ? s.slice(idx) : '';
+
+ while (--idx > n) {
+ if (s[idx] !== '0') { ++idx; break; }
+ }
+ return s.slice(0, idx) + end;
+ };
+}
+
+function rightmostDigit(s, n) {
+ var i = s.lastIndexOf('e'), c;
+ if (i > 0) return i;
+ for (i=s.length; --i > n;) {
+ c = s.charCodeAt(i);
+ if (c >= 48 && c <= 57) return i+1; // is digit
+ }
+}
+
+function autoNumberFormat(f) {
+ var decimal = numberF.format('.1f')(1)[1]; // get decimal char
+ if (f == null) f = ',';
+ f = d3_numberF.formatSpecifier(f);
+ if (f.precision == null) f.precision = 12;
+ switch (f.type) {
+ case '%': f.precision -= 2; break;
+ case 'e': f.precision -= 1; break;
+ }
+ return trimZero(numberF.format(f), decimal);
+}
+
+function linearNumberFormat(domain, count, f) {
+ var range = linearRange(domain, count);
+
+ if (f == null) f = ',f';
+
+ switch (f = d3_numberF.formatSpecifier(f), f.type) {
+ case 's': {
+ var value = Math.max(Math.abs(range[0]), Math.abs(range[1]));
+ if (f.precision == null) f.precision = d3_numberF.precisionPrefix(range[2], value);
+ return numberF.formatPrefix(f, value);
+ }
+ case '':
+ case 'e':
+ case 'g':
+ case 'p':
+ case 'r': {
+ if (f.precision == null) f.precision = d3_numberF.precisionRound(range[2], Math.max(Math.abs(range[0]), Math.abs(range[1]))) - (f.type === 'e');
+ break;
+ }
+ case 'f':
+ case '%': {
+ if (f.precision == null) f.precision = d3_numberF.precisionFixed(range[2]) - 2 * (f.type === '%');
+ break;
+ }
+ }
+ return numberF.format(f);
+}
+
+// -- Datetime Formatting ----
+
+function timeAutoFormat() {
+ var f = timeF.format,
+ formatMillisecond = f('.%L'),
+ formatSecond = f(':%S'),
+ formatMinute = f('%I:%M'),
+ formatHour = f('%I %p'),
+ formatDay = f('%a %d'),
+ formatWeek = f('%b %d'),
+ formatMonth = f('%B'),
+ formatYear = f('%Y');
+
+ return function(date) {
+ var d = +date;
+ return (d3_time.second(date) < d ? formatMillisecond
+ : d3_time.minute(date) < d ? formatSecond
+ : d3_time.hour(date) < d ? formatMinute
+ : d3_time.day(date) < d ? formatHour
+ : d3_time.month(date) < d ?
+ (d3_time.week(date) < d ? formatDay : formatWeek)
+ : d3_time.year(date) < d ? formatMonth
+ : formatYear)(date);
+ };
+}
+
+function utcAutoFormat() {
+ var f = timeF.utcFormat,
+ formatMillisecond = f('.%L'),
+ formatSecond = f(':%S'),
+ formatMinute = f('%I:%M'),
+ formatHour = f('%I %p'),
+ formatDay = f('%a %d'),
+ formatWeek = f('%b %d'),
+ formatMonth = f('%B'),
+ formatYear = f('%Y');
+
+ return function(date) {
+ var d = +date;
+ return (d3_time.utcSecond(date) < d ? formatMillisecond
+ : d3_time.utcMinute(date) < d ? formatSecond
+ : d3_time.utcHour(date) < d ? formatMinute
+ : d3_time.utcDay(date) < d ? formatHour
+ : d3_time.utcMonth(date) < d ?
+ (d3_time.utcWeek(date) < d ? formatDay : formatWeek)
+ : d3_time.utcYear(date) < d ? formatMonth
+ : formatYear)(date);
+ };
+}
+
+function monthFormat(month, abbreviate) {
+ var f = abbreviate ?
+ (monthAbbr || (monthAbbr = timeF.format('%b'))) :
+ (monthFull || (monthFull = timeF.format('%B')));
+ return (tmpDate.setMonth(month), f(tmpDate));
+}
+
+function dayFormat(day, abbreviate) {
+ var f = abbreviate ?
+ (dayAbbr || (dayAbbr = timeF.format('%a'))) :
+ (dayFull || (dayFull = timeF.format('%A')));
+ return (tmpDate.setMonth(0), tmpDate.setDate(2 + day), f(tmpDate));
+}
+},{"./util":30,"d3-format":4,"d3-time":6,"d3-time-format":5}],16:[function(require,module,exports){
+var util = require('./util'),
+ gen = module.exports;
+
+gen.repeat = function(val, n) {
+ var a = Array(n), i;
+ for (i=0; i stop) range.push(j);
+ else while ((j = start + step * ++i) < stop) range.push(j);
+ return range;
+};
+
+gen.random = {};
+
+gen.random.uniform = function(min, max) {
+ if (max === undefined) {
+ max = min === undefined ? 1 : min;
+ min = 0;
+ }
+ var d = max - min;
+ var f = function() {
+ return min + d * Math.random();
+ };
+ f.samples = function(n) {
+ return gen.zeros(n).map(f);
+ };
+ f.pdf = function(x) {
+ return (x >= min && x <= max) ? 1/d : 0;
+ };
+ f.cdf = function(x) {
+ return x < min ? 0 : x > max ? 1 : (x - min) / d;
+ };
+ f.icdf = function(p) {
+ return (p >= 0 && p <= 1) ? min + p*d : NaN;
+ };
+ return f;
+};
+
+gen.random.integer = function(a, b) {
+ if (b === undefined) {
+ b = a;
+ a = 0;
+ }
+ var d = b - a;
+ var f = function() {
+ return a + Math.floor(d * Math.random());
+ };
+ f.samples = function(n) {
+ return gen.zeros(n).map(f);
+ };
+ f.pdf = function(x) {
+ return (x === Math.floor(x) && x >= a && x < b) ? 1/d : 0;
+ };
+ f.cdf = function(x) {
+ var v = Math.floor(x);
+ return v < a ? 0 : v >= b ? 1 : (v - a + 1) / d;
+ };
+ f.icdf = function(p) {
+ return (p >= 0 && p <= 1) ? a - 1 + Math.floor(p*d) : NaN;
+ };
+ return f;
+};
+
+gen.random.normal = function(mean, stdev) {
+ mean = mean || 0;
+ stdev = stdev || 1;
+ var next;
+ var f = function() {
+ var x = 0, y = 0, rds, c;
+ if (next !== undefined) {
+ x = next;
+ next = undefined;
+ return x;
+ }
+ do {
+ x = Math.random()*2-1;
+ y = Math.random()*2-1;
+ rds = x*x + y*y;
+ } while (rds === 0 || rds > 1);
+ c = Math.sqrt(-2*Math.log(rds)/rds); // Box-Muller transform
+ next = mean + y*c*stdev;
+ return mean + x*c*stdev;
+ };
+ f.samples = function(n) {
+ return gen.zeros(n).map(f);
+ };
+ f.pdf = function(x) {
+ var exp = Math.exp(Math.pow(x-mean, 2) / (-2 * Math.pow(stdev, 2)));
+ return (1 / (stdev * Math.sqrt(2*Math.PI))) * exp;
+ };
+ f.cdf = function(x) {
+ // Approximation from West (2009)
+ // Better Approximations to Cumulative Normal Functions
+ var cd,
+ z = (x - mean) / stdev,
+ Z = Math.abs(z);
+ if (Z > 37) {
+ cd = 0;
+ } else {
+ var sum, exp = Math.exp(-Z*Z/2);
+ if (Z < 7.07106781186547) {
+ sum = 3.52624965998911e-02 * Z + 0.700383064443688;
+ sum = sum * Z + 6.37396220353165;
+ sum = sum * Z + 33.912866078383;
+ sum = sum * Z + 112.079291497871;
+ sum = sum * Z + 221.213596169931;
+ sum = sum * Z + 220.206867912376;
+ cd = exp * sum;
+ sum = 8.83883476483184e-02 * Z + 1.75566716318264;
+ sum = sum * Z + 16.064177579207;
+ sum = sum * Z + 86.7807322029461;
+ sum = sum * Z + 296.564248779674;
+ sum = sum * Z + 637.333633378831;
+ sum = sum * Z + 793.826512519948;
+ sum = sum * Z + 440.413735824752;
+ cd = cd / sum;
+ } else {
+ sum = Z + 0.65;
+ sum = Z + 4 / sum;
+ sum = Z + 3 / sum;
+ sum = Z + 2 / sum;
+ sum = Z + 1 / sum;
+ cd = exp / sum / 2.506628274631;
+ }
+ }
+ return z > 0 ? 1 - cd : cd;
+ };
+ f.icdf = function(p) {
+ // Approximation of Probit function using inverse error function.
+ if (p <= 0 || p >= 1) return NaN;
+ var x = 2*p - 1,
+ v = (8 * (Math.PI - 3)) / (3 * Math.PI * (4-Math.PI)),
+ a = (2 / (Math.PI*v)) + (Math.log(1 - Math.pow(x,2)) / 2),
+ b = Math.log(1 - (x*x)) / v,
+ s = (x > 0 ? 1 : -1) * Math.sqrt(Math.sqrt((a*a) - b) - a);
+ return mean + stdev * Math.SQRT2 * s;
+ };
+ return f;
+};
+
+gen.random.bootstrap = function(domain, smooth) {
+ // Generates a bootstrap sample from a set of observations.
+ // Smooth bootstrapping adds random zero-centered noise to the samples.
+ var val = domain.filter(util.isValid),
+ len = val.length,
+ err = smooth ? gen.random.normal(0, smooth) : null;
+ var f = function() {
+ return val[~~(Math.random()*len)] + (err ? err() : 0);
+ };
+ f.samples = function(n) {
+ return gen.zeros(n).map(f);
+ };
+ return f;
+};
+},{"./util":30}],17:[function(require,module,exports){
+var util = require('../../util');
+var d3_dsv = require('d3-dsv');
+
+function dsv(data, format) {
+ if (data) {
+ var h = format.header;
+ data = (h ? h.join(format.delimiter) + '\n' : '') + data;
+ }
+ return d3_dsv.dsv(format.delimiter).parse(data);
+}
+
+dsv.delimiter = function(delim) {
+ var fmt = {delimiter: delim};
+ return function(data, format) {
+ return dsv(data, format ? util.extend(format, fmt) : fmt);
+ };
+};
+
+module.exports = dsv;
+
+},{"../../util":30,"d3-dsv":3}],18:[function(require,module,exports){
+var dsv = require('./dsv');
+
+module.exports = {
+ json: require('./json'),
+ topojson: require('./topojson'),
+ treejson: require('./treejson'),
+ dsv: dsv,
+ csv: dsv.delimiter(','),
+ tsv: dsv.delimiter('\t')
+};
+
+},{"./dsv":17,"./json":19,"./topojson":20,"./treejson":21}],19:[function(require,module,exports){
+var util = require('../../util');
+
+module.exports = function(data, format) {
+ var d = util.isObject(data) && !util.isBuffer(data) ?
+ data : JSON.parse(data);
+ if (format && format.property) {
+ d = util.accessor(format.property)(d);
+ }
+ return d;
+};
+
+},{"../../util":30}],20:[function(require,module,exports){
+var json = require('./json');
+
+var reader = function(data, format) {
+ var topojson = reader.topojson;
+ if (topojson == null) { throw Error('TopoJSON library not loaded.'); }
+
+ var t = json(data, format), obj;
+
+ if (format && format.feature) {
+ if ((obj = t.objects[format.feature])) {
+ return topojson.feature(t, obj).features;
+ } else {
+ throw Error('Invalid TopoJSON object: ' + format.feature);
+ }
+ } else if (format && format.mesh) {
+ if ((obj = t.objects[format.mesh])) {
+ return [topojson.mesh(t, t.objects[format.mesh])];
+ } else {
+ throw Error('Invalid TopoJSON object: ' + format.mesh);
+ }
+ } else {
+ throw Error('Missing TopoJSON feature or mesh parameter.');
+ }
+};
+
+reader.topojson = require('topojson');
+module.exports = reader;
+
+},{"./json":19,"topojson":31}],21:[function(require,module,exports){
+var json = require('./json');
+
+module.exports = function(tree, format) {
+ return toTable(json(tree, format), format);
+};
+
+function toTable(root, fields) {
+ var childrenField = fields && fields.children || 'children',
+ parentField = fields && fields.parent || 'parent',
+ table = [];
+
+ function visit(node, parent) {
+ node[parentField] = parent;
+ table.push(node);
+ var children = node[childrenField];
+ if (children) {
+ for (var i=0; i 1 && domain[idx-1] === '.' && domain.lastIndexOf(d) === idx);
+ });
+ if (!whiteListed) {
+ throw 'URL is not whitelisted: ' + url;
+ }
+ }
+ }
+ return url;
+}
+
+function load(opt, callback) {
+ return load.loader(opt, callback);
+}
+
+function loader(opt, callback) {
+ var error = callback || function(e) { throw e; }, url;
+
+ try {
+ url = load.sanitizeUrl(opt); // enable override
+ } catch (err) {
+ error(err);
+ return;
+ }
+
+ if (!url) {
+ error('Invalid URL: ' + opt.url);
+ } else if (load.useXHR) {
+ // on client, use xhr
+ return load.xhr(url, opt, callback);
+ } else if (startsWith(url, fileProtocol)) {
+ // on server, if url starts with 'file://', strip it and load from file
+ return load.file(url.slice(fileProtocol.length), opt, callback);
+ } else if (url.indexOf('://') < 0) { // TODO better protocol check?
+ // on server, if no protocol assume file
+ return load.file(url, opt, callback);
+ } else {
+ // for regular URLs on server
+ return load.http(url, opt, callback);
+ }
+}
+
+function xhrHasResponse(request) {
+ var type = request.responseType;
+ return type && type !== 'text' ?
+ request.response : // null on error
+ request.responseText; // '' on error
+}
+
+function xhr(url, opt, callback) {
+ var async = !!callback;
+ var request = new XMLHttpRequest();
+ // If IE does not support CORS, use XDomainRequest (copied from d3.xhr)
+ if (typeof XDomainRequest !== 'undefined' &&
+ !('withCredentials' in request) &&
+ /^(http(s)?:)?\/\//.test(url)) request = new XDomainRequest();
+
+ function respond() {
+ var status = request.status;
+ if (!status && xhrHasResponse(request) || status >= 200 && status < 300 || status === 304) {
+ callback(null, request.responseText);
+ } else {
+ callback(request, null);
+ }
+ }
+
+ if (async) {
+ if ('onload' in request) {
+ request.onload = request.onerror = respond;
+ } else {
+ request.onreadystatechange = function() {
+ if (request.readyState > 3) respond();
+ };
+ }
+ }
+
+ request.open('GET', url, async);
+ /* istanbul ignore else */
+ if (request.setRequestHeader) {
+ var headers = util.extend({}, load.headers, opt.headers);
+ for (var name in headers) {
+ request.setRequestHeader(name, headers[name]);
+ }
+ }
+ request.send();
+
+ if (!async && xhrHasResponse(request)) {
+ return request.responseText;
+ }
+}
+
+function file(filename, opt, callback) {
+ var fs = require('fs');
+ if (!callback) {
+ return fs.readFileSync(filename, 'utf8');
+ }
+ fs.readFile(filename, callback);
+}
+
+function http(url, opt, callback) {
+ var headers = util.extend({}, load.headers, opt.headers);
+
+ if (!callback) {
+ return require('sync-request')('GET', url, {headers: headers}).getBody();
+ }
+
+ var options = {url: url, encoding: null, gzip: true, headers: headers};
+ require('request')(options, function(error, response, body) {
+ if (!error && response.statusCode === 200) {
+ callback(null, body);
+ } else {
+ error = error ||
+ 'Load failed with response code ' + response.statusCode + '.';
+ callback(error, null);
+ }
+ });
+}
+
+function startsWith(string, searchString) {
+ return string == null ? false : string.lastIndexOf(searchString, 0) === 0;
+}
+
+// Allow these functions to be overriden by the user of the library
+load.loader = loader;
+load.sanitizeUrl = sanitizeUrl;
+load.xhr = xhr;
+load.file = file;
+load.http = http;
+
+// Default settings
+load.useXHR = (typeof XMLHttpRequest !== 'undefined');
+load.headers = {};
+
+module.exports = load;
+
+},{"../util":30,"fs":2,"request":2,"sync-request":2,"url":2}],23:[function(require,module,exports){
+var util = require('../util'),
+ type = require('./type'),
+ formats = require('./formats'),
+ timeF = require('../format').time;
+
+function read(data, format) {
+ var type = (format && format.type) || 'json';
+ data = formats[type](data, format);
+ if (format && format.parse) parse(data, format.parse);
+ return data;
+}
+
+function parse(data, types) {
+ var cols, parsers, d, i, j, clen, len = data.length;
+
+ types = (types==='auto') ? type.inferAll(data) : util.duplicate(types);
+ cols = util.keys(types);
+ parsers = cols.map(function(c) {
+ var t = types[c];
+ if (t && t.indexOf('date:') === 0) {
+ var parts = t.split(':', 2),
+ pattern = parts[1];
+ if ((pattern[0] === '\'' && pattern[pattern.length-1] === '\'') ||
+ (pattern[0] === '"' && pattern[pattern.length-1] === '"')) {
+ pattern = pattern.slice(1, -1);
+ } else {
+ throw Error('Format pattern must be quoted: ' + pattern);
+ }
+ pattern = timeF(pattern);
+ return function(v) { return pattern.parse(v); };
+ }
+ if (!type.parsers[t]) {
+ throw Error('Illegal format pattern: ' + c + ':' + t);
+ }
+ return type.parsers[t];
+ });
+
+ for (i=0, clen=cols.length; i 0 ? Math.pow(mean, 1/c) : 0;
+ return mean;
+};
+
+// Compute the harmonic mean of an array of numbers.
+stats.mean.harmonic = function(values, f) {
+ f = util.$(f);
+ var mean = 0, c, n, v, i;
+ for (i=0, c=0, n=values.length; i b) b = v;
+ }
+ }
+ return [a, b];
+};
+
+// Find the integer indices of the minimum and maximum values.
+stats.extent.index = function(values, f) {
+ f = util.$(f);
+ var x = -1, y = -1, a, b, v, i, n = values.length;
+ for (i=0; i b) { b = v; y = i; }
+ }
+ }
+ return [x, y];
+};
+
+// Compute the dot product of two arrays of numbers.
+stats.dot = function(values, a, b) {
+ var sum = 0, i, v;
+ if (!b) {
+ if (values.length !== a.length) {
+ throw Error('Array lengths must match.');
+ }
+ for (i=0; i -1 && p !== v) {
+ mu = 1 + (i-1 + tie) / 2;
+ for (; tie -1) {
+ mu = 1 + (n-1 + tie) / 2;
+ for (; tie max) max = x;
+ delta = x - mean;
+ mean = mean + delta / (++valid);
+ M2 = M2 + delta * (x - mean);
+ vals.push(x);
+ }
+ }
+ M2 = M2 / (valid - 1);
+ sd = Math.sqrt(M2);
+
+ // sort values for median and iqr
+ vals.sort(util.cmp);
+
+ return {
+ type: type(values, f),
+ unique: u,
+ count: values.length,
+ valid: valid,
+ missing: missing,
+ distinct: distinct,
+ min: min,
+ max: max,
+ mean: mean,
+ stdev: sd,
+ median: (v = stats.quantile(vals, 0.5)),
+ q1: stats.quantile(vals, 0.25),
+ q3: stats.quantile(vals, 0.75),
+ modeskew: sd === 0 ? 0 : (mean - v) / sd
+ };
+};
+
+// Compute profiles for all variables in a data set.
+stats.summary = function(data, fields) {
+ fields = fields || util.keys(data[0]);
+ var s = fields.map(function(f) {
+ var p = stats.profile(data, util.$(f));
+ return (p.field = f, p);
+ });
+ return (s.__summary__ = true, s);
+};
+
+},{"./generate":16,"./import/type":25,"./util":30}],28:[function(require,module,exports){
+var util = require('./util'),
+ format = require('./format');
+
+var context = {
+ formats: [],
+ format_map: {},
+ truncate: util.truncate,
+ pad: util.pad,
+ day: format.day,
+ month: format.month
+};
+
+function template(text) {
+ var src = source(text, 'd');
+ src = 'var __t; return ' + src + ';';
+
+ /* jshint evil: true */
+ return (new Function('d', src)).bind(context);
+}
+
+template.source = source;
+template.context = context;
+template.format = get_format;
+module.exports = template;
+
+// Clear cache of format objects.
+// This can *break* prior template functions, so invoke with care!
+template.clearFormatCache = function() {
+ context.formats = [];
+ context.format_map = {};
+};
+
+// Generate property access code for use within template source.
+// object: the name of the object (variable) containing template data
+// property: the property access string, verbatim from template tag
+template.property = function(object, property) {
+ var src = util.field(property).map(util.str).join('][');
+ return object + '[' + src + ']';
+};
+
+// Generate source code for a template function.
+// text: the template text
+// variable: the name of the data object variable ('obj' by default)
+// properties: optional hash for collecting all accessed properties
+function source(text, variable, properties) {
+ variable = variable || 'obj';
+ var index = 0;
+ var src = '\'';
+ var regex = template_re;
+
+ // Compile the template source, escaping string literals appropriately.
+ text.replace(regex, function(match, interpolate, offset) {
+ src += text
+ .slice(index, offset)
+ .replace(template_escaper, template_escapeChar);
+ index = offset + match.length;
+
+ if (interpolate) {
+ src += '\'\n+((__t=(' +
+ template_var(interpolate, variable, properties) +
+ '))==null?\'\':__t)+\n\'';
+ }
+
+ // Adobe VMs need the match returned to produce the correct offest.
+ return match;
+ });
+ return src + '\'';
+}
+
+function template_var(text, variable, properties) {
+ var filters = text.match(filter_re);
+ var prop = filters.shift().trim();
+ var stringCast = true;
+
+ function strcall(fn) {
+ fn = fn || '';
+ if (stringCast) {
+ stringCast = false;
+ src = 'String(' + src + ')' + fn;
+ } else {
+ src += fn;
+ }
+ return src;
+ }
+
+ function date() {
+ return '(typeof ' + src + '==="number"?new Date('+src+'):'+src+')';
+ }
+
+ function formatter(type) {
+ var pattern = args[0];
+ if ((pattern[0] === '\'' && pattern[pattern.length-1] === '\'') ||
+ (pattern[0] === '"' && pattern[pattern.length-1] === '"')) {
+ pattern = pattern.slice(1, -1);
+ } else {
+ throw Error('Format pattern must be quoted: ' + pattern);
+ }
+ a = template_format(pattern, type);
+ stringCast = false;
+ var arg = type === 'number' ? src : date();
+ src = 'this.formats['+a+']('+arg+')';
+ }
+
+ if (properties) properties[prop] = 1;
+ var src = template.property(variable, prop);
+
+ for (var i=0; i 0) {
+ f = f.slice(0, pidx);
+ args = filters[i].slice(pidx+1)
+ .match(args_re)
+ .map(function(s) { return s.trim(); });
+ }
+ f = f.trim();
+
+ switch (f) {
+ case 'length':
+ strcall('.length');
+ break;
+ case 'lower':
+ strcall('.toLowerCase()');
+ break;
+ case 'upper':
+ strcall('.toUpperCase()');
+ break;
+ case 'lower-locale':
+ strcall('.toLocaleLowerCase()');
+ break;
+ case 'upper-locale':
+ strcall('.toLocaleUpperCase()');
+ break;
+ case 'trim':
+ strcall('.trim()');
+ break;
+ case 'left':
+ a = util.number(args[0]);
+ strcall('.slice(0,' + a + ')');
+ break;
+ case 'right':
+ a = util.number(args[0]);
+ strcall('.slice(-' + a +')');
+ break;
+ case 'mid':
+ a = util.number(args[0]);
+ b = a + util.number(args[1]);
+ strcall('.slice(+'+a+','+b+')');
+ break;
+ case 'slice':
+ a = util.number(args[0]);
+ strcall('.slice('+ a +
+ (args.length > 1 ? ',' + util.number(args[1]) : '') +
+ ')');
+ break;
+ case 'truncate':
+ a = util.number(args[0]);
+ b = args[1];
+ b = (b!=='left' && b!=='middle' && b!=='center') ? 'right' : b;
+ src = 'this.truncate(' + strcall() + ',' + a + ',\'' + b + '\')';
+ break;
+ case 'pad':
+ a = util.number(args[0]);
+ b = args[1];
+ b = (b!=='left' && b!=='middle' && b!=='center') ? 'right' : b;
+ src = 'this.pad(' + strcall() + ',' + a + ',\'' + b + '\')';
+ break;
+ case 'number':
+ formatter('number');
+ break;
+ case 'time':
+ formatter('time');
+ break;
+ case 'time-utc':
+ formatter('utc');
+ break;
+ case 'month':
+ src = 'this.month(' + src + ')';
+ break;
+ case 'month-abbrev':
+ src = 'this.month(' + src + ',true)';
+ break;
+ case 'day':
+ src = 'this.day(' + src + ')';
+ break;
+ case 'day-abbrev':
+ src = 'this.day(' + src + ',true)';
+ break;
+ default:
+ throw Error('Unrecognized template filter: ' + f);
+ }
+ }
+
+ return src;
+}
+
+var template_re = /\{\{(.+?)\}\}|$/g,
+ filter_re = /(?:"[^"]*"|\'[^\']*\'|[^\|"]+|[^\|\']+)+/g,
+ args_re = /(?:"[^"]*"|\'[^\']*\'|[^,"]+|[^,\']+)+/g;
+
+// Certain characters need to be escaped so that they can be put into a
+// string literal.
+var template_escapes = {
+ '\'': '\'',
+ '\\': '\\',
+ '\r': 'r',
+ '\n': 'n',
+ '\u2028': 'u2028',
+ '\u2029': 'u2029'
+};
+
+var template_escaper = /\\|'|\r|\n|\u2028|\u2029/g;
+
+function template_escapeChar(match) {
+ return '\\' + template_escapes[match];
+}
+
+function template_format(pattern, type) {
+ var key = type + ':' + pattern;
+ if (context.format_map[key] == null) {
+ var f = format[type](pattern);
+ var i = context.formats.length;
+ context.formats.push(f);
+ context.format_map[key] = i;
+ return i;
+ }
+ return context.format_map[key];
+}
+
+function get_format(pattern, type) {
+ return context.formats[template_format(pattern, type)];
+}
+
+},{"./format":15,"./util":30}],29:[function(require,module,exports){
+var d3_time = require('d3-time');
+
+var tempDate = new Date(),
+ baseDate = new Date(0, 0, 1).setFullYear(0), // Jan 1, 0 AD
+ utcBaseDate = new Date(Date.UTC(0, 0, 1)).setUTCFullYear(0);
+
+function date(d) {
+ return (tempDate.setTime(+d), tempDate);
+}
+
+// create a time unit entry
+function entry(type, date, unit, step, min, max) {
+ var e = {
+ type: type,
+ date: date,
+ unit: unit
+ };
+ if (step) {
+ e.step = step;
+ } else {
+ e.minstep = 1;
+ }
+ if (min != null) e.min = min;
+ if (max != null) e.max = max;
+ return e;
+}
+
+function create(type, unit, base, step, min, max) {
+ return entry(type,
+ function(d) { return unit.offset(base, d); },
+ function(d) { return unit.count(base, d); },
+ step, min, max);
+}
+
+var locale = [
+ create('second', d3_time.second, baseDate),
+ create('minute', d3_time.minute, baseDate),
+ create('hour', d3_time.hour, baseDate),
+ create('day', d3_time.day, baseDate, [1, 7]),
+ create('month', d3_time.month, baseDate, [1, 3, 6]),
+ create('year', d3_time.year, baseDate),
+
+ // periodic units
+ entry('seconds',
+ function(d) { return new Date(1970, 0, 1, 0, 0, d); },
+ function(d) { return date(d).getSeconds(); },
+ null, 0, 59
+ ),
+ entry('minutes',
+ function(d) { return new Date(1970, 0, 1, 0, d); },
+ function(d) { return date(d).getMinutes(); },
+ null, 0, 59
+ ),
+ entry('hours',
+ function(d) { return new Date(1970, 0, 1, d); },
+ function(d) { return date(d).getHours(); },
+ null, 0, 23
+ ),
+ entry('weekdays',
+ function(d) { return new Date(1970, 0, 4+d); },
+ function(d) { return date(d).getDay(); },
+ [1], 0, 6
+ ),
+ entry('dates',
+ function(d) { return new Date(1970, 0, d); },
+ function(d) { return date(d).getDate(); },
+ [1], 1, 31
+ ),
+ entry('months',
+ function(d) { return new Date(1970, d % 12, 1); },
+ function(d) { return date(d).getMonth(); },
+ [1], 0, 11
+ )
+];
+
+var utc = [
+ create('second', d3_time.utcSecond, utcBaseDate),
+ create('minute', d3_time.utcMinute, utcBaseDate),
+ create('hour', d3_time.utcHour, utcBaseDate),
+ create('day', d3_time.utcDay, utcBaseDate, [1, 7]),
+ create('month', d3_time.utcMonth, utcBaseDate, [1, 3, 6]),
+ create('year', d3_time.utcYear, utcBaseDate),
+
+ // periodic units
+ entry('seconds',
+ function(d) { return new Date(Date.UTC(1970, 0, 1, 0, 0, d)); },
+ function(d) { return date(d).getUTCSeconds(); },
+ null, 0, 59
+ ),
+ entry('minutes',
+ function(d) { return new Date(Date.UTC(1970, 0, 1, 0, d)); },
+ function(d) { return date(d).getUTCMinutes(); },
+ null, 0, 59
+ ),
+ entry('hours',
+ function(d) { return new Date(Date.UTC(1970, 0, 1, d)); },
+ function(d) { return date(d).getUTCHours(); },
+ null, 0, 23
+ ),
+ entry('weekdays',
+ function(d) { return new Date(Date.UTC(1970, 0, 4+d)); },
+ function(d) { return date(d).getUTCDay(); },
+ [1], 0, 6
+ ),
+ entry('dates',
+ function(d) { return new Date(Date.UTC(1970, 0, d)); },
+ function(d) { return date(d).getUTCDate(); },
+ [1], 1, 31
+ ),
+ entry('months',
+ function(d) { return new Date(Date.UTC(1970, d % 12, 1)); },
+ function(d) { return date(d).getUTCMonth(); },
+ [1], 0, 11
+ )
+];
+
+var STEPS = [
+ [31536e6, 5], // 1-year
+ [7776e6, 4], // 3-month
+ [2592e6, 4], // 1-month
+ [12096e5, 3], // 2-week
+ [6048e5, 3], // 1-week
+ [1728e5, 3], // 2-day
+ [864e5, 3], // 1-day
+ [432e5, 2], // 12-hour
+ [216e5, 2], // 6-hour
+ [108e5, 2], // 3-hour
+ [36e5, 2], // 1-hour
+ [18e5, 1], // 30-minute
+ [9e5, 1], // 15-minute
+ [3e5, 1], // 5-minute
+ [6e4, 1], // 1-minute
+ [3e4, 0], // 30-second
+ [15e3, 0], // 15-second
+ [5e3, 0], // 5-second
+ [1e3, 0] // 1-second
+];
+
+function find(units, span, minb, maxb) {
+ var step = STEPS[0], i, n, bins;
+
+ for (i=1, n=STEPS.length; i step[0]) {
+ bins = span / step[0];
+ if (bins > maxb) {
+ return units[STEPS[i-1][1]];
+ }
+ if (bins >= minb) {
+ return units[step[1]];
+ }
+ }
+ }
+ return units[STEPS[n-1][1]];
+}
+
+function toUnitMap(units) {
+ var map = {}, i, n;
+ for (i=0, n=units.length; i 1 ?
+ function(x, v) {
+ for (var i=0; i y) return sign[i];
+ }
+ return 0;
+ };
+};
+
+u.cmp = function(a, b) {
+ if (a < b) {
+ return -1;
+ } else if (a > b) {
+ return 1;
+ } else if (a >= b) {
+ return 0;
+ } else if (a === null) {
+ return -1;
+ } else if (b === null) {
+ return 1;
+ }
+ return NaN;
+};
+
+u.numcmp = function(a, b) { return a - b; };
+
+u.stablesort = function(array, sortBy, keyFn) {
+ var indices = array.reduce(function(idx, v, i) {
+ return (idx[keyFn(v)] = i, idx);
+ }, {});
+
+ array.sort(function(a, b) {
+ var sa = sortBy(a),
+ sb = sortBy(b);
+ return sa < sb ? -1 : sa > sb ? 1
+ : (indices[keyFn(a)] - indices[keyFn(b)]);
+ });
+
+ return array;
+};
+
+
+// string functions
+
+u.pad = function(s, length, pos, padchar) {
+ padchar = padchar || " ";
+ var d = length - s.length;
+ if (d <= 0) return s;
+ switch (pos) {
+ case 'left':
+ return strrep(d, padchar) + s;
+ case 'middle':
+ case 'center':
+ return strrep(Math.floor(d/2), padchar) +
+ s + strrep(Math.ceil(d/2), padchar);
+ default:
+ return s + strrep(d, padchar);
+ }
+};
+
+function strrep(n, str) {
+ var s = "", i;
+ for (i=0; i>> 1;
+ if (a[mid] < x) lo = mid + 1;
+ else hi = mid;
+ }
+ return lo;
+ }
+
+ function feature(topology, o) {
+ return o.type === "GeometryCollection" ? {
+ type: "FeatureCollection",
+ features: o.geometries.map(function(o) { return feature$1(topology, o); })
+ } : feature$1(topology, o);
+ }
+
+ function feature$1(topology, o) {
+ var f = {
+ type: "Feature",
+ id: o.id,
+ properties: o.properties || {},
+ geometry: object(topology, o)
+ };
+ if (o.id == null) delete f.id;
+ return f;
+ }
+
+ function object(topology, o) {
+ var absolute$$ = absolute(topology.transform),
+ arcs = topology.arcs;
+
+ function arc(i, points) {
+ if (points.length) points.pop();
+ for (var a = arcs[i < 0 ? ~i : i], k = 0, n = a.length, p; k < n; ++k) {
+ points.push(p = a[k].slice());
+ absolute$$(p, k);
+ }
+ if (i < 0) reverse(points, n);
+ }
+
+ function point(p) {
+ p = p.slice();
+ absolute$$(p, 0);
+ return p;
+ }
+
+ function line(arcs) {
+ var points = [];
+ for (var i = 0, n = arcs.length; i < n; ++i) arc(arcs[i], points);
+ if (points.length < 2) points.push(points[0].slice());
+ return points;
+ }
+
+ function ring(arcs) {
+ var points = line(arcs);
+ while (points.length < 4) points.push(points[0].slice());
+ return points;
+ }
+
+ function polygon(arcs) {
+ return arcs.map(ring);
+ }
+
+ function geometry(o) {
+ var t = o.type;
+ return t === "GeometryCollection" ? {type: t, geometries: o.geometries.map(geometry)}
+ : t in geometryType ? {type: t, coordinates: geometryType[t](o)}
+ : null;
+ }
+
+ var geometryType = {
+ Point: function(o) { return point(o.coordinates); },
+ MultiPoint: function(o) { return o.coordinates.map(point); },
+ LineString: function(o) { return line(o.arcs); },
+ MultiLineString: function(o) { return o.arcs.map(line); },
+ Polygon: function(o) { return polygon(o.arcs); },
+ MultiPolygon: function(o) { return o.arcs.map(polygon); }
+ };
+
+ return geometry(o);
+ }
+
+ function stitchArcs(topology, arcs) {
+ var stitchedArcs = {},
+ fragmentByStart = {},
+ fragmentByEnd = {},
+ fragments = [],
+ emptyIndex = -1;
+
+ // Stitch empty arcs first, since they may be subsumed by other arcs.
+ arcs.forEach(function(i, j) {
+ var arc = topology.arcs[i < 0 ? ~i : i], t;
+ if (arc.length < 3 && !arc[1][0] && !arc[1][1]) {
+ t = arcs[++emptyIndex], arcs[emptyIndex] = i, arcs[j] = t;
+ }
+ });
+
+ arcs.forEach(function(i) {
+ var e = ends(i),
+ start = e[0],
+ end = e[1],
+ f, g;
+
+ if (f = fragmentByEnd[start]) {
+ delete fragmentByEnd[f.end];
+ f.push(i);
+ f.end = end;
+ if (g = fragmentByStart[end]) {
+ delete fragmentByStart[g.start];
+ var fg = g === f ? f : f.concat(g);
+ fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.end] = fg;
+ } else {
+ fragmentByStart[f.start] = fragmentByEnd[f.end] = f;
+ }
+ } else if (f = fragmentByStart[end]) {
+ delete fragmentByStart[f.start];
+ f.unshift(i);
+ f.start = start;
+ if (g = fragmentByEnd[start]) {
+ delete fragmentByEnd[g.end];
+ var gf = g === f ? f : g.concat(f);
+ fragmentByStart[gf.start = g.start] = fragmentByEnd[gf.end = f.end] = gf;
+ } else {
+ fragmentByStart[f.start] = fragmentByEnd[f.end] = f;
+ }
+ } else {
+ f = [i];
+ fragmentByStart[f.start = start] = fragmentByEnd[f.end = end] = f;
+ }
+ });
+
+ function ends(i) {
+ var arc = topology.arcs[i < 0 ? ~i : i], p0 = arc[0], p1;
+ if (topology.transform) p1 = [0, 0], arc.forEach(function(dp) { p1[0] += dp[0], p1[1] += dp[1]; });
+ else p1 = arc[arc.length - 1];
+ return i < 0 ? [p1, p0] : [p0, p1];
+ }
+
+ function flush(fragmentByEnd, fragmentByStart) {
+ for (var k in fragmentByEnd) {
+ var f = fragmentByEnd[k];
+ delete fragmentByStart[f.start];
+ delete f.start;
+ delete f.end;
+ f.forEach(function(i) { stitchedArcs[i < 0 ? ~i : i] = 1; });
+ fragments.push(f);
+ }
+ }
+
+ flush(fragmentByEnd, fragmentByStart);
+ flush(fragmentByStart, fragmentByEnd);
+ arcs.forEach(function(i) { if (!stitchedArcs[i < 0 ? ~i : i]) fragments.push([i]); });
+
+ return fragments;
+ }
+
+ function mesh(topology) {
+ return object(topology, meshArcs.apply(this, arguments));
+ }
+
+ function meshArcs(topology, o, filter) {
+ var arcs = [];
+
+ function arc(i) {
+ var j = i < 0 ? ~i : i;
+ (geomsByArc[j] || (geomsByArc[j] = [])).push({i: i, g: geom});
+ }
+
+ function line(arcs) {
+ arcs.forEach(arc);
+ }
+
+ function polygon(arcs) {
+ arcs.forEach(line);
+ }
+
+ function geometry(o) {
+ if (o.type === "GeometryCollection") o.geometries.forEach(geometry);
+ else if (o.type in geometryType) geom = o, geometryType[o.type](o.arcs);
+ }
+
+ if (arguments.length > 1) {
+ var geomsByArc = [],
+ geom;
+
+ var geometryType = {
+ LineString: line,
+ MultiLineString: polygon,
+ Polygon: polygon,
+ MultiPolygon: function(arcs) { arcs.forEach(polygon); }
+ };
+
+ geometry(o);
+
+ geomsByArc.forEach(arguments.length < 3
+ ? function(geoms) { arcs.push(geoms[0].i); }
+ : function(geoms) { if (filter(geoms[0].g, geoms[geoms.length - 1].g)) arcs.push(geoms[0].i); });
+ } else {
+ for (var i = 0, n = topology.arcs.length; i < n; ++i) arcs.push(i);
+ }
+
+ return {type: "MultiLineString", arcs: stitchArcs(topology, arcs)};
+ }
+
+ function triangle(triangle) {
+ var a = triangle[0], b = triangle[1], c = triangle[2];
+ return Math.abs((a[0] - c[0]) * (b[1] - a[1]) - (a[0] - b[0]) * (c[1] - a[1]));
+ }
+
+ function ring(ring) {
+ var i = -1,
+ n = ring.length,
+ a,
+ b = ring[n - 1],
+ area = 0;
+
+ while (++i < n) {
+ a = b;
+ b = ring[i];
+ area += a[0] * b[1] - a[1] * b[0];
+ }
+
+ return area / 2;
+ }
+
+ function merge(topology) {
+ return object(topology, mergeArcs.apply(this, arguments));
+ }
+
+ function mergeArcs(topology, objects) {
+ var polygonsByArc = {},
+ polygons = [],
+ components = [];
+
+ objects.forEach(function(o) {
+ if (o.type === "Polygon") register(o.arcs);
+ else if (o.type === "MultiPolygon") o.arcs.forEach(register);
+ });
+
+ function register(polygon) {
+ polygon.forEach(function(ring$$) {
+ ring$$.forEach(function(arc) {
+ (polygonsByArc[arc = arc < 0 ? ~arc : arc] || (polygonsByArc[arc] = [])).push(polygon);
+ });
+ });
+ polygons.push(polygon);
+ }
+
+ function exterior(ring$$) {
+ return ring(object(topology, {type: "Polygon", arcs: [ring$$]}).coordinates[0]) > 0; // TODO allow spherical?
+ }
+
+ polygons.forEach(function(polygon) {
+ if (!polygon._) {
+ var component = [],
+ neighbors = [polygon];
+ polygon._ = 1;
+ components.push(component);
+ while (polygon = neighbors.pop()) {
+ component.push(polygon);
+ polygon.forEach(function(ring$$) {
+ ring$$.forEach(function(arc) {
+ polygonsByArc[arc < 0 ? ~arc : arc].forEach(function(polygon) {
+ if (!polygon._) {
+ polygon._ = 1;
+ neighbors.push(polygon);
+ }
+ });
+ });
+ });
+ }
+ }
+ });
+
+ polygons.forEach(function(polygon) {
+ delete polygon._;
+ });
+
+ return {
+ type: "MultiPolygon",
+ arcs: components.map(function(polygons) {
+ var arcs = [], n;
+
+ // Extract the exterior (unique) arcs.
+ polygons.forEach(function(polygon) {
+ polygon.forEach(function(ring$$) {
+ ring$$.forEach(function(arc) {
+ if (polygonsByArc[arc < 0 ? ~arc : arc].length < 2) {
+ arcs.push(arc);
+ }
+ });
+ });
+ });
+
+ // Stitch the arcs into one or more rings.
+ arcs = stitchArcs(topology, arcs);
+
+ // If more than one ring is returned,
+ // at most one of these rings can be the exterior;
+ // this exterior ring has the same winding order
+ // as any exterior ring in the original polygons.
+ if ((n = arcs.length) > 1) {
+ var sgn = exterior(polygons[0][0]);
+ for (var i = 0, t; i < n; ++i) {
+ if (sgn === exterior(arcs[i])) {
+ t = arcs[0], arcs[0] = arcs[i], arcs[i] = t;
+ break;
+ }
+ }
+ }
+
+ return arcs;
+ })
+ };
+ }
+
+ function neighbors(objects) {
+ var indexesByArc = {}, // arc index -> array of object indexes
+ neighbors = objects.map(function() { return []; });
+
+ function line(arcs, i) {
+ arcs.forEach(function(a) {
+ if (a < 0) a = ~a;
+ var o = indexesByArc[a];
+ if (o) o.push(i);
+ else indexesByArc[a] = [i];
+ });
+ }
+
+ function polygon(arcs, i) {
+ arcs.forEach(function(arc) { line(arc, i); });
+ }
+
+ function geometry(o, i) {
+ if (o.type === "GeometryCollection") o.geometries.forEach(function(o) { geometry(o, i); });
+ else if (o.type in geometryType) geometryType[o.type](o.arcs, i);
+ }
+
+ var geometryType = {
+ LineString: line,
+ MultiLineString: polygon,
+ Polygon: polygon,
+ MultiPolygon: function(arcs, i) { arcs.forEach(function(arc) { polygon(arc, i); }); }
+ };
+
+ objects.forEach(geometry);
+
+ for (var i in indexesByArc) {
+ for (var indexes = indexesByArc[i], m = indexes.length, j = 0; j < m; ++j) {
+ for (var k = j + 1; k < m; ++k) {
+ var ij = indexes[j], ik = indexes[k], n;
+ if ((n = neighbors[ij])[i = bisect(n, ik)] !== ik) n.splice(i, 0, ik);
+ if ((n = neighbors[ik])[i = bisect(n, ij)] !== ij) n.splice(i, 0, ij);
+ }
+ }
+ }
+
+ return neighbors;
+ }
+
+ function compareArea(a, b) {
+ return a[1][2] - b[1][2];
+ }
+
+ function minAreaHeap() {
+ var heap = {},
+ array = [],
+ size = 0;
+
+ heap.push = function(object) {
+ up(array[object._ = size] = object, size++);
+ return size;
+ };
+
+ heap.pop = function() {
+ if (size <= 0) return;
+ var removed = array[0], object;
+ if (--size > 0) object = array[size], down(array[object._ = 0] = object, 0);
+ return removed;
+ };
+
+ heap.remove = function(removed) {
+ var i = removed._, object;
+ if (array[i] !== removed) return; // invalid request
+ if (i !== --size) object = array[size], (compareArea(object, removed) < 0 ? up : down)(array[object._ = i] = object, i);
+ return i;
+ };
+
+ function up(object, i) {
+ while (i > 0) {
+ var j = ((i + 1) >> 1) - 1,
+ parent = array[j];
+ if (compareArea(object, parent) >= 0) break;
+ array[parent._ = i] = parent;
+ array[object._ = i = j] = object;
+ }
+ }
+
+ function down(object, i) {
+ while (true) {
+ var r = (i + 1) << 1,
+ l = r - 1,
+ j = i,
+ child = array[j];
+ if (l < size && compareArea(array[l], child) < 0) child = array[j = l];
+ if (r < size && compareArea(array[r], child) < 0) child = array[j = r];
+ if (j === i) break;
+ array[child._ = i] = child;
+ array[object._ = i = j] = object;
+ }
+ }
+
+ return heap;
+ }
+
+ function presimplify(topology, triangleArea) {
+ var absolute$$ = absolute(topology.transform),
+ relative$$ = relative(topology.transform),
+ heap = minAreaHeap();
+
+ if (!triangleArea) triangleArea = triangle;
+
+ topology.arcs.forEach(function(arc) {
+ var triangles = [],
+ maxArea = 0,
+ triangle,
+ i,
+ n,
+ p;
+
+ // To store each point’s effective area, we create a new array rather than
+ // extending the passed-in point to workaround a Chrome/V8 bug (getting
+ // stuck in smi mode). For midpoints, the initial effective area of
+ // Infinity will be computed in the next step.
+ for (i = 0, n = arc.length; i < n; ++i) {
+ p = arc[i];
+ absolute$$(arc[i] = [p[0], p[1], Infinity], i);
+ }
+
+ for (i = 1, n = arc.length - 1; i < n; ++i) {
+ triangle = arc.slice(i - 1, i + 2);
+ triangle[1][2] = triangleArea(triangle);
+ triangles.push(triangle);
+ heap.push(triangle);
+ }
+
+ for (i = 0, n = triangles.length; i < n; ++i) {
+ triangle = triangles[i];
+ triangle.previous = triangles[i - 1];
+ triangle.next = triangles[i + 1];
+ }
+
+ while (triangle = heap.pop()) {
+ var previous = triangle.previous,
+ next = triangle.next;
+
+ // If the area of the current point is less than that of the previous point
+ // to be eliminated, use the latter's area instead. This ensures that the
+ // current point cannot be eliminated without eliminating previously-
+ // eliminated points.
+ if (triangle[1][2] < maxArea) triangle[1][2] = maxArea;
+ else maxArea = triangle[1][2];
+
+ if (previous) {
+ previous.next = next;
+ previous[2] = triangle[2];
+ update(previous);
+ }
+
+ if (next) {
+ next.previous = previous;
+ next[0] = triangle[0];
+ update(next);
+ }
+ }
+
+ arc.forEach(relative$$);
+ });
+
+ function update(triangle) {
+ heap.remove(triangle);
+ triangle[1][2] = triangleArea(triangle);
+ heap.push(triangle);
+ }
+
+ return topology;
+ }
+
+ var version = "1.6.24";
+
+ exports.version = version;
+ exports.mesh = mesh;
+ exports.meshArcs = meshArcs;
+ exports.merge = merge;
+ exports.mergeArcs = mergeArcs;
+ exports.feature = feature;
+ exports.neighbors = neighbors;
+ exports.presimplify = presimplify;
+
+}));
+},{}],32:[function(require,module,exports){
+var DEPS = require('./Dependencies').ALL;
+
+function create(cs, reflow) {
+ var out = {};
+ copy(cs, out);
+
+ out.add = [];
+ out.mod = [];
+ out.rem = [];
+
+ out.reflow = reflow;
+
+ return out;
+}
+
+function copy(a, b) {
+ b.stamp = a ? a.stamp : 0;
+ b.sort = a ? a.sort : null;
+ b.facet = a ? a.facet : null;
+ b.trans = a ? a.trans : null;
+ b.dirty = a ? a.dirty : [];
+ b.request = a ? a.request : null;
+ for (var d, i=0, n=DEPS.length; i 1) {
+ for (var i=1, n=ref.length; i 0) {
+ node = pq.peek();
+ isSg = node instanceof Signal;
+ pulse = pulses[node._id];
+
+ if (node.rank() !== node.qrank()) {
+ // A node's rank might change during a propagation. Re-queue if so.
+ pq.replace(node.qrank(true));
+ } else {
+ // Evaluate node and propagate pulse.
+ pq.pop();
+ pulses[node._id] = null;
+ listeners = node._listeners;
+
+ if (!isSg || (isSg && !skipSignals)) {
+ pulse = this.evaluate(pulse, node);
+ }
+
+ // Propagate the pulse.
+ if (pulse !== this.doNotPropagate) {
+ // Ensure reflow pulses always send reflow pulses even if skipped.
+ if (!pulse.reflow && node.reflows()) {
+ pulse = ChangeSet.create(pulse, true);
+ }
+
+ for (i=0, len=listeners.length; i 0) branch[i-1].addListener(node);
+ }
+
+ return branch;
+};
+
+prototype.disconnect = function(branch) {
+ var collector, node, data, signals, i, n, j, m;
+
+ for (i=0, n=branch.length; i= pulse.stamp,
+ run = node.router() || pulse.add.length || pulse.rem.length;
+
+ return run || !reflowed || node.reevaluate(pulse);
+};
+
+prototype.evaluate = function(pulse, node) {
+ if (!this.reevaluate(pulse, node)) return pulse;
+ pulse = node.evaluate(pulse);
+ node.last(pulse.stamp);
+ return pulse;
+};
+
+module.exports = Graph;
+
+},{"./ChangeSet":32,"./Collector":33,"./DataSource":34,"./Dependencies":35,"./Heap":37,"./Signal":39,"./Tuple":40,"datalib":26,"vega-logging":48}],37:[function(require,module,exports){
+function Heap(comparator) {
+ this.cmp = comparator;
+ this.nodes = [];
+}
+
+var prototype = Heap.prototype;
+
+prototype.size = function() {
+ return this.nodes.length;
+};
+
+prototype.clear = function() {
+ return (this.nodes = [], this);
+};
+
+prototype.peek = function() {
+ return this.nodes[0];
+};
+
+prototype.push = function(x) {
+ var array = this.nodes;
+ array.push(x);
+ return _siftdown(array, 0, array.length-1, this.cmp);
+};
+
+prototype.pop = function() {
+ var array = this.nodes,
+ last = array.pop(),
+ item;
+
+ if (array.length) {
+ item = array[0];
+ array[0] = last;
+ _siftup(array, 0, this.cmp);
+ } else {
+ item = last;
+ }
+ return item;
+};
+
+prototype.replace = function(item) {
+ var array = this.nodes,
+ retval = array[0];
+ array[0] = item;
+ _siftup(array, 0, this.cmp);
+ return retval;
+};
+
+prototype.pushpop = function(item) {
+ var array = this.nodes, ref = array[0];
+ if (array.length && this.cmp(ref, item) < 0) {
+ array[0] = item;
+ item = ref;
+ _siftup(array, 0, this.cmp);
+ }
+ return item;
+};
+
+function _siftdown(array, start, idx, cmp) {
+ var item, parent, pidx;
+
+ item = array[idx];
+ while (idx > start) {
+ pidx = (idx - 1) >> 1;
+ parent = array[pidx];
+ if (cmp(item, parent) < 0) {
+ array[idx] = parent;
+ idx = pidx;
+ continue;
+ }
+ break;
+ }
+ return (array[idx] = item);
+}
+
+function _siftup(array, idx, cmp) {
+ var start = idx,
+ end = array.length,
+ item = array[idx],
+ cidx = 2 * idx + 1, ridx;
+
+ while (cidx < end) {
+ ridx = cidx + 1;
+ if (ridx < end && cmp(array[cidx], array[ridx]) >= 0) {
+ cidx = ridx;
+ }
+ array[idx] = array[cidx];
+ idx = cidx;
+ cidx = 2 * idx + 1;
+ }
+ array[idx] = item;
+ return _siftdown(array, start, idx, cmp);
+}
+
+module.exports = Heap;
+
+},{}],38:[function(require,module,exports){
+var DEPS = require('./Dependencies').ALL,
+ nodeID = 0;
+
+function Node(graph) {
+ if (graph) this.init(graph);
+}
+
+var Flags = Node.Flags = {
+ Router: 0x01, // Responsible for propagating tuples, cannot be skipped.
+ Collector: 0x02, // Holds a materialized dataset, pulse node to reflow.
+ Produces: 0x04, // Produces new tuples.
+ Mutates: 0x08, // Sets properties of incoming tuples.
+ Reflows: 0x10, // Forwards a reflow pulse.
+ Batch: 0x20 // Performs batch data processing, needs collector.
+};
+
+var prototype = Node.prototype;
+
+prototype.init = function(graph) {
+ this._id = ++nodeID;
+ this._graph = graph;
+ this._rank = graph.rank(); // Topological sort by rank
+ this._qrank = null; // Rank when enqueued for propagation
+ this._stamp = 0; // Last stamp seen
+
+ this._listeners = [];
+ this._listeners._ids = {}; // To prevent duplicate listeners
+
+ // Initialize dependencies.
+ this._deps = {};
+ for (var i=0, n=DEPS.length; i l._rank) {
+ l.rerank();
+ }
+
+ return this;
+};
+
+prototype.removeListener = function(l) {
+ if (!this._listeners._ids[l._id]) return false;
+
+ var idx = this._listeners.indexOf(l),
+ b = idx >= 0;
+
+ if (b) {
+ this._listeners.splice(idx, 1);
+ this._listeners._ids[l._id] = null;
+ }
+ return b;
+};
+
+prototype.disconnect = function() {
+ this._listeners = [];
+ this._listeners._ids = {};
+};
+
+// Evaluate this dataflow node for the current pulse.
+// Subclasses should override to perform custom processing.
+prototype.evaluate = function(pulse) {
+ return pulse;
+};
+
+// Should this node be re-evaluated for the current pulse?
+// Searches pulse to see if any dependencies have updated.
+prototype.reevaluate = function(pulse) {
+ var prop, dep, i, n, j, m;
+
+ for (i=0, n=DEPS.length; i=0;) {
+ if (!handler || h[i].handler === handler) {
+ x = h.splice(i, 1)[0];
+ this.removeListener(x.node);
+ }
+ }
+
+ return this;
+};
+
+module.exports = Signal;
+
+},{"./ChangeSet":32,"./Node":38}],40:[function(require,module,exports){
+var tupleID = 0;
+
+function ingest(datum) {
+ datum = (datum === Object(datum)) ? datum : {data: datum};
+ datum._id = ++tupleID;
+ if (datum._prev) datum._prev = null;
+ return datum;
+}
+
+function idMap(a, ids) {
+ ids = ids || {};
+ for (var i=0, n=a.length; i0;) {
+ idMap(arguments[i], ids);
+ }
+ return data.filter(function(x) { return !ids[x._id]; });
+ }
+};
+
+},{}],41:[function(require,module,exports){
+module.exports = {
+ ChangeSet: require('./ChangeSet'),
+ Collector: require('./Collector'),
+ DataSource: require('./DataSource'),
+ Dependencies: require('./Dependencies'),
+ Graph: require('./Graph'),
+ Node: require('./Node'),
+ Signal: require('./Signal'),
+ Tuple: require('./Tuple'),
+ debug: require('vega-logging').debug
+};
+
+},{"./ChangeSet":32,"./Collector":33,"./DataSource":34,"./Dependencies":35,"./Graph":36,"./Node":38,"./Signal":39,"./Tuple":40,"vega-logging":48}],42:[function(require,module,exports){
+module.exports = (function() {
+ "use strict";
+
+ /*
+ * Generated by PEG.js 0.9.0.
+ *
+ * http://pegjs.org/
+ */
+
+ function peg$subclass(child, parent) {
+ function ctor() { this.constructor = child; }
+ ctor.prototype = parent.prototype;
+ child.prototype = new ctor();
+ }
+
+ function peg$SyntaxError(message, expected, found, location) {
+ this.message = message;
+ this.expected = expected;
+ this.found = found;
+ this.location = location;
+ this.name = "SyntaxError";
+
+ if (typeof Error.captureStackTrace === "function") {
+ Error.captureStackTrace(this, peg$SyntaxError);
+ }
+ }
+
+ peg$subclass(peg$SyntaxError, Error);
+
+ function peg$parse(input) {
+ var options = arguments.length > 1 ? arguments[1] : {},
+ parser = this,
+
+ peg$FAILED = {},
+
+ peg$startRuleFunctions = { start: peg$parsestart },
+ peg$startRuleFunction = peg$parsestart,
+
+ peg$c0 = ",",
+ peg$c1 = { type: "literal", value: ",", description: "\",\"" },
+ peg$c2 = function(o, m) { return [o].concat(m); },
+ peg$c3 = function(o) { return [o]; },
+ peg$c4 = "[",
+ peg$c5 = { type: "literal", value: "[", description: "\"[\"" },
+ peg$c6 = "]",
+ peg$c7 = { type: "literal", value: "]", description: "\"]\"" },
+ peg$c8 = ">",
+ peg$c9 = { type: "literal", value: ">", description: "\">\"" },
+ peg$c10 = function(f1, f2, o) { return {start: f1, end: f2, middle: o}; },
+ peg$c11 = function(s, f) { return (s.filters = f, s); },
+ peg$c12 = function(s) { return s; },
+ peg$c13 = "(",
+ peg$c14 = { type: "literal", value: "(", description: "\"(\"" },
+ peg$c15 = ")",
+ peg$c16 = { type: "literal", value: ")", description: "\")\"" },
+ peg$c17 = function(m) { return {stream: m}; },
+ peg$c18 = "@",
+ peg$c19 = { type: "literal", value: "@", description: "\"@\"" },
+ peg$c20 = ":",
+ peg$c21 = { type: "literal", value: ":", description: "\":\"" },
+ peg$c22 = function(n, e) { return {event: e, name: n}; },
+ peg$c23 = function(m, e) { return {event: e, mark: m}; },
+ peg$c24 = function(t, e) { return {event: e, target: t}; },
+ peg$c25 = function(e) { return {event: e}; },
+ peg$c26 = function(s) { return {signal: s}; },
+ peg$c27 = "rect",
+ peg$c28 = { type: "literal", value: "rect", description: "\"rect\"" },
+ peg$c29 = "symbol",
+ peg$c30 = { type: "literal", value: "symbol", description: "\"symbol\"" },
+ peg$c31 = "path",
+ peg$c32 = { type: "literal", value: "path", description: "\"path\"" },
+ peg$c33 = "arc",
+ peg$c34 = { type: "literal", value: "arc", description: "\"arc\"" },
+ peg$c35 = "area",
+ peg$c36 = { type: "literal", value: "area", description: "\"area\"" },
+ peg$c37 = "line",
+ peg$c38 = { type: "literal", value: "line", description: "\"line\"" },
+ peg$c39 = "rule",
+ peg$c40 = { type: "literal", value: "rule", description: "\"rule\"" },
+ peg$c41 = "image",
+ peg$c42 = { type: "literal", value: "image", description: "\"image\"" },
+ peg$c43 = "text",
+ peg$c44 = { type: "literal", value: "text", description: "\"text\"" },
+ peg$c45 = "group",
+ peg$c46 = { type: "literal", value: "group", description: "\"group\"" },
+ peg$c47 = "mousedown",
+ peg$c48 = { type: "literal", value: "mousedown", description: "\"mousedown\"" },
+ peg$c49 = "mouseup",
+ peg$c50 = { type: "literal", value: "mouseup", description: "\"mouseup\"" },
+ peg$c51 = "click",
+ peg$c52 = { type: "literal", value: "click", description: "\"click\"" },
+ peg$c53 = "dblclick",
+ peg$c54 = { type: "literal", value: "dblclick", description: "\"dblclick\"" },
+ peg$c55 = "wheel",
+ peg$c56 = { type: "literal", value: "wheel", description: "\"wheel\"" },
+ peg$c57 = "keydown",
+ peg$c58 = { type: "literal", value: "keydown", description: "\"keydown\"" },
+ peg$c59 = "keypress",
+ peg$c60 = { type: "literal", value: "keypress", description: "\"keypress\"" },
+ peg$c61 = "keyup",
+ peg$c62 = { type: "literal", value: "keyup", description: "\"keyup\"" },
+ peg$c63 = "mousewheel",
+ peg$c64 = { type: "literal", value: "mousewheel", description: "\"mousewheel\"" },
+ peg$c65 = "mousemove",
+ peg$c66 = { type: "literal", value: "mousemove", description: "\"mousemove\"" },
+ peg$c67 = "mouseout",
+ peg$c68 = { type: "literal", value: "mouseout", description: "\"mouseout\"" },
+ peg$c69 = "mouseover",
+ peg$c70 = { type: "literal", value: "mouseover", description: "\"mouseover\"" },
+ peg$c71 = "mouseenter",
+ peg$c72 = { type: "literal", value: "mouseenter", description: "\"mouseenter\"" },
+ peg$c73 = "touchstart",
+ peg$c74 = { type: "literal", value: "touchstart", description: "\"touchstart\"" },
+ peg$c75 = "touchmove",
+ peg$c76 = { type: "literal", value: "touchmove", description: "\"touchmove\"" },
+ peg$c77 = "touchend",
+ peg$c78 = { type: "literal", value: "touchend", description: "\"touchend\"" },
+ peg$c79 = "dragenter",
+ peg$c80 = { type: "literal", value: "dragenter", description: "\"dragenter\"" },
+ peg$c81 = "dragover",
+ peg$c82 = { type: "literal", value: "dragover", description: "\"dragover\"" },
+ peg$c83 = "dragleave",
+ peg$c84 = { type: "literal", value: "dragleave", description: "\"dragleave\"" },
+ peg$c85 = function(e) { return e; },
+ peg$c86 = /^[a-zA-Z0-9_\-]/,
+ peg$c87 = { type: "class", value: "[a-zA-Z0-9_-]", description: "[a-zA-Z0-9_-]" },
+ peg$c88 = function(n) { return n.join(""); },
+ peg$c89 = /^[a-zA-Z0-9\-_ #.>+~[\]=|\^$*]/,
+ peg$c90 = { type: "class", value: "[a-zA-Z0-9-_ #\\.\\>\\+~\\[\\]=|\\^\\$\\*]", description: "[a-zA-Z0-9-_ #\\.\\>\\+~\\[\\]=|\\^\\$\\*]" },
+ peg$c91 = function(c) { return c.join(""); },
+ peg$c92 = /^['"a-zA-Z0-9_().><=! \t-&|~]/,
+ peg$c93 = { type: "class", value: "['\"a-zA-Z0-9_\\(\\)\\.\\>\\<\\=\\! \\t-&|~]", description: "['\"a-zA-Z0-9_\\(\\)\\.\\>\\<\\=\\! \\t-&|~]" },
+ peg$c94 = function(v) { return v.join(""); },
+ peg$c95 = /^[ \t\r\n]/,
+ peg$c96 = { type: "class", value: "[ \\t\\r\\n]", description: "[ \\t\\r\\n]" },
+
+ peg$currPos = 0,
+ peg$savedPos = 0,
+ peg$posDetailsCache = [{ line: 1, column: 1, seenCR: false }],
+ peg$maxFailPos = 0,
+ peg$maxFailExpected = [],
+ peg$silentFails = 0,
+
+ peg$result;
+
+ if ("startRule" in options) {
+ if (!(options.startRule in peg$startRuleFunctions)) {
+ throw new Error("Can't start parsing from rule \"" + options.startRule + "\".");
+ }
+
+ peg$startRuleFunction = peg$startRuleFunctions[options.startRule];
+ }
+
+ function text() {
+ return input.substring(peg$savedPos, peg$currPos);
+ }
+
+ function location() {
+ return peg$computeLocation(peg$savedPos, peg$currPos);
+ }
+
+ function expected(description) {
+ throw peg$buildException(
+ null,
+ [{ type: "other", description: description }],
+ input.substring(peg$savedPos, peg$currPos),
+ peg$computeLocation(peg$savedPos, peg$currPos)
+ );
+ }
+
+ function error(message) {
+ throw peg$buildException(
+ message,
+ null,
+ input.substring(peg$savedPos, peg$currPos),
+ peg$computeLocation(peg$savedPos, peg$currPos)
+ );
+ }
+
+ function peg$computePosDetails(pos) {
+ var details = peg$posDetailsCache[pos],
+ p, ch;
+
+ if (details) {
+ return details;
+ } else {
+ p = pos - 1;
+ while (!peg$posDetailsCache[p]) {
+ p--;
+ }
+
+ details = peg$posDetailsCache[p];
+ details = {
+ line: details.line,
+ column: details.column,
+ seenCR: details.seenCR
+ };
+
+ while (p < pos) {
+ ch = input.charAt(p);
+ if (ch === "\n") {
+ if (!details.seenCR) { details.line++; }
+ details.column = 1;
+ details.seenCR = false;
+ } else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") {
+ details.line++;
+ details.column = 1;
+ details.seenCR = true;
+ } else {
+ details.column++;
+ details.seenCR = false;
+ }
+
+ p++;
+ }
+
+ peg$posDetailsCache[pos] = details;
+ return details;
+ }
+ }
+
+ function peg$computeLocation(startPos, endPos) {
+ var startPosDetails = peg$computePosDetails(startPos),
+ endPosDetails = peg$computePosDetails(endPos);
+
+ return {
+ start: {
+ offset: startPos,
+ line: startPosDetails.line,
+ column: startPosDetails.column
+ },
+ end: {
+ offset: endPos,
+ line: endPosDetails.line,
+ column: endPosDetails.column
+ }
+ };
+ }
+
+ function peg$fail(expected) {
+ if (peg$currPos < peg$maxFailPos) { return; }
+
+ if (peg$currPos > peg$maxFailPos) {
+ peg$maxFailPos = peg$currPos;
+ peg$maxFailExpected = [];
+ }
+
+ peg$maxFailExpected.push(expected);
+ }
+
+ function peg$buildException(message, expected, found, location) {
+ function cleanupExpected(expected) {
+ var i = 1;
+
+ expected.sort(function(a, b) {
+ if (a.description < b.description) {
+ return -1;
+ } else if (a.description > b.description) {
+ return 1;
+ } else {
+ return 0;
+ }
+ });
+
+ while (i < expected.length) {
+ if (expected[i - 1] === expected[i]) {
+ expected.splice(i, 1);
+ } else {
+ i++;
+ }
+ }
+ }
+
+ function buildMessage(expected, found) {
+ function stringEscape(s) {
+ function hex(ch) { return ch.charCodeAt(0).toString(16).toUpperCase(); }
+
+ return s
+ .replace(/\\/g, '\\\\')
+ .replace(/"/g, '\\"')
+ .replace(/\x08/g, '\\b')
+ .replace(/\t/g, '\\t')
+ .replace(/\n/g, '\\n')
+ .replace(/\f/g, '\\f')
+ .replace(/\r/g, '\\r')
+ .replace(/[\x00-\x07\x0B\x0E\x0F]/g, function(ch) { return '\\x0' + hex(ch); })
+ .replace(/[\x10-\x1F\x80-\xFF]/g, function(ch) { return '\\x' + hex(ch); })
+ .replace(/[\u0100-\u0FFF]/g, function(ch) { return '\\u0' + hex(ch); })
+ .replace(/[\u1000-\uFFFF]/g, function(ch) { return '\\u' + hex(ch); });
+ }
+
+ var expectedDescs = new Array(expected.length),
+ expectedDesc, foundDesc, i;
+
+ for (i = 0; i < expected.length; i++) {
+ expectedDescs[i] = expected[i].description;
+ }
+
+ expectedDesc = expected.length > 1
+ ? expectedDescs.slice(0, -1).join(", ")
+ + " or "
+ + expectedDescs[expected.length - 1]
+ : expectedDescs[0];
+
+ foundDesc = found ? "\"" + stringEscape(found) + "\"" : "end of input";
+
+ return "Expected " + expectedDesc + " but " + foundDesc + " found.";
+ }
+
+ if (expected !== null) {
+ cleanupExpected(expected);
+ }
+
+ return new peg$SyntaxError(
+ message !== null ? message : buildMessage(expected, found),
+ expected,
+ found,
+ location
+ );
+ }
+
+ function peg$parsestart() {
+ var s0;
+
+ s0 = peg$parsemerged();
+
+ return s0;
+ }
+
+ function peg$parsemerged() {
+ var s0, s1, s2, s3, s4, s5;
+
+ s0 = peg$currPos;
+ s1 = peg$parseordered();
+ if (s1 !== peg$FAILED) {
+ s2 = peg$parsesep();
+ if (s2 !== peg$FAILED) {
+ if (input.charCodeAt(peg$currPos) === 44) {
+ s3 = peg$c0;
+ peg$currPos++;
+ } else {
+ s3 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c1); }
+ }
+ if (s3 !== peg$FAILED) {
+ s4 = peg$parsesep();
+ if (s4 !== peg$FAILED) {
+ s5 = peg$parsemerged();
+ if (s5 !== peg$FAILED) {
+ peg$savedPos = s0;
+ s1 = peg$c2(s1, s5);
+ s0 = s1;
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ if (s0 === peg$FAILED) {
+ s0 = peg$currPos;
+ s1 = peg$parseordered();
+ if (s1 !== peg$FAILED) {
+ peg$savedPos = s0;
+ s1 = peg$c3(s1);
+ }
+ s0 = s1;
+ }
+
+ return s0;
+ }
+
+ function peg$parseordered() {
+ var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13;
+
+ s0 = peg$currPos;
+ if (input.charCodeAt(peg$currPos) === 91) {
+ s1 = peg$c4;
+ peg$currPos++;
+ } else {
+ s1 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c5); }
+ }
+ if (s1 !== peg$FAILED) {
+ s2 = peg$parsesep();
+ if (s2 !== peg$FAILED) {
+ s3 = peg$parsefiltered();
+ if (s3 !== peg$FAILED) {
+ s4 = peg$parsesep();
+ if (s4 !== peg$FAILED) {
+ if (input.charCodeAt(peg$currPos) === 44) {
+ s5 = peg$c0;
+ peg$currPos++;
+ } else {
+ s5 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c1); }
+ }
+ if (s5 !== peg$FAILED) {
+ s6 = peg$parsesep();
+ if (s6 !== peg$FAILED) {
+ s7 = peg$parsefiltered();
+ if (s7 !== peg$FAILED) {
+ s8 = peg$parsesep();
+ if (s8 !== peg$FAILED) {
+ if (input.charCodeAt(peg$currPos) === 93) {
+ s9 = peg$c6;
+ peg$currPos++;
+ } else {
+ s9 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c7); }
+ }
+ if (s9 !== peg$FAILED) {
+ s10 = peg$parsesep();
+ if (s10 !== peg$FAILED) {
+ if (input.charCodeAt(peg$currPos) === 62) {
+ s11 = peg$c8;
+ peg$currPos++;
+ } else {
+ s11 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c9); }
+ }
+ if (s11 !== peg$FAILED) {
+ s12 = peg$parsesep();
+ if (s12 !== peg$FAILED) {
+ s13 = peg$parseordered();
+ if (s13 !== peg$FAILED) {
+ peg$savedPos = s0;
+ s1 = peg$c10(s3, s7, s13);
+ s0 = s1;
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ if (s0 === peg$FAILED) {
+ s0 = peg$parsefiltered();
+ }
+
+ return s0;
+ }
+
+ function peg$parsefiltered() {
+ var s0, s1, s2, s3;
+
+ s0 = peg$currPos;
+ s1 = peg$parsestream();
+ if (s1 !== peg$FAILED) {
+ s2 = [];
+ s3 = peg$parsefilter();
+ if (s3 !== peg$FAILED) {
+ while (s3 !== peg$FAILED) {
+ s2.push(s3);
+ s3 = peg$parsefilter();
+ }
+ } else {
+ s2 = peg$FAILED;
+ }
+ if (s2 !== peg$FAILED) {
+ peg$savedPos = s0;
+ s1 = peg$c11(s1, s2);
+ s0 = s1;
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ if (s0 === peg$FAILED) {
+ s0 = peg$currPos;
+ s1 = peg$parsestream();
+ if (s1 !== peg$FAILED) {
+ peg$savedPos = s0;
+ s1 = peg$c12(s1);
+ }
+ s0 = s1;
+ }
+
+ return s0;
+ }
+
+ function peg$parsestream() {
+ var s0, s1, s2, s3, s4;
+
+ s0 = peg$currPos;
+ if (input.charCodeAt(peg$currPos) === 40) {
+ s1 = peg$c13;
+ peg$currPos++;
+ } else {
+ s1 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c14); }
+ }
+ if (s1 !== peg$FAILED) {
+ s2 = peg$parsemerged();
+ if (s2 !== peg$FAILED) {
+ if (input.charCodeAt(peg$currPos) === 41) {
+ s3 = peg$c15;
+ peg$currPos++;
+ } else {
+ s3 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c16); }
+ }
+ if (s3 !== peg$FAILED) {
+ peg$savedPos = s0;
+ s1 = peg$c17(s2);
+ s0 = s1;
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ if (s0 === peg$FAILED) {
+ s0 = peg$currPos;
+ if (input.charCodeAt(peg$currPos) === 64) {
+ s1 = peg$c18;
+ peg$currPos++;
+ } else {
+ s1 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c19); }
+ }
+ if (s1 !== peg$FAILED) {
+ s2 = peg$parsename();
+ if (s2 !== peg$FAILED) {
+ if (input.charCodeAt(peg$currPos) === 58) {
+ s3 = peg$c20;
+ peg$currPos++;
+ } else {
+ s3 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c21); }
+ }
+ if (s3 !== peg$FAILED) {
+ s4 = peg$parseeventType();
+ if (s4 !== peg$FAILED) {
+ peg$savedPos = s0;
+ s1 = peg$c22(s2, s4);
+ s0 = s1;
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ if (s0 === peg$FAILED) {
+ s0 = peg$currPos;
+ s1 = peg$parsemarkType();
+ if (s1 !== peg$FAILED) {
+ if (input.charCodeAt(peg$currPos) === 58) {
+ s2 = peg$c20;
+ peg$currPos++;
+ } else {
+ s2 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c21); }
+ }
+ if (s2 !== peg$FAILED) {
+ s3 = peg$parseeventType();
+ if (s3 !== peg$FAILED) {
+ peg$savedPos = s0;
+ s1 = peg$c23(s1, s3);
+ s0 = s1;
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ if (s0 === peg$FAILED) {
+ s0 = peg$currPos;
+ s1 = peg$parsecss();
+ if (s1 !== peg$FAILED) {
+ if (input.charCodeAt(peg$currPos) === 58) {
+ s2 = peg$c20;
+ peg$currPos++;
+ } else {
+ s2 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c21); }
+ }
+ if (s2 !== peg$FAILED) {
+ s3 = peg$parseeventType();
+ if (s3 !== peg$FAILED) {
+ peg$savedPos = s0;
+ s1 = peg$c24(s1, s3);
+ s0 = s1;
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ if (s0 === peg$FAILED) {
+ s0 = peg$currPos;
+ s1 = peg$parseeventType();
+ if (s1 !== peg$FAILED) {
+ peg$savedPos = s0;
+ s1 = peg$c25(s1);
+ }
+ s0 = s1;
+ if (s0 === peg$FAILED) {
+ s0 = peg$currPos;
+ s1 = peg$parsename();
+ if (s1 !== peg$FAILED) {
+ peg$savedPos = s0;
+ s1 = peg$c26(s1);
+ }
+ s0 = s1;
+ }
+ }
+ }
+ }
+ }
+
+ return s0;
+ }
+
+ function peg$parsemarkType() {
+ var s0;
+
+ if (input.substr(peg$currPos, 4) === peg$c27) {
+ s0 = peg$c27;
+ peg$currPos += 4;
+ } else {
+ s0 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c28); }
+ }
+ if (s0 === peg$FAILED) {
+ if (input.substr(peg$currPos, 6) === peg$c29) {
+ s0 = peg$c29;
+ peg$currPos += 6;
+ } else {
+ s0 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c30); }
+ }
+ if (s0 === peg$FAILED) {
+ if (input.substr(peg$currPos, 4) === peg$c31) {
+ s0 = peg$c31;
+ peg$currPos += 4;
+ } else {
+ s0 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c32); }
+ }
+ if (s0 === peg$FAILED) {
+ if (input.substr(peg$currPos, 3) === peg$c33) {
+ s0 = peg$c33;
+ peg$currPos += 3;
+ } else {
+ s0 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c34); }
+ }
+ if (s0 === peg$FAILED) {
+ if (input.substr(peg$currPos, 4) === peg$c35) {
+ s0 = peg$c35;
+ peg$currPos += 4;
+ } else {
+ s0 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c36); }
+ }
+ if (s0 === peg$FAILED) {
+ if (input.substr(peg$currPos, 4) === peg$c37) {
+ s0 = peg$c37;
+ peg$currPos += 4;
+ } else {
+ s0 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c38); }
+ }
+ if (s0 === peg$FAILED) {
+ if (input.substr(peg$currPos, 4) === peg$c39) {
+ s0 = peg$c39;
+ peg$currPos += 4;
+ } else {
+ s0 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c40); }
+ }
+ if (s0 === peg$FAILED) {
+ if (input.substr(peg$currPos, 5) === peg$c41) {
+ s0 = peg$c41;
+ peg$currPos += 5;
+ } else {
+ s0 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c42); }
+ }
+ if (s0 === peg$FAILED) {
+ if (input.substr(peg$currPos, 4) === peg$c43) {
+ s0 = peg$c43;
+ peg$currPos += 4;
+ } else {
+ s0 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c44); }
+ }
+ if (s0 === peg$FAILED) {
+ if (input.substr(peg$currPos, 5) === peg$c45) {
+ s0 = peg$c45;
+ peg$currPos += 5;
+ } else {
+ s0 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c46); }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return s0;
+ }
+
+ function peg$parseeventType() {
+ var s0;
+
+ if (input.substr(peg$currPos, 9) === peg$c47) {
+ s0 = peg$c47;
+ peg$currPos += 9;
+ } else {
+ s0 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c48); }
+ }
+ if (s0 === peg$FAILED) {
+ if (input.substr(peg$currPos, 7) === peg$c49) {
+ s0 = peg$c49;
+ peg$currPos += 7;
+ } else {
+ s0 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c50); }
+ }
+ if (s0 === peg$FAILED) {
+ if (input.substr(peg$currPos, 5) === peg$c51) {
+ s0 = peg$c51;
+ peg$currPos += 5;
+ } else {
+ s0 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c52); }
+ }
+ if (s0 === peg$FAILED) {
+ if (input.substr(peg$currPos, 8) === peg$c53) {
+ s0 = peg$c53;
+ peg$currPos += 8;
+ } else {
+ s0 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c54); }
+ }
+ if (s0 === peg$FAILED) {
+ if (input.substr(peg$currPos, 5) === peg$c55) {
+ s0 = peg$c55;
+ peg$currPos += 5;
+ } else {
+ s0 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c56); }
+ }
+ if (s0 === peg$FAILED) {
+ if (input.substr(peg$currPos, 7) === peg$c57) {
+ s0 = peg$c57;
+ peg$currPos += 7;
+ } else {
+ s0 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c58); }
+ }
+ if (s0 === peg$FAILED) {
+ if (input.substr(peg$currPos, 8) === peg$c59) {
+ s0 = peg$c59;
+ peg$currPos += 8;
+ } else {
+ s0 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c60); }
+ }
+ if (s0 === peg$FAILED) {
+ if (input.substr(peg$currPos, 5) === peg$c61) {
+ s0 = peg$c61;
+ peg$currPos += 5;
+ } else {
+ s0 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c62); }
+ }
+ if (s0 === peg$FAILED) {
+ if (input.substr(peg$currPos, 10) === peg$c63) {
+ s0 = peg$c63;
+ peg$currPos += 10;
+ } else {
+ s0 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c64); }
+ }
+ if (s0 === peg$FAILED) {
+ if (input.substr(peg$currPos, 9) === peg$c65) {
+ s0 = peg$c65;
+ peg$currPos += 9;
+ } else {
+ s0 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c66); }
+ }
+ if (s0 === peg$FAILED) {
+ if (input.substr(peg$currPos, 8) === peg$c67) {
+ s0 = peg$c67;
+ peg$currPos += 8;
+ } else {
+ s0 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c68); }
+ }
+ if (s0 === peg$FAILED) {
+ if (input.substr(peg$currPos, 9) === peg$c69) {
+ s0 = peg$c69;
+ peg$currPos += 9;
+ } else {
+ s0 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c70); }
+ }
+ if (s0 === peg$FAILED) {
+ if (input.substr(peg$currPos, 10) === peg$c71) {
+ s0 = peg$c71;
+ peg$currPos += 10;
+ } else {
+ s0 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c72); }
+ }
+ if (s0 === peg$FAILED) {
+ if (input.substr(peg$currPos, 10) === peg$c73) {
+ s0 = peg$c73;
+ peg$currPos += 10;
+ } else {
+ s0 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c74); }
+ }
+ if (s0 === peg$FAILED) {
+ if (input.substr(peg$currPos, 9) === peg$c75) {
+ s0 = peg$c75;
+ peg$currPos += 9;
+ } else {
+ s0 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c76); }
+ }
+ if (s0 === peg$FAILED) {
+ if (input.substr(peg$currPos, 8) === peg$c77) {
+ s0 = peg$c77;
+ peg$currPos += 8;
+ } else {
+ s0 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c78); }
+ }
+ if (s0 === peg$FAILED) {
+ if (input.substr(peg$currPos, 9) === peg$c79) {
+ s0 = peg$c79;
+ peg$currPos += 9;
+ } else {
+ s0 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c80); }
+ }
+ if (s0 === peg$FAILED) {
+ if (input.substr(peg$currPos, 8) === peg$c81) {
+ s0 = peg$c81;
+ peg$currPos += 8;
+ } else {
+ s0 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c82); }
+ }
+ if (s0 === peg$FAILED) {
+ if (input.substr(peg$currPos, 9) === peg$c83) {
+ s0 = peg$c83;
+ peg$currPos += 9;
+ } else {
+ s0 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c84); }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return s0;
+ }
+
+ function peg$parsefilter() {
+ var s0, s1, s2, s3;
+
+ s0 = peg$currPos;
+ if (input.charCodeAt(peg$currPos) === 91) {
+ s1 = peg$c4;
+ peg$currPos++;
+ } else {
+ s1 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c5); }
+ }
+ if (s1 !== peg$FAILED) {
+ s2 = peg$parseexpr();
+ if (s2 !== peg$FAILED) {
+ if (input.charCodeAt(peg$currPos) === 93) {
+ s3 = peg$c6;
+ peg$currPos++;
+ } else {
+ s3 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c7); }
+ }
+ if (s3 !== peg$FAILED) {
+ peg$savedPos = s0;
+ s1 = peg$c85(s2);
+ s0 = s1;
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+
+ return s0;
+ }
+
+ function peg$parsename() {
+ var s0, s1, s2;
+
+ s0 = peg$currPos;
+ s1 = [];
+ if (peg$c86.test(input.charAt(peg$currPos))) {
+ s2 = input.charAt(peg$currPos);
+ peg$currPos++;
+ } else {
+ s2 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c87); }
+ }
+ if (s2 !== peg$FAILED) {
+ while (s2 !== peg$FAILED) {
+ s1.push(s2);
+ if (peg$c86.test(input.charAt(peg$currPos))) {
+ s2 = input.charAt(peg$currPos);
+ peg$currPos++;
+ } else {
+ s2 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c87); }
+ }
+ }
+ } else {
+ s1 = peg$FAILED;
+ }
+ if (s1 !== peg$FAILED) {
+ peg$savedPos = s0;
+ s1 = peg$c88(s1);
+ }
+ s0 = s1;
+
+ return s0;
+ }
+
+ function peg$parsecss() {
+ var s0, s1, s2;
+
+ s0 = peg$currPos;
+ s1 = [];
+ if (peg$c89.test(input.charAt(peg$currPos))) {
+ s2 = input.charAt(peg$currPos);
+ peg$currPos++;
+ } else {
+ s2 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c90); }
+ }
+ if (s2 !== peg$FAILED) {
+ while (s2 !== peg$FAILED) {
+ s1.push(s2);
+ if (peg$c89.test(input.charAt(peg$currPos))) {
+ s2 = input.charAt(peg$currPos);
+ peg$currPos++;
+ } else {
+ s2 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c90); }
+ }
+ }
+ } else {
+ s1 = peg$FAILED;
+ }
+ if (s1 !== peg$FAILED) {
+ peg$savedPos = s0;
+ s1 = peg$c91(s1);
+ }
+ s0 = s1;
+
+ return s0;
+ }
+
+ function peg$parseexpr() {
+ var s0, s1, s2;
+
+ s0 = peg$currPos;
+ s1 = [];
+ if (peg$c92.test(input.charAt(peg$currPos))) {
+ s2 = input.charAt(peg$currPos);
+ peg$currPos++;
+ } else {
+ s2 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c93); }
+ }
+ if (s2 !== peg$FAILED) {
+ while (s2 !== peg$FAILED) {
+ s1.push(s2);
+ if (peg$c92.test(input.charAt(peg$currPos))) {
+ s2 = input.charAt(peg$currPos);
+ peg$currPos++;
+ } else {
+ s2 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c93); }
+ }
+ }
+ } else {
+ s1 = peg$FAILED;
+ }
+ if (s1 !== peg$FAILED) {
+ peg$savedPos = s0;
+ s1 = peg$c94(s1);
+ }
+ s0 = s1;
+
+ return s0;
+ }
+
+ function peg$parsesep() {
+ var s0, s1;
+
+ s0 = [];
+ if (peg$c95.test(input.charAt(peg$currPos))) {
+ s1 = input.charAt(peg$currPos);
+ peg$currPos++;
+ } else {
+ s1 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c96); }
+ }
+ while (s1 !== peg$FAILED) {
+ s0.push(s1);
+ if (peg$c95.test(input.charAt(peg$currPos))) {
+ s1 = input.charAt(peg$currPos);
+ peg$currPos++;
+ } else {
+ s1 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c96); }
+ }
+ }
+
+ return s0;
+ }
+
+ peg$result = peg$startRuleFunction();
+
+ if (peg$result !== peg$FAILED && peg$currPos === input.length) {
+ return peg$result;
+ } else {
+ if (peg$result !== peg$FAILED && peg$currPos < input.length) {
+ peg$fail({ type: "end", description: "end of input" });
+ }
+
+ throw peg$buildException(
+ null,
+ peg$maxFailExpected,
+ peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null,
+ peg$maxFailPos < input.length
+ ? peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1)
+ : peg$computeLocation(peg$maxFailPos, peg$maxFailPos)
+ );
+ }
+ }
+
+ return {
+ SyntaxError: peg$SyntaxError,
+ parse: peg$parse
+ };
+})();
+
+},{}],43:[function(require,module,exports){
+function toMap(list) {
+ var map = {}, i, n;
+ for (i=0, n=list.length; i 0) {
+ return id;
+ }
+ if (constants.hasOwnProperty(id)) {
+ return constants[id];
+ }
+ if (idWhiteList) {
+ if (idWhiteList.hasOwnProperty(id)) {
+ return id;
+ } else {
+ globals[id] = 1;
+ return lookupGlobal(id);
+ }
+ }
+ if (idBlackList && idBlackList.hasOwnProperty(id)) {
+ throw new Error('Illegal identifier: ' + id);
+ }
+ return id;
+ },
+ 'Program': function(n) {
+ return n.body.map(codegen).join('\n');
+ },
+ 'MemberExpression': function(n) {
+ var d = !n.computed;
+ var o = codegen(n.object);
+ if (d) memberDepth += 1;
+ var p = codegen(n.property);
+ if (o === FIELD_VAR) { fields[p] = 1; } // HACKish...
+ if (d) memberDepth -= 1;
+ return o + (d ? '.'+p : '['+p+']');
+ },
+ 'CallExpression': function(n) {
+ if (n.callee.type !== 'Identifier') {
+ throw new Error('Illegal callee type: ' + n.callee.type);
+ }
+ var callee = n.callee.name;
+ var args = n.arguments;
+ var fn = functions.hasOwnProperty(callee) && functions[callee];
+ if (!fn) throw new Error('Unrecognized function: ' + callee);
+ return fn instanceof Function ?
+ fn(args, globals, fields, dataSources) :
+ fn + '(' + args.map(codegen).join(',') + ')';
+ },
+ 'ArrayExpression': function(n) {
+ return '[' + n.elements.map(codegen).join(',') + ']';
+ },
+ 'BinaryExpression': function(n) {
+ return '(' + codegen(n.left) + n.operator + codegen(n.right) + ')';
+ },
+ 'UnaryExpression': function(n) {
+ return '(' + n.operator + codegen(n.argument) + ')';
+ },
+ 'ConditionalExpression': function(n) {
+ return '(' + codegen(n.test) +
+ '?' + codegen(n.consequent) +
+ ':' + codegen(n.alternate) +
+ ')';
+ },
+ 'LogicalExpression': function(n) {
+ return '(' + codegen(n.left) + n.operator + codegen(n.right) + ')';
+ },
+ 'ObjectExpression': function(n) {
+ return '{' + n.properties.map(codegen).join(',') + '}';
+ },
+ 'Property': function(n) {
+ memberDepth += 1;
+ var k = codegen(n.key);
+ memberDepth -= 1;
+ return k + ':' + codegen(n.value);
+ },
+ 'ExpressionStatement': function(n) {
+ return codegen(n.expression);
+ }
+ };
+
+ codegen_wrap.functions = functions;
+ codegen_wrap.functionDefs = functionDefs;
+ codegen_wrap.constants = constants;
+ return codegen_wrap;
+};
+
+},{"./constants":44,"./functions":45}],44:[function(require,module,exports){
+module.exports = {
+ 'NaN': 'NaN',
+ 'E': 'Math.E',
+ 'LN2': 'Math.LN2',
+ 'LN10': 'Math.LN10',
+ 'LOG2E': 'Math.LOG2E',
+ 'LOG10E': 'Math.LOG10E',
+ 'PI': 'Math.PI',
+ 'SQRT1_2': 'Math.SQRT1_2',
+ 'SQRT2': 'Math.SQRT2'
+};
+},{}],45:[function(require,module,exports){
+module.exports = function(codegen) {
+
+ function fncall(name, args, cast, type) {
+ var obj = codegen(args[0]);
+ if (cast) {
+ obj = cast + '(' + obj + ')';
+ if (cast.lastIndexOf('new ', 0) === 0) obj = '(' + obj + ')';
+ }
+ return obj + '.' + name + (type < 0 ? '' : type === 0 ?
+ '()' :
+ '(' + args.slice(1).map(codegen).join(',') + ')');
+ }
+
+ function fn(name, cast, type) {
+ return function(args) {
+ return fncall(name, args, cast, type);
+ };
+ }
+
+ var DATE = 'new Date',
+ STRING = 'String',
+ REGEXP = 'RegExp';
+
+ return {
+ // MATH functions
+ 'isNaN': 'isNaN',
+ 'isFinite': 'isFinite',
+ 'abs': 'Math.abs',
+ 'acos': 'Math.acos',
+ 'asin': 'Math.asin',
+ 'atan': 'Math.atan',
+ 'atan2': 'Math.atan2',
+ 'ceil': 'Math.ceil',
+ 'cos': 'Math.cos',
+ 'exp': 'Math.exp',
+ 'floor': 'Math.floor',
+ 'log': 'Math.log',
+ 'max': 'Math.max',
+ 'min': 'Math.min',
+ 'pow': 'Math.pow',
+ 'random': 'Math.random',
+ 'round': 'Math.round',
+ 'sin': 'Math.sin',
+ 'sqrt': 'Math.sqrt',
+ 'tan': 'Math.tan',
+
+ 'clamp': function(args) {
+ if (args.length < 3)
+ throw new Error('Missing arguments to clamp function.');
+ if (args.length > 3)
+ throw new Error('Too many arguments to clamp function.');
+ var a = args.map(codegen);
+ return 'Math.max('+a[1]+', Math.min('+a[2]+','+a[0]+'))';
+ },
+
+ // DATE functions
+ 'now': 'Date.now',
+ 'utc': 'Date.UTC',
+ 'datetime': DATE,
+ 'date': fn('getDate', DATE, 0),
+ 'day': fn('getDay', DATE, 0),
+ 'year': fn('getFullYear', DATE, 0),
+ 'month': fn('getMonth', DATE, 0),
+ 'hours': fn('getHours', DATE, 0),
+ 'minutes': fn('getMinutes', DATE, 0),
+ 'seconds': fn('getSeconds', DATE, 0),
+ 'milliseconds': fn('getMilliseconds', DATE, 0),
+ 'time': fn('getTime', DATE, 0),
+ 'timezoneoffset': fn('getTimezoneOffset', DATE, 0),
+ 'utcdate': fn('getUTCDate', DATE, 0),
+ 'utcday': fn('getUTCDay', DATE, 0),
+ 'utcyear': fn('getUTCFullYear', DATE, 0),
+ 'utcmonth': fn('getUTCMonth', DATE, 0),
+ 'utchours': fn('getUTCHours', DATE, 0),
+ 'utcminutes': fn('getUTCMinutes', DATE, 0),
+ 'utcseconds': fn('getUTCSeconds', DATE, 0),
+ 'utcmilliseconds': fn('getUTCMilliseconds', DATE, 0),
+
+ // shared sequence functions
+ 'length': fn('length', null, -1),
+ 'indexof': fn('indexOf', null),
+ 'lastindexof': fn('lastIndexOf', null),
+
+ // STRING functions
+ 'parseFloat': 'parseFloat',
+ 'parseInt': 'parseInt',
+ 'upper': fn('toUpperCase', STRING, 0),
+ 'lower': fn('toLowerCase', STRING, 0),
+ 'slice': fn('slice', STRING),
+ 'substring': fn('substring', STRING),
+ 'replace': fn('replace', STRING),
+
+ // REGEXP functions
+ 'regexp': REGEXP,
+ 'test': fn('test', REGEXP),
+
+ // Control Flow functions
+ 'if': function(args) {
+ if (args.length < 3)
+ throw new Error('Missing arguments to if function.');
+ if (args.length > 3)
+ throw new Error('Too many arguments to if function.');
+ var a = args.map(codegen);
+ return a[0]+'?'+a[1]+':'+a[2];
+ }
+ };
+};
+
+},{}],46:[function(require,module,exports){
+var parser = require('./parser'),
+ codegen = require('./codegen');
+
+var expr = module.exports = {
+ parse: function(input, opt) {
+ return parser.parse('('+input+')', opt);
+ },
+ code: function(opt) {
+ return codegen(opt);
+ },
+ compiler: function(args, opt) {
+ args = args.slice();
+ var generator = codegen(opt),
+ len = args.length,
+ compile = function(str) {
+ var value = generator(expr.parse(str));
+ args[len] = '"use strict"; return (' + value.code + ');';
+ var fn = Function.apply(null, args);
+ value.fn = (args.length > 8) ?
+ function() { return fn.apply(value, arguments); } :
+ function(a, b, c, d, e, f, g) {
+ return fn.call(value, a, b, c, d, e, f, g);
+ }; // call often faster than apply, use if args low enough
+ return value;
+ };
+ compile.codegen = generator;
+ return compile;
+ },
+ functions: require('./functions'),
+ constants: require('./constants')
+};
+},{"./codegen":43,"./constants":44,"./functions":45,"./parser":47}],47:[function(require,module,exports){
+/*
+ The following expression parser is based on Esprima (http://esprima.org/).
+ Original header comment and license for Esprima is included here:
+
+ Copyright (C) 2013 Ariya Hidayat
+ Copyright (C) 2013 Thaddee Tyl
+ Copyright (C) 2013 Mathias Bynens
+ Copyright (C) 2012 Ariya Hidayat
+ Copyright (C) 2012 Mathias Bynens
+ Copyright (C) 2012 Joost-Wim Boekesteijn
+ Copyright (C) 2012 Kris Kowal
+ Copyright (C) 2012 Yusuke Suzuki
+ Copyright (C) 2012 Arpad Borsos
+ Copyright (C) 2011 Ariya Hidayat
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/* istanbul ignore next */
+module.exports = (function() {
+ 'use strict';
+
+ var Token,
+ TokenName,
+ Syntax,
+ PropertyKind,
+ Messages,
+ Regex,
+ source,
+ strict,
+ index,
+ lineNumber,
+ lineStart,
+ length,
+ lookahead,
+ state,
+ extra;
+
+ Token = {
+ BooleanLiteral: 1,
+ EOF: 2,
+ Identifier: 3,
+ Keyword: 4,
+ NullLiteral: 5,
+ NumericLiteral: 6,
+ Punctuator: 7,
+ StringLiteral: 8,
+ RegularExpression: 9
+ };
+
+ TokenName = {};
+ TokenName[Token.BooleanLiteral] = 'Boolean';
+ TokenName[Token.EOF] = '';
+ TokenName[Token.Identifier] = 'Identifier';
+ TokenName[Token.Keyword] = 'Keyword';
+ TokenName[Token.NullLiteral] = 'Null';
+ TokenName[Token.NumericLiteral] = 'Numeric';
+ TokenName[Token.Punctuator] = 'Punctuator';
+ TokenName[Token.StringLiteral] = 'String';
+ TokenName[Token.RegularExpression] = 'RegularExpression';
+
+ Syntax = {
+ AssignmentExpression: 'AssignmentExpression',
+ ArrayExpression: 'ArrayExpression',
+ BinaryExpression: 'BinaryExpression',
+ CallExpression: 'CallExpression',
+ ConditionalExpression: 'ConditionalExpression',
+ ExpressionStatement: 'ExpressionStatement',
+ Identifier: 'Identifier',
+ Literal: 'Literal',
+ LogicalExpression: 'LogicalExpression',
+ MemberExpression: 'MemberExpression',
+ ObjectExpression: 'ObjectExpression',
+ Program: 'Program',
+ Property: 'Property',
+ UnaryExpression: 'UnaryExpression'
+ };
+
+ PropertyKind = {
+ Data: 1,
+ Get: 2,
+ Set: 4
+ };
+
+ // Error messages should be identical to V8.
+ Messages = {
+ UnexpectedToken: 'Unexpected token %0',
+ UnexpectedNumber: 'Unexpected number',
+ UnexpectedString: 'Unexpected string',
+ UnexpectedIdentifier: 'Unexpected identifier',
+ UnexpectedReserved: 'Unexpected reserved word',
+ UnexpectedEOS: 'Unexpected end of input',
+ NewlineAfterThrow: 'Illegal newline after throw',
+ InvalidRegExp: 'Invalid regular expression',
+ UnterminatedRegExp: 'Invalid regular expression: missing /',
+ InvalidLHSInAssignment: 'Invalid left-hand side in assignment',
+ InvalidLHSInForIn: 'Invalid left-hand side in for-in',
+ MultipleDefaultsInSwitch: 'More than one default clause in switch statement',
+ NoCatchOrFinally: 'Missing catch or finally after try',
+ UnknownLabel: 'Undefined label \'%0\'',
+ Redeclaration: '%0 \'%1\' has already been declared',
+ IllegalContinue: 'Illegal continue statement',
+ IllegalBreak: 'Illegal break statement',
+ IllegalReturn: 'Illegal return statement',
+ StrictModeWith: 'Strict mode code may not include a with statement',
+ StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode',
+ StrictVarName: 'Variable name may not be eval or arguments in strict mode',
+ StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode',
+ StrictParamDupe: 'Strict mode function may not have duplicate parameter names',
+ StrictFunctionName: 'Function name may not be eval or arguments in strict mode',
+ StrictOctalLiteral: 'Octal literals are not allowed in strict mode.',
+ StrictDelete: 'Delete of an unqualified identifier in strict mode.',
+ StrictDuplicateProperty: 'Duplicate data property in object literal not allowed in strict mode',
+ AccessorDataProperty: 'Object literal may not have data and accessor property with the same name',
+ AccessorGetSet: 'Object literal may not have multiple get/set accessors with the same name',
+ StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode',
+ StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode',
+ StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode',
+ StrictReservedWord: 'Use of future reserved word in strict mode'
+ };
+
+ // See also tools/generate-unicode-regex.py.
+ Regex = {
+ NonAsciiIdentifierStart: new RegExp('[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]'),
+ NonAsciiIdentifierPart: new RegExp('[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0-\u08B2\u08E4-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58\u0C59\u0C60-\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D01-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D60-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1CF8\u1CF9\u1D00-\u1DF5\u1DFC-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099\u309A\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA69D\uA69F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2D\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]')
+ };
+
+ // Ensure the condition is true, otherwise throw an error.
+ // This is only to have a better contract semantic, i.e. another safety net
+ // to catch a logic error. The condition shall be fulfilled in normal case.
+ // Do NOT use this to enforce a certain condition on any user input.
+
+ function assert(condition, message) {
+ if (!condition) {
+ throw new Error('ASSERT: ' + message);
+ }
+ }
+
+ function isDecimalDigit(ch) {
+ return (ch >= 0x30 && ch <= 0x39); // 0..9
+ }
+
+ function isHexDigit(ch) {
+ return '0123456789abcdefABCDEF'.indexOf(ch) >= 0;
+ }
+
+ function isOctalDigit(ch) {
+ return '01234567'.indexOf(ch) >= 0;
+ }
+
+ // 7.2 White Space
+
+ function isWhiteSpace(ch) {
+ return (ch === 0x20) || (ch === 0x09) || (ch === 0x0B) || (ch === 0x0C) || (ch === 0xA0) ||
+ (ch >= 0x1680 && [0x1680, 0x180E, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202F, 0x205F, 0x3000, 0xFEFF].indexOf(ch) >= 0);
+ }
+
+ // 7.3 Line Terminators
+
+ function isLineTerminator(ch) {
+ return (ch === 0x0A) || (ch === 0x0D) || (ch === 0x2028) || (ch === 0x2029);
+ }
+
+ // 7.6 Identifier Names and Identifiers
+
+ function isIdentifierStart(ch) {
+ return (ch === 0x24) || (ch === 0x5F) || // $ (dollar) and _ (underscore)
+ (ch >= 0x41 && ch <= 0x5A) || // A..Z
+ (ch >= 0x61 && ch <= 0x7A) || // a..z
+ (ch === 0x5C) || // \ (backslash)
+ ((ch >= 0x80) && Regex.NonAsciiIdentifierStart.test(String.fromCharCode(ch)));
+ }
+
+ function isIdentifierPart(ch) {
+ return (ch === 0x24) || (ch === 0x5F) || // $ (dollar) and _ (underscore)
+ (ch >= 0x41 && ch <= 0x5A) || // A..Z
+ (ch >= 0x61 && ch <= 0x7A) || // a..z
+ (ch >= 0x30 && ch <= 0x39) || // 0..9
+ (ch === 0x5C) || // \ (backslash)
+ ((ch >= 0x80) && Regex.NonAsciiIdentifierPart.test(String.fromCharCode(ch)));
+ }
+
+ // 7.6.1.2 Future Reserved Words
+
+ function isFutureReservedWord(id) {
+ switch (id) {
+ case 'class':
+ case 'enum':
+ case 'export':
+ case 'extends':
+ case 'import':
+ case 'super':
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ function isStrictModeReservedWord(id) {
+ switch (id) {
+ case 'implements':
+ case 'interface':
+ case 'package':
+ case 'private':
+ case 'protected':
+ case 'public':
+ case 'static':
+ case 'yield':
+ case 'let':
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ // 7.6.1.1 Keywords
+
+ function isKeyword(id) {
+ if (strict && isStrictModeReservedWord(id)) {
+ return true;
+ }
+
+ // 'const' is specialized as Keyword in V8.
+ // 'yield' and 'let' are for compatiblity with SpiderMonkey and ES.next.
+ // Some others are from future reserved words.
+
+ switch (id.length) {
+ case 2:
+ return (id === 'if') || (id === 'in') || (id === 'do');
+ case 3:
+ return (id === 'var') || (id === 'for') || (id === 'new') ||
+ (id === 'try') || (id === 'let');
+ case 4:
+ return (id === 'this') || (id === 'else') || (id === 'case') ||
+ (id === 'void') || (id === 'with') || (id === 'enum');
+ case 5:
+ return (id === 'while') || (id === 'break') || (id === 'catch') ||
+ (id === 'throw') || (id === 'const') || (id === 'yield') ||
+ (id === 'class') || (id === 'super');
+ case 6:
+ return (id === 'return') || (id === 'typeof') || (id === 'delete') ||
+ (id === 'switch') || (id === 'export') || (id === 'import');
+ case 7:
+ return (id === 'default') || (id === 'finally') || (id === 'extends');
+ case 8:
+ return (id === 'function') || (id === 'continue') || (id === 'debugger');
+ case 10:
+ return (id === 'instanceof');
+ default:
+ return false;
+ }
+ }
+
+ function skipComment() {
+ var ch, start;
+
+ start = (index === 0);
+ while (index < length) {
+ ch = source.charCodeAt(index);
+
+ if (isWhiteSpace(ch)) {
+ ++index;
+ } else if (isLineTerminator(ch)) {
+ ++index;
+ if (ch === 0x0D && source.charCodeAt(index) === 0x0A) {
+ ++index;
+ }
+ ++lineNumber;
+ lineStart = index;
+ start = true;
+ } else {
+ break;
+ }
+ }
+ }
+
+ function scanHexEscape(prefix) {
+ var i, len, ch, code = 0;
+
+ len = (prefix === 'u') ? 4 : 2;
+ for (i = 0; i < len; ++i) {
+ if (index < length && isHexDigit(source[index])) {
+ ch = source[index++];
+ code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
+ } else {
+ return '';
+ }
+ }
+ return String.fromCharCode(code);
+ }
+
+ function scanUnicodeCodePointEscape() {
+ var ch, code, cu1, cu2;
+
+ ch = source[index];
+ code = 0;
+
+ // At least, one hex digit is required.
+ if (ch === '}') {
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ }
+
+ while (index < length) {
+ ch = source[index++];
+ if (!isHexDigit(ch)) {
+ break;
+ }
+ code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
+ }
+
+ if (code > 0x10FFFF || ch !== '}') {
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ }
+
+ // UTF-16 Encoding
+ if (code <= 0xFFFF) {
+ return String.fromCharCode(code);
+ }
+ cu1 = ((code - 0x10000) >> 10) + 0xD800;
+ cu2 = ((code - 0x10000) & 1023) + 0xDC00;
+ return String.fromCharCode(cu1, cu2);
+ }
+
+ function getEscapedIdentifier() {
+ var ch, id;
+
+ ch = source.charCodeAt(index++);
+ id = String.fromCharCode(ch);
+
+ // '\u' (U+005C, U+0075) denotes an escaped character.
+ if (ch === 0x5C) {
+ if (source.charCodeAt(index) !== 0x75) {
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ }
+ ++index;
+ ch = scanHexEscape('u');
+ if (!ch || ch === '\\' || !isIdentifierStart(ch.charCodeAt(0))) {
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ }
+ id = ch;
+ }
+
+ while (index < length) {
+ ch = source.charCodeAt(index);
+ if (!isIdentifierPart(ch)) {
+ break;
+ }
+ ++index;
+ id += String.fromCharCode(ch);
+
+ // '\u' (U+005C, U+0075) denotes an escaped character.
+ if (ch === 0x5C) {
+ id = id.substr(0, id.length - 1);
+ if (source.charCodeAt(index) !== 0x75) {
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ }
+ ++index;
+ ch = scanHexEscape('u');
+ if (!ch || ch === '\\' || !isIdentifierPart(ch.charCodeAt(0))) {
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ }
+ id += ch;
+ }
+ }
+
+ return id;
+ }
+
+ function getIdentifier() {
+ var start, ch;
+
+ start = index++;
+ while (index < length) {
+ ch = source.charCodeAt(index);
+ if (ch === 0x5C) {
+ // Blackslash (U+005C) marks Unicode escape sequence.
+ index = start;
+ return getEscapedIdentifier();
+ }
+ if (isIdentifierPart(ch)) {
+ ++index;
+ } else {
+ break;
+ }
+ }
+
+ return source.slice(start, index);
+ }
+
+ function scanIdentifier() {
+ var start, id, type;
+
+ start = index;
+
+ // Backslash (U+005C) starts an escaped character.
+ id = (source.charCodeAt(index) === 0x5C) ? getEscapedIdentifier() : getIdentifier();
+
+ // There is no keyword or literal with only one character.
+ // Thus, it must be an identifier.
+ if (id.length === 1) {
+ type = Token.Identifier;
+ } else if (isKeyword(id)) {
+ type = Token.Keyword;
+ } else if (id === 'null') {
+ type = Token.NullLiteral;
+ } else if (id === 'true' || id === 'false') {
+ type = Token.BooleanLiteral;
+ } else {
+ type = Token.Identifier;
+ }
+
+ return {
+ type: type,
+ value: id,
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ start: start,
+ end: index
+ };
+ }
+
+ // 7.7 Punctuators
+
+ function scanPunctuator() {
+ var start = index,
+ code = source.charCodeAt(index),
+ code2,
+ ch1 = source[index],
+ ch2,
+ ch3,
+ ch4;
+
+ switch (code) {
+
+ // Check for most common single-character punctuators.
+ case 0x2E: // . dot
+ case 0x28: // ( open bracket
+ case 0x29: // ) close bracket
+ case 0x3B: // ; semicolon
+ case 0x2C: // , comma
+ case 0x7B: // { open curly brace
+ case 0x7D: // } close curly brace
+ case 0x5B: // [
+ case 0x5D: // ]
+ case 0x3A: // :
+ case 0x3F: // ?
+ case 0x7E: // ~
+ ++index;
+ if (extra.tokenize) {
+ if (code === 0x28) {
+ extra.openParenToken = extra.tokens.length;
+ } else if (code === 0x7B) {
+ extra.openCurlyToken = extra.tokens.length;
+ }
+ }
+ return {
+ type: Token.Punctuator,
+ value: String.fromCharCode(code),
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ start: start,
+ end: index
+ };
+
+ default:
+ code2 = source.charCodeAt(index + 1);
+
+ // '=' (U+003D) marks an assignment or comparison operator.
+ if (code2 === 0x3D) {
+ switch (code) {
+ case 0x2B: // +
+ case 0x2D: // -
+ case 0x2F: // /
+ case 0x3C: // <
+ case 0x3E: // >
+ case 0x5E: // ^
+ case 0x7C: // |
+ case 0x25: // %
+ case 0x26: // &
+ case 0x2A: // *
+ index += 2;
+ return {
+ type: Token.Punctuator,
+ value: String.fromCharCode(code) + String.fromCharCode(code2),
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ start: start,
+ end: index
+ };
+
+ case 0x21: // !
+ case 0x3D: // =
+ index += 2;
+
+ // !== and ===
+ if (source.charCodeAt(index) === 0x3D) {
+ ++index;
+ }
+ return {
+ type: Token.Punctuator,
+ value: source.slice(start, index),
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ start: start,
+ end: index
+ };
+ }
+ }
+ }
+
+ // 4-character punctuator: >>>=
+
+ ch4 = source.substr(index, 4);
+
+ if (ch4 === '>>>=') {
+ index += 4;
+ return {
+ type: Token.Punctuator,
+ value: ch4,
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ start: start,
+ end: index
+ };
+ }
+
+ // 3-character punctuators: === !== >>> <<= >>=
+
+ ch3 = ch4.substr(0, 3);
+
+ if (ch3 === '>>>' || ch3 === '<<=' || ch3 === '>>=') {
+ index += 3;
+ return {
+ type: Token.Punctuator,
+ value: ch3,
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ start: start,
+ end: index
+ };
+ }
+
+ // Other 2-character punctuators: ++ -- << >> && ||
+ ch2 = ch3.substr(0, 2);
+
+ if ((ch1 === ch2[1] && ('+-<>&|'.indexOf(ch1) >= 0)) || ch2 === '=>') {
+ index += 2;
+ return {
+ type: Token.Punctuator,
+ value: ch2,
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ start: start,
+ end: index
+ };
+ }
+
+ // 1-character punctuators: < > = ! + - * % & | ^ /
+
+ if ('<>=!+-*%&|^/'.indexOf(ch1) >= 0) {
+ ++index;
+ return {
+ type: Token.Punctuator,
+ value: ch1,
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ start: start,
+ end: index
+ };
+ }
+
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ }
+
+ // 7.8.3 Numeric Literals
+
+ function scanHexLiteral(start) {
+ var number = '';
+
+ while (index < length) {
+ if (!isHexDigit(source[index])) {
+ break;
+ }
+ number += source[index++];
+ }
+
+ if (number.length === 0) {
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ }
+
+ if (isIdentifierStart(source.charCodeAt(index))) {
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ }
+
+ return {
+ type: Token.NumericLiteral,
+ value: parseInt('0x' + number, 16),
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ start: start,
+ end: index
+ };
+ }
+
+ function scanOctalLiteral(start) {
+ var number = '0' + source[index++];
+ while (index < length) {
+ if (!isOctalDigit(source[index])) {
+ break;
+ }
+ number += source[index++];
+ }
+
+ if (isIdentifierStart(source.charCodeAt(index)) || isDecimalDigit(source.charCodeAt(index))) {
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ }
+
+ return {
+ type: Token.NumericLiteral,
+ value: parseInt(number, 8),
+ octal: true,
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ start: start,
+ end: index
+ };
+ }
+
+ function scanNumericLiteral() {
+ var number, start, ch;
+
+ ch = source[index];
+ assert(isDecimalDigit(ch.charCodeAt(0)) || (ch === '.'),
+ 'Numeric literal must start with a decimal digit or a decimal point');
+
+ start = index;
+ number = '';
+ if (ch !== '.') {
+ number = source[index++];
+ ch = source[index];
+
+ // Hex number starts with '0x'.
+ // Octal number starts with '0'.
+ if (number === '0') {
+ if (ch === 'x' || ch === 'X') {
+ ++index;
+ return scanHexLiteral(start);
+ }
+ if (isOctalDigit(ch)) {
+ return scanOctalLiteral(start);
+ }
+
+ // decimal number starts with '0' such as '09' is illegal.
+ if (ch && isDecimalDigit(ch.charCodeAt(0))) {
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ }
+ }
+
+ while (isDecimalDigit(source.charCodeAt(index))) {
+ number += source[index++];
+ }
+ ch = source[index];
+ }
+
+ if (ch === '.') {
+ number += source[index++];
+ while (isDecimalDigit(source.charCodeAt(index))) {
+ number += source[index++];
+ }
+ ch = source[index];
+ }
+
+ if (ch === 'e' || ch === 'E') {
+ number += source[index++];
+
+ ch = source[index];
+ if (ch === '+' || ch === '-') {
+ number += source[index++];
+ }
+ if (isDecimalDigit(source.charCodeAt(index))) {
+ while (isDecimalDigit(source.charCodeAt(index))) {
+ number += source[index++];
+ }
+ } else {
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ }
+ }
+
+ if (isIdentifierStart(source.charCodeAt(index))) {
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ }
+
+ return {
+ type: Token.NumericLiteral,
+ value: parseFloat(number),
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ start: start,
+ end: index
+ };
+ }
+
+ // 7.8.4 String Literals
+
+ function scanStringLiteral() {
+ var str = '', quote, start, ch, code, unescaped, restore, octal = false, startLineNumber, startLineStart;
+ startLineNumber = lineNumber;
+ startLineStart = lineStart;
+
+ quote = source[index];
+ assert((quote === '\'' || quote === '"'),
+ 'String literal must starts with a quote');
+
+ start = index;
+ ++index;
+
+ while (index < length) {
+ ch = source[index++];
+
+ if (ch === quote) {
+ quote = '';
+ break;
+ } else if (ch === '\\') {
+ ch = source[index++];
+ if (!ch || !isLineTerminator(ch.charCodeAt(0))) {
+ switch (ch) {
+ case 'u':
+ case 'x':
+ if (source[index] === '{') {
+ ++index;
+ str += scanUnicodeCodePointEscape();
+ } else {
+ restore = index;
+ unescaped = scanHexEscape(ch);
+ if (unescaped) {
+ str += unescaped;
+ } else {
+ index = restore;
+ str += ch;
+ }
+ }
+ break;
+ case 'n':
+ str += '\n';
+ break;
+ case 'r':
+ str += '\r';
+ break;
+ case 't':
+ str += '\t';
+ break;
+ case 'b':
+ str += '\b';
+ break;
+ case 'f':
+ str += '\f';
+ break;
+ case 'v':
+ str += '\x0B';
+ break;
+
+ default:
+ if (isOctalDigit(ch)) {
+ code = '01234567'.indexOf(ch);
+
+ // \0 is not octal escape sequence
+ if (code !== 0) {
+ octal = true;
+ }
+
+ if (index < length && isOctalDigit(source[index])) {
+ octal = true;
+ code = code * 8 + '01234567'.indexOf(source[index++]);
+
+ // 3 digits are only allowed when string starts
+ // with 0, 1, 2, 3
+ if ('0123'.indexOf(ch) >= 0 &&
+ index < length &&
+ isOctalDigit(source[index])) {
+ code = code * 8 + '01234567'.indexOf(source[index++]);
+ }
+ }
+ str += String.fromCharCode(code);
+ } else {
+ str += ch;
+ }
+ break;
+ }
+ } else {
+ ++lineNumber;
+ if (ch === '\r' && source[index] === '\n') {
+ ++index;
+ }
+ lineStart = index;
+ }
+ } else if (isLineTerminator(ch.charCodeAt(0))) {
+ break;
+ } else {
+ str += ch;
+ }
+ }
+
+ if (quote !== '') {
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
+ }
+
+ return {
+ type: Token.StringLiteral,
+ value: str,
+ octal: octal,
+ startLineNumber: startLineNumber,
+ startLineStart: startLineStart,
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ start: start,
+ end: index
+ };
+ }
+
+ function testRegExp(pattern, flags) {
+ var tmp = pattern,
+ value;
+
+ if (flags.indexOf('u') >= 0) {
+ // Replace each astral symbol and every Unicode code point
+ // escape sequence with a single ASCII symbol to avoid throwing on
+ // regular expressions that are only valid in combination with the
+ // `/u` flag.
+ // Note: replacing with the ASCII symbol `x` might cause false
+ // negatives in unlikely scenarios. For example, `[\u{61}-b]` is a
+ // perfectly valid pattern that is equivalent to `[a-b]`, but it
+ // would be replaced by `[x-b]` which throws an error.
+ tmp = tmp
+ .replace(/\\u\{([0-9a-fA-F]+)\}/g, function ($0, $1) {
+ if (parseInt($1, 16) <= 0x10FFFF) {
+ return 'x';
+ }
+ throwError({}, Messages.InvalidRegExp);
+ })
+ .replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, 'x');
+ }
+
+ // First, detect invalid regular expressions.
+ try {
+ value = new RegExp(tmp);
+ } catch (e) {
+ throwError({}, Messages.InvalidRegExp);
+ }
+
+ // Return a regular expression object for this pattern-flag pair, or
+ // `null` in case the current environment doesn't support the flags it
+ // uses.
+ try {
+ return new RegExp(pattern, flags);
+ } catch (exception) {
+ return null;
+ }
+ }
+
+ function scanRegExpBody() {
+ var ch, str, classMarker, terminated, body;
+
+ ch = source[index];
+ assert(ch === '/', 'Regular expression literal must start with a slash');
+ str = source[index++];
+
+ classMarker = false;
+ terminated = false;
+ while (index < length) {
+ ch = source[index++];
+ str += ch;
+ if (ch === '\\') {
+ ch = source[index++];
+ // ECMA-262 7.8.5
+ if (isLineTerminator(ch.charCodeAt(0))) {
+ throwError({}, Messages.UnterminatedRegExp);
+ }
+ str += ch;
+ } else if (isLineTerminator(ch.charCodeAt(0))) {
+ throwError({}, Messages.UnterminatedRegExp);
+ } else if (classMarker) {
+ if (ch === ']') {
+ classMarker = false;
+ }
+ } else {
+ if (ch === '/') {
+ terminated = true;
+ break;
+ } else if (ch === '[') {
+ classMarker = true;
+ }
+ }
+ }
+
+ if (!terminated) {
+ throwError({}, Messages.UnterminatedRegExp);
+ }
+
+ // Exclude leading and trailing slash.
+ body = str.substr(1, str.length - 2);
+ return {
+ value: body,
+ literal: str
+ };
+ }
+
+ function scanRegExpFlags() {
+ var ch, str, flags, restore;
+
+ str = '';
+ flags = '';
+ while (index < length) {
+ ch = source[index];
+ if (!isIdentifierPart(ch.charCodeAt(0))) {
+ break;
+ }
+
+ ++index;
+ if (ch === '\\' && index < length) {
+ ch = source[index];
+ if (ch === 'u') {
+ ++index;
+ restore = index;
+ ch = scanHexEscape('u');
+ if (ch) {
+ flags += ch;
+ for (str += '\\u'; restore < index; ++restore) {
+ str += source[restore];
+ }
+ } else {
+ index = restore;
+ flags += 'u';
+ str += '\\u';
+ }
+ throwErrorTolerant({}, Messages.UnexpectedToken, 'ILLEGAL');
+ } else {
+ str += '\\';
+ throwErrorTolerant({}, Messages.UnexpectedToken, 'ILLEGAL');
+ }
+ } else {
+ flags += ch;
+ str += ch;
+ }
+ }
+
+ return {
+ value: flags,
+ literal: str
+ };
+ }
+
+ function scanRegExp() {
+ var start, body, flags, value;
+
+ lookahead = null;
+ skipComment();
+ start = index;
+
+ body = scanRegExpBody();
+ flags = scanRegExpFlags();
+ value = testRegExp(body.value, flags.value);
+
+ if (extra.tokenize) {
+ return {
+ type: Token.RegularExpression,
+ value: value,
+ regex: {
+ pattern: body.value,
+ flags: flags.value
+ },
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ start: start,
+ end: index
+ };
+ }
+
+ return {
+ literal: body.literal + flags.literal,
+ value: value,
+ regex: {
+ pattern: body.value,
+ flags: flags.value
+ },
+ start: start,
+ end: index
+ };
+ }
+
+ function collectRegex() {
+ var pos, loc, regex, token;
+
+ skipComment();
+
+ pos = index;
+ loc = {
+ start: {
+ line: lineNumber,
+ column: index - lineStart
+ }
+ };
+
+ regex = scanRegExp();
+
+ loc.end = {
+ line: lineNumber,
+ column: index - lineStart
+ };
+
+ if (!extra.tokenize) {
+ // Pop the previous token, which is likely '/' or '/='
+ if (extra.tokens.length > 0) {
+ token = extra.tokens[extra.tokens.length - 1];
+ if (token.range[0] === pos && token.type === 'Punctuator') {
+ if (token.value === '/' || token.value === '/=') {
+ extra.tokens.pop();
+ }
+ }
+ }
+
+ extra.tokens.push({
+ type: 'RegularExpression',
+ value: regex.literal,
+ regex: regex.regex,
+ range: [pos, index],
+ loc: loc
+ });
+ }
+
+ return regex;
+ }
+
+ function isIdentifierName(token) {
+ return token.type === Token.Identifier ||
+ token.type === Token.Keyword ||
+ token.type === Token.BooleanLiteral ||
+ token.type === Token.NullLiteral;
+ }
+
+ function advanceSlash() {
+ var prevToken,
+ checkToken;
+ // Using the following algorithm:
+ // https://github.com/mozilla/sweet.js/wiki/design
+ prevToken = extra.tokens[extra.tokens.length - 1];
+ if (!prevToken) {
+ // Nothing before that: it cannot be a division.
+ return collectRegex();
+ }
+ if (prevToken.type === 'Punctuator') {
+ if (prevToken.value === ']') {
+ return scanPunctuator();
+ }
+ if (prevToken.value === ')') {
+ checkToken = extra.tokens[extra.openParenToken - 1];
+ if (checkToken &&
+ checkToken.type === 'Keyword' &&
+ (checkToken.value === 'if' ||
+ checkToken.value === 'while' ||
+ checkToken.value === 'for' ||
+ checkToken.value === 'with')) {
+ return collectRegex();
+ }
+ return scanPunctuator();
+ }
+ if (prevToken.value === '}') {
+ // Dividing a function by anything makes little sense,
+ // but we have to check for that.
+ if (extra.tokens[extra.openCurlyToken - 3] &&
+ extra.tokens[extra.openCurlyToken - 3].type === 'Keyword') {
+ // Anonymous function.
+ checkToken = extra.tokens[extra.openCurlyToken - 4];
+ if (!checkToken) {
+ return scanPunctuator();
+ }
+ } else if (extra.tokens[extra.openCurlyToken - 4] &&
+ extra.tokens[extra.openCurlyToken - 4].type === 'Keyword') {
+ // Named function.
+ checkToken = extra.tokens[extra.openCurlyToken - 5];
+ if (!checkToken) {
+ return collectRegex();
+ }
+ } else {
+ return scanPunctuator();
+ }
+ return scanPunctuator();
+ }
+ return collectRegex();
+ }
+ if (prevToken.type === 'Keyword' && prevToken.value !== 'this') {
+ return collectRegex();
+ }
+ return scanPunctuator();
+ }
+
+ function advance() {
+ var ch;
+
+ skipComment();
+
+ if (index >= length) {
+ return {
+ type: Token.EOF,
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ start: index,
+ end: index
+ };
+ }
+
+ ch = source.charCodeAt(index);
+
+ if (isIdentifierStart(ch)) {
+ return scanIdentifier();
+ }
+
+ // Very common: ( and ) and ;
+ if (ch === 0x28 || ch === 0x29 || ch === 0x3B) {
+ return scanPunctuator();
+ }
+
+ // String literal starts with single quote (U+0027) or double quote (U+0022).
+ if (ch === 0x27 || ch === 0x22) {
+ return scanStringLiteral();
+ }
+
+
+ // Dot (.) U+002E can also start a floating-point number, hence the need
+ // to check the next character.
+ if (ch === 0x2E) {
+ if (isDecimalDigit(source.charCodeAt(index + 1))) {
+ return scanNumericLiteral();
+ }
+ return scanPunctuator();
+ }
+
+ if (isDecimalDigit(ch)) {
+ return scanNumericLiteral();
+ }
+
+ // Slash (/) U+002F can also start a regex.
+ if (extra.tokenize && ch === 0x2F) {
+ return advanceSlash();
+ }
+
+ return scanPunctuator();
+ }
+
+ function collectToken() {
+ var loc, token, value, entry;
+
+ skipComment();
+ loc = {
+ start: {
+ line: lineNumber,
+ column: index - lineStart
+ }
+ };
+
+ token = advance();
+ loc.end = {
+ line: lineNumber,
+ column: index - lineStart
+ };
+
+ if (token.type !== Token.EOF) {
+ value = source.slice(token.start, token.end);
+ entry = {
+ type: TokenName[token.type],
+ value: value,
+ range: [token.start, token.end],
+ loc: loc
+ };
+ if (token.regex) {
+ entry.regex = {
+ pattern: token.regex.pattern,
+ flags: token.regex.flags
+ };
+ }
+ extra.tokens.push(entry);
+ }
+
+ return token;
+ }
+
+ function lex() {
+ var token;
+
+ token = lookahead;
+ index = token.end;
+ lineNumber = token.lineNumber;
+ lineStart = token.lineStart;
+
+ lookahead = (typeof extra.tokens !== 'undefined') ? collectToken() : advance();
+
+ index = token.end;
+ lineNumber = token.lineNumber;
+ lineStart = token.lineStart;
+
+ return token;
+ }
+
+ function peek() {
+ var pos, line, start;
+
+ pos = index;
+ line = lineNumber;
+ start = lineStart;
+ lookahead = (typeof extra.tokens !== 'undefined') ? collectToken() : advance();
+ index = pos;
+ lineNumber = line;
+ lineStart = start;
+ }
+
+ function Position() {
+ this.line = lineNumber;
+ this.column = index - lineStart;
+ }
+
+ function SourceLocation() {
+ this.start = new Position();
+ this.end = null;
+ }
+
+ function WrappingSourceLocation(startToken) {
+ if (startToken.type === Token.StringLiteral) {
+ this.start = {
+ line: startToken.startLineNumber,
+ column: startToken.start - startToken.startLineStart
+ };
+ } else {
+ this.start = {
+ line: startToken.lineNumber,
+ column: startToken.start - startToken.lineStart
+ };
+ }
+ this.end = null;
+ }
+
+ function Node() {
+ // Skip comment.
+ index = lookahead.start;
+ if (lookahead.type === Token.StringLiteral) {
+ lineNumber = lookahead.startLineNumber;
+ lineStart = lookahead.startLineStart;
+ } else {
+ lineNumber = lookahead.lineNumber;
+ lineStart = lookahead.lineStart;
+ }
+ if (extra.range) {
+ this.range = [index, 0];
+ }
+ if (extra.loc) {
+ this.loc = new SourceLocation();
+ }
+ }
+
+ function WrappingNode(startToken) {
+ if (extra.range) {
+ this.range = [startToken.start, 0];
+ }
+ if (extra.loc) {
+ this.loc = new WrappingSourceLocation(startToken);
+ }
+ }
+
+ WrappingNode.prototype = Node.prototype = {
+
+ finish: function () {
+ if (extra.range) {
+ this.range[1] = index;
+ }
+ if (extra.loc) {
+ this.loc.end = new Position();
+ if (extra.source) {
+ this.loc.source = extra.source;
+ }
+ }
+ },
+
+ finishArrayExpression: function (elements) {
+ this.type = Syntax.ArrayExpression;
+ this.elements = elements;
+ this.finish();
+ return this;
+ },
+
+ finishAssignmentExpression: function (operator, left, right) {
+ this.type = Syntax.AssignmentExpression;
+ this.operator = operator;
+ this.left = left;
+ this.right = right;
+ this.finish();
+ return this;
+ },
+
+ finishBinaryExpression: function (operator, left, right) {
+ this.type = (operator === '||' || operator === '&&') ? Syntax.LogicalExpression : Syntax.BinaryExpression;
+ this.operator = operator;
+ this.left = left;
+ this.right = right;
+ this.finish();
+ return this;
+ },
+
+ finishCallExpression: function (callee, args) {
+ this.type = Syntax.CallExpression;
+ this.callee = callee;
+ this.arguments = args;
+ this.finish();
+ return this;
+ },
+
+ finishConditionalExpression: function (test, consequent, alternate) {
+ this.type = Syntax.ConditionalExpression;
+ this.test = test;
+ this.consequent = consequent;
+ this.alternate = alternate;
+ this.finish();
+ return this;
+ },
+
+ finishExpressionStatement: function (expression) {
+ this.type = Syntax.ExpressionStatement;
+ this.expression = expression;
+ this.finish();
+ return this;
+ },
+
+ finishIdentifier: function (name) {
+ this.type = Syntax.Identifier;
+ this.name = name;
+ this.finish();
+ return this;
+ },
+
+ finishLiteral: function (token) {
+ this.type = Syntax.Literal;
+ this.value = token.value;
+ this.raw = source.slice(token.start, token.end);
+ if (token.regex) {
+ if (this.raw == '//') {
+ this.raw = '/(?:)/';
+ }
+ this.regex = token.regex;
+ }
+ this.finish();
+ return this;
+ },
+
+ finishMemberExpression: function (accessor, object, property) {
+ this.type = Syntax.MemberExpression;
+ this.computed = accessor === '[';
+ this.object = object;
+ this.property = property;
+ this.finish();
+ return this;
+ },
+
+ finishObjectExpression: function (properties) {
+ this.type = Syntax.ObjectExpression;
+ this.properties = properties;
+ this.finish();
+ return this;
+ },
+
+ finishProgram: function (body) {
+ this.type = Syntax.Program;
+ this.body = body;
+ this.finish();
+ return this;
+ },
+
+ finishProperty: function (kind, key, value) {
+ this.type = Syntax.Property;
+ this.key = key;
+ this.value = value;
+ this.kind = kind;
+ this.finish();
+ return this;
+ },
+
+ finishUnaryExpression: function (operator, argument) {
+ this.type = Syntax.UnaryExpression;
+ this.operator = operator;
+ this.argument = argument;
+ this.prefix = true;
+ this.finish();
+ return this;
+ }
+ };
+
+ // Return true if there is a line terminator before the next token.
+
+ function peekLineTerminator() {
+ var pos, line, start, found;
+
+ pos = index;
+ line = lineNumber;
+ start = lineStart;
+ skipComment();
+ found = lineNumber !== line;
+ index = pos;
+ lineNumber = line;
+ lineStart = start;
+
+ return found;
+ }
+
+ // Throw an exception
+
+ function throwError(token, messageFormat) {
+ var error,
+ args = Array.prototype.slice.call(arguments, 2),
+ msg = messageFormat.replace(
+ /%(\d)/g,
+ function (whole, index) {
+ assert(index < args.length, 'Message reference must be in range');
+ return args[index];
+ }
+ );
+
+ if (typeof token.lineNumber === 'number') {
+ error = new Error('Line ' + token.lineNumber + ': ' + msg);
+ error.index = token.start;
+ error.lineNumber = token.lineNumber;
+ error.column = token.start - lineStart + 1;
+ } else {
+ error = new Error('Line ' + lineNumber + ': ' + msg);
+ error.index = index;
+ error.lineNumber = lineNumber;
+ error.column = index - lineStart + 1;
+ }
+
+ error.description = msg;
+ throw error;
+ }
+
+ function throwErrorTolerant() {
+ try {
+ throwError.apply(null, arguments);
+ } catch (e) {
+ if (extra.errors) {
+ extra.errors.push(e);
+ } else {
+ throw e;
+ }
+ }
+ }
+
+
+ // Throw an exception because of the token.
+
+ function throwUnexpected(token) {
+ if (token.type === Token.EOF) {
+ throwError(token, Messages.UnexpectedEOS);
+ }
+
+ if (token.type === Token.NumericLiteral) {
+ throwError(token, Messages.UnexpectedNumber);
+ }
+
+ if (token.type === Token.StringLiteral) {
+ throwError(token, Messages.UnexpectedString);
+ }
+
+ if (token.type === Token.Identifier) {
+ throwError(token, Messages.UnexpectedIdentifier);
+ }
+
+ if (token.type === Token.Keyword) {
+ if (isFutureReservedWord(token.value)) {
+ throwError(token, Messages.UnexpectedReserved);
+ } else if (strict && isStrictModeReservedWord(token.value)) {
+ throwErrorTolerant(token, Messages.StrictReservedWord);
+ return;
+ }
+ throwError(token, Messages.UnexpectedToken, token.value);
+ }
+
+ // BooleanLiteral, NullLiteral, or Punctuator.
+ throwError(token, Messages.UnexpectedToken, token.value);
+ }
+
+ // Expect the next token to match the specified punctuator.
+ // If not, an exception will be thrown.
+
+ function expect(value) {
+ var token = lex();
+ if (token.type !== Token.Punctuator || token.value !== value) {
+ throwUnexpected(token);
+ }
+ }
+
+ /**
+ * @name expectTolerant
+ * @description Quietly expect the given token value when in tolerant mode, otherwise delegates
+ * to expect(value)
+ * @param {String} value The value we are expecting the lookahead token to have
+ * @since 2.0
+ */
+ function expectTolerant(value) {
+ if (extra.errors) {
+ var token = lookahead;
+ if (token.type !== Token.Punctuator && token.value !== value) {
+ throwErrorTolerant(token, Messages.UnexpectedToken, token.value);
+ } else {
+ lex();
+ }
+ } else {
+ expect(value);
+ }
+ }
+
+ // Return true if the next token matches the specified punctuator.
+
+ function match(value) {
+ return lookahead.type === Token.Punctuator && lookahead.value === value;
+ }
+
+ // Return true if the next token matches the specified keyword
+
+ function matchKeyword(keyword) {
+ return lookahead.type === Token.Keyword && lookahead.value === keyword;
+ }
+
+ function consumeSemicolon() {
+ var line;
+
+ // Catch the very common case first: immediately a semicolon (U+003B).
+ if (source.charCodeAt(index) === 0x3B || match(';')) {
+ lex();
+ return;
+ }
+
+ line = lineNumber;
+ skipComment();
+ if (lineNumber !== line) {
+ return;
+ }
+
+ if (lookahead.type !== Token.EOF && !match('}')) {
+ throwUnexpected(lookahead);
+ }
+ }
+
+ // 11.1.4 Array Initialiser
+
+ function parseArrayInitialiser() {
+ var elements = [], node = new Node();
+
+ expect('[');
+
+ while (!match(']')) {
+ if (match(',')) {
+ lex();
+ elements.push(null);
+ } else {
+ elements.push(parseAssignmentExpression());
+
+ if (!match(']')) {
+ expect(',');
+ }
+ }
+ }
+
+ lex();
+
+ return node.finishArrayExpression(elements);
+ }
+
+ // 11.1.5 Object Initialiser
+
+ function parseObjectPropertyKey() {
+ var token, node = new Node();
+
+ token = lex();
+
+ // Note: This function is called only from parseObjectProperty(), where
+ // EOF and Punctuator tokens are already filtered out.
+
+ if (token.type === Token.StringLiteral || token.type === Token.NumericLiteral) {
+ if (strict && token.octal) {
+ throwErrorTolerant(token, Messages.StrictOctalLiteral);
+ }
+ return node.finishLiteral(token);
+ }
+
+ return node.finishIdentifier(token.value);
+ }
+
+ function parseObjectProperty() {
+ var token, key, id, value, node = new Node();
+
+ token = lookahead;
+
+ if (token.type === Token.Identifier) {
+ id = parseObjectPropertyKey();
+ expect(':');
+ value = parseAssignmentExpression();
+ return node.finishProperty('init', id, value);
+ }
+ if (token.type === Token.EOF || token.type === Token.Punctuator) {
+ throwUnexpected(token);
+ } else {
+ key = parseObjectPropertyKey();
+ expect(':');
+ value = parseAssignmentExpression();
+ return node.finishProperty('init', key, value);
+ }
+ }
+
+ function parseObjectInitialiser() {
+ var properties = [], property, name, key, kind, map = {}, toString = String, node = new Node();
+
+ expect('{');
+
+ while (!match('}')) {
+ property = parseObjectProperty();
+
+ if (property.key.type === Syntax.Identifier) {
+ name = property.key.name;
+ } else {
+ name = toString(property.key.value);
+ }
+ kind = (property.kind === 'init') ? PropertyKind.Data : (property.kind === 'get') ? PropertyKind.Get : PropertyKind.Set;
+
+ key = '$' + name;
+ if (Object.prototype.hasOwnProperty.call(map, key)) {
+ if (map[key] === PropertyKind.Data) {
+ if (strict && kind === PropertyKind.Data) {
+ throwErrorTolerant({}, Messages.StrictDuplicateProperty);
+ } else if (kind !== PropertyKind.Data) {
+ throwErrorTolerant({}, Messages.AccessorDataProperty);
+ }
+ } else {
+ if (kind === PropertyKind.Data) {
+ throwErrorTolerant({}, Messages.AccessorDataProperty);
+ } else if (map[key] & kind) {
+ throwErrorTolerant({}, Messages.AccessorGetSet);
+ }
+ }
+ map[key] |= kind;
+ } else {
+ map[key] = kind;
+ }
+
+ properties.push(property);
+
+ if (!match('}')) {
+ expectTolerant(',');
+ }
+ }
+
+ expect('}');
+
+ return node.finishObjectExpression(properties);
+ }
+
+ // 11.1.6 The Grouping Operator
+
+ function parseGroupExpression() {
+ var expr;
+
+ expect('(');
+
+ ++state.parenthesisCount;
+
+ expr = parseExpression();
+
+ expect(')');
+
+ return expr;
+ }
+
+
+ // 11.1 Primary Expressions
+
+ var legalKeywords = {"if":1, "this":1};
+
+ function parsePrimaryExpression() {
+ var type, token, expr, node;
+
+ if (match('(')) {
+ return parseGroupExpression();
+ }
+
+ if (match('[')) {
+ return parseArrayInitialiser();
+ }
+
+ if (match('{')) {
+ return parseObjectInitialiser();
+ }
+
+ type = lookahead.type;
+ node = new Node();
+
+ if (type === Token.Identifier || legalKeywords[lookahead.value]) {
+ expr = node.finishIdentifier(lex().value);
+ } else if (type === Token.StringLiteral || type === Token.NumericLiteral) {
+ if (strict && lookahead.octal) {
+ throwErrorTolerant(lookahead, Messages.StrictOctalLiteral);
+ }
+ expr = node.finishLiteral(lex());
+ } else if (type === Token.Keyword) {
+ throw new Error("Disabled.");
+ } else if (type === Token.BooleanLiteral) {
+ token = lex();
+ token.value = (token.value === 'true');
+ expr = node.finishLiteral(token);
+ } else if (type === Token.NullLiteral) {
+ token = lex();
+ token.value = null;
+ expr = node.finishLiteral(token);
+ } else if (match('/') || match('/=')) {
+ if (typeof extra.tokens !== 'undefined') {
+ expr = node.finishLiteral(collectRegex());
+ } else {
+ expr = node.finishLiteral(scanRegExp());
+ }
+ peek();
+ } else {
+ throwUnexpected(lex());
+ }
+
+ return expr;
+ }
+
+ // 11.2 Left-Hand-Side Expressions
+
+ function parseArguments() {
+ var args = [];
+
+ expect('(');
+
+ if (!match(')')) {
+ while (index < length) {
+ args.push(parseAssignmentExpression());
+ if (match(')')) {
+ break;
+ }
+ expectTolerant(',');
+ }
+ }
+
+ expect(')');
+
+ return args;
+ }
+
+ function parseNonComputedProperty() {
+ var token, node = new Node();
+
+ token = lex();
+
+ if (!isIdentifierName(token)) {
+ throwUnexpected(token);
+ }
+
+ return node.finishIdentifier(token.value);
+ }
+
+ function parseNonComputedMember() {
+ expect('.');
+
+ return parseNonComputedProperty();
+ }
+
+ function parseComputedMember() {
+ var expr;
+
+ expect('[');
+
+ expr = parseExpression();
+
+ expect(']');
+
+ return expr;
+ }
+
+ function parseLeftHandSideExpressionAllowCall() {
+ var expr, args, property, startToken, previousAllowIn = state.allowIn;
+
+ startToken = lookahead;
+ state.allowIn = true;
+ expr = parsePrimaryExpression();
+
+ for (;;) {
+ if (match('.')) {
+ property = parseNonComputedMember();
+ expr = new WrappingNode(startToken).finishMemberExpression('.', expr, property);
+ } else if (match('(')) {
+ args = parseArguments();
+ expr = new WrappingNode(startToken).finishCallExpression(expr, args);
+ } else if (match('[')) {
+ property = parseComputedMember();
+ expr = new WrappingNode(startToken).finishMemberExpression('[', expr, property);
+ } else {
+ break;
+ }
+ }
+ state.allowIn = previousAllowIn;
+
+ return expr;
+ }
+
+ // 11.3 Postfix Expressions
+
+ function parsePostfixExpression() {
+ var expr = parseLeftHandSideExpressionAllowCall();
+
+ if (lookahead.type === Token.Punctuator) {
+ if ((match('++') || match('--')) && !peekLineTerminator()) {
+ throw new Error("Disabled.");
+ }
+ }
+
+ return expr;
+ }
+
+ // 11.4 Unary Operators
+
+ function parseUnaryExpression() {
+ var token, expr, startToken;
+
+ if (lookahead.type !== Token.Punctuator && lookahead.type !== Token.Keyword) {
+ expr = parsePostfixExpression();
+ } else if (match('++') || match('--')) {
+ throw new Error("Disabled.");
+ } else if (match('+') || match('-') || match('~') || match('!')) {
+ startToken = lookahead;
+ token = lex();
+ expr = parseUnaryExpression();
+ expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr);
+ } else if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) {
+ throw new Error("Disabled.");
+ } else {
+ expr = parsePostfixExpression();
+ }
+
+ return expr;
+ }
+
+ function binaryPrecedence(token, allowIn) {
+ var prec = 0;
+
+ if (token.type !== Token.Punctuator && token.type !== Token.Keyword) {
+ return 0;
+ }
+
+ switch (token.value) {
+ case '||':
+ prec = 1;
+ break;
+
+ case '&&':
+ prec = 2;
+ break;
+
+ case '|':
+ prec = 3;
+ break;
+
+ case '^':
+ prec = 4;
+ break;
+
+ case '&':
+ prec = 5;
+ break;
+
+ case '==':
+ case '!=':
+ case '===':
+ case '!==':
+ prec = 6;
+ break;
+
+ case '<':
+ case '>':
+ case '<=':
+ case '>=':
+ case 'instanceof':
+ prec = 7;
+ break;
+
+ case 'in':
+ prec = allowIn ? 7 : 0;
+ break;
+
+ case '<<':
+ case '>>':
+ case '>>>':
+ prec = 8;
+ break;
+
+ case '+':
+ case '-':
+ prec = 9;
+ break;
+
+ case '*':
+ case '/':
+ case '%':
+ prec = 11;
+ break;
+
+ default:
+ break;
+ }
+
+ return prec;
+ }
+
+ // 11.5 Multiplicative Operators
+ // 11.6 Additive Operators
+ // 11.7 Bitwise Shift Operators
+ // 11.8 Relational Operators
+ // 11.9 Equality Operators
+ // 11.10 Binary Bitwise Operators
+ // 11.11 Binary Logical Operators
+
+ function parseBinaryExpression() {
+ var marker, markers, expr, token, prec, stack, right, operator, left, i;
+
+ marker = lookahead;
+ left = parseUnaryExpression();
+
+ token = lookahead;
+ prec = binaryPrecedence(token, state.allowIn);
+ if (prec === 0) {
+ return left;
+ }
+ token.prec = prec;
+ lex();
+
+ markers = [marker, lookahead];
+ right = parseUnaryExpression();
+
+ stack = [left, token, right];
+
+ while ((prec = binaryPrecedence(lookahead, state.allowIn)) > 0) {
+
+ // Reduce: make a binary expression from the three topmost entries.
+ while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) {
+ right = stack.pop();
+ operator = stack.pop().value;
+ left = stack.pop();
+ markers.pop();
+ expr = new WrappingNode(markers[markers.length - 1]).finishBinaryExpression(operator, left, right);
+ stack.push(expr);
+ }
+
+ // Shift.
+ token = lex();
+ token.prec = prec;
+ stack.push(token);
+ markers.push(lookahead);
+ expr = parseUnaryExpression();
+ stack.push(expr);
+ }
+
+ // Final reduce to clean-up the stack.
+ i = stack.length - 1;
+ expr = stack[i];
+ markers.pop();
+ while (i > 1) {
+ expr = new WrappingNode(markers.pop()).finishBinaryExpression(stack[i - 1].value, stack[i - 2], expr);
+ i -= 2;
+ }
+
+ return expr;
+ }
+
+ // 11.12 Conditional Operator
+
+ function parseConditionalExpression() {
+ var expr, previousAllowIn, consequent, alternate, startToken;
+
+ startToken = lookahead;
+
+ expr = parseBinaryExpression();
+
+ if (match('?')) {
+ lex();
+ previousAllowIn = state.allowIn;
+ state.allowIn = true;
+ consequent = parseAssignmentExpression();
+ state.allowIn = previousAllowIn;
+ expect(':');
+ alternate = parseAssignmentExpression();
+
+ expr = new WrappingNode(startToken).finishConditionalExpression(expr, consequent, alternate);
+ }
+
+ return expr;
+ }
+
+ // 11.13 Assignment Operators
+
+ function parseAssignmentExpression() {
+ var oldParenthesisCount, token, expr, startToken;
+
+ oldParenthesisCount = state.parenthesisCount;
+
+ startToken = lookahead;
+ token = lookahead;
+
+ expr = parseConditionalExpression();
+
+ return expr;
+ }
+
+ // 11.14 Comma Operator
+
+ function parseExpression() {
+ var expr = parseAssignmentExpression();
+
+ if (match(',')) {
+ throw new Error("Disabled."); // no sequence expressions
+ }
+
+ return expr;
+ }
+
+ // 12.4 Expression Statement
+
+ function parseExpressionStatement(node) {
+ var expr = parseExpression();
+ consumeSemicolon();
+ return node.finishExpressionStatement(expr);
+ }
+
+ // 12 Statements
+
+ function parseStatement() {
+ var type = lookahead.type,
+ expr,
+ node;
+
+ if (type === Token.EOF) {
+ throwUnexpected(lookahead);
+ }
+
+ if (type === Token.Punctuator && lookahead.value === '{') {
+ throw new Error("Disabled."); // block statement
+ }
+
+ node = new Node();
+
+ if (type === Token.Punctuator) {
+ switch (lookahead.value) {
+ case ';':
+ throw new Error("Disabled."); // empty statement
+ case '(':
+ return parseExpressionStatement(node);
+ default:
+ break;
+ }
+ } else if (type === Token.Keyword) {
+ throw new Error("Disabled."); // keyword
+ }
+
+ expr = parseExpression();
+ consumeSemicolon();
+ return node.finishExpressionStatement(expr);
+ }
+
+ // 14 Program
+
+ function parseSourceElement() {
+ if (lookahead.type === Token.Keyword) {
+ switch (lookahead.value) {
+ case 'const':
+ case 'let':
+ throw new Error("Disabled.");
+ case 'function':
+ throw new Error("Disabled.");
+ default:
+ return parseStatement();
+ }
+ }
+
+ if (lookahead.type !== Token.EOF) {
+ return parseStatement();
+ }
+ }
+
+ function parseSourceElements() {
+ var sourceElement, sourceElements = [], token, directive, firstRestricted;
+
+ while (index < length) {
+ token = lookahead;
+ if (token.type !== Token.StringLiteral) {
+ break;
+ }
+
+ sourceElement = parseSourceElement();
+ sourceElements.push(sourceElement);
+ if (sourceElement.expression.type !== Syntax.Literal) {
+ // this is not directive
+ break;
+ }
+ directive = source.slice(token.start + 1, token.end - 1);
+ if (directive === 'use strict') {
+ strict = true;
+ if (firstRestricted) {
+ throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral);
+ }
+ } else {
+ if (!firstRestricted && token.octal) {
+ firstRestricted = token;
+ }
+ }
+ }
+
+ while (index < length) {
+ sourceElement = parseSourceElement();
+ if (typeof sourceElement === 'undefined') {
+ break;
+ }
+ sourceElements.push(sourceElement);
+ }
+ return sourceElements;
+ }
+
+ function parseProgram() {
+ var body, node;
+
+ skipComment();
+ peek();
+ node = new Node();
+ strict = true; // assume strict
+
+ body = parseSourceElements();
+ return node.finishProgram(body);
+ }
+
+ function filterTokenLocation() {
+ var i, entry, token, tokens = [];
+
+ for (i = 0; i < extra.tokens.length; ++i) {
+ entry = extra.tokens[i];
+ token = {
+ type: entry.type,
+ value: entry.value
+ };
+ if (entry.regex) {
+ token.regex = {
+ pattern: entry.regex.pattern,
+ flags: entry.regex.flags
+ };
+ }
+ if (extra.range) {
+ token.range = entry.range;
+ }
+ if (extra.loc) {
+ token.loc = entry.loc;
+ }
+ tokens.push(token);
+ }
+
+ extra.tokens = tokens;
+ }
+
+ function tokenize(code, options) {
+ var toString,
+ tokens;
+
+ toString = String;
+ if (typeof code !== 'string' && !(code instanceof String)) {
+ code = toString(code);
+ }
+
+ source = code;
+ index = 0;
+ lineNumber = (source.length > 0) ? 1 : 0;
+ lineStart = 0;
+ length = source.length;
+ lookahead = null;
+ state = {
+ allowIn: true,
+ labelSet: {},
+ inFunctionBody: false,
+ inIteration: false,
+ inSwitch: false,
+ lastCommentStart: -1
+ };
+
+ extra = {};
+
+ // Options matching.
+ options = options || {};
+
+ // Of course we collect tokens here.
+ options.tokens = true;
+ extra.tokens = [];
+ extra.tokenize = true;
+ // The following two fields are necessary to compute the Regex tokens.
+ extra.openParenToken = -1;
+ extra.openCurlyToken = -1;
+
+ extra.range = (typeof options.range === 'boolean') && options.range;
+ extra.loc = (typeof options.loc === 'boolean') && options.loc;
+
+ if (typeof options.tolerant === 'boolean' && options.tolerant) {
+ extra.errors = [];
+ }
+
+ try {
+ peek();
+ if (lookahead.type === Token.EOF) {
+ return extra.tokens;
+ }
+
+ lex();
+ while (lookahead.type !== Token.EOF) {
+ try {
+ lex();
+ } catch (lexError) {
+ if (extra.errors) {
+ extra.errors.push(lexError);
+ // We have to break on the first error
+ // to avoid infinite loops.
+ break;
+ } else {
+ throw lexError;
+ }
+ }
+ }
+
+ filterTokenLocation();
+ tokens = extra.tokens;
+ if (typeof extra.errors !== 'undefined') {
+ tokens.errors = extra.errors;
+ }
+ } catch (e) {
+ throw e;
+ } finally {
+ extra = {};
+ }
+ return tokens;
+ }
+
+ function parse(code, options) {
+ var program, toString;
+
+ toString = String;
+ if (typeof code !== 'string' && !(code instanceof String)) {
+ code = toString(code);
+ }
+
+ source = code;
+ index = 0;
+ lineNumber = (source.length > 0) ? 1 : 0;
+ lineStart = 0;
+ length = source.length;
+ lookahead = null;
+ state = {
+ allowIn: true,
+ labelSet: {},
+ parenthesisCount: 0,
+ inFunctionBody: false,
+ inIteration: false,
+ inSwitch: false,
+ lastCommentStart: -1
+ };
+
+ extra = {};
+ if (typeof options !== 'undefined') {
+ extra.range = (typeof options.range === 'boolean') && options.range;
+ extra.loc = (typeof options.loc === 'boolean') && options.loc;
+
+ if (extra.loc && options.source !== null && options.source !== undefined) {
+ extra.source = toString(options.source);
+ }
+
+ if (typeof options.tokens === 'boolean' && options.tokens) {
+ extra.tokens = [];
+ }
+ if (typeof options.tolerant === 'boolean' && options.tolerant) {
+ extra.errors = [];
+ }
+ }
+
+ try {
+ program = parseProgram();
+ if (typeof extra.tokens !== 'undefined') {
+ filterTokenLocation();
+ program.tokens = extra.tokens;
+ }
+ if (typeof extra.errors !== 'undefined') {
+ program.errors = extra.errors;
+ }
+ } catch (e) {
+ throw e;
+ } finally {
+ extra = {};
+ }
+
+ return program;
+ }
+
+ return {
+ tokenize: tokenize,
+ parse: parse
+ };
+
+})();
+},{}],48:[function(require,module,exports){
+var ts = Date.now();
+
+function write(msg) {
+ console.log('[Vega Log]', msg);
+}
+
+function error(msg) {
+ console.error('[Vega Err]', msg);
+}
+
+function debug(input, args) {
+ if (!debug.enable) return;
+ var log = Function.prototype.bind.call(console.log, console);
+ var state = {
+ prevTime: Date.now() - ts,
+ stamp: input.stamp
+ };
+
+ if (input.add) {
+ state.add = input.add.length;
+ state.mod = input.mod.length;
+ state.rem = input.rem.length;
+ state.reflow = !!input.reflow;
+ }
+
+ log.apply(console, (args.push(JSON.stringify(state)), args));
+ ts = Date.now();
+}
+
+module.exports = {
+ log: write,
+ error: error,
+ debug: (debug.enable = false, debug)
+};
+
+},{}],49:[function(require,module,exports){
+module.exports = {
+ path: require('./path'),
+ render: require('./render'),
+ Item: require('./util/Item'),
+ bound: require('./util/bound'),
+ Bounds: require('./util/Bounds'),
+ canvas: require('./util/canvas'),
+ Gradient: require('./util/Gradient'),
+ toJSON: require('./util/scene').toJSON,
+ fromJSON: require('./util/scene').fromJSON
+};
+},{"./path":51,"./render":71,"./util/Bounds":77,"./util/Gradient":79,"./util/Item":81,"./util/bound":82,"./util/canvas":83,"./util/scene":85}],50:[function(require,module,exports){
+var segmentCache = {},
+ bezierCache = {},
+ join = [].join;
+
+// Copied from Inkscape svgtopdf, thanks!
+function segments(x, y, rx, ry, large, sweep, rotateX, ox, oy) {
+ var key = join.call(arguments);
+ if (segmentCache[key]) {
+ return segmentCache[key];
+ }
+
+ var th = rotateX * (Math.PI/180);
+ var sin_th = Math.sin(th);
+ var cos_th = Math.cos(th);
+ rx = Math.abs(rx);
+ ry = Math.abs(ry);
+ var px = cos_th * (ox - x) * 0.5 + sin_th * (oy - y) * 0.5;
+ var py = cos_th * (oy - y) * 0.5 - sin_th * (ox - x) * 0.5;
+ var pl = (px*px) / (rx*rx) + (py*py) / (ry*ry);
+ if (pl > 1) {
+ pl = Math.sqrt(pl);
+ rx *= pl;
+ ry *= pl;
+ }
+
+ var a00 = cos_th / rx;
+ var a01 = sin_th / rx;
+ var a10 = (-sin_th) / ry;
+ var a11 = (cos_th) / ry;
+ var x0 = a00 * ox + a01 * oy;
+ var y0 = a10 * ox + a11 * oy;
+ var x1 = a00 * x + a01 * y;
+ var y1 = a10 * x + a11 * y;
+
+ var d = (x1-x0) * (x1-x0) + (y1-y0) * (y1-y0);
+ var sfactor_sq = 1 / d - 0.25;
+ if (sfactor_sq < 0) sfactor_sq = 0;
+ var sfactor = Math.sqrt(sfactor_sq);
+ if (sweep == large) sfactor = -sfactor;
+ var xc = 0.5 * (x0 + x1) - sfactor * (y1-y0);
+ var yc = 0.5 * (y0 + y1) + sfactor * (x1-x0);
+
+ var th0 = Math.atan2(y0-yc, x0-xc);
+ var th1 = Math.atan2(y1-yc, x1-xc);
+
+ var th_arc = th1-th0;
+ if (th_arc < 0 && sweep === 1){
+ th_arc += 2 * Math.PI;
+ } else if (th_arc > 0 && sweep === 0) {
+ th_arc -= 2 * Math.PI;
+ }
+
+ var segs = Math.ceil(Math.abs(th_arc / (Math.PI * 0.5 + 0.001)));
+ var result = [];
+ for (var i=0; i len) {
+ for (j=1, m=parsed.length; j=0;) {
+ if (h[i].type !== type) continue;
+ if (!handler || h[i].handler === handler) h.splice(i, 1);
+ }
+ return this;
+};
+
+prototype.pickEvent = function(evt) {
+ var rect = this._canvas.getBoundingClientRect(),
+ pad = this._padding, x, y;
+ return this.pick(this._scene,
+ x = (evt.clientX - rect.left),
+ y = (evt.clientY - rect.top),
+ x - pad.left, y - pad.top);
+};
+
+// find the scenegraph item at the current mouse position
+// x, y -- the absolute x, y mouse coordinates on the canvas element
+// gx, gy -- the relative coordinates within the current group
+prototype.pick = function(scene, x, y, gx, gy) {
+ var g = this.context(),
+ mark = marks[scene.marktype];
+ return mark.pick.call(this, g, scene, x, y, gx, gy);
+};
+
+module.exports = CanvasHandler;
+
+},{"../../util/dom":84,"../Handler":54,"./marks":63}],57:[function(require,module,exports){
+var DOM = require('../../util/dom'),
+ Bounds = require('../../util/Bounds'),
+ ImageLoader = require('../../util/ImageLoader'),
+ Canvas = require('../../util/canvas'),
+ Renderer = require('../Renderer'),
+ marks = require('./marks');
+
+function CanvasRenderer(loadConfig) {
+ Renderer.call(this);
+ this._loader = new ImageLoader(loadConfig);
+}
+
+CanvasRenderer.RETINA = true;
+
+var base = Renderer.prototype;
+var prototype = (CanvasRenderer.prototype = Object.create(base));
+prototype.constructor = CanvasRenderer;
+
+prototype.initialize = function(el, width, height, padding) {
+ this._canvas = Canvas.instance(width, height);
+ if (el) {
+ DOM.clear(el, 0).appendChild(this._canvas);
+ this._canvas.setAttribute('class', 'marks');
+ }
+ return base.initialize.call(this, el, width, height, padding);
+};
+
+prototype.resize = function(width, height, padding) {
+ base.resize.call(this, width, height, padding);
+ Canvas.resize(this._canvas, this._width, this._height,
+ this._padding, CanvasRenderer.RETINA);
+ return this;
+};
+
+prototype.canvas = function() {
+ return this._canvas;
+};
+
+prototype.context = function() {
+ return this._canvas ? this._canvas.getContext('2d') : null;
+};
+
+prototype.pendingImages = function() {
+ return this._loader.pending();
+};
+
+function clipToBounds(g, items) {
+ if (!items) return null;
+
+ var b = new Bounds(), i, n, item, mark, group;
+ for (i=0, n=items.length; i 0) {
+ if (group.fill && util.fill(g, group, opac)) {
+ g.fillRect(gx, gy, w, h);
+ }
+ if (group.stroke && util.stroke(g, group, opac)) {
+ g.strokeRect(gx, gy, w, h);
+ }
+ }
+ }
+
+ // setup graphics context
+ g.save();
+ g.translate(gx, gy);
+ if (group.clip) {
+ g.beginPath();
+ g.rect(0, 0, w, h);
+ g.clip();
+ }
+ if (bounds) bounds.translate(-gx, -gy);
+
+ // draw group contents
+ for (j=0, m=axes.length; j=0;) {
+ group = groups[i];
+
+ // first hit test against bounding box
+ // if a group is clipped, that should be handled by the bounds check.
+ b = group.bounds;
+ if (b && !b.contains(gx, gy)) continue;
+
+ // passed bounds check, so test sub-groups
+ axes = group.axisItems || EMPTY;
+ items = group.items || EMPTY;
+ legends = group.legendItems || EMPTY;
+ dx = (group.x || 0);
+ dy = (group.y || 0);
+
+ g.save();
+ g.translate(dx, dy);
+ dx = gx - dx;
+ dy = gy - dy;
+ for (j=legends.length; --j>=0;) {
+ subscene = legends[j];
+ if (subscene.interactive !== false) {
+ hits = this.pick(subscene, x, y, dx, dy);
+ if (hits) { g.restore(); return hits; }
+ }
+ }
+ for (j=axes.length; --j>=0;) {
+ subscene = axes[j];
+ if (subscene.interactive !== false && subscene.layer !== 'back') {
+ hits = this.pick(subscene, x, y, dx, dy);
+ if (hits) { g.restore(); return hits; }
+ }
+ }
+ for (j=items.length; --j>=0;) {
+ subscene = items[j];
+ if (subscene.interactive !== false) {
+ hits = this.pick(subscene, x, y, dx, dy);
+ if (hits) { g.restore(); return hits; }
+ }
+ }
+ for (j=axes.length; --j>=0;) {
+ subscene = axes[j];
+ if (subscene.interative !== false && subscene.layer === 'back') {
+ hits = this.pick(subscene, x, y, dx, dy);
+ if (hits) { g.restore(); return hits; }
+ }
+ }
+ g.restore();
+
+ if (scene.interactive !== false && (group.fill || group.stroke) &&
+ dx >= 0 && dx <= group.width && dy >= 0 && dy <= group.height) {
+ return group;
+ }
+ }
+
+ return null;
+}
+
+module.exports = {
+ draw: draw,
+ pick: pick
+};
+
+},{"./util":70}],62:[function(require,module,exports){
+var util = require('./util');
+
+function draw(g, scene, bounds) {
+ if (!scene.items || !scene.items.length) return;
+
+ var renderer = this,
+ items = scene.items, o;
+
+ for (var i=0, len=items.length; i= 0;) {
+ o = scene.items[i]; b = o.bounds;
+ // first hit test against bounding box
+ if ((b && !b.contains(gx, gy)) || !b) continue;
+ // if in bounding box, perform more careful test
+ if (test(g, o, x, y, gx, gy)) return o;
+ }
+ return null;
+ };
+}
+
+function testPath(path, filled) {
+ return function(g, o, x, y) {
+ var item = Array.isArray(o) ? o[0] : o,
+ fill = (filled == null) ? item.fill : filled,
+ stroke = item.stroke && g.isPointInStroke, lw, lc;
+
+ if (stroke) {
+ lw = item.strokeWidth;
+ lc = item.strokeCap;
+ g.lineWidth = lw != null ? lw : 1;
+ g.lineCap = lc != null ? lc : 'butt';
+ }
+
+ return path(g, o) ? false :
+ (fill && g.isPointInPath(x, y)) ||
+ (stroke && g.isPointInStroke(x, y));
+ };
+}
+
+function pickPath(path) {
+ return pick(testPath(path));
+}
+
+function fill(g, o, opacity) {
+ opacity *= (o.fillOpacity==null ? 1 : o.fillOpacity);
+ if (opacity > 0) {
+ g.globalAlpha = opacity;
+ g.fillStyle = color(g, o, o.fill);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+function stroke(g, o, opacity) {
+ var lw = (lw = o.strokeWidth) != null ? lw : 1, lc;
+ if (lw <= 0) return false;
+
+ opacity *= (o.strokeOpacity==null ? 1 : o.strokeOpacity);
+ if (opacity > 0) {
+ g.globalAlpha = opacity;
+ g.strokeStyle = color(g, o, o.stroke);
+ g.lineWidth = lw;
+ g.lineCap = (lc = o.strokeCap) != null ? lc : 'butt';
+ g.vgLineDash(o.strokeDash || null);
+ g.vgLineDashOffset(o.strokeDashOffset || 0);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+function color(g, o, value) {
+ return (value.id) ?
+ gradient(g, value, o.bounds) :
+ value;
+}
+
+function gradient(g, p, b) {
+ var w = b.width(),
+ h = b.height(),
+ x1 = b.x1 + p.x1 * w,
+ y1 = b.y1 + p.y1 * h,
+ x2 = b.x1 + p.x2 * w,
+ y2 = b.y1 + p.y2 * h,
+ grad = g.createLinearGradient(x1, y1, x2, y2),
+ stop = p.stops,
+ i, n;
+
+ for (i=0, n=stop.length; i=0;) {
+ if (h[i].type === type && !handler || h[i].handler === handler) {
+ svg.removeEventListener(name, h[i].listener);
+ h.splice(i, 1);
+ }
+ }
+ return this;
+};
+
+module.exports = SVGHandler;
+
+},{"../../util/dom":84,"../Handler":54}],73:[function(require,module,exports){
+var ImageLoader = require('../../util/ImageLoader'),
+ Renderer = require('../Renderer'),
+ text = require('../../util/text'),
+ DOM = require('../../util/dom'),
+ SVG = require('../../util/svg'),
+ ns = SVG.metadata.xmlns,
+ marks = require('./marks');
+
+function SVGRenderer(loadConfig) {
+ Renderer.call(this);
+ this._loader = new ImageLoader(loadConfig);
+ this._dirtyID = 0;
+}
+
+var base = Renderer.prototype;
+var prototype = (SVGRenderer.prototype = Object.create(base));
+prototype.constructor = SVGRenderer;
+
+prototype.initialize = function(el, width, height, padding) {
+ if (el) {
+ this._svg = DOM.child(el, 0, 'svg', ns, 'marks');
+ DOM.clear(el, 1);
+ // set the svg root group
+ this._root = DOM.child(this._svg, 0, 'g', ns);
+ DOM.clear(this._svg, 1);
+ }
+
+ // create the svg definitions cache
+ this._defs = {
+ clip_id: 1,
+ gradient: {},
+ clipping: {}
+ };
+
+ // set background color if defined
+ this.background(this._bgcolor);
+
+ return base.initialize.call(this, el, width, height, padding);
+};
+
+prototype.background = function(bgcolor) {
+ if (arguments.length && this._svg) {
+ this._svg.style.setProperty('background-color', bgcolor);
+ }
+ return base.background.apply(this, arguments);
+};
+
+prototype.resize = function(width, height, padding) {
+ base.resize.call(this, width, height, padding);
+
+ if (this._svg) {
+ var w = this._width,
+ h = this._height,
+ p = this._padding;
+
+ this._svg.setAttribute('width', w + p.left + p.right);
+ this._svg.setAttribute('height', h + p.top + p.bottom);
+
+ this._root.setAttribute('transform', 'translate('+p.left+','+p.top+')');
+ }
+
+ return this;
+};
+
+prototype.svg = function() {
+ if (!this._svg) return null;
+
+ var attr = {
+ 'class': 'marks',
+ 'width': this._width + this._padding.left + this._padding.right,
+ 'height': this._height + this._padding.top + this._padding.bottom,
+ };
+ for (var key in SVG.metadata) {
+ attr[key] = SVG.metadata[key];
+ }
+
+ return DOM.openTag('svg', attr) + this._svg.innerHTML + DOM.closeTag('svg');
+};
+
+prototype.imageURL = function(url) {
+ return this._loader.imageURL(url);
+};
+
+
+// -- Render entry point --
+
+prototype.render = function(scene, items) {
+ if (this._dirtyCheck(items)) {
+ if (this._dirtyAll) this._resetDefs();
+ this.draw(this._root, scene, -1);
+ DOM.clear(this._root, 1);
+ }
+ this.updateDefs();
+ return this;
+};
+
+prototype.draw = function(el, scene, index) {
+ this.drawMark(el, scene, index, marks[scene.marktype]);
+};
+
+
+// -- Manage SVG definitions ('defs') block --
+
+prototype.updateDefs = function() {
+ var svg = this._svg,
+ defs = this._defs,
+ el = defs.el,
+ index = 0, id;
+
+ for (id in defs.gradient) {
+ if (!el) el = (defs.el = DOM.child(svg, 0, 'defs', ns));
+ updateGradient(el, defs.gradient[id], index++);
+ }
+
+ for (id in defs.clipping) {
+ if (!el) el = (defs.el = DOM.child(svg, 0, 'defs', ns));
+ updateClipping(el, defs.clipping[id], index++);
+ }
+
+ // clean-up
+ if (el) {
+ if (index === 0) {
+ svg.removeChild(el);
+ defs.el = null;
+ } else {
+ DOM.clear(el, index);
+ }
+ }
+};
+
+function updateGradient(el, grad, index) {
+ var i, n, stop;
+
+ el = DOM.child(el, index, 'linearGradient', ns);
+ el.setAttribute('id', grad.id);
+ el.setAttribute('x1', grad.x1);
+ el.setAttribute('x2', grad.x2);
+ el.setAttribute('y1', grad.y1);
+ el.setAttribute('y2', grad.y2);
+
+ for (i=0, n=grad.stops.length; i 0) ? openTag('defs') + defs + closeTag('defs') : '';
+};
+
+prototype.imageURL = function(url) {
+ return this._loader.imageURL(url);
+};
+
+var object;
+
+function emit(name, value, ns, prefixed) {
+ object[prefixed || name] = value;
+}
+
+prototype.attributes = function(attr, item) {
+ object = {};
+ attr(emit, item, this);
+ return object;
+};
+
+prototype.mark = function(scene) {
+ var mdef = MARKS[scene.marktype],
+ tag = mdef.tag,
+ attr = mdef.attr,
+ nest = mdef.nest || false,
+ data = nest ?
+ (scene.items && scene.items.length ? [scene.items[0]] : []) :
+ (scene.items || []),
+ defs = this._defs,
+ str = '',
+ style, i, item;
+
+ if (tag !== 'g' && scene.interactive === false) {
+ style = 'style="pointer-events: none;"';
+ }
+
+ // render opening group tag
+ str += openTag('g', {
+ 'class': DOM.cssClass(scene)
+ }, style);
+
+ // render contained elements
+ for (i=0; i/g, '>');
+}
+
+module.exports = SVGStringRenderer;
+
+},{"../../util/ImageLoader":80,"../../util/dom":84,"../../util/svg":86,"../../util/text":87,"../Renderer":55,"./marks":76}],75:[function(require,module,exports){
+module.exports = {
+ Handler: require('./SVGHandler'),
+ Renderer: require('./SVGRenderer'),
+ string: {
+ Renderer : require('./SVGStringRenderer')
+ }
+};
+},{"./SVGHandler":72,"./SVGRenderer":73,"./SVGStringRenderer":74}],76:[function(require,module,exports){
+var text = require('../../util/text'),
+ SVG = require('../../util/svg'),
+ textAlign = SVG.textAlign,
+ path = SVG.path;
+
+function translateItem(o) {
+ return translate(o.x || 0, o.y || 0);
+}
+
+function translate(x, y) {
+ return 'translate(' + x + ',' + y + ')';
+}
+
+module.exports = {
+ arc: {
+ tag: 'path',
+ type: 'arc',
+ attr: function(emit, o) {
+ emit('transform', translateItem(o));
+ emit('d', path.arc(o));
+ }
+ },
+ area: {
+ tag: 'path',
+ type: 'area',
+ nest: true,
+ attr: function(emit, o) {
+ var items = o.mark.items;
+ if (items.length) emit('d', path.area(items));
+ }
+ },
+ group: {
+ tag: 'g',
+ type: 'group',
+ attr: function(emit, o, renderer) {
+ var id = null, defs, c;
+ emit('transform', translateItem(o));
+ if (o.clip) {
+ defs = renderer._defs;
+ id = o.clip_id || (o.clip_id = 'clip' + defs.clip_id++);
+ c = defs.clipping[id] || (defs.clipping[id] = {id: id});
+ c.width = o.width || 0;
+ c.height = o.height || 0;
+ }
+ emit('clip-path', id ? ('url(#' + id + ')') : null);
+ },
+ background: function(emit, o) {
+ emit('class', 'background');
+ emit('width', o.width || 0);
+ emit('height', o.height || 0);
+ }
+ },
+ image: {
+ tag: 'image',
+ type: 'image',
+ attr: function(emit, o, renderer) {
+ var x = o.x || 0,
+ y = o.y || 0,
+ w = o.width || 0,
+ h = o.height || 0,
+ url = renderer.imageURL(o.url);
+
+ x = x - (o.align === 'center' ? w/2 : o.align === 'right' ? w : 0);
+ y = y - (o.baseline === 'middle' ? h/2 : o.baseline === 'bottom' ? h : 0);
+
+ emit('href', url, 'http://www.w3.org/1999/xlink', 'xlink:href');
+ emit('transform', translate(x, y));
+ emit('width', w);
+ emit('height', h);
+ }
+ },
+ line: {
+ tag: 'path',
+ type: 'line',
+ nest: true,
+ attr: function(emit, o) {
+ var items = o.mark.items;
+ if (items.length) emit('d', path.line(items));
+ }
+ },
+ path: {
+ tag: 'path',
+ type: 'path',
+ attr: function(emit, o) {
+ emit('transform', translateItem(o));
+ emit('d', o.path);
+ }
+ },
+ rect: {
+ tag: 'rect',
+ type: 'rect',
+ nest: false,
+ attr: function(emit, o) {
+ emit('transform', translateItem(o));
+ emit('width', o.width || 0);
+ emit('height', o.height || 0);
+ }
+ },
+ rule: {
+ tag: 'line',
+ type: 'rule',
+ attr: function(emit, o) {
+ emit('transform', translateItem(o));
+ emit('x2', o.x2 != null ? o.x2 - (o.x||0) : 0);
+ emit('y2', o.y2 != null ? o.y2 - (o.y||0) : 0);
+ }
+ },
+ symbol: {
+ tag: 'path',
+ type: 'symbol',
+ attr: function(emit, o) {
+ emit('transform', translateItem(o));
+ emit('d', path.symbol(o));
+ }
+ },
+ text: {
+ tag: 'text',
+ type: 'text',
+ nest: false,
+ attr: function(emit, o) {
+ var dx = (o.dx || 0),
+ dy = (o.dy || 0) + text.offset(o),
+ x = (o.x || 0),
+ y = (o.y || 0),
+ a = o.angle || 0,
+ r = o.radius || 0, t;
+
+ if (r) {
+ t = (o.theta || 0) - Math.PI/2;
+ x += r * Math.cos(t);
+ y += r * Math.sin(t);
+ }
+
+ emit('text-anchor', textAlign[o.align] || 'start');
+
+ if (a) {
+ t = translate(x, y) + ' rotate('+a+')';
+ if (dx || dy) t += ' ' + translate(dx, dy);
+ } else {
+ t = translate(x+dx, y+dy);
+ }
+ emit('transform', t);
+ }
+ }
+};
+
+},{"../../util/svg":86,"../../util/text":87}],77:[function(require,module,exports){
+function Bounds(b) {
+ this.clear();
+ if (b) this.union(b);
+}
+
+var prototype = Bounds.prototype;
+
+prototype.clone = function() {
+ return new Bounds(this);
+};
+
+prototype.clear = function() {
+ this.x1 = +Number.MAX_VALUE;
+ this.y1 = +Number.MAX_VALUE;
+ this.x2 = -Number.MAX_VALUE;
+ this.y2 = -Number.MAX_VALUE;
+ return this;
+};
+
+prototype.set = function(x1, y1, x2, y2) {
+ this.x1 = x1;
+ this.y1 = y1;
+ this.x2 = x2;
+ this.y2 = y2;
+ return this;
+};
+
+prototype.add = function(x, y) {
+ if (x < this.x1) this.x1 = x;
+ if (y < this.y1) this.y1 = y;
+ if (x > this.x2) this.x2 = x;
+ if (y > this.y2) this.y2 = y;
+ return this;
+};
+
+prototype.expand = function(d) {
+ this.x1 -= d;
+ this.y1 -= d;
+ this.x2 += d;
+ this.y2 += d;
+ return this;
+};
+
+prototype.round = function() {
+ this.x1 = Math.floor(this.x1);
+ this.y1 = Math.floor(this.y1);
+ this.x2 = Math.ceil(this.x2);
+ this.y2 = Math.ceil(this.y2);
+ return this;
+};
+
+prototype.translate = function(dx, dy) {
+ this.x1 += dx;
+ this.x2 += dx;
+ this.y1 += dy;
+ this.y2 += dy;
+ return this;
+};
+
+prototype.rotate = function(angle, x, y) {
+ var cos = Math.cos(angle),
+ sin = Math.sin(angle),
+ cx = x - x*cos + y*sin,
+ cy = y - x*sin - y*cos,
+ x1 = this.x1, x2 = this.x2,
+ y1 = this.y1, y2 = this.y2;
+
+ return this.clear()
+ .add(cos*x1 - sin*y1 + cx, sin*x1 + cos*y1 + cy)
+ .add(cos*x1 - sin*y2 + cx, sin*x1 + cos*y2 + cy)
+ .add(cos*x2 - sin*y1 + cx, sin*x2 + cos*y1 + cy)
+ .add(cos*x2 - sin*y2 + cx, sin*x2 + cos*y2 + cy);
+};
+
+prototype.union = function(b) {
+ if (b.x1 < this.x1) this.x1 = b.x1;
+ if (b.y1 < this.y1) this.y1 = b.y1;
+ if (b.x2 > this.x2) this.x2 = b.x2;
+ if (b.y2 > this.y2) this.y2 = b.y2;
+ return this;
+};
+
+prototype.encloses = function(b) {
+ return b && (
+ this.x1 <= b.x1 &&
+ this.x2 >= b.x2 &&
+ this.y1 <= b.y1 &&
+ this.y2 >= b.y2
+ );
+};
+
+prototype.alignsWith = function(b) {
+ return b && (
+ this.x1 == b.x1 ||
+ this.x2 == b.x2 ||
+ this.y1 == b.y1 ||
+ this.y2 == b.y2
+ );
+};
+
+prototype.intersects = function(b) {
+ return b && !(
+ this.x2 < b.x1 ||
+ this.x1 > b.x2 ||
+ this.y2 < b.y1 ||
+ this.y1 > b.y2
+ );
+};
+
+prototype.contains = function(x, y) {
+ return !(
+ x < this.x1 ||
+ x > this.x2 ||
+ y < this.y1 ||
+ y > this.y2
+ );
+};
+
+prototype.width = function() {
+ return this.x2 - this.x1;
+};
+
+prototype.height = function() {
+ return this.y2 - this.y1;
+};
+
+module.exports = Bounds;
+
+},{}],78:[function(require,module,exports){
+module.exports = function(b) {
+ function noop() { }
+ function add(x,y) { b.add(x, y); }
+
+ return {
+ bounds: function(_) {
+ if (!arguments.length) return b;
+ return (b = _, this);
+ },
+ beginPath: noop,
+ closePath: noop,
+ moveTo: add,
+ lineTo: add,
+ quadraticCurveTo: function(x1, y1, x2, y2) {
+ b.add(x1, y1);
+ b.add(x2, y2);
+ },
+ bezierCurveTo: function(x1, y1, x2, y2, x3, y3) {
+ b.add(x1, y1);
+ b.add(x2, y2);
+ b.add(x3, y3);
+ }
+ };
+};
+
+},{}],79:[function(require,module,exports){
+var gradient_id = 0;
+
+function Gradient(type) {
+ this.id = 'gradient_' + (gradient_id++);
+ this.type = type || 'linear';
+ this.stops = [];
+ this.x1 = 0;
+ this.x2 = 1;
+ this.y1 = 0;
+ this.y2 = 0;
+}
+
+var prototype = Gradient.prototype;
+
+prototype.stop = function(offset, color) {
+ this.stops.push({
+ offset: offset,
+ color: color
+ });
+ return this;
+};
+
+module.exports = Gradient;
+},{}],80:[function(require,module,exports){
+(function (global){
+var load = require('datalib/src/import/load');
+
+function ImageLoader(loadConfig) {
+ this._pending = 0;
+ this._config = loadConfig || ImageLoader.Config;
+}
+
+// Overridable global default load configuration
+ImageLoader.Config = null;
+
+var prototype = ImageLoader.prototype;
+
+prototype.pending = function() {
+ return this._pending;
+};
+
+prototype.params = function(uri) {
+ var p = {url: uri}, k;
+ for (k in this._config) { p[k] = this._config[k]; }
+ return p;
+};
+
+prototype.imageURL = function(uri) {
+ return load.sanitizeUrl(this.params(uri));
+};
+
+function browser(uri, callback) {
+ var url = load.sanitizeUrl(this.params(uri));
+ if (!url) { // error
+ if (callback) callback(uri, null);
+ return null;
+ }
+
+ var loader = this,
+ image = new Image();
+
+ loader._pending += 1;
+
+ image.onload = function() {
+ loader._pending -= 1;
+ image.loaded = true;
+ if (callback) callback(null, image);
+ };
+ image.src = url;
+
+ return image;
+}
+
+function server(uri, callback) {
+ var loader = this,
+ image = new ((typeof window !== "undefined" ? window['canvas'] : typeof global !== "undefined" ? global['canvas'] : null).Image)();
+
+ loader._pending += 1;
+
+ load(this.params(uri), function(err, data) {
+ loader._pending -= 1;
+ if (err) {
+ if (callback) callback(err, null);
+ return null;
+ }
+ image.src = data;
+ image.loaded = true;
+ if (callback) callback(null, image);
+ });
+
+ return image;
+}
+
+prototype.loadImage = function(uri, callback) {
+ return load.useXHR ?
+ browser.call(this, uri, callback) :
+ server.call(this, uri, callback);
+};
+
+module.exports = ImageLoader;
+
+}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+
+},{"datalib/src/import/load":22}],81:[function(require,module,exports){
+function Item(mark) {
+ this.mark = mark;
+}
+
+var prototype = Item.prototype;
+
+prototype.hasPropertySet = function(name) {
+ var props = this.mark.def.properties;
+ return props && props[name] != null;
+};
+
+prototype.cousin = function(offset, index) {
+ if (offset === 0) return this;
+ offset = offset || -1;
+ var mark = this.mark,
+ group = mark.group,
+ iidx = index==null ? mark.items.indexOf(this) : index,
+ midx = group.items.indexOf(mark) + offset;
+ return group.items[midx].items[iidx];
+};
+
+prototype.sibling = function(offset) {
+ if (offset === 0) return this;
+ offset = offset || -1;
+ var mark = this.mark,
+ iidx = mark.items.indexOf(this) + offset;
+ return mark.items[iidx];
+};
+
+prototype.remove = function() {
+ var item = this,
+ list = item.mark.items,
+ i = list.indexOf(item);
+ if (i >= 0) {
+ if (i===list.length-1) {
+ list.pop();
+ } else {
+ list.splice(i, 1);
+ }
+ }
+ return item;
+};
+
+prototype.touch = function() {
+ if (this.pathCache) this.pathCache = null;
+};
+
+module.exports = Item;
+},{}],82:[function(require,module,exports){
+var BoundsContext = require('./BoundsContext'),
+ Bounds = require('./Bounds'),
+ canvas = require('./canvas'),
+ svg = require('./svg'),
+ text = require('./text'),
+ paths = require('../path'),
+ parse = paths.parse,
+ drawPath = paths.render,
+ areaPath = svg.path.area,
+ linePath = svg.path.line,
+ halfpi = Math.PI / 2,
+ sqrt3 = Math.sqrt(3),
+ tan30 = Math.tan(30 * Math.PI / 180),
+ g2D = null,
+ bc = BoundsContext();
+
+function context() {
+ return g2D || (g2D = canvas.instance(1,1).getContext('2d'));
+}
+
+function strokeBounds(o, bounds) {
+ if (o.stroke && o.opacity !== 0 && o.stokeOpacity !== 0) {
+ bounds.expand(o.strokeWidth != null ? o.strokeWidth : 1);
+ }
+ return bounds;
+}
+
+function pathBounds(o, path, bounds, x, y) {
+ if (path == null) {
+ bounds.set(0, 0, 0, 0);
+ } else {
+ drawPath(bc.bounds(bounds), path, x, y);
+ strokeBounds(o, bounds);
+ }
+ return bounds;
+}
+
+function path(o, bounds) {
+ var p = o.path ? o.pathCache || (o.pathCache = parse(o.path)) : null;
+ return pathBounds(o, p, bounds, o.x, o.y);
+}
+
+function area(mark, bounds) {
+ if (mark.items.length === 0) return bounds;
+ var items = mark.items,
+ item = items[0],
+ p = item.pathCache || (item.pathCache = parse(areaPath(items)));
+ return pathBounds(item, p, bounds);
+}
+
+function line(mark, bounds) {
+ if (mark.items.length === 0) return bounds;
+ var items = mark.items,
+ item = items[0],
+ p = item.pathCache || (item.pathCache = parse(linePath(items)));
+ return pathBounds(item, p, bounds);
+}
+
+function rect(o, bounds) {
+ var x, y;
+ return strokeBounds(o, bounds.set(
+ x = o.x || 0,
+ y = o.y || 0,
+ (x + o.width) || 0,
+ (y + o.height) || 0
+ ));
+}
+
+function image(o, bounds) {
+ var x = o.x || 0,
+ y = o.y || 0,
+ w = o.width || 0,
+ h = o.height || 0;
+ x = x - (o.align === 'center' ? w/2 : (o.align === 'right' ? w : 0));
+ y = y - (o.baseline === 'middle' ? h/2 : (o.baseline === 'bottom' ? h : 0));
+ return bounds.set(x, y, x+w, y+h);
+}
+
+function rule(o, bounds) {
+ var x1, y1;
+ return strokeBounds(o, bounds.set(
+ x1 = o.x || 0,
+ y1 = o.y || 0,
+ o.x2 != null ? o.x2 : x1,
+ o.y2 != null ? o.y2 : y1
+ ));
+}
+
+function arc(o, bounds) {
+ var cx = o.x || 0,
+ cy = o.y || 0,
+ ir = o.innerRadius || 0,
+ or = o.outerRadius || 0,
+ sa = (o.startAngle || 0) - halfpi,
+ ea = (o.endAngle || 0) - halfpi,
+ xmin = Infinity, xmax = -Infinity,
+ ymin = Infinity, ymax = -Infinity,
+ a, i, n, x, y, ix, iy, ox, oy;
+
+ var angles = [sa, ea],
+ s = sa - (sa % halfpi);
+ for (i=0; i<4 && s index) {
+ el.removeChild(el.childNodes[--curr]);
+ }
+ return el;
+ },
+ remove: remove,
+ // generate css class name for mark
+ cssClass: function(mark) {
+ return 'mark-' + mark.marktype + (mark.name ? ' '+mark.name : '');
+ },
+ // generate string for an opening xml tag
+ // tag: the name of the xml tag
+ // attr: hash of attribute name-value pairs to include
+ // raw: additional raw string to include in tag markup
+ openTag: function(tag, attr, raw) {
+ var s = '<' + tag, key, val;
+ if (attr) {
+ for (key in attr) {
+ val = attr[key];
+ if (val != null) {
+ s += ' ' + key + '="' + val + '"';
+ }
+ }
+ }
+ if (raw) s += ' ' + raw;
+ return s + '>';
+ },
+ // generate string for closing xml tag
+ // tag: the name of the xml tag
+ closeTag: function(tag) {
+ return '' + tag + '>';
+ }
+};
+
+},{}],85:[function(require,module,exports){
+var bound = require('../util/bound');
+
+var sets = [
+ 'items',
+ 'axisItems',
+ 'legendItems'
+];
+
+var keys = [
+ 'marktype', 'name', 'interactive', 'clip',
+ 'items', 'axisItems', 'legendItems', 'layer',
+ 'x', 'y', 'width', 'height', 'align', 'baseline', // layout
+ 'fill', 'fillOpacity', 'opacity', // fill
+ 'stroke', 'strokeOpacity', 'strokeWidth', 'strokeCap', // stroke
+ 'strokeDash', 'strokeDashOffset', // stroke dash
+ 'startAngle', 'endAngle', 'innerRadius', 'outerRadius', // arc
+ 'interpolate', 'tension', 'orient', // area, line
+ 'url', // image
+ 'path', // path
+ 'x2', 'y2', // rule
+ 'size', 'shape', // symbol
+ 'text', 'angle', 'theta', 'radius', 'dx', 'dy', // text
+ 'font', 'fontSize', 'fontWeight', 'fontStyle', 'fontVariant' // font
+];
+
+function toJSON(scene, indent) {
+ return JSON.stringify(scene, keys, indent);
+}
+
+function fromJSON(json) {
+ var scene = (typeof json === 'string' ? JSON.parse(json) : json);
+ return initialize(scene);
+}
+
+function initialize(scene) {
+ var type = scene.marktype,
+ i, n, s, m, items;
+
+ for (s=0, m=sets.length; s 0) { wait(); } else { callback(this.canvas()); }
+};
+
+prototype.svg = function() {
+ return (this._type === 'svg') ? this._renderer.svg() : null;
+};
+
+prototype.initialize = function() {
+ var w = this._width,
+ h = this._height,
+ bg = this._bgcolor,
+ pad = this._padding,
+ config = this.model().config();
+
+ if (this._viewport) {
+ w = this._viewport[0] - (pad ? pad.left + pad.right : 0);
+ h = this._viewport[1] - (pad ? pad.top + pad.bottom : 0);
+ }
+
+ this._renderer = (this._renderer || new this._io.Renderer(config.load))
+ .initialize(null, w, h, pad)
+ .background(bg);
+
+ return this;
+};
+
+module.exports = HeadlessView;
+},{"./View":90,"vega-scenegraph":49}],89:[function(require,module,exports){
+var dl = require('datalib'),
+ df = require('vega-dataflow'),
+ ChangeSet = df.ChangeSet,
+ Base = df.Graph.prototype,
+ Node = df.Node, // jshint ignore:line
+ GroupBuilder = require('../scene/GroupBuilder'),
+ visit = require('../scene/visit'),
+ compiler = require('../parse/expr'),
+ config = require('./config');
+
+function Model(cfg) {
+ this._defs = {};
+ this._predicates = {};
+
+ this._scene = null; // Root scenegraph node.
+ this._groups = null; // Index of group items.
+
+ this._node = null;
+ this._builder = null; // Top-level scenegraph builder.
+
+ this._reset = {axes: false, legends: false};
+
+ this.config(cfg);
+ this.expr = compiler(this);
+ Base.init.call(this);
+}
+
+var prototype = (Model.prototype = Object.create(Base));
+prototype.constructor = Model;
+
+prototype.defs = function(defs) {
+ if (!arguments.length) return this._defs;
+ this._defs = defs;
+ return this;
+};
+
+prototype.config = function(cfg) {
+ if (!arguments.length) return this._config;
+ this._config = Object.create(config);
+ for (var name in cfg) {
+ var x = cfg[name], y = this._config[name];
+ if (dl.isObject(x) && dl.isObject(y)) {
+ this._config[name] = dl.extend({}, y, x);
+ } else {
+ this._config[name] = x;
+ }
+ }
+
+ return this;
+};
+
+prototype.width = function(width) {
+ if (this._defs) this._defs.width = width;
+ if (this._defs && this._defs.marks) this._defs.marks.width = width;
+ if (this._scene) {
+ this._scene.items[0].width = width;
+ this._scene.items[0]._dirty = true;
+ }
+ this._reset.axes = true;
+ return this;
+};
+
+prototype.height = function(height) {
+ if (this._defs) this._defs.height = height;
+ if (this._defs && this._defs.marks) this._defs.marks.height = height;
+ if (this._scene) {
+ this._scene.items[0].height = height;
+ this._scene.items[0]._dirty = true;
+ }
+ this._reset.axes = true;
+ return this;
+};
+
+prototype.node = function() {
+ return this._node || (this._node = new Node(this));
+};
+
+prototype.data = function() {
+ var data = Base.data.apply(this, arguments);
+ if (arguments.length > 1) { // new Datasource
+ this.node().addListener(data.pipeline()[0]);
+ }
+ return data;
+};
+
+function predicates(name) {
+ var m = this, pred = {};
+ if (!dl.isArray(name)) return this._predicates[name];
+ name.forEach(function(n) { pred[n] = m._predicates[n]; });
+ return pred;
+}
+
+prototype.predicate = function(name, predicate) {
+ if (arguments.length === 1) return predicates.call(this, name);
+ return (this._predicates[name] = predicate);
+};
+
+prototype.predicates = function() { return this._predicates; };
+
+prototype.scene = function(renderer) {
+ if (!arguments.length) return this._scene;
+
+ if (this._builder) {
+ this.node().removeListener(this._builder);
+ this._builder._groupBuilder.disconnect();
+ }
+
+ var m = this,
+ b = this._builder = new Node(this);
+
+ b.evaluate = function(input) {
+ if (b._groupBuilder) return input;
+
+ var gb = b._groupBuilder = new GroupBuilder(m, m._defs.marks, m._scene={}),
+ p = gb.pipeline();
+
+ m._groups = {};
+ this.addListener(gb.connect());
+ p[p.length-1].addListener(renderer);
+ return input;
+ };
+
+ this.addListener(b);
+ return this;
+};
+
+prototype.group = function(id, item) {
+ var groups = this._groups;
+ if (arguments.length === 1) return groups[id];
+ return (groups[id] = item, this);
+};
+
+prototype.reset = function() {
+ if (this._scene && this._reset.axes) {
+ visit(this._scene, function(item) {
+ if (item.axes) item.axes.forEach(function(axis) { axis.reset(); });
+ });
+ this._reset.axes = false;
+ }
+ if (this._scene && this._reset.legends) {
+ visit(this._scene, function(item) {
+ if (item.legends) item.legends.forEach(function(l) { l.reset(); });
+ });
+ this._reset.legends = false;
+ }
+ return this;
+};
+
+prototype.addListener = function(l) {
+ this.node().addListener(l);
+};
+
+prototype.removeListener = function(l) {
+ this.node().removeListener(l);
+};
+
+prototype.fire = function(cs) {
+ if (!cs) cs = ChangeSet.create();
+ this.propagate(cs, this.node());
+};
+
+module.exports = Model;
+},{"../parse/expr":96,"../scene/GroupBuilder":112,"../scene/visit":117,"./config":91,"datalib":26,"vega-dataflow":41}],90:[function(require,module,exports){
+(function (global){
+var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null),
+ dl = require('datalib'),
+ df = require('vega-dataflow'),
+ sg = require('vega-scenegraph').render,
+ log = require('vega-logging'),
+ Deps = df.Dependencies,
+ parseStreams = require('../parse/streams'),
+ Encoder = require('../scene/Encoder'),
+ Transition = require('../scene/Transition');
+
+function View(el, width, height) {
+ this._el = null;
+ this._model = null;
+ this._width = this.__width = width || 500;
+ this._height = this.__height = height || 300;
+ this._bgcolor = null;
+ this._cursor = true; // Set cursor based on hover propset?
+ this._autopad = 1;
+ this._padding = {top:0, left:0, bottom:0, right:0};
+ this._viewport = null;
+ this._renderer = null;
+ this._handler = null;
+ this._streamer = null; // Targeted update for streaming changes
+ this._skipSignals = false; // Batch set signals can skip reevaluation.
+ this._changeset = null;
+ this._repaint = true; // Full re-render on every re-init
+ this._renderers = sg;
+ this._io = null;
+ this._api = {}; // Stash streaming data API sandboxes.
+}
+
+var prototype = View.prototype;
+
+prototype.model = function(model) {
+ if (!arguments.length) return this._model;
+ if (this._model !== model) {
+ this._model = model;
+ this._streamer = new df.Node(model);
+ this._streamer._rank = -1; // HACK: To reduce re-ranking churn.
+ this._changeset = df.ChangeSet.create();
+ if (this._handler) this._handler.model(model);
+ }
+ return this;
+};
+
+// Sandboxed streaming data API
+function streaming(src) {
+ var view = this,
+ ds = this._model.data(src);
+ if (!ds) return log.error('Data source "'+src+'" is not defined.');
+
+ var listener = ds.pipeline()[0],
+ streamer = this._streamer,
+ api = {};
+
+ // If we have it stashed, don't create a new closure.
+ if (this._api[src]) return this._api[src];
+
+ api.insert = function(vals) {
+ ds.insert(dl.duplicate(vals)); // Don't pollute the environment
+ streamer.addListener(listener);
+ view._changeset.data[src] = 1;
+ return api;
+ };
+
+ api.update = function() {
+ streamer.addListener(listener);
+ view._changeset.data[src] = 1;
+ return (ds.update.apply(ds, arguments), api);
+ };
+
+ api.remove = function() {
+ streamer.addListener(listener);
+ view._changeset.data[src] = 1;
+ return (ds.remove.apply(ds, arguments), api);
+ };
+
+ api.values = function() { return ds.values(); };
+
+ return (this._api[src] = api);
+}
+
+prototype.data = function(data) {
+ var v = this;
+ if (!arguments.length) return v._model.values();
+ else if (dl.isString(data)) return streaming.call(v, data);
+ else if (dl.isObject(data)) {
+ dl.keys(data).forEach(function(k) {
+ var api = streaming.call(v, k);
+ data[k](api);
+ });
+ }
+ return this;
+};
+
+var VIEW_SIGNALS = dl.toMap(['width', 'height', 'padding']);
+
+prototype.signal = function(name, value, skip) {
+ var m = this._model,
+ key, values;
+
+ // Getter. Returns the value for the specified signal, or
+ // returns all signal values.
+ if (!arguments.length) {
+ return m.values(Deps.SIGNALS);
+ } else if (arguments.length === 1 && dl.isString(name)) {
+ return m.values(Deps.SIGNALS, name);
+ }
+
+ // Setter. Can be done in batch or individually. In either case,
+ // the final argument determines if set signals should be skipped.
+ if (dl.isObject(name)) {
+ values = name;
+ skip = value;
+ } else {
+ values = {};
+ values[name] = value;
+ }
+ for (key in values) {
+ if (VIEW_SIGNALS[key]) {
+ this[key](values[key]);
+ } else {
+ setSignal.call(this, key, values[key]);
+ }
+ }
+ return (this._skipSignals = skip, this);
+};
+
+function setSignal(name, value) {
+ var cs = this._changeset,
+ sg = this._model.signal(name);
+ if (!sg) return log.error('Signal "'+name+'" is not defined.');
+
+ this._streamer.addListener(sg.value(value));
+ cs.signals[name] = 1;
+ cs.reflow = true;
+}
+
+prototype.width = function(width) {
+ if (!arguments.length) return this.__width;
+ if (this.__width !== width) {
+ this._width = this.__width = width;
+ this.model().width(width);
+ this.initialize();
+ if (this._strict) this._autopad = 1;
+ setSignal.call(this, 'width', width);
+ }
+ return this;
+};
+
+prototype.height = function(height) {
+ if (!arguments.length) return this.__height;
+ if (this.__height !== height) {
+ this._height = this.__height = height;
+ this.model().height(height);
+ this.initialize();
+ if (this._strict) this._autopad = 1;
+ setSignal.call(this, 'height', height);
+ }
+ return this;
+};
+
+prototype.background = function(bgcolor) {
+ if (!arguments.length) return this._bgcolor;
+ if (this._bgcolor !== bgcolor) {
+ this._bgcolor = bgcolor;
+ this.initialize();
+ }
+ return this;
+};
+
+prototype.padding = function(pad) {
+ if (!arguments.length) return this._padding;
+ if (this._padding !== pad) {
+ if (dl.isString(pad)) {
+ this._autopad = 1;
+ this._padding = {top:0, left:0, bottom:0, right:0};
+ this._strict = (pad === 'strict');
+ } else {
+ this._autopad = 0;
+ this._padding = pad;
+ this._strict = false;
+ }
+ if (this._renderer) this._renderer.resize(this._width, this._height, this._padding);
+ if (this._handler) this._handler.padding(this._padding);
+ setSignal.call(this, 'padding', this._padding);
+ }
+ return (this._repaint = true, this);
+};
+
+prototype.autopad = function(opt) {
+ if (this._autopad < 1) return this;
+ else this._autopad = 0;
+
+ var b = this.model().scene().bounds,
+ pad = this._padding,
+ config = this.model().config(),
+ inset = config.autopadInset,
+ l = b.x1 < 0 ? Math.ceil(-b.x1) + inset : 0,
+ t = b.y1 < 0 ? Math.ceil(-b.y1) + inset : 0,
+ r = b.x2 > this._width ? Math.ceil(+b.x2 - this._width) + inset : 0;
+ b = b.y2 > this._height ? Math.ceil(+b.y2 - this._height) + inset : 0;
+ pad = {left:l, top:t, right:r, bottom:b};
+
+ if (this._strict) {
+ this._autopad = 0;
+ this._padding = pad;
+ this._width = Math.max(0, this.__width - (l+r));
+ this._height = Math.max(0, this.__height - (t+b));
+
+ this._model.width(this._width).height(this._height).reset();
+ setSignal.call(this, 'width', this._width);
+ setSignal.call(this, 'height', this._height);
+ setSignal.call(this, 'padding', pad);
+
+ this.initialize().update({props:'enter'}).update({props:'update'});
+ } else {
+ this.padding(pad).update(opt);
+ }
+ return this;
+};
+
+prototype.viewport = function(size) {
+ if (!arguments.length) return this._viewport;
+ if (this._viewport !== size) {
+ this._viewport = size;
+ this.initialize();
+ }
+ return this;
+};
+
+prototype.renderer = function(type) {
+ if (!arguments.length) return this._renderer;
+ if (this._renderers[type]) type = this._renderers[type];
+ else if (dl.isString(type)) throw new Error('Unknown renderer: ' + type);
+ else if (!type) throw new Error('No renderer specified');
+
+ if (this._io !== type) {
+ this._io = type;
+ this._renderer = null;
+ this.initialize();
+ if (this._build) this.render();
+ }
+ return this;
+};
+
+prototype.initialize = function(el) {
+ var v = this, prevHandler,
+ w = v._width, h = v._height, pad = v._padding, bg = v._bgcolor,
+ config = this.model().config();
+
+ if (!arguments.length || el === null) {
+ el = this._el ? this._el.parentNode : null;
+ if (!el) return this; // This View cannot init w/o an
+ }
+
+ // clear pre-existing container
+ d3.select(el).select('div.vega').remove();
+
+ // add div container
+ this._el = el = d3.select(el)
+ .append('div')
+ .attr('class', 'vega')
+ .style('position', 'relative')
+ .node();
+ if (v._viewport) {
+ d3.select(el)
+ .style('width', (v._viewport[0] || w)+'px')
+ .style('height', (v._viewport[1] || h)+'px')
+ .style('overflow', 'auto');
+ }
+
+ // renderer
+ sg.canvas.Renderer.RETINA = config.render.retina;
+ v._renderer = (v._renderer || new this._io.Renderer(config.load))
+ .initialize(el, w, h, pad)
+ .background(bg);
+
+ // input handler
+ prevHandler = v._handler;
+ v._handler = new this._io.Handler()
+ .initialize(el, pad, v);
+
+ if (prevHandler) {
+ prevHandler.handlers().forEach(function(h) {
+ v._handler.on(h.type, h.handler);
+ });
+ } else {
+ // Register event listeners for signal stream definitions.
+ v._detach = parseStreams(this);
+ }
+
+ return (this._repaint = true, this);
+};
+
+prototype.destroy = function() {
+ if (this._detach) this._detach();
+};
+
+function build() {
+ var v = this;
+ v._renderNode = new df.Node(v._model)
+ .router(true);
+
+ v._renderNode.evaluate = function(input) {
+ log.debug(input, ['rendering']);
+
+ var s = v._model.scene(),
+ h = v._handler;
+
+ if (h && h.scene) h.scene(s);
+
+ if (input.trans) {
+ input.trans.start(function(items) { v._renderer.render(s, items); });
+ } else if (v._repaint) {
+ v._renderer.render(s);
+ } else if (input.dirty.length) {
+ v._renderer.render(s, input.dirty);
+ }
+
+ if (input.dirty.length) {
+ input.dirty.forEach(function(i) { i._dirty = false; });
+ s.items[0]._dirty = false;
+ }
+
+ v._repaint = v._skipSignals = false;
+ return input;
+ };
+
+ return (v._model.scene(v._renderNode), true);
+}
+
+prototype.update = function(opt) {
+ opt = opt || {};
+ var v = this,
+ model = this._model,
+ streamer = this._streamer,
+ cs = this._changeset,
+ trans = opt.duration ? new Transition(opt.duration, opt.ease) : null;
+
+ if (trans) cs.trans = trans;
+ if (opt.props !== undefined) {
+ if (dl.keys(cs.data).length > 0) {
+ throw Error(
+ 'New data values are not reflected in the visualization.' +
+ ' Please call view.update() before updating a specified property set.'
+ );
+ }
+
+ cs.reflow = true;
+ cs.request = opt.props;
+ }
+
+ var built = v._build;
+ v._build = v._build || build.call(this);
+
+ // If specific items are specified, short-circuit dataflow graph.
+ // Else-If there are streaming updates, perform a targeted propagation.
+ // Otherwise, re-evaluate the entire model (datasources + scene).
+ if (opt.items && built) {
+ Encoder.update(model, opt.trans, opt.props, opt.items, cs.dirty);
+ v._renderNode.evaluate(cs);
+ } else if (streamer.listeners().length && built) {
+ // Include re-evaluation entire model when repaint flag is set
+ if (this._repaint) streamer.addListener(model.node());
+ model.propagate(cs, streamer, null, this._skipSignals);
+ streamer.disconnect();
+ } else {
+ model.fire(cs);
+ }
+
+ v._changeset = df.ChangeSet.create();
+
+ return v.autopad(opt);
+};
+
+prototype.toImageURL = function(type) {
+ var v = this, Renderer;
+
+ // lookup appropriate renderer
+ switch (type || 'png') {
+ case 'canvas':
+ case 'png':
+ Renderer = sg.canvas.Renderer; break;
+ case 'svg':
+ Renderer = sg.svg.string.Renderer; break;
+ default: throw Error('Unrecognized renderer type: ' + type);
+ }
+
+ var retina = sg.canvas.Renderer.RETINA;
+ sg.canvas.Renderer.RETINA = false; // ignore retina screen
+
+ // render the scenegraph
+ var ren = new Renderer(v._model.config.load)
+ .initialize(null, v._width, v._height, v._padding)
+ .background(v._bgcolor)
+ .render(v._model.scene());
+
+ sg.canvas.Renderer.RETINA = retina; // restore retina settings
+
+ // return data url
+ if (type === 'svg') {
+ var blob = new Blob([ren.svg()], {type: 'image/svg+xml'});
+ return window.URL.createObjectURL(blob);
+ } else {
+ return ren.canvas().toDataURL('image/png');
+ }
+};
+
+prototype.render = function(items) {
+ this._renderer.render(this._model.scene(), items);
+ return this;
+};
+
+prototype.on = function() {
+ this._handler.on.apply(this._handler, arguments);
+ return this;
+};
+
+prototype.onSignal = function(name, handler) {
+ var sg = this._model.signal(name);
+ return (sg ?
+ sg.on(handler) : log.error('Signal "'+name+'" is not defined.'), this);
+};
+
+prototype.off = function() {
+ this._handler.off.apply(this._handler, arguments);
+ return this;
+};
+
+prototype.offSignal = function(name, handler) {
+ var sg = this._model.signal(name);
+ return (sg ?
+ sg.off(handler) : log.error('Signal "'+name+'" is not defined.'), this);
+};
+
+View.factory = function(model) {
+ var HeadlessView = require('./HeadlessView');
+ return function(opt) {
+ opt = opt || {};
+ var defs = model.defs();
+ var v = (opt.el ? new View() : new HeadlessView())
+ .model(model)
+ .renderer(opt.renderer || 'canvas')
+ .width(defs.width)
+ .height(defs.height)
+ .background(defs.background)
+ .padding(defs.padding)
+ .viewport(defs.viewport)
+ .initialize(opt.el);
+
+ if (opt.data) v.data(opt.data);
+
+ // Register handlers for the hover propset and cursors.
+ if (opt.el) {
+ if (opt.hover !== false) {
+ v.on('mouseover', function(evt, item) {
+ if (item && item.hasPropertySet('hover')) {
+ this.update({props:'hover', items:item});
+ }
+ })
+ .on('mouseout', function(evt, item) {
+ if (item && item.hasPropertySet('hover')) {
+ this.update({props:'update', items:item});
+ }
+ });
+ }
+
+ if (opt.cursor !== false) {
+ // If value is a string, it is a custom value set by the user.
+ // In this case, the user is responsible for maintaining the cursor state
+ // and control only reverts back to this handler if set back to 'default'.
+ v.onSignal('cursor', function(name, value) {
+ var body = d3.select('body');
+ if (dl.isString(value)) {
+ v._cursor = value === 'default';
+ body.style('cursor', value);
+ } else if (dl.isObject(value) && v._cursor) {
+ body.style('cursor', value.default);
+ }
+ });
+ }
+ }
+
+ return v;
+ };
+};
+
+module.exports = View;
+}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+
+},{"../parse/streams":107,"../scene/Encoder":111,"../scene/Transition":114,"./HeadlessView":88,"datalib":26,"vega-dataflow":41,"vega-logging":48,"vega-scenegraph":49}],91:[function(require,module,exports){
+(function (global){
+var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null),
+ config = {};
+
+config.load = {
+ // base url for loading external data files
+ // used only for server-side operation
+ baseURL: '',
+ // Allows domain restriction when using data loading via XHR.
+ // To enable, set it to a list of allowed domains
+ // e.g., ['wikipedia.org', 'eff.org']
+ domainWhiteList: false
+};
+
+// inset padding for automatic padding calculation
+config.autopadInset = 5;
+
+// extensible scale lookup table
+// all d3.scale.* instances also supported
+config.scale = {
+ time: d3.time.scale,
+ utc: d3.time.scale.utc
+};
+
+// default rendering settings
+config.render = {
+ retina: true
+};
+
+// root scenegraph group
+config.scene = {
+ fill: undefined,
+ fillOpacity: undefined,
+ stroke: undefined,
+ strokeOpacity: undefined,
+ strokeWidth: undefined,
+ strokeDash: undefined,
+ strokeDashOffset: undefined
+};
+
+// default axis properties
+config.axis = {
+ orient: 'bottom',
+ ticks: 10,
+ padding: 3,
+ axisColor: '#000',
+ axisWidth: 1,
+ gridColor: '#000',
+ gridOpacity: 0.15,
+ tickColor: '#000',
+ tickLabelColor: '#000',
+ tickWidth: 1,
+ tickSize: 6,
+ tickLabelFontSize: 11,
+ tickLabelFont: 'sans-serif',
+ titleColor: '#000',
+ titleFont: 'sans-serif',
+ titleFontSize: 11,
+ titleFontWeight: 'bold',
+ titleOffset: 'auto',
+ titleOffsetAutoMin: 30,
+ titleOffsetAutoMax: Infinity,
+ titleOffsetAutoMargin: 4
+};
+
+// default legend properties
+config.legend = {
+ orient: 'right',
+ offset: 20,
+ padding: 3, // padding between legend items and border
+ margin: 2, // extra margin between two consecutive legends
+ gradientStrokeColor: '#888',
+ gradientStrokeWidth: 1,
+ gradientHeight: 16,
+ gradientWidth: 100,
+ labelColor: '#000',
+ labelFontSize: 10,
+ labelFont: 'sans-serif',
+ labelAlign: 'left',
+ labelBaseline: 'middle',
+ labelOffset: 8,
+ symbolShape: 'circle',
+ symbolSize: 50,
+ symbolColor: '#888',
+ symbolStrokeWidth: 1,
+ titleColor: '#000',
+ titleFont: 'sans-serif',
+ titleFontSize: 11,
+ titleFontWeight: 'bold'
+};
+
+// default color values
+config.color = {
+ rgb: [128, 128, 128],
+ lab: [50, 0, 0],
+ hcl: [0, 0, 50],
+ hsl: [0, 0, 0.5]
+};
+
+// default scale ranges
+config.range = {
+ category10: d3.scale.category10().range(),
+ category20: d3.scale.category20().range(),
+ category20b: d3.scale.category20b().range(),
+ category20c: d3.scale.category20c().range(),
+ shapes: [
+ 'circle',
+ 'cross',
+ 'diamond',
+ 'square',
+ 'triangle-down',
+ 'triangle-up'
+ ]
+};
+
+module.exports = config;
+}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+
+},{}],92:[function(require,module,exports){
+var dl = require('datalib'),
+ parse = require('../parse'),
+ Scale = require('../scene/Scale'),
+ config = require('./config');
+
+function compile(module, opt, schema) {
+ var s = module.schema;
+ if (!s) return;
+ if (s.refs) dl.extend(schema.refs, s.refs);
+ if (s.defs) dl.extend(schema.defs, s.defs);
+}
+
+module.exports = function(opt) {
+ var schema = null;
+ opt = opt || {};
+
+ // Compile if we're not loading the schema from a URL.
+ // Load from a URL to extend the existing base schema.
+ if (opt.url) {
+ schema = dl.json(dl.extend({url: opt.url}, config.load));
+ } else {
+ schema = {
+ "$schema": "http://json-schema.org/draft-04/schema#",
+ "title": "Vega Visualization Specification Language",
+ "defs": {},
+ "refs": {},
+ "$ref": "#/defs/spec"
+ };
+
+ dl.keys(parse).forEach(function(k) { compile(parse[k], opt, schema); });
+
+ // Scales aren't in the parser, add schema manually
+ compile(Scale, opt, schema);
+ }
+
+ // Extend schema to support custom mark properties or property sets.
+ if (opt.properties) dl.keys(opt.properties).forEach(function(k) {
+ schema.defs.propset.properties[k] = {"$ref": "#/refs/"+opt.properties[k]+"Value"};
+ });
+
+ if (opt.propertySets) dl.keys(opt.propertySets).forEach(function(k) {
+ schema.defs.mark.properties.properties.properties[k] = {"$ref": "#/defs/propset"};
+ });
+
+ return schema;
+};
+},{"../parse":97,"../scene/Scale":113,"./config":91,"datalib":26}],93:[function(require,module,exports){
+var dl = require('datalib'),
+ axs = require('../scene/axis');
+
+var ORIENT = {
+ "x": "bottom",
+ "y": "left",
+ "top": "top",
+ "bottom": "bottom",
+ "left": "left",
+ "right": "right"
+};
+
+function parseAxes(model, spec, axes, group) {
+ var config = model.config();
+ (spec || []).forEach(function(def, index) {
+ axes[index] = axes[index] || axs(model);
+ parseAxis(config, def, index, axes[index], group);
+ });
+}
+
+function parseAxis(config, def, index, axis, group) {
+ // axis scale
+ if (def.scale !== undefined) {
+ axis.scale(group.scale(def.scale));
+ }
+
+ // axis orientation
+ axis.orient(def.orient || ORIENT[def.type]);
+ // axis offset
+ axis.offset(def.offset || 0);
+ // axis layer
+ axis.layer(def.layer || "front");
+ // axis grid lines
+ axis.grid(def.grid || false);
+ // axis title
+ axis.title(def.title || null);
+ // axis title offset
+ axis.titleOffset(def.titleOffset != null ?
+ def.titleOffset : config.axis.titleOffset);
+ // axis values
+ axis.tickValues(def.values || null);
+ // axis label formatting
+ axis.tickFormat(def.format || null);
+ axis.tickFormatType(def.formatType || null);
+ // axis tick subdivision
+ axis.tickSubdivide(def.subdivide || 0);
+ // axis tick padding
+ axis.tickPadding(def.tickPadding || config.axis.padding);
+
+ // axis tick size(s)
+ var size = [];
+ if (def.tickSize !== undefined) {
+ for (var i=0; i<3; ++i) size.push(def.tickSize);
+ } else {
+ var ts = config.axis.tickSize;
+ size = [ts, ts, ts];
+ }
+ if (def.tickSizeMajor != null) size[0] = def.tickSizeMajor;
+ if (def.tickSizeMinor != null) size[1] = def.tickSizeMinor;
+ if (def.tickSizeEnd != null) size[2] = def.tickSizeEnd;
+ if (size.length) {
+ axis.tickSize.apply(axis, size);
+ }
+
+ // axis tick count
+ axis.tickCount(def.ticks || config.axis.ticks);
+
+ // style properties
+ var p = def.properties;
+ if (p && p.ticks) {
+ axis.majorTickProperties(p.majorTicks ?
+ dl.extend({}, p.ticks, p.majorTicks) : p.ticks);
+ axis.minorTickProperties(p.minorTicks ?
+ dl.extend({}, p.ticks, p.minorTicks) : p.ticks);
+ } else {
+ axis.majorTickProperties(p && p.majorTicks || {});
+ axis.minorTickProperties(p && p.minorTicks || {});
+ }
+ axis.tickLabelProperties(p && p.labels || {});
+ axis.titleProperties(p && p.title || {});
+ axis.gridLineProperties(p && p.grid || {});
+ axis.domainProperties(p && p.axis || {});
+}
+
+module.exports = parseAxes;
+},{"../scene/axis":115,"datalib":26}],94:[function(require,module,exports){
+(function (global){
+var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null);
+
+function parseBg(bg) {
+ // return null if input is null or undefined
+ if (bg == null) return null;
+ // run through d3 rgb to sanity check
+ return d3.rgb(bg) + '';
+}
+
+module.exports = parseBg;
+}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+
+},{}],95:[function(require,module,exports){
+var dl = require('datalib'),
+ log = require('vega-logging'),
+ parseTransforms = require('./transforms'),
+ parseModify = require('./modify');
+
+function parseData(model, spec, callback) {
+ var config = model.config(),
+ count = 0;
+
+ function onError(error, d) {
+ log.error('PARSE DATA FAILED: ' + d.name + ' ' + error);
+ count = -1;
+ callback(error);
+ }
+
+ function onLoad(d) {
+ return function(error, data) {
+ if (error) {
+ onError(error, d);
+ } else if (count > 0) {
+ try {
+ model.data(d.name).values(dl.read(data, d.format));
+ if (--count === 0) callback();
+ } catch (err) {
+ onError(err, d);
+ }
+ }
+ };
+ }
+
+ // process each data set definition
+ (spec || []).forEach(function(d) {
+ if (d.url) {
+ count += 1;
+ dl.load(dl.extend({url: d.url}, config.load), onLoad(d));
+ }
+ try {
+ parseData.datasource(model, d);
+ } catch (err) {
+ onError(err, d);
+ }
+ });
+
+ if (count === 0) setTimeout(callback, 1);
+ return spec;
+}
+
+parseData.datasource = function(model, d) {
+ var transform = (d.transform || []).map(function(t) {
+ return parseTransforms(model, t);
+ }),
+ mod = (d.modify || []).map(function(m) {
+ return parseModify(model, m, d);
+ }),
+ ds = model.data(d.name, mod.concat(transform));
+
+ if (d.values) {
+ ds.values(dl.read(d.values, d.format));
+ } else if (d.source) {
+ // Derived ds will be pulsed by its src rather than the model.
+ ds.source(d.source).addListener(ds);
+ model.removeListener(ds.pipeline()[0]);
+ }
+
+ return ds;
+};
+
+module.exports = parseData;
+},{"./modify":101,"./transforms":108,"datalib":26,"vega-logging":48}],96:[function(require,module,exports){
+var dl = require('datalib'),
+ template = dl.template,
+ expr = require('vega-expression'),
+ args = ['datum', 'event', 'signals'];
+
+var compile = expr.compiler(args, {
+ idWhiteList: args,
+ fieldVar: args[0],
+ globalVar: function(id) {
+ return 'this.sig[' + dl.str(id) + ']._value';
+ },
+ functions: function(codegen) {
+ var fn = expr.functions(codegen);
+ fn.eventItem = 'event.vg.getItem';
+ fn.eventGroup = 'event.vg.getGroup';
+ fn.eventX = 'event.vg.getX';
+ fn.eventY = 'event.vg.getY';
+ fn.open = 'window.open';
+ fn.scale = scaleGen(codegen, false);
+ fn.iscale = scaleGen(codegen, true);
+ fn.inrange = 'this.defs.inrange';
+ fn.indata = indataGen(codegen);
+ fn.format = 'this.defs.format';
+ fn.timeFormat = 'this.defs.timeFormat';
+ fn.utcFormat = 'this.defs.utcFormat';
+ return fn;
+ },
+ functionDefs: function(/*codegen*/) {
+ return {
+ 'scale': scale,
+ 'inrange': inrange,
+ 'indata': indata,
+ 'format': numberFormat,
+ 'timeFormat': timeFormat,
+ 'utcFormat': utcFormat
+ };
+ }
+});
+
+function scaleGen(codegen, invert) {
+ return function(args) {
+ args = args.map(codegen);
+ var n = args.length;
+ if (n < 2 || n > 3) {
+ throw Error("scale takes exactly 2 or 3 arguments.");
+ }
+ return 'this.defs.scale(this.model, ' + invert + ', ' +
+ args[0] + ',' + args[1] + (n > 2 ? ',' + args[2] : '') + ')';
+ };
+}
+
+function scale(model, invert, name, value, scope) {
+ if (!scope || !scope.scale) {
+ scope = (scope && scope.mark) ? scope.mark.group : model.scene().items[0];
+ }
+ // Verify scope is valid
+ if (model.group(scope._id) !== scope) {
+ throw Error('Scope for scale "'+name+'" is not a valid group item.');
+ }
+ var s = scope.scale(name);
+ return !s ? value : (invert ? s.invert(value) : s(value));
+}
+
+function inrange(val, a, b, exclusive) {
+ var min = a, max = b;
+ if (a > b) { min = b; max = a; }
+ return exclusive ?
+ (min < val && max > val) :
+ (min <= val && max >= val);
+}
+
+function indataGen(codegen) {
+ return function(args, globals, fields, dataSources) {
+ var data;
+ if (args.length !== 3) {
+ throw Error("indata takes 3 arguments.");
+ }
+ if (args[0].type !== 'Literal') {
+ throw Error("Data source name must be a literal for indata.");
+ }
+
+ data = args[0].value;
+ dataSources[data] = 1;
+ if (args[2].type === 'Literal') {
+ indataGen.model.requestIndex(data, args[2].value);
+ }
+
+ args = args.map(codegen);
+ return 'this.defs.indata(this.model,' +
+ args[0] + ',' + args[1] + ',' + args[2] + ')';
+ };
+}
+
+function indata(model, dataname, val, field) {
+ var data = model.data(dataname),
+ index = data.getIndex(field);
+ return index[val] > 0;
+}
+
+function numberFormat(specifier, v) {
+ return template.format(specifier, 'number')(v);
+}
+
+function timeFormat(specifier, d) {
+ return template.format(specifier, 'time')(d);
+}
+
+function utcFormat(specifier, d) {
+ return template.format(specifier, 'utc')(d);
+}
+
+function wrap(model) {
+ return function(str) {
+ indataGen.model = model;
+ var x = compile(str);
+ x.model = model;
+ x.sig = model ? model._signals : {};
+ return x;
+ };
+}
+
+wrap.scale = scale;
+wrap.codegen = compile.codegen;
+module.exports = wrap;
+},{"datalib":26,"vega-expression":46}],97:[function(require,module,exports){
+module.exports = {
+ axes: require('./axes'),
+ background: require('./background'),
+ data: require('./data'),
+ events: require('vega-event-selector'),
+ expr: require('./expr'),
+ legends: require('./legends'),
+ mark: require('./mark'),
+ marks: require('./marks'),
+ modify: require('./modify'),
+ padding: require('./padding'),
+ predicates: require('./predicates'),
+ properties: require('./properties'),
+ signals: require('./signals'),
+ spec: require('./spec'),
+ streams: require('./streams'),
+ transforms: require('./transforms')
+};
+},{"./axes":93,"./background":94,"./data":95,"./expr":96,"./legends":98,"./mark":99,"./marks":100,"./modify":101,"./padding":102,"./predicates":103,"./properties":104,"./signals":105,"./spec":106,"./streams":107,"./transforms":108,"vega-event-selector":42}],98:[function(require,module,exports){
+var lgnd = require('../scene/legend');
+
+function parseLegends(model, spec, legends, group) {
+ (spec || []).forEach(function(def, index) {
+ legends[index] = legends[index] || lgnd(model);
+ parseLegend(def, index, legends[index], group);
+ });
+}
+
+function parseLegend(def, index, legend, group) {
+ // legend scales
+ legend.size (def.size ? group.scale(def.size) : null);
+ legend.shape (def.shape ? group.scale(def.shape) : null);
+ legend.fill (def.fill ? group.scale(def.fill) : null);
+ legend.stroke(def.stroke ? group.scale(def.stroke) : null);
+
+ // legend orientation
+ if (def.orient) legend.orient(def.orient);
+
+ // legend offset
+ if (def.offset != null) legend.offset(def.offset);
+
+ // legend title
+ legend.title(def.title || null);
+
+ // legend values
+ legend.values(def.values || null);
+
+ // legend label formatting
+ legend.format(def.format !== undefined ? def.format : null);
+ legend.formatType(def.formatType || null);
+
+ // style properties
+ var p = def.properties;
+ legend.titleProperties(p && p.title || {});
+ legend.labelProperties(p && p.labels || {});
+ legend.legendProperties(p && p.legend || {});
+ legend.symbolProperties(p && p.symbols || {});
+ legend.gradientProperties(p && p.gradient || {});
+}
+
+module.exports = parseLegends;
+},{"../scene/legend":116}],99:[function(require,module,exports){
+var dl = require('datalib'),
+ parseProperties = require('./properties');
+
+function parseMark(model, mark) {
+ var props = mark.properties,
+ group = mark.marks;
+
+ // parse mark property definitions
+ dl.keys(props).forEach(function(k) {
+ props[k] = parseProperties(model, mark.type, props[k]);
+ });
+
+ // parse delay function
+ if (mark.delay) {
+ mark.delay = parseProperties(model, mark.type, {delay: mark.delay});
+ }
+
+ // recurse if group type
+ if (group) {
+ mark.marks = group.map(function(g) { return parseMark(model, g); });
+ }
+
+ return mark;
+}
+
+module.exports = parseMark;
+},{"./properties":104,"datalib":26}],100:[function(require,module,exports){
+var parseMark = require('./mark'),
+ parseProperties = require('./properties');
+
+function parseRootMark(model, spec, width, height) {
+ return {
+ type: 'group',
+ width: width,
+ height: height,
+ properties: defaults(spec.scene || {}, model),
+ scales: spec.scales || [],
+ axes: spec.axes || [],
+ legends: spec.legends || [],
+ marks: (spec.marks || []).map(function(m) { return parseMark(model, m); })
+ };
+}
+
+var PROPERTIES = [
+ 'fill', 'fillOpacity', 'stroke', 'strokeOpacity',
+ 'strokeWidth', 'strokeDash', 'strokeDashOffset'
+];
+
+function defaults(spec, model) {
+ var config = model.config().scene,
+ props = {}, i, n, m, p, s;
+
+ for (i=0, n=m=PROPERTIES.length; i= 0; --i) {
+ for (j=0; j': parseComparator,
+ '>=': parseComparator,
+ '<': parseComparator,
+ '<=': parseComparator,
+ 'and': parseLogical,
+ '&&': parseLogical,
+ 'or': parseLogical,
+ '||': parseLogical,
+ 'in': parseIn
+};
+
+var nullScale = function() { return 0; };
+nullScale.invert = nullScale;
+
+function parsePredicates(model, spec) {
+ (spec || []).forEach(function(s) {
+ var parse = types[s.type](model, s);
+
+ /* jshint evil:true */
+ var pred = Function("args", "db", "signals", "predicates", parse.code);
+ pred.root = function() { return model.scene().items[0]; }; // For global scales
+ pred.nullScale = nullScale;
+ pred.isFunction = dl.isFunction;
+ pred.signals = parse.signals;
+ pred.data = parse.data;
+
+ model.predicate(s.name, pred);
+ });
+
+ return spec;
+}
+
+function parseSignal(signal, signals) {
+ var s = dl.field(signal),
+ code = "signals["+s.map(dl.str).join("][")+"]";
+ signals[s[0]] = 1;
+ return code;
+}
+
+function parseOperands(model, operands) {
+ var decl = [], defs = [],
+ signals = {}, db = {};
+
+ function setSignal(s) { signals[s] = 1; }
+ function setData(d) { db[d] = 1; }
+
+ dl.array(operands).forEach(function(o, i) {
+ var name = "o" + i,
+ def = "";
+
+ if (o.value !== undefined) {
+ def = dl.str(o.value);
+ } else if (o.arg) {
+ def = "args["+dl.str(o.arg)+"]";
+ } else if (o.signal) {
+ def = parseSignal(o.signal, signals);
+ } else if (o.predicate) {
+ var ref = o.predicate,
+ predName = ref && (ref.name || ref),
+ pred = model.predicate(predName),
+ p = "predicates["+dl.str(predName)+"]";
+
+ pred.signals.forEach(setSignal);
+ pred.data.forEach(setData);
+
+ if (dl.isObject(ref)) {
+ dl.keys(ref).forEach(function(k) {
+ if (k === "name") return;
+ var i = ref[k];
+ def += "args["+dl.str(k)+"] = ";
+ if (i.signal) {
+ def += parseSignal(i.signal, signals);
+ } else if (i.arg) {
+ def += "args["+dl.str(i.arg)+"]";
+ }
+ def += ", ";
+ });
+ }
+
+ def += p+".call("+p+", args, db, signals, predicates)";
+ }
+
+ decl.push(name);
+ defs.push(name+"=("+def+")");
+ });
+
+ return {
+ code: "var " + decl.join(", ") + ";\n" + defs.join(";\n") + ";\n",
+ signals: dl.keys(signals),
+ data: dl.keys(db)
+ };
+}
+
+function parseComparator(model, spec) {
+ var ops = parseOperands(model, spec.operands);
+ if (spec.type === '=') spec.type = '==';
+
+ ops.code += "o0 = o0 instanceof Date ? o0.getTime() : o0;\n" +
+ "o1 = o1 instanceof Date ? o1.getTime() : o1;\n";
+
+ return {
+ code: ops.code + "return " + ["o0", "o1"].join(spec.type) + ";",
+ signals: ops.signals,
+ data: ops.data
+ };
+}
+
+function parseLogical(model, spec) {
+ var ops = parseOperands(model, spec.operands),
+ o = [], i = 0, len = spec.operands.length;
+
+ while (o.push("o"+i++) < len);
+ if (spec.type === 'and') spec.type = '&&';
+ else if (spec.type === 'or') spec.type = '||';
+
+ return {
+ code: ops.code + "return " + o.join(spec.type) + ";",
+ signals: ops.signals,
+ data: ops.data
+ };
+}
+
+function parseIn(model, spec) {
+ var o = [spec.item], code = "";
+ if (spec.range) o.push.apply(o, spec.range);
+ if (spec.scale) {
+ code = parseScale(spec.scale, o);
+ }
+
+ var ops = parseOperands(model, o);
+ code = ops.code + code + "\n var ordSet = null;\n";
+
+ if (spec.data) {
+ var field = dl.field(spec.field).map(dl.str);
+ code += "var where = function(d) { return d["+field.join("][")+"] == o0 };\n";
+ code += "return db["+dl.str(spec.data)+"].filter(where).length > 0;";
+ } else if (spec.range) {
+ // TODO: inclusive/exclusive range?
+ if (spec.scale) {
+ code += "if (scale.length == 2) {\n" + // inverting ordinal scales
+ " ordSet = scale(o1, o2);\n" +
+ "} else {\n" +
+ " o1 = scale(o1);\no2 = scale(o2);\n" +
+ "}";
+ }
+
+ code += "return ordSet !== null ? ordSet.indexOf(o0) !== -1 :\n" +
+ " o1 < o2 ? o1 <= o0 && o0 <= o2 : o2 <= o0 && o0 <= o1;";
+ }
+
+ return {
+ code: code,
+ signals: ops.signals,
+ data: ops.data.concat(spec.data ? [spec.data] : [])
+ };
+}
+
+// Populate ops such that ultimate scale/inversion function will be in `scale` var.
+function parseScale(spec, ops) {
+ var code = "var scale = ",
+ idx = ops.length;
+
+ if (dl.isString(spec)) {
+ ops.push({ value: spec });
+ code += "this.root().scale(o"+idx+")";
+ } else if (spec.arg) { // Scale function is being passed as an arg
+ ops.push(spec);
+ code += "o"+idx;
+ } else if (spec.name) { // Full scale parameter {name: ..}
+ ops.push(dl.isString(spec.name) ? {value: spec.name} : spec.name);
+ code += "(this.isFunction(o"+idx+") ? o"+idx+" : ";
+ if (spec.scope) {
+ ops.push(spec.scope);
+ code += "((o"+(idx+1)+".scale || this.root().scale)(o"+idx+") || this.nullScale)";
+ } else {
+ code += "this.root().scale(o"+idx+")";
+ }
+ code += ")";
+ }
+
+ if (spec.invert === true) { // Allow spec.invert.arg?
+ code += ".invert";
+ }
+
+ return code+";\n";
+}
+
+module.exports = parsePredicates;
+},{"datalib":26}],104:[function(require,module,exports){
+(function (global){
+var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null),
+ dl = require('datalib'),
+ log = require('vega-logging'),
+ Tuple = require('vega-dataflow').Tuple;
+
+var DEPS = ["signals", "scales", "data", "fields"];
+
+function properties(model, mark, spec) {
+ var config = model.config(),
+ code = "",
+ names = dl.keys(spec),
+ exprs = [], // parsed expressions injected in the generated code
+ i, len, name, ref, vars = {},
+ deps = {
+ signals: {},
+ scales: {},
+ data: {},
+ fields: {},
+ nested: [],
+ _nRefs: {}, // Temp stash to de-dupe nested refs.
+ reflow: false
+ };
+
+ code += "var o = trans ? {} : item, d=0, exprs=this.exprs, set=this.tpl.set, tmpl=signals||{}, t;\n" +
+ // Stash for dl.template
+ "tmpl.datum = item.datum;\n" +
+ "tmpl.group = group;\n" +
+ "tmpl.parent = group.datum;\n";
+
+ function handleDep(p) {
+ if (ref[p] == null) return;
+ var k = dl.array(ref[p]), i, n;
+ for (i=0, n=k.length; i 0) ? "\n " : " ";
+ if (ref.rule) {
+ // a production rule valueref
+ ref = rule(model, name, ref.rule, exprs);
+ code += "\n " + ref.code;
+ } else if (dl.isArray(ref)) {
+ // a production rule valueref as an array
+ ref = rule(model, name, ref, exprs);
+ code += "\n " + ref.code;
+ } else {
+ // a simple valueref
+ ref = valueRef(config, name, ref);
+ code += "d += set(o, "+dl.str(name)+", "+ref.val+");";
+ }
+
+ vars[name] = true;
+ DEPS.forEach(handleDep);
+ deps.reflow = deps.reflow || ref.reflow;
+ if (ref.nested.length) ref.nested.forEach(handleNestedRefs);
+ }
+
+ // If nested references are present, sort them based on their level
+ // to speed up determination of whether encoders should be reeval'd.
+ dl.keys(deps._nRefs).forEach(function(k) { deps.nested.push(deps._nRefs[k]); });
+ deps.nested.sort(function(a, b) {
+ a = a.level;
+ b = b.level;
+ return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
+ });
+
+ if (vars.x2) {
+ if (vars.x) {
+ code += "\n if (o.x > o.x2) { " +
+ "\n t = o.x;" +
+ "\n d += set(o, 'x', o.x2);" +
+ "\n d += set(o, 'x2', t); " +
+ "\n };";
+ code += "\n d += set(o, 'width', (o.x2 - o.x));";
+ } else if (vars.width) {
+ code += "\n d += set(o, 'x', (o.x2 - o.width));";
+ } else {
+ code += "\n d += set(o, 'x', o.x2);";
+ }
+ }
+
+ if (vars.xc) {
+ if (vars.width) {
+ code += "\n d += set(o, 'x', (o.xc - o.width/2));" ;
+ } else {
+ code += "\n d += set(o, 'x', o.xc);" ;
+ }
+ }
+
+ if (vars.y2) {
+ if (vars.y) {
+ code += "\n if (o.y > o.y2) { " +
+ "\n t = o.y;" +
+ "\n d += set(o, 'y', o.y2);" +
+ "\n d += set(o, 'y2', t);" +
+ "\n };";
+ code += "\n d += set(o, 'height', (o.y2 - o.y));";
+ } else if (vars.height) {
+ code += "\n d += set(o, 'y', (o.y2 - o.height));";
+ } else {
+ code += "\n d += set(o, 'y', o.y2);";
+ }
+ }
+
+ if (vars.yc) {
+ if (vars.height) {
+ code += "\n d += set(o, 'y', (o.yc - o.height/2));" ;
+ } else {
+ code += "\n d += set(o, 'y', o.yc);" ;
+ }
+ }
+
+ if (hasPath(mark, vars)) code += "\n d += (item.touch(), 1);";
+ code += "\n if (trans) trans.interpolate(item, o);";
+ code += "\n return d > 0;";
+
+ try {
+ /* jshint evil:true */
+ var encoder = Function('item', 'group', 'trans', 'db',
+ 'signals', 'predicates', code);
+
+ encoder.tpl = Tuple;
+ encoder.exprs = exprs;
+ encoder.util = dl;
+ encoder.d3 = d3; // For color spaces
+ dl.extend(encoder, dl.template.context);
+ return {
+ encode: encoder,
+ signals: dl.keys(deps.signals),
+ scales: dl.keys(deps.scales),
+ data: dl.keys(deps.data),
+ fields: dl.keys(deps.fields),
+ nested: deps.nested,
+ reflow: deps.reflow
+ };
+ } catch (e) {
+ log.error(e);
+ log.log(code);
+ }
+}
+
+function dependencies(a, b) {
+ if (!dl.isObject(a)) {
+ a = {reflow: false, nested: []};
+ DEPS.forEach(function(d) { a[d] = []; });
+ }
+
+ if (dl.isObject(b)) {
+ a.reflow = a.reflow || b.reflow;
+ a.nested.push.apply(a.nested, b.nested);
+ DEPS.forEach(function(d) { a[d].push.apply(a[d], b[d]); });
+ }
+
+ return a;
+}
+
+function hasPath(mark, vars) {
+ return vars.path ||
+ ((mark==='area' || mark==='line') &&
+ (vars.x || vars.x2 || vars.width ||
+ vars.y || vars.y2 || vars.height ||
+ vars.tension || vars.interpolate));
+}
+
+function rule(model, name, rules, exprs) {
+ var config = model.config(),
+ deps = dependencies(),
+ inputs = [],
+ code = '';
+
+ (rules||[]).forEach(function(r, i) {
+ var ref = valueRef(config, name, r);
+ dependencies(deps, ref);
+
+ if (r.test) {
+ // rule uses an expression instead of a predicate.
+ var exprFn = model.expr(r.test);
+ deps.signals.push.apply(deps.signals, exprFn.globals);
+ deps.data.push.apply(deps.data, exprFn.dataSources);
+
+ code += "if (exprs[" + exprs.length + "](item.datum, null)) {" +
+ "\n d += set(o, "+dl.str(name)+", " +ref.val+");";
+ code += rules[i+1] ? "\n } else " : " }";
+
+ exprs.push(exprFn.fn);
+ } else {
+ var def = r.predicate,
+ predName = def && (def.name || def),
+ pred = model.predicate(predName),
+ p = 'predicates['+dl.str(predName)+']',
+ input = [], args = name+'_arg'+i;
+
+ if (dl.isObject(def)) {
+ dl.keys(def).forEach(function(k) {
+ if (k === 'name') return;
+ var ref = valueRef(config, i, def[k], true);
+ input.push(dl.str(k)+': '+ref.val);
+ dependencies(deps, ref);
+ });
+ }
+
+ if (predName) {
+ // append the predicates dependencies to our dependencies
+ deps.signals.push.apply(deps.signals, pred.signals);
+ deps.data.push.apply(deps.data, pred.data);
+ inputs.push(args+" = {\n "+input.join(",\n ")+"\n }");
+ code += "if ("+p+".call("+p+","+args+", db, signals, predicates)) {" +
+ "\n d += set(o, "+dl.str(name)+", "+ref.val+");";
+ code += rules[i+1] ? "\n } else " : " }";
+ } else {
+ code += "{" +
+ "\n d += set(o, "+dl.str(name)+", "+ref.val+");"+
+ "\n }\n";
+ }
+ }
+ });
+
+ if (inputs.length) code = "var " + inputs.join(",\n ") + ";\n " + code;
+ return (deps.code = code, deps);
+}
+
+function valueRef(config, name, ref, predicateArg) {
+ if (ref == null) return null;
+
+ if (name==='fill' || name==='stroke') {
+ if (ref.c) {
+ return colorRef(config, 'hcl', ref.h, ref.c, ref.l);
+ } else if (ref.h || ref.s) {
+ return colorRef(config, 'hsl', ref.h, ref.s, ref.l);
+ } else if (ref.l || ref.a) {
+ return colorRef(config, 'lab', ref.l, ref.a, ref.b);
+ } else if (ref.r || ref.g || ref.b) {
+ return colorRef(config, 'rgb', ref.r, ref.g, ref.b);
+ }
+ }
+
+ // initialize value
+ var val = null, scale = null,
+ deps = dependencies(),
+ sgRef = null, fRef = null, sRef = null, tmpl = {};
+
+ if (ref.template !== undefined) {
+ val = dl.template.source(ref.template, 'tmpl', tmpl);
+ dl.keys(tmpl).forEach(function(k) {
+ var f = dl.field(k),
+ a = f.shift();
+ if (a === 'parent' || a === 'group') {
+ deps.nested.push({
+ parent: a === 'parent',
+ group: a === 'group',
+ level: 1
+ });
+ } else if (a === 'datum') {
+ deps.fields.push(f[0]);
+ } else {
+ deps.signals.push(a);
+ }
+ });
+ }
+
+ if (ref.value !== undefined) {
+ val = dl.str(ref.value);
+ }
+
+ if (ref.signal !== undefined) {
+ sgRef = dl.field(ref.signal);
+ val = 'signals['+sgRef.map(dl.str).join('][')+']';
+ deps.signals.push(sgRef.shift());
+ }
+
+ if (ref.field !== undefined) {
+ ref.field = dl.isString(ref.field) ? {datum: ref.field} : ref.field;
+ fRef = fieldRef(ref.field);
+ val = fRef.val;
+ dependencies(deps, fRef);
+ }
+
+ if (ref.scale !== undefined) {
+ sRef = scaleRef(ref.scale);
+ scale = sRef.val;
+ dependencies(deps, sRef);
+ deps.scales.push(ref.scale.name || ref.scale);
+
+ // run through scale function if val specified.
+ // if no val, scale function is predicate arg.
+ if (val !== null || ref.band || ref.mult || ref.offset || !predicateArg) {
+ val = scale + (ref.band ? '.rangeBand()' :
+ '('+(val !== null ? val : 'item.datum.data')+')');
+ } else if (predicateArg) {
+ val = scale;
+ }
+ }
+
+ // multiply, offset, return value
+ val = '(' + (ref.mult?(dl.number(ref.mult)+' * '):'') + val + ')' +
+ (ref.offset ? ' + ' + dl.number(ref.offset) : '');
+
+ // Collate dependencies
+ return (deps.val = val, deps);
+}
+
+function colorRef(config, type, x, y, z) {
+ var xx = x ? valueRef(config, '', x) : config.color[type][0],
+ yy = y ? valueRef(config, '', y) : config.color[type][1],
+ zz = z ? valueRef(config, '', z) : config.color[type][2],
+ deps = dependencies();
+
+ [xx, yy, zz].forEach(function(v) {
+ if (dl.isArray) return;
+ dependencies(deps, v);
+ });
+
+ var val = '(this.d3.' + type + '(' + [xx.val, yy.val, zz.val].join(',') + ') + "")';
+ return (deps.val = val, deps);
+}
+
+// {field: {datum: "foo"} } -> item.datum.foo
+// {field: {group: "foo"} } -> group.foo
+// {field: {parent: "foo"} } -> group.datum.foo
+function fieldRef(ref) {
+ if (dl.isString(ref)) {
+ return {val: dl.field(ref).map(dl.str).join('][')};
+ }
+
+ // Resolve nesting/parent lookups
+ var l = ref.level || 1,
+ nested = (ref.group || ref.parent) && l,
+ scope = nested ? Array(l).join('group.mark.') : '',
+ r = fieldRef(ref.datum || ref.group || ref.parent || ref.signal),
+ val = r.val,
+ deps = dependencies(null, r);
+
+ if (ref.datum) {
+ val = 'item.datum['+val+']';
+ deps.fields.push(ref.datum);
+ } else if (ref.group) {
+ val = scope+'group['+val+']';
+ deps.nested.push({ level: l, group: true });
+ } else if (ref.parent) {
+ val = scope+'group.datum['+val+']';
+ deps.nested.push({ level: l, parent: true });
+ } else if (ref.signal) {
+ val = 'signals['+val+']';
+ deps.signals.push(dl.field(ref.signal)[0]);
+ deps.reflow = true;
+ }
+
+ return (deps.val = val, deps);
+}
+
+// {scale: "x"}
+// {scale: {name: "x"}},
+// {scale: fieldRef}
+function scaleRef(ref) {
+ var scale = null,
+ fr = null,
+ deps = dependencies();
+
+ if (dl.isString(ref)) {
+ scale = dl.str(ref);
+ } else if (ref.name) {
+ scale = dl.isString(ref.name) ? dl.str(ref.name) : (fr = fieldRef(ref.name)).val;
+ } else {
+ scale = (fr = fieldRef(ref)).val;
+ }
+
+ scale = '(item.mark._scaleRefs['+scale+'] = 1, group.scale('+scale+'))';
+ if (ref.invert) scale += '.invert';
+
+ // Mark scale refs as they're dealt with separately in mark._scaleRefs.
+ if (fr) fr.nested.forEach(function(g) { g.scale = true; });
+ return fr ? (fr.val = scale, fr) : (deps.val = scale, deps);
+}
+
+module.exports = properties;
+}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+
+},{"datalib":26,"vega-dataflow":41,"vega-logging":48}],105:[function(require,module,exports){
+var dl = require('datalib'),
+ expr = require('./expr'),
+ SIGNALS = require('vega-dataflow').Dependencies.SIGNALS;
+
+var RESERVED = ['datum', 'event', 'signals', 'width', 'height', 'padding']
+ .concat(dl.keys(expr.codegen.functions));
+
+function parseSignals(model, spec) {
+ // process each signal definition
+ (spec || []).forEach(function(s) {
+ if (RESERVED.indexOf(s.name) !== -1) {
+ throw Error('Signal name "'+s.name+'" is a '+
+ 'reserved keyword ('+RESERVED.join(', ')+').');
+ }
+
+ var signal = model.signal(s.name, s.init)
+ .verbose(s.verbose);
+
+ if (s.init && s.init.expr) {
+ s.init.expr = model.expr(s.init.expr);
+ signal.value(exprVal(model, s.init));
+ }
+
+ if (s.expr) {
+ s.expr = model.expr(s.expr);
+ signal.evaluate = function(input) {
+ var val = exprVal(model, s),
+ sg = input.signals;
+ if (val !== signal.value() || signal.verbose()) {
+ signal.value(val);
+ sg[s.name] = 1;
+ }
+ return sg[s.name] ? input : model.doNotPropagate;
+ };
+ signal.dependency(SIGNALS, s.expr.globals);
+ s.expr.globals.forEach(function(dep) {
+ model.signal(dep).addListener(signal);
+ });
+ }
+ });
+
+ return spec;
+}
+
+function exprVal(model, spec) {
+ var e = spec.expr, v = e.fn();
+ return spec.scale ? parseSignals.scale(model, spec, v) : v;
+}
+
+parseSignals.scale = function scale(model, spec, value, datum, evt) {
+ var def = spec.scale,
+ name = def.name || def.signal || def,
+ scope = def.scope, e;
+
+ if (scope) {
+ if (scope.signal) {
+ scope = model.signalRef(scope.signal);
+ } else if (dl.isString(scope)) { // Scope is an expression
+ e = def._expr = (def._expr || model.expr(scope));
+ scope = e.fn(datum, evt);
+ }
+ }
+
+ return expr.scale(model, def.invert, name, value, scope);
+};
+
+module.exports = parseSignals;
+},{"./expr":96,"datalib":26,"vega-dataflow":41}],106:[function(require,module,exports){
+var dl = require('datalib'),
+ log = require('vega-logging'),
+ Model = require('../core/Model'),
+ View = require('../core/View');
+
+/**
+ * Parse graph specification
+ * @param spec (object)
+ * @param config (optional object)
+ * @param viewFactory (optional function)
+ * @param callback (error, model)
+ */
+ function parseSpec(spec /*, [config,] [viewFactory,] callback */) {
+ // do not assign any values to callback, as it will change arguments
+ var arglen = arguments.length,
+ argidx = 2,
+ cb = arguments[arglen-1],
+ model = new Model(),
+ viewFactory = View.factory;
+
+ if (arglen > argidx && dl.isFunction(arguments[arglen - argidx])) {
+ viewFactory = arguments[arglen - argidx];
+ ++argidx;
+ }
+ if (arglen > argidx && dl.isObject(arguments[arglen - argidx])) {
+ model.config(arguments[arglen - argidx]);
+ }
+
+ if (dl.isObject(spec)) {
+ parse(spec);
+ } else if (dl.isString(spec)) {
+ var opts = dl.extend({url: spec}, model.config().load);
+ dl.json(opts, function(err, spec) {
+ if (err) done('SPECIFICATION LOAD FAILED: ' + err);
+ else parse(spec);
+ });
+ } else {
+ done('INVALID SPECIFICATION: Must be a valid JSON object or URL.');
+ }
+
+ function parse(spec) {
+ try {
+ // protect against subsequent spec modification
+ spec = dl.duplicate(spec);
+
+ var parsers = require('./'),
+ width = spec.width || 500,
+ height = spec.height || 500,
+ padding = parsers.padding(spec.padding);
+
+ // create signals for width, height, padding, and cursor
+ model.signal('width', width);
+ model.signal('height', height);
+ model.signal('padding', padding);
+ cursor(spec);
+
+ // initialize model
+ model.defs({
+ width: width,
+ height: height,
+ padding: padding,
+ viewport: spec.viewport || null,
+ background: parsers.background(spec.background),
+ signals: parsers.signals(model, spec.signals),
+ predicates: parsers.predicates(model, spec.predicates),
+ marks: parsers.marks(model, spec, width, height),
+ data: parsers.data(model, spec.data, done)
+ });
+ } catch (err) { done(err); }
+ }
+
+ function cursor(spec) {
+ var signals = spec.signals || (spec.signals=[]), def;
+ signals.some(function(sg) {
+ return (sg.name === 'cursor') ? (def=sg, true) : false;
+ });
+
+ if (!def) signals.push(def={name: 'cursor', streams: []});
+
+ // Add a stream def at the head, so that custom defs can override it.
+ def.init = def.init || {};
+ def.streams.unshift({
+ type: 'mousemove',
+ expr: 'eventItem().cursor === cursor.default ? cursor : {default: eventItem().cursor}'
+ });
+ }
+
+ function done(err) {
+ var view;
+ if (err) {
+ log.error(err);
+ } else {
+ view = viewFactory(model.buildIndexes());
+ }
+
+ if (cb) {
+ if (cb.length > 1) cb(err, view);
+ else if (!err) cb(view);
+ cb = null;
+ }
+ }
+}
+
+module.exports = parseSpec;
+},{"../core/Model":89,"../core/View":90,"./":97,"datalib":26,"vega-logging":48}],107:[function(require,module,exports){
+(function (global){
+var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null),
+ dl = require('datalib'),
+ df = require('vega-dataflow'),
+ selector = require('vega-event-selector'),
+ parseSignals = require('./signals');
+
+var GATEKEEPER = '_vgGATEKEEPER',
+ EVALUATOR = '_vgEVALUATOR';
+
+var vgEvent = {
+ getItem: function() { return this.item; },
+ getGroup: function(name) { return name ? this.name[name] : this.group; },
+ getXY: function(item) {
+ var p = {x: this.x, y: this.y};
+ if (typeof item === 'string') {
+ item = this.name[item];
+ }
+ for (; item; item = item.mark && item.mark.group) {
+ p.x -= item.x || 0;
+ p.y -= item.y || 0;
+ }
+ return p;
+ },
+ getX: function(item) { return this.getXY(item).x; },
+ getY: function(item) { return this.getXY(item).y; }
+};
+
+function parseStreams(view) {
+ var model = view.model(),
+ trueFn = model.expr('true'),
+ falseFn = model.expr('false'),
+ spec = model.defs().signals,
+ registry = {handlers: {}, nodes: {}},
+ internal = dl.duplicate(registry), // Internal event processing
+ external = dl.duplicate(registry); // External event processing
+
+ dl.array(spec).forEach(function(sig) {
+ var signal = model.signal(sig.name);
+ if (sig.expr) return; // Cannot have an expr and stream definition.
+
+ dl.array(sig.streams).forEach(function(stream) {
+ var sel = selector.parse(stream.type),
+ exp = model.expr(stream.expr);
+ mergedStream(signal, sel, exp, stream);
+ });
+ });
+
+ // We register the event listeners all together so that if multiple
+ // signals are registered on the same event, they will receive the
+ // new value on the same pulse.
+ dl.keys(internal.handlers).forEach(function(type) {
+ view.on(type, function(evt, item) {
+ evt.preventDefault(); // stop text selection
+ extendEvent(evt, item);
+ fire(internal, type, (item && item.datum) || {}, evt);
+ });
+ });
+
+ // add external event listeners
+ dl.keys(external.handlers).forEach(function(type) {
+ if (typeof window === 'undefined') return; // No external support
+
+ var h = external.handlers[type],
+ t = type.split(':'), // --> no element pseudo-selectors
+ elt = (t[0] === 'window') ? [window] :
+ window.document.querySelectorAll(t[0]);
+
+ function handler(evt) {
+ extendEvent(evt);
+ fire(external, type, d3.select(this).datum(), evt);
+ }
+
+ for (var i=0; i 0,
+ bounds = mark.bounds,
+ rebound = !bounds || input.rem.length,
+ i, ilen, j, jlen, group, legend;
+
+ if (type === 'line' || type === 'area') {
+ bound.mark(mark, null, isGrp && !hasLegends);
+ } else {
+ input.add.forEach(function(item) {
+ bound.item(item);
+ rebound = rebound || (bounds && !bounds.encloses(item.bounds));
+ });
+
+ input.mod.forEach(function(item) {
+ rebound = rebound || (bounds && bounds.alignsWith(item.bounds));
+ bound.item(item);
+ });
+
+ if (rebound) {
+ bounds = mark.bounds && mark.bounds.clear() || (mark.bounds = new Bounds());
+ for (i=0, ilen=items.length; i this._stamp) {
+ join.call(this, fcs, output, this._ds.values(), true, fullUpdate);
+ } else if (fullUpdate) {
+ output.mod = this._mark.items.slice();
+ }
+ } else {
+ data = dl.isFunction(this._def.from) ? this._def.from() : [Sentinel];
+ join.call(this, input, output, data);
+ }
+
+ // Stash output before Bounder for downstream reactive geometry.
+ this._output = output = this._graph.evaluate(output, this._encoder);
+
+ // Add any new scale references to the dependency list, and ensure
+ // they're connected.
+ if (update.nested && update.nested.length && this._status === CONNECTED) {
+ dl.keys(this._mark._scaleRefs).forEach(function(s) {
+ var scale = self._parent.scale(s);
+ if (!scale) return;
+
+ scale.addListener(self);
+ self.dependency(Deps.SCALES, s);
+ self._encoder.dependency(Deps.SCALES, s);
+ });
+ }
+
+ // Supernodes calculate bounds too, but only on items marked dirty.
+ if (this._isSuper) {
+ output.mod = output.mod.filter(function(x) { return x._dirty; });
+ output = this._graph.evaluate(output, this._bounder);
+ }
+
+ return output;
+};
+
+function newItem() {
+ var item = Tuple.ingest(new Item(this._mark));
+
+ // For the root node's item
+ if (this._def.width) Tuple.set(item, 'width', this._def.width);
+ if (this._def.height) Tuple.set(item, 'height', this._def.height);
+ return item;
+}
+
+function join(input, output, data, ds, fullUpdate) {
+ var keyf = keyFunction(this._def.key || (ds ? '_id' : null)),
+ prev = this._mark.items || [],
+ rem = ds ? input.rem : prev,
+ mod = Tuple.idMap((!ds || fullUpdate) ? data : input.mod),
+ next = [],
+ i, key, len, item, datum, enter, diff;
+
+ // Only mark rems as exiting. Due to keyf, there may be an add/mod
+ // tuple that replaces it.
+ for (i=0, len=rem.length; i0) s += '|';
+ s += String(f[i](d));
+ }
+ return s;
+ };
+}
+
+module.exports = Builder;
+},{"../parse/data":95,"./Bounder":109,"./Encoder":111,"datalib":26,"vega-dataflow":41,"vega-logging":48,"vega-scenegraph":49}],111:[function(require,module,exports){
+var dl = require('datalib'),
+ log = require('vega-logging'),
+ df = require('vega-dataflow'),
+ Node = df.Node, // jshint ignore:line
+ Deps = df.Dependencies,
+ bound = require('vega-scenegraph').bound;
+
+var EMPTY = {};
+
+function Encoder(graph, mark, builder) {
+ var props = mark.def.properties || {},
+ enter = props.enter,
+ update = props.update,
+ exit = props.exit;
+
+ Node.prototype.init.call(this, graph);
+
+ this._mark = mark;
+ this._builder = builder;
+ var s = this._scales = [];
+
+ // Only scales used in the 'update' property set are set as
+ // encoder depedencies to have targeted reevaluations. However,
+ // we still want scales in 'enter' and 'exit' to be evaluated
+ // before the encoder.
+ if (enter) s.push.apply(s, enter.scales);
+
+ if (update) {
+ this.dependency(Deps.DATA, update.data);
+ this.dependency(Deps.SIGNALS, update.signals);
+ this.dependency(Deps.FIELDS, update.fields);
+ this.dependency(Deps.SCALES, update.scales);
+ s.push.apply(s, update.scales);
+ }
+
+ if (exit) s.push.apply(s, exit.scales);
+
+ return this.mutates(true);
+}
+
+var proto = (Encoder.prototype = new Node());
+
+proto.evaluate = function(input) {
+ log.debug(input, ['encoding', this._mark.def.type]);
+ var graph = this._graph,
+ props = this._mark.def.properties || {},
+ items = this._mark.items,
+ enter = props.enter,
+ update = props.update,
+ exit = props.exit,
+ dirty = input.dirty,
+ preds = graph.predicates(),
+ req = input.request,
+ group = this._mark.group,
+ guide = group && (group.mark.axis || group.mark.legend),
+ db = EMPTY, sg = EMPTY, i, len, item, prop;
+
+ if (req && !guide) {
+ if ((prop = props[req]) && input.mod.length) {
+ db = prop.data ? graph.values(Deps.DATA, prop.data) : null;
+ sg = prop.signals ? graph.values(Deps.SIGNALS, prop.signals) : null;
+
+ for (i=0, len=input.mod.length; i this._stamp) return true;
+ }
+
+ return false;
+}
+
+// Short-circuit encoder if user specifies items
+Encoder.update = function(graph, trans, request, items, dirty) {
+ items = dl.array(items);
+ var preds = graph.predicates(),
+ db = graph.values(Deps.DATA),
+ sg = graph.values(Deps.SIGNALS),
+ i, len, item, props, prop;
+
+ for (i=0, len=items.length; i 0,
+ hasAxes = dl.array(this._def.axes).length > 0,
+ hasLegends = dl.array(this._def.legends).length > 0,
+ i, j, c, len, group, pipeline, def, inline = false;
+
+ for (i=0, len=input.add.length; i=0; --i) {
+ group = input.add[i];
+ for (j=this._children[group._id].length-1; j>=0; --j) {
+ c = this._children[group._id][j];
+ c.builder.connect();
+ pipeline = c.builder.pipeline();
+ def = c.builder._def;
+
+ // This new child needs to be built during this propagation cycle.
+ // We could add its builder as a listener off the _recursor node,
+ // but try to inline it if we can to minimize graph dispatches.
+ inline = (def.type !== Types.GROUP);
+ inline = inline && (this._graph.data(c.from) !== undefined);
+ inline = inline && (pipeline[pipeline.length-1].listeners().length === 1); // Reactive geom source
+ inline = inline && (def.from && !def.from.mark); // Reactive geom target
+ c.inline = inline;
+
+ if (inline) this._graph.evaluate(input, c.builder);
+ else this._recursor.addListener(c.builder);
+ }
+ }
+
+ function removeTemp(c) {
+ if (c.type == Types.MARK && !c.inline &&
+ builder._graph.data(c.from) !== undefined) {
+ builder._recursor.removeListener(c.builder);
+ }
+ }
+
+ function updateAxis(a) {
+ var scale = a.scale();
+ if (!input.scales[scale.scaleName]) return;
+ a.reset().def();
+ }
+
+ function updateLegend(l) {
+ var scale = l.size() || l.shape() || l.fill() || l.stroke();
+ if (!input.scales[scale.scaleName]) return;
+ l.reset().def();
+ }
+
+ for (i=0, len=input.mod.length; i rng[1]) {
+ start = rng[1] || 0;
+ rng = [start + (bw * len + space), start];
+ } else {
+ start = rng[0] || 0;
+ rng = [start, start + (bw * len + space)];
+ }
+
+ if (def.reverse) rng = rng.reverse();
+ }
+
+ str = typeof rng[0] === 'string';
+ if (str || rng.length > 2 || rng.length===1 || dataDrivenRange) {
+ scale.range(rng); // color or shape values
+ spatial = false;
+ } else if (points && round) {
+ scale.rangeRoundPoints(rng, pad);
+ } else if (points) {
+ scale.rangePoints(rng, pad);
+ } else if (round) {
+ scale.rangeRoundBands(rng, pad, outer);
+ } else {
+ scale.rangeBands(rng, pad, outer);
+ }
+
+ prev.range = rng;
+ this._updated = true;
+ }
+
+ if (!scale.invert && spatial) invertOrdinal(scale);
+}
+
+// "Polyfill" ordinal scale inversion. Currently, only ordinal scales
+// with ordered numeric ranges are supported.
+var bisect = d3.bisector(dl.numcmp).right,
+ findAsc = function(a, x) { return bisect(a,x) - 1; },
+ findDsc = d3.bisector(function(a,b) { return -1 * dl.numcmp(a,b); }).left;
+
+function invertOrdinal(scale) {
+ scale.invert = function(x, y) {
+ var rng = scale.range(),
+ asc = rng[0] < rng[1],
+ find = asc ? findAsc : findDsc;
+
+ if (arguments.length === 1) {
+ if (!dl.isNumber(x)) {
+ throw Error('Ordinal scale inversion is only supported for numeric input ('+x+').');
+ }
+ return scale.domain()[find(rng, x)];
+
+ } else if (arguments.length === 2) { // Invert extents
+ if (!dl.isNumber(x) || !dl.isNumber(y)) {
+ throw Error('Extents to ordinal invert are not numbers ('+x+', '+y+').');
+ }
+
+ var domain = scale.domain(),
+ a = find(rng, x),
+ b = find(rng, y),
+ n = rng.length - 1, r;
+ if (b < a) { r = a; a = b; b = a; } // ensure a <= b
+ if (a < 0) a = 0;
+ if (b > n) b = n;
+
+ return (asc ? dl.range(a, b+1) : dl.range(b, a-1, -1))
+ .map(function(i) { return domain[i]; });
+ }
+ };
+}
+
+function quantitative(scale, rng, group) {
+ var def = this._def,
+ prev = scale._prev,
+ round = signal.call(this, def.round),
+ exponent = signal.call(this, def.exponent),
+ clamp = signal.call(this, def.clamp),
+ nice = signal.call(this, def.nice),
+ domain, interval;
+
+ // domain
+ domain = (def.type === Types.QUANTILE) ?
+ dataRef.call(this, DataRef.DOMAIN, def.domain, scale, group) :
+ domainMinMax.call(this, scale, group);
+ if (domain && !dl.equal(prev.domain, domain)) {
+ scale.domain(domain);
+ prev.domain = domain;
+ this._updated = true;
+ }
+
+ // range
+ // vertical scales should flip by default, so use XOR here
+ if (signal.call(this, def.range) === 'height') rng = rng.reverse();
+ if (rng && !dl.equal(prev.range, rng)) {
+ scale[round && scale.rangeRound ? 'rangeRound' : 'range'](rng);
+ prev.range = rng;
+ this._updated = true;
+ }
+
+ if (exponent && def.type===Types.POWER) scale.exponent(exponent);
+ if (clamp) scale.clamp(true);
+ if (nice) {
+ if (def.type === Types.TIME) {
+ interval = d3.time[nice];
+ if (!interval) log.error('Unrecognized interval: ' + interval);
+ scale.nice(interval);
+ } else {
+ scale.nice();
+ }
+ }
+}
+
+function isUniques(scale) {
+ return scale.type === Types.ORDINAL || scale.type === Types.QUANTILE;
+}
+
+function getRefs(def) {
+ return def.fields || dl.array(def);
+}
+
+function inherits(refs) {
+ return refs.some(function(r) {
+ if (!r.data) return true;
+ return r.data && dl.array(r.field).some(function(f) {
+ return f.parent;
+ });
+ });
+}
+
+function getFields(ref, group) {
+ return dl.array(ref.field).map(function(f) {
+ return f.parent ?
+ dl.accessor(f.parent)(group.datum) :
+ f; // String or {'signal'}
+ });
+}
+
+// Scale datarefs can be computed over multiple schema types.
+// This function determines the type of aggregator created, and
+// what data is sent to it: values, tuples, or multi-tuples that must
+// be standardized into a consistent schema.
+function aggrType(def, scale) {
+ var refs = getRefs(def);
+
+ // If we're operating over only a single domain, send full tuples
+ // through for efficiency (fewer accessor creations/calls)
+ if (refs.length == 1 && dl.array(refs[0].field).length == 1) {
+ return Aggregate.TYPES.TUPLE;
+ }
+
+ // With quantitative scales, we only care about min/max.
+ if (!isUniques(scale)) return Aggregate.TYPES.VALUE;
+
+ // If we don't sort, then we can send values directly to aggrs as well
+ if (!dl.isObject(def.sort)) return Aggregate.TYPES.VALUE;
+
+ return Aggregate.TYPES.MULTI;
+}
+
+function getCache(which, def, scale, group) {
+ var refs = getRefs(def),
+ inherit = inherits(refs),
+ atype = aggrType(def, scale),
+ uniques = isUniques(scale),
+ sort = def.sort,
+ ck = '_'+which,
+ fields = getFields(refs[0], group);
+
+ if (scale[ck] || this[ck]) return scale[ck] || this[ck];
+
+ var cache = new Aggregate(this._graph).type(atype),
+ groupby, summarize;
+
+ // If a scale's dataref doesn't inherit data from the group, we can
+ // store the dataref aggregator at the Scale (dataflow node) level.
+ if (inherit) {
+ scale[ck] = cache;
+ } else {
+ this[ck] = cache;
+ }
+
+ if (uniques) {
+ if (atype === Aggregate.TYPES.VALUE) {
+ groupby = [{ name: DataRef.GROUPBY, get: dl.identity }];
+ summarize = {'*': DataRef.COUNT};
+ } else if (atype === Aggregate.TYPES.TUPLE) {
+ groupby = [{ name: DataRef.GROUPBY, get: dl.$(fields[0]) }];
+ summarize = dl.isObject(sort) ? [{
+ field: DataRef.VALUE,
+ get: dl.$(sort.field),
+ ops: [sort.op]
+ }] : {'*': DataRef.COUNT};
+ } else { // atype === Aggregate.TYPES.MULTI
+ groupby = DataRef.GROUPBY;
+ summarize = [{ field: DataRef.VALUE, ops: [sort.op] }];
+ }
+ } else {
+ groupby = [];
+ summarize = [{
+ field: DataRef.VALUE,
+ get: (atype == Aggregate.TYPES.TUPLE) ? dl.$(fields[0]) : dl.identity,
+ ops: [DataRef.MIN, DataRef.MAX],
+ as: [DataRef.MIN, DataRef.MAX]
+ }];
+ }
+
+ cache.param('groupby', groupby)
+ .param('summarize', summarize);
+
+ return (cache._lastUpdate = -1, cache);
+}
+
+function dataRef(which, def, scale, group) {
+ if (def == null) { return []; }
+ if (dl.isArray(def)) return def.map(signal.bind(this));
+
+ var self = this, graph = this._graph,
+ refs = getRefs(def),
+ inherit = inherits(refs),
+ atype = aggrType(def, scale),
+ cache = getCache.apply(this, arguments),
+ sort = def.sort,
+ uniques = isUniques(scale),
+ i, rlen, j, flen, ref, fields, field, data, from, cmp;
+
+ function addDep(s) {
+ self.dependency(Deps.SIGNALS, s);
+ }
+
+ if (inherit || (!inherit && cache._lastUpdate < this._stamp)) {
+ for (i=0, rlen=refs.length; i 1) f = 1;
+ e = curr.ease(f);
+
+ for (i=0, n=curr.length; i 1 ? +y : tickMajorSize,
+ end = n > 0 ? +arguments[n] : tickMajorSize;
+
+ if (tickMajorSize !== major ||
+ tickMinorSize !== minor ||
+ tickEndSize !== end) {
+ reset();
+ }
+
+ tickMajorSize = major;
+ tickMinorSize = minor;
+ tickEndSize = end;
+ return axis;
+ };
+
+ axis.tickSubdivide = function(x) {
+ if (!arguments.length) return tickSubdivide;
+ tickSubdivide = +x;
+ return axis;
+ };
+
+ axis.offset = function(x) {
+ if (!arguments.length) return offset;
+ offset = dl.isObject(x) ? x : +x;
+ return axis;
+ };
+
+ axis.tickPadding = function(x) {
+ if (!arguments.length) return tickPadding;
+ if (tickPadding !== +x) { tickPadding = +x; reset(); }
+ return axis;
+ };
+
+ axis.titleOffset = function(x) {
+ if (!arguments.length) return titleOffset;
+ if (titleOffset !== x) { titleOffset = x; reset(); }
+ return axis;
+ };
+
+ axis.layer = function(x) {
+ if (!arguments.length) return layer;
+ if (layer !== x) { layer = x; reset(); }
+ return axis;
+ };
+
+ axis.grid = function(x) {
+ if (!arguments.length) return grid;
+ if (grid !== x) { grid = x; reset(); }
+ return axis;
+ };
+
+ axis.gridLineProperties = function(x) {
+ if (!arguments.length) return gridLineStyle;
+ if (gridLineStyle !== x) { gridLineStyle = x; }
+ return axis;
+ };
+
+ axis.majorTickProperties = function(x) {
+ if (!arguments.length) return majorTickStyle;
+ if (majorTickStyle !== x) { majorTickStyle = x; }
+ return axis;
+ };
+
+ axis.minorTickProperties = function(x) {
+ if (!arguments.length) return minorTickStyle;
+ if (minorTickStyle !== x) { minorTickStyle = x; }
+ return axis;
+ };
+
+ axis.tickLabelProperties = function(x) {
+ if (!arguments.length) return tickLabelStyle;
+ if (tickLabelStyle !== x) { tickLabelStyle = x; }
+ return axis;
+ };
+
+ axis.titleProperties = function(x) {
+ if (!arguments.length) return titleStyle;
+ if (titleStyle !== x) { titleStyle = x; }
+ return axis;
+ };
+
+ axis.domainProperties = function(x) {
+ if (!arguments.length) return domainStyle;
+ if (domainStyle !== x) { domainStyle = x; }
+ return axis;
+ };
+
+ axis.reset = function() {
+ reset();
+ return axis;
+ };
+
+ return axis;
+}
+
+var axisOrients = {top: 1, right: 1, bottom: 1, left: 1};
+
+function axisSubdivide(scale, ticks, m) {
+ var subticks = [];
+ if (m && ticks.length > 1) {
+ var extent = axisScaleExtent(scale.domain()),
+ i = -1,
+ n = ticks.length,
+ d = (ticks[1] - ticks[0]) / ++m,
+ j,
+ v;
+ while (++i < n) {
+ for (j = m; --j > 0;) {
+ if ((v = +ticks[i] - j * d) >= extent[0]) {
+ subticks.push(v);
+ }
+ }
+ }
+ for (--i, j = 0; ++j < m && (v = +ticks[i] + j * d) < extent[1];) {
+ subticks.push(v);
+ }
+ }
+ return subticks;
+}
+
+function axisScaleExtent(domain) {
+ var start = domain[0], stop = domain[domain.length - 1];
+ return start < stop ? [start, stop] : [stop, start];
+}
+
+function axisScaleRange(scale) {
+ return scale.rangeExtent ?
+ scale.rangeExtent() :
+ axisScaleExtent(scale.range());
+}
+
+var axisAlign = {
+ bottom: 'center',
+ top: 'center',
+ left: 'right',
+ right: 'left'
+};
+
+var axisBaseline = {
+ bottom: 'top',
+ top: 'bottom',
+ left: 'middle',
+ right: 'middle'
+};
+
+function axisLabelExtend(orient, labels, oldScale, newScale, size, pad) {
+ size = Math.max(size, 0) + pad;
+ if (orient === 'left' || orient === 'top') {
+ size *= -1;
+ }
+ if (orient === 'top' || orient === 'bottom') {
+ dl.extend(labels.properties.enter, {
+ x: oldScale,
+ y: {value: size},
+ });
+ dl.extend(labels.properties.update, {
+ x: newScale,
+ y: {value: size},
+ align: {value: 'center'},
+ baseline: {value: axisBaseline[orient]}
+ });
+ } else {
+ dl.extend(labels.properties.enter, {
+ x: {value: size},
+ y: oldScale,
+ });
+ dl.extend(labels.properties.update, {
+ x: {value: size},
+ y: newScale,
+ align: {value: axisAlign[orient]},
+ baseline: {value: 'middle'}
+ });
+ }
+}
+
+function axisTicksExtend(orient, ticks, oldScale, newScale, size, offset) {
+ var sign = (orient === 'left' || orient === 'top') ? -1 : 1;
+ if (size === Infinity) {
+ size = (orient === 'top' || orient === 'bottom') ?
+ {field: {group: 'height', level: 2}, mult: -sign, offset: offset*-sign} :
+ {field: {group: 'width', level: 2}, mult: -sign, offset: offset*-sign};
+ } else {
+ size = {value: sign * size, offset: offset};
+ }
+ if (orient === 'top' || orient === 'bottom') {
+ dl.extend(ticks.properties.enter, {
+ x: oldScale,
+ y: {value: 0},
+ y2: size
+ });
+ dl.extend(ticks.properties.update, {
+ x: newScale,
+ y: {value: 0},
+ y2: size
+ });
+ dl.extend(ticks.properties.exit, {
+ x: newScale,
+ });
+ } else {
+ dl.extend(ticks.properties.enter, {
+ x: {value: 0},
+ x2: size,
+ y: oldScale
+ });
+ dl.extend(ticks.properties.update, {
+ x: {value: 0},
+ x2: size,
+ y: newScale
+ });
+ dl.extend(ticks.properties.exit, {
+ y: newScale,
+ });
+ }
+}
+
+function axisTitleExtend(orient, title, range, offset) {
+ var update = title.properties.update,
+ mid = ~~((range[0] + range[1]) / 2),
+ sign = (orient === 'top' || orient === 'left') ? -1 : 1;
+
+ if (orient === 'bottom' || orient === 'top') {
+ update.x = {value: mid};
+ update.angle = {value: 0};
+ if (offset >= 0) update.y = {value: sign * offset};
+ } else {
+ update.y = {value: mid};
+ update.angle = {value: orient === 'left' ? -90 : 90};
+ if (offset >= 0) update.x = {value: sign * offset};
+ }
+}
+
+function axisDomainExtend(orient, domain, range, size) {
+ var path;
+ if (orient === 'top' || orient === 'left') {
+ size = -1 * size;
+ }
+ if (orient === 'bottom' || orient === 'top') {
+ path = 'M' + range[0] + ',' + size + 'V0H' + range[1] + 'V' + size;
+ } else {
+ path = 'M' + size + ',' + range[0] + 'H0V' + range[1] + 'H' + size;
+ }
+ domain.properties.update.path = {value: path};
+}
+
+function axisUpdate(item, group, trans) {
+ var o = trans ? {} : item,
+ offset = item.mark.def.offset,
+ orient = item.mark.def.orient,
+ width = group.width,
+ height = group.height; // TODO fallback to global w,h?
+
+ if (dl.isArray(offset)) {
+ var ofx = offset[0],
+ ofy = offset[1];
+
+ switch (orient) {
+ case 'left': { Tuple.set(o, 'x', -ofx); Tuple.set(o, 'y', ofy); break; }
+ case 'right': { Tuple.set(o, 'x', width + ofx); Tuple.set(o, 'y', ofy); break; }
+ case 'bottom': { Tuple.set(o, 'x', ofx); Tuple.set(o, 'y', height + ofy); break; }
+ case 'top': { Tuple.set(o, 'x', ofx); Tuple.set(o, 'y', -ofy); break; }
+ default: { Tuple.set(o, 'x', ofx); Tuple.set(o, 'y', ofy); }
+ }
+ } else {
+ if (dl.isObject(offset)) {
+ offset = -group.scale(offset.scale)(offset.value);
+ }
+
+ switch (orient) {
+ case 'left': { Tuple.set(o, 'x', -offset); Tuple.set(o, 'y', 0); break; }
+ case 'right': { Tuple.set(o, 'x', width + offset); Tuple.set(o, 'y', 0); break; }
+ case 'bottom': { Tuple.set(o, 'x', 0); Tuple.set(o, 'y', height + offset); break; }
+ case 'top': { Tuple.set(o, 'x', 0); Tuple.set(o, 'y', -offset); break; }
+ default: { Tuple.set(o, 'x', 0); Tuple.set(o, 'y', 0); }
+ }
+ }
+
+ if (trans) trans.interpolate(item, o);
+ return true;
+}
+
+function axisTicks(config) {
+ return {
+ type: 'rule',
+ interactive: false,
+ key: 'data',
+ properties: {
+ enter: {
+ stroke: {value: config.tickColor},
+ strokeWidth: {value: config.tickWidth},
+ opacity: {value: 1e-6}
+ },
+ exit: { opacity: {value: 1e-6} },
+ update: { opacity: {value: 1} }
+ }
+ };
+}
+
+function axisTickLabels(config) {
+ return {
+ type: 'text',
+ interactive: true,
+ key: 'data',
+ properties: {
+ enter: {
+ fill: {value: config.tickLabelColor},
+ font: {value: config.tickLabelFont},
+ fontSize: {value: config.tickLabelFontSize},
+ opacity: {value: 1e-6},
+ text: {field: 'label'}
+ },
+ exit: { opacity: {value: 1e-6} },
+ update: { opacity: {value: 1} }
+ }
+ };
+}
+
+function axisTitle(config) {
+ return {
+ type: 'text',
+ interactive: true,
+ properties: {
+ enter: {
+ font: {value: config.titleFont},
+ fontSize: {value: config.titleFontSize},
+ fontWeight: {value: config.titleFontWeight},
+ fill: {value: config.titleColor},
+ align: {value: 'center'},
+ baseline: {value: 'middle'},
+ text: {field: 'data'}
+ },
+ update: {}
+ }
+ };
+}
+
+function axisDomain(config) {
+ return {
+ type: 'path',
+ interactive: false,
+ properties: {
+ enter: {
+ x: {value: 0.5},
+ y: {value: 0.5},
+ stroke: {value: config.axisColor},
+ strokeWidth: {value: config.axisWidth}
+ },
+ update: {}
+ }
+ };
+}
+
+module.exports = axs;
+},{"../parse/mark":99,"../util":148,"datalib":26,"vega-dataflow":41,"vega-scenegraph":49}],116:[function(require,module,exports){
+(function (global){
+var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null),
+ dl = require('datalib'),
+ Gradient = require('vega-scenegraph').Gradient,
+ parseProperties = require('../parse/properties'),
+ parseMark = require('../parse/mark'),
+ util = require('../util');
+
+function lgnd(model) {
+ var size = null,
+ shape = null,
+ fill = null,
+ stroke = null,
+ spacing = null,
+ values = null,
+ formatString = null,
+ formatType = null,
+ title = null,
+ config = model.config().legend,
+ orient = config.orient,
+ offset = config.offset,
+ padding = config.padding,
+ tickArguments = [5],
+ legendStyle = {},
+ symbolStyle = {},
+ gradientStyle = {},
+ titleStyle = {},
+ labelStyle = {},
+ m = { // Legend marks as references for updates
+ titles: {},
+ symbols: {},
+ labels: {},
+ gradient: {}
+ };
+
+ var legend = {},
+ legendDef = {};
+
+ function reset() { legendDef.type = null; }
+ function ingest(d, i) { return {data: d, index: i}; }
+
+ legend.def = function() {
+ var scale = size || shape || fill || stroke;
+
+ if (!legendDef.type) {
+ legendDef = (scale===fill || scale===stroke) && !discrete(scale.type) ?
+ quantDef(scale) : ordinalDef(scale);
+ }
+ legendDef.orient = orient;
+ legendDef.offset = offset;
+ legendDef.padding = padding;
+ legendDef.margin = config.margin;
+ return legendDef;
+ };
+
+ function discrete(type) {
+ return type==='ordinal' || type==='quantize' ||
+ type==='quantile' || type==='threshold';
+ }
+
+ function ordinalDef(scale) {
+ var def = o_legend_def(size, shape, fill, stroke);
+
+ // generate data
+ var data = (values == null ?
+ (scale.ticks ? scale.ticks.apply(scale, tickArguments) : scale.domain()) :
+ values).map(ingest);
+
+ var fmt = util.getTickFormat(scale, data.length, formatType, formatString);
+
+ // determine spacing between legend entries
+ var fs, range, offset, pad=5, domain = d3.range(data.length);
+ if (size) {
+ range = data.map(function(x) { return Math.sqrt(size(x.data)); });
+ offset = d3.max(range);
+ range = range.reduce(function(a,b,i,z) {
+ if (i > 0) a[i] = a[i-1] + z[i-1]/2 + pad;
+ return (a[i] += b/2, a); }, [0]).map(Math.round);
+ } else {
+ offset = Math.round(Math.sqrt(config.symbolSize));
+ range = spacing ||
+ (fs = labelStyle.fontSize) && (fs.value + pad) ||
+ (config.labelFontSize + pad);
+ range = domain.map(function(d,i) {
+ return Math.round(offset/2 + i*range);
+ });
+ }
+
+ // account for padding and title size
+ var sz = padding, ts;
+ if (title) {
+ ts = titleStyle.fontSize;
+ sz += 5 + ((ts && ts.value) || config.titleFontSize);
+ }
+ for (var i=0, n=range.length; i'},
+ summarize: {
+ type: 'custom',
+ set: function(summarize) {
+ var signalDeps = {},
+ tx = this._transform,
+ i, len, f, fields, name, ops;
+
+ if (!dl.isArray(fields = summarize)) { // Object syntax from dl
+ fields = [];
+ for (name in summarize) {
+ ops = dl.array(summarize[name]);
+ fields.push({field: name, ops: ops});
+ }
+ }
+
+ function sg(x) { if (x.signal) signalDeps[x.signal] = 1; }
+
+ for (i=0, len=fields.length; i', default: [5, 2]}
+ });
+
+ this._output = {
+ start: 'bin_start',
+ end: 'bin_end',
+ mid: 'bin_mid'
+ };
+ return this.mutates(true);
+}
+
+var prototype = (Bin.prototype = Object.create(BatchTransform.prototype));
+prototype.constructor = Bin;
+
+prototype.extent = function(data) {
+ // TODO only recompute extent upon data or field change?
+ var e = [this.param('min'), this.param('max')], d;
+ if (e[0] == null || e[1] == null) {
+ d = dl.extent(data, this.param('field').accessor);
+ if (e[0] == null) e[0] = d[0];
+ if (e[1] == null) e[1] = d[1];
+ }
+ return e;
+};
+
+prototype.batchTransform = function(input, data) {
+ log.debug(input, ['binning']);
+
+ var extent = this.extent(data),
+ output = this._output,
+ step = this.param('step'),
+ steps = this.param('steps'),
+ minstep = this.param('minstep'),
+ get = this.param('field').accessor,
+ opt = {
+ min: extent[0],
+ max: extent[1],
+ base: this.param('base'),
+ maxbins: this.param('maxbins'),
+ div: this.param('div')
+ };
+
+ if (step) opt.step = step;
+ if (steps) opt.steps = steps;
+ if (minstep) opt.minstep = minstep;
+ var b = dl.bins(opt),
+ s = b.step;
+
+ function update(d) {
+ var v = get(d);
+ v = v == null ? null
+ : b.start + s * ~~((v - b.start) / s);
+ Tuple.set(d, output.start, v);
+ Tuple.set(d, output.end, v + s);
+ Tuple.set(d, output.mid, v + s/2);
+ }
+ input.add.forEach(update);
+ input.mod.forEach(update);
+ input.rem.forEach(update);
+
+ input.fields[output.start] = 1;
+ input.fields[output.end] = 1;
+ input.fields[output.mid] = 1;
+ return input;
+};
+
+module.exports = Bin;
+},{"./BatchTransform":119,"./Transform":140,"datalib":26,"vega-dataflow":41,"vega-logging":48}],121:[function(require,module,exports){
+var df = require('vega-dataflow'),
+ Tuple = df.Tuple,
+ log = require('vega-logging'),
+ Transform = require('./Transform');
+
+function CountPattern(graph) {
+ Transform.prototype.init.call(this, graph);
+ Transform.addParameters(this, {
+ field: {type: 'field', default: 'data'},
+ pattern: {type: 'value', default: '[\\w\']+'},
+ case: {type: 'value', default: 'lower'},
+ stopwords: {type: 'value', default: ''}
+ });
+
+ this._output = {text: 'text', count: 'count'};
+
+ return this.router(true).produces(true);
+}
+
+var prototype = (CountPattern.prototype = Object.create(Transform.prototype));
+prototype.constructor = CountPattern;
+
+prototype.transform = function(input, reset) {
+ log.debug(input, ['countpattern']);
+
+ var get = this.param('field').accessor,
+ pattern = this.param('pattern'),
+ stop = this.param('stopwords'),
+ rem = false;
+
+ // update parameters
+ if (this._stop !== stop) {
+ this._stop = stop;
+ this._stop_re = new RegExp('^' + stop + '$', 'i');
+ reset = true;
+ }
+
+ if (this._pattern !== pattern) {
+ this._pattern = pattern;
+ this._match = new RegExp(this._pattern, 'g');
+ reset = true;
+ }
+
+ if (reset) this._counts = {};
+
+ function curr(t) { return (Tuple.prev_init(t), get(t)); }
+ function prev(t) { return get(Tuple.prev(t)); }
+
+ this._add(input.add, curr);
+ if (!reset) this._rem(input.rem, prev);
+ if (reset || (rem = input.fields[get.field])) {
+ if (rem) this._rem(input.mod, prev);
+ this._add(input.mod, curr);
+ }
+
+ // generate output tuples
+ return this._changeset(input);
+};
+
+prototype._changeset = function(input) {
+ var counts = this._counts,
+ tuples = this._tuples || (this._tuples = {}),
+ change = df.ChangeSet.create(input),
+ out = this._output, w, t, c;
+
+ for (w in counts) {
+ t = tuples[w];
+ c = counts[w] || 0;
+ if (!t && c) {
+ tuples[w] = (t = Tuple.ingest({}));
+ t[out.text] = w;
+ t[out.count] = c;
+ change.add.push(t);
+ } else if (c === 0) {
+ if (t) change.rem.push(t);
+ delete counts[w];
+ delete tuples[w];
+ } else if (t[out.count] !== c) {
+ Tuple.set(t, out.count, c);
+ change.mod.push(t);
+ }
+ }
+ return change;
+};
+
+prototype._tokenize = function(text) {
+ switch (this.param('case')) {
+ case 'upper': text = text.toUpperCase(); break;
+ case 'lower': text = text.toLowerCase(); break;
+ }
+ return text.match(this._match);
+};
+
+prototype._add = function(tuples, get) {
+ var counts = this._counts,
+ stop = this._stop_re,
+ tok, i, j, t;
+
+ for (j=0; j=0; --i) {
+ t = tpls[i];
+ l = x === t[as.left]; // Cache has tpls w/x both on left & right.
+ y = l ? t[as.right] : t[as.left];
+ cid = _cid(l, x, y);
+
+ // Lazy removal: y was previously rem'd, so clean up the cache.
+ if (!cache[y._id]) {
+ cids[cid] = false;
+ tpls.splice(i, 1);
+ continue;
+ }
+
+ if (!test || test(t)) {
+ if (mids[t._id]) continue;
+ omod.push(t);
+ mids[t._id] = 1;
+ } else {
+ if (!rids[t._id]) orem.push.apply(orem, tpls.splice(i, 1));
+ rids[t._id] = 1;
+ cids[cid] = false;
+ cross.f = true;
+ }
+ }
+ }
+
+ // If we have a filter param, call add to catch any tuples that may
+ // have previously been filtered.
+ if (test && fltrd) add.call(this, output, left, data, diag, test, mids, x);
+}
+
+function rem(output, left, rids, x) {
+ var as = this._output,
+ cross = this._cache[x._id],
+ cids = this._cids,
+ orem = output.rem,
+ i, len, t, y, l;
+ if (!cross) return;
+
+ for (i=0, len=cross.c.length; i this._lastWith) {
+ woutput.rem.forEach(rem.bind(this, output, false, rids));
+ woutput.add.forEach(add.bind(this, output, false, data, diag, test, mids));
+ woutput.mod.forEach(mod.bind(this, output, false, data, diag, test, mids, rids));
+ this._lastWith = woutput.stamp;
+ }
+
+ // Mods need to come after all removals have been run.
+ input.mod.forEach(mod.bind(this, output, true, wdata, diag, test, mids, rids));
+ }
+
+ output.fields[as.left] = 1;
+ output.fields[as.right] = 1;
+ return output;
+};
+
+module.exports = Cross;
+},{"./BatchTransform":119,"./Transform":140,"datalib":26,"vega-dataflow":41,"vega-logging":48}],123:[function(require,module,exports){
+var Transform = require('./Transform'),
+ Aggregate = require('./Aggregate');
+
+function Facet(graph) {
+ Transform.addParameters(this, {
+ transform: {
+ type: "custom",
+ set: function(pipeline) {
+ return (this._transform._pipeline = pipeline, this._transform);
+ },
+ get: function() {
+ var parse = require('../parse/transforms'),
+ facet = this._transform;
+ return facet._pipeline.map(function(t) {
+ return parse(facet._graph, t);
+ });
+ }
+ }
+ });
+
+ this._pipeline = [];
+ return Aggregate.call(this, graph);
+}
+
+var prototype = (Facet.prototype = Object.create(Aggregate.prototype));
+prototype.constructor = Facet;
+
+prototype.aggr = function() {
+ return Aggregate.prototype.aggr.call(this).facet(this);
+};
+
+prototype.transform = function(input, reset) {
+ var output = Aggregate.prototype.transform.call(this, input, reset);
+
+ // New facet cells should trigger a re-ranking of the dataflow graph.
+ // This ensures facet datasources are computed before scenegraph nodes.
+ // We rerank the Facet's first listener, which is the next node in the
+ // datasource's pipeline.
+ if (input.add.length) {
+ this.listeners()[0].rerank();
+ }
+
+ return output;
+};
+
+module.exports = Facet;
+},{"../parse/transforms":108,"./Aggregate":118,"./Transform":140}],124:[function(require,module,exports){
+var dl = require('datalib'),
+ Aggregator = dl.Aggregator,
+ Base = Aggregator.prototype,
+ df = require('vega-dataflow'),
+ Tuple = df.Tuple,
+ log = require('vega-logging'),
+ facetID = 0;
+
+function Facetor() {
+ Aggregator.call(this);
+ this._facet = null;
+ this._facetID = ++facetID;
+}
+
+var prototype = (Facetor.prototype = Object.create(Base));
+prototype.constructor = Facetor;
+
+prototype.facet = function(f) {
+ return arguments.length ? (this._facet = f, this) : this._facet;
+};
+
+prototype._ingest = function(t) {
+ return Tuple.ingest(t, null);
+};
+
+prototype._assign = Tuple.set;
+
+function disconnect_cell(facet) {
+ log.debug({}, ['disconnecting cell', this.tuple._id]);
+ var pipeline = this.ds.pipeline();
+ facet.removeListener(pipeline[0]);
+ facet._graph.removeListener(pipeline[0]);
+ facet._graph.disconnect(pipeline);
+}
+
+prototype._newcell = function(x, key) {
+ var cell = Base._newcell.call(this, x, key),
+ facet = this._facet;
+
+ if (facet) {
+ var graph = facet._graph,
+ tuple = cell.tuple,
+ pipeline = facet.param('transform');
+ cell.ds = graph.data(tuple._facetID, pipeline, tuple);
+ cell.disconnect = disconnect_cell;
+ facet.addListener(pipeline[0]);
+ }
+
+ return cell;
+};
+
+prototype._newtuple = function(x, key) {
+ var t = Base._newtuple.call(this, x);
+ if (this._facet) {
+ Tuple.set(t, 'key', key);
+ Tuple.set(t, '_facetID', this._facetID + '_' + key);
+ }
+ return t;
+};
+
+prototype.clear = function() {
+ if (this._facet) {
+ for (var k in this._cells) {
+ this._cells[k].disconnect(this._facet);
+ }
+ }
+ return Base.clear.call(this);
+};
+
+prototype._on_add = function(x, cell) {
+ if (this._facet) cell.ds._input.add.push(x);
+};
+
+prototype._on_rem = function(x, cell) {
+ if (this._facet) cell.ds._input.rem.push(x);
+};
+
+prototype._on_mod = function(x, prev, cell0, cell1) {
+ if (this._facet) { // Propagate tuples
+ if (cell0 === cell1) {
+ cell0.ds._input.mod.push(x);
+ } else {
+ cell0.ds._input.rem.push(x);
+ cell1.ds._input.add.push(x);
+ }
+ }
+};
+
+prototype._on_drop = function(cell) {
+ if (this._facet) cell.disconnect(this._facet);
+};
+
+prototype._on_keep = function(cell) {
+ // propagate sort, signals, fields, etc.
+ if (this._facet) df.ChangeSet.copy(this._input, cell.ds._input);
+};
+
+module.exports = Facetor;
+},{"datalib":26,"vega-dataflow":41,"vega-logging":48}],125:[function(require,module,exports){
+var df = require('vega-dataflow'),
+ log = require('vega-logging'),
+ Transform = require('./Transform');
+
+function Filter(graph) {
+ Transform.prototype.init.call(this, graph);
+ Transform.addParameters(this, {test: {type: 'expr'}});
+
+ this._skip = {};
+ return this.router(true);
+}
+
+var prototype = (Filter.prototype = Object.create(Transform.prototype));
+prototype.constructor = Filter;
+
+prototype.transform = function(input) {
+ log.debug(input, ['filtering']);
+
+ var output = df.ChangeSet.create(input),
+ skip = this._skip,
+ test = this.param('test');
+
+ input.rem.forEach(function(x) {
+ if (skip[x._id] !== 1) output.rem.push(x);
+ else skip[x._id] = 0;
+ });
+
+ input.add.forEach(function(x) {
+ if (test(x)) output.add.push(x);
+ else skip[x._id] = 1;
+ });
+
+ input.mod.forEach(function(x) {
+ var b = test(x),
+ s = (skip[x._id] === 1);
+ if (b && s) {
+ skip[x._id] = 0;
+ output.add.push(x);
+ } else if (b && !s) {
+ output.mod.push(x);
+ } else if (!b && s) {
+ // do nothing, keep skip true
+ } else { // !b && !s
+ output.rem.push(x);
+ skip[x._id] = 1;
+ }
+ });
+
+ return output;
+};
+
+module.exports = Filter;
+},{"./Transform":140,"vega-dataflow":41,"vega-logging":48}],126:[function(require,module,exports){
+var df = require('vega-dataflow'),
+ Tuple = df.Tuple,
+ log = require('vega-logging'),
+ Transform = require('./Transform');
+
+function Fold(graph) {
+ Transform.prototype.init.call(this, graph);
+ Transform.addParameters(this, {
+ fields: {type: 'array'}
+ });
+
+ this._output = {key: 'key', value: 'value'};
+ this._cache = {};
+
+ return this.router(true).produces(true);
+}
+
+var prototype = (Fold.prototype = Object.create(Transform.prototype));
+prototype.constructor = Fold;
+
+prototype._reset = function(input, output) {
+ for (var id in this._cache) {
+ output.rem.push.apply(output.rem, this._cache[id]);
+ }
+ this._cache = {};
+};
+
+prototype._tuple = function(x, i, len) {
+ var list = this._cache[x._id] || (this._cache[x._id] = Array(len));
+ return list[i] ? Tuple.rederive(x, list[i]) : (list[i] = Tuple.derive(x));
+};
+
+prototype._fn = function(data, on, out) {
+ var i, j, n, m, d, t;
+ for (i=0, n=data.length; i', default: require('./screen').size},
+ bound: {type: 'value', default: true},
+ links: {type: 'data'},
+
+ // TODO: for now force these to be value params only (pun-intended)
+ // Can update to include fields after Parameter refactoring.
+ linkStrength: {type: 'value', default: 1},
+ linkDistance: {type: 'value', default: 20},
+ charge: {type: 'value', default: -30},
+
+ chargeDistance: {type: 'value', default: Infinity},
+ friction: {type: 'value', default: 0.9},
+ theta: {type: 'value', default: 0.8},
+ gravity: {type: 'value', default: 0.1},
+ alpha: {type: 'value', default: 0.1},
+ iterations: {type: 'value', default: 500},
+
+ interactive: {type: 'value', default: this._interactive},
+ active: {type: 'value', default: this._prev},
+ fixed: {type: 'data'}
+ });
+
+ this._output = {
+ 'x': 'layout_x',
+ 'y': 'layout_y'
+ };
+
+ return this.mutates(true);
+}
+
+var prototype = (Force.prototype = Object.create(Transform.prototype));
+prototype.constructor = Force;
+
+prototype.transform = function(nodeInput, reset) {
+ log.debug(nodeInput, ['force']);
+ reset = reset - (nodeInput.signals.active ? 1 : 0);
+
+ // get variables
+ var interactive = this.param('interactive'),
+ linkSource = this.param('links').source,
+ linkInput = linkSource.last(),
+ active = this.param('active'),
+ output = this._output,
+ layout = this._layout,
+ nodes = this._nodes,
+ links = this._links;
+
+ // configure nodes, links and layout
+ if (linkInput.stamp < nodeInput.stamp) linkInput = null;
+ this.configure(nodeInput, linkInput, interactive, reset);
+
+ // run batch layout
+ if (!interactive) {
+ var iterations = this.param('iterations');
+ for (var i=0; i'},
+ translate: {type: 'array', default: require('./screen').center},
+ rotate: {type: 'array'},
+ scale: {type: 'value'},
+ precision: {type: 'value'},
+ clipAngle: {type: 'value'},
+ clipExtent: {type: 'value'}
+};
+
+Geo.d3Projection = function() {
+ var p = this.param('projection'),
+ param = Geo.Parameters,
+ proj, name, value;
+
+ if (p !== this._mode) {
+ this._mode = p;
+ this._projection = d3.geo[p]();
+ }
+ proj = this._projection;
+
+ for (name in param) {
+ if (name === 'projection' || !proj[name]) continue;
+ value = this.param(name);
+ if (value === undefined || (dl.isArray(value) && value.length === 0)) {
+ continue;
+ }
+ if (value !== proj[name]()) {
+ proj[name](value);
+ }
+ }
+
+ return proj;
+};
+
+var prototype = (Geo.prototype = Object.create(Transform.prototype));
+prototype.constructor = Geo;
+
+prototype.transform = function(input) {
+ log.debug(input, ['geo']);
+
+ var output = this._output,
+ lon = this.param('lon').accessor,
+ lat = this.param('lat').accessor,
+ proj = Geo.d3Projection.call(this);
+
+ function set(t) {
+ var ll = [lon(t), lat(t)];
+ var xy = proj(ll) || [null, null];
+ Tuple.set(t, output.x, xy[0]);
+ Tuple.set(t, output.y, xy[1]);
+ }
+
+ input.add.forEach(set);
+ if (this.reevaluate(input)) {
+ input.mod.forEach(set);
+ input.rem.forEach(set);
+ }
+
+ input.fields[output.x] = 1;
+ input.fields[output.y] = 1;
+ return input;
+};
+
+module.exports = Geo;
+}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+
+},{"./Transform":140,"./screen":146,"datalib":26,"vega-dataflow":41,"vega-logging":48}],130:[function(require,module,exports){
+(function (global){
+var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null),
+ dl = require('datalib'),
+ Tuple = require('vega-dataflow').Tuple,
+ log = require('vega-logging'),
+ Geo = require('./Geo'),
+ Transform = require('./Transform');
+
+function GeoPath(graph) {
+ Transform.prototype.init.call(this, graph);
+ Transform.addParameters(this, Geo.Parameters);
+ Transform.addParameters(this, {
+ field: {type: 'field', default: null},
+ });
+
+ this._output = {
+ 'path': 'layout_path'
+ };
+ return this.mutates(true);
+}
+
+var prototype = (GeoPath.prototype = Object.create(Transform.prototype));
+prototype.constructor = GeoPath;
+
+prototype.transform = function(input) {
+ log.debug(input, ['geopath']);
+
+ var output = this._output,
+ geojson = this.param('field').accessor || dl.identity,
+ proj = Geo.d3Projection.call(this),
+ path = d3.geo.path().projection(proj);
+
+ function set(t) {
+ Tuple.set(t, output.path, path(geojson(t)));
+ }
+
+ input.add.forEach(set);
+ if (this.reevaluate(input)) {
+ input.mod.forEach(set);
+ input.rem.forEach(set);
+ }
+
+ input.fields[output.path] = 1;
+ return input;
+};
+
+module.exports = GeoPath;
+}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+
+},{"./Geo":129,"./Transform":140,"datalib":26,"vega-dataflow":41,"vega-logging":48}],131:[function(require,module,exports){
+(function (global){
+var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null),
+ dl = require('datalib'),
+ Tuple = require('vega-dataflow').Tuple,
+ log = require('vega-logging'),
+ Transform = require('./Transform'),
+ BatchTransform = require('./BatchTransform');
+
+function Hierarchy(graph) {
+ BatchTransform.prototype.init.call(this, graph);
+ Transform.addParameters(this, {
+ // hierarchy parameters
+ sort: {type: 'array', default: null},
+ children: {type: 'field', default: 'children'},
+ parent: {type: 'field', default: 'parent'},
+ field: {type: 'value', default: null},
+ // layout parameters
+ mode: {type: 'value', default: 'tidy'}, // tidy, cluster, partition
+ size: {type: 'array', default: require('./screen').size},
+ nodesize: {type: 'array', default: null},
+ orient: {type: 'value', default: 'cartesian'}
+ });
+
+ this._mode = null;
+ this._output = {
+ 'x': 'layout_x',
+ 'y': 'layout_y',
+ 'width': 'layout_width',
+ 'height': 'layout_height',
+ 'depth': 'layout_depth'
+ };
+ return this.mutates(true);
+}
+
+var PARTITION = 'partition';
+
+var SEPARATION = {
+ cartesian: function(a, b) { return (a.parent === b.parent ? 1 : 2); },
+ radial: function(a, b) { return (a.parent === b.parent ? 1 : 2) / a.depth; }
+};
+
+var prototype = (Hierarchy.prototype = Object.create(BatchTransform.prototype));
+prototype.constructor = Hierarchy;
+
+prototype.batchTransform = function(input, data) {
+ log.debug(input, ['hierarchy layout']);
+
+ // get variables
+ var layout = this._layout,
+ output = this._output,
+ mode = this.param('mode'),
+ sort = this.param('sort'),
+ nodesz = this.param('nodesize'),
+ parent = this.param('parent').accessor,
+ root = data.filter(function(d) { return parent(d) === null; })[0];
+
+ if (mode !== this._mode) {
+ this._mode = mode;
+ if (mode === 'tidy') mode = 'tree';
+ layout = (this._layout = d3.layout[mode]());
+ }
+
+ input.fields[output.x] = 1;
+ input.fields[output.y] = 1;
+ input.fields[output.depth] = 1;
+ if (mode === PARTITION) {
+ input.fields[output.width] = 1;
+ input.fields[output.height] = 1;
+ layout.value(this.param('field').accessor);
+ } else {
+ layout.separation(SEPARATION[this.param('orient')]);
+ }
+
+ if (nodesz.length && mode !== PARTITION) {
+ layout.nodeSize(nodesz);
+ } else {
+ layout.size(this.param('size'));
+ }
+
+ layout
+ .sort(sort.field.length ? dl.comparator(sort.field) : null)
+ .children(this.param('children').accessor)
+ .nodes(root);
+
+ // copy layout values to nodes
+ data.forEach(function(n) {
+ Tuple.set(n, output.x, n.x);
+ Tuple.set(n, output.y, n.y);
+ Tuple.set(n, output.depth, n.depth);
+ if (mode === PARTITION) {
+ Tuple.set(n, output.width, n.dx);
+ Tuple.set(n, output.height, n.dy);
+ }
+ });
+
+ // return changeset
+ return input;
+};
+
+module.exports = Hierarchy;
+}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+
+},{"./BatchTransform":119,"./Transform":140,"./screen":146,"datalib":26,"vega-dataflow":41,"vega-logging":48}],132:[function(require,module,exports){
+var dl = require('datalib'),
+ log = require('vega-logging'),
+ Tuple = require('vega-dataflow').Tuple,
+ Transform = require('./Transform'),
+ BatchTransform = require('./BatchTransform');
+
+function Impute(graph) {
+ BatchTransform.prototype.init.call(this, graph);
+ Transform.addParameters(this, {
+ groupby: {type: 'array'},
+ orderby: {type: 'array'},
+ field: {type: 'field'},
+ method: {type: 'value', default: 'value'},
+ value: {type: 'value', default: 0}
+ });
+
+ return this.router(true).produces(true);
+}
+
+var prototype = (Impute.prototype = Object.create(BatchTransform.prototype));
+prototype.constructor = Impute;
+
+prototype.batchTransform = function(input, data) {
+ log.debug(input, ['imputing']);
+
+ var groupby = this.param('groupby'),
+ orderby = this.param('orderby'),
+ method = this.param('method'),
+ value = this.param('value'),
+ field = this.param('field'),
+ get = field.accessor,
+ name = field.field,
+ prev = this._imputed || [], curr = [],
+ groups = partition(data, groupby.accessor, orderby.accessor),
+ domain = groups.domain,
+ group, i, j, n, m, t;
+
+ function getval(x) {
+ return x == null ? null : get(x);
+ }
+
+ for (j=0, m=groups.length; j Math.PI ? ta <= sa : ta > sa;
+ return 'M' + (sr*sc) + ',' + (sr*ss) +
+ 'A' + sr + ',' + sr + ' 0 0,' + (sf?1:0) +
+ ' ' + (sr*tc) + ',' + (sr*ts) +
+ 'L' + (tr*tc) + ',' + (tr*ts);
+}
+
+function diagonalX(sx, sy, tx, ty) {
+ var m = (sx + tx) / 2;
+ return 'M' + sx + ',' + sy +
+ 'C' + m + ',' + sy +
+ ' ' + m + ',' + ty +
+ ' ' + tx + ',' + ty;
+}
+
+function diagonalY(sx, sy, tx, ty) {
+ var m = (sy + ty) / 2;
+ return 'M' + sx + ',' + sy +
+ 'C' + sx + ',' + m +
+ ' ' + tx + ',' + m +
+ ' ' + tx + ',' + ty;
+}
+
+function diagonalR(sa, sr, ta, tr) {
+ var sc = Math.cos(sa),
+ ss = Math.sin(sa),
+ tc = Math.cos(ta),
+ ts = Math.sin(ta),
+ mr = (sr + tr) / 2;
+ return 'M' + (sr*sc) + ',' + (sr*ss) +
+ 'C' + (mr*sc) + ',' + (mr*ss) +
+ ' ' + (mr*tc) + ',' + (mr*ts) +
+ ' ' + (tr*tc) + ',' + (tr*ts);
+}
+
+var shapes = {
+ line: line,
+ curve: curve,
+ cornerX: cornerX,
+ cornerY: cornerY,
+ cornerR: cornerR,
+ diagonalX: diagonalX,
+ diagonalY: diagonalY,
+ diagonalR: diagonalR
+};
+
+prototype.transform = function(input) {
+ log.debug(input, ['linkpath']);
+
+ var output = this._output,
+ shape = shapes[this.param('shape')] || shapes.line,
+ sourceX = this.param('sourceX').accessor,
+ sourceY = this.param('sourceY').accessor,
+ targetX = this.param('targetX').accessor,
+ targetY = this.param('targetY').accessor,
+ tension = this.param('tension');
+
+ function set(t) {
+ var path = shape(sourceX(t), sourceY(t), targetX(t), targetY(t), tension);
+ Tuple.set(t, output.path, path);
+ }
+
+ input.add.forEach(set);
+ if (this.reevaluate(input)) {
+ input.mod.forEach(set);
+ input.rem.forEach(set);
+ }
+
+ input.fields[output.path] = 1;
+ return input;
+};
+
+module.exports = LinkPath;
+},{"./Transform":140,"vega-dataflow":41,"vega-logging":48}],134:[function(require,module,exports){
+var Tuple = require('vega-dataflow').Tuple,
+ log = require('vega-logging'),
+ Transform = require('./Transform');
+
+function Lookup(graph) {
+ Transform.prototype.init.call(this, graph);
+ Transform.addParameters(this, {
+ on: {type: 'data'},
+ onKey: {type: 'field', default: null},
+ as: {type: 'array'},
+ keys: {type: 'array', default: ['data']},
+ default: {type: 'value'}
+ });
+
+ return this.mutates(true);
+}
+
+var prototype = (Lookup.prototype = Object.create(Transform.prototype));
+prototype.constructor = Lookup;
+
+prototype.transform = function(input, reset) {
+ log.debug(input, ['lookup']);
+
+ var on = this.param('on'),
+ onLast = on.source.last(),
+ onData = on.source.values(),
+ onKey = this.param('onKey'),
+ onF = onKey.field,
+ keys = this.param('keys'),
+ get = keys.accessor,
+ as = this.param('as'),
+ defaultValue = this.param('default'),
+ lut = this._lut,
+ i, v;
+
+ // build lookup table on init, withKey modified, or tuple add/rem
+ if (lut == null || this._on !== onF || onF && onLast.fields[onF] ||
+ onLast.add.length || onLast.rem.length)
+ {
+ if (onF) { // build hash from withKey field
+ onKey = onKey.accessor;
+ for (lut={}, i=0; i'} });
+ this.router(true);
+}
+
+var prototype = (Sort.prototype = Object.create(Transform.prototype));
+prototype.constructor = Sort;
+
+prototype.transform = function(input) {
+ log.debug(input, ['sorting']);
+
+ if (input.add.length || input.mod.length || input.rem.length) {
+ input.sort = dl.comparator(this.param('by').field);
+ }
+ return input;
+};
+
+module.exports = Sort;
+},{"./Transform":140,"datalib":26,"vega-logging":48}],139:[function(require,module,exports){
+var dl = require('datalib'),
+ Tuple = require('vega-dataflow').Tuple,
+ log = require('vega-logging'),
+ Transform = require('./Transform'),
+ BatchTransform = require('./BatchTransform');
+
+function Stack(graph) {
+ BatchTransform.prototype.init.call(this, graph);
+ Transform.addParameters(this, {
+ groupby: {type: 'array'},
+ sortby: {type: 'array'},
+ field: {type: 'field'},
+ offset: {type: 'value', default: 'zero'}
+ });
+
+ this._output = {
+ 'start': 'layout_start',
+ 'end': 'layout_end',
+ 'mid': 'layout_mid'
+ };
+ return this.mutates(true);
+}
+
+var prototype = (Stack.prototype = Object.create(BatchTransform.prototype));
+prototype.constructor = Stack;
+
+prototype.batchTransform = function(input, data) {
+ log.debug(input, ['stacking']);
+
+ var groupby = this.param('groupby').accessor,
+ sortby = dl.comparator(this.param('sortby').field),
+ field = this.param('field').accessor,
+ offset = this.param('offset'),
+ output = this._output;
+
+ // partition, sum, and sort the stack groups
+ var groups = partition(data, groupby, sortby, field);
+
+ // compute stack layouts per group
+ for (var i=0, max=groups.max; i max) max = s;
+ if (sortby != null) g.sort(sortby);
+ }
+ groups.max = max;
+
+ return groups;
+}
+
+module.exports = Stack;
+},{"./BatchTransform":119,"./Transform":140,"datalib":26,"vega-dataflow":41,"vega-logging":48}],140:[function(require,module,exports){
+var df = require('vega-dataflow'),
+ Base = df.Node.prototype, // jshint ignore:line
+ Deps = df.Dependencies,
+ Parameter = require('./Parameter');
+
+function Transform(graph) {
+ if (graph) Base.init.call(this, graph);
+}
+
+Transform.addParameters = function(proto, params) {
+ proto._parameters = proto._parameters || {};
+ for (var name in params) {
+ var p = params[name],
+ param = new Parameter(name, p.type, proto);
+
+ proto._parameters[name] = param;
+
+ if (p.type === 'custom') {
+ if (p.set) param.set = p.set.bind(param);
+ if (p.get) param.get = p.get.bind(param);
+ }
+
+ if (p.hasOwnProperty('default')) param.set(p.default);
+ }
+};
+
+var prototype = (Transform.prototype = Object.create(Base));
+prototype.constructor = Transform;
+
+prototype.param = function(name, value) {
+ var param = this._parameters[name];
+ return (param === undefined) ? this :
+ (arguments.length === 1) ? param.get() : param.set(value);
+};
+
+// Perform transformation. Subclasses should override.
+prototype.transform = function(input/*, reset */) {
+ return input;
+};
+
+prototype.evaluate = function(input) {
+ // Many transforms store caches that must be invalidated if
+ // a signal value has changed.
+ var reset = this._stamp < input.stamp &&
+ this.dependency(Deps.SIGNALS).reduce(function(c, s) {
+ return c += input.signals[s] ? 1 : 0;
+ }, 0);
+ return this.transform(input, reset);
+};
+
+prototype.output = function(map) {
+ for (var key in this._output) {
+ if (map[key] !== undefined) {
+ this._output[key] = map[key];
+ }
+ }
+ return this;
+};
+
+module.exports = Transform;
+},{"./Parameter":135,"vega-dataflow":41}],141:[function(require,module,exports){
+var dl = require('datalib'),
+ Tuple = require('vega-dataflow').Tuple,
+ log = require('vega-logging'),
+ Transform = require('./Transform'),
+ BatchTransform = require('./BatchTransform');
+
+function Treeify(graph) {
+ BatchTransform.prototype.init.call(this, graph);
+ Transform.addParameters(this, {
+ groupby: {type: 'array'}
+ });
+
+ this._output = {
+ 'children': 'children',
+ 'parent': 'parent'
+ };
+ return this.router(true).produces(true);
+}
+
+var prototype = (Treeify.prototype = Object.create(BatchTransform.prototype));
+prototype.constructor = Treeify;
+
+prototype.batchTransform = function(input, data) {
+ log.debug(input, ['treeifying']);
+
+ var fields = this.param('groupby').field,
+ childField = this._output.children,
+ parentField = this._output.parent,
+ summary = [{name:'*', ops: ['values'], as: [childField]}],
+ aggrs = fields.map(function(f) {
+ return dl.groupby(f).summarize(summary);
+ }),
+ prev = this._internal || [], curr = [], i, n;
+
+ function level(index, node, values) {
+ var vals = aggrs[index].execute(values);
+
+ node[childField] = vals;
+ vals.forEach(function(n) {
+ n[parentField] = node;
+ curr.push(Tuple.ingest(n));
+ if (index+1 < fields.length) level(index+1, n, n[childField]);
+ else n[childField].forEach(function(c) { c[parentField] = n; });
+ });
+ }
+
+ var root = Tuple.ingest({});
+ root[parentField] = null;
+ curr.push(root);
+ level(0, root, data);
+
+ // update changeset with internal nodes
+ for (i=0, n=curr.length; i', default: ['-value']},
+ children: {type: 'field', default: 'children'},
+ parent: {type: 'field', default: 'parent'},
+ field: {type: 'field', default: 'value'},
+ // treemap parameters
+ size: {type: 'array', default: require('./screen').size},
+ round: {type: 'value', default: true},
+ sticky: {type: 'value', default: false},
+ ratio: {type: 'value', default: defaultRatio},
+ padding: {type: 'value', default: null},
+ mode: {type: 'value', default: 'squarify'}
+ });
+
+ this._layout = d3.layout.treemap();
+
+ this._output = {
+ 'x': 'layout_x',
+ 'y': 'layout_y',
+ 'width': 'layout_width',
+ 'height': 'layout_height',
+ 'depth': 'layout_depth',
+ };
+ return this.mutates(true);
+}
+
+var prototype = (Treemap.prototype = Object.create(BatchTransform.prototype));
+prototype.constructor = Treemap;
+
+prototype.batchTransform = function(input, data) {
+ log.debug(input, ['treemap']);
+
+ // get variables
+ var layout = this._layout,
+ output = this._output,
+ sticky = this.param('sticky'),
+ parent = this.param('parent').accessor,
+ root = data.filter(function(d) { return parent(d) === null; })[0];
+
+ // layout.sticky resets state _regardless_ of input value
+ // so, we perform out own check first
+ if (layout.sticky() !== sticky) { layout.sticky(sticky); }
+
+ // configure layout
+ layout
+ .sort(dl.comparator(this.param('sort').field))
+ .children(this.param('children').accessor)
+ .value(this.param('field').accessor)
+ .size(this.param('size'))
+ .round(this.param('round'))
+ .ratio(this.param('ratio'))
+ .padding(this.param('padding'))
+ .mode(this.param('mode'))
+ .nodes(root);
+
+ // copy layout values to nodes
+ data.forEach(function(n) {
+ Tuple.set(n, output.x, n.x);
+ Tuple.set(n, output.y, n.y);
+ Tuple.set(n, output.width, n.dx);
+ Tuple.set(n, output.height, n.dy);
+ Tuple.set(n, output.depth, n.depth);
+ });
+
+ // return changeset
+ input.fields[output.x] = 1;
+ input.fields[output.y] = 1;
+ input.fields[output.width] = 1;
+ input.fields[output.height] = 1;
+ input.fields[output.depth] = 1;
+ return input;
+};
+
+module.exports = Treemap;
+}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+
+},{"./BatchTransform":119,"./Transform":140,"./screen":146,"datalib":26,"vega-dataflow":41,"vega-logging":48}],143:[function(require,module,exports){
+(function (global){
+var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null),
+ Tuple = require('vega-dataflow/src/Tuple'),
+ log = require('vega-logging'),
+ Transform = require('./Transform'),
+ BatchTransform = require('./BatchTransform');
+
+function Voronoi(graph) {
+ BatchTransform.prototype.init.call(this, graph);
+ Transform.addParameters(this, {
+ clipExtent: {type: 'array', default: require('./screen').extent},
+ x: {type: 'field', default: 'layout_x'},
+ y: {type: 'field', default: 'layout_y'}
+ });
+
+ this._layout = d3.geom.voronoi();
+ this._output = {'path': 'layout_path'};
+
+ return this.mutates(true);
+}
+
+var prototype = (Voronoi.prototype = Object.create(BatchTransform.prototype));
+prototype.constructor = Voronoi;
+
+prototype.batchTransform = function(input, data) {
+ log.debug(input, ['voronoi']);
+
+ // get variables
+ var pathname = this._output.path;
+
+ // configure layout
+ var polygons = this._layout
+ .clipExtent(this.param('clipExtent'))
+ .x(this.param('x').accessor)
+ .y(this.param('y').accessor)
+ (data);
+
+ // build and assign path strings
+ for (var i=0; i', default: require('./screen').size},
+ text: {type: 'field', default: 'data'},
+ rotate: {type: 'field|value', default: 0},
+ font: {type: 'field|value', default: {value: 'sans-serif'}},
+ fontSize: {type: 'field|value', default: 14},
+ fontStyle: {type: 'field|value', default: {value: 'normal'}},
+ fontWeight: {type: 'field|value', default: {value: 'normal'}},
+ fontScale: {type: 'array', default: [10, 50]},
+ padding: {type: 'value', default: 1},
+ spiral: {type: 'value', default: 'archimedean'}
+ });
+
+ this._layout = d3_cloud().canvas(canvas.instance);
+
+ this._output = {
+ 'x': 'layout_x',
+ 'y': 'layout_y',
+ 'font': 'layout_font',
+ 'fontSize': 'layout_fontSize',
+ 'fontStyle': 'layout_fontStyle',
+ 'fontWeight': 'layout_fontWeight',
+ 'rotate': 'layout_rotate',
+ };
+
+ return this.mutates(true);
+}
+
+var prototype = (Wordcloud.prototype = Object.create(BatchTransform.prototype));
+prototype.constructor = Wordcloud;
+
+function get(p) {
+ return (p && p.accessor) || p;
+}
+
+function wrap(tuple) {
+ var x = Object.create(tuple);
+ x._tuple = tuple;
+ return x;
+}
+
+prototype.batchTransform = function(input, data) {
+ log.debug(input, ['wordcloud']);
+
+ // get variables
+ var layout = this._layout,
+ output = this._output,
+ fontSize = this.param('fontSize'),
+ range = fontSize.accessor && this.param('fontScale'),
+ size, scale;
+ fontSize = fontSize.accessor || d3.functor(fontSize);
+
+ // create font size scaling function as needed
+ if (range.length) {
+ scale = d3.scale.sqrt()
+ .domain(dl.extent(data, size=fontSize))
+ .range(range);
+ fontSize = function(x) { return scale(size(x)); };
+ }
+
+ // configure layout
+ layout
+ .size(this.param('size'))
+ .text(get(this.param('text')))
+ .padding(this.param('padding'))
+ .spiral(this.param('spiral'))
+ .rotate(get(this.param('rotate')))
+ .font(get(this.param('font')))
+ .fontStyle(get(this.param('fontStyle')))
+ .fontWeight(get(this.param('fontWeight')))
+ .fontSize(fontSize)
+ .words(data.map(wrap)) // wrap to avoid tuple writes
+ .on('end', function(words) {
+ var size = layout.size(),
+ dx = size[0] >> 1,
+ dy = size[1] >> 1,
+ w, t, i, len;
+
+ for (i=0, len=words.length; i 0 ? (e = 1e-12, Math.ceil) : (e = -1e-12, Math.floor),
+ e;
+ function log(x) {
+ return (domain[0] < 0 ?
+ -Math.log(x > 0 ? 0 : -x) :
+ Math.log(x < 0 ? 0 : x)) / Math.log(base);
+ }
+ function pow(x) {
+ return domain[0] < 0 ? -Math.pow(base, -x) : Math.pow(base, x);
+ }
+ return function(d) {
+ return pow(v(log(d) + e)) / d >= k ? f(d) : '';
+ };
+}
+
+function getFormatter(scale, tickCount, formatType, str) {
+ var fmt = dl.format,
+ log = scale.type === 'log',
+ domain;
+
+ switch (formatType) {
+ case NUMBER:
+ domain = scale.domain();
+ return log ?
+ logFilter(scale, domain, tickCount, fmt.auto.number(str || null)) :
+ fmt.auto.linear(domain, tickCount, str || null);
+ case TIME: return (str ? fmt : fmt.auto).time(str);
+ case UTC: return (str ? fmt : fmt.auto).utc(str);
+ default: return String;
+ }
+}
+
+module.exports = {
+ getTickFormat: getTickFormat
+};
+},{"datalib":26}],148:[function(require,module,exports){
+var dl = require('datalib'),
+ u = {};
+
+dl.extend(u, require('./format'));
+module.exports = dl.extend(u, dl);
+},{"./format":147,"datalib":26}]},{},[1])(1)
+});
+//# sourceMappingURL=vega.js.map
diff --git a/features/ids-authentication-artifacts/ids-authentication-analytics/dashboard/TotalTokensBarChart_v2_1.0.0/total-tokens-v2/js/wso2gadgets.js b/features/ids-authentication-artifacts/ids-authentication-analytics/dashboard/TotalTokensBarChart_v2_1.0.0/total-tokens-v2/js/wso2gadgets.js
new file mode 100644
index 0000000..41db6d0
--- /dev/null
+++ b/features/ids-authentication-artifacts/ids-authentication-analytics/dashboard/TotalTokensBarChart_v2_1.0.0/total-tokens-v2/js/wso2gadgets.js
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+(function() {
+
+ var wso2gadgets = window.wso2gadgets || {};
+ window.wso2gadgets = wso2gadgets;
+
+ //Collection of view defintions
+ var views = {};
+
+ //Reference to currenr view defintion
+ var currentView;
+
+ //Reference to the vizg object of currentView object
+ var chart;
+
+ var canvas;
+
+ var MODE_REDRAW = "redraw";
+ var MODE_APPEND = "append";
+
+ /*
+ * Initialise the wso2gadgets object by passing the canvas element and view definitions.
+ * View definitions can be an array or a single view definition object
+ * Optionally default view can be passed (view that should be loaded first)
+ * E.g wso2gadgets.init("#canvas",views,"chart-0");
+ */
+ wso2gadgets.init = function(el, configs, defaultView) {
+ canvas = el;
+ if (configs.constructor === Array) {
+ configs.forEach(function(view) {
+ views[view.id] = view;
+ });
+ } else if (typeof configs === 'object') {
+ views[configs.id] = configs;
+ }
+ if (defaultView) {
+ wso2gadgets.load(defaultView);
+ }
+ };
+
+ wso2gadgets.load = function(id, context) {
+ currentView = views[id];
+ if (!currentView) {
+ throw new Error("View with specified id [" + id + "] does not exist.");
+ }
+ //load data into current view using view's data configuration
+ if (currentView.data && typeof currentView.data === "function") {
+ currentView.data();
+ }
+ //initialize inter-gadget subscriptions
+ /*gadgets.HubSettings.onConnect = function() {
+ if (currentView.subscriptions) {
+ currentView.subscriptions.forEach(function(subscription) {
+ gadgets.Hub.subscribe(subscription.topic, subscription.callback);
+ });
+ }
+ };*/
+ console.log("View [" + id + "] has been loaded.");
+ };
+
+ /*
+ * This method needs to be called by interested parties with necessary data in their hands.
+ * data should be in VizGrammar compatible format
+ * drawMode redraw || append. 'redraw' forces the chart to be redrawn with new data while 'append' just adds the new entries in to the chart.
+ * Usually in realtime chart, this method needs to be called with drawMode='append'
+ */
+ wso2gadgets.onDataReady = function(data, drawMode) {
+ try {
+ if (data.length == 0) {
+ $(canvas).html(gadgetUtil.getEmptyRecordsText());
+ return;
+ }
+ //setting the data for the underlying VizGrammar chart
+ currentView.schema[0].data = data;
+ //calling the draw function on the current view object
+ if (drawMode) {
+ if(drawMode === MODE_REDRAW) {
+ wso2gadgets.draw(currentView);
+ } else if(drawMode === MODE_APPEND) {
+ wso2gadgets.update(data);
+ }
+ } else {
+ wso2gadgets.draw(currentView); //if the drawMode parameter has been specified, use it, otherwise just redraw
+ }
+ } catch (e) {
+ wso2gadgets.onError(e);
+ }
+ };
+
+ wso2gadgets.draw = function(view) {
+ if (!view.chartConfig.width) {
+ view.chartConfig.width = $('body').width();
+ }
+ if (!view.chartConfig.height) {
+ view.chartConfig.height = $('body').height();
+ }
+ $(canvas).empty();
+ chart = new vizg(view.schema, view.chartConfig);
+ if (view.callbacks && view.callbacks.length > 0) {
+ chart.draw(canvas, view.callbacks);
+ } else {
+ chart.draw(canvas);
+ }
+ };
+
+ wso2gadgets.update = function(data) {
+ if (chart) {
+ console.log(data);
+ chart.insert(data);
+ } else {
+ wso2gadgets.draw(currentView); //if this is the very first time we render the chart. E.g CEP usecase
+ }
+ };
+
+ wso2gadgets.onError = function(e) {
+ console.error(e);
+ $(canvas).html(gadgetUtil.getErrorText(e));
+ };
+
+
+})();
\ No newline at end of file
diff --git a/features/ids-authentication-artifacts/ids-authentication-analytics/processing/TokenEndpointEventSink_1.0.0/com_wso2telco_token_endpoint.xml b/features/ids-authentication-artifacts/ids-authentication-analytics/processing/TokenEndpointEventSink_1.0.0/com_wso2telco_token_endpoint.xml
index e07a8af..0b7688c 100644
--- a/features/ids-authentication-artifacts/ids-authentication-analytics/processing/TokenEndpointEventSink_1.0.0/com_wso2telco_token_endpoint.xml
+++ b/features/ids-authentication-artifacts/ids-authentication-analytics/processing/TokenEndpointEventSink_1.0.0/com_wso2telco_token_endpoint.xml
@@ -96,6 +96,14 @@
false
false
STRING
+
+
+ status
+ false
+ false
+ false
+ false
+ STRING
sessionID
@@ -111,4 +119,4 @@
false
EVENT_STORE
-
\ No newline at end of file
+
diff --git a/features/ids-authentication-artifacts/ids-authentication-analytics/processing/TokenEndpointEventStream_1.0.0/com.wso2telco.token.endpoint_1.0.0.json b/features/ids-authentication-artifacts/ids-authentication-analytics/processing/TokenEndpointEventStream_1.0.0/com.wso2telco.token.endpoint_1.0.0.json
index 1aaf66d..90c6685 100644
--- a/features/ids-authentication-artifacts/ids-authentication-analytics/processing/TokenEndpointEventStream_1.0.0/com.wso2telco.token.endpoint_1.0.0.json
+++ b/features/ids-authentication-artifacts/ids-authentication-analytics/processing/TokenEndpointEventStream_1.0.0/com.wso2telco.token.endpoint_1.0.0.json
@@ -56,6 +56,10 @@
"name": "sessionID",
"type": "STRING"
},
+ {
+ "name": "status",
+ "type": "STRING"
+ },
{
"name": "_timestamp",
"type": "LONG"
diff --git a/features/ids-authentication-artifacts/ids-authentication-analytics/processing/TotalTokenCountsSparkscripts_1.0.0/artifact.xml b/features/ids-authentication-artifacts/ids-authentication-analytics/processing/TotalTokenCountsSparkscripts_1.0.0/artifact.xml
new file mode 100644
index 0000000..bf12bfa
--- /dev/null
+++ b/features/ids-authentication-artifacts/ids-authentication-analytics/processing/TotalTokenCountsSparkscripts_1.0.0/artifact.xml
@@ -0,0 +1,4 @@
+
+
+ total_token_counts.xml
+
diff --git a/features/ids-authentication-artifacts/ids-authentication-analytics/processing/TotalTokenCountsSparkscripts_1.0.0/total_token_counts.xml b/features/ids-authentication-artifacts/ids-authentication-analytics/processing/TotalTokenCountsSparkscripts_1.0.0/total_token_counts.xml
new file mode 100644
index 0000000..de1a0af
--- /dev/null
+++ b/features/ids-authentication-artifacts/ids-authentication-analytics/processing/TotalTokenCountsSparkscripts_1.0.0/total_token_counts.xml
@@ -0,0 +1,119 @@
+
+
+ total_token_counts
+
+ 0 0 0 1/1 * ? *
+