diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/api/device-api.jag b/modules/distribution/src/repository/jaggeryapps/sensebot/api/device-api.jag new file mode 100755 index 00000000..0a5c8ef4 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/api/device-api.jag @@ -0,0 +1,46 @@ +<% +/* + * 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 uri = request.getRequestURI(); +var uriMatcher = new URIMatcher(String(uri)); + +var log = new Log("api/device-api.jag"); + +var constants = require("/modules/constants.js"); +var dcProps = require('/config/dc-props.js').config(); +var downloadModule = require("/modules/download.js").downloadModule; +var utility = require("/modules/utility.js").utility; + +var result; + +if (uriMatcher.match("/{context}/api/device/sketch/")) { + sketchType = request.getParameter("type"); + if(!sketchType){log.error("Sketch Type is empty");} + + senseBotManagerService = "http://localhost:9763/iotdevices/SenseBotManager"; + sketchDownloadEndPoint = senseBotManagerService + "/downloadSketch"; + response.sendRedirect(sketchDownloadEndPoint + "?type="+sketchType+"&owner=anonymous"); + exit(); +} + +// returning the result. +if (result) { + print(result); +} +%> diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/api/stats-api.jag b/modules/distribution/src/repository/jaggeryapps/sensebot/api/stats-api.jag new file mode 100755 index 00000000..e56545b5 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/api/stats-api.jag @@ -0,0 +1,144 @@ +<% +/* + * 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 uri = request.getRequestURI(); +var uriMatcher = new URIMatcher(String(uri)); + +var log = new Log("api/stats-api.jag"); + +var constants = require("/modules/constants.js"); +var dcProps = require('/config/dc-props.js').config(); +var utility = require("/modules/utility.js").utility; + +var result; +var statsClient = new Packages.org.wso2.carbon.device.mgt.iot.usage.statistics.IoTUsageStatisticsClient; + +if (uriMatcher.match("/{context}/api/stats")) { + + var deviceId = request.getParameter("deviceId"); + var from = request.getParameter("from"); + var to = request.getParameter("to"); + + log.info("deviceId : " + deviceId + " from : " + from + " to : " + to); + + result = getData(getUsername(), deviceId, from, to); + +} + +// returning the result. +if (result) { + print(result); +} + +function getUsername() { + + var user = session.get(constants.USER_SESSION_KEY); + + if (user) { + log.info("username: "+ user.username); + return user.username; + } else { + log.info("username is null"); + return null; + } + + + +} + +function getData(user, deviceId, from, to) { + + result = new Object(); + + result['sonarData'] = getSensorData("SONAR_SENSOR_SUMMARY","SONAR",user, deviceId, from, to); + result['motionData'] = getSensorData("PIR_MOTION_SENSOR_SUMMARY","MOTION",user, deviceId, from, to); + result['lightData'] = getSensorData("LDR_LIGHT_SENSOR_SUMMARY","LIGHT",user, deviceId, from, to); + result['temperatureData'] = getSensorData("DEVICE_TEMPERATURE_SUMMARY","TEMPERATURE",user, deviceId, from, to); + + return result; + +} + +function getSensorData(table, column, user, deviceId, from, to) { + + var fetchedData = statsClient.getDeviceStats(table, column, user, deviceId, from, to); + + var temperatureData = []; + + for (var i = 0; i < fetchedData.size(); i++) { + temperatureData.push({ + time: fetchedData.get(i).getTime(), + value: fetchedData.get(i).getValue() + }); + } + + return temperatureData; +} + +// ------------- Sample data generation ----------------- + +function getSampleData() { + + result = new Object(); + + result['bulbStatusData'] = getBulbStatusSampleData(); + result['fanStatusData'] = getFanStatusSampleData(); + result['temperatureData'] = getTemperatureSampleData(); + + return result; +} + +function getBulbStatusSampleData(from, to) { + + var bulbStatusData = []; + + for (var i = 0; i < 100; i++) { + bulbStatusData.push({ + time: Date.now() + (i * 1000), + value: Math.floor((Math.random() * 100) + 1) % 2 == 0 ? 'ON' : 'OFF'}); + } + + return bulbStatusData; +}; + + +function getFanStatusSampleData(from, to) { + + var fanStatusData = []; + + for (var i = 0; i < 100; i++) { + fanStatusData.push({time: Date.now() + (i * 1000), value: Math.floor((Math.random() * 100) + 1) % 2 == 0 ? 'ON' : 'OFF'}); + } + + return fanStatusData; +} + +function getTemperatureSampleData(from, to) { + + var temperatureData = []; + + for (var i = 0; i < 100; i++) { + temperatureData.push({time: Date.now() + (i * 1000), value: Math.random() * 100}); + } + + return temperatureData; +} + + +%> \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/config/config.json b/modules/distribution/src/repository/jaggeryapps/sensebot/config/config.json new file mode 100755 index 00000000..95a917df --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/config/config.json @@ -0,0 +1,16 @@ +{ + "appContext" : "/iot/", + "apiContext" : "api", + "httpsURL": "%https.ip%", + "httpURL": "%http.ip%", + "ssoConfiguration": { + "enabled": false, + "issuer": "iot", + "appName": "iot", + "identityProviderURL": "%https.ip%/sso/samlsso.jag", + "responseSigningEnabled": "true", + "keyStorePassword": "wso2carbon", + "identityAlias": "wso2carbon", + "keyStoreName": "/repository/resources/security/wso2carbon.jks" + } +} \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/config/dc-props.js b/modules/distribution/src/repository/jaggeryapps/sensebot/config/dc-props.js new file mode 100755 index 00000000..7911f514 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/config/dc-props.js @@ -0,0 +1,37 @@ +/* + * 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 config = function () { + var conf = application.get("PINCH_CONFIG"); + if (!conf) {//if not in cache + var pinch = require('/modules/pinch.min.js').pinch; + var server = require('carbon').server; + var config = require('/config/config.json'); + pinch(config, /^/, function (path, key, value) { + if ((typeof value === 'string') && value.indexOf('%https.ip%') > -1) { + return value.replace('%https.ip%', server.address("https")); + } else if ((typeof value === 'string') && value.indexOf('%http.ip%') > -1) { + return value.replace('%http.ip%', server.address("http")); + } + return value; + }); + application.put("PINCH_CONFIG", config);//caching + conf = config; + } + return conf; +}; \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/config/init.js b/modules/distribution/src/repository/jaggeryapps/sensebot/config/init.js new file mode 100755 index 00000000..d492ae79 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/config/init.js @@ -0,0 +1,28 @@ +/* + * 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 carbonModule = require("carbon"); +var dcProps = require('/config/dc-props.js').config(); +var carbonServer = new carbonModule.server.Server({ + tenanted: true, + url: dcProps.httpsURL + '/admin' +}); +application.put("carbonServer", carbonServer); +var userModule = require("/modules/user.js").userModule; +var utility = require("/modules/utility.js").utility; +utility.insertAppPermissions(userModule, "init"); \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/jaggery.conf b/modules/distribution/src/repository/jaggeryapps/sensebot/jaggery.conf new file mode 100755 index 00000000..c0d708f1 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/jaggery.conf @@ -0,0 +1,23 @@ +{ + "displayName": "Fuse Sample", + "logLevel": "info", + "initScripts": ["/config/init.js"], + "urlMappings": [ + { + "url" : "/test/*", + "path" : "test/testExecutor.jag" + }, + { + "url": "/api/stats/*", + "path": "/api/stats-api.jag" + }, + { + "url": "/api/device/*", + "path": "/api/device-api.jag" + }, + { + "url": "/*", + "path": "/lib/fuse.jag" + } + ] +} \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/layouts/enrollment.hbs b/modules/distribution/src/repository/jaggeryapps/sensebot/layouts/enrollment.hbs new file mode 100755 index 00000000..388ca0d4 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/layouts/enrollment.hbs @@ -0,0 +1,29 @@ + + + + + + + {{ defineZone "title"}} + + {{ defineZone "topLibCss"}} + {{ defineZone "topCss"}} + + +
+ +
+
+ +
+
+ + {{ defineZone "body"}} +
+ {{ defineZone "bottomjquery" }} + {{ defineZone "bottomLibJs" }} + {{ defineZone "bottomJs" }} + + diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/layouts/fluid.hbs b/modules/distribution/src/repository/jaggeryapps/sensebot/layouts/fluid.hbs new file mode 100755 index 00000000..1c9a5847 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/layouts/fluid.hbs @@ -0,0 +1,23 @@ + + + + + + + + {{ defineZone "title"}} + {{ defineZone "topLibCss"}} + {{ defineZone "topCss"}} + {{ defineZone "topJs"}} + + +
+ + {{ defineZone "header"}} + + {{ defineZone "body"}} +
+ {{ defineZone "bottomLibJs" }} + {{ defineZone "bottomJs" }} + + diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/layouts/nav-fluid.hbs b/modules/distribution/src/repository/jaggeryapps/sensebot/layouts/nav-fluid.hbs new file mode 100755 index 00000000..00278772 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/layouts/nav-fluid.hbs @@ -0,0 +1,50 @@ + + + + + {{ defineZone "title"}} + {{ defineZone "topCss"}} + + + + +
+
+ +
+
+ {{ defineZone "left"}} +
+ +
+ {{ defineZone "content"}} +
+
+ +
+ +
+ + + + diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/lib/acs.jag b/modules/distribution/src/repository/jaggeryapps/sensebot/lib/acs.jag new file mode 100755 index 00000000..147c20a2 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/lib/acs.jag @@ -0,0 +1,49 @@ +<% +/* + * 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 dataConfig = require('/config/dc-props.js').config(); +var sso = require('/modules/sso.js').sso; +var constants = require('/modules/constants.js'); +var carbonModule = require("carbon"); +var log = new Log(); +var keyStoreParams = { + keyStoreName: dataConfig.ssoConfiguration.keyStoreName, + keyStorePassword: dataConfig.ssoConfiguration.keyStorePassword, + identityAlias: dataConfig.ssoConfiguration.identityAlias +}; +sso.configure(dataConfig.ssoConfiguration.issuer, + dataConfig.ssoConfiguration.appName, + keyStoreParams, dataConfig.ssoConfiguration.identityProviderURL); +sso.acs( + function(loggedInUser) { + var carbonUser = carbonModule.server.tenantUser(loggedInUser); + session.put(constants.USER_SESSION_KEY, carbonUser); + var username = carbonUser.username; + if(log.isDebugEnabled()){ + log.debug("User logged in: "+username); + } + response.sendRedirect(dataConfig.appContext); + }, function() { + if(log.isDebugEnabled()){ + log.debug("User logged out"); + } + response.sendRedirect(dataConfig.appContext); + } +); +%> \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/lib/fuse-router.js b/modules/distribution/src/repository/jaggeryapps/sensebot/lib/fuse-router.js new file mode 100755 index 00000000..7aab77d7 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/lib/fuse-router.js @@ -0,0 +1,210 @@ +//public function declarations +var route; + +(function () { + + //public + /** + * front controller entity point. acts as the main function for every request. + */ + route = function () { + //lets assume URL looks like https://my.domain.com/app/{one}/{two}/{three}/{four} + var uri = request.getRequestURI(); // = app/{one}/{two}/{three}/{four} + var parts = splitFirst(uri); + fuseState.appName = parts.head; + var path = parts.tail; // = /{one}/{two}/{three}/{four} + var handled = false; + + parts = splitFirst(path); + if (parts.head == 'public') { // {one} == 'public' + parts = splitFirst(parts.tail); + if (splitFirst(parts.tail).head == 'less') { // {three} == 'less' + handled = renderLess(parts.head, parts.tail); // renderLess({two},{three}/{four}) + } else { + handled = renderStatic(parts.head, parts.tail); + } + } else { + handled = renderPage(path); + if (!handled) { + handled = renderUnit(path); + } + } + + if (!handled) { + response.sendError(404, 'Requested resource not found'); + } + + }; + + + //private + var log = new Log('fuse.router'); + + var getMime = function (path) { + var index = path.lastIndexOf('.') + 1; + var knowMime = { + 'js': 'application/javascript', + 'html': 'text/html', + 'htm': 'text/html', + 'woff': 'application/x-font-woff', + "png": "image/png", + "css": "text/css", + "hbs": "text/x-handlebars-template", + "apk": "application/vnd.android.package-archive", + "ipa": "application/octet-stream" + }; + var mime; + if (index >= 0) { + mime = knowMime[path.substr(index)]; + } + return mime || 'text/plain'; + }; + + /** + * '/a/b/c/d' -> {'a','b/c/d'} + * @param path URI part, should start with '/' + * @returns {{head: string, tail: string}} + */ + var splitFirst = function (path) { + var firstSlashPos = path.indexOf('/', 1); + var head = path.substring(1, firstSlashPos); + var tail = path.substring(firstSlashPos); + return {head: head, tail: tail}; + }; + + /** + * @param str + * @param prefix + * @returns {boolean} true iif str starts with prefix + */ + var startsWith = function (str, prefix) { + return (str.lastIndexOf(prefix, 0) === 0); + }; + + var renderStatic = function (unit, path) { + log.debug('[' + requestId + '] for unit "' + unit + '" a request received for a static file "' + path + '"'); + var staticFile = fuse.getFile(unit, 'public' + path); + if (staticFile.isExists() && !staticFile.isDirectory()) { + response.addHeader('Content-type', getMime(path)); + response.addHeader('Cache-Control', 'public,max-age=12960000'); + staticFile.open('r'); + var stream = staticFile.getStream(); + print(stream); + staticFile.close(); + return true; + } + return false; + }; + + var renderPage = function (path) { + var jagFile; + if (path.indexOf('/', path.length - 1) !== -1) { + jagFile = new File('/pages' + path + 'index.jag'); + } else { + jagFile = new File('/pages' + path + '.jag'); + } + if (jagFile.isExists()) { + include(jagFile.getPath()); + return true; + }else{ + return false; + } + }; + + var renderUnit = function (path) { + var mainUnit = null; + var matchedUnits = fuse.getMatchedUnitDefinitions(); + fuse.addDependencies(matchedUnits); + var zones = fuseState.zones; + + // A map of maps. this is used to ensure same zone is not render twice in to same definition. + // zonesAdded = { titleZone : { zoneFromA : true, zoneFromB : true } } + var zonesAdded = {}; + + for (var i = 0; i < matchedUnits.length; i++) { + var definition = matchedUnits[i]; + + for (var j = 0; j < definition.zones.length; j++) { + var zone = definition.zones[j]; + if (!zones[zone.name]) { + zones[zone.name] = []; + zonesAdded[zone.name] = {}; + } + var zoneKey = zone.origin + ':' + zone.name; // temp unique key to identify zone form a given unit. + if (!zonesAdded[zone.name][zoneKey]) { + var zoneInfo = {unitName: definition.name}; + if (zone.origin != definition.name) { + zoneInfo.originUnitName = zone.origin; + } + zones[zone.name].push(zoneInfo); + zonesAdded[zone.name][zoneKey] = true; + } + } + + } + + var layout = fuseState.layout; + if (layout !== null) { + log.debug( + '[' + requestId + '] request for "' + path + '" will be rendered using layout "' + + layout + '" (defined in "' + mainUnit + '") and zones ' + + stringify(zones) + ); + + var output = handlebars.Handlebars.compileFile(fuse.getLayoutPath(layout))({}); + response.addHeader('Content-type', 'text/html'); + print(output); + return true; + } else { + log.debug( + '[' + requestId + '] request for "' + path + '" will can\'t be rendered, since no layout is defined' + + 'in any of the units ' + stringify(zones)); + return false; + } + }; + + function fileToString(path) { + } + + /** + * convert less file to css and print to output. add '?nocache=true' to force regenerate. + * @param unit name of the unit + * @param path the path to the less file relative to unit root (should start with slash) + * @returns {boolean} is successfully rendered. + */ + function renderLess(unit, path) { + //TODO: fix - incorrect less files makes it respond the old less even if it is nocahce. + log.debug('[' + requestId + '] for unit "' + unit + '" a request received for a less file "' + path + '"'); + var cacheKey = '/tmp/cached_' + unit + path.replace(/[^\w\.-]/g, '_'); + fuseState.currentUnit = unit; + var cachedCss = new File(cacheKey); + + //TODO: move this check to caller function ?? + if (fuseDebug || request.getParameter('nocache') == 'true' || !cachedCss.isExists()) { + var parts = splitFirst(path); + var lessPath = '/public/less' + parts.tail.replace(/\.css$/, '') + '.less'; + var lessFile = fuse.getFile(unit, lessPath); + + if (lessFile.isExists()) { + var x = require('less-rhino-1.7.5.js'); + x.compile([lessFile.getPath(), cacheKey]); + log.debug('[' + requestId + '] for unit "' + unit + '" request for "' + path + '" is cached as "' + cacheKey + '"'); + } + } + + + if (cachedCss.isExists()) { + response.addHeader('Content-type', 'text/css'); + response.addHeader('Cache-Control', 'public,max-age=12960000'); + cachedCss.open('r'); + var stream = cachedCss.getStream(); + print(stream); + cachedCss.close(); + return true; + } + return false; + + } + + +})(); diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/lib/fuse.jag b/modules/distribution/src/repository/jaggeryapps/sensebot/lib/fuse.jag new file mode 100755 index 00000000..597c9970 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/lib/fuse.jag @@ -0,0 +1,29 @@ +<% + +//global object to pass request stat among fuse framework files. +var fuseState = { + zones: {}, + appName: '', + zoneStack: [], + currentUnit: null +}; + +var requestId = function makeId() { + var text = ""; + var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + for (var i = 0; i < 5; i++) + text += possible.charAt(Math.floor(Math.random() * possible.length)); + + return text; +}(); +var fuseDebug = false; +//var fuseDebug = true; + +var handlebars = require('handlebars-helpers.js'); +var fuseRouter = require('fuse-router.js'); +var fuse = require('fuse.js'); + + +fuseRouter.route(); + +%> diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/lib/fuse.js b/modules/distribution/src/repository/jaggeryapps/sensebot/lib/fuse.js new file mode 100755 index 00000000..f802f4be --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/lib/fuse.js @@ -0,0 +1,417 @@ +//public function declarations +var getHbsFile, getFile, toRelativePath, cleanupAncestors, + getUnitPath, getMatchedUnitDefinitions, getZoneDefinition, getUnitDefinition, + getUnitDefinitions, getLayoutPath; + +(function () { + //private + var log = new Log('fuse.core'); + var lookUpTable = null; + var definitions = null; + + var initLookUp = function (definitions) { + if (lookUpTable === null) { + lookUpTable = {}; + for (var i = 0; i < definitions.length; i++) { + var definition = definitions[i]; + lookUpTable[definition.name] = i; + } + } + }; + + var isMatched = function (definition, layout) { + var urlMatch = function (pattern) { + var uriMatcher = new URIMatcher(request.getRequestURI()); + return Boolean(uriMatcher.match('/{appName}' + pattern)); + }; + var permission = function (permissionStr) { + var carbonModule = require("carbon"); + var carbonServer = application.get("carbonServer"); + var carbonUser = session.get("USER"); + if (carbonUser) { + var userManager = new carbonModule.user.UserManager(carbonServer, carbonUser.tenantId); + var user = new carbonModule.user.User(userManager, carbonUser.username); + return user.isAuthorized(permissionStr, "ui.execute"); + } + return false; + }; + var config = {'theme': 'default'}; + var predicateStr = definition.definition.predicate; + if (predicateStr) { + var js = 'function(config,urlMatch,permission,layout){ return ' + predicateStr + ';}'; + return Boolean(eval(js)(config, urlMatch,permission, layout ? layout : NaN)); + } + return false; + }; + + var getAncestorModels = function (unit) { + var unitModel = getUnitDefinition(unit); + var ancestors = [unitModel]; + var parentName; + while ((parentName = unitModel.definition.extends) != null) { + unitModel = getUnitDefinition(parentName); + ancestors.push(unitModel); + } + return ancestors; + }; + + addDependencies = function (unitModels) { + var resolved = {}; + for (var i = 0; i < unitModels.length; i++) { + resolved[unitModels[i].name] = true; + } + + for (i = 0; i < unitModels.length; i++) { + var unitModel = unitModels[i]; + var dependencies = unitModel.definition.dependencies; + if (dependencies) { + for (var j = 0; j < dependencies.length; j++) { + var dependencyName = dependencies[j]; + unitModels.push(getUnitDefinition(dependencyName)); + resolved[dependencyName] = true; + } + } + } + + + }; + + + //public + getMatchedUnitDefinitions = function () { + //TODO: return map not list + var unitDefinitions = getUnitDefinitions(); + var matched = []; + var unMatched = []; + var layout = null; + var mainUnit = null; + + var addToMatched = function (model) { + matched.push(model); + if (model.layout) { + if (layout == null) { + layout = model.layout; + mainUnit = model.name; + } else { + log.warn( + '[' + requestId + '] multiple layouts ' + mainUnit + ':' + + layout + ' vs ' + model.name + ':' + model.layout + ); + } + } + }; + + + // first pass + for (var i = 0; i < unitDefinitions.length; i++) { + var unitDefinition = unitDefinitions[i]; + if (isMatched(unitDefinition)) { + addToMatched(unitDefinition); + } else { + unMatched.push(unitDefinition); + } + } + + fuseState.layout = layout; + + // second pass : we have to do this two passes since we don't know the layout + // first time around + if (layout) { + for (i = 0; i < unMatched.length; i++) { + unitDefinition = unMatched[i]; + if (isMatched(unitDefinition, layout)) { + addToMatched(unitDefinition) + } + } + } + + + var toDelete = []; + + for (i = 0; i < matched.length; i++) { + var ancestors = getAncestorModels(matched[i].name); + for (var j = 1; j < ancestors.length; j++) { + var ancestor = ancestors[j]; + toDelete.push(ancestor.name); + } + } + + + for (i = matched.length - 1; i >= 0; i--) { + //log.info(matched[i].name); + if (toDelete.indexOf(matched[i].name) >= 0) { + matched.splice(i, 1); + } + } + + return matched; + }; + + getUnitDefinition = function (unit) { + var definitions = getUnitDefinitions(); + initLookUp(definitions); + var model = definitions[lookUpTable[unit]]; + if (!model) { + log.warn('[' + requestId + '] unit "' + unit + '" does not exits'); + throw '[' + requestId + '] unit "' + unit + '" does not exits'; + } + return model; + }; + + var flattenAllInheritance = function (unitModels) { + var hasFlattend = {}; + for (var i = 0; i < unitModels.length; i++) { + var model = unitModels[i]; + if (!hasFlattend[model]) { + var ancestors = getAncestorModels(model.name); + for (var j = ancestors.length - 1; j >= 1; j--) { + flattenInheritance(ancestors[j], ancestors[j - 1]); + } + } + } + }; + + var flattenInheritance = function (parent, child) { + var parentZones = parent.zones; + for (var i = 0; i < parentZones.length; i++) { + var parentZone = parentZones[i]; + child.zones.push(parentZone); + } + }; + + getUnitDefinitions = function () { + if (definitions !== null) { + return definitions; + } else { + definitions = []; + } + + var unitDirs = new File('/units').listFiles(); + for (var i = 0; i < unitDirs.length; i++) { + var unitDir = unitDirs[i]; + if (unitDir.isDirectory()) { + + var unitName = unitDir.getName(); + var unitModel = { + name: unitName, + path: unitDir.getPath() + }; + + // unit definition is read form is the .json file. + // if doesn't exits it will be an empty json. + var definitionFile = new File(fuse.getUnitPath(unitName) + '/' + unitName + '.json'); + if (definitionFile.isExists() && !definitionFile.isDirectory()) { + var path = definitionFile.getPath(); + log.debug('[' + requestId + '] reading file "' + path + '"'); + unitModel.definition = require(path); + } else { + log.warn('[' + requestId + '] for unit "' + unitName + '", unable to find a definition file'); + unitModel.definition = {}; + } + + // add the information derived by parsing hbs file to the same model + var hbsMetadata = getHbsMetadata(unitModel); + unitModel.zones = hbsMetadata.zones; + if (hbsMetadata.layout) { + unitModel.layout = hbsMetadata.layout; + } + + definitions.push(unitModel); + } + } + + addPageUnitDefinitions(definitions); + + initLookUp(definitions); + flattenAllInheritance(definitions); + + return definitions; + }; + + addPageUnitDefinitions = function (unitModels, dir) { + var pageFiles = new File(dir || '/pages').listFiles(); + for (var i = 0; i < pageFiles.length; i++) { + var pageFile = pageFiles[i]; + var fileName = pageFile.getName(); + if (pageFile.isDirectory()) { + addPageUnitDefinitions(unitModels, pageFile.getPath()) + } else if (fileName.indexOf('.hbs', fileName.length - 4) !== -1) { // File name ends with '.hbs' + + var isLeaf = true; + //path relative to app root + var relativePath = pageFile.getPath() + .substring(6 + pageFile.getPath().indexOf('/pages/'), pageFile.getPath().length - 4); + + if (relativePath.match(/\/index$/)) { + relativePath = relativePath.replace(/\/index$/, ''); + var parentFile = new File(pageFile.getPath().substr(0, pageFile.getPath().lastIndexOf('/'))); + var hasSiblings = parentFile.listFiles().length != 1; + if (hasSiblings) { + isLeaf = false; + } + } + + //this will be used as a name for the virtual unit, useful for debugging purposes. + var unitName = (relativePath == '' ? 'index' : relativePath.substr(1).replace(/\//, '-') ) + '-page'; + + var predicate = "urlMatch('" + relativePath + "')"; + // leaf is page that can handle multiple URLs. in this case it should have a wildcard at end. + // but since our current matcher doesn't support {/wildcard*} patten, "OR" ( || ) is used + if (isLeaf) { + predicate += " || urlMatch('" + relativePath + "/{+wildcard}')"; + } + var unitModel = { + name: unitName, + + path: pageFile.getPath(), + definition: {predicate: predicate} + }; + var hbsMetadata = getHbsMetadata(unitModel); + unitModel.zones = hbsMetadata.zones; + if (hbsMetadata.layout) { + unitModel.layout = hbsMetadata.layout; + } + + unitModels.push(unitModel); + } + } + }; + + + getLayoutPath = function (layout) { + return '/layouts/' + layout + '.hbs'; + }; + + getHbsFile = function (unit) { + // we determining if it's page unit or a proper unit + // by checking if path ends with '.hbs' + // TODO: improve getFile to do include this logic + if (unit.path.indexOf('.hbs', unit.path.length - 4) !== -1) { + return new File(unit.path); + } else { + return new File(unit.path + '/' + unit.name + '.hbs'); + } + }; + + var getHbsMetadata = function (unit) { + var zoneDef = {'zones': []}; + var hbsFile = getHbsFile(unit); + if (!hbsFile.isExists()) { + return zoneDef; + } + var output = handlebars.Handlebars.compileFile(hbsFile)({}); + var zonesAndLayouts = output.trim().split(/\s+/gm); + for (var i = 0; i < zonesAndLayouts.length; i++) { + var name = zonesAndLayouts[i]; + if (name.lastIndexOf('zone_', 0) === 0) { + zoneDef.zones.push({name: name.substr(5), origin: unit.name}); + } else if (name.lastIndexOf('layout_', 0) === 0) { + zoneDef.layout = name.substr(7); + } + } + return zoneDef; + }; + + + getUnitPath = function (unit) { + return '/units/' + unit; + }; + + cleanupAncestors = function (units) { + var toDelete = {}; + var len = units.length; + for (var i = 0; i < len; i++) { + var unit = units[i]; + if (!toDelete[unit]) { + var ancestors = getAncestorModels(unit.name); + for (var j = 1; j < ancestors.length; j++) { + toDelete[ancestors[j].name] = unit; + } + } + } + while (len--) { + if (toDelete[units[len]]) { + log.debug( + '[' + requestId + '] unit "' + units[len] + + '" is overridden by "' + toDelete[units[len]] + '"' + ); + units.splice(len, 1); + } + } + }; + + toRelativePath = function (path) { + var start = 0; + if (path.lastIndexOf('/units/', 0) == 0) { + start = 7; // len('/units/') + } + var slashPos = path.indexOf('/', 7); + return { + unit: path.substring(start, slashPos), + path: path.substr(slashPos) + } + }; + + /** + * Get a file inside a unit by relative path. if the file is not available in the given unit, + * the closest ancestor's file will be returned. if an optional suffix is used the relative path is + * calculated as ( path + < unit name > + opt_suffix ). if no such a file exists a returned file object will + * point to provided unit's non-existing file location (not to any ancestors). + * + * @param unitName name of the unit + * @param path path relative to unit root. + * @param opt_suffix + * @returns {File} + */ + getFile = function (unitName, path, opt_suffix) { + var slashPath = ((path[0] === '/') ? '' : '/') + path; + var selfFileName = ''; + var fileName = ''; + if (opt_suffix) { + selfFileName = unitName + opt_suffix; + slashPath = slashPath + ((slashPath[slashPath.length - 1] === '/') ? '' : '/'); + } + + //TODO: remove this hack that makes in page-unit, any file is same + var unitDef = getUnitDefinition(unitName); + if (unitDef.path.indexOf('.hbs', unitDef.path.length - 4) !== -1) { + if (opt_suffix.indexOf('.hbs', opt_suffix.length - 4) !== -1) { + return new File(unitDef.path); + } else { + return new File(unitDef.path.replace(/.hbs$/, opt_suffix)); + } + } + + var selfFile = new File(getUnitPath(unitName) + slashPath + selfFileName); + if (selfFile.isExists()) { + log.debug( + '[' + requestId + '] for unit "' + unitName + '" file resolved : "' + + slashPath + selfFileName + '" -> "' + selfFile.getPath() + '"' + ); + + return selfFile; + } + + var ancestors = getAncestorModels(unitName); + for (var i = 1; i < ancestors.length; i++) { + var ancestorName = ancestors[i].name; + if (opt_suffix) { + fileName = ancestorName + opt_suffix; + } + var file = new File(getUnitPath(ancestorName) + slashPath + fileName); + if (file.isExists()) { + log.debug( + '[' + requestId + '] for unit "' + unitName + '" file resolved : "' + + slashPath + selfFileName + '" -> "' + file.getPath() + '"' + ); + return file; + } + } + log.debug( + '[' + requestId + '] for unit "' + unitName + '" (non-excising) file resolved : "' + + slashPath + selfFileName + '" -> "' + selfFile.getPath() + '"' + ); + return selfFile; + }; + +})(); \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/lib/handlebars-helpers.js b/modules/distribution/src/repository/jaggeryapps/sensebot/lib/handlebars-helpers.js new file mode 100755 index 00000000..80342019 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/lib/handlebars-helpers.js @@ -0,0 +1,194 @@ +var log = new Log('fuse.handlebars'); +//TODO: create a different set of helpers for init parsing + +var Handlebars = require('handlebars-v2.0.0.js').Handlebars; +var USER_SESSION_KEY = "USER"; +var getScope = function (unit,configs) { + var jsFile = fuse.getFile(unit, '', '.js'); + var templateConfigs = configs || {}; + var script; + var onRequestCb = function(){}; //Assume that onRequest function will not be defined by the user + var viewModel = {}; + var cbResult; + if (jsFile.isExists()) { + script = require(jsFile.getPath()); + //Eagerly make the viewModel the template configs + viewModel = templateConfigs; + //Check if the unit author has specified an onRequest + //callback + if(script.hasOwnProperty('onRequest')){ + script.app = { + url: '/' + fuseState.appName, + publicURL: '/' + fuseState.appName + '/public/' + unit, + "class": unit + '-unit' + }; + onRequestCb = script.onRequest; + cbResult = onRequestCb(templateConfigs); + log.debug("passing configs to unit "+unit+" configs: "+stringify(templateConfigs)); + //If the execution does not yield an object we will print + //a warning as the unit author may have forgotten to return a data object + if(cbResult===undefined){ + cbResult = {}; //Give an empty data object + log.warn('[' + requestId + '] unit "' + unit + '" has a onRequest method which does not return a value.This may lead to the ' + +'unit not been rendered correctly.'); + } + viewModel = cbResult; + } + } + else{ + //If there is no script then the view should get the configurations + //passed in the unit call + viewModel = templateConfigs; + } + viewModel.app = { + url: '/' + fuseState.appName + }; + viewModel.self = { + publicURL: '/' + fuseState.appName + '/public/' + unit, + "class": unit + '-unit' + }; + return viewModel; +}; + +Handlebars.innerZones = []; +Handlebars.innerZonesFromUnit = null; + +Handlebars.registerHelper('defineZone', function (zoneName, zoneContent) { + var result = ''; + var zone = Handlebars.Utils.escapeExpression(zoneName); + fuseState.zoneStack.push(zone); + var unitsToRender = fuseState.zones[zone] || []; + + if (Handlebars.innerZones.length > 0) { + unitsToRender = fuseState.zones[Handlebars.innerZones[0]] || []; + } + + // if there is no one overriding, then display inline zone + if (zoneContent['fn'] && unitsToRender.length == 0) { + return zoneContent.fn(this).trim(); + } + + for (var i = 0; i < unitsToRender.length; i++) { + var unit = unitsToRender[i]; + if (Handlebars.innerZonesFromUnit == null || Handlebars.innerZonesFromUnit.unitName == unit.unitName) { + var template = fuse.getFile(unit.originUnitName || unit.unitName, '', '.hbs'); + log.debug('[' + requestId + '] for zone "' + zone + '" including template :"' + template.getPath() + '"'); + result += Handlebars.compileFile(template)(getScope(unit.unitName, zoneContent.data.root)); + } + } + + // we go to inner zones if result is empty, what we should really do it + // if matched zone is fully made of sub-zones. this is a hack to + // make it easy to implement. + if (result.trim().length == 0 && zoneContent['fn']) { + Handlebars.innerZones.push(zoneName); + for (i = 0; i < unitsToRender.length; i++) { + unit = unitsToRender[i]; + Handlebars.innerZonesFromUnit = unit; + result += zoneContent.fn(this).trim(); + Handlebars.innerZonesFromUnit = null; + } + Handlebars.innerZones.pop(); + return result; + } + + fuseState.zoneStack.pop(); + return new Handlebars.SafeString(result); +}); + +Handlebars.registerHelper('zone', function (zoneName, zoneContent) { + var currentZone = fuseState.zoneStack[fuseState.zoneStack.length - 1]; + if (currentZone == null) { + return 'zone_' + zoneName + ' '; + } + + // if it's exact zone match or if any in inner zone matches we render zone. + // this second condition is a hack. what we should really do is to keep another stack, + // and only match with the peek of that stack and always fill it with next in innerZone stack. + if (zoneName == currentZone || Handlebars.innerZones.indexOf(zoneName) >= 0) { + return zoneContent.fn(this).trim(); + } else { + return ''; + } +}); + +Handlebars.registerHelper('layout', function (layoutName) { + var currentZone = fuseState.zoneStack[fuseState.zoneStack.length - 1]; + if (currentZone == null) { + return 'layout_' + layoutName; + } else { + return ''; + } +}); + +Handlebars.registerHelper('authorized', function () { + var currentZone = fuseState.zoneStack[fuseState.zoneStack.length - 1]; + if (currentZone == null) { + return ''; + } else { + var loggedUser = session.get(USER_SESSION_KEY); + if(loggedUser == null){ + response.sendRedirect("/"+ fuseState.appName + "/login"); + exit(); + } + } +}); + +Handlebars.registerHelper('unit', function (unitName,options) { + var unitDef = fuse.getUnitDefinition(unitName); + var baseUnit = null; + var templateConfigs = options.hash || {}; + for (var i = 0; i < unitDef.zones.length; i++) { + var zone = unitDef.zones[i]; + if (zone.name == 'main') { + baseUnit = zone.origin; + } else { + var golbalZone = fuseState.zones[zone.name]; + if (!golbalZone) { + fuseState.zones[zone.name] = [{"unitName": unitName}]; + } else { + fuseState.zones[zone.name].push({"unitName": unitName}); + } + } + } + if (baseUnit == null) { + log.error('unit does not have a main zone'); + } + //TODO warn when unspecified decencies are included. + fuseState.zoneStack.push('main'); + var template = fuse.getFile(baseUnit, '', '.hbs'); + log.debug('[' + requestId + '] including "' + baseUnit + '"'+" with configs "+stringify(templateConfigs)); + var result = new Handlebars.SafeString(Handlebars.compileFile(template)(getScope(baseUnit,templateConfigs))); + fuseState.zoneStack.pop(); + return result; +}); + +Handlebars.compileFile = function (file) { + //TODO: remove this overloaded argument + var f = (typeof file === 'string') ? new File(file) : file; + + if (!Handlebars.cache) { + Handlebars.cache = {}; + } + + if (Handlebars.cache[f.getPath()] != null) { + return Handlebars.cache[f.getPath()]; + } + + f.open('r'); + log.debug('[' + requestId + '] reading file "' + f.getPath() + '"'); + var content = f.readAll().trim(); + f.close(); + var compiled = Handlebars.compile(content); + Handlebars.cache[f.getPath()] = compiled; + return compiled; +}; +Handlebars.registerHelper('equal', function(lvalue, rvalue, options) { + if (arguments.length < 3) + throw new Error("Handlebars Helper equal needs 2 parameters"); + if( lvalue!=rvalue ) { + return options.inverse(this); + } else { + return options.fn(this); + } +}); diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/lib/handlebars-v2.0.0.js b/modules/distribution/src/repository/jaggeryapps/sensebot/lib/handlebars-v2.0.0.js new file mode 100755 index 00000000..f826bbfd --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/lib/handlebars-v2.0.0.js @@ -0,0 +1,3079 @@ +/*! + + handlebars v2.0.0 + +Copyright (C) 2011-2014 by Yehuda Katz + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +@license +*/ +/* exported Handlebars */ +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + define([], factory); + } else if (typeof exports === 'object') { + module.exports = factory(); + } else { + root.Handlebars = root.Handlebars || factory(); + } +}(this, function () { +// handlebars/safe-string.js +var __module4__ = (function() { + "use strict"; + var __exports__; + // Build out our basic SafeString type + function SafeString(string) { + this.string = string; + } + + SafeString.prototype.toString = function() { + return "" + this.string; + }; + + __exports__ = SafeString; + return __exports__; +})(); + +// handlebars/utils.js +var __module3__ = (function(__dependency1__) { + "use strict"; + var __exports__ = {}; + /*jshint -W004 */ + var SafeString = __dependency1__; + + var escape = { + "&": "&", + "<": "<", + ">": ">", + '"': """, + "'": "'", + "`": "`" + }; + + var badChars = /[&<>"'`]/g; + var possible = /[&<>"'`]/; + + function escapeChar(chr) { + return escape[chr]; + } + + function extend(obj /* , ...source */) { + for (var i = 1; i < arguments.length; i++) { + for (var key in arguments[i]) { + if (Object.prototype.hasOwnProperty.call(arguments[i], key)) { + obj[key] = arguments[i][key]; + } + } + } + + return obj; + } + + __exports__.extend = extend;var toString = Object.prototype.toString; + __exports__.toString = toString; + // Sourced from lodash + // https://github.com/bestiejs/lodash/blob/master/LICENSE.txt + var isFunction = function(value) { + return typeof value === 'function'; + }; + // fallback for older versions of Chrome and Safari + /* istanbul ignore next */ + if (isFunction(/x/)) { + isFunction = function(value) { + return typeof value === 'function' && toString.call(value) === '[object Function]'; + }; + } + var isFunction; + __exports__.isFunction = isFunction; + /* istanbul ignore next */ + var isArray = Array.isArray || function(value) { + return (value && typeof value === 'object') ? toString.call(value) === '[object Array]' : false; + }; + __exports__.isArray = isArray; + + function escapeExpression(string) { + // don't escape SafeStrings, since they're already safe + if (string instanceof SafeString) { + return string.toString(); + } else if (string == null) { + return ""; + } else if (!string) { + return string + ''; + } + + // Force a string conversion as this will be done by the append regardless and + // the regex test will do this transparently behind the scenes, causing issues if + // an object's to string has escaped characters in it. + string = "" + string; + + if(!possible.test(string)) { return string; } + return string.replace(badChars, escapeChar); + } + + __exports__.escapeExpression = escapeExpression;function isEmpty(value) { + if (!value && value !== 0) { + return true; + } else if (isArray(value) && value.length === 0) { + return true; + } else { + return false; + } + } + + __exports__.isEmpty = isEmpty;function appendContextPath(contextPath, id) { + return (contextPath ? contextPath + '.' : '') + id; + } + + __exports__.appendContextPath = appendContextPath; + return __exports__; +})(__module4__); + +// handlebars/exception.js +var __module5__ = (function() { + "use strict"; + var __exports__; + + var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack']; + + function Exception(message, node) { + var line; + if (node && node.firstLine) { + line = node.firstLine; + + message += ' - ' + line + ':' + node.firstColumn; + } + + var tmp = Error.prototype.constructor.call(this, message); + + // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work. + for (var idx = 0; idx < errorProps.length; idx++) { + this[errorProps[idx]] = tmp[errorProps[idx]]; + } + + if (line) { + this.lineNumber = line; + this.column = node.firstColumn; + } + } + + Exception.prototype = new Error(); + + __exports__ = Exception; + return __exports__; +})(); + +// handlebars/base.js +var __module2__ = (function(__dependency1__, __dependency2__) { + "use strict"; + var __exports__ = {}; + var Utils = __dependency1__; + var Exception = __dependency2__; + + var VERSION = "2.0.0"; + __exports__.VERSION = VERSION;var COMPILER_REVISION = 6; + __exports__.COMPILER_REVISION = COMPILER_REVISION; + var REVISION_CHANGES = { + 1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it + 2: '== 1.0.0-rc.3', + 3: '== 1.0.0-rc.4', + 4: '== 1.x.x', + 5: '== 2.0.0-alpha.x', + 6: '>= 2.0.0-beta.1' + }; + __exports__.REVISION_CHANGES = REVISION_CHANGES; + var isArray = Utils.isArray, + isFunction = Utils.isFunction, + toString = Utils.toString, + objectType = '[object Object]'; + + function HandlebarsEnvironment(helpers, partials) { + this.helpers = helpers || {}; + this.partials = partials || {}; + + registerDefaultHelpers(this); + } + + __exports__.HandlebarsEnvironment = HandlebarsEnvironment;HandlebarsEnvironment.prototype = { + constructor: HandlebarsEnvironment, + + logger: logger, + log: log, + + registerHelper: function(name, fn) { + if (toString.call(name) === objectType) { + if (fn) { throw new Exception('Arg not supported with multiple helpers'); } + Utils.extend(this.helpers, name); + } else { + this.helpers[name] = fn; + } + }, + unregisterHelper: function(name) { + delete this.helpers[name]; + }, + + registerPartial: function(name, partial) { + if (toString.call(name) === objectType) { + Utils.extend(this.partials, name); + } else { + this.partials[name] = partial; + } + }, + unregisterPartial: function(name) { + delete this.partials[name]; + } + }; + + function registerDefaultHelpers(instance) { + instance.registerHelper('helperMissing', function(/* [args, ]options */) { + if(arguments.length === 1) { + // A missing field in a {{foo}} constuct. + return undefined; + } else { + // Someone is actually trying to call something, blow up. + throw new Exception("Missing helper: '" + arguments[arguments.length-1].name + "'"); + } + }); + + instance.registerHelper('blockHelperMissing', function(context, options) { + var inverse = options.inverse, + fn = options.fn; + + if(context === true) { + return fn(this); + } else if(context === false || context == null) { + return inverse(this); + } else if (isArray(context)) { + if(context.length > 0) { + if (options.ids) { + options.ids = [options.name]; + } + + return instance.helpers.each(context, options); + } else { + return inverse(this); + } + } else { + if (options.data && options.ids) { + var data = createFrame(options.data); + data.contextPath = Utils.appendContextPath(options.data.contextPath, options.name); + options = {data: data}; + } + + return fn(context, options); + } + }); + + instance.registerHelper('each', function(context, options) { + if (!options) { + throw new Exception('Must pass iterator to #each'); + } + + var fn = options.fn, inverse = options.inverse; + var i = 0, ret = "", data; + + var contextPath; + if (options.data && options.ids) { + contextPath = Utils.appendContextPath(options.data.contextPath, options.ids[0]) + '.'; + } + + if (isFunction(context)) { context = context.call(this); } + + if (options.data) { + data = createFrame(options.data); + } + + if(context && typeof context === 'object') { + if (isArray(context)) { + for(var j = context.length; i 0) { + throw new Exception("Invalid path: " + original, this); + } else if (part === "..") { + depth++; + depthString += '../'; + } else { + this.isScoped = true; + } + } else { + dig.push(part); + } + } + + this.original = original; + this.parts = dig; + this.string = dig.join('.'); + this.depth = depth; + this.idName = depthString + this.string; + + // an ID is simple if it only has one part, and that part is not + // `..` or `this`. + this.isSimple = parts.length === 1 && !this.isScoped && depth === 0; + + this.stringModeValue = this.string; + }, + + PartialNameNode: function(name, locInfo) { + LocationInfo.call(this, locInfo); + this.type = "PARTIAL_NAME"; + this.name = name.original; + }, + + DataNode: function(id, locInfo) { + LocationInfo.call(this, locInfo); + this.type = "DATA"; + this.id = id; + this.stringModeValue = id.stringModeValue; + this.idName = '@' + id.stringModeValue; + }, + + StringNode: function(string, locInfo) { + LocationInfo.call(this, locInfo); + this.type = "STRING"; + this.original = + this.string = + this.stringModeValue = string; + }, + + NumberNode: function(number, locInfo) { + LocationInfo.call(this, locInfo); + this.type = "NUMBER"; + this.original = + this.number = number; + this.stringModeValue = Number(number); + }, + + BooleanNode: function(bool, locInfo) { + LocationInfo.call(this, locInfo); + this.type = "BOOLEAN"; + this.bool = bool; + this.stringModeValue = bool === "true"; + }, + + CommentNode: function(comment, locInfo) { + LocationInfo.call(this, locInfo); + this.type = "comment"; + this.comment = comment; + + this.strip = { + inlineStandalone: true + }; + } + }; + + + // Must be exported as an object rather than the root of the module as the jison lexer + // most modify the object to operate properly. + __exports__ = AST; + return __exports__; +})(__module5__); + +// handlebars/compiler/parser.js +var __module9__ = (function() { + "use strict"; + var __exports__; + /* jshint ignore:start */ + /* istanbul ignore next */ + /* Jison generated parser */ + var handlebars = (function(){ + var parser = {trace: function trace() { }, + yy: {}, + symbols_: {"error":2,"root":3,"program":4,"EOF":5,"program_repetition0":6,"statement":7,"mustache":8,"block":9,"rawBlock":10,"partial":11,"CONTENT":12,"COMMENT":13,"openRawBlock":14,"END_RAW_BLOCK":15,"OPEN_RAW_BLOCK":16,"sexpr":17,"CLOSE_RAW_BLOCK":18,"openBlock":19,"block_option0":20,"closeBlock":21,"openInverse":22,"block_option1":23,"OPEN_BLOCK":24,"CLOSE":25,"OPEN_INVERSE":26,"inverseAndProgram":27,"INVERSE":28,"OPEN_ENDBLOCK":29,"path":30,"OPEN":31,"OPEN_UNESCAPED":32,"CLOSE_UNESCAPED":33,"OPEN_PARTIAL":34,"partialName":35,"param":36,"partial_option0":37,"partial_option1":38,"sexpr_repetition0":39,"sexpr_option0":40,"dataName":41,"STRING":42,"NUMBER":43,"BOOLEAN":44,"OPEN_SEXPR":45,"CLOSE_SEXPR":46,"hash":47,"hash_repetition_plus0":48,"hashSegment":49,"ID":50,"EQUALS":51,"DATA":52,"pathSegments":53,"SEP":54,"$accept":0,"$end":1}, + terminals_: {2:"error",5:"EOF",12:"CONTENT",13:"COMMENT",15:"END_RAW_BLOCK",16:"OPEN_RAW_BLOCK",18:"CLOSE_RAW_BLOCK",24:"OPEN_BLOCK",25:"CLOSE",26:"OPEN_INVERSE",28:"INVERSE",29:"OPEN_ENDBLOCK",31:"OPEN",32:"OPEN_UNESCAPED",33:"CLOSE_UNESCAPED",34:"OPEN_PARTIAL",42:"STRING",43:"NUMBER",44:"BOOLEAN",45:"OPEN_SEXPR",46:"CLOSE_SEXPR",50:"ID",51:"EQUALS",52:"DATA",54:"SEP"}, + productions_: [0,[3,2],[4,1],[7,1],[7,1],[7,1],[7,1],[7,1],[7,1],[10,3],[14,3],[9,4],[9,4],[19,3],[22,3],[27,2],[21,3],[8,3],[8,3],[11,5],[11,4],[17,3],[17,1],[36,1],[36,1],[36,1],[36,1],[36,1],[36,3],[47,1],[49,3],[35,1],[35,1],[35,1],[41,2],[30,1],[53,3],[53,1],[6,0],[6,2],[20,0],[20,1],[23,0],[23,1],[37,0],[37,1],[38,0],[38,1],[39,0],[39,2],[40,0],[40,1],[48,1],[48,2]], + performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) { + + var $0 = $$.length - 1; + switch (yystate) { + case 1: yy.prepareProgram($$[$0-1].statements, true); return $$[$0-1]; + break; + case 2:this.$ = new yy.ProgramNode(yy.prepareProgram($$[$0]), {}, this._$); + break; + case 3:this.$ = $$[$0]; + break; + case 4:this.$ = $$[$0]; + break; + case 5:this.$ = $$[$0]; + break; + case 6:this.$ = $$[$0]; + break; + case 7:this.$ = new yy.ContentNode($$[$0], this._$); + break; + case 8:this.$ = new yy.CommentNode($$[$0], this._$); + break; + case 9:this.$ = new yy.RawBlockNode($$[$0-2], $$[$0-1], $$[$0], this._$); + break; + case 10:this.$ = new yy.MustacheNode($$[$0-1], null, '', '', this._$); + break; + case 11:this.$ = yy.prepareBlock($$[$0-3], $$[$0-2], $$[$0-1], $$[$0], false, this._$); + break; + case 12:this.$ = yy.prepareBlock($$[$0-3], $$[$0-2], $$[$0-1], $$[$0], true, this._$); + break; + case 13:this.$ = new yy.MustacheNode($$[$0-1], null, $$[$0-2], yy.stripFlags($$[$0-2], $$[$0]), this._$); + break; + case 14:this.$ = new yy.MustacheNode($$[$0-1], null, $$[$0-2], yy.stripFlags($$[$0-2], $$[$0]), this._$); + break; + case 15:this.$ = { strip: yy.stripFlags($$[$0-1], $$[$0-1]), program: $$[$0] }; + break; + case 16:this.$ = {path: $$[$0-1], strip: yy.stripFlags($$[$0-2], $$[$0])}; + break; + case 17:this.$ = new yy.MustacheNode($$[$0-1], null, $$[$0-2], yy.stripFlags($$[$0-2], $$[$0]), this._$); + break; + case 18:this.$ = new yy.MustacheNode($$[$0-1], null, $$[$0-2], yy.stripFlags($$[$0-2], $$[$0]), this._$); + break; + case 19:this.$ = new yy.PartialNode($$[$0-3], $$[$0-2], $$[$0-1], yy.stripFlags($$[$0-4], $$[$0]), this._$); + break; + case 20:this.$ = new yy.PartialNode($$[$0-2], undefined, $$[$0-1], yy.stripFlags($$[$0-3], $$[$0]), this._$); + break; + case 21:this.$ = new yy.SexprNode([$$[$0-2]].concat($$[$0-1]), $$[$0], this._$); + break; + case 22:this.$ = new yy.SexprNode([$$[$0]], null, this._$); + break; + case 23:this.$ = $$[$0]; + break; + case 24:this.$ = new yy.StringNode($$[$0], this._$); + break; + case 25:this.$ = new yy.NumberNode($$[$0], this._$); + break; + case 26:this.$ = new yy.BooleanNode($$[$0], this._$); + break; + case 27:this.$ = $$[$0]; + break; + case 28:$$[$0-1].isHelper = true; this.$ = $$[$0-1]; + break; + case 29:this.$ = new yy.HashNode($$[$0], this._$); + break; + case 30:this.$ = [$$[$0-2], $$[$0]]; + break; + case 31:this.$ = new yy.PartialNameNode($$[$0], this._$); + break; + case 32:this.$ = new yy.PartialNameNode(new yy.StringNode($$[$0], this._$), this._$); + break; + case 33:this.$ = new yy.PartialNameNode(new yy.NumberNode($$[$0], this._$)); + break; + case 34:this.$ = new yy.DataNode($$[$0], this._$); + break; + case 35:this.$ = new yy.IdNode($$[$0], this._$); + break; + case 36: $$[$0-2].push({part: $$[$0], separator: $$[$0-1]}); this.$ = $$[$0-2]; + break; + case 37:this.$ = [{part: $$[$0]}]; + break; + case 38:this.$ = []; + break; + case 39:$$[$0-1].push($$[$0]); + break; + case 48:this.$ = []; + break; + case 49:$$[$0-1].push($$[$0]); + break; + case 52:this.$ = [$$[$0]]; + break; + case 53:$$[$0-1].push($$[$0]); + break; + } + }, + table: [{3:1,4:2,5:[2,38],6:3,12:[2,38],13:[2,38],16:[2,38],24:[2,38],26:[2,38],31:[2,38],32:[2,38],34:[2,38]},{1:[3]},{5:[1,4]},{5:[2,2],7:5,8:6,9:7,10:8,11:9,12:[1,10],13:[1,11],14:16,16:[1,20],19:14,22:15,24:[1,18],26:[1,19],28:[2,2],29:[2,2],31:[1,12],32:[1,13],34:[1,17]},{1:[2,1]},{5:[2,39],12:[2,39],13:[2,39],16:[2,39],24:[2,39],26:[2,39],28:[2,39],29:[2,39],31:[2,39],32:[2,39],34:[2,39]},{5:[2,3],12:[2,3],13:[2,3],16:[2,3],24:[2,3],26:[2,3],28:[2,3],29:[2,3],31:[2,3],32:[2,3],34:[2,3]},{5:[2,4],12:[2,4],13:[2,4],16:[2,4],24:[2,4],26:[2,4],28:[2,4],29:[2,4],31:[2,4],32:[2,4],34:[2,4]},{5:[2,5],12:[2,5],13:[2,5],16:[2,5],24:[2,5],26:[2,5],28:[2,5],29:[2,5],31:[2,5],32:[2,5],34:[2,5]},{5:[2,6],12:[2,6],13:[2,6],16:[2,6],24:[2,6],26:[2,6],28:[2,6],29:[2,6],31:[2,6],32:[2,6],34:[2,6]},{5:[2,7],12:[2,7],13:[2,7],16:[2,7],24:[2,7],26:[2,7],28:[2,7],29:[2,7],31:[2,7],32:[2,7],34:[2,7]},{5:[2,8],12:[2,8],13:[2,8],16:[2,8],24:[2,8],26:[2,8],28:[2,8],29:[2,8],31:[2,8],32:[2,8],34:[2,8]},{17:21,30:22,41:23,50:[1,26],52:[1,25],53:24},{17:27,30:22,41:23,50:[1,26],52:[1,25],53:24},{4:28,6:3,12:[2,38],13:[2,38],16:[2,38],24:[2,38],26:[2,38],28:[2,38],29:[2,38],31:[2,38],32:[2,38],34:[2,38]},{4:29,6:3,12:[2,38],13:[2,38],16:[2,38],24:[2,38],26:[2,38],28:[2,38],29:[2,38],31:[2,38],32:[2,38],34:[2,38]},{12:[1,30]},{30:32,35:31,42:[1,33],43:[1,34],50:[1,26],53:24},{17:35,30:22,41:23,50:[1,26],52:[1,25],53:24},{17:36,30:22,41:23,50:[1,26],52:[1,25],53:24},{17:37,30:22,41:23,50:[1,26],52:[1,25],53:24},{25:[1,38]},{18:[2,48],25:[2,48],33:[2,48],39:39,42:[2,48],43:[2,48],44:[2,48],45:[2,48],46:[2,48],50:[2,48],52:[2,48]},{18:[2,22],25:[2,22],33:[2,22],46:[2,22]},{18:[2,35],25:[2,35],33:[2,35],42:[2,35],43:[2,35],44:[2,35],45:[2,35],46:[2,35],50:[2,35],52:[2,35],54:[1,40]},{30:41,50:[1,26],53:24},{18:[2,37],25:[2,37],33:[2,37],42:[2,37],43:[2,37],44:[2,37],45:[2,37],46:[2,37],50:[2,37],52:[2,37],54:[2,37]},{33:[1,42]},{20:43,27:44,28:[1,45],29:[2,40]},{23:46,27:47,28:[1,45],29:[2,42]},{15:[1,48]},{25:[2,46],30:51,36:49,38:50,41:55,42:[1,52],43:[1,53],44:[1,54],45:[1,56],47:57,48:58,49:60,50:[1,59],52:[1,25],53:24},{25:[2,31],42:[2,31],43:[2,31],44:[2,31],45:[2,31],50:[2,31],52:[2,31]},{25:[2,32],42:[2,32],43:[2,32],44:[2,32],45:[2,32],50:[2,32],52:[2,32]},{25:[2,33],42:[2,33],43:[2,33],44:[2,33],45:[2,33],50:[2,33],52:[2,33]},{25:[1,61]},{25:[1,62]},{18:[1,63]},{5:[2,17],12:[2,17],13:[2,17],16:[2,17],24:[2,17],26:[2,17],28:[2,17],29:[2,17],31:[2,17],32:[2,17],34:[2,17]},{18:[2,50],25:[2,50],30:51,33:[2,50],36:65,40:64,41:55,42:[1,52],43:[1,53],44:[1,54],45:[1,56],46:[2,50],47:66,48:58,49:60,50:[1,59],52:[1,25],53:24},{50:[1,67]},{18:[2,34],25:[2,34],33:[2,34],42:[2,34],43:[2,34],44:[2,34],45:[2,34],46:[2,34],50:[2,34],52:[2,34]},{5:[2,18],12:[2,18],13:[2,18],16:[2,18],24:[2,18],26:[2,18],28:[2,18],29:[2,18],31:[2,18],32:[2,18],34:[2,18]},{21:68,29:[1,69]},{29:[2,41]},{4:70,6:3,12:[2,38],13:[2,38],16:[2,38],24:[2,38],26:[2,38],29:[2,38],31:[2,38],32:[2,38],34:[2,38]},{21:71,29:[1,69]},{29:[2,43]},{5:[2,9],12:[2,9],13:[2,9],16:[2,9],24:[2,9],26:[2,9],28:[2,9],29:[2,9],31:[2,9],32:[2,9],34:[2,9]},{25:[2,44],37:72,47:73,48:58,49:60,50:[1,74]},{25:[1,75]},{18:[2,23],25:[2,23],33:[2,23],42:[2,23],43:[2,23],44:[2,23],45:[2,23],46:[2,23],50:[2,23],52:[2,23]},{18:[2,24],25:[2,24],33:[2,24],42:[2,24],43:[2,24],44:[2,24],45:[2,24],46:[2,24],50:[2,24],52:[2,24]},{18:[2,25],25:[2,25],33:[2,25],42:[2,25],43:[2,25],44:[2,25],45:[2,25],46:[2,25],50:[2,25],52:[2,25]},{18:[2,26],25:[2,26],33:[2,26],42:[2,26],43:[2,26],44:[2,26],45:[2,26],46:[2,26],50:[2,26],52:[2,26]},{18:[2,27],25:[2,27],33:[2,27],42:[2,27],43:[2,27],44:[2,27],45:[2,27],46:[2,27],50:[2,27],52:[2,27]},{17:76,30:22,41:23,50:[1,26],52:[1,25],53:24},{25:[2,47]},{18:[2,29],25:[2,29],33:[2,29],46:[2,29],49:77,50:[1,74]},{18:[2,37],25:[2,37],33:[2,37],42:[2,37],43:[2,37],44:[2,37],45:[2,37],46:[2,37],50:[2,37],51:[1,78],52:[2,37],54:[2,37]},{18:[2,52],25:[2,52],33:[2,52],46:[2,52],50:[2,52]},{12:[2,13],13:[2,13],16:[2,13],24:[2,13],26:[2,13],28:[2,13],29:[2,13],31:[2,13],32:[2,13],34:[2,13]},{12:[2,14],13:[2,14],16:[2,14],24:[2,14],26:[2,14],28:[2,14],29:[2,14],31:[2,14],32:[2,14],34:[2,14]},{12:[2,10]},{18:[2,21],25:[2,21],33:[2,21],46:[2,21]},{18:[2,49],25:[2,49],33:[2,49],42:[2,49],43:[2,49],44:[2,49],45:[2,49],46:[2,49],50:[2,49],52:[2,49]},{18:[2,51],25:[2,51],33:[2,51],46:[2,51]},{18:[2,36],25:[2,36],33:[2,36],42:[2,36],43:[2,36],44:[2,36],45:[2,36],46:[2,36],50:[2,36],52:[2,36],54:[2,36]},{5:[2,11],12:[2,11],13:[2,11],16:[2,11],24:[2,11],26:[2,11],28:[2,11],29:[2,11],31:[2,11],32:[2,11],34:[2,11]},{30:79,50:[1,26],53:24},{29:[2,15]},{5:[2,12],12:[2,12],13:[2,12],16:[2,12],24:[2,12],26:[2,12],28:[2,12],29:[2,12],31:[2,12],32:[2,12],34:[2,12]},{25:[1,80]},{25:[2,45]},{51:[1,78]},{5:[2,20],12:[2,20],13:[2,20],16:[2,20],24:[2,20],26:[2,20],28:[2,20],29:[2,20],31:[2,20],32:[2,20],34:[2,20]},{46:[1,81]},{18:[2,53],25:[2,53],33:[2,53],46:[2,53],50:[2,53]},{30:51,36:82,41:55,42:[1,52],43:[1,53],44:[1,54],45:[1,56],50:[1,26],52:[1,25],53:24},{25:[1,83]},{5:[2,19],12:[2,19],13:[2,19],16:[2,19],24:[2,19],26:[2,19],28:[2,19],29:[2,19],31:[2,19],32:[2,19],34:[2,19]},{18:[2,28],25:[2,28],33:[2,28],42:[2,28],43:[2,28],44:[2,28],45:[2,28],46:[2,28],50:[2,28],52:[2,28]},{18:[2,30],25:[2,30],33:[2,30],46:[2,30],50:[2,30]},{5:[2,16],12:[2,16],13:[2,16],16:[2,16],24:[2,16],26:[2,16],28:[2,16],29:[2,16],31:[2,16],32:[2,16],34:[2,16]}], + defaultActions: {4:[2,1],44:[2,41],47:[2,43],57:[2,47],63:[2,10],70:[2,15],73:[2,45]}, + parseError: function parseError(str, hash) { + throw new Error(str); + }, + parse: function parse(input) { + var self = this, stack = [0], vstack = [null], lstack = [], table = this.table, yytext = "", yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1; + this.lexer.setInput(input); + this.lexer.yy = this.yy; + this.yy.lexer = this.lexer; + this.yy.parser = this; + if (typeof this.lexer.yylloc == "undefined") + this.lexer.yylloc = {}; + var yyloc = this.lexer.yylloc; + lstack.push(yyloc); + var ranges = this.lexer.options && this.lexer.options.ranges; + if (typeof this.yy.parseError === "function") + this.parseError = this.yy.parseError; + function popStack(n) { + stack.length = stack.length - 2 * n; + vstack.length = vstack.length - n; + lstack.length = lstack.length - n; + } + function lex() { + var token; + token = self.lexer.lex() || 1; + if (typeof token !== "number") { + token = self.symbols_[token] || token; + } + return token; + } + var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected; + while (true) { + state = stack[stack.length - 1]; + if (this.defaultActions[state]) { + action = this.defaultActions[state]; + } else { + if (symbol === null || typeof symbol == "undefined") { + symbol = lex(); + } + action = table[state] && table[state][symbol]; + } + if (typeof action === "undefined" || !action.length || !action[0]) { + var errStr = ""; + if (!recovering) { + expected = []; + for (p in table[state]) + if (this.terminals_[p] && p > 2) { + expected.push("'" + this.terminals_[p] + "'"); + } + if (this.lexer.showPosition) { + errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + (this.terminals_[symbol] || symbol) + "'"; + } else { + errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == 1?"end of input":"'" + (this.terminals_[symbol] || symbol) + "'"); + } + this.parseError(errStr, {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected}); + } + } + if (action[0] instanceof Array && action.length > 1) { + throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol); + } + switch (action[0]) { + case 1: + stack.push(symbol); + vstack.push(this.lexer.yytext); + lstack.push(this.lexer.yylloc); + stack.push(action[1]); + symbol = null; + if (!preErrorSymbol) { + yyleng = this.lexer.yyleng; + yytext = this.lexer.yytext; + yylineno = this.lexer.yylineno; + yyloc = this.lexer.yylloc; + if (recovering > 0) + recovering--; + } else { + symbol = preErrorSymbol; + preErrorSymbol = null; + } + break; + case 2: + len = this.productions_[action[1]][1]; + yyval.$ = vstack[vstack.length - len]; + yyval._$ = {first_line: lstack[lstack.length - (len || 1)].first_line, last_line: lstack[lstack.length - 1].last_line, first_column: lstack[lstack.length - (len || 1)].first_column, last_column: lstack[lstack.length - 1].last_column}; + if (ranges) { + yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]]; + } + r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack); + if (typeof r !== "undefined") { + return r; + } + if (len) { + stack = stack.slice(0, -1 * len * 2); + vstack = vstack.slice(0, -1 * len); + lstack = lstack.slice(0, -1 * len); + } + stack.push(this.productions_[action[1]][0]); + vstack.push(yyval.$); + lstack.push(yyval._$); + newState = table[stack[stack.length - 2]][stack[stack.length - 1]]; + stack.push(newState); + break; + case 3: + return true; + } + } + return true; + } + }; + /* Jison generated lexer */ + var lexer = (function(){ + var lexer = ({EOF:1, + parseError:function parseError(str, hash) { + if (this.yy.parser) { + this.yy.parser.parseError(str, hash); + } else { + throw new Error(str); + } + }, + setInput:function (input) { + this._input = input; + this._more = this._less = this.done = false; + this.yylineno = this.yyleng = 0; + this.yytext = this.matched = this.match = ''; + this.conditionStack = ['INITIAL']; + this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0}; + if (this.options.ranges) this.yylloc.range = [0,0]; + this.offset = 0; + return this; + }, + input:function () { + var ch = this._input[0]; + this.yytext += ch; + this.yyleng++; + this.offset++; + this.match += ch; + this.matched += ch; + var lines = ch.match(/(?:\r\n?|\n).*/g); + if (lines) { + this.yylineno++; + this.yylloc.last_line++; + } else { + this.yylloc.last_column++; + } + if (this.options.ranges) this.yylloc.range[1]++; + + this._input = this._input.slice(1); + return ch; + }, + unput:function (ch) { + var len = ch.length; + var lines = ch.split(/(?:\r\n?|\n)/g); + + this._input = ch + this._input; + this.yytext = this.yytext.substr(0, this.yytext.length-len-1); + //this.yyleng -= len; + this.offset -= len; + var oldLines = this.match.split(/(?:\r\n?|\n)/g); + this.match = this.match.substr(0, this.match.length-1); + this.matched = this.matched.substr(0, this.matched.length-1); + + if (lines.length-1) this.yylineno -= lines.length-1; + var r = this.yylloc.range; + + this.yylloc = {first_line: this.yylloc.first_line, + last_line: this.yylineno+1, + first_column: this.yylloc.first_column, + last_column: lines ? + (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length: + this.yylloc.first_column - len + }; + + if (this.options.ranges) { + this.yylloc.range = [r[0], r[0] + this.yyleng - len]; + } + return this; + }, + more:function () { + this._more = true; + return this; + }, + less:function (n) { + this.unput(this.match.slice(n)); + }, + pastInput:function () { + var past = this.matched.substr(0, this.matched.length - this.match.length); + return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, ""); + }, + upcomingInput:function () { + var next = this.match; + if (next.length < 20) { + next += this._input.substr(0, 20-next.length); + } + return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, ""); + }, + showPosition:function () { + var pre = this.pastInput(); + var c = new Array(pre.length + 1).join("-"); + return pre + this.upcomingInput() + "\n" + c+"^"; + }, + next:function () { + if (this.done) { + return this.EOF; + } + if (!this._input) this.done = true; + + var token, + match, + tempMatch, + index, + col, + lines; + if (!this._more) { + this.yytext = ''; + this.match = ''; + } + var rules = this._currentRules(); + for (var i=0;i < rules.length; i++) { + tempMatch = this._input.match(this.rules[rules[i]]); + if (tempMatch && (!match || tempMatch[0].length > match[0].length)) { + match = tempMatch; + index = i; + if (!this.options.flex) break; + } + } + if (match) { + lines = match[0].match(/(?:\r\n?|\n).*/g); + if (lines) this.yylineno += lines.length; + this.yylloc = {first_line: this.yylloc.last_line, + last_line: this.yylineno+1, + first_column: this.yylloc.last_column, + last_column: lines ? lines[lines.length-1].length-lines[lines.length-1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length}; + this.yytext += match[0]; + this.match += match[0]; + this.matches = match; + this.yyleng = this.yytext.length; + if (this.options.ranges) { + this.yylloc.range = [this.offset, this.offset += this.yyleng]; + } + this._more = false; + this._input = this._input.slice(match[0].length); + this.matched += match[0]; + token = this.performAction.call(this, this.yy, this, rules[index],this.conditionStack[this.conditionStack.length-1]); + if (this.done && this._input) this.done = false; + if (token) return token; + else return; + } + if (this._input === "") { + return this.EOF; + } else { + return this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(), + {text: "", token: null, line: this.yylineno}); + } + }, + lex:function lex() { + var r = this.next(); + if (typeof r !== 'undefined') { + return r; + } else { + return this.lex(); + } + }, + begin:function begin(condition) { + this.conditionStack.push(condition); + }, + popState:function popState() { + return this.conditionStack.pop(); + }, + _currentRules:function _currentRules() { + return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules; + }, + topState:function () { + return this.conditionStack[this.conditionStack.length-2]; + }, + pushState:function begin(condition) { + this.begin(condition); + }}); + lexer.options = {}; + lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) { + + + function strip(start, end) { + return yy_.yytext = yy_.yytext.substr(start, yy_.yyleng-end); + } + + + var YYSTATE=YY_START + switch($avoiding_name_collisions) { + case 0: + if(yy_.yytext.slice(-2) === "\\\\") { + strip(0,1); + this.begin("mu"); + } else if(yy_.yytext.slice(-1) === "\\") { + strip(0,1); + this.begin("emu"); + } else { + this.begin("mu"); + } + if(yy_.yytext) return 12; + + break; + case 1:return 12; + break; + case 2: + this.popState(); + return 12; + + break; + case 3: + yy_.yytext = yy_.yytext.substr(5, yy_.yyleng-9); + this.popState(); + return 15; + + break; + case 4: return 12; + break; + case 5:strip(0,4); this.popState(); return 13; + break; + case 6:return 45; + break; + case 7:return 46; + break; + case 8: return 16; + break; + case 9: + this.popState(); + this.begin('raw'); + return 18; + + break; + case 10:return 34; + break; + case 11:return 24; + break; + case 12:return 29; + break; + case 13:this.popState(); return 28; + break; + case 14:this.popState(); return 28; + break; + case 15:return 26; + break; + case 16:return 26; + break; + case 17:return 32; + break; + case 18:return 31; + break; + case 19:this.popState(); this.begin('com'); + break; + case 20:strip(3,5); this.popState(); return 13; + break; + case 21:return 31; + break; + case 22:return 51; + break; + case 23:return 50; + break; + case 24:return 50; + break; + case 25:return 54; + break; + case 26:// ignore whitespace + break; + case 27:this.popState(); return 33; + break; + case 28:this.popState(); return 25; + break; + case 29:yy_.yytext = strip(1,2).replace(/\\"/g,'"'); return 42; + break; + case 30:yy_.yytext = strip(1,2).replace(/\\'/g,"'"); return 42; + break; + case 31:return 52; + break; + case 32:return 44; + break; + case 33:return 44; + break; + case 34:return 43; + break; + case 35:return 50; + break; + case 36:yy_.yytext = strip(1,2); return 50; + break; + case 37:return 'INVALID'; + break; + case 38:return 5; + break; + } + }; + lexer.rules = [/^(?:[^\x00]*?(?=(\{\{)))/,/^(?:[^\x00]+)/,/^(?:[^\x00]{2,}?(?=(\{\{|\\\{\{|\\\\\{\{|$)))/,/^(?:\{\{\{\{\/[^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=[=}\s\/.])\}\}\}\})/,/^(?:[^\x00]*?(?=(\{\{\{\{\/)))/,/^(?:[\s\S]*?--\}\})/,/^(?:\()/,/^(?:\))/,/^(?:\{\{\{\{)/,/^(?:\}\}\}\})/,/^(?:\{\{(~)?>)/,/^(?:\{\{(~)?#)/,/^(?:\{\{(~)?\/)/,/^(?:\{\{(~)?\^\s*(~)?\}\})/,/^(?:\{\{(~)?\s*else\s*(~)?\}\})/,/^(?:\{\{(~)?\^)/,/^(?:\{\{(~)?\s*else\b)/,/^(?:\{\{(~)?\{)/,/^(?:\{\{(~)?&)/,/^(?:\{\{!--)/,/^(?:\{\{![\s\S]*?\}\})/,/^(?:\{\{(~)?)/,/^(?:=)/,/^(?:\.\.)/,/^(?:\.(?=([=~}\s\/.)])))/,/^(?:[\/.])/,/^(?:\s+)/,/^(?:\}(~)?\}\})/,/^(?:(~)?\}\})/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(?:@)/,/^(?:true(?=([~}\s)])))/,/^(?:false(?=([~}\s)])))/,/^(?:-?[0-9]+(?:\.[0-9]+)?(?=([~}\s)])))/,/^(?:([^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=([=~}\s\/.)]))))/,/^(?:\[[^\]]*\])/,/^(?:.)/,/^(?:$)/]; + lexer.conditions = {"mu":{"rules":[6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38],"inclusive":false},"emu":{"rules":[2],"inclusive":false},"com":{"rules":[5],"inclusive":false},"raw":{"rules":[3,4],"inclusive":false},"INITIAL":{"rules":[0,1,38],"inclusive":true}}; + return lexer;})() + parser.lexer = lexer; + function Parser () { this.yy = {}; }Parser.prototype = parser;parser.Parser = Parser; + return new Parser; + })();__exports__ = handlebars; + /* jshint ignore:end */ + return __exports__; +})(); + +// handlebars/compiler/helpers.js +var __module10__ = (function(__dependency1__) { + "use strict"; + var __exports__ = {}; + var Exception = __dependency1__; + + function stripFlags(open, close) { + return { + left: open.charAt(2) === '~', + right: close.charAt(close.length-3) === '~' + }; + } + + __exports__.stripFlags = stripFlags; + function prepareBlock(mustache, program, inverseAndProgram, close, inverted, locInfo) { + /*jshint -W040 */ + if (mustache.sexpr.id.original !== close.path.original) { + throw new Exception(mustache.sexpr.id.original + ' doesn\'t match ' + close.path.original, mustache); + } + + var inverse = inverseAndProgram && inverseAndProgram.program; + + var strip = { + left: mustache.strip.left, + right: close.strip.right, + + // Determine the standalone candiacy. Basically flag our content as being possibly standalone + // so our parent can determine if we actually are standalone + openStandalone: isNextWhitespace(program.statements), + closeStandalone: isPrevWhitespace((inverse || program).statements) + }; + + if (mustache.strip.right) { + omitRight(program.statements, null, true); + } + + if (inverse) { + var inverseStrip = inverseAndProgram.strip; + + if (inverseStrip.left) { + omitLeft(program.statements, null, true); + } + if (inverseStrip.right) { + omitRight(inverse.statements, null, true); + } + if (close.strip.left) { + omitLeft(inverse.statements, null, true); + } + + // Find standalone else statments + if (isPrevWhitespace(program.statements) + && isNextWhitespace(inverse.statements)) { + + omitLeft(program.statements); + omitRight(inverse.statements); + } + } else { + if (close.strip.left) { + omitLeft(program.statements, null, true); + } + } + + if (inverted) { + return new this.BlockNode(mustache, inverse, program, strip, locInfo); + } else { + return new this.BlockNode(mustache, program, inverse, strip, locInfo); + } + } + + __exports__.prepareBlock = prepareBlock; + function prepareProgram(statements, isRoot) { + for (var i = 0, l = statements.length; i < l; i++) { + var current = statements[i], + strip = current.strip; + + if (!strip) { + continue; + } + + var _isPrevWhitespace = isPrevWhitespace(statements, i, isRoot, current.type === 'partial'), + _isNextWhitespace = isNextWhitespace(statements, i, isRoot), + + openStandalone = strip.openStandalone && _isPrevWhitespace, + closeStandalone = strip.closeStandalone && _isNextWhitespace, + inlineStandalone = strip.inlineStandalone && _isPrevWhitespace && _isNextWhitespace; + + if (strip.right) { + omitRight(statements, i, true); + } + if (strip.left) { + omitLeft(statements, i, true); + } + + if (inlineStandalone) { + omitRight(statements, i); + + if (omitLeft(statements, i)) { + // If we are on a standalone node, save the indent info for partials + if (current.type === 'partial') { + current.indent = (/([ \t]+$)/).exec(statements[i-1].original) ? RegExp.$1 : ''; + } + } + } + if (openStandalone) { + omitRight((current.program || current.inverse).statements); + + // Strip out the previous content node if it's whitespace only + omitLeft(statements, i); + } + if (closeStandalone) { + // Always strip the next node + omitRight(statements, i); + + omitLeft((current.inverse || current.program).statements); + } + } + + return statements; + } + + __exports__.prepareProgram = prepareProgram;function isPrevWhitespace(statements, i, isRoot) { + if (i === undefined) { + i = statements.length; + } + + // Nodes that end with newlines are considered whitespace (but are special + // cased for strip operations) + var prev = statements[i-1], + sibling = statements[i-2]; + if (!prev) { + return isRoot; + } + + if (prev.type === 'content') { + return (sibling || !isRoot ? (/\r?\n\s*?$/) : (/(^|\r?\n)\s*?$/)).test(prev.original); + } + } + function isNextWhitespace(statements, i, isRoot) { + if (i === undefined) { + i = -1; + } + + var next = statements[i+1], + sibling = statements[i+2]; + if (!next) { + return isRoot; + } + + if (next.type === 'content') { + return (sibling || !isRoot ? (/^\s*?\r?\n/) : (/^\s*?(\r?\n|$)/)).test(next.original); + } + } + + // Marks the node to the right of the position as omitted. + // I.e. {{foo}}' ' will mark the ' ' node as omitted. + // + // If i is undefined, then the first child will be marked as such. + // + // If mulitple is truthy then all whitespace will be stripped out until non-whitespace + // content is met. + function omitRight(statements, i, multiple) { + var current = statements[i == null ? 0 : i + 1]; + if (!current || current.type !== 'content' || (!multiple && current.rightStripped)) { + return; + } + + var original = current.string; + current.string = current.string.replace(multiple ? (/^\s+/) : (/^[ \t]*\r?\n?/), ''); + current.rightStripped = current.string !== original; + } + + // Marks the node to the left of the position as omitted. + // I.e. ' '{{foo}} will mark the ' ' node as omitted. + // + // If i is undefined then the last child will be marked as such. + // + // If mulitple is truthy then all whitespace will be stripped out until non-whitespace + // content is met. + function omitLeft(statements, i, multiple) { + var current = statements[i == null ? statements.length - 1 : i - 1]; + if (!current || current.type !== 'content' || (!multiple && current.leftStripped)) { + return; + } + + // We omit the last node if it's whitespace only and not preceeded by a non-content node. + var original = current.string; + current.string = current.string.replace(multiple ? (/\s+$/) : (/[ \t]+$/), ''); + current.leftStripped = current.string !== original; + return current.leftStripped; + } + return __exports__; +})(__module5__); + +// handlebars/compiler/base.js +var __module8__ = (function(__dependency1__, __dependency2__, __dependency3__, __dependency4__) { + "use strict"; + var __exports__ = {}; + var parser = __dependency1__; + var AST = __dependency2__; + var Helpers = __dependency3__; + var extend = __dependency4__.extend; + + __exports__.parser = parser; + + var yy = {}; + extend(yy, Helpers, AST); + + function parse(input) { + // Just return if an already-compile AST was passed in. + if (input.constructor === AST.ProgramNode) { return input; } + + parser.yy = yy; + + return parser.parse(input); + } + + __exports__.parse = parse; + return __exports__; +})(__module9__, __module7__, __module10__, __module3__); + +// handlebars/compiler/compiler.js +var __module11__ = (function(__dependency1__, __dependency2__) { + "use strict"; + var __exports__ = {}; + var Exception = __dependency1__; + var isArray = __dependency2__.isArray; + + var slice = [].slice; + + function Compiler() {} + + __exports__.Compiler = Compiler;// the foundHelper register will disambiguate helper lookup from finding a + // function in a context. This is necessary for mustache compatibility, which + // requires that context functions in blocks are evaluated by blockHelperMissing, + // and then proceed as if the resulting value was provided to blockHelperMissing. + + Compiler.prototype = { + compiler: Compiler, + + equals: function(other) { + var len = this.opcodes.length; + if (other.opcodes.length !== len) { + return false; + } + + for (var i = 0; i < len; i++) { + var opcode = this.opcodes[i], + otherOpcode = other.opcodes[i]; + if (opcode.opcode !== otherOpcode.opcode || !argEquals(opcode.args, otherOpcode.args)) { + return false; + } + } + + // We know that length is the same between the two arrays because they are directly tied + // to the opcode behavior above. + len = this.children.length; + for (i = 0; i < len; i++) { + if (!this.children[i].equals(other.children[i])) { + return false; + } + } + + return true; + }, + + guid: 0, + + compile: function(program, options) { + this.opcodes = []; + this.children = []; + this.depths = {list: []}; + this.options = options; + this.stringParams = options.stringParams; + this.trackIds = options.trackIds; + + // These changes will propagate to the other compiler components + var knownHelpers = this.options.knownHelpers; + this.options.knownHelpers = { + 'helperMissing': true, + 'blockHelperMissing': true, + 'each': true, + 'if': true, + 'unless': true, + 'with': true, + 'log': true, + 'lookup': true + }; + if (knownHelpers) { + for (var name in knownHelpers) { + this.options.knownHelpers[name] = knownHelpers[name]; + } + } + + return this.accept(program); + }, + + accept: function(node) { + return this[node.type](node); + }, + + program: function(program) { + var statements = program.statements; + + for(var i=0, l=statements.length; i 0) { + varDeclarations += ", " + locals.join(", "); + } + + // Generate minimizer alias mappings + for (var alias in this.aliases) { + if (this.aliases.hasOwnProperty(alias)) { + varDeclarations += ', ' + alias + '=' + this.aliases[alias]; + } + } + + var params = ["depth0", "helpers", "partials", "data"]; + + if (this.useDepths) { + params.push('depths'); + } + + // Perform a second pass over the output to merge content when possible + var source = this.mergeSource(varDeclarations); + + if (asObject) { + params.push(source); + + return Function.apply(this, params); + } else { + return 'function(' + params.join(',') + ') {\n ' + source + '}'; + } + }, + mergeSource: function(varDeclarations) { + var source = '', + buffer, + appendOnly = !this.forceBuffer, + appendFirst; + + for (var i = 0, len = this.source.length; i < len; i++) { + var line = this.source[i]; + if (line.appendToBuffer) { + if (buffer) { + buffer = buffer + '\n + ' + line.content; + } else { + buffer = line.content; + } + } else { + if (buffer) { + if (!source) { + appendFirst = true; + source = buffer + ';\n '; + } else { + source += 'buffer += ' + buffer + ';\n '; + } + buffer = undefined; + } + source += line + '\n '; + + if (!this.environment.isSimple) { + appendOnly = false; + } + } + } + + if (appendOnly) { + if (buffer || !source) { + source += 'return ' + (buffer || '""') + ';\n'; + } + } else { + varDeclarations += ", buffer = " + (appendFirst ? '' : this.initializeBuffer()); + if (buffer) { + source += 'return buffer + ' + buffer + ';\n'; + } else { + source += 'return buffer;\n'; + } + } + + if (varDeclarations) { + source = 'var ' + varDeclarations.substring(2) + (appendFirst ? '' : ';\n ') + source; + } + + return source; + }, + + // [blockValue] + // + // On stack, before: hash, inverse, program, value + // On stack, after: return value of blockHelperMissing + // + // The purpose of this opcode is to take a block of the form + // `{{#this.foo}}...{{/this.foo}}`, resolve the value of `foo`, and + // replace it on the stack with the result of properly + // invoking blockHelperMissing. + blockValue: function(name) { + this.aliases.blockHelperMissing = 'helpers.blockHelperMissing'; + + var params = [this.contextName(0)]; + this.setupParams(name, 0, params); + + var blockName = this.popStack(); + params.splice(1, 0, blockName); + + this.push('blockHelperMissing.call(' + params.join(', ') + ')'); + }, + + // [ambiguousBlockValue] + // + // On stack, before: hash, inverse, program, value + // Compiler value, before: lastHelper=value of last found helper, if any + // On stack, after, if no lastHelper: same as [blockValue] + // On stack, after, if lastHelper: value + ambiguousBlockValue: function() { + this.aliases.blockHelperMissing = 'helpers.blockHelperMissing'; + + // We're being a bit cheeky and reusing the options value from the prior exec + var params = [this.contextName(0)]; + this.setupParams('', 0, params, true); + + this.flushInline(); + + var current = this.topStack(); + params.splice(1, 0, current); + + this.pushSource("if (!" + this.lastHelper + ") { " + current + " = blockHelperMissing.call(" + params.join(", ") + "); }"); + }, + + // [appendContent] + // + // On stack, before: ... + // On stack, after: ... + // + // Appends the string value of `content` to the current buffer + appendContent: function(content) { + if (this.pendingContent) { + content = this.pendingContent + content; + } + + this.pendingContent = content; + }, + + // [append] + // + // On stack, before: value, ... + // On stack, after: ... + // + // Coerces `value` to a String and appends it to the current buffer. + // + // If `value` is truthy, or 0, it is coerced into a string and appended + // Otherwise, the empty string is appended + append: function() { + // Force anything that is inlined onto the stack so we don't have duplication + // when we examine local + this.flushInline(); + var local = this.popStack(); + this.pushSource('if (' + local + ' != null) { ' + this.appendToBuffer(local) + ' }'); + if (this.environment.isSimple) { + this.pushSource("else { " + this.appendToBuffer("''") + " }"); + } + }, + + // [appendEscaped] + // + // On stack, before: value, ... + // On stack, after: ... + // + // Escape `value` and append it to the buffer + appendEscaped: function() { + this.aliases.escapeExpression = 'this.escapeExpression'; + + this.pushSource(this.appendToBuffer("escapeExpression(" + this.popStack() + ")")); + }, + + // [getContext] + // + // On stack, before: ... + // On stack, after: ... + // Compiler value, after: lastContext=depth + // + // Set the value of the `lastContext` compiler value to the depth + getContext: function(depth) { + this.lastContext = depth; + }, + + // [pushContext] + // + // On stack, before: ... + // On stack, after: currentContext, ... + // + // Pushes the value of the current context onto the stack. + pushContext: function() { + this.pushStackLiteral(this.contextName(this.lastContext)); + }, + + // [lookupOnContext] + // + // On stack, before: ... + // On stack, after: currentContext[name], ... + // + // Looks up the value of `name` on the current context and pushes + // it onto the stack. + lookupOnContext: function(parts, falsy, scoped) { + /*jshint -W083 */ + var i = 0, + len = parts.length; + + if (!scoped && this.options.compat && !this.lastContext) { + // The depthed query is expected to handle the undefined logic for the root level that + // is implemented below, so we evaluate that directly in compat mode + this.push(this.depthedLookup(parts[i++])); + } else { + this.pushContext(); + } + + for (; i < len; i++) { + this.replaceStack(function(current) { + var lookup = this.nameLookup(current, parts[i], 'context'); + // We want to ensure that zero and false are handled properly if the context (falsy flag) + // needs to have the special handling for these values. + if (!falsy) { + return ' != null ? ' + lookup + ' : ' + current; + } else { + // Otherwise we can use generic falsy handling + return ' && ' + lookup; + } + }); + } + }, + + // [lookupData] + // + // On stack, before: ... + // On stack, after: data, ... + // + // Push the data lookup operator + lookupData: function(depth, parts) { + /*jshint -W083 */ + if (!depth) { + this.pushStackLiteral('data'); + } else { + this.pushStackLiteral('this.data(data, ' + depth + ')'); + } + + var len = parts.length; + for (var i = 0; i < len; i++) { + this.replaceStack(function(current) { + return ' && ' + this.nameLookup(current, parts[i], 'data'); + }); + } + }, + + // [resolvePossibleLambda] + // + // On stack, before: value, ... + // On stack, after: resolved value, ... + // + // If the `value` is a lambda, replace it on the stack by + // the return value of the lambda + resolvePossibleLambda: function() { + this.aliases.lambda = 'this.lambda'; + + this.push('lambda(' + this.popStack() + ', ' + this.contextName(0) + ')'); + }, + + // [pushStringParam] + // + // On stack, before: ... + // On stack, after: string, currentContext, ... + // + // This opcode is designed for use in string mode, which + // provides the string value of a parameter along with its + // depth rather than resolving it immediately. + pushStringParam: function(string, type) { + this.pushContext(); + this.pushString(type); + + // If it's a subexpression, the string result + // will be pushed after this opcode. + if (type !== 'sexpr') { + if (typeof string === 'string') { + this.pushString(string); + } else { + this.pushStackLiteral(string); + } + } + }, + + emptyHash: function() { + this.pushStackLiteral('{}'); + + if (this.trackIds) { + this.push('{}'); // hashIds + } + if (this.stringParams) { + this.push('{}'); // hashContexts + this.push('{}'); // hashTypes + } + }, + pushHash: function() { + if (this.hash) { + this.hashes.push(this.hash); + } + this.hash = {values: [], types: [], contexts: [], ids: []}; + }, + popHash: function() { + var hash = this.hash; + this.hash = this.hashes.pop(); + + if (this.trackIds) { + this.push('{' + hash.ids.join(',') + '}'); + } + if (this.stringParams) { + this.push('{' + hash.contexts.join(',') + '}'); + this.push('{' + hash.types.join(',') + '}'); + } + + this.push('{\n ' + hash.values.join(',\n ') + '\n }'); + }, + + // [pushString] + // + // On stack, before: ... + // On stack, after: quotedString(string), ... + // + // Push a quoted version of `string` onto the stack + pushString: function(string) { + this.pushStackLiteral(this.quotedString(string)); + }, + + // [push] + // + // On stack, before: ... + // On stack, after: expr, ... + // + // Push an expression onto the stack + push: function(expr) { + this.inlineStack.push(expr); + return expr; + }, + + // [pushLiteral] + // + // On stack, before: ... + // On stack, after: value, ... + // + // Pushes a value onto the stack. This operation prevents + // the compiler from creating a temporary variable to hold + // it. + pushLiteral: function(value) { + this.pushStackLiteral(value); + }, + + // [pushProgram] + // + // On stack, before: ... + // On stack, after: program(guid), ... + // + // Push a program expression onto the stack. This takes + // a compile-time guid and converts it into a runtime-accessible + // expression. + pushProgram: function(guid) { + if (guid != null) { + this.pushStackLiteral(this.programExpression(guid)); + } else { + this.pushStackLiteral(null); + } + }, + + // [invokeHelper] + // + // On stack, before: hash, inverse, program, params..., ... + // On stack, after: result of helper invocation + // + // Pops off the helper's parameters, invokes the helper, + // and pushes the helper's return value onto the stack. + // + // If the helper is not found, `helperMissing` is called. + invokeHelper: function(paramSize, name, isSimple) { + this.aliases.helperMissing = 'helpers.helperMissing'; + + var nonHelper = this.popStack(); + var helper = this.setupHelper(paramSize, name); + + var lookup = (isSimple ? helper.name + ' || ' : '') + nonHelper + ' || helperMissing'; + this.push('((' + lookup + ').call(' + helper.callParams + '))'); + }, + + // [invokeKnownHelper] + // + // On stack, before: hash, inverse, program, params..., ... + // On stack, after: result of helper invocation + // + // This operation is used when the helper is known to exist, + // so a `helperMissing` fallback is not required. + invokeKnownHelper: function(paramSize, name) { + var helper = this.setupHelper(paramSize, name); + this.push(helper.name + ".call(" + helper.callParams + ")"); + }, + + // [invokeAmbiguous] + // + // On stack, before: hash, inverse, program, params..., ... + // On stack, after: result of disambiguation + // + // This operation is used when an expression like `{{foo}}` + // is provided, but we don't know at compile-time whether it + // is a helper or a path. + // + // This operation emits more code than the other options, + // and can be avoided by passing the `knownHelpers` and + // `knownHelpersOnly` flags at compile-time. + invokeAmbiguous: function(name, helperCall) { + this.aliases.functionType = '"function"'; + this.aliases.helperMissing = 'helpers.helperMissing'; + this.useRegister('helper'); + + var nonHelper = this.popStack(); + + this.emptyHash(); + var helper = this.setupHelper(0, name, helperCall); + + var helperName = this.lastHelper = this.nameLookup('helpers', name, 'helper'); + + this.push( + '((helper = (helper = ' + helperName + ' || ' + nonHelper + ') != null ? helper : helperMissing' + + (helper.paramsInit ? '),(' + helper.paramsInit : '') + '),' + + '(typeof helper === functionType ? helper.call(' + helper.callParams + ') : helper))'); + }, + + // [invokePartial] + // + // On stack, before: context, ... + // On stack after: result of partial invocation + // + // This operation pops off a context, invokes a partial with that context, + // and pushes the result of the invocation back. + invokePartial: function(name, indent) { + var params = [this.nameLookup('partials', name, 'partial'), "'" + indent + "'", "'" + name + "'", this.popStack(), this.popStack(), "helpers", "partials"]; + + if (this.options.data) { + params.push("data"); + } else if (this.options.compat) { + params.push('undefined'); + } + if (this.options.compat) { + params.push('depths'); + } + + this.push("this.invokePartial(" + params.join(", ") + ")"); + }, + + // [assignToHash] + // + // On stack, before: value, ..., hash, ... + // On stack, after: ..., hash, ... + // + // Pops a value off the stack and assigns it to the current hash + assignToHash: function(key) { + var value = this.popStack(), + context, + type, + id; + + if (this.trackIds) { + id = this.popStack(); + } + if (this.stringParams) { + type = this.popStack(); + context = this.popStack(); + } + + var hash = this.hash; + if (context) { + hash.contexts.push("'" + key + "': " + context); + } + if (type) { + hash.types.push("'" + key + "': " + type); + } + if (id) { + hash.ids.push("'" + key + "': " + id); + } + hash.values.push("'" + key + "': (" + value + ")"); + }, + + pushId: function(type, name) { + if (type === 'ID' || type === 'DATA') { + this.pushString(name); + } else if (type === 'sexpr') { + this.pushStackLiteral('true'); + } else { + this.pushStackLiteral('null'); + } + }, + + // HELPERS + + compiler: JavaScriptCompiler, + + compileChildren: function(environment, options) { + var children = environment.children, child, compiler; + + for(var i=0, l=children.length; i this.stackVars.length) { this.stackVars.push("stack" + this.stackSlot); } + return this.topStackName(); + }, + topStackName: function() { + return "stack" + this.stackSlot; + }, + flushInline: function() { + var inlineStack = this.inlineStack; + if (inlineStack.length) { + this.inlineStack = []; + for (var i = 0, len = inlineStack.length; i < len; i++) { + var entry = inlineStack[i]; + if (entry instanceof Literal) { + this.compileStack.push(entry); + } else { + this.pushStack(entry); + } + } + } + }, + isInline: function() { + return this.inlineStack.length; + }, + + popStack: function(wrapped) { + var inline = this.isInline(), + item = (inline ? this.inlineStack : this.compileStack).pop(); + + if (!wrapped && (item instanceof Literal)) { + return item.value; + } else { + if (!inline) { + /* istanbul ignore next */ + if (!this.stackSlot) { + throw new Exception('Invalid stack pop'); + } + this.stackSlot--; + } + return item; + } + }, + + topStack: function() { + var stack = (this.isInline() ? this.inlineStack : this.compileStack), + item = stack[stack.length - 1]; + + if (item instanceof Literal) { + return item.value; + } else { + return item; + } + }, + + contextName: function(context) { + if (this.useDepths && context) { + return 'depths[' + context + ']'; + } else { + return 'depth' + context; + } + }, + + quotedString: function(str) { + return '"' + str + .replace(/\\/g, '\\\\') + .replace(/"/g, '\\"') + .replace(/\n/g, '\\n') + .replace(/\r/g, '\\r') + .replace(/\u2028/g, '\\u2028') // Per Ecma-262 7.3 + 7.8.4 + .replace(/\u2029/g, '\\u2029') + '"'; + }, + + objectLiteral: function(obj) { + var pairs = []; + + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + pairs.push(this.quotedString(key) + ':' + obj[key]); + } + } + + return '{' + pairs.join(',') + '}'; + }, + + setupHelper: function(paramSize, name, blockHelper) { + var params = [], + paramsInit = this.setupParams(name, paramSize, params, blockHelper); + var foundHelper = this.nameLookup('helpers', name, 'helper'); + + return { + params: params, + paramsInit: paramsInit, + name: foundHelper, + callParams: [this.contextName(0)].concat(params).join(", ") + }; + }, + + setupOptions: function(helper, paramSize, params) { + var options = {}, contexts = [], types = [], ids = [], param, inverse, program; + + options.name = this.quotedString(helper); + options.hash = this.popStack(); + + if (this.trackIds) { + options.hashIds = this.popStack(); + } + if (this.stringParams) { + options.hashTypes = this.popStack(); + options.hashContexts = this.popStack(); + } + + inverse = this.popStack(); + program = this.popStack(); + + // Avoid setting fn and inverse if neither are set. This allows + // helpers to do a check for `if (options.fn)` + if (program || inverse) { + if (!program) { + program = 'this.noop'; + } + + if (!inverse) { + inverse = 'this.noop'; + } + + options.fn = program; + options.inverse = inverse; + } + + // The parameters go on to the stack in order (making sure that they are evaluated in order) + // so we need to pop them off the stack in reverse order + var i = paramSize; + while (i--) { + param = this.popStack(); + params[i] = param; + + if (this.trackIds) { + ids[i] = this.popStack(); + } + if (this.stringParams) { + types[i] = this.popStack(); + contexts[i] = this.popStack(); + } + } + + if (this.trackIds) { + options.ids = "[" + ids.join(",") + "]"; + } + if (this.stringParams) { + options.types = "[" + types.join(",") + "]"; + options.contexts = "[" + contexts.join(",") + "]"; + } + + if (this.options.data) { + options.data = "data"; + } + + return options; + }, + + // the params and contexts arguments are passed in arrays + // to fill in + setupParams: function(helperName, paramSize, params, useRegister) { + var options = this.objectLiteral(this.setupOptions(helperName, paramSize, params)); + + if (useRegister) { + this.useRegister('options'); + params.push('options'); + return 'options=' + options; + } else { + params.push(options); + return ''; + } + } + }; + + var reservedWords = ( + "break else new var" + + " case finally return void" + + " catch for switch while" + + " continue function this with" + + " default if throw" + + " delete in try" + + " do instanceof typeof" + + " abstract enum int short" + + " boolean export interface static" + + " byte extends long super" + + " char final native synchronized" + + " class float package throws" + + " const goto private transient" + + " debugger implements protected volatile" + + " double import public let yield" + ).split(" "); + + var compilerWords = JavaScriptCompiler.RESERVED_WORDS = {}; + + for(var i=0, l=reservedWords.length; i */ + +// +// Stub out `require` in rhino +// +function require(arg) { + var split = arg.split('/'); + var resultModule = split.length == 1 ? less.modules[split[0]] : less[split[1]]; + if (!resultModule) { + throw {message: "Cannot find module '" + arg + "'"}; + } + return resultModule; +} + + +if (typeof(window) === 'undefined') { + less = {} +} +else { + less = window.less = {} +} +tree = less.tree = {}; +less.mode = 'rhino'; + +(function () { + + console = function () { + function doLog(out) { + return function (a) { + //TODO: for some reason loging dosn't work,fix later + } + } + + return { + log: doLog(log.info), + info: doLog(log.info), + error: doLog(log.error), + warn: doLog(log.warn) + }; + }(); + + less.modules = {}; + + less.modules.path = { + join: function () { + var parts = []; + for (i in arguments) { + parts = parts.concat(arguments[i].split(/\/|\\/)); + } + var result = []; + for (i in parts) { + var part = parts[i]; + if (part === '..' && result.length > 0 && result[result.length - 1] !== '..') { + result.pop(); + } else if (part === '' && result.length > 0) { + // skip + } else if (part !== '.') { + if (part.slice(-1) === '\\' || part.slice(-1) === '/') { + part = part.slice(0, -1); + } + result.push(part); + } + } + return result.join('/'); + }, + dirname: function (p) { + var path = p.split('/'); + path.pop(); + return path.join('/'); + }, + basename: function (p, ext) { + var base = p.split('/').pop(); + if (ext) { + var index = base.lastIndexOf(ext); + if (base.length === index + ext.length) { + base = base.substr(0, index); + } + } + return base; + }, + extname: function (p) { + var index = p.lastIndexOf('.'); + return index > 0 ? p.substring(index) : ''; + } + }; + + less.modules.fs = { + readFileSync: function (name) { + // read a file into a byte array + var file = new java.io.File(name); + new Log('xxxxxxxx').info(file.getCanonicalPath()); + var stream = new java.io.FileInputStream(file); + var buffer = []; + var c; + while ((c = stream.read()) != -1) { + buffer.push(c); + } + stream.close(); + return { + length: buffer.length, + toString: function (enc) { + if (enc === 'base64') { + return encodeBase64Bytes(buffer); + } else if (enc) { + return java.lang.String["(byte[],java.lang.String)"](buffer, enc); + } else { + return java.lang.String["(byte[])"](buffer); + } + } + }; + } + }; + + less.encoder = { + encodeBase64: function (str) { + return encodeBase64String(str); + } + }; + + // --------------------------------------------------------------------------------------------- + // private helper functions + // --------------------------------------------------------------------------------------------- + + function encodeBase64Bytes(bytes) { + // requires at least a JRE Platform 6 (or JAXB 1.0 on the classpath) + return javax.xml.bind.DatatypeConverter.printBase64Binary(bytes) + } + + function encodeBase64String(str) { + return encodeBase64Bytes(new java.lang.String(str).getBytes()); + } + +})(); + +var less, tree; + +// Node.js does not have a header file added which defines less +if (less === undefined) { + less = exports; + tree = require('./tree'); + less.mode = 'node'; +} +// +// less.js - parser +// +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. +// +// To make the parser fast enough to run in the browser, several +// optimization had to be made: +// +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `currentPos` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. +// +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. +// +// +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +// +// +less.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + saveStack = [], // holds state for backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // current chunk + currentPos, // index of current chunk, in `input` + parser, + parsers, + rootFilename = env && env.filename; + + // Top parser on an import tree must be sure there is one "env" + // which will then be passed around by reference. + if (!(env instanceof tree.parseEnv)) { + env = new tree.parseEnv(env); + } + + var imports = this.imports = { + paths: env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: env.files, // Holds the imported parse trees + contents: env.contents, // Holds the imported file contents + contentsIgnoredChars: env.contentsIgnoredChars, // lines inserted, not in the original less + mime: env.mime, // MIME type of .less files + error: null, // Error in parsing/evaluating an import + push: function (path, currentFileInfo, importOptions, callback) { + var parserImports = this; + this.queue.push(path); + + var fileParsedFunc = function (e, root, fullPath) { + parserImports.queue.splice(parserImports.queue.indexOf(path), 1); // Remove the path from the queue + + var importedPreviously = fullPath === rootFilename; + + parserImports.files[fullPath] = root; // Store the root + + if (e && !parserImports.error) { + parserImports.error = e; + } + + callback(e, root, importedPreviously, fullPath); + }; + + if (less.Parser.importer) { + less.Parser.importer(path, currentFileInfo, fileParsedFunc, env); + } else { + less.Parser.fileLoader(path, currentFileInfo, function (e, contents, fullPath, newFileInfo) { + if (e) { + fileParsedFunc(e); + return; + } + + var newEnv = new tree.parseEnv(env); + + newEnv.currentFileInfo = newFileInfo; + newEnv.processImports = false; + newEnv.contents[fullPath] = contents; + + if (currentFileInfo.reference || importOptions.reference) { + newFileInfo.reference = true; + } + + if (importOptions.inline) { + fileParsedFunc(null, contents, fullPath); + } else { + new (less.Parser)(newEnv).parse(contents, function (e, root) { + fileParsedFunc(e, root, fullPath); + }); + } + }, env); + } + } + }; + + function save() { + currentPos = i; + saveStack.push({current: current, i: i, j: j}); + } + + function restore() { + var state = saveStack.pop(); + current = state.current; + currentPos = i = state.i; + j = state.j; + } + + function forget() { + saveStack.pop(); + } + + function sync() { + if (i > currentPos) { + current = current.slice(i - currentPos); + currentPos = i; + } + } + + function isWhitespace(str, pos) { + var code = str.charCodeAt(pos | 0); + return (code <= 32) && (code === 32 || code === 10 || code === 9); + } + + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var tokType = typeof tok, + match, length; + + // Either match a single character in the input, + // or match a regexp in the current chunk (`current`). + // + if (tokType === "string") { + if (input.charAt(i) !== tok) { + return null; + } + skipWhitespace(1); + return tok; + } + + // regexp + sync(); + if (!(match = tok.exec(current))) { + return null; + } + + length = match[0].length; + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + skipWhitespace(length); + + if (typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + + // Specialization of $(tok) + function $re(tok) { + if (i > currentPos) { + current = current.slice(i - currentPos); + currentPos = i; + } + var m = tok.exec(current); + if (!m) { + return null; + } + + skipWhitespace(m[0].length); + if (typeof m === "string") { + return m; + } + + return m.length === 1 ? m[0] : m; + } + + var _$re = $re; + + // Specialization of $(tok) + function $char(tok) { + if (input.charAt(i) !== tok) { + return null; + } + skipWhitespace(1); + return tok; + } + + function skipWhitespace(length) { + var oldi = i, oldj = j, + curr = i - currentPos, + endIndex = i + current.length - curr, + mem = (i += length), + inp = input, + c; + + for (; i < endIndex; i++) { + c = inp.charCodeAt(i); + if (c > 32) { + break; + } + + if ((c !== 32) && (c !== 10) && (c !== 9) && (c !== 13)) { + break; + } + } + + current = current.slice(length + i - mem + curr); + currentPos = i; + + if (!current.length && (j < chunks.length - 1)) { + current = chunks[++j]; + skipWhitespace(0); // skip space at the beginning of a chunk + return true; // things changed + } + + return oldi !== i || oldj !== j; + } + + function expect(arg, msg, index) { + // some older browsers return typeof 'function' for RegExp + var result = (Object.prototype.toString.call(arg) === '[object Function]') ? arg.call(parsers) : $(arg); + if (result) { + return result; + } + error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" + : "unexpected token")); + } + + // Specialization of expect() + function expectChar(arg, msg) { + if (input.charAt(i) === arg) { + skipWhitespace(1); + return arg; + } + error(msg || "expected '" + arg + "' got '" + input.charAt(i) + "'"); + } + + function error(msg, type) { + var e = new Error(msg); + e.index = i; + e.type = type || 'Syntax'; + throw e; + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + return tok.test(current); + } + } + + // Specialization of peek() + function peekChar(tok) { + return input.charAt(i) === tok; + } + + + function getInput(e, env) { + if (e.filename && env.currentFileInfo.filename && (e.filename !== env.currentFileInfo.filename)) { + return parser.imports.contents[e.filename]; + } else { + return input; + } + } + + function getLocation(index, inputStream) { + var n = index + 1, + line = null, + column = -1; + + while (--n >= 0 && inputStream.charAt(n) !== '\n') { + column++; + } + + if (typeof index === 'number') { + line = (inputStream.slice(0, index).match(/\n/g) || "").length; + } + + return { + line: line, + column: column + }; + } + + function getDebugInfo(index, inputStream, env) { + var filename = env.currentFileInfo.filename; + if (less.mode !== 'browser' && less.mode !== 'rhino') { + filename = require('path').resolve(filename); + } + + return { + lineNumber: getLocation(index, inputStream).line + 1, + fileName: filename + }; + } + + function LessError(e, env) { + var input = getInput(e, env), + loc = getLocation(e.index, input), + line = loc.line, + col = loc.column, + callLine = e.call && getLocation(e.call, input).line, + lines = input.split('\n'); + + this.type = e.type || 'Syntax'; + this.message = e.message; + this.filename = e.filename || env.currentFileInfo.filename; + this.index = e.index; + this.line = typeof(line) === 'number' ? line + 1 : null; + this.callLine = callLine + 1; + this.callExtract = lines[callLine]; + this.stack = e.stack; + this.column = col; + this.extract = [ + lines[line - 1], + lines[line], + lines[line + 1] + ]; + } + + LessError.prototype = new Error(); + LessError.prototype.constructor = LessError; + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + // + // The Parser + // + parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // @param str A string containing 'less' markup + // @param callback call `callback` when done. + // @param [additionalData] An optional map which can contains vars - a map (key, value) of variables to apply + // + parse: function (str, callback, additionalData) { + var root, line, lines, error = null, globalVars, modifyVars, preText = ""; + + i = j = currentPos = furthest = 0; + + globalVars = (additionalData && additionalData.globalVars) ? less.Parser.serializeVars(additionalData.globalVars) + '\n' : ''; + modifyVars = (additionalData && additionalData.modifyVars) ? '\n' + less.Parser.serializeVars(additionalData.modifyVars) : ''; + + if (globalVars || (additionalData && additionalData.banner)) { + preText = ((additionalData && additionalData.banner) ? additionalData.banner : "") + globalVars; + parser.imports.contentsIgnoredChars[env.currentFileInfo.filename] = preText.length; + } + + str = str.replace(/\r\n/g, '\n'); + // Remove potential UTF Byte Order Mark + input = str = preText + str.replace(/^\uFEFF/, '') + modifyVars; + parser.imports.contents[env.currentFileInfo.filename] = str; + + // Split the input into chunks. + chunks = (function (input) { + var len = input.length, level = 0, parenLevel = 0, + lastOpening, lastOpeningParen, lastMultiComment, lastMultiCommentEndBrace, + chunks = [], emitFrom = 0, + parserCurrentIndex, currentChunkStartIndex, cc, cc2, matched; + + function fail(msg, index) { + error = new (LessError)({ + index: index || parserCurrentIndex, + type: 'Parse', + message: msg, + filename: env.currentFileInfo.filename + }, env); + } + + function emitChunk(force) { + var len = parserCurrentIndex - emitFrom; + if (((len < 512) && !force) || !len) { + return; + } + chunks.push(input.slice(emitFrom, parserCurrentIndex + 1)); + emitFrom = parserCurrentIndex + 1; + } + + for (parserCurrentIndex = 0; parserCurrentIndex < len; parserCurrentIndex++) { + cc = input.charCodeAt(parserCurrentIndex); + if (((cc >= 97) && (cc <= 122)) || (cc < 34)) { + // a-z or whitespace + continue; + } + + switch (cc) { + case 40: // ( + parenLevel++; + lastOpeningParen = parserCurrentIndex; + continue; + case 41: // ) + if (--parenLevel < 0) { + return fail("missing opening `(`"); + } + continue; + case 59: // ; + if (!parenLevel) { + emitChunk(); + } + continue; + case 123: // { + level++; + lastOpening = parserCurrentIndex; + continue; + case 125: // } + if (--level < 0) { + return fail("missing opening `{`"); + } + if (!level && !parenLevel) { + emitChunk(); + } + continue; + case 92: // \ + if (parserCurrentIndex < len - 1) { + parserCurrentIndex++; + continue; + } + return fail("unescaped `\\`"); + case 34: + case 39: + case 96: // ", ' and ` + matched = 0; + currentChunkStartIndex = parserCurrentIndex; + for (parserCurrentIndex = parserCurrentIndex + 1; parserCurrentIndex < len; parserCurrentIndex++) { + cc2 = input.charCodeAt(parserCurrentIndex); + if (cc2 > 96) { + continue; + } + if (cc2 == cc) { + matched = 1; + break; + } + if (cc2 == 92) { // \ + if (parserCurrentIndex == len - 1) { + return fail("unescaped `\\`"); + } + parserCurrentIndex++; + } + } + if (matched) { + continue; + } + return fail("unmatched `" + String.fromCharCode(cc) + "`", currentChunkStartIndex); + case 47: // /, check for comment + if (parenLevel || (parserCurrentIndex == len - 1)) { + continue; + } + cc2 = input.charCodeAt(parserCurrentIndex + 1); + if (cc2 == 47) { + // //, find lnfeed + for (parserCurrentIndex = parserCurrentIndex + 2; parserCurrentIndex < len; parserCurrentIndex++) { + cc2 = input.charCodeAt(parserCurrentIndex); + if ((cc2 <= 13) && ((cc2 == 10) || (cc2 == 13))) { + break; + } + } + } else if (cc2 == 42) { + // /*, find */ + lastMultiComment = currentChunkStartIndex = parserCurrentIndex; + for (parserCurrentIndex = parserCurrentIndex + 2; parserCurrentIndex < len - 1; parserCurrentIndex++) { + cc2 = input.charCodeAt(parserCurrentIndex); + if (cc2 == 125) { + lastMultiCommentEndBrace = parserCurrentIndex; + } + if (cc2 != 42) { + continue; + } + if (input.charCodeAt(parserCurrentIndex + 1) == 47) { + break; + } + } + if (parserCurrentIndex == len - 1) { + return fail("missing closing `*/`", currentChunkStartIndex); + } + parserCurrentIndex++; + } + continue; + case 42: // *, check for unmatched */ + if ((parserCurrentIndex < len - 1) && (input.charCodeAt(parserCurrentIndex + 1) == 47)) { + return fail("unmatched `/*`"); + } + continue; + } + } + + if (level !== 0) { + if ((lastMultiComment > lastOpening) && (lastMultiCommentEndBrace > lastMultiComment)) { + return fail("missing closing `}` or `*/`", lastOpening); + } else { + return fail("missing closing `}`", lastOpening); + } + } else if (parenLevel !== 0) { + return fail("missing closing `)`", lastOpeningParen); + } + + emitChunk(true); + return chunks; + })(str); + + if (error) { + return callback(new (LessError)(error, env)); + } + + current = chunks[0]; + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + try { + root = new (tree.Ruleset)(null, this.parsers.primary()); + root.root = true; + root.firstRoot = true; + } catch (e) { + return callback(new (LessError)(e, env)); + } + + root.toCSS = (function (evaluate) { + return function (options, variables) { + options = options || {}; + var evaldRoot, + css, + evalEnv = new tree.evalEnv(options); + + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (!(value instanceof tree.Value)) { + if (!(value instanceof tree.Expression)) { + value = new (tree.Expression)([value]); + } + value = new (tree.Value)([value]); + } + return new (tree.Rule)('@' + k, value, false, null, 0); + }); + evalEnv.frames = [new (tree.Ruleset)(null, variables)]; + } + + try { + var preEvalVisitors = [], + visitors = [ + new (tree.joinSelectorVisitor)(), + new (tree.processExtendsVisitor)(), + new (tree.toCSSVisitor)({compress: Boolean(options.compress)}) + ], i, root = this; + + if (options.plugins) { + for (i = 0; i < options.plugins.length; i++) { + if (options.plugins[i].isPreEvalVisitor) { + preEvalVisitors.push(options.plugins[i]); + } else { + if (options.plugins[i].isPreVisitor) { + visitors.splice(0, 0, options.plugins[i]); + } else { + visitors.push(options.plugins[i]); + } + } + } + } + + for (i = 0; i < preEvalVisitors.length; i++) { + preEvalVisitors[i].run(root); + } + + evaldRoot = evaluate.call(root, evalEnv); + + for (i = 0; i < visitors.length; i++) { + visitors[i].run(evaldRoot); + } + + if (options.sourceMap) { + evaldRoot = new tree.sourceMapOutput( + { + contentsIgnoredCharsMap: parser.imports.contentsIgnoredChars, + writeSourceMap: options.writeSourceMap, + rootNode: evaldRoot, + contentsMap: parser.imports.contents, + sourceMapFilename: options.sourceMapFilename, + sourceMapURL: options.sourceMapURL, + outputFilename: options.sourceMapOutputFilename, + sourceMapBasepath: options.sourceMapBasepath, + sourceMapRootpath: options.sourceMapRootpath, + outputSourceFiles: options.outputSourceFiles, + sourceMapGenerator: options.sourceMapGenerator + }); + } + + css = evaldRoot.toCSS({ + compress: Boolean(options.compress), + dumpLineNumbers: env.dumpLineNumbers, + strictUnits: Boolean(options.strictUnits), + numPrecision: 8 + }); + } catch (e) { + throw new (LessError)(e, env); + } + + if (options.cleancss && less.mode === 'node') { + var CleanCSS = require('clean-css'), + cleancssOptions = options.cleancssOptions || {}; + + if (cleancssOptions.keepSpecialComments === undefined) { + cleancssOptions.keepSpecialComments = "*"; + } + cleancssOptions.processImport = false; + cleancssOptions.noRebase = true; + if (cleancssOptions.noAdvanced === undefined) { + cleancssOptions.noAdvanced = true; + } + + return new CleanCSS(cleancssOptions).minify(css); + } else if (options.compress) { + return css.replace(/(^(\s)+)|((\s)+$)/g, ""); + } else { + return css; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + var loc = getLocation(i, input); + lines = input.split('\n'); + line = loc.line + 1; + + error = { + type: "Parse", + message: "Unrecognised input", + index: i, + filename: env.currentFileInfo.filename, + line: line, + column: loc.column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + var finish = function (e) { + e = error || e || parser.imports.error; + + if (e) { + if (!(e instanceof LessError)) { + e = new (LessError)(e, env); + } + + return callback(e); + } + else { + return callback(null, root); + } + }; + + if (env.processImports !== false) { + new tree.importVisitor(this.imports, finish) + .run(root); + } else { + return finish(); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some Less code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: parsers = { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var mixin = this.mixin, $re = _$re, root = [], node; + + while (current) { + node = this.extendRule() || mixin.definition() || this.rule() || this.ruleset() || + mixin.call() || this.comment() || this.rulesetCall() || this.directive(); + if (node) { + root.push(node); + } else { + if (!($re(/^[\s\n]+/) || $re(/^;+/))) { + break; + } + } + if (peekChar('}')) { + break; + } + } + + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') { + return; + } + + if (input.charAt(i + 1) === '/') { + return new (tree.Comment)($re(/^\/\/.*/), true, i, env.currentFileInfo); + } + comment = $re(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/); + if (comment) { + return new (tree.Comment)(comment, false, i, env.currentFileInfo); + } + }, + + comments: function () { + var comment, comments = []; + + while (true) { + comment = this.comment(); + if (!comment) { + break; + } + comments.push(comment); + } + + return comments; + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e, index = i; + + if (input.charAt(j) === '~') { + j++; + e = true; + } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") { + return; + } + + if (e) { + $char('~'); + } + + str = $re(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/); + if (str) { + return new (tree.Quoted)(str[0], str[1] || str[2], e, index, env.currentFileInfo); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + + k = $re(/^%|^[_A-Za-z-][_A-Za-z0-9-]*/); + if (k) { + var color = tree.Color.fromKeyword(k); + if (color) { + return color; + } + return new (tree.Keyword)(k); + } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, nameLC, args, alpha_ret, index = i; + + name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(current); + if (!name) { + return; + } + + name = name[1]; + nameLC = name.toLowerCase(); + if (nameLC === 'url') { + return null; + } + + i += name.length; + + if (nameLC === 'alpha') { + alpha_ret = parsers.alpha(); + if (typeof alpha_ret !== 'undefined') { + return alpha_ret; + } + } + + $char('('); // Parse the '(' and consume whitespace. + + args = this.arguments(); + + if (!$char(')')) { + return; + } + + if (name) { + return new (tree.Call)(name, args, index, env.currentFileInfo); + } + }, + arguments: function () { + var args = [], arg; + + while (true) { + arg = this.assignment() || parsers.expression(); + if (!arg) { + break; + } + args.push(arg); + if (!$char(',')) { + break; + } + } + return args; + }, + literal: function () { + return this.dimension() || + this.color() || + this.quoted() || + this.unicodeDescriptor(); + }, + + // Assignments are argument entities for calls. + // They are present in ie filter properties as shown below. + // + // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) + // + + assignment: function () { + var key, value; + key = $re(/^\w+(?=\s?=)/i); + if (!key) { + return; + } + if (!$char('=')) { + return; + } + value = parsers.entity(); + if (value) { + return new (tree.Assignment)(key, value); + } + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$re(/^url\(/)) { + return; + } + + value = this.quoted() || this.variable() || + $re(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/) || ""; + + expectChar(')'); + + return new (tree.URL)((value.value != null || value instanceof tree.Variable) + ? value : new (tree.Anonymous)(value), env.currentFileInfo); + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $re(/^@@?[\w-]+/))) { + return new (tree.Variable)(name, index, env.currentFileInfo); + } + }, + + // A variable entity useing the protective {} e.g. @{var} + variableCurly: function () { + var curly, index = i; + + if (input.charAt(i) === '@' && (curly = $re(/^@\{([\w-]+)\}/))) { + return new (tree.Variable)("@" + curly[1], index, env.currentFileInfo); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $re(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/))) { + var colorCandidateString = rgb.input.match(/^#([\w]+).*/); // strip colons, brackets, whitespaces and other characters that should not definitely be part of color string + colorCandidateString = colorCandidateString[1]; + if (!colorCandidateString.match(/^[A-Fa-f0-9]+$/)) { // verify if candidate consists only of allowed HEX characters + error("Invalid HEX color code"); + } + return new (tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + //Is the first char of the dimension 0-9, '.', '+' or '-' + if ((c > 57 || c < 43) || c === 47 || c == 44) { + return; + } + + value = $re(/^([+-]?\d*\.?\d+)(%|[a-z]+)?/); + if (value) { + return new (tree.Dimension)(value[1], value[2]); + } + }, + + // + // A unicode descriptor, as is used in unicode-range + // + // U+0?? or U+00A1-00A9 + // + unicodeDescriptor: function () { + var ud; + + ud = $re(/^U\+[0-9a-fA-F?]+(\-[0-9a-fA-F?]+)?/); + if (ud) { + return new (tree.UnicodeDescriptor)(ud[0]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { + j++; + e = true; + } // Escaped strings + if (input.charAt(j) !== '`') { + return; + } + if (env.javascriptEnabled !== undefined && !env.javascriptEnabled) { + error("You are using JavaScript, which has been disabled."); + } + + if (e) { + $char('~'); + } + + str = $re(/^`([^`]*)`/); + if (str) { + return new (tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $re(/^(@[\w-]+)\s*:/))) { + return name[1]; + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink(); + // + rulesetCall: function () { + var name; + + if (input.charAt(i) === '@' && (name = $re(/^(@[\w-]+)\s*\(\s*\)\s*;/))) { + return new tree.RulesetCall(name[1]); + } + }, + + // + // extend syntax - used to extend selectors + // + extend: function (isRule) { + var elements, e, index = i, option, extendList, extend; + + if (!(isRule ? $re(/^&:extend\(/) : $re(/^:extend\(/))) { + return; + } + + do { + option = null; + elements = null; + while (!(option = $re(/^(all)(?=\s*(\)|,))/))) { + e = this.element(); + if (!e) { + break; + } + if (elements) { + elements.push(e); + } else { + elements = [e]; + } + } + + option = option && option[1]; + if (!elements) + error("Missing target selector for :extend()."); + extend = new (tree.Extend)(new (tree.Selector)(elements), option, index); + if (extendList) { + extendList.push(extend); + } else { + extendList = [extend]; + } + + } while ($char(",")); + + expect(/^\)/); + + if (isRule) { + expect(/^;/); + } + + return extendList; + }, + + // + // extendRule - used in a rule to extend all the parent selectors + // + extendRule: function () { + return this.extend(true); + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var s = input.charAt(i), important = false, index = i, elemIndex, + elements, elem, e, c, args; + + if (s !== '.' && s !== '#') { + return; + } + + save(); // stop us absorbing part of an invalid selector + + while (true) { + elemIndex = i; + e = $re(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/); + if (!e) { + break; + } + elem = new (tree.Element)(c, e, elemIndex, env.currentFileInfo); + if (elements) { + elements.push(elem); + } else { + elements = [elem]; + } + c = $char('>'); + } + + if (elements) { + if ($char('(')) { + args = this.args(true).args; + expectChar(')'); + } + + if (parsers.important()) { + important = true; + } + + if (parsers.end()) { + forget(); + return new (tree.mixin.Call)(elements, args, index, env.currentFileInfo, important); + } + } + + restore(); + }, + args: function (isCall) { + var parsers = parser.parsers, entities = parsers.entities, + returner = {args: null, variadic: false}, + expressions = [], argsSemiColon = [], argsComma = [], + isSemiColonSeperated, expressionContainsNamed, name, nameLoop, value, arg; + + save(); + + while (true) { + if (isCall) { + arg = parsers.detachedRuleset() || parsers.expression(); + } else { + parsers.comments(); + if (input.charAt(i) === '.' && $re(/^\.{3}/)) { + returner.variadic = true; + if ($char(";") && !isSemiColonSeperated) { + isSemiColonSeperated = true; + } + (isSemiColonSeperated ? argsSemiColon : argsComma) + .push({variadic: true}); + break; + } + arg = entities.variable() || entities.literal() || entities.keyword(); + } + + if (!arg) { + break; + } + + nameLoop = null; + if (arg.throwAwayComments) { + arg.throwAwayComments(); + } + value = arg; + var val = null; + + if (isCall) { + // Variable + if (arg.value && arg.value.length == 1) { + val = arg.value[0]; + } + } else { + val = arg; + } + + if (val && val instanceof tree.Variable) { + if ($char(':')) { + if (expressions.length > 0) { + if (isSemiColonSeperated) { + error("Cannot mix ; and , as delimiter types"); + } + expressionContainsNamed = true; + } + + // we do not support setting a ruleset as a default variable - it doesn't make sense + // However if we do want to add it, there is nothing blocking it, just don't error + // and remove isCall dependency below + value = (isCall && parsers.detachedRuleset()) || parsers.expression(); + + if (!value) { + if (isCall) { + error("could not understand value for named argument"); + } else { + restore(); + returner.args = []; + return returner; + } + } + nameLoop = (name = val.name); + } else if (!isCall && $re(/^\.{3}/)) { + returner.variadic = true; + if ($char(";") && !isSemiColonSeperated) { + isSemiColonSeperated = true; + } + (isSemiColonSeperated ? argsSemiColon : argsComma) + .push({name: arg.name, variadic: true}); + break; + } else if (!isCall) { + name = nameLoop = val.name; + value = null; + } + } + + if (value) { + expressions.push(value); + } + + argsComma.push({name: nameLoop, value: value}); + + if ($char(',')) { + continue; + } + + if ($char(';') || isSemiColonSeperated) { + + if (expressionContainsNamed) { + error("Cannot mix ; and , as delimiter types"); + } + + isSemiColonSeperated = true; + + if (expressions.length > 1) { + value = new (tree.Value)(expressions); + } + argsSemiColon.push({name: name, value: value}); + + name = null; + expressions = []; + expressionContainsNamed = false; + } + } + + forget(); + returner.args = isSemiColonSeperated ? argsSemiColon : argsComma; + return returner; + }, + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, cond, variadic = false; + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*\}/)) { + return; + } + + save(); + + match = $re(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/); + if (match) { + name = match[1]; + + var argInfo = this.args(false); + params = argInfo.args; + variadic = argInfo.variadic; + + // .mixincall("@{a}"); + // looks a bit like a mixin definition.. + // also + // .mixincall(@a: {rule: set;}); + // so we have to be nice and restore + if (!$char(')')) { + furthest = i; + restore(); + return; + } + + parsers.comments(); + + if ($re(/^when/)) { // Guard + cond = expect(parsers.conditions, 'expected condition'); + } + + ruleset = parsers.block(); + + if (ruleset) { + forget(); + return new (tree.mixin.Definition)(name, params, ruleset, cond, variadic); + } else { + restore(); + } + } else { + forget(); + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + var entities = this.entities; + + return entities.literal() || entities.variable() || entities.url() || + entities.call() || entities.keyword() || entities.javascript() || + this.comment(); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $char(';') || peekChar('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (!$re(/^\(opacity=/i)) { + return; + } + value = $re(/^\d+/) || this.entities.variable(); + if (value) { + expectChar(')'); + return new (tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, c, v, index = i; + + c = this.combinator(); + + e = $re(/^(?:\d+\.\d+|\d+)%/) || $re(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/) || + $char('*') || $char('&') || this.attribute() || $re(/^\([^()@]+\)/) || $re(/^[\.#](?=@)/) || + this.entities.variableCurly(); + + if (!e) { + save(); + if ($char('(')) { + if ((v = this.selector()) && $char(')')) { + e = new (tree.Paren)(v); + forget(); + } else { + restore(); + } + } else { + forget(); + } + } + + if (e) { + return new (tree.Element)(c, e, index, env.currentFileInfo); + } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var c = input.charAt(i); + + if (c === '/') { + save(); + var slashedCombinator = $re(/^\/[a-z]+\//i); + if (slashedCombinator) { + forget(); + return new (tree.Combinator)(slashedCombinator); + } + restore(); + } + + if (c === '>' || c === '+' || c === '~' || c === '|' || c === '^') { + i++; + if (c === '^' && input.charAt(i) === '^') { + c = '^^'; + i++; + } + while (isWhitespace(input, i)) { + i++; + } + return new (tree.Combinator)(c); + } else if (isWhitespace(input, i - 1)) { + return new (tree.Combinator)(" "); + } else { + return new (tree.Combinator)(null); + } + }, + // + // A CSS selector (see selector below) + // with less extensions e.g. the ability to extend and guard + // + lessSelector: function () { + return this.selector(true); + }, + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function (isLess) { + var index = i, $re = _$re, elements, extendList, c, e, extend, when, condition; + + while ((isLess && (extend = this.extend())) || (isLess && (when = $re(/^when/))) || (e = this.element())) { + if (when) { + condition = expect(this.conditions, 'expected condition'); + } else if (condition) { + error("CSS guard can only be used at the end of selector"); + } else if (extend) { + if (extendList) { + extendList.push(extend); + } else { + extendList = [extend]; + } + } else { + if (extendList) { + error("Extend can only be used at the end of selector"); + } + c = input.charAt(i); + if (elements) { + elements.push(e); + } else { + elements = [e]; + } + e = null; + } + if (c === '{' || c === '}' || c === ';' || c === ',' || c === ')') { + break; + } + } + + if (elements) { + return new (tree.Selector)(elements, extendList, condition, index, env.currentFileInfo); + } + if (extendList) { + error("Extend must be used to extend a selector, it cannot be used on its own"); + } + }, + attribute: function () { + if (!$char('[')) { + return; + } + + var entities = this.entities, + key, val, op; + + if (!(key = entities.variableCurly())) { + key = expect(/^(?:[_A-Za-z0-9-\*]*\|)?(?:[_A-Za-z0-9-]|\\.)+/); + } + + op = $re(/^[|~*$^]?=/); + if (op) { + val = entities.quoted() || $re(/^[0-9]+%/) || $re(/^[\w-]+/) || entities.variableCurly(); + } + + expectChar(']'); + + return new (tree.Attribute)(key, op, val); + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + if ($char('{') && (content = this.primary()) && $char('}')) { + return content; + } + }, + + blockRuleset: function () { + var block = this.block(); + + if (block) { + block = new tree.Ruleset(null, block); + } + return block; + }, + + detachedRuleset: function () { + var blockRuleset = this.blockRuleset(); + if (blockRuleset) { + return new tree.DetachedRuleset(blockRuleset); + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors, s, rules, debugInfo; + + save(); + + if (env.dumpLineNumbers) { + debugInfo = getDebugInfo(i, input, env); + } + + while (true) { + s = this.lessSelector(); + if (!s) { + break; + } + if (selectors) { + selectors.push(s); + } else { + selectors = [s]; + } + this.comments(); + if (s.condition && selectors.length > 1) { + error("Guards are only currently allowed on a single selector."); + } + if (!$char(',')) { + break; + } + if (s.condition) { + error("Guards are only currently allowed on a single selector."); + } + this.comments(); + } + + if (selectors && (rules = this.block())) { + forget(); + var ruleset = new (tree.Ruleset)(selectors, rules, env.strictImports); + if (env.dumpLineNumbers) { + ruleset.debugInfo = debugInfo; + } + return ruleset; + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function (tryAnonymous) { + var name, value, startOfRule = i, c = input.charAt(startOfRule), important, merge, isVariable; + + if (c === '.' || c === '#' || c === '&') { + return; + } + + save(); + + name = this.variable() || this.ruleProperty(); + if (name) { + isVariable = typeof name === "string"; + + if (isVariable) { + value = this.detachedRuleset(); + } + + this.comments(); + if (!value) { + // prefer to try to parse first if its a variable or we are compressing + // but always fallback on the other one + value = !tryAnonymous && (env.compress || isVariable) ? + (this.value() || this.anonymousValue()) : + (this.anonymousValue() || this.value()); + + important = this.important(); + + // a name returned by this.ruleProperty() is always an array of the form: + // [string-1, ..., string-n, ""] or [string-1, ..., string-n, "+"] + // where each item is a tree.Keyword or tree.Variable + merge = !isVariable && name.pop().value; + } + + if (value && this.end()) { + forget(); + return new (tree.Rule)(name, value, important, merge, startOfRule, env.currentFileInfo); + } else { + furthest = i; + restore(); + if (value && !tryAnonymous) { + return this.rule(true); + } + } + } else { + forget(); + } + }, + anonymousValue: function () { + var match; + match = /^([^@+\/'"*`(;{}-]*);/.exec(current); + if (match) { + i += match[0].length - 1; + return new (tree.Anonymous)(match[1]); + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environment, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path, features, index = i; + + var dir = $re(/^@import?\s+/); + + if (dir) { + var options = (dir ? this.importOptions() : null) || {}; + + if ((path = this.entities.quoted() || this.entities.url())) { + features = this.mediaFeatures(); + + if (!$(';')) { + i = index; + error("missing semi-colon or unrecognised media features on import"); + } + features = features && new (tree.Value)(features); + return new (tree.Import)(path, features, options, index, env.currentFileInfo); + } + else { + i = index; + error("malformed import statement"); + } + } + }, + + importOptions: function () { + var o, options = {}, optionName, value; + + // list of options, surrounded by parens + if (!$char('(')) { + return null; + } + do { + o = this.importOption(); + if (o) { + optionName = o; + value = true; + switch (optionName) { + case "css": + optionName = "less"; + value = false; + break; + case "once": + optionName = "multiple"; + value = false; + break; + } + options[optionName] = value; + if (!$char(',')) { + break; + } + } + } while (o); + expectChar(')'); + return options; + }, + + importOption: function () { + var opt = $re(/^(less|css|multiple|once|inline|reference)/); + if (opt) { + return opt[1]; + } + }, + + mediaFeature: function () { + var entities = this.entities, nodes = [], e, p; + do { + e = entities.keyword() || entities.variable(); + if (e) { + nodes.push(e); + } else if ($char('(')) { + p = this.property(); + e = this.value(); + if ($char(')')) { + if (p && e) { + nodes.push(new (tree.Paren)(new (tree.Rule)(p, e, null, null, i, env.currentFileInfo, true))); + } else if (e) { + nodes.push(new (tree.Paren)(e)); + } else { + return null; + } + } else { + return null; + } + } + } while (e); + + if (nodes.length > 0) { + return new (tree.Expression)(nodes); + } + }, + + mediaFeatures: function () { + var entities = this.entities, features = [], e; + do { + e = this.mediaFeature(); + if (e) { + features.push(e); + if (!$char(',')) { + break; + } + } else { + e = entities.variable(); + if (e) { + features.push(e); + if (!$char(',')) { + break; + } + } + } + } while (e); + + return features.length > 0 ? features : null; + }, + + media: function () { + var features, rules, media, debugInfo; + + if (env.dumpLineNumbers) { + debugInfo = getDebugInfo(i, input, env); + } + + if ($re(/^@media/)) { + features = this.mediaFeatures(); + + rules = this.block(); + if (rules) { + media = new (tree.Media)(rules, features, i, env.currentFileInfo); + if (env.dumpLineNumbers) { + media.debugInfo = debugInfo; + } + return media; + } + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var index = i, name, value, rules, nonVendorSpecificName, + hasIdentifier, hasExpression, hasUnknown, hasBlock = true; + + if (input.charAt(i) !== '@') { + return; + } + + value = this['import']() || this.media(); + if (value) { + return value; + } + + save(); + + name = $re(/^@[a-z-]+/); + + if (!name) { + return; + } + + nonVendorSpecificName = name; + if (name.charAt(1) == '-' && name.indexOf('-', 2) > 0) { + nonVendorSpecificName = "@" + name.slice(name.indexOf('-', 2) + 1); + } + + switch (nonVendorSpecificName) { + /* + case "@font-face": + case "@viewport": + case "@top-left": + case "@top-left-corner": + case "@top-center": + case "@top-right": + case "@top-right-corner": + case "@bottom-left": + case "@bottom-left-corner": + case "@bottom-center": + case "@bottom-right": + case "@bottom-right-corner": + case "@left-top": + case "@left-middle": + case "@left-bottom": + case "@right-top": + case "@right-middle": + case "@right-bottom": + hasBlock = true; + break; + */ + case "@charset": + hasIdentifier = true; + hasBlock = false; + break; + case "@namespace": + hasExpression = true; + hasBlock = false; + break; + case "@keyframes": + hasIdentifier = true; + break; + case "@host": + case "@page": + case "@document": + case "@supports": + hasUnknown = true; + break; + } + + this.comments(); + + if (hasIdentifier) { + value = this.entity(); + if (!value) { + error("expected " + name + " identifier"); + } + } else if (hasExpression) { + value = this.expression(); + if (!value) { + error("expected " + name + " expression"); + } + } else if (hasUnknown) { + value = ($re(/^[^{;]+/) || '').trim(); + if (value) { + value = new (tree.Anonymous)(value); + } + } + + this.comments(); + + if (hasBlock) { + rules = this.blockRuleset(); + } + + if (rules || (!hasBlock && value && $char(';'))) { + forget(); + return new (tree.Directive)(name, value, rules, index, env.currentFileInfo, + env.dumpLineNumbers ? getDebugInfo(index, input, env) : null); + } + + restore(); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = []; + + do { + e = this.expression(); + if (e) { + expressions.push(e); + if (!$char(',')) { + break; + } + } + } while (e); + + if (expressions.length > 0) { + return new (tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $re(/^! *important/); + } + }, + sub: function () { + var a, e; + + if ($char('(')) { + a = this.addition(); + if (a) { + e = new (tree.Expression)([a]); + expectChar(')'); + e.parens = true; + return e; + } + } + }, + multiplication: function () { + var m, a, op, operation, isSpaced; + m = this.operand(); + if (m) { + isSpaced = isWhitespace(input, i - 1); + while (true) { + if (peek(/^\/[*\/]/)) { + break; + } + + save(); + + op = $char('/') || $char('*'); + + if (!op) { + forget(); + break; + } + + a = this.operand(); + + if (!a) { + restore(); + break; + } + forget(); + + m.parensInOp = true; + a.parensInOp = true; + operation = new (tree.Operation)(op, [operation || m, a], isSpaced); + isSpaced = isWhitespace(input, i - 1); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation, isSpaced; + m = this.multiplication(); + if (m) { + isSpaced = isWhitespace(input, i - 1); + while (true) { + op = $re(/^[-+]\s+/) || (!isSpaced && ($char('+') || $char('-'))); + if (!op) { + break; + } + a = this.multiplication(); + if (!a) { + break; + } + + m.parensInOp = true; + a.parensInOp = true; + operation = new (tree.Operation)(op, [operation || m, a], isSpaced); + isSpaced = isWhitespace(input, i - 1); + } + return operation || m; + } + }, + conditions: function () { + var a, b, index = i, condition; + + a = this.condition(); + if (a) { + while (true) { + if (!peek(/^,\s*(not\s*)?\(/) || !$char(',')) { + break; + } + b = this.condition(); + if (!b) { + break; + } + condition = new (tree.Condition)('or', condition || a, b, index); + } + return condition || a; + } + }, + condition: function () { + var entities = this.entities, index = i, negate = false, + a, b, c, op; + + if ($re(/^not/)) { + negate = true; + } + expectChar('('); + a = this.addition() || entities.keyword() || entities.quoted(); + if (a) { + op = $re(/^(?:>=|<=|=<|[<=>])/); + if (op) { + b = this.addition() || entities.keyword() || entities.quoted(); + if (b) { + c = new (tree.Condition)(op, a, b, index, negate); + } else { + error('expected expression'); + } + } else { + c = new (tree.Condition)('=', a, new (tree.Keyword)('true'), index, negate); + } + expectChar(')'); + return $re(/^and/) ? new (tree.Condition)('and', c, this.condition()) : c; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var entities = this.entities, + p = input.charAt(i + 1), negate; + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { + negate = $char('-'); + } + var o = this.sub() || entities.dimension() || + entities.color() || entities.variable() || + entities.call(); + + if (negate) { + o.parensInOp = true; + o = new (tree.Negative)(o); + } + + return o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var entities = [], e, delim; + + do { + e = this.addition() || this.entity(); + if (e) { + entities.push(e); + // operations do not allow keyword "/" dimension (e.g. small/20px) so we support that here + if (!peek(/^\/[\/*]/)) { + delim = $char('/'); + if (delim) { + entities.push(new (tree.Anonymous)(delim)); + } + } + } + } while (e); + if (entities.length > 0) { + return new (tree.Expression)(entities); + } + }, + property: function () { + var name = $re(/^(\*?-?[_a-zA-Z0-9-]+)\s*:/); + if (name) { + return name[1]; + } + }, + ruleProperty: function () { + var c = current, name = [], index = [], length = 0, s, k; + + function match(re) { + var a = re.exec(c); + if (a) { + index.push(i + length); + length += a[0].length; + c = c.slice(a[1].length); + return name.push(a[1]); + } + } + + function cutOutBlockComments() { + //match block comments + var a = /^\s*\/\*(?:[^*]|\*+[^\/*])*\*+\//.exec(c); + if (a) { + length += a[0].length; + c = c.slice(a[0].length); + return true; + } + return false; + } + + match(/^(\*?)/); + while (match(/^((?:[\w-]+)|(?:@\{[\w-]+\}))/)); // ! + while (cutOutBlockComments()); + if ((name.length > 1) && match(/^\s*((?:\+_|\+)?)\s*:/)) { + // at last, we have the complete match now. move forward, + // convert name particles to tree objects and return: + skipWhitespace(length); + if (name[0] === '') { + name.shift(); + index.shift(); + } + for (k = 0; k < name.length; k++) { + s = name[k]; + name[k] = (s.charAt(0) !== '@') + ? new (tree.Keyword)(s) + : new (tree.Variable)('@' + s.slice(2, -1), + index[k], env.currentFileInfo); + } + return name; + } + } + } + }; + return parser; +}; +less.Parser.serializeVars = function (vars) { + var s = ''; + + for (var name in vars) { + if (Object.hasOwnProperty.call(vars, name)) { + var value = vars[name]; + s += ((name[0] === '@') ? '' : '@') + name + ': ' + value + + ((('' + value).slice(-1) === ';') ? '' : ';'); + } + } + + return s; +}; + +(function (tree) { + + tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { + return scaled(c, 255); + }); + a = number(a); + return new (tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) { + return m1 + (m2 - m1) * h * 6; + } + else if (h * 2 < 1) { + return m2; + } + else if (h * 3 < 2) { + return m1 + (m2 - m1) * (2 / 3 - h) * 6; + } + else { + return m1; + } + } + + h = (number(h) % 360) / 360; + s = clamp(number(s)); + l = clamp(number(l)); + a = clamp(number(a)); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1 / 3) * 255, + hue(h) * 255, + hue(h - 1 / 3) * 255, + a); + }, + + hsv: function (h, s, v) { + return this.hsva(h, s, v, 1.0); + }, + + hsva: function (h, s, v, a) { + h = ((number(h) % 360) / 360) * 360; + s = number(s); + v = number(v); + a = number(a); + + var i, f; + i = Math.floor((h / 60) % 6); + f = (h / 60) - i; + + var vs = [v, + v * (1 - s), + v * (1 - f * s), + v * (1 - (1 - f) * s)]; + var perm = [[0, 3, 1], + [2, 0, 1], + [1, 0, 3], + [1, 2, 0], + [3, 1, 0], + [0, 1, 2]]; + + return this.rgba(vs[perm[i][0]] * 255, + vs[perm[i][1]] * 255, + vs[perm[i][2]] * 255, + a); + }, + + hue: function (color) { + return new (tree.Dimension)(color.toHSL().h); + }, + saturation: function (color) { + return new (tree.Dimension)(color.toHSL().s * 100, '%'); + }, + lightness: function (color) { + return new (tree.Dimension)(color.toHSL().l * 100, '%'); + }, + hsvhue: function (color) { + return new (tree.Dimension)(color.toHSV().h); + }, + hsvsaturation: function (color) { + return new (tree.Dimension)(color.toHSV().s * 100, '%'); + }, + hsvvalue: function (color) { + return new (tree.Dimension)(color.toHSV().v * 100, '%'); + }, + red: function (color) { + return new (tree.Dimension)(color.rgb[0]); + }, + green: function (color) { + return new (tree.Dimension)(color.rgb[1]); + }, + blue: function (color) { + return new (tree.Dimension)(color.rgb[2]); + }, + alpha: function (color) { + return new (tree.Dimension)(color.toHSL().a); + }, + luma: function (color) { + return new (tree.Dimension)(color.luma() * color.alpha * 100, '%'); + }, + luminance: function (color) { + var luminance = + (0.2126 * color.rgb[0] / 255) + + (0.7152 * color.rgb[1] / 255) + + (0.0722 * color.rgb[2] / 255); + + return new (tree.Dimension)(luminance * color.alpha * 100, '%'); + }, + saturate: function (color, amount) { + // filter: saturate(3.2); + // should be kept as is, so check for color + if (!color.rgb) { + return null; + } + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fade: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a = amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + if (!weight) { + weight = new (tree.Dimension)(50); + } + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new (tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new (tree.Dimension)(100)); + }, + contrast: function (color, dark, light, threshold) { + // filter: contrast(3.2); + // should be kept as is, so check for color + if (!color.rgb) { + return null; + } + if (typeof light === 'undefined') { + light = this.rgba(255, 255, 255, 1.0); + } + if (typeof dark === 'undefined') { + dark = this.rgba(0, 0, 0, 1.0); + } + //Figure out which is actually light and dark! + if (dark.luma() > light.luma()) { + var t = light; + light = dark; + dark = t; + } + if (typeof threshold === 'undefined') { + threshold = 0.43; + } else { + threshold = number(threshold); + } + if (color.luma() < threshold) { + return light; + } else { + return dark; + } + }, + e: function (str) { + return new (tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str.value); + }, + escape: function (str) { + return new (tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + replace: function (string, pattern, replacement, flags) { + var result = string.value; + + result = result.replace(new RegExp(pattern.value, flags ? flags.value : ''), replacement.value); + return new (tree.Quoted)(string.quote || '', result, string.escaped); + }, + '%': function (string /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + result = string.value; + + for (var i = 0; i < args.length; i++) { + /*jshint loopfunc:true */ + result = result.replace(/%[sda]/i, function (token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + result = result.replace(/%%/g, '%'); + return new (tree.Quoted)(string.quote || '', result, string.escaped); + }, + unit: function (val, unit) { + if (!(val instanceof tree.Dimension)) { + throw { + type: "Argument", + message: "the first argument to unit must be a number" + (val instanceof tree.Operation ? ". Have you forgotten parenthesis?" : "") + }; + } + if (unit) { + if (unit instanceof tree.Keyword) { + unit = unit.value; + } else { + unit = unit.toCSS(); + } + } else { + unit = ""; + } + return new (tree.Dimension)(val.value, unit); + }, + convert: function (val, unit) { + return val.convertTo(unit.value); + }, + round: function (n, f) { + var fraction = typeof(f) === "undefined" ? 0 : f.value; + return _math(function (num) { + return num.toFixed(fraction); + }, null, n); + }, + pi: function () { + return new (tree.Dimension)(Math.PI); + }, + mod: function (a, b) { + return new (tree.Dimension)(a.value % b.value, a.unit); + }, + pow: function (x, y) { + if (typeof x === "number" && typeof y === "number") { + x = new (tree.Dimension)(x); + y = new (tree.Dimension)(y); + } else if (!(x instanceof tree.Dimension) || !(y instanceof tree.Dimension)) { + throw {type: "Argument", message: "arguments must be numbers"}; + } + + return new (tree.Dimension)(Math.pow(x.value, y.value), x.unit); + }, + _minmax: function (isMin, args) { + args = Array.prototype.slice.call(args); + switch (args.length) { + case 0: + throw {type: "Argument", message: "one or more arguments required"}; + } + var i, j, current, currentUnified, referenceUnified, unit, unitStatic, unitClone, + order = [], // elems only contains original argument values. + values = {}; // key is the unit.toString() for unified tree.Dimension values, + // value is the index into the order array. + for (i = 0; i < args.length; i++) { + current = args[i]; + if (!(current instanceof tree.Dimension)) { + if (Array.isArray(args[i].value)) { + Array.prototype.push.apply(args, Array.prototype.slice.call(args[i].value)); + } + continue; + } + currentUnified = current.unit.toString() === "" && unitClone !== undefined ? new (tree.Dimension)(current.value, unitClone).unify() : current.unify(); + unit = currentUnified.unit.toString() === "" && unitStatic !== undefined ? unitStatic : currentUnified.unit.toString(); + unitStatic = unit !== "" && unitStatic === undefined || unit !== "" && order[0].unify().unit.toString() === "" ? unit : unitStatic; + unitClone = unit !== "" && unitClone === undefined ? current.unit.toString() : unitClone; + j = values[""] !== undefined && unit !== "" && unit === unitStatic ? values[""] : values[unit]; + if (j === undefined) { + if (unitStatic !== undefined && unit !== unitStatic) { + throw{type: "Argument", message: "incompatible types"}; + } + values[unit] = order.length; + order.push(current); + continue; + } + referenceUnified = order[j].unit.toString() === "" && unitClone !== undefined ? new (tree.Dimension)(order[j].value, unitClone).unify() : order[j].unify(); + if (isMin && currentUnified.value < referenceUnified.value || + !isMin && currentUnified.value > referenceUnified.value) { + order[j] = current; + } + } + if (order.length == 1) { + return order[0]; + } + args = order.map(function (a) { + return a.toCSS(this.env); + }).join(this.env.compress ? "," : ", "); + return new (tree.Anonymous)((isMin ? "min" : "max") + "(" + args + ")"); + }, + min: function () { + return this._minmax(true, arguments); + }, + max: function () { + return this._minmax(false, arguments); + }, + "get-unit": function (n) { + return new (tree.Anonymous)(n.unit); + }, + argb: function (color) { + return new (tree.Anonymous)(color.toARGB()); + }, + percentage: function (n) { + return new (tree.Dimension)(n.value * 100, '%'); + }, + color: function (n) { + if (n instanceof tree.Quoted) { + var colorCandidate = n.value, + returnColor; + returnColor = tree.Color.fromKeyword(colorCandidate); + if (returnColor) { + return returnColor; + } + if (/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/.test(colorCandidate)) { + return new (tree.Color)(colorCandidate.slice(1)); + } + throw {type: "Argument", message: "argument must be a color keyword or 3/6 digit hex e.g. #FFF"}; + } else { + throw {type: "Argument", message: "argument must be a string"}; + } + }, + iscolor: function (n) { + return this._isa(n, tree.Color); + }, + isnumber: function (n) { + return this._isa(n, tree.Dimension); + }, + isstring: function (n) { + return this._isa(n, tree.Quoted); + }, + iskeyword: function (n) { + return this._isa(n, tree.Keyword); + }, + isurl: function (n) { + return this._isa(n, tree.URL); + }, + ispixel: function (n) { + return this.isunit(n, 'px'); + }, + ispercentage: function (n) { + return this.isunit(n, '%'); + }, + isem: function (n) { + return this.isunit(n, 'em'); + }, + isunit: function (n, unit) { + return (n instanceof tree.Dimension) && n.unit.is(unit.value || unit) ? tree.True : tree.False; + }, + _isa: function (n, Type) { + return (n instanceof Type) ? tree.True : tree.False; + }, + tint: function (color, amount) { + return this.mix(this.rgb(255, 255, 255), color, amount); + }, + shade: function (color, amount) { + return this.mix(this.rgb(0, 0, 0), color, amount); + }, + extract: function (values, index) { + index = index.value - 1; // (1-based index) + // handle non-array values as an array of length 1 + // return 'undefined' if index is invalid + return Array.isArray(values.value) + ? values.value[index] : Array(values)[index]; + }, + length: function (values) { + var n = Array.isArray(values.value) ? values.value.length : 1; + return new tree.Dimension(n); + }, + + "data-uri": function (mimetypeNode, filePathNode) { + + if (typeof window !== 'undefined') { + return new tree.URL(filePathNode || mimetypeNode, this.currentFileInfo).eval(this.env); + } + + var mimetype = mimetypeNode.value; + var filePath = (filePathNode && filePathNode.value); + + var fs = require('./fs'), + path = require('path'), + useBase64 = false; + + if (arguments.length < 2) { + filePath = mimetype; + } + + var fragmentStart = filePath.indexOf('#'); + var fragment = ''; + if (fragmentStart !== -1) { + fragment = filePath.slice(fragmentStart); + filePath = filePath.slice(0, fragmentStart); + } + + if (this.env.isPathRelative(filePath)) { + if (this.currentFileInfo.relativeUrls) { + filePath = path.join(this.currentFileInfo.currentDirectory, filePath); + } else { + filePath = path.join(this.currentFileInfo.entryPath, filePath); + } + } + + // detect the mimetype if not given + if (arguments.length < 2) { + var mime; + try { + mime = require('mime'); + } catch (ex) { + mime = tree._mime; + } + + mimetype = mime.lookup(filePath); + + // use base 64 unless it's an ASCII or UTF-8 format + var charset = mime.charsets.lookup(mimetype); + useBase64 = ['US-ASCII', 'UTF-8'].indexOf(charset) < 0; + if (useBase64) { + mimetype += ';base64'; + } + } + else { + useBase64 = /;base64$/.test(mimetype); + } + + var buf = fs.readFileSync(filePath); + + // IE8 cannot handle a data-uri larger than 32KB. If this is exceeded + // and the --ieCompat flag is enabled, return a normal url() instead. + var DATA_URI_MAX_KB = 32, + fileSizeInKB = parseInt((buf.length / 1024), 10); + if (fileSizeInKB >= DATA_URI_MAX_KB) { + + if (this.env.ieCompat !== false) { + if (!this.env.silent) { + console.warn("Skipped data-uri embedding of %s because its size (%dKB) exceeds IE8-safe %dKB!", filePath, fileSizeInKB, DATA_URI_MAX_KB); + } + + return new tree.URL(filePathNode || mimetypeNode, this.currentFileInfo).eval(this.env); + } + } + + buf = useBase64 ? buf.toString('base64') + : encodeURIComponent(buf); + + var uri = "\"data:" + mimetype + ',' + buf + fragment + "\""; + return new (tree.URL)(new (tree.Anonymous)(uri)); + }, + + "svg-gradient": function (direction) { + + function throwArgumentDescriptor() { + throw { + type: "Argument", + message: "svg-gradient expects direction, start_color [start_position], [color position,]..., end_color [end_position]" + }; + } + + if (arguments.length < 3) { + throwArgumentDescriptor(); + } + var stops = Array.prototype.slice.call(arguments, 1), + gradientDirectionSvg, + gradientType = "linear", + rectangleDimension = 'x="0" y="0" width="1" height="1"', + useBase64 = true, + renderEnv = {compress: false}, + returner, + directionValue = direction.toCSS(renderEnv), + i, color, position, positionValue, alpha; + + switch (directionValue) { + case "to bottom": + gradientDirectionSvg = 'x1="0%" y1="0%" x2="0%" y2="100%"'; + break; + case "to right": + gradientDirectionSvg = 'x1="0%" y1="0%" x2="100%" y2="0%"'; + break; + case "to bottom right": + gradientDirectionSvg = 'x1="0%" y1="0%" x2="100%" y2="100%"'; + break; + case "to top right": + gradientDirectionSvg = 'x1="0%" y1="100%" x2="100%" y2="0%"'; + break; + case "ellipse": + case "ellipse at center": + gradientType = "radial"; + gradientDirectionSvg = 'cx="50%" cy="50%" r="75%"'; + rectangleDimension = 'x="-50" y="-50" width="101" height="101"'; + break; + default: + throw { + type: "Argument", + message: "svg-gradient direction must be 'to bottom', 'to right', 'to bottom right', 'to top right' or 'ellipse at center'" + }; + } + returner = '' + + '' + + '<' + gradientType + 'Gradient id="gradient" gradientUnits="userSpaceOnUse" ' + gradientDirectionSvg + '>'; + + for (i = 0; i < stops.length; i += 1) { + if (stops[i].value) { + color = stops[i].value[0]; + position = stops[i].value[1]; + } else { + color = stops[i]; + position = undefined; + } + + if (!(color instanceof tree.Color) || (!((i === 0 || i + 1 === stops.length) && position === undefined) && !(position instanceof tree.Dimension))) { + throwArgumentDescriptor(); + } + positionValue = position ? position.toCSS(renderEnv) : i === 0 ? "0%" : "100%"; + alpha = color.alpha; + returner += ''; + } + returner += '' + + ''; + + if (useBase64) { + try { + returner = require('./encoder').encodeBase64(returner); // TODO browser implementation + } catch (e) { + useBase64 = false; + } + } + + returner = "'data:image/svg+xml" + (useBase64 ? ";base64" : "") + "," + returner + "'"; + return new (tree.URL)(new (tree.Anonymous)(returner)); + } + }; + +// these static methods are used as a fallback when the optional 'mime' dependency is missing + tree._mime = { + // this map is intentionally incomplete + // if you want more, install 'mime' dep + _types: { + '.htm': 'text/html', + '.html': 'text/html', + '.gif': 'image/gif', + '.jpg': 'image/jpeg', + '.jpeg': 'image/jpeg', + '.png': 'image/png' + }, + lookup: function (filepath) { + var ext = require('path').extname(filepath), + type = tree._mime._types[ext]; + if (type === undefined) { + throw new Error('Optional dependency "mime" is required for ' + ext); + } + return type; + }, + charsets: { + lookup: function (type) { + // assumes all text types are UTF-8 + return type && (/^text\//).test(type) ? 'UTF-8' : ''; + } + } + }; + +// Math + + var mathFunctions = { + // name, unit + ceil: null, + floor: null, + sqrt: null, + abs: null, + tan: "", + sin: "", + cos: "", + atan: "rad", + asin: "rad", + acos: "rad" + }; + + function _math(fn, unit, n) { + if (!(n instanceof tree.Dimension)) { + throw {type: "Argument", message: "argument must be a number"}; + } + if (unit == null) { + unit = n.unit; + } else { + n = n.unify(); + } + return new (tree.Dimension)(fn(parseFloat(n.value)), unit); + } + +// ~ End of Math + +// Color Blending +// ref: http://www.w3.org/TR/compositing-1 + + function colorBlend(mode, color1, color2) { + var ab = color1.alpha, cb, // backdrop + as = color2.alpha, cs, // source + ar, cr, r = []; // result + + ar = as + ab * (1 - as); + for (var i = 0; i < 3; i++) { + cb = color1.rgb[i] / 255; + cs = color2.rgb[i] / 255; + cr = mode(cb, cs); + if (ar) { + cr = (as * cs + ab * (cb + - as * (cb + cs - cr))) / ar; + } + r[i] = cr * 255; + } + + return new (tree.Color)(r, ar); + } + + var colorBlendMode = { + multiply: function (cb, cs) { + return cb * cs; + }, + screen: function (cb, cs) { + return cb + cs - cb * cs; + }, + overlay: function (cb, cs) { + cb *= 2; + return (cb <= 1) + ? colorBlendMode.multiply(cb, cs) + : colorBlendMode.screen(cb - 1, cs); + }, + softlight: function (cb, cs) { + var d = 1, e = cb; + if (cs > 0.5) { + e = 1; + d = (cb > 0.25) ? Math.sqrt(cb) + : ((16 * cb - 12) * cb + 4) * cb; + } + return cb - (1 - 2 * cs) * e * (d - cb); + }, + hardlight: function (cb, cs) { + return colorBlendMode.overlay(cs, cb); + }, + difference: function (cb, cs) { + return Math.abs(cb - cs); + }, + exclusion: function (cb, cs) { + return cb + cs - 2 * cb * cs; + }, + + // non-w3c functions: + average: function (cb, cs) { + return (cb + cs) / 2; + }, + negation: function (cb, cs) { + return 1 - Math.abs(cb + cs - 1); + } + }; + +// ~ End of Color Blending + + tree.defaultFunc = { + eval: function () { + var v = this.value_, e = this.error_; + if (e) { + throw e; + } + if (v != null) { + return v ? tree.True : tree.False; + } + }, + value: function (v) { + this.value_ = v; + }, + error: function (e) { + this.error_ = e; + }, + reset: function () { + this.value_ = this.error_ = null; + } + }; + + function initFunctions() { + var f, tf = tree.functions; + + // math + for (f in mathFunctions) { + if (mathFunctions.hasOwnProperty(f)) { + tf[f] = _math.bind(null, Math[f], mathFunctions[f]); + } + } + + // color blending + for (f in colorBlendMode) { + if (colorBlendMode.hasOwnProperty(f)) { + tf[f] = colorBlend.bind(null, colorBlendMode[f]); + } + } + + // default + f = tree.defaultFunc; + tf["default"] = f.eval.bind(f); + + } + + initFunctions(); + + function hsla(color) { + return tree.functions.hsla(color.h, color.s, color.l, color.a); + } + + function scaled(n, size) { + if (n instanceof tree.Dimension && n.unit.is('%')) { + return parseFloat(n.value * size / 100); + } else { + return number(n); + } + } + + function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit.is('%') ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } + } + + function clamp(val) { + return Math.min(1, Math.max(0, val)); + } + + tree.fround = function (env, value) { + var p = env && env.numPrecision; + //add "epsilon" to ensure numbers like 1.000000005 (represented as 1.000000004999....) are properly rounded... + return (p == null) ? value : Number((value + 2e-16).toFixed(p)); + }; + + tree.functionCall = function (env, currentFileInfo) { + this.env = env; + this.currentFileInfo = currentFileInfo; + }; + + tree.functionCall.prototype = tree.functions; + +})(require('./tree')); + +(function (tree) { + tree.colors = { + 'aliceblue': '#f0f8ff', + 'antiquewhite': '#faebd7', + 'aqua': '#00ffff', + 'aquamarine': '#7fffd4', + 'azure': '#f0ffff', + 'beige': '#f5f5dc', + 'bisque': '#ffe4c4', + 'black': '#000000', + 'blanchedalmond': '#ffebcd', + 'blue': '#0000ff', + 'blueviolet': '#8a2be2', + 'brown': '#a52a2a', + 'burlywood': '#deb887', + 'cadetblue': '#5f9ea0', + 'chartreuse': '#7fff00', + 'chocolate': '#d2691e', + 'coral': '#ff7f50', + 'cornflowerblue': '#6495ed', + 'cornsilk': '#fff8dc', + 'crimson': '#dc143c', + 'cyan': '#00ffff', + 'darkblue': '#00008b', + 'darkcyan': '#008b8b', + 'darkgoldenrod': '#b8860b', + 'darkgray': '#a9a9a9', + 'darkgrey': '#a9a9a9', + 'darkgreen': '#006400', + 'darkkhaki': '#bdb76b', + 'darkmagenta': '#8b008b', + 'darkolivegreen': '#556b2f', + 'darkorange': '#ff8c00', + 'darkorchid': '#9932cc', + 'darkred': '#8b0000', + 'darksalmon': '#e9967a', + 'darkseagreen': '#8fbc8f', + 'darkslateblue': '#483d8b', + 'darkslategray': '#2f4f4f', + 'darkslategrey': '#2f4f4f', + 'darkturquoise': '#00ced1', + 'darkviolet': '#9400d3', + 'deeppink': '#ff1493', + 'deepskyblue': '#00bfff', + 'dimgray': '#696969', + 'dimgrey': '#696969', + 'dodgerblue': '#1e90ff', + 'firebrick': '#b22222', + 'floralwhite': '#fffaf0', + 'forestgreen': '#228b22', + 'fuchsia': '#ff00ff', + 'gainsboro': '#dcdcdc', + 'ghostwhite': '#f8f8ff', + 'gold': '#ffd700', + 'goldenrod': '#daa520', + 'gray': '#808080', + 'grey': '#808080', + 'green': '#008000', + 'greenyellow': '#adff2f', + 'honeydew': '#f0fff0', + 'hotpink': '#ff69b4', + 'indianred': '#cd5c5c', + 'indigo': '#4b0082', + 'ivory': '#fffff0', + 'khaki': '#f0e68c', + 'lavender': '#e6e6fa', + 'lavenderblush': '#fff0f5', + 'lawngreen': '#7cfc00', + 'lemonchiffon': '#fffacd', + 'lightblue': '#add8e6', + 'lightcoral': '#f08080', + 'lightcyan': '#e0ffff', + 'lightgoldenrodyellow': '#fafad2', + 'lightgray': '#d3d3d3', + 'lightgrey': '#d3d3d3', + 'lightgreen': '#90ee90', + 'lightpink': '#ffb6c1', + 'lightsalmon': '#ffa07a', + 'lightseagreen': '#20b2aa', + 'lightskyblue': '#87cefa', + 'lightslategray': '#778899', + 'lightslategrey': '#778899', + 'lightsteelblue': '#b0c4de', + 'lightyellow': '#ffffe0', + 'lime': '#00ff00', + 'limegreen': '#32cd32', + 'linen': '#faf0e6', + 'magenta': '#ff00ff', + 'maroon': '#800000', + 'mediumaquamarine': '#66cdaa', + 'mediumblue': '#0000cd', + 'mediumorchid': '#ba55d3', + 'mediumpurple': '#9370d8', + 'mediumseagreen': '#3cb371', + 'mediumslateblue': '#7b68ee', + 'mediumspringgreen': '#00fa9a', + 'mediumturquoise': '#48d1cc', + 'mediumvioletred': '#c71585', + 'midnightblue': '#191970', + 'mintcream': '#f5fffa', + 'mistyrose': '#ffe4e1', + 'moccasin': '#ffe4b5', + 'navajowhite': '#ffdead', + 'navy': '#000080', + 'oldlace': '#fdf5e6', + 'olive': '#808000', + 'olivedrab': '#6b8e23', + 'orange': '#ffa500', + 'orangered': '#ff4500', + 'orchid': '#da70d6', + 'palegoldenrod': '#eee8aa', + 'palegreen': '#98fb98', + 'paleturquoise': '#afeeee', + 'palevioletred': '#d87093', + 'papayawhip': '#ffefd5', + 'peachpuff': '#ffdab9', + 'peru': '#cd853f', + 'pink': '#ffc0cb', + 'plum': '#dda0dd', + 'powderblue': '#b0e0e6', + 'purple': '#800080', + 'red': '#ff0000', + 'rosybrown': '#bc8f8f', + 'royalblue': '#4169e1', + 'saddlebrown': '#8b4513', + 'salmon': '#fa8072', + 'sandybrown': '#f4a460', + 'seagreen': '#2e8b57', + 'seashell': '#fff5ee', + 'sienna': '#a0522d', + 'silver': '#c0c0c0', + 'skyblue': '#87ceeb', + 'slateblue': '#6a5acd', + 'slategray': '#708090', + 'slategrey': '#708090', + 'snow': '#fffafa', + 'springgreen': '#00ff7f', + 'steelblue': '#4682b4', + 'tan': '#d2b48c', + 'teal': '#008080', + 'thistle': '#d8bfd8', + 'tomato': '#ff6347', + 'turquoise': '#40e0d0', + 'violet': '#ee82ee', + 'wheat': '#f5deb3', + 'white': '#ffffff', + 'whitesmoke': '#f5f5f5', + 'yellow': '#ffff00', + 'yellowgreen': '#9acd32' + }; +})(require('./tree')); + +(function (tree) { + + tree.debugInfo = function (env, ctx, lineSeperator) { + var result = ""; + if (env.dumpLineNumbers && !env.compress) { + switch (env.dumpLineNumbers) { + case 'comments': + result = tree.debugInfo.asComment(ctx); + break; + case 'mediaquery': + result = tree.debugInfo.asMediaQuery(ctx); + break; + case 'all': + result = tree.debugInfo.asComment(ctx) + (lineSeperator || "") + tree.debugInfo.asMediaQuery(ctx); + break; + } + } + return result; + }; + + tree.debugInfo.asComment = function (ctx) { + return '/* line ' + ctx.debugInfo.lineNumber + ', ' + ctx.debugInfo.fileName + ' */\n'; + }; + + tree.debugInfo.asMediaQuery = function (ctx) { + return '@media -sass-debug-info{filename{font-family:' + + ('file://' + ctx.debugInfo.fileName).replace(/([.:\/\\])/g, function (a) { + if (a == '\\') { + a = '\/'; + } + return '\\' + a; + }) + + '}line{font-family:\\00003' + ctx.debugInfo.lineNumber + '}}\n'; + }; + + tree.find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + r = fun.call(obj, obj[i]); + if (r) { + return r; + } + } + return null; + }; + + tree.jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { + return v.toCSS(); + }).join(', ') + ']'; + } else { + return obj.toCSS(); + } + }; + + tree.toCSS = function (env) { + var strs = []; + this.genCSS(env, { + add: function (chunk, fileInfo, index) { + strs.push(chunk); + }, + isEmpty: function () { + return strs.length === 0; + } + }); + return strs.join(''); + }; + + tree.outputRuleset = function (env, output, rules) { + var ruleCnt = rules.length, i; + env.tabLevel = (env.tabLevel | 0) + 1; + + // Compressed + if (env.compress) { + output.add('{'); + for (i = 0; i < ruleCnt; i++) { + rules[i].genCSS(env, output); + } + output.add('}'); + env.tabLevel--; + return; + } + + // Non-compressed + var tabSetStr = '\n' + Array(env.tabLevel).join(" "), tabRuleStr = tabSetStr + " "; + if (!ruleCnt) { + output.add(" {" + tabSetStr + '}'); + } else { + output.add(" {" + tabRuleStr); + rules[0].genCSS(env, output); + for (i = 1; i < ruleCnt; i++) { + output.add(tabRuleStr); + rules[i].genCSS(env, output); + } + output.add(tabSetStr + '}'); + } + + env.tabLevel--; + }; + +})(require('./tree')); + +(function (tree) { + + tree.Alpha = function (val) { + this.value = val; + }; + tree.Alpha.prototype = { + type: "Alpha", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + if (this.value.eval) { + return new tree.Alpha(this.value.eval(env)); + } + return this; + }, + genCSS: function (env, output) { + output.add("alpha(opacity="); + + if (this.value.genCSS) { + this.value.genCSS(env, output); + } else { + output.add(this.value); + } + + output.add(")"); + }, + toCSS: tree.toCSS + }; + +})(require('../tree')); + +(function (tree) { + + tree.Anonymous = function (value, index, currentFileInfo, mapLines, rulesetLike) { + this.value = value; + this.index = index; + this.mapLines = mapLines; + this.currentFileInfo = currentFileInfo; + this.rulesetLike = (typeof rulesetLike === 'undefined') ? false : rulesetLike; + }; + tree.Anonymous.prototype = { + type: "Anonymous", + eval: function () { + return new tree.Anonymous(this.value, this.index, this.currentFileInfo, this.mapLines, this.rulesetLike); + }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + }, + isRulesetLike: function () { + return this.rulesetLike; + }, + genCSS: function (env, output) { + output.add(this.value, this.currentFileInfo, this.index, this.mapLines); + }, + toCSS: tree.toCSS + }; + +})(require('../tree')); + +(function (tree) { + + tree.Assignment = function (key, val) { + this.key = key; + this.value = val; + }; + tree.Assignment.prototype = { + type: "Assignment", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + if (this.value.eval) { + return new (tree.Assignment)(this.key, this.value.eval(env)); + } + return this; + }, + genCSS: function (env, output) { + output.add(this.key + '='); + if (this.value.genCSS) { + this.value.genCSS(env, output); + } else { + output.add(this.value); + } + }, + toCSS: tree.toCSS + }; + +})(require('../tree')); + +(function (tree) { + +// +// A function call node. +// + tree.Call = function (name, args, index, currentFileInfo) { + this.name = name; + this.args = args; + this.index = index; + this.currentFileInfo = currentFileInfo; + }; + tree.Call.prototype = { + type: "Call", + accept: function (visitor) { + if (this.args) { + this.args = visitor.visitArray(this.args); + } + }, + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // if this returns null or we cannot find the function, we + // simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { + return a.eval(env); + }), + nameLC = this.name.toLowerCase(), + result, func; + + if (nameLC in tree.functions) { // 1. + try { + func = new tree.functionCall(env, this.currentFileInfo); + result = func[nameLC].apply(func, args); + if (result != null) { + return result; + } + } catch (e) { + throw { + type: e.type || "Runtime", + message: "error evaluating function `" + this.name + "`" + + (e.message ? ': ' + e.message : ''), + index: this.index, filename: this.currentFileInfo.filename + }; + } + } + + return new tree.Call(this.name, args, this.index, this.currentFileInfo); + }, + + genCSS: function (env, output) { + output.add(this.name + "(", this.currentFileInfo, this.index); + + for (var i = 0; i < this.args.length; i++) { + this.args[i].genCSS(env, output); + if (i + 1 < this.args.length) { + output.add(", "); + } + } + + output.add(")"); + }, + + toCSS: tree.toCSS + }; + +})(require('../tree')); + +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// + tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; + }; + + var transparentKeyword = "transparent"; + + tree.Color.prototype = { + type: "Color", + eval: function () { + return this; + }, + luma: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255; + + r = (r <= 0.03928) ? r / 12.92 : Math.pow(((r + 0.055) / 1.055), 2.4); + g = (g <= 0.03928) ? g / 12.92 : Math.pow(((g + 0.055) / 1.055), 2.4); + b = (b <= 0.03928) ? b / 12.92 : Math.pow(((b + 0.055) / 1.055), 2.4); + + return 0.2126 * r + 0.7152 * g + 0.0722 * b; + }, + + genCSS: function (env, output) { + output.add(this.toCSS(env)); + }, + toCSS: function (env, doNotCompress) { + var compress = env && env.compress && !doNotCompress, + alpha = tree.fround(env, this.alpha); + + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + if (alpha < 1) { + if (alpha === 0 && this.isTransparentKeyword) { + return transparentKeyword; + } + return "rgba(" + this.rgb.map(function (c) { + return clamp(Math.round(c), 255); + }).concat(clamp(alpha, 1)) + .join(',' + (compress ? '' : ' ')) + ")"; + } else { + var color = this.toRGB(); + + if (compress) { + var splitcolor = color.split(''); + + // Convert color to short format + if (splitcolor[1] === splitcolor[2] && splitcolor[3] === splitcolor[4] && splitcolor[5] === splitcolor[6]) { + color = '#' + splitcolor[1] + splitcolor[3] + splitcolor[5]; + } + } + + return color; + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (env, op, other) { + var rgb = []; + var alpha = this.alpha * (1 - other.alpha) + other.alpha; + for (var c = 0; c < 3; c++) { + rgb[c] = tree.operate(env, op, this.rgb[c], other.rgb[c]); + } + return new (tree.Color)(rgb, alpha); + }, + + toRGB: function () { + return toHex(this.rgb); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: + h = (g - b) / d + (g < b ? 6 : 0); + break; + case g: + h = (b - r) / d + 2; + break; + case b: + h = (r - g) / d + 4; + break; + } + h /= 6; + } + return {h: h * 360, s: s, l: l, a: a}; + }, + //Adapted from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript + toHSV: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, v = max; + + var d = max - min; + if (max === 0) { + s = 0; + } else { + s = d / max; + } + + if (max === min) { + h = 0; + } else { + switch (max) { + case r: + h = (g - b) / d + (g < b ? 6 : 0); + break; + case g: + h = (b - r) / d + 2; + break; + case b: + h = (r - g) / d + 4; + break; + } + h /= 6; + } + return {h: h * 360, s: s, v: v, a: a}; + }, + toARGB: function () { + return toHex([this.alpha * 255].concat(this.rgb)); + }, + compare: function (x) { + if (!x.rgb) { + return -1; + } + + return (x.rgb[0] === this.rgb[0] && + x.rgb[1] === this.rgb[1] && + x.rgb[2] === this.rgb[2] && + x.alpha === this.alpha) ? 0 : -1; + } + }; + + tree.Color.fromKeyword = function (keyword) { + keyword = keyword.toLowerCase(); + + if (tree.colors.hasOwnProperty(keyword)) { + // detect named color + return new (tree.Color)(tree.colors[keyword].slice(1)); + } + if (keyword === transparentKeyword) { + var transparent = new (tree.Color)([0, 0, 0], 0); + transparent.isTransparentKeyword = true; + return transparent; + } + }; + + function toHex(v) { + return '#' + v.map(function (c) { + c = clamp(Math.round(c), 255); + return (c < 16 ? '0' : '') + c.toString(16); + }).join(''); + } + + function clamp(v, max) { + return Math.min(Math.max(v, 0), max); + } + +})(require('../tree')); + +(function (tree) { + + tree.Comment = function (value, silent, index, currentFileInfo) { + this.value = value; + this.silent = !!silent; + this.currentFileInfo = currentFileInfo; + }; + tree.Comment.prototype = { + type: "Comment", + genCSS: function (env, output) { + if (this.debugInfo) { + output.add(tree.debugInfo(env, this), this.currentFileInfo, this.index); + } + output.add(this.value.trim()); //TODO shouldn't need to trim, we shouldn't grab the \n + }, + toCSS: tree.toCSS, + isSilent: function (env) { + var isReference = (this.currentFileInfo && this.currentFileInfo.reference && !this.isReferenced), + isCompressed = env.compress && !this.value.match(/^\/\*!/); + return this.silent || isReference || isCompressed; + }, + eval: function () { + return this; + }, + markReferenced: function () { + this.isReferenced = true; + } + }; + +})(require('../tree')); + +(function (tree) { + + tree.Condition = function (op, l, r, i, negate) { + this.op = op.trim(); + this.lvalue = l; + this.rvalue = r; + this.index = i; + this.negate = negate; + }; + tree.Condition.prototype = { + type: "Condition", + accept: function (visitor) { + this.lvalue = visitor.visit(this.lvalue); + this.rvalue = visitor.visit(this.rvalue); + }, + eval: function (env) { + var a = this.lvalue.eval(env), + b = this.rvalue.eval(env); + + var i = this.index, result; + + result = (function (op) { + switch (op) { + case 'and': + return a && b; + case 'or': + return a || b; + default: + if (a.compare) { + result = a.compare(b); + } else if (b.compare) { + result = b.compare(a); + } else { + throw { + type: "Type", + message: "Unable to perform comparison", + index: i + }; + } + switch (result) { + case -1: + return op === '<' || op === '=<' || op === '<='; + case 0: + return op === '=' || op === '>=' || op === '=<' || op === '<='; + case 1: + return op === '>' || op === '>='; + } + } + })(this.op); + return this.negate ? !result : result; + } + }; + +})(require('../tree')); + +(function (tree) { + + tree.DetachedRuleset = function (ruleset, frames) { + this.ruleset = ruleset; + this.frames = frames; + }; + tree.DetachedRuleset.prototype = { + type: "DetachedRuleset", + accept: function (visitor) { + this.ruleset = visitor.visit(this.ruleset); + }, + eval: function (env) { + var frames = this.frames || env.frames.slice(0); + return new tree.DetachedRuleset(this.ruleset, frames); + }, + callEval: function (env) { + return this.ruleset.eval(this.frames ? new (tree.evalEnv)(env, this.frames.concat(env.frames)) : env); + } + }; +})(require('../tree')); + +(function (tree) { + +// +// A number with a unit +// + tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = (unit && unit instanceof tree.Unit) ? unit : + new (tree.Unit)(unit ? [unit] : undefined); + }; + + tree.Dimension.prototype = { + type: "Dimension", + accept: function (visitor) { + this.unit = visitor.visit(this.unit); + }, + eval: function (env) { + return this; + }, + toColor: function () { + return new (tree.Color)([this.value, this.value, this.value]); + }, + genCSS: function (env, output) { + if ((env && env.strictUnits) && !this.unit.isSingular()) { + throw new Error("Multiple units in dimension. Correct the units or use the unit function. Bad unit: " + this.unit.toString()); + } + + var value = tree.fround(env, this.value), + strValue = String(value); + + if (value !== 0 && value < 0.000001 && value > -0.000001) { + // would be output 1e-6 etc. + strValue = value.toFixed(20).replace(/0+$/, ""); + } + + if (env && env.compress) { + // Zero values doesn't need a unit + if (value === 0 && this.unit.isLength()) { + output.add(strValue); + return; + } + + // Float values doesn't need a leading zero + if (value > 0 && value < 1) { + strValue = (strValue).substr(1); + } + } + + output.add(strValue); + this.unit.genCSS(env, output); + }, + toCSS: tree.toCSS, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2` will yield `3px`. + operate: function (env, op, other) { + /*jshint noempty:false */ + var value = tree.operate(env, op, this.value, other.value), + unit = this.unit.clone(); + + if (op === '+' || op === '-') { + if (unit.numerator.length === 0 && unit.denominator.length === 0) { + unit.numerator = other.unit.numerator.slice(0); + unit.denominator = other.unit.denominator.slice(0); + } else if (other.unit.numerator.length === 0 && unit.denominator.length === 0) { + // do nothing + } else { + other = other.convertTo(this.unit.usedUnits()); + + if (env.strictUnits && other.unit.toString() !== unit.toString()) { + throw new Error("Incompatible units. Change the units or use the unit function. Bad units: '" + unit.toString() + + "' and '" + other.unit.toString() + "'."); + } + + value = tree.operate(env, op, this.value, other.value); + } + } else if (op === '*') { + unit.numerator = unit.numerator.concat(other.unit.numerator).sort(); + unit.denominator = unit.denominator.concat(other.unit.denominator).sort(); + unit.cancel(); + } else if (op === '/') { + unit.numerator = unit.numerator.concat(other.unit.denominator).sort(); + unit.denominator = unit.denominator.concat(other.unit.numerator).sort(); + unit.cancel(); + } + return new (tree.Dimension)(value, unit); + }, + + compare: function (other) { + if (other instanceof tree.Dimension) { + var a, b, + aValue, bValue; + + if (this.unit.isEmpty() || other.unit.isEmpty()) { + a = this; + b = other; + } else { + a = this.unify(); + b = other.unify(); + if (a.unit.compare(b.unit) !== 0) { + return -1; + } + } + aValue = a.value; + bValue = b.value; + + if (bValue > aValue) { + return -1; + } else if (bValue < aValue) { + return 1; + } else { + return 0; + } + } else { + return -1; + } + }, + + unify: function () { + return this.convertTo({length: 'px', duration: 's', angle: 'rad'}); + }, + + convertTo: function (conversions) { + var value = this.value, unit = this.unit.clone(), + i, groupName, group, targetUnit, derivedConversions = {}, applyUnit; + + if (typeof conversions === 'string') { + for (i in tree.UnitConversions) { + if (tree.UnitConversions[i].hasOwnProperty(conversions)) { + derivedConversions = {}; + derivedConversions[i] = conversions; + } + } + conversions = derivedConversions; + } + applyUnit = function (atomicUnit, denominator) { + /*jshint loopfunc:true */ + if (group.hasOwnProperty(atomicUnit)) { + if (denominator) { + value = value / (group[atomicUnit] / group[targetUnit]); + } else { + value = value * (group[atomicUnit] / group[targetUnit]); + } + + return targetUnit; + } + + return atomicUnit; + }; + + for (groupName in conversions) { + if (conversions.hasOwnProperty(groupName)) { + targetUnit = conversions[groupName]; + group = tree.UnitConversions[groupName]; + + unit.map(applyUnit); + } + } + + unit.cancel(); + + return new (tree.Dimension)(value, unit); + } + }; + +// http://www.w3.org/TR/css3-values/#absolute-lengths + tree.UnitConversions = { + length: { + 'm': 1, + 'cm': 0.01, + 'mm': 0.001, + 'in': 0.0254, + 'px': 0.0254 / 96, + 'pt': 0.0254 / 72, + 'pc': 0.0254 / 72 * 12 + }, + duration: { + 's': 1, + 'ms': 0.001 + }, + angle: { + 'rad': 1 / (2 * Math.PI), + 'deg': 1 / 360, + 'grad': 1 / 400, + 'turn': 1 + } + }; + + tree.Unit = function (numerator, denominator, backupUnit) { + this.numerator = numerator ? numerator.slice(0).sort() : []; + this.denominator = denominator ? denominator.slice(0).sort() : []; + this.backupUnit = backupUnit; + }; + + tree.Unit.prototype = { + type: "Unit", + clone: function () { + return new tree.Unit(this.numerator.slice(0), this.denominator.slice(0), this.backupUnit); + }, + genCSS: function (env, output) { + if (this.numerator.length >= 1) { + output.add(this.numerator[0]); + } else if (this.denominator.length >= 1) { + output.add(this.denominator[0]); + } else if ((!env || !env.strictUnits) && this.backupUnit) { + output.add(this.backupUnit); + } + }, + toCSS: tree.toCSS, + + toString: function () { + var i, returnStr = this.numerator.join("*"); + for (i = 0; i < this.denominator.length; i++) { + returnStr += "/" + this.denominator[i]; + } + return returnStr; + }, + + compare: function (other) { + return this.is(other.toString()) ? 0 : -1; + }, + + is: function (unitString) { + return this.toString() === unitString; + }, + + isLength: function () { + return Boolean(this.toCSS().match(/px|em|%|in|cm|mm|pc|pt|ex/)); + }, + + isEmpty: function () { + return this.numerator.length === 0 && this.denominator.length === 0; + }, + + isSingular: function () { + return this.numerator.length <= 1 && this.denominator.length === 0; + }, + + map: function (callback) { + var i; + + for (i = 0; i < this.numerator.length; i++) { + this.numerator[i] = callback(this.numerator[i], false); + } + + for (i = 0; i < this.denominator.length; i++) { + this.denominator[i] = callback(this.denominator[i], true); + } + }, + + usedUnits: function () { + var group, result = {}, mapUnit; + + mapUnit = function (atomicUnit) { + /*jshint loopfunc:true */ + if (group.hasOwnProperty(atomicUnit) && !result[groupName]) { + result[groupName] = atomicUnit; + } + + return atomicUnit; + }; + + for (var groupName in tree.UnitConversions) { + if (tree.UnitConversions.hasOwnProperty(groupName)) { + group = tree.UnitConversions[groupName]; + + this.map(mapUnit); + } + } + + return result; + }, + + cancel: function () { + var counter = {}, atomicUnit, i, backup; + + for (i = 0; i < this.numerator.length; i++) { + atomicUnit = this.numerator[i]; + if (!backup) { + backup = atomicUnit; + } + counter[atomicUnit] = (counter[atomicUnit] || 0) + 1; + } + + for (i = 0; i < this.denominator.length; i++) { + atomicUnit = this.denominator[i]; + if (!backup) { + backup = atomicUnit; + } + counter[atomicUnit] = (counter[atomicUnit] || 0) - 1; + } + + this.numerator = []; + this.denominator = []; + + for (atomicUnit in counter) { + if (counter.hasOwnProperty(atomicUnit)) { + var count = counter[atomicUnit]; + + if (count > 0) { + for (i = 0; i < count; i++) { + this.numerator.push(atomicUnit); + } + } else if (count < 0) { + for (i = 0; i < -count; i++) { + this.denominator.push(atomicUnit); + } + } + } + } + + if (this.numerator.length === 0 && this.denominator.length === 0 && backup) { + this.backupUnit = backup; + } + + this.numerator.sort(); + this.denominator.sort(); + } + }; + +})(require('../tree')); + +(function (tree) { + + tree.Directive = function (name, value, rules, index, currentFileInfo, debugInfo) { + this.name = name; + this.value = value; + if (rules) { + this.rules = rules; + this.rules.allowImports = true; + } + this.index = index; + this.currentFileInfo = currentFileInfo; + this.debugInfo = debugInfo; + }; + + tree.Directive.prototype = { + type: "Directive", + accept: function (visitor) { + var value = this.value, rules = this.rules; + if (rules) { + rules = visitor.visit(rules); + } + if (value) { + value = visitor.visit(value); + } + }, + isRulesetLike: function () { + return !this.isCharset(); + }, + isCharset: function () { + return "@charset" === this.name; + }, + genCSS: function (env, output) { + var value = this.value, rules = this.rules; + output.add(this.name, this.currentFileInfo, this.index); + if (value) { + output.add(' '); + value.genCSS(env, output); + } + if (rules) { + tree.outputRuleset(env, output, [rules]); + } else { + output.add(';'); + } + }, + toCSS: tree.toCSS, + eval: function (env) { + var value = this.value, rules = this.rules; + if (value) { + value = value.eval(env); + } + if (rules) { + rules = rules.eval(env); + rules.root = true; + } + return new (tree.Directive)(this.name, value, rules, + this.index, this.currentFileInfo, this.debugInfo); + }, + variable: function (name) { + if (this.rules) return tree.Ruleset.prototype.variable.call(this.rules, name); + }, + find: function () { + if (this.rules) return tree.Ruleset.prototype.find.apply(this.rules, arguments); + }, + rulesets: function () { + if (this.rules) return tree.Ruleset.prototype.rulesets.apply(this.rules); + }, + markReferenced: function () { + var i, rules; + this.isReferenced = true; + if (this.rules) { + rules = this.rules.rules; + for (i = 0; i < rules.length; i++) { + if (rules[i].markReferenced) { + rules[i].markReferenced(); + } + } + } + } + }; + +})(require('../tree')); + +(function (tree) { + + tree.Element = function (combinator, value, index, currentFileInfo) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new (tree.Combinator)(combinator); + + if (typeof(value) === 'string') { + this.value = value.trim(); + } else if (value) { + this.value = value; + } else { + this.value = ""; + } + this.index = index; + this.currentFileInfo = currentFileInfo; + }; + tree.Element.prototype = { + type: "Element", + accept: function (visitor) { + var value = this.value; + this.combinator = visitor.visit(this.combinator); + if (typeof value === "object") { + this.value = visitor.visit(value); + } + }, + eval: function (env) { + return new (tree.Element)(this.combinator, + this.value.eval ? this.value.eval(env) : this.value, + this.index, + this.currentFileInfo); + }, + genCSS: function (env, output) { + output.add(this.toCSS(env), this.currentFileInfo, this.index); + }, + toCSS: function (env) { + var value = (this.value.toCSS ? this.value.toCSS(env) : this.value); + if (value === '' && this.combinator.value.charAt(0) === '&') { + return ''; + } else { + return this.combinator.toCSS(env || {}) + value; + } + } + }; + + tree.Attribute = function (key, op, value) { + this.key = key; + this.op = op; + this.value = value; + }; + tree.Attribute.prototype = { + type: "Attribute", + eval: function (env) { + return new (tree.Attribute)(this.key.eval ? this.key.eval(env) : this.key, + this.op, (this.value && this.value.eval) ? this.value.eval(env) : this.value); + }, + genCSS: function (env, output) { + output.add(this.toCSS(env)); + }, + toCSS: function (env) { + var value = this.key.toCSS ? this.key.toCSS(env) : this.key; + + if (this.op) { + value += this.op; + value += (this.value.toCSS ? this.value.toCSS(env) : this.value); + } + + return '[' + value + ']'; + } + }; + + tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else { + this.value = value ? value.trim() : ""; + } + }; + tree.Combinator.prototype = { + type: "Combinator", + _noSpaceCombinators: { + '': true, + ' ': true, + '|': true + }, + genCSS: function (env, output) { + var spaceOrEmpty = (env.compress || this._noSpaceCombinators[this.value]) ? '' : ' '; + output.add(spaceOrEmpty + this.value + spaceOrEmpty); + }, + toCSS: tree.toCSS + }; + +})(require('../tree')); + +(function (tree) { + + tree.Expression = function (value) { + this.value = value; + }; + tree.Expression.prototype = { + type: "Expression", + accept: function (visitor) { + if (this.value) { + this.value = visitor.visitArray(this.value); + } + }, + eval: function (env) { + var returnValue, + inParenthesis = this.parens && !this.parensInOp, + doubleParen = false; + if (inParenthesis) { + env.inParenthesis(); + } + if (this.value.length > 1) { + returnValue = new (tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + if (this.value[0].parens && !this.value[0].parensInOp) { + doubleParen = true; + } + returnValue = this.value[0].eval(env); + } else { + returnValue = this; + } + if (inParenthesis) { + env.outOfParenthesis(); + } + if (this.parens && this.parensInOp && !(env.isMathOn()) && !doubleParen) { + returnValue = new (tree.Paren)(returnValue); + } + return returnValue; + }, + genCSS: function (env, output) { + for (var i = 0; i < this.value.length; i++) { + this.value[i].genCSS(env, output); + if (i + 1 < this.value.length) { + output.add(" "); + } + } + }, + toCSS: tree.toCSS, + throwAwayComments: function () { + this.value = this.value.filter(function (v) { + return !(v instanceof tree.Comment); + }); + } + }; + +})(require('../tree')); + +(function (tree) { + + tree.Extend = function Extend(selector, option, index) { + this.selector = selector; + this.option = option; + this.index = index; + this.object_id = tree.Extend.next_id++; + this.parent_ids = [this.object_id]; + + switch (option) { + case "all": + this.allowBefore = true; + this.allowAfter = true; + break; + default: + this.allowBefore = false; + this.allowAfter = false; + break; + } + }; + tree.Extend.next_id = 0; + + tree.Extend.prototype = { + type: "Extend", + accept: function (visitor) { + this.selector = visitor.visit(this.selector); + }, + eval: function (env) { + return new (tree.Extend)(this.selector.eval(env), this.option, this.index); + }, + clone: function (env) { + return new (tree.Extend)(this.selector, this.option, this.index); + }, + findSelfSelectors: function (selectors) { + var selfElements = [], + i, + selectorElements; + + for (i = 0; i < selectors.length; i++) { + selectorElements = selectors[i].elements; + // duplicate the logic in genCSS function inside the selector node. + // future TODO - move both logics into the selector joiner visitor + if (i > 0 && selectorElements.length && selectorElements[0].combinator.value === "") { + selectorElements[0].combinator.value = ' '; + } + selfElements = selfElements.concat(selectors[i].elements); + } + + this.selfSelectors = [{elements: selfElements}]; + } + }; + +})(require('../tree')); + +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// + tree.Import = function (path, features, options, index, currentFileInfo) { + this.options = options; + this.index = index; + this.path = path; + this.features = features; + this.currentFileInfo = currentFileInfo; + + if (this.options.less !== undefined || this.options.inline) { + this.css = !this.options.less || this.options.inline; + } else { + var pathValue = this.getPath(); + if (pathValue && /css([\?;].*)?$/.test(pathValue)) { + this.css = true; + } + } + }; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// + tree.Import.prototype = { + type: "Import", + accept: function (visitor) { + if (this.features) { + this.features = visitor.visit(this.features); + } + this.path = visitor.visit(this.path); + if (!this.options.inline && this.root) { + this.root = visitor.visit(this.root); + } + }, + genCSS: function (env, output) { + if (this.css) { + output.add("@import ", this.currentFileInfo, this.index); + this.path.genCSS(env, output); + if (this.features) { + output.add(" "); + this.features.genCSS(env, output); + } + output.add(';'); + } + }, + toCSS: tree.toCSS, + getPath: function () { + if (this.path instanceof tree.Quoted) { + var path = this.path.value; + return (this.css !== undefined || /(\.[a-z]*$)|([\?;].*)$/.test(path)) ? path : path + '.less'; + } else if (this.path instanceof tree.URL) { + return this.path.value.value; + } + return null; + }, + evalForImport: function (env) { + return new (tree.Import)(this.path.eval(env), this.features, this.options, this.index, this.currentFileInfo); + }, + evalPath: function (env) { + var path = this.path.eval(env); + var rootpath = this.currentFileInfo && this.currentFileInfo.rootpath; + + if (!(path instanceof tree.URL)) { + if (rootpath) { + var pathValue = path.value; + // Add the base path if the import is relative + if (pathValue && env.isPathRelative(pathValue)) { + path.value = rootpath + pathValue; + } + } + path.value = env.normalizePath(path.value); + } + + return path; + }, + eval: function (env) { + var ruleset, features = this.features && this.features.eval(env); + + if (this.skip) { + if (typeof this.skip === "function") { + this.skip = this.skip(); + } + if (this.skip) { + return []; + } + } + + if (this.options.inline) { + //todo needs to reference css file not import + var contents = new (tree.Anonymous)(this.root, 0, {filename: this.importedFilename}, true, true); + return this.features ? new (tree.Media)([contents], this.features.value) : [contents]; + } else if (this.css) { + var newImport = new (tree.Import)(this.evalPath(env), features, this.options, this.index); + if (!newImport.css && this.error) { + throw this.error; + } + return newImport; + } else { + ruleset = new (tree.Ruleset)(null, this.root.rules.slice(0)); + + ruleset.evalImports(env); + + return this.features ? new (tree.Media)(ruleset.rules, this.features.value) : ruleset.rules; + } + } + }; + +})(require('../tree')); + +(function (tree) { + + tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; + }; + tree.JavaScript.prototype = { + type: "JavaScript", + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new (tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new (Function)('return (' + expression + ')'); + } catch (e) { + throw { + message: "JavaScript evaluation error: " + e.message + " from `" + expression + "`", + index: this.index + }; + } + + var variables = env.frames[0].variables(); + for (var k in variables) { + if (variables.hasOwnProperty(k)) { + /*jshint loopfunc:true */ + context[k.slice(1)] = { + value: variables[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + } + + try { + result = expression.call(context); + } catch (e) { + throw { + message: "JavaScript evaluation error: '" + e.name + ': ' + e.message.replace(/["]/g, "'") + "'", + index: this.index + }; + } + if (typeof(result) === 'number') { + return new (tree.Dimension)(result); + } else if (typeof(result) === 'string') { + return new (tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new (tree.Anonymous)(result.join(', ')); + } else { + return new (tree.Anonymous)(result); + } + } + }; + +})(require('../tree')); + + +(function (tree) { + + tree.Keyword = function (value) { + this.value = value; + }; + tree.Keyword.prototype = { + type: "Keyword", + eval: function () { + return this; + }, + genCSS: function (env, output) { + if (this.value === '%') { + throw {type: "Syntax", message: "Invalid % without number"}; + } + output.add(this.value); + }, + toCSS: tree.toCSS, + compare: function (other) { + if (other instanceof tree.Keyword) { + return other.value === this.value ? 0 : 1; + } else { + return -1; + } + } + }; + + tree.True = new (tree.Keyword)('true'); + tree.False = new (tree.Keyword)('false'); + +})(require('../tree')); + +(function (tree) { + + tree.Media = function (value, features, index, currentFileInfo) { + this.index = index; + this.currentFileInfo = currentFileInfo; + + var selectors = this.emptySelectors(); + + this.features = new (tree.Value)(features); + this.rules = [new (tree.Ruleset)(selectors, value)]; + this.rules[0].allowImports = true; + }; + tree.Media.prototype = { + type: "Media", + accept: function (visitor) { + if (this.features) { + this.features = visitor.visit(this.features); + } + if (this.rules) { + this.rules = visitor.visitArray(this.rules); + } + }, + genCSS: function (env, output) { + output.add('@media ', this.currentFileInfo, this.index); + this.features.genCSS(env, output); + tree.outputRuleset(env, output, this.rules); + }, + toCSS: tree.toCSS, + eval: function (env) { + if (!env.mediaBlocks) { + env.mediaBlocks = []; + env.mediaPath = []; + } + + var media = new (tree.Media)(null, [], this.index, this.currentFileInfo); + if (this.debugInfo) { + this.rules[0].debugInfo = this.debugInfo; + media.debugInfo = this.debugInfo; + } + var strictMathBypass = false; + if (!env.strictMath) { + strictMathBypass = true; + env.strictMath = true; + } + try { + media.features = this.features.eval(env); + } + finally { + if (strictMathBypass) { + env.strictMath = false; + } + } + + env.mediaPath.push(media); + env.mediaBlocks.push(media); + + env.frames.unshift(this.rules[0]); + media.rules = [this.rules[0].eval(env)]; + env.frames.shift(); + + env.mediaPath.pop(); + + return env.mediaPath.length === 0 ? media.evalTop(env) : + media.evalNested(env); + }, + variable: function (name) { + return tree.Ruleset.prototype.variable.call(this.rules[0], name); + }, + find: function () { + return tree.Ruleset.prototype.find.apply(this.rules[0], arguments); + }, + rulesets: function () { + return tree.Ruleset.prototype.rulesets.apply(this.rules[0]); + }, + emptySelectors: function () { + var el = new (tree.Element)('', '&', this.index, this.currentFileInfo), + sels = [new (tree.Selector)([el], null, null, this.index, this.currentFileInfo)]; + sels[0].mediaEmpty = true; + return sels; + }, + markReferenced: function () { + var i, rules = this.rules[0].rules; + this.rules[0].markReferenced(); + this.isReferenced = true; + for (i = 0; i < rules.length; i++) { + if (rules[i].markReferenced) { + rules[i].markReferenced(); + } + } + }, + + evalTop: function (env) { + var result = this; + + // Render all dependent Media blocks. + if (env.mediaBlocks.length > 1) { + var selectors = this.emptySelectors(); + result = new (tree.Ruleset)(selectors, env.mediaBlocks); + result.multiMedia = true; + } + + delete env.mediaBlocks; + delete env.mediaPath; + + return result; + }, + evalNested: function (env) { + var i, value, + path = env.mediaPath.concat([this]); + + // Extract the media-query conditions separated with `,` (OR). + for (i = 0; i < path.length; i++) { + value = path[i].features instanceof tree.Value ? + path[i].features.value : path[i].features; + path[i] = Array.isArray(value) ? value : [value]; + } + + // Trace all permutations to generate the resulting media-query. + // + // (a, b and c) with nested (d, e) -> + // a and d + // a and e + // b and c and d + // b and c and e + this.features = new (tree.Value)(this.permute(path).map(function (path) { + path = path.map(function (fragment) { + return fragment.toCSS ? fragment : new (tree.Anonymous)(fragment); + }); + + for (i = path.length - 1; i > 0; i--) { + path.splice(i, 0, new (tree.Anonymous)("and")); + } + + return new (tree.Expression)(path); + })); + + // Fake a tree-node that doesn't output anything. + return new (tree.Ruleset)([], []); + }, + permute: function (arr) { + if (arr.length === 0) { + return []; + } else if (arr.length === 1) { + return arr[0]; + } else { + var result = []; + var rest = this.permute(arr.slice(1)); + for (var i = 0; i < rest.length; i++) { + for (var j = 0; j < arr[0].length; j++) { + result.push([arr[0][j]].concat(rest[i])); + } + } + return result; + } + }, + bubbleSelectors: function (selectors) { + if (!selectors) + return; + this.rules = [new (tree.Ruleset)(selectors.slice(0), [this.rules[0]])]; + } + }; + +})(require('../tree')); + +(function (tree) { + + tree.mixin = {}; + tree.mixin.Call = function (elements, args, index, currentFileInfo, important) { + this.selector = new (tree.Selector)(elements); + this.arguments = (args && args.length) ? args : null; + this.index = index; + this.currentFileInfo = currentFileInfo; + this.important = important; + }; + tree.mixin.Call.prototype = { + type: "MixinCall", + accept: function (visitor) { + if (this.selector) { + this.selector = visitor.visit(this.selector); + } + if (this.arguments) { + this.arguments = visitor.visitArray(this.arguments); + } + }, + eval: function (env) { + var mixins, mixin, args, rules = [], match = false, i, m, f, isRecursive, isOneFound, rule, + candidates = [], candidate, conditionResult = [], defaultFunc = tree.defaultFunc, + defaultResult, defNone = 0, defTrue = 1, defFalse = 2, count, originalRuleset; + + args = this.arguments && this.arguments.map(function (a) { + return {name: a.name, value: a.value.eval(env)}; + }); + + for (i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + isOneFound = true; + + // To make `default()` function independent of definition order we have two "subpasses" here. + // At first we evaluate each guard *twice* (with `default() == true` and `default() == false`), + // and build candidate list with corresponding flags. Then, when we know all possible matches, + // we make a final decision. + + for (m = 0; m < mixins.length; m++) { + mixin = mixins[m]; + isRecursive = false; + for (f = 0; f < env.frames.length; f++) { + if ((!(mixin instanceof tree.mixin.Definition)) && mixin === (env.frames[f].originalRuleset || env.frames[f])) { + isRecursive = true; + break; + } + } + if (isRecursive) { + continue; + } + + if (mixin.matchArgs(args, env)) { + candidate = {mixin: mixin, group: defNone}; + + if (mixin.matchCondition) { + for (f = 0; f < 2; f++) { + defaultFunc.value(f); + conditionResult[f] = mixin.matchCondition(args, env); + } + if (conditionResult[0] || conditionResult[1]) { + if (conditionResult[0] != conditionResult[1]) { + candidate.group = conditionResult[1] ? + defTrue : defFalse; + } + + candidates.push(candidate); + } + } + else { + candidates.push(candidate); + } + + match = true; + } + } + + defaultFunc.reset(); + + count = [0, 0, 0]; + for (m = 0; m < candidates.length; m++) { + count[candidates[m].group]++; + } + + if (count[defNone] > 0) { + defaultResult = defFalse; + } else { + defaultResult = defTrue; + if ((count[defTrue] + count[defFalse]) > 1) { + throw { + type: 'Runtime', + message: 'Ambiguous use of `default()` found when matching for `' + + this.format(args) + '`', + index: this.index, filename: this.currentFileInfo.filename + }; + } + } + + for (m = 0; m < candidates.length; m++) { + candidate = candidates[m].group; + if ((candidate === defNone) || (candidate === defaultResult)) { + try { + mixin = candidates[m].mixin; + if (!(mixin instanceof tree.mixin.Definition)) { + originalRuleset = mixin.originalRuleset || mixin; + mixin = new tree.mixin.Definition("", [], mixin.rules, null, false); + mixin.originalRuleset = originalRuleset; + } + Array.prototype.push.apply( + rules, mixin.evalCall(env, args, this.important).rules); + } catch (e) { + throw { + message: e.message, + index: this.index, + filename: this.currentFileInfo.filename, + stack: e.stack + }; + } + } + } + + if (match) { + if (!this.currentFileInfo || !this.currentFileInfo.reference) { + for (i = 0; i < rules.length; i++) { + rule = rules[i]; + if (rule.markReferenced) { + rule.markReferenced(); + } + } + } + return rules; + } + } + } + if (isOneFound) { + throw { + type: 'Runtime', + message: 'No matching definition was found for `' + this.format(args) + '`', + index: this.index, filename: this.currentFileInfo.filename + }; + } else { + throw { + type: 'Name', + message: this.selector.toCSS().trim() + " is undefined", + index: this.index, filename: this.currentFileInfo.filename + }; + } + }, + format: function (args) { + return this.selector.toCSS().trim() + '(' + + (args ? args.map(function (a) { + var argValue = ""; + if (a.name) { + argValue += a.name + ":"; + } + if (a.value.toCSS) { + argValue += a.value.toCSS(); + } else { + argValue += "???"; + } + return argValue; + }).join(', ') : "") + ")"; + } + }; + + tree.mixin.Definition = function (name, params, rules, condition, variadic, frames) { + this.name = name; + this.selectors = [new (tree.Selector)([new (tree.Element)(null, name, this.index, this.currentFileInfo)])]; + this.params = params; + this.condition = condition; + this.variadic = variadic; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { + return count + 1; + } + else { + return count; + } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = frames; + }; + tree.mixin.Definition.prototype = { + type: "MixinDefinition", + accept: function (visitor) { + if (this.params && this.params.length) { + this.params = visitor.visitArray(this.params); + } + this.rules = visitor.visitArray(this.rules); + if (this.condition) { + this.condition = visitor.visit(this.condition); + } + }, + variable: function (name) { + return this.parent.variable.call(this, name); + }, + variables: function () { + return this.parent.variables.call(this); + }, + find: function () { + return this.parent.find.apply(this, arguments); + }, + rulesets: function () { + return this.parent.rulesets.apply(this); + }, + + evalParams: function (env, mixinEnv, args, evaldArguments) { + /*jshint boss:true */ + var frame = new (tree.Ruleset)(null, null), + varargs, arg, + params = this.params.slice(0), + i, j, val, name, isNamedFound, argIndex, argsLength = 0; + + mixinEnv = new tree.evalEnv(mixinEnv, [frame].concat(mixinEnv.frames)); + + if (args) { + args = args.slice(0); + argsLength = args.length; + + for (i = 0; i < argsLength; i++) { + arg = args[i]; + if (name = (arg && arg.name)) { + isNamedFound = false; + for (j = 0; j < params.length; j++) { + if (!evaldArguments[j] && name === params[j].name) { + evaldArguments[j] = arg.value.eval(env); + frame.prependRule(new (tree.Rule)(name, arg.value.eval(env))); + isNamedFound = true; + break; + } + } + if (isNamedFound) { + args.splice(i, 1); + i--; + continue; + } else { + throw { + type: 'Runtime', message: "Named argument for " + this.name + + ' ' + args[i].name + ' not found' + }; + } + } + } + } + argIndex = 0; + for (i = 0; i < params.length; i++) { + if (evaldArguments[i]) { + continue; + } + + arg = args && args[argIndex]; + + if (name = params[i].name) { + if (params[i].variadic) { + varargs = []; + for (j = argIndex; j < argsLength; j++) { + varargs.push(args[j].value.eval(env)); + } + frame.prependRule(new (tree.Rule)(name, new (tree.Expression)(varargs).eval(env))); + } else { + val = arg && arg.value; + if (val) { + val = val.eval(env); + } else if (params[i].value) { + val = params[i].value.eval(mixinEnv); + frame.resetCache(); + } else { + throw { + type: 'Runtime', message: "wrong number of arguments for " + this.name + + ' (' + argsLength + ' for ' + this.arity + ')' + }; + } + + frame.prependRule(new (tree.Rule)(name, val)); + evaldArguments[i] = val; + } + } + + if (params[i].variadic && args) { + for (j = argIndex; j < argsLength; j++) { + evaldArguments[j] = args[j].value.eval(env); + } + } + argIndex++; + } + + return frame; + }, + eval: function (env) { + return new tree.mixin.Definition(this.name, this.params, this.rules, this.condition, this.variadic, this.frames || env.frames.slice(0)); + }, + evalCall: function (env, args, important) { + var _arguments = [], + mixinFrames = this.frames ? this.frames.concat(env.frames) : env.frames, + frame = this.evalParams(env, new (tree.evalEnv)(env, mixinFrames), args, _arguments), + rules, ruleset; + + frame.prependRule(new (tree.Rule)('@arguments', new (tree.Expression)(_arguments).eval(env))); + + rules = this.rules.slice(0); + + ruleset = new (tree.Ruleset)(null, rules); + ruleset.originalRuleset = this; + ruleset = ruleset.eval(new (tree.evalEnv)(env, [this, frame].concat(mixinFrames))); + if (important) { + ruleset = this.parent.makeImportant.apply(ruleset); + } + return ruleset; + }, + matchCondition: function (args, env) { + if (this.condition && !this.condition.eval( + new (tree.evalEnv)(env, + [this.evalParams(env, new (tree.evalEnv)(env, this.frames ? this.frames.concat(env.frames) : env.frames), args, [])] // the parameter variables + .concat(this.frames) // the parent namespace/mixin frames + .concat(env.frames)))) { // the current environment frames + return false; + } + return true; + }, + matchArgs: function (args, env) { + var argsLength = (args && args.length) || 0, len; + + if (!this.variadic) { + if (argsLength < this.required) { + return false; + } + if (argsLength > this.params.length) { + return false; + } + } else { + if (argsLength < (this.required - 1)) { + return false; + } + } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name && !this.params[i].variadic) { + if (args[i].value.eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } + }; + +})(require('../tree')); + +(function (tree) { + + tree.Negative = function (node) { + this.value = node; + }; + tree.Negative.prototype = { + type: "Negative", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + genCSS: function (env, output) { + output.add('-'); + this.value.genCSS(env, output); + }, + toCSS: tree.toCSS, + eval: function (env) { + if (env.isMathOn()) { + return (new (tree.Operation)('*', [new (tree.Dimension)(-1), this.value])).eval(env); + } + return new (tree.Negative)(this.value.eval(env)); + } + }; + +})(require('../tree')); + +(function (tree) { + + tree.Operation = function (op, operands, isSpaced) { + this.op = op.trim(); + this.operands = operands; + this.isSpaced = isSpaced; + }; + tree.Operation.prototype = { + type: "Operation", + accept: function (visitor) { + this.operands = visitor.visit(this.operands); + }, + eval: function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env); + + if (env.isMathOn()) { + if (a instanceof tree.Dimension && b instanceof tree.Color) { + a = a.toColor(); + } + if (b instanceof tree.Dimension && a instanceof tree.Color) { + b = b.toColor(); + } + if (!a.operate) { + throw { + type: "Operation", + message: "Operation on an invalid type" + }; + } + + return a.operate(env, this.op, b); + } else { + return new (tree.Operation)(this.op, [a, b], this.isSpaced); + } + }, + genCSS: function (env, output) { + this.operands[0].genCSS(env, output); + if (this.isSpaced) { + output.add(" "); + } + output.add(this.op); + if (this.isSpaced) { + output.add(" "); + } + this.operands[1].genCSS(env, output); + }, + toCSS: tree.toCSS + }; + + tree.operate = function (env, op, a, b) { + switch (op) { + case '+': + return a + b; + case '-': + return a - b; + case '*': + return a * b; + case '/': + return a / b; + } + }; + +})(require('../tree')); + + +(function (tree) { + + tree.Paren = function (node) { + this.value = node; + }; + tree.Paren.prototype = { + type: "Paren", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + genCSS: function (env, output) { + output.add('('); + this.value.genCSS(env, output); + output.add(')'); + }, + toCSS: tree.toCSS, + eval: function (env) { + return new (tree.Paren)(this.value.eval(env)); + } + }; + +})(require('../tree')); + +(function (tree) { + + tree.Quoted = function (str, content, escaped, index, currentFileInfo) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = index; + this.currentFileInfo = currentFileInfo; + }; + tree.Quoted.prototype = { + type: "Quoted", + genCSS: function (env, output) { + if (!this.escaped) { + output.add(this.quote, this.currentFileInfo, this.index); + } + output.add(this.value); + if (!this.escaped) { + output.add(this.quote); + } + }, + toCSS: tree.toCSS, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new (tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new (tree.Variable)('@' + name, that.index, that.currentFileInfo).eval(env, true); + return (v instanceof tree.Quoted) ? v.value : v.toCSS(); + }); + return new (tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index, this.currentFileInfo); + }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left, right; + + // when comparing quoted strings allow the quote to differ + if (x.type === "Quoted" && !this.escaped && !x.escaped) { + left = x.value; + right = this.value; + } else { + left = this.toCSS(); + right = x.toCSS(); + } + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + } + }; + +})(require('../tree')); + +(function (tree) { + + tree.Rule = function (name, value, important, merge, index, currentFileInfo, inline, variable) { + this.name = name; + this.value = (value instanceof tree.Value || value instanceof tree.Ruleset) ? value : new (tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.merge = merge; + this.index = index; + this.currentFileInfo = currentFileInfo; + this.inline = inline || false; + this.variable = (variable !== undefined) ? variable + : (name.charAt && (name.charAt(0) === '@')); + }; + + tree.Rule.prototype = { + type: "Rule", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + genCSS: function (env, output) { + output.add(this.name + (env.compress ? ':' : ': '), this.currentFileInfo, this.index); + try { + this.value.genCSS(env, output); + } + catch (e) { + e.index = this.index; + e.filename = this.currentFileInfo.filename; + throw e; + } + output.add(this.important + ((this.inline || (env.lastRule && env.compress)) ? "" : ";"), this.currentFileInfo, this.index); + }, + toCSS: tree.toCSS, + eval: function (env) { + var strictMathBypass = false, name = this.name, variable = this.variable, evaldValue; + if (typeof name !== "string") { + // expand 'primitive' name directly to get + // things faster (~10% for benchmark.less): + name = (name.length === 1) + && (name[0] instanceof tree.Keyword) + ? name[0].value : evalName(env, name); + variable = false; // never treat expanded interpolation as new variable name + } + if (name === "font" && !env.strictMath) { + strictMathBypass = true; + env.strictMath = true; + } + try { + evaldValue = this.value.eval(env); + + if (!this.variable && evaldValue.type === "DetachedRuleset") { + throw { + message: "Rulesets cannot be evaluated on a property.", + index: this.index, filename: this.currentFileInfo.filename + }; + } + + return new (tree.Rule)(name, + evaldValue, + this.important, + this.merge, + this.index, this.currentFileInfo, this.inline, + variable); + } + catch (e) { + if (typeof e.index !== 'number') { + e.index = this.index; + e.filename = this.currentFileInfo.filename; + } + throw e; + } + finally { + if (strictMathBypass) { + env.strictMath = false; + } + } + }, + makeImportant: function () { + return new (tree.Rule)(this.name, + this.value, + "!important", + this.merge, + this.index, this.currentFileInfo, this.inline); + } + }; + + function evalName(env, name) { + var value = "", i, n = name.length, + output = { + add: function (s) { + value += s; + } + }; + for (i = 0; i < n; i++) { + name[i].eval(env).genCSS(env, output); + } + return value; + } + +})(require('../tree')); + +(function (tree) { + + tree.RulesetCall = function (variable) { + this.variable = variable; + }; + tree.RulesetCall.prototype = { + type: "RulesetCall", + accept: function (visitor) { + }, + eval: function (env) { + var detachedRuleset = new (tree.Variable)(this.variable).eval(env); + return detachedRuleset.callEval(env); + } + }; + +})(require('../tree')); + +(function (tree) { + + tree.Ruleset = function (selectors, rules, strictImports) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; + this.strictImports = strictImports; + }; + tree.Ruleset.prototype = { + type: "Ruleset", + accept: function (visitor) { + if (this.paths) { + visitor.visitArray(this.paths, true); + } else if (this.selectors) { + this.selectors = visitor.visitArray(this.selectors); + } + if (this.rules && this.rules.length) { + this.rules = visitor.visitArray(this.rules); + } + }, + eval: function (env) { + var thisSelectors = this.selectors, selectors, + selCnt, selector, i, defaultFunc = tree.defaultFunc, hasOnePassingSelector = false; + + if (thisSelectors && (selCnt = thisSelectors.length)) { + selectors = []; + defaultFunc.error({ + type: "Syntax", + message: "it is currently only allowed in parametric mixin guards," + }); + for (i = 0; i < selCnt; i++) { + selector = thisSelectors[i].eval(env); + selectors.push(selector); + if (selector.evaldCondition) { + hasOnePassingSelector = true; + } + } + defaultFunc.reset(); + } else { + hasOnePassingSelector = true; + } + + var rules = this.rules ? this.rules.slice(0) : null, + ruleset = new (tree.Ruleset)(selectors, rules, this.strictImports), + rule, subRule; + + ruleset.originalRuleset = this; + ruleset.root = this.root; + ruleset.firstRoot = this.firstRoot; + ruleset.allowImports = this.allowImports; + + if (this.debugInfo) { + ruleset.debugInfo = this.debugInfo; + } + + if (!hasOnePassingSelector) { + rules.length = 0; + } + + // push the current ruleset to the frames stack + var envFrames = env.frames; + envFrames.unshift(ruleset); + + // currrent selectors + var envSelectors = env.selectors; + if (!envSelectors) { + env.selectors = envSelectors = []; + } + envSelectors.unshift(this.selectors); + + // Evaluate imports + if (ruleset.root || ruleset.allowImports || !ruleset.strictImports) { + ruleset.evalImports(env); + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + var rsRules = ruleset.rules, rsRuleCnt = rsRules ? rsRules.length : 0; + for (i = 0; i < rsRuleCnt; i++) { + if (rsRules[i] instanceof tree.mixin.Definition || rsRules[i] instanceof tree.DetachedRuleset) { + rsRules[i] = rsRules[i].eval(env); + } + } + + var mediaBlockCount = (env.mediaBlocks && env.mediaBlocks.length) || 0; + + // Evaluate mixin calls. + for (i = 0; i < rsRuleCnt; i++) { + if (rsRules[i] instanceof tree.mixin.Call) { + /*jshint loopfunc:true */ + rules = rsRules[i].eval(env).filter(function (r) { + if ((r instanceof tree.Rule) && r.variable) { + // do not pollute the scope if the variable is + // already there. consider returning false here + // but we need a way to "return" variable from mixins + return !(ruleset.variable(r.name)); + } + return true; + }); + rsRules.splice.apply(rsRules, [i, 1].concat(rules)); + rsRuleCnt += rules.length - 1; + i += rules.length - 1; + ruleset.resetCache(); + } else if (rsRules[i] instanceof tree.RulesetCall) { + /*jshint loopfunc:true */ + rules = rsRules[i].eval(env).rules.filter(function (r) { + if ((r instanceof tree.Rule) && r.variable) { + // do not pollute the scope at all + return false; + } + return true; + }); + rsRules.splice.apply(rsRules, [i, 1].concat(rules)); + rsRuleCnt += rules.length - 1; + i += rules.length - 1; + ruleset.resetCache(); + } + } + + // Evaluate everything else + for (i = 0; i < rsRules.length; i++) { + rule = rsRules[i]; + if (!(rule instanceof tree.mixin.Definition || rule instanceof tree.DetachedRuleset)) { + rsRules[i] = rule = rule.eval ? rule.eval(env) : rule; + } + } + + // Evaluate everything else + for (i = 0; i < rsRules.length; i++) { + rule = rsRules[i]; + // for rulesets, check if it is a css guard and can be removed + if (rule instanceof tree.Ruleset && rule.selectors && rule.selectors.length === 1) { + // check if it can be folded in (e.g. & where) + if (rule.selectors[0].isJustParentSelector()) { + rsRules.splice(i--, 1); + + for (var j = 0; j < rule.rules.length; j++) { + subRule = rule.rules[j]; + if (!(subRule instanceof tree.Rule) || !subRule.variable) { + rsRules.splice(++i, 0, subRule); + } + } + } + } + } + + // Pop the stack + envFrames.shift(); + envSelectors.shift(); + + if (env.mediaBlocks) { + for (i = mediaBlockCount; i < env.mediaBlocks.length; i++) { + env.mediaBlocks[i].bubbleSelectors(selectors); + } + } + + return ruleset; + }, + evalImports: function (env) { + var rules = this.rules, i, importRules; + if (!rules) { + return; + } + + for (i = 0; i < rules.length; i++) { + if (rules[i] instanceof tree.Import) { + importRules = rules[i].eval(env); + if (importRules && importRules.length) { + rules.splice.apply(rules, [i, 1].concat(importRules)); + i += importRules.length - 1; + } else { + rules.splice(i, 1, importRules); + } + this.resetCache(); + } + } + }, + makeImportant: function () { + return new tree.Ruleset(this.selectors, this.rules.map(function (r) { + if (r.makeImportant) { + return r.makeImportant(); + } else { + return r; + } + }), this.strictImports); + }, + matchArgs: function (args) { + return !args || args.length === 0; + }, + // lets you call a css selector with a guard + matchCondition: function (args, env) { + var lastSelector = this.selectors[this.selectors.length - 1]; + if (!lastSelector.evaldCondition) { + return false; + } + if (lastSelector.condition && !lastSelector.condition.eval( + new (tree.evalEnv)(env, + env.frames))) { + return false; + } + return true; + }, + resetCache: function () { + this._rulesets = null; + this._variables = null; + this._lookups = {}; + }, + variables: function () { + if (!this._variables) { + this._variables = !this.rules ? {} : this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + return this._variables; + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + if (!this.rules) { + return null; + } + + var _Ruleset = tree.Ruleset, _MixinDefinition = tree.mixin.Definition, + filtRules = [], rules = this.rules, cnt = rules.length, + i, rule; + + for (i = 0; i < cnt; i++) { + rule = rules[i]; + if ((rule instanceof _Ruleset) || (rule instanceof _MixinDefinition)) { + filtRules.push(rule); + } + } + + return filtRules; + }, + prependRule: function (rule) { + var rules = this.rules; + if (rules) { + rules.unshift(rule); + } else { + this.rules = [rule]; + } + }, + find: function (selector, self) { + self = self || this; + var rules = [], match, + key = selector.toCSS(); + + if (key in this._lookups) { + return this._lookups[key]; + } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + match = selector.match(rule.selectors[j]); + if (match) { + if (selector.elements.length > match) { + Array.prototype.push.apply(rules, rule.find( + new (tree.Selector)(selector.elements.slice(match)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + this._lookups[key] = rules; + return rules; + }, + genCSS: function (env, output) { + var i, j, + charsetRuleNodes = [], + ruleNodes = [], + rulesetNodes = [], + rulesetNodeCnt, + debugInfo, // Line number debugging + rule, + path; + + env.tabLevel = (env.tabLevel || 0); + + if (!this.root) { + env.tabLevel++; + } + + var tabRuleStr = env.compress ? '' : Array(env.tabLevel + 1).join(" "), + tabSetStr = env.compress ? '' : Array(env.tabLevel).join(" "), + sep; + + function isRulesetLikeNode(rule, root) { + // if it has nested rules, then it should be treated like a ruleset + if (rule.rules) + return true; + + // medias and comments do not have nested rules, but should be treated like rulesets anyway + if ((rule instanceof tree.Media) || (root && rule instanceof tree.Comment)) + return true; + + // some directives and anonumoust nodes are ruleset like, others are not + if ((rule instanceof tree.Directive) || (rule instanceof tree.Anonymous)) { + return rule.isRulesetLike(); + } + + //anything else is assumed to be a rule + return false; + } + + for (i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + if (isRulesetLikeNode(rule, this.root)) { + rulesetNodes.push(rule); + } else { + //charsets should float on top of everything + if (rule.isCharset && rule.isCharset()) { + charsetRuleNodes.push(rule); + } else { + ruleNodes.push(rule); + } + } + } + ruleNodes = charsetRuleNodes.concat(ruleNodes); + + // If this is the root node, we don't render + // a selector, or {}. + if (!this.root) { + debugInfo = tree.debugInfo(env, this, tabSetStr); + + if (debugInfo) { + output.add(debugInfo); + output.add(tabSetStr); + } + + var paths = this.paths, pathCnt = paths.length, + pathSubCnt; + + sep = env.compress ? ',' : (',\n' + tabSetStr); + + for (i = 0; i < pathCnt; i++) { + path = paths[i]; + if (!(pathSubCnt = path.length)) { + continue; + } + if (i > 0) { + output.add(sep); + } + + env.firstSelector = true; + path[0].genCSS(env, output); + + env.firstSelector = false; + for (j = 1; j < pathSubCnt; j++) { + path[j].genCSS(env, output); + } + } + + output.add((env.compress ? '{' : ' {\n') + tabRuleStr); + } + + // Compile rules and rulesets + for (i = 0; i < ruleNodes.length; i++) { + rule = ruleNodes[i]; + + // @page{ directive ends up with root elements inside it, a mix of rules and rulesets + // In this instance we do not know whether it is the last property + if (i + 1 === ruleNodes.length && (!this.root || rulesetNodes.length === 0 || this.firstRoot)) { + env.lastRule = true; + } + + if (rule.genCSS) { + rule.genCSS(env, output); + } else if (rule.value) { + output.add(rule.value.toString()); + } + + if (!env.lastRule) { + output.add(env.compress ? '' : ('\n' + tabRuleStr)); + } else { + env.lastRule = false; + } + } + + if (!this.root) { + output.add((env.compress ? '}' : '\n' + tabSetStr + '}')); + env.tabLevel--; + } + + sep = (env.compress ? "" : "\n") + (this.root ? tabRuleStr : tabSetStr); + rulesetNodeCnt = rulesetNodes.length; + if (rulesetNodeCnt) { + if (ruleNodes.length && sep) { + output.add(sep); + } + rulesetNodes[0].genCSS(env, output); + for (i = 1; i < rulesetNodeCnt; i++) { + if (sep) { + output.add(sep); + } + rulesetNodes[i].genCSS(env, output); + } + } + + if (!output.isEmpty() && !env.compress && this.firstRoot) { + output.add('\n'); + } + }, + + toCSS: tree.toCSS, + + markReferenced: function () { + if (!this.selectors) { + return; + } + for (var s = 0; s < this.selectors.length; s++) { + this.selectors[s].markReferenced(); + } + }, + + joinSelectors: function (paths, context, selectors) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function (paths, context, selector) { + + var i, j, k, + hasParentSelector, newSelectors, el, sel, parentSel, + newSelectorPath, afterParentJoin, newJoinedSelector, + newJoinedSelectorEmpty, lastSelector, currentElements, + selectorsMultiplied; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.value === '&') { + hasParentSelector = true; + } + } + + if (!hasParentSelector) { + if (context.length > 0) { + for (i = 0; i < context.length; i++) { + paths.push(context[i].concat(selector)); + } + } + else { + paths.push([selector]); + } + return; + } + + // The paths are [[Selector]] + // The first list is a list of comma seperated selectors + // The inner list is a list of inheritance seperated selectors + // e.g. + // .a, .b { + // .c { + // } + // } + // == [[.a] [.c]] [[.b] [.c]] + // + + // the elements from the current selector so far + currentElements = []; + // the current list of new selectors to add to the path. + // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors + // by the parents + newSelectors = [[]]; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + // non parent reference elements just get added + if (el.value !== "&") { + currentElements.push(el); + } else { + // the new list of selectors to add + selectorsMultiplied = []; + + // merge the current list of non parent selector elements + // on to the current list of selectors to add + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + // loop through our current selectors + for (j = 0; j < newSelectors.length; j++) { + sel = newSelectors[j]; + // if we don't have any parent paths, the & might be in a mixin so that it can be used + // whether there are parents or not + if (context.length === 0) { + // the combinator used on el should now be applied to the next element instead so that + // it is not lost + if (sel.length > 0) { + sel[0].elements = sel[0].elements.slice(0); + sel[0].elements.push(new (tree.Element)(el.combinator, '', el.index, el.currentFileInfo)); + } + selectorsMultiplied.push(sel); + } + else { + // and the parent selectors + for (k = 0; k < context.length; k++) { + parentSel = context[k]; + // We need to put the current selectors + // then join the last selector's elements on to the parents selectors + + // our new selector path + newSelectorPath = []; + // selectors from the parent after the join + afterParentJoin = []; + newJoinedSelectorEmpty = true; + + //construct the joined selector - if & is the first thing this will be empty, + // if not newJoinedSelector will be the last set of elements in the selector + if (sel.length > 0) { + newSelectorPath = sel.slice(0); + lastSelector = newSelectorPath.pop(); + newJoinedSelector = selector.createDerived(lastSelector.elements.slice(0)); + newJoinedSelectorEmpty = false; + } + else { + newJoinedSelector = selector.createDerived([]); + } + + //put together the parent selectors after the join + if (parentSel.length > 1) { + afterParentJoin = afterParentJoin.concat(parentSel.slice(1)); + } + + if (parentSel.length > 0) { + newJoinedSelectorEmpty = false; + + // join the elements so far with the first part of the parent + newJoinedSelector.elements.push(new (tree.Element)(el.combinator, parentSel[0].elements[0].value, el.index, el.currentFileInfo)); + newJoinedSelector.elements = newJoinedSelector.elements.concat(parentSel[0].elements.slice(1)); + } + + if (!newJoinedSelectorEmpty) { + // now add the joined selector + newSelectorPath.push(newJoinedSelector); + } + + // and the rest of the parent + newSelectorPath = newSelectorPath.concat(afterParentJoin); + + // add that to our new set of selectors + selectorsMultiplied.push(newSelectorPath); + } + } + } + + // our new selectors has been multiplied, so reset the state + newSelectors = selectorsMultiplied; + currentElements = []; + } + } + + // if we have any elements left over (e.g. .a& .b == .b) + // add them on to all the current selectors + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + for (i = 0; i < newSelectors.length; i++) { + if (newSelectors[i].length > 0) { + paths.push(newSelectors[i]); + } + } + }, + + mergeElementsOnToSelectors: function (elements, selectors) { + var i, sel; + + if (selectors.length === 0) { + selectors.push([new (tree.Selector)(elements)]); + return; + } + + for (i = 0; i < selectors.length; i++) { + sel = selectors[i]; + + // if the previous thing in sel is a parent this needs to join on to it + if (sel.length > 0) { + sel[sel.length - 1] = sel[sel.length - 1].createDerived(sel[sel.length - 1].elements.concat(elements)); + } + else { + sel.push(new (tree.Selector)(elements)); + } + } + } + }; +})(require('../tree')); + +(function (tree) { + + tree.Selector = function (elements, extendList, condition, index, currentFileInfo, isReferenced) { + this.elements = elements; + this.extendList = extendList; + this.condition = condition; + this.currentFileInfo = currentFileInfo || {}; + this.isReferenced = isReferenced; + if (!condition) { + this.evaldCondition = true; + } + }; + tree.Selector.prototype = { + type: "Selector", + accept: function (visitor) { + if (this.elements) { + this.elements = visitor.visitArray(this.elements); + } + if (this.extendList) { + this.extendList = visitor.visitArray(this.extendList); + } + if (this.condition) { + this.condition = visitor.visit(this.condition); + } + }, + createDerived: function (elements, extendList, evaldCondition) { + evaldCondition = (evaldCondition != null) ? evaldCondition : this.evaldCondition; + var newSelector = new (tree.Selector)(elements, extendList || this.extendList, null, this.index, this.currentFileInfo, this.isReferenced); + newSelector.evaldCondition = evaldCondition; + newSelector.mediaEmpty = this.mediaEmpty; + return newSelector; + }, + match: function (other) { + var elements = this.elements, + len = elements.length, + olen, i; + + other.CacheElements(); + + olen = other._elements.length; + if (olen === 0 || len < olen) { + return 0; + } else { + for (i = 0; i < olen; i++) { + if (elements[i].value !== other._elements[i]) { + return 0; + } + } + } + + return olen; // return number of matched elements + }, + CacheElements: function () { + var css = '', len, v, i; + + if (!this._elements) { + + len = this.elements.length; + for (i = 0; i < len; i++) { + + v = this.elements[i]; + css += v.combinator.value; + + if (!v.value.value) { + css += v.value; + continue; + } + + if (typeof v.value.value !== "string") { + css = ''; + break; + } + css += v.value.value; + } + + this._elements = css.match(/[,&#\*\.\w-]([\w-]|(\\.))*/g); + + if (this._elements) { + if (this._elements[0] === "&") { + this._elements.shift(); + } + + } else { + this._elements = []; + } + + } + }, + isJustParentSelector: function () { + return !this.mediaEmpty && + this.elements.length === 1 && + this.elements[0].value === '&' && + (this.elements[0].combinator.value === ' ' || this.elements[0].combinator.value === ''); + }, + eval: function (env) { + var evaldCondition = this.condition && this.condition.eval(env), + elements = this.elements, extendList = this.extendList; + + elements = elements && elements.map(function (e) { + return e.eval(env); + }); + extendList = extendList && extendList.map(function (extend) { + return extend.eval(env); + }); + + return this.createDerived(elements, extendList, evaldCondition); + }, + genCSS: function (env, output) { + var i, element; + if ((!env || !env.firstSelector) && this.elements[0].combinator.value === "") { + output.add(' ', this.currentFileInfo, this.index); + } + if (!this._css) { + //TODO caching? speed comparison? + for (i = 0; i < this.elements.length; i++) { + element = this.elements[i]; + element.genCSS(env, output); + } + } + }, + toCSS: tree.toCSS, + markReferenced: function () { + this.isReferenced = true; + }, + getIsReferenced: function () { + return !this.currentFileInfo.reference || this.isReferenced; + }, + getIsOutput: function () { + return this.evaldCondition; + } + }; + +})(require('../tree')); + +(function (tree) { + + tree.UnicodeDescriptor = function (value) { + this.value = value; + }; + tree.UnicodeDescriptor.prototype = { + type: "UnicodeDescriptor", + genCSS: function (env, output) { + output.add(this.value); + }, + toCSS: tree.toCSS, + eval: function () { + return this; + } + }; + +})(require('../tree')); + +(function (tree) { + + tree.URL = function (val, currentFileInfo, isEvald) { + this.value = val; + this.currentFileInfo = currentFileInfo; + this.isEvald = isEvald; + }; + tree.URL.prototype = { + type: "Url", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + genCSS: function (env, output) { + output.add("url("); + this.value.genCSS(env, output); + output.add(")"); + }, + toCSS: tree.toCSS, + eval: function (ctx) { + var val = this.value.eval(ctx), + rootpath; + + if (!this.isEvald) { + // Add the base path if the URL is relative + rootpath = this.currentFileInfo && this.currentFileInfo.rootpath; + if (rootpath && typeof val.value === "string" && ctx.isPathRelative(val.value)) { + if (!val.quote) { + rootpath = rootpath.replace(/[\(\)'"\s]/g, function (match) { + return "\\" + match; + }); + } + val.value = rootpath + val.value; + } + + val.value = ctx.normalizePath(val.value); + + // Add url args if enabled + if (ctx.urlArgs) { + if (!val.value.match(/^\s*data:/)) { + var delimiter = val.value.indexOf('?') === -1 ? '?' : '&'; + var urlArgs = delimiter + ctx.urlArgs; + if (val.value.indexOf('#') !== -1) { + val.value = val.value.replace('#', urlArgs + '#'); + } else { + val.value += urlArgs; + } + } + } + } + + return new (tree.URL)(val, this.currentFileInfo, true); + } + }; + +})(require('../tree')); + +(function (tree) { + + tree.Value = function (value) { + this.value = value; + }; + tree.Value.prototype = { + type: "Value", + accept: function (visitor) { + if (this.value) { + this.value = visitor.visitArray(this.value); + } + }, + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new (tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + genCSS: function (env, output) { + var i; + for (i = 0; i < this.value.length; i++) { + this.value[i].genCSS(env, output); + if (i + 1 < this.value.length) { + output.add((env && env.compress) ? ',' : ', '); + } + } + }, + toCSS: tree.toCSS + }; + +})(require('../tree')); + +(function (tree) { + + tree.Variable = function (name, index, currentFileInfo) { + this.name = name; + this.index = index; + this.currentFileInfo = currentFileInfo || {}; + }; + tree.Variable.prototype = { + type: "Variable", + eval: function (env) { + var variable, name = this.name; + + if (name.indexOf('@@') === 0) { + name = '@' + new (tree.Variable)(name.slice(1)).eval(env).value; + } + + if (this.evaluating) { + throw { + type: 'Name', + message: "Recursive variable definition for " + name, + filename: this.currentFileInfo.file, + index: this.index + }; + } + + this.evaluating = true; + + variable = tree.find(env.frames, function (frame) { + var v = frame.variable(name); + if (v) { + return v.value.eval(env); + } + }); + if (variable) { + this.evaluating = false; + return variable; + } else { + throw { + type: 'Name', + message: "variable " + name + " is undefined", + filename: this.currentFileInfo.filename, + index: this.index + }; + } + } + }; + +})(require('../tree')); + +(function (tree) { + + var parseCopyProperties = [ + 'paths', // option - unmodified - paths to search for imports on + 'optimization', // option - optimization level (for the chunker) + 'files', // list of files that have been imported, used for import-once + 'contents', // map - filename to contents of all the files + 'contentsIgnoredChars', // map - filename to lines at the begining of each file to ignore + 'relativeUrls', // option - whether to adjust URL's to be relative + 'rootpath', // option - rootpath to append to URL's + 'strictImports', // option - + 'insecure', // option - whether to allow imports from insecure ssl hosts + 'dumpLineNumbers', // option - whether to dump line numbers + 'compress', // option - whether to compress + 'processImports', // option - whether to process imports. if false then imports will not be imported + 'syncImport', // option - whether to import synchronously + 'javascriptEnabled',// option - whether JavaScript is enabled. if undefined, defaults to true + 'mime', // browser only - mime type for sheet import + 'useFileCache', // browser only - whether to use the per file session cache + 'currentFileInfo' // information about the current file - for error reporting and importing and making urls relative etc. + ]; + + //currentFileInfo = { + // 'relativeUrls' - option - whether to adjust URL's to be relative + // 'filename' - full resolved filename of current file + // 'rootpath' - path to append to normal URLs for this node + // 'currentDirectory' - path to the current file, absolute + // 'rootFilename' - filename of the base file + // 'entryPath' - absolute path to the entry file + // 'reference' - whether the file should not be output and only output parts that are referenced + + tree.parseEnv = function (options) { + copyFromOriginal(options, this, parseCopyProperties); + + if (!this.contents) { + this.contents = {}; + } + if (!this.contentsIgnoredChars) { + this.contentsIgnoredChars = {}; + } + if (!this.files) { + this.files = {}; + } + + if (typeof this.paths === "string") { + this.paths = [this.paths]; + } + + if (!this.currentFileInfo) { + var filename = (options && options.filename) || "input"; + var entryPath = filename.replace(/[^\/\\]*$/, ""); + if (options) { + options.filename = null; + } + this.currentFileInfo = { + filename: filename, + relativeUrls: this.relativeUrls, + rootpath: (options && options.rootpath) || "", + currentDirectory: entryPath, + entryPath: entryPath, + rootFilename: filename + }; + } + }; + + var evalCopyProperties = [ + 'silent', // whether to swallow errors and warnings + 'verbose', // whether to log more activity + 'compress', // whether to compress + 'yuicompress', // whether to compress with the outside tool yui compressor + 'ieCompat', // whether to enforce IE compatibility (IE8 data-uri) + 'strictMath', // whether math has to be within parenthesis + 'strictUnits', // whether units need to evaluate correctly + 'cleancss', // whether to compress with clean-css + 'sourceMap', // whether to output a source map + 'importMultiple', // whether we are currently importing multiple copies + 'urlArgs' // whether to add args into url tokens + ]; + + tree.evalEnv = function (options, frames) { + copyFromOriginal(options, this, evalCopyProperties); + + this.frames = frames || []; + }; + + tree.evalEnv.prototype.inParenthesis = function () { + if (!this.parensStack) { + this.parensStack = []; + } + this.parensStack.push(true); + }; + + tree.evalEnv.prototype.outOfParenthesis = function () { + this.parensStack.pop(); + }; + + tree.evalEnv.prototype.isMathOn = function () { + return this.strictMath ? (this.parensStack && this.parensStack.length) : true; + }; + + tree.evalEnv.prototype.isPathRelative = function (path) { + return !/^(?:[a-z-]+:|\/)/.test(path); + }; + + tree.evalEnv.prototype.normalizePath = function (path) { + var + segments = path.split("/").reverse(), + segment; + + path = []; + while (segments.length !== 0) { + segment = segments.pop(); + switch (segment) { + case ".": + break; + case "..": + if ((path.length === 0) || (path[path.length - 1] === "..")) { + path.push(segment); + } else { + path.pop(); + } + break; + default: + path.push(segment); + break; + } + } + + return path.join("/"); + }; + + //todo - do the same for the toCSS env + //tree.toCSSEnv = function (options) { + //}; + + var copyFromOriginal = function (original, destination, propertiesToCopy) { + if (!original) { + return; + } + + for (var i = 0; i < propertiesToCopy.length; i++) { + if (original.hasOwnProperty(propertiesToCopy[i])) { + destination[propertiesToCopy[i]] = original[propertiesToCopy[i]]; + } + } + }; + +})(require('./tree')); + +(function (tree) { + + var _visitArgs = {visitDeeper: true}, + _hasIndexed = false; + + function _noop(node) { + return node; + } + + function indexNodeTypes(parent, ticker) { + // add .typeIndex to tree node types for lookup table + var key, child; + for (key in parent) { + if (parent.hasOwnProperty(key)) { + child = parent[key]; + switch (typeof child) { + case "function": + // ignore bound functions directly on tree which do not have a prototype + // or aren't nodes + if (child.prototype && child.prototype.type) { + child.prototype.typeIndex = ticker++; + } + break; + case "object": + ticker = indexNodeTypes(child, ticker); + break; + } + } + } + return ticker; + } + + tree.visitor = function (implementation) { + this._implementation = implementation; + this._visitFnCache = []; + + if (!_hasIndexed) { + indexNodeTypes(tree, 1); + _hasIndexed = true; + } + }; + + tree.visitor.prototype = { + visit: function (node) { + if (!node) { + return node; + } + + var nodeTypeIndex = node.typeIndex; + if (!nodeTypeIndex) { + return node; + } + + var visitFnCache = this._visitFnCache, + impl = this._implementation, + aryIndx = nodeTypeIndex << 1, + outAryIndex = aryIndx | 1, + func = visitFnCache[aryIndx], + funcOut = visitFnCache[outAryIndex], + visitArgs = _visitArgs, + fnName; + + visitArgs.visitDeeper = true; + + if (!func) { + fnName = "visit" + node.type; + func = impl[fnName] || _noop; + funcOut = impl[fnName + "Out"] || _noop; + visitFnCache[aryIndx] = func; + visitFnCache[outAryIndex] = funcOut; + } + + if (func !== _noop) { + var newNode = func.call(impl, node, visitArgs); + if (impl.isReplacing) { + node = newNode; + } + } + + if (visitArgs.visitDeeper && node && node.accept) { + node.accept(this); + } + + if (funcOut != _noop) { + funcOut.call(impl, node); + } + + return node; + }, + visitArray: function (nodes, nonReplacing) { + if (!nodes) { + return nodes; + } + + var cnt = nodes.length, i; + + // Non-replacing + if (nonReplacing || !this._implementation.isReplacing) { + for (i = 0; i < cnt; i++) { + this.visit(nodes[i]); + } + return nodes; + } + + // Replacing + var out = []; + for (i = 0; i < cnt; i++) { + var evald = this.visit(nodes[i]); + if (!evald.splice) { + out.push(evald); + } else if (evald.length) { + this.flatten(evald, out); + } + } + return out; + }, + flatten: function (arr, out) { + if (!out) { + out = []; + } + + var cnt, i, item, + nestedCnt, j, nestedItem; + + for (i = 0, cnt = arr.length; i < cnt; i++) { + item = arr[i]; + if (!item.splice) { + out.push(item); + continue; + } + + for (j = 0, nestedCnt = item.length; j < nestedCnt; j++) { + nestedItem = item[j]; + if (!nestedItem.splice) { + out.push(nestedItem); + } else if (nestedItem.length) { + this.flatten(nestedItem, out); + } + } + } + + return out; + } + }; + +})(require('./tree')); +(function (tree) { + tree.importVisitor = function (importer, finish, evalEnv, onceFileDetectionMap, recursionDetector) { + this._visitor = new tree.visitor(this); + this._importer = importer; + this._finish = finish; + this.env = evalEnv || new tree.evalEnv(); + this.importCount = 0; + this.onceFileDetectionMap = onceFileDetectionMap || {}; + this.recursionDetector = {}; + if (recursionDetector) { + for (var fullFilename in recursionDetector) { + if (recursionDetector.hasOwnProperty(fullFilename)) { + this.recursionDetector[fullFilename] = true; + } + } + } + }; + + tree.importVisitor.prototype = { + isReplacing: true, + run: function (root) { + var error; + try { + // process the contents + this._visitor.visit(root); + } + catch (e) { + error = e; + } + + this.isFinished = true; + + if (this.importCount === 0) { + this._finish(error); + } + }, + visitImport: function (importNode, visitArgs) { + var importVisitor = this, + evaldImportNode, + inlineCSS = importNode.options.inline; + + if (!importNode.css || inlineCSS) { + + try { + evaldImportNode = importNode.evalForImport(this.env); + } catch (e) { + if (!e.filename) { + e.index = importNode.index; + e.filename = importNode.currentFileInfo.filename; + } + // attempt to eval properly and treat as css + importNode.css = true; + // if that fails, this error will be thrown + importNode.error = e; + } + + if (evaldImportNode && (!evaldImportNode.css || inlineCSS)) { + importNode = evaldImportNode; + this.importCount++; + var env = new tree.evalEnv(this.env, this.env.frames.slice(0)); + + if (importNode.options.multiple) { + env.importMultiple = true; + } + + this._importer.push(importNode.getPath(), importNode.currentFileInfo, importNode.options, function (e, root, importedAtRoot, fullPath) { + if (e && !e.filename) { + e.index = importNode.index; + e.filename = importNode.currentFileInfo.filename; + } + + var duplicateImport = importedAtRoot || fullPath in importVisitor.recursionDetector; + if (!env.importMultiple) { + if (duplicateImport) { + importNode.skip = true; + } else { + importNode.skip = function () { + if (fullPath in importVisitor.onceFileDetectionMap) { + return true; + } + importVisitor.onceFileDetectionMap[fullPath] = true; + return false; + }; + } + } + + var subFinish = function (e) { + importVisitor.importCount--; + + if (importVisitor.importCount === 0 && importVisitor.isFinished) { + importVisitor._finish(e); + } + }; + + if (root) { + importNode.root = root; + importNode.importedFilename = fullPath; + + if (!inlineCSS && (env.importMultiple || !duplicateImport)) { + importVisitor.recursionDetector[fullPath] = true; + new (tree.importVisitor)(importVisitor._importer, subFinish, env, importVisitor.onceFileDetectionMap, importVisitor.recursionDetector) + .run(root); + return; + } + } + + subFinish(); + }); + } + } + visitArgs.visitDeeper = false; + return importNode; + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + return ruleNode; + }, + visitDirective: function (directiveNode, visitArgs) { + this.env.frames.unshift(directiveNode); + return directiveNode; + }, + visitDirectiveOut: function (directiveNode) { + this.env.frames.shift(); + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + this.env.frames.unshift(mixinDefinitionNode); + return mixinDefinitionNode; + }, + visitMixinDefinitionOut: function (mixinDefinitionNode) { + this.env.frames.shift(); + }, + visitRuleset: function (rulesetNode, visitArgs) { + this.env.frames.unshift(rulesetNode); + return rulesetNode; + }, + visitRulesetOut: function (rulesetNode) { + this.env.frames.shift(); + }, + visitMedia: function (mediaNode, visitArgs) { + this.env.frames.unshift(mediaNode.rules[0]); + return mediaNode; + }, + visitMediaOut: function (mediaNode) { + this.env.frames.shift(); + } + }; + +})(require('./tree')); +(function (tree) { + tree.joinSelectorVisitor = function () { + this.contexts = [[]]; + this._visitor = new tree.visitor(this); + }; + + tree.joinSelectorVisitor.prototype = { + run: function (root) { + return this._visitor.visit(root); + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + + visitRuleset: function (rulesetNode, visitArgs) { + var context = this.contexts[this.contexts.length - 1], + paths = [], selectors; + + this.contexts.push(paths); + + if (!rulesetNode.root) { + selectors = rulesetNode.selectors; + if (selectors) { + selectors = selectors.filter(function (selector) { + return selector.getIsOutput(); + }); + rulesetNode.selectors = selectors.length ? selectors : (selectors = null); + if (selectors) { + rulesetNode.joinSelectors(paths, context, selectors); + } + } + if (!selectors) { + rulesetNode.rules = null; + } + rulesetNode.paths = paths; + } + }, + visitRulesetOut: function (rulesetNode) { + this.contexts.length = this.contexts.length - 1; + }, + visitMedia: function (mediaNode, visitArgs) { + var context = this.contexts[this.contexts.length - 1]; + mediaNode.rules[0].root = (context.length === 0 || context[0].multiMedia); + } + }; + +})(require('./tree')); +(function (tree) { + tree.toCSSVisitor = function (env) { + this._visitor = new tree.visitor(this); + this._env = env; + }; + + tree.toCSSVisitor.prototype = { + isReplacing: true, + run: function (root) { + return this._visitor.visit(root); + }, + + visitRule: function (ruleNode, visitArgs) { + if (ruleNode.variable) { + return []; + } + return ruleNode; + }, + + visitMixinDefinition: function (mixinNode, visitArgs) { + // mixin definitions do not get eval'd - this means they keep state + // so we have to clear that state here so it isn't used if toCSS is called twice + mixinNode.frames = []; + return []; + }, + + visitExtend: function (extendNode, visitArgs) { + return []; + }, + + visitComment: function (commentNode, visitArgs) { + if (commentNode.isSilent(this._env)) { + return []; + } + return commentNode; + }, + + visitMedia: function (mediaNode, visitArgs) { + mediaNode.accept(this._visitor); + visitArgs.visitDeeper = false; + + if (!mediaNode.rules.length) { + return []; + } + return mediaNode; + }, + + visitDirective: function (directiveNode, visitArgs) { + if (directiveNode.currentFileInfo.reference && !directiveNode.isReferenced) { + return []; + } + if (directiveNode.name === "@charset") { + // Only output the debug info together with subsequent @charset definitions + // a comment (or @media statement) before the actual @charset directive would + // be considered illegal css as it has to be on the first line + if (this.charset) { + if (directiveNode.debugInfo) { + var comment = new tree.Comment("/* " + directiveNode.toCSS(this._env).replace(/\n/g, "") + " */\n"); + comment.debugInfo = directiveNode.debugInfo; + return this._visitor.visit(comment); + } + return []; + } + this.charset = true; + } + if (directiveNode.rules && directiveNode.rules.rules) { + this._mergeRules(directiveNode.rules.rules); + } + return directiveNode; + }, + + checkPropertiesInRoot: function (rules) { + var ruleNode; + for (var i = 0; i < rules.length; i++) { + ruleNode = rules[i]; + if (ruleNode instanceof tree.Rule && !ruleNode.variable) { + throw { + message: "properties must be inside selector blocks, they cannot be in the root.", + index: ruleNode.index, + filename: ruleNode.currentFileInfo ? ruleNode.currentFileInfo.filename : null + }; + } + } + }, + + visitRuleset: function (rulesetNode, visitArgs) { + var rule, rulesets = []; + if (rulesetNode.firstRoot) { + this.checkPropertiesInRoot(rulesetNode.rules); + } + if (!rulesetNode.root) { + if (rulesetNode.paths) { + rulesetNode.paths = rulesetNode.paths + .filter(function (p) { + var i; + if (p[0].elements[0].combinator.value === ' ') { + p[0].elements[0].combinator = new (tree.Combinator)(''); + } + for (i = 0; i < p.length; i++) { + if (p[i].getIsReferenced() && p[i].getIsOutput()) { + return true; + } + } + return false; + }); + } + + // Compile rules and rulesets + var nodeRules = rulesetNode.rules, nodeRuleCnt = nodeRules ? nodeRules.length : 0; + for (var i = 0; i < nodeRuleCnt;) { + rule = nodeRules[i]; + if (rule && rule.rules) { + // visit because we are moving them out from being a child + rulesets.push(this._visitor.visit(rule)); + nodeRules.splice(i, 1); + nodeRuleCnt--; + continue; + } + i++; + } + // accept the visitor to remove rules and refactor itself + // then we can decide now whether we want it or not + if (nodeRuleCnt > 0) { + rulesetNode.accept(this._visitor); + } else { + rulesetNode.rules = null; + } + visitArgs.visitDeeper = false; + + nodeRules = rulesetNode.rules; + if (nodeRules) { + this._mergeRules(nodeRules); + nodeRules = rulesetNode.rules; + } + if (nodeRules) { + this._removeDuplicateRules(nodeRules); + nodeRules = rulesetNode.rules; + } + + // now decide whether we keep the ruleset + if (nodeRules && nodeRules.length > 0 && rulesetNode.paths.length > 0) { + rulesets.splice(0, 0, rulesetNode); + } + } else { + rulesetNode.accept(this._visitor); + visitArgs.visitDeeper = false; + if (rulesetNode.firstRoot || (rulesetNode.rules && rulesetNode.rules.length > 0)) { + rulesets.splice(0, 0, rulesetNode); + } + } + if (rulesets.length === 1) { + return rulesets[0]; + } + return rulesets; + }, + + _removeDuplicateRules: function (rules) { + if (!rules) { + return; + } + + // remove duplicates + var ruleCache = {}, + ruleList, rule, i; + + for (i = rules.length - 1; i >= 0; i--) { + rule = rules[i]; + if (rule instanceof tree.Rule) { + if (!ruleCache[rule.name]) { + ruleCache[rule.name] = rule; + } else { + ruleList = ruleCache[rule.name]; + if (ruleList instanceof tree.Rule) { + ruleList = ruleCache[rule.name] = [ruleCache[rule.name].toCSS(this._env)]; + } + var ruleCSS = rule.toCSS(this._env); + if (ruleList.indexOf(ruleCSS) !== -1) { + rules.splice(i, 1); + } else { + ruleList.push(ruleCSS); + } + } + } + } + }, + + _mergeRules: function (rules) { + if (!rules) { + return; + } + + var groups = {}, + parts, + rule, + key; + + for (var i = 0; i < rules.length; i++) { + rule = rules[i]; + + if ((rule instanceof tree.Rule) && rule.merge) { + key = [rule.name, + rule.important ? "!" : ""].join(","); + + if (!groups[key]) { + groups[key] = []; + } else { + rules.splice(i--, 1); + } + + groups[key].push(rule); + } + } + + Object.keys(groups).map(function (k) { + + function toExpression(values) { + return new (tree.Expression)(values.map(function (p) { + return p.value; + })); + } + + function toValue(values) { + return new (tree.Value)(values.map(function (p) { + return p; + })); + } + + parts = groups[k]; + + if (parts.length > 1) { + rule = parts[0]; + var spacedGroups = []; + var lastSpacedGroup = []; + parts.map(function (p) { + if (p.merge === "+") { + if (lastSpacedGroup.length > 0) { + spacedGroups.push(toExpression(lastSpacedGroup)); + } + lastSpacedGroup = []; + } + lastSpacedGroup.push(p); + }); + spacedGroups.push(toExpression(lastSpacedGroup)); + rule.value = toValue(spacedGroups); + } + }); + } + }; + +})(require('./tree')); +(function (tree) { + /*jshint loopfunc:true */ + + tree.extendFinderVisitor = function () { + this._visitor = new tree.visitor(this); + this.contexts = []; + this.allExtendsStack = [[]]; + }; + + tree.extendFinderVisitor.prototype = { + run: function (root) { + root = this._visitor.visit(root); + root.allExtends = this.allExtendsStack[0]; + return root; + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitRuleset: function (rulesetNode, visitArgs) { + if (rulesetNode.root) { + return; + } + + var i, j, extend, allSelectorsExtendList = [], extendList; + + // get &:extend(.a); rules which apply to all selectors in this ruleset + var rules = rulesetNode.rules, ruleCnt = rules ? rules.length : 0; + for (i = 0; i < ruleCnt; i++) { + if (rulesetNode.rules[i] instanceof tree.Extend) { + allSelectorsExtendList.push(rules[i]); + rulesetNode.extendOnEveryPath = true; + } + } + + // now find every selector and apply the extends that apply to all extends + // and the ones which apply to an individual extend + var paths = rulesetNode.paths; + for (i = 0; i < paths.length; i++) { + var selectorPath = paths[i], + selector = selectorPath[selectorPath.length - 1], + selExtendList = selector.extendList; + + extendList = selExtendList ? selExtendList.slice(0).concat(allSelectorsExtendList) + : allSelectorsExtendList; + + if (extendList) { + extendList = extendList.map(function (allSelectorsExtend) { + return allSelectorsExtend.clone(); + }); + } + + for (j = 0; j < extendList.length; j++) { + this.foundExtends = true; + extend = extendList[j]; + extend.findSelfSelectors(selectorPath); + extend.ruleset = rulesetNode; + if (j === 0) { + extend.firstExtendOnThisSelectorPath = true; + } + this.allExtendsStack[this.allExtendsStack.length - 1].push(extend); + } + } + + this.contexts.push(rulesetNode.selectors); + }, + visitRulesetOut: function (rulesetNode) { + if (!rulesetNode.root) { + this.contexts.length = this.contexts.length - 1; + } + }, + visitMedia: function (mediaNode, visitArgs) { + mediaNode.allExtends = []; + this.allExtendsStack.push(mediaNode.allExtends); + }, + visitMediaOut: function (mediaNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + }, + visitDirective: function (directiveNode, visitArgs) { + directiveNode.allExtends = []; + this.allExtendsStack.push(directiveNode.allExtends); + }, + visitDirectiveOut: function (directiveNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + } + }; + + tree.processExtendsVisitor = function () { + this._visitor = new tree.visitor(this); + }; + + tree.processExtendsVisitor.prototype = { + run: function (root) { + var extendFinder = new tree.extendFinderVisitor(); + extendFinder.run(root); + if (!extendFinder.foundExtends) { + return root; + } + root.allExtends = root.allExtends.concat(this.doExtendChaining(root.allExtends, root.allExtends)); + this.allExtendsStack = [root.allExtends]; + return this._visitor.visit(root); + }, + doExtendChaining: function (extendsList, extendsListTarget, iterationCount) { + // + // chaining is different from normal extension.. if we extend an extend then we are not just copying, altering and pasting + // the selector we would do normally, but we are also adding an extend with the same target selector + // this means this new extend can then go and alter other extends + // + // this method deals with all the chaining work - without it, extend is flat and doesn't work on other extend selectors + // this is also the most expensive.. and a match on one selector can cause an extension of a selector we had already processed if + // we look at each selector at a time, as is done in visitRuleset + + var extendIndex, targetExtendIndex, matches, extendsToAdd = [], newSelector, extendVisitor = this, selectorPath, extend, targetExtend, newExtend; + + iterationCount = iterationCount || 0; + + //loop through comparing every extend with every target extend. + // a target extend is the one on the ruleset we are looking at copy/edit/pasting in place + // e.g. .a:extend(.b) {} and .b:extend(.c) {} then the first extend extends the second one + // and the second is the target. + // the seperation into two lists allows us to process a subset of chains with a bigger set, as is the + // case when processing media queries + for (extendIndex = 0; extendIndex < extendsList.length; extendIndex++) { + for (targetExtendIndex = 0; targetExtendIndex < extendsListTarget.length; targetExtendIndex++) { + + extend = extendsList[extendIndex]; + targetExtend = extendsListTarget[targetExtendIndex]; + + // look for circular references + if (extend.parent_ids.indexOf(targetExtend.object_id) >= 0) { + continue; + } + + // find a match in the target extends self selector (the bit before :extend) + selectorPath = [targetExtend.selfSelectors[0]]; + matches = extendVisitor.findMatch(extend, selectorPath); + + if (matches.length) { + + // we found a match, so for each self selector.. + extend.selfSelectors.forEach(function (selfSelector) { + + // process the extend as usual + newSelector = extendVisitor.extendSelector(matches, selectorPath, selfSelector); + + // but now we create a new extend from it + newExtend = new (tree.Extend)(targetExtend.selector, targetExtend.option, 0); + newExtend.selfSelectors = newSelector; + + // add the extend onto the list of extends for that selector + newSelector[newSelector.length - 1].extendList = [newExtend]; + + // record that we need to add it. + extendsToAdd.push(newExtend); + newExtend.ruleset = targetExtend.ruleset; + + //remember its parents for circular references + newExtend.parent_ids = newExtend.parent_ids.concat(targetExtend.parent_ids, extend.parent_ids); + + // only process the selector once.. if we have :extend(.a,.b) then multiple + // extends will look at the same selector path, so when extending + // we know that any others will be duplicates in terms of what is added to the css + if (targetExtend.firstExtendOnThisSelectorPath) { + newExtend.firstExtendOnThisSelectorPath = true; + targetExtend.ruleset.paths.push(newSelector); + } + }); + } + } + } + + if (extendsToAdd.length) { + // try to detect circular references to stop a stack overflow. + // may no longer be needed. + this.extendChainCount++; + if (iterationCount > 100) { + var selectorOne = "{unable to calculate}"; + var selectorTwo = "{unable to calculate}"; + try { + selectorOne = extendsToAdd[0].selfSelectors[0].toCSS(); + selectorTwo = extendsToAdd[0].selector.toCSS(); + } + catch (e) { + } + throw {message: "extend circular reference detected. One of the circular extends is currently:" + selectorOne + ":extend(" + selectorTwo + ")"}; + } + + // now process the new extends on the existing rules so that we can handle a extending b extending c ectending d extending e... + return extendsToAdd.concat(extendVisitor.doExtendChaining(extendsToAdd, extendsListTarget, iterationCount + 1)); + } else { + return extendsToAdd; + } + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitSelector: function (selectorNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitRuleset: function (rulesetNode, visitArgs) { + if (rulesetNode.root) { + return; + } + var matches, pathIndex, extendIndex, allExtends = this.allExtendsStack[this.allExtendsStack.length - 1], selectorsToAdd = [], extendVisitor = this, selectorPath; + + // look at each selector path in the ruleset, find any extend matches and then copy, find and replace + + for (extendIndex = 0; extendIndex < allExtends.length; extendIndex++) { + for (pathIndex = 0; pathIndex < rulesetNode.paths.length; pathIndex++) { + selectorPath = rulesetNode.paths[pathIndex]; + + // extending extends happens initially, before the main pass + if (rulesetNode.extendOnEveryPath) { + continue; + } + var extendList = selectorPath[selectorPath.length - 1].extendList; + if (extendList && extendList.length) { + continue; + } + + matches = this.findMatch(allExtends[extendIndex], selectorPath); + + if (matches.length) { + + allExtends[extendIndex].selfSelectors.forEach(function (selfSelector) { + selectorsToAdd.push(extendVisitor.extendSelector(matches, selectorPath, selfSelector)); + }); + } + } + } + rulesetNode.paths = rulesetNode.paths.concat(selectorsToAdd); + }, + findMatch: function (extend, haystackSelectorPath) { + // + // look through the haystack selector path to try and find the needle - extend.selector + // returns an array of selector matches that can then be replaced + // + var haystackSelectorIndex, hackstackSelector, hackstackElementIndex, haystackElement, + targetCombinator, i, + extendVisitor = this, + needleElements = extend.selector.elements, + potentialMatches = [], potentialMatch, matches = []; + + // loop through the haystack elements + for (haystackSelectorIndex = 0; haystackSelectorIndex < haystackSelectorPath.length; haystackSelectorIndex++) { + hackstackSelector = haystackSelectorPath[haystackSelectorIndex]; + + for (hackstackElementIndex = 0; hackstackElementIndex < hackstackSelector.elements.length; hackstackElementIndex++) { + + haystackElement = hackstackSelector.elements[hackstackElementIndex]; + + // if we allow elements before our match we can add a potential match every time. otherwise only at the first element. + if (extend.allowBefore || (haystackSelectorIndex === 0 && hackstackElementIndex === 0)) { + potentialMatches.push({ + pathIndex: haystackSelectorIndex, + index: hackstackElementIndex, + matched: 0, + initialCombinator: haystackElement.combinator + }); + } + + for (i = 0; i < potentialMatches.length; i++) { + potentialMatch = potentialMatches[i]; + + // selectors add " " onto the first element. When we use & it joins the selectors together, but if we don't + // then each selector in haystackSelectorPath has a space before it added in the toCSS phase. so we need to work out + // what the resulting combinator will be + targetCombinator = haystackElement.combinator.value; + if (targetCombinator === '' && hackstackElementIndex === 0) { + targetCombinator = ' '; + } + + // if we don't match, null our match to indicate failure + if (!extendVisitor.isElementValuesEqual(needleElements[potentialMatch.matched].value, haystackElement.value) || + (potentialMatch.matched > 0 && needleElements[potentialMatch.matched].combinator.value !== targetCombinator)) { + potentialMatch = null; + } else { + potentialMatch.matched++; + } + + // if we are still valid and have finished, test whether we have elements after and whether these are allowed + if (potentialMatch) { + potentialMatch.finished = potentialMatch.matched === needleElements.length; + if (potentialMatch.finished && + (!extend.allowAfter && (hackstackElementIndex + 1 < hackstackSelector.elements.length || haystackSelectorIndex + 1 < haystackSelectorPath.length))) { + potentialMatch = null; + } + } + // if null we remove, if not, we are still valid, so either push as a valid match or continue + if (potentialMatch) { + if (potentialMatch.finished) { + potentialMatch.length = needleElements.length; + potentialMatch.endPathIndex = haystackSelectorIndex; + potentialMatch.endPathElementIndex = hackstackElementIndex + 1; // index after end of match + potentialMatches.length = 0; // we don't allow matches to overlap, so start matching again + matches.push(potentialMatch); + } + } else { + potentialMatches.splice(i, 1); + i--; + } + } + } + } + return matches; + }, + isElementValuesEqual: function (elementValue1, elementValue2) { + if (typeof elementValue1 === "string" || typeof elementValue2 === "string") { + return elementValue1 === elementValue2; + } + if (elementValue1 instanceof tree.Attribute) { + if (elementValue1.op !== elementValue2.op || elementValue1.key !== elementValue2.key) { + return false; + } + if (!elementValue1.value || !elementValue2.value) { + if (elementValue1.value || elementValue2.value) { + return false; + } + return true; + } + elementValue1 = elementValue1.value.value || elementValue1.value; + elementValue2 = elementValue2.value.value || elementValue2.value; + return elementValue1 === elementValue2; + } + elementValue1 = elementValue1.value; + elementValue2 = elementValue2.value; + if (elementValue1 instanceof tree.Selector) { + if (!(elementValue2 instanceof tree.Selector) || elementValue1.elements.length !== elementValue2.elements.length) { + return false; + } + for (var i = 0; i < elementValue1.elements.length; i++) { + if (elementValue1.elements[i].combinator.value !== elementValue2.elements[i].combinator.value) { + if (i !== 0 || (elementValue1.elements[i].combinator.value || ' ') !== (elementValue2.elements[i].combinator.value || ' ')) { + return false; + } + } + if (!this.isElementValuesEqual(elementValue1.elements[i].value, elementValue2.elements[i].value)) { + return false; + } + } + return true; + } + return false; + }, + extendSelector: function (matches, selectorPath, replacementSelector) { + + //for a set of matches, replace each match with the replacement selector + + var currentSelectorPathIndex = 0, + currentSelectorPathElementIndex = 0, + path = [], + matchIndex, + selector, + firstElement, + match, + newElements; + + for (matchIndex = 0; matchIndex < matches.length; matchIndex++) { + match = matches[matchIndex]; + selector = selectorPath[match.pathIndex]; + firstElement = new tree.Element( + match.initialCombinator, + replacementSelector.elements[0].value, + replacementSelector.elements[0].index, + replacementSelector.elements[0].currentFileInfo + ); + + if (match.pathIndex > currentSelectorPathIndex && currentSelectorPathElementIndex > 0) { + path[path.length - 1].elements = path[path.length - 1].elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex)); + currentSelectorPathElementIndex = 0; + currentSelectorPathIndex++; + } + + newElements = selector.elements + .slice(currentSelectorPathElementIndex, match.index) + .concat([firstElement]) + .concat(replacementSelector.elements.slice(1)); + + if (currentSelectorPathIndex === match.pathIndex && matchIndex > 0) { + path[path.length - 1].elements = + path[path.length - 1].elements.concat(newElements); + } else { + path = path.concat(selectorPath.slice(currentSelectorPathIndex, match.pathIndex)); + + path.push(new tree.Selector( + newElements + )); + } + currentSelectorPathIndex = match.endPathIndex; + currentSelectorPathElementIndex = match.endPathElementIndex; + if (currentSelectorPathElementIndex >= selectorPath[currentSelectorPathIndex].elements.length) { + currentSelectorPathElementIndex = 0; + currentSelectorPathIndex++; + } + } + + if (currentSelectorPathIndex < selectorPath.length && currentSelectorPathElementIndex > 0) { + path[path.length - 1].elements = path[path.length - 1].elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex)); + currentSelectorPathIndex++; + } + + path = path.concat(selectorPath.slice(currentSelectorPathIndex, selectorPath.length)); + + return path; + }, + visitRulesetOut: function (rulesetNode) { + }, + visitMedia: function (mediaNode, visitArgs) { + var newAllExtends = mediaNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length - 1]); + newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, mediaNode.allExtends)); + this.allExtendsStack.push(newAllExtends); + }, + visitMediaOut: function (mediaNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + }, + visitDirective: function (directiveNode, visitArgs) { + var newAllExtends = directiveNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length - 1]); + newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, directiveNode.allExtends)); + this.allExtendsStack.push(newAllExtends); + }, + visitDirectiveOut: function (directiveNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + } + }; + +})(require('./tree')); + +(function (tree) { + + tree.sourceMapOutput = function (options) { + this._css = []; + this._rootNode = options.rootNode; + this._writeSourceMap = options.writeSourceMap; + this._contentsMap = options.contentsMap; + this._contentsIgnoredCharsMap = options.contentsIgnoredCharsMap; + this._sourceMapFilename = options.sourceMapFilename; + this._outputFilename = options.outputFilename; + this._sourceMapURL = options.sourceMapURL; + if (options.sourceMapBasepath) { + this._sourceMapBasepath = options.sourceMapBasepath.replace(/\\/g, '/'); + } + this._sourceMapRootpath = options.sourceMapRootpath; + this._outputSourceFiles = options.outputSourceFiles; + this._sourceMapGeneratorConstructor = options.sourceMapGenerator || require("source-map").SourceMapGenerator; + + if (this._sourceMapRootpath && this._sourceMapRootpath.charAt(this._sourceMapRootpath.length - 1) !== '/') { + this._sourceMapRootpath += '/'; + } + + this._lineNumber = 0; + this._column = 0; + }; + + tree.sourceMapOutput.prototype.normalizeFilename = function (filename) { + filename = filename.replace(/\\/g, '/'); + + if (this._sourceMapBasepath && filename.indexOf(this._sourceMapBasepath) === 0) { + filename = filename.substring(this._sourceMapBasepath.length); + if (filename.charAt(0) === '\\' || filename.charAt(0) === '/') { + filename = filename.substring(1); + } + } + return (this._sourceMapRootpath || "") + filename; + }; + + tree.sourceMapOutput.prototype.add = function (chunk, fileInfo, index, mapLines) { + + //ignore adding empty strings + if (!chunk) { + return; + } + + var lines, + sourceLines, + columns, + sourceColumns, + i; + + if (fileInfo) { + var inputSource = this._contentsMap[fileInfo.filename]; + + // remove vars/banner added to the top of the file + if (this._contentsIgnoredCharsMap[fileInfo.filename]) { + // adjust the index + index -= this._contentsIgnoredCharsMap[fileInfo.filename]; + if (index < 0) { + index = 0; + } + // adjust the source + inputSource = inputSource.slice(this._contentsIgnoredCharsMap[fileInfo.filename]); + } + inputSource = inputSource.substring(0, index); + sourceLines = inputSource.split("\n"); + sourceColumns = sourceLines[sourceLines.length - 1]; + } + + lines = chunk.split("\n"); + columns = lines[lines.length - 1]; + + if (fileInfo) { + if (!mapLines) { + this._sourceMapGenerator.addMapping({ + generated: {line: this._lineNumber + 1, column: this._column}, + original: {line: sourceLines.length, column: sourceColumns.length}, + source: this.normalizeFilename(fileInfo.filename) + }); + } else { + for (i = 0; i < lines.length; i++) { + this._sourceMapGenerator.addMapping({ + generated: {line: this._lineNumber + i + 1, column: i === 0 ? this._column : 0}, + original: {line: sourceLines.length + i, column: i === 0 ? sourceColumns.length : 0}, + source: this.normalizeFilename(fileInfo.filename) + }); + } + } + } + + if (lines.length === 1) { + this._column += columns.length; + } else { + this._lineNumber += lines.length - 1; + this._column = columns.length; + } + + this._css.push(chunk); + }; + + tree.sourceMapOutput.prototype.isEmpty = function () { + return this._css.length === 0; + }; + + tree.sourceMapOutput.prototype.toCSS = function (env) { + this._sourceMapGenerator = new this._sourceMapGeneratorConstructor({ + file: this._outputFilename, + sourceRoot: null + }); + + if (this._outputSourceFiles) { + for (var filename in this._contentsMap) { + if (this._contentsMap.hasOwnProperty(filename)) { + var source = this._contentsMap[filename]; + if (this._contentsIgnoredCharsMap[filename]) { + source = source.slice(this._contentsIgnoredCharsMap[filename]); + } + this._sourceMapGenerator.setSourceContent(this.normalizeFilename(filename), source); + } + } + } + + this._rootNode.genCSS(env, this); + + if (this._css.length > 0) { + var sourceMapURL, + sourceMapContent = JSON.stringify(this._sourceMapGenerator.toJSON()); + + if (this._sourceMapURL) { + sourceMapURL = this._sourceMapURL; + } else if (this._sourceMapFilename) { + sourceMapURL = this.normalizeFilename(this._sourceMapFilename); + } + + if (this._writeSourceMap) { + this._writeSourceMap(sourceMapContent); + } else { + sourceMapURL = "data:application/json;base64," + require('./encoder.js').encodeBase64(sourceMapContent); + } + + if (sourceMapURL) { + this._css.push("/*# sourceMappingURL=" + sourceMapURL + " */"); + } + } + + return this._css.join(''); + }; + +})(require('./tree')); + +// wraps the source-map code in a less module +(function () { + less.modules["source-map"] = function () { + + /* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + + /** + * Define a module along with a payload. + * @param {string} moduleName Name for the payload + * @param {ignored} deps Ignored. For compatibility with CommonJS AMD Spec + * @param {function} payload Function with (require, exports, module) params + */ + function define(moduleName, deps, payload) { + if (typeof moduleName != "string") { + throw new TypeError('Expected string, got: ' + moduleName); + } + + if (arguments.length == 2) { + payload = deps; + } + + if (moduleName in define.modules) { + throw new Error("Module already defined: " + moduleName); + } + define.modules[moduleName] = payload; + }; + + /** + * The global store of un-instantiated modules + */ + define.modules = {}; + + + /** + * We invoke require() in the context of a Domain so we can have multiple + * sets of modules running separate from each other. + * This contrasts with JSMs which are singletons, Domains allows us to + * optionally load a CommonJS module twice with separate data each time. + * Perhaps you want 2 command lines with a different set of commands in each, + * for example. + */ + function Domain() { + this.modules = {}; + this._currentModule = null; + } + + (function () { + + /** + * Lookup module names and resolve them by calling the definition function if + * needed. + * There are 2 ways to call this, either with an array of dependencies and a + * callback to call when the dependencies are found (which can happen + * asynchronously in an in-page context) or with a single string an no callback + * where the dependency is resolved synchronously and returned. + * The API is designed to be compatible with the CommonJS AMD spec and + * RequireJS. + * @param {string[]|string} deps A name, or names for the payload + * @param {function|undefined} callback Function to call when the dependencies + * are resolved + * @return {undefined|object} The module required or undefined for + * array/callback method + */ + Domain.prototype.require = function (deps, callback) { + if (Array.isArray(deps)) { + var params = deps.map(function (dep) { + return this.lookup(dep); + }, this); + if (callback) { + callback.apply(null, params); + } + return undefined; + } + else { + return this.lookup(deps); + } + }; + + function normalize(path) { + var bits = path.split('/'); + var i = 1; + while (i < bits.length) { + if (bits[i] === '..') { + bits.splice(i - 1, 1); + } else if (bits[i] === '.') { + bits.splice(i, 1); + } else { + i++; + } + } + return bits.join('/'); + } + + function join(a, b) { + a = a.trim(); + b = b.trim(); + if (/^\//.test(b)) { + return b; + } else { + return a.replace(/\/*$/, '/') + b; + } + } + + function dirname(path) { + var bits = path.split('/'); + bits.pop(); + return bits.join('/'); + } + + /** + * Lookup module names and resolve them by calling the definition function if + * needed. + * @param {string} moduleName A name for the payload to lookup + * @return {object} The module specified by aModuleName or null if not found. + */ + Domain.prototype.lookup = function (moduleName) { + if (/^\./.test(moduleName)) { + moduleName = normalize(join(dirname(this._currentModule), moduleName)); + } + + if (moduleName in this.modules) { + var module = this.modules[moduleName]; + return module; + } + + if (!(moduleName in define.modules)) { + throw new Error("Module not defined: " + moduleName); + } + + var module = define.modules[moduleName]; + + if (typeof module == "function") { + var exports = {}; + var previousModule = this._currentModule; + this._currentModule = moduleName; + module(this.require.bind(this), exports, {id: moduleName, uri: ""}); + this._currentModule = previousModule; + module = exports; + } + + // cache the resulting module object for next time + this.modules[moduleName] = module; + + return module; + }; + + }()); + + define.Domain = Domain; + define.globalDomain = new Domain(); + var require = define.globalDomain.require.bind(define.globalDomain); + /* -*- Mode: js; js-indent-level: 2; -*- */ + /* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + define('source-map/source-map-generator', ['require', 'exports', 'module', 'source-map/base64-vlq', 'source-map/util', 'source-map/array-set'], function (require, exports, module) { + + var base64VLQ = require('./base64-vlq'); + var util = require('./util'); + var ArraySet = require('./array-set').ArraySet; + + /** + * An instance of the SourceMapGenerator represents a source map which is + * being built incrementally. To create a new one, you must pass an object + * with the following properties: + * + * - file: The filename of the generated source. + * - sourceRoot: An optional root for all URLs in this source map. + */ + function SourceMapGenerator(aArgs) { + this._file = util.getArg(aArgs, 'file'); + this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null); + this._sources = new ArraySet(); + this._names = new ArraySet(); + this._mappings = []; + this._sourcesContents = null; + } + + SourceMapGenerator.prototype._version = 3; + + /** + * Creates a new SourceMapGenerator based on a SourceMapConsumer + * + * @param aSourceMapConsumer The SourceMap. + */ + SourceMapGenerator.fromSourceMap = + function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) { + var sourceRoot = aSourceMapConsumer.sourceRoot; + var generator = new SourceMapGenerator({ + file: aSourceMapConsumer.file, + sourceRoot: sourceRoot + }); + aSourceMapConsumer.eachMapping(function (mapping) { + var newMapping = { + generated: { + line: mapping.generatedLine, + column: mapping.generatedColumn + } + }; + + if (mapping.source) { + newMapping.source = mapping.source; + if (sourceRoot) { + newMapping.source = util.relative(sourceRoot, newMapping.source); + } + + newMapping.original = { + line: mapping.originalLine, + column: mapping.originalColumn + }; + + if (mapping.name) { + newMapping.name = mapping.name; + } + } + + generator.addMapping(newMapping); + }); + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content) { + generator.setSourceContent(sourceFile, content); + } + }); + return generator; + }; + + /** + * Add a single mapping from original source line and column to the generated + * source's line and column for this source map being created. The mapping + * object should have the following properties: + * + * - generated: An object with the generated line and column positions. + * - original: An object with the original line and column positions. + * - source: The original source file (relative to the sourceRoot). + * - name: An optional original token name for this mapping. + */ + SourceMapGenerator.prototype.addMapping = + function SourceMapGenerator_addMapping(aArgs) { + var generated = util.getArg(aArgs, 'generated'); + var original = util.getArg(aArgs, 'original', null); + var source = util.getArg(aArgs, 'source', null); + var name = util.getArg(aArgs, 'name', null); + + this._validateMapping(generated, original, source, name); + + if (source && !this._sources.has(source)) { + this._sources.add(source); + } + + if (name && !this._names.has(name)) { + this._names.add(name); + } + + this._mappings.push({ + generatedLine: generated.line, + generatedColumn: generated.column, + originalLine: original != null && original.line, + originalColumn: original != null && original.column, + source: source, + name: name + }); + }; + + /** + * Set the source content for a source file. + */ + SourceMapGenerator.prototype.setSourceContent = + function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) { + var source = aSourceFile; + if (this._sourceRoot) { + source = util.relative(this._sourceRoot, source); + } + + if (aSourceContent !== null) { + // Add the source content to the _sourcesContents map. + // Create a new _sourcesContents map if the property is null. + if (!this._sourcesContents) { + this._sourcesContents = {}; + } + this._sourcesContents[util.toSetString(source)] = aSourceContent; + } else { + // Remove the source file from the _sourcesContents map. + // If the _sourcesContents map is empty, set the property to null. + delete this._sourcesContents[util.toSetString(source)]; + if (Object.keys(this._sourcesContents).length === 0) { + this._sourcesContents = null; + } + } + }; + + /** + * Applies the mappings of a sub-source-map for a specific source file to the + * source map being generated. Each mapping to the supplied source file is + * rewritten using the supplied source map. Note: The resolution for the + * resulting mappings is the minimium of this map and the supplied map. + * + * @param aSourceMapConsumer The source map to be applied. + * @param aSourceFile Optional. The filename of the source file. + * If omitted, SourceMapConsumer's file property will be used. + */ + SourceMapGenerator.prototype.applySourceMap = + function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile) { + // If aSourceFile is omitted, we will use the file property of the SourceMap + if (!aSourceFile) { + aSourceFile = aSourceMapConsumer.file; + } + var sourceRoot = this._sourceRoot; + // Make "aSourceFile" relative if an absolute Url is passed. + if (sourceRoot) { + aSourceFile = util.relative(sourceRoot, aSourceFile); + } + // Applying the SourceMap can add and remove items from the sources and + // the names array. + var newSources = new ArraySet(); + var newNames = new ArraySet(); + + // Find mappings for the "aSourceFile" + this._mappings.forEach(function (mapping) { + if (mapping.source === aSourceFile && mapping.originalLine) { + // Check if it can be mapped by the source map, then update the mapping. + var original = aSourceMapConsumer.originalPositionFor({ + line: mapping.originalLine, + column: mapping.originalColumn + }); + if (original.source !== null) { + // Copy mapping + if (sourceRoot) { + mapping.source = util.relative(sourceRoot, original.source); + } else { + mapping.source = original.source; + } + mapping.originalLine = original.line; + mapping.originalColumn = original.column; + if (original.name !== null && mapping.name !== null) { + // Only use the identifier name if it's an identifier + // in both SourceMaps + mapping.name = original.name; + } + } + } + + var source = mapping.source; + if (source && !newSources.has(source)) { + newSources.add(source); + } + + var name = mapping.name; + if (name && !newNames.has(name)) { + newNames.add(name); + } + + }, this); + this._sources = newSources; + this._names = newNames; + + // Copy sourcesContents of applied map. + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content) { + if (sourceRoot) { + sourceFile = util.relative(sourceRoot, sourceFile); + } + this.setSourceContent(sourceFile, content); + } + }, this); + }; + + /** + * A mapping can have one of the three levels of data: + * + * 1. Just the generated position. + * 2. The Generated position, original position, and original source. + * 3. Generated and original position, original source, as well as a name + * token. + * + * To maintain consistency, we validate that any new mapping being added falls + * in to one of these categories. + */ + SourceMapGenerator.prototype._validateMapping = + function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource, + aName) { + if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aGenerated.line > 0 && aGenerated.column >= 0 + && !aOriginal && !aSource && !aName) { + // Case 1. + return; + } + else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aOriginal && 'line' in aOriginal && 'column' in aOriginal + && aGenerated.line > 0 && aGenerated.column >= 0 + && aOriginal.line > 0 && aOriginal.column >= 0 + && aSource) { + // Cases 2 and 3. + return; + } + else { + throw new Error('Invalid mapping: ' + JSON.stringify({ + generated: aGenerated, + source: aSource, + original: aOriginal, + name: aName + })); + } + }; + + /** + * Serialize the accumulated mappings in to the stream of base 64 VLQs + * specified by the source map format. + */ + SourceMapGenerator.prototype._serializeMappings = + function SourceMapGenerator_serializeMappings() { + var previousGeneratedColumn = 0; + var previousGeneratedLine = 1; + var previousOriginalColumn = 0; + var previousOriginalLine = 0; + var previousName = 0; + var previousSource = 0; + var result = ''; + var mapping; + + // The mappings must be guaranteed to be in sorted order before we start + // serializing them or else the generated line numbers (which are defined + // via the ';' separators) will be all messed up. Note: it might be more + // performant to maintain the sorting as we insert them, rather than as we + // serialize them, but the big O is the same either way. + this._mappings.sort(util.compareByGeneratedPositions); + + for (var i = 0, len = this._mappings.length; i < len; i++) { + mapping = this._mappings[i]; + + if (mapping.generatedLine !== previousGeneratedLine) { + previousGeneratedColumn = 0; + while (mapping.generatedLine !== previousGeneratedLine) { + result += ';'; + previousGeneratedLine++; + } + } + else { + if (i > 0) { + if (!util.compareByGeneratedPositions(mapping, this._mappings[i - 1])) { + continue; + } + result += ','; + } + } + + result += base64VLQ.encode(mapping.generatedColumn + - previousGeneratedColumn); + previousGeneratedColumn = mapping.generatedColumn; + + if (mapping.source) { + result += base64VLQ.encode(this._sources.indexOf(mapping.source) + - previousSource); + previousSource = this._sources.indexOf(mapping.source); + + // lines are stored 0-based in SourceMap spec version 3 + result += base64VLQ.encode(mapping.originalLine - 1 + - previousOriginalLine); + previousOriginalLine = mapping.originalLine - 1; + + result += base64VLQ.encode(mapping.originalColumn + - previousOriginalColumn); + previousOriginalColumn = mapping.originalColumn; + + if (mapping.name) { + result += base64VLQ.encode(this._names.indexOf(mapping.name) + - previousName); + previousName = this._names.indexOf(mapping.name); + } + } + } + + return result; + }; + + SourceMapGenerator.prototype._generateSourcesContent = + function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) { + return aSources.map(function (source) { + if (!this._sourcesContents) { + return null; + } + if (aSourceRoot) { + source = util.relative(aSourceRoot, source); + } + var key = util.toSetString(source); + return Object.prototype.hasOwnProperty.call(this._sourcesContents, + key) + ? this._sourcesContents[key] + : null; + }, this); + }; + + /** + * Externalize the source map. + */ + SourceMapGenerator.prototype.toJSON = + function SourceMapGenerator_toJSON() { + var map = { + version: this._version, + file: this._file, + sources: this._sources.toArray(), + names: this._names.toArray(), + mappings: this._serializeMappings() + }; + if (this._sourceRoot) { + map.sourceRoot = this._sourceRoot; + } + if (this._sourcesContents) { + map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot); + } + + return map; + }; + + /** + * Render the source map being generated to a string. + */ + SourceMapGenerator.prototype.toString = + function SourceMapGenerator_toString() { + return JSON.stringify(this); + }; + + exports.SourceMapGenerator = SourceMapGenerator; + + }); + /* -*- Mode: js; js-indent-level: 2; -*- */ + /* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + * + * Based on the Base 64 VLQ implementation in Closure Compiler: + * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java + * + * Copyright 2011 The Closure Compiler Authors. All rights reserved. + * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 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 THE COPYRIGHT + * OWNER OR CONTRIBUTORS 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. + */ + define('source-map/base64-vlq', ['require', 'exports', 'module', 'source-map/base64'], function (require, exports, module) { + + var base64 = require('./base64'); + + // A single base 64 digit can contain 6 bits of data. For the base 64 variable + // length quantities we use in the source map spec, the first bit is the sign, + // the next four bits are the actual value, and the 6th bit is the + // continuation bit. The continuation bit tells us whether there are more + // digits in this value following this digit. + // + // Continuation + // | Sign + // | | + // V V + // 101011 + + var VLQ_BASE_SHIFT = 5; + + // binary: 100000 + var VLQ_BASE = 1 << VLQ_BASE_SHIFT; + + // binary: 011111 + var VLQ_BASE_MASK = VLQ_BASE - 1; + + // binary: 100000 + var VLQ_CONTINUATION_BIT = VLQ_BASE; + + /** + * Converts from a two-complement value to a value where the sign bit is + * is placed in the least significant bit. For example, as decimals: + * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary) + * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary) + */ + function toVLQSigned(aValue) { + return aValue < 0 + ? ((-aValue) << 1) + 1 + : (aValue << 1) + 0; + } + + /** + * Converts to a two-complement value from a value where the sign bit is + * is placed in the least significant bit. For example, as decimals: + * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1 + * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2 + */ + function fromVLQSigned(aValue) { + var isNegative = (aValue & 1) === 1; + var shifted = aValue >> 1; + return isNegative + ? -shifted + : shifted; + } + + /** + * Returns the base 64 VLQ encoded value. + */ + exports.encode = function base64VLQ_encode(aValue) { + var encoded = ""; + var digit; + + var vlq = toVLQSigned(aValue); + + do { + digit = vlq & VLQ_BASE_MASK; + vlq >>>= VLQ_BASE_SHIFT; + if (vlq > 0) { + // There are still more digits in this value, so we must make sure the + // continuation bit is marked. + digit |= VLQ_CONTINUATION_BIT; + } + encoded += base64.encode(digit); + } while (vlq > 0); + + return encoded; + }; + + /** + * Decodes the next base 64 VLQ value from the given string and returns the + * value and the rest of the string. + */ + exports.decode = function base64VLQ_decode(aStr) { + var i = 0; + var strLen = aStr.length; + var result = 0; + var shift = 0; + var continuation, digit; + + do { + if (i >= strLen) { + throw new Error("Expected more digits in base 64 VLQ value."); + } + digit = base64.decode(aStr.charAt(i++)); + continuation = !!(digit & VLQ_CONTINUATION_BIT); + digit &= VLQ_BASE_MASK; + result = result + (digit << shift); + shift += VLQ_BASE_SHIFT; + } while (continuation); + + return { + value: fromVLQSigned(result), + rest: aStr.slice(i) + }; + }; + + }); + /* -*- Mode: js; js-indent-level: 2; -*- */ + /* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + define('source-map/base64', ['require', 'exports', 'module',], function (require, exports, module) { + + var charToIntMap = {}; + var intToCharMap = {}; + + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' + .split('') + .forEach(function (ch, index) { + charToIntMap[ch] = index; + intToCharMap[index] = ch; + }); + + /** + * Encode an integer in the range of 0 to 63 to a single base 64 digit. + */ + exports.encode = function base64_encode(aNumber) { + if (aNumber in intToCharMap) { + return intToCharMap[aNumber]; + } + throw new TypeError("Must be between 0 and 63: " + aNumber); + }; + + /** + * Decode a single base 64 digit to an integer. + */ + exports.decode = function base64_decode(aChar) { + if (aChar in charToIntMap) { + return charToIntMap[aChar]; + } + throw new TypeError("Not a valid base 64 digit: " + aChar); + }; + + }); + /* -*- Mode: js; js-indent-level: 2; -*- */ + /* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + define('source-map/util', ['require', 'exports', 'module',], function (require, exports, module) { + + /** + * This is a helper function for getting values from parameter/options + * objects. + * + * @param args The object we are extracting values from + * @param name The name of the property we are getting. + * @param defaultValue An optional value to return if the property is missing + * from the object. If this is not specified and the property is missing, an + * error will be thrown. + */ + function getArg(aArgs, aName, aDefaultValue) { + if (aName in aArgs) { + return aArgs[aName]; + } else if (arguments.length === 3) { + return aDefaultValue; + } else { + throw new Error('"' + aName + '" is a required argument.'); + } + } + + exports.getArg = getArg; + + var urlRegexp = /([\w+\-.]+):\/\/((\w+:\w+)@)?([\w.]+)?(:(\d+))?(\S+)?/; + var dataUrlRegexp = /^data:.+\,.+/; + + function urlParse(aUrl) { + var match = aUrl.match(urlRegexp); + if (!match) { + return null; + } + return { + scheme: match[1], + auth: match[3], + host: match[4], + port: match[6], + path: match[7] + }; + } + + exports.urlParse = urlParse; + + function urlGenerate(aParsedUrl) { + var url = aParsedUrl.scheme + "://"; + if (aParsedUrl.auth) { + url += aParsedUrl.auth + "@" + } + if (aParsedUrl.host) { + url += aParsedUrl.host; + } + if (aParsedUrl.port) { + url += ":" + aParsedUrl.port + } + if (aParsedUrl.path) { + url += aParsedUrl.path; + } + return url; + } + + exports.urlGenerate = urlGenerate; + + function join(aRoot, aPath) { + var url; + + if (aPath.match(urlRegexp) || aPath.match(dataUrlRegexp)) { + return aPath; + } + + if (aPath.charAt(0) === '/' && (url = urlParse(aRoot))) { + url.path = aPath; + return urlGenerate(url); + } + + return aRoot.replace(/\/$/, '') + '/' + aPath; + } + + exports.join = join; + + /** + * Because behavior goes wacky when you set `__proto__` on objects, we + * have to prefix all the strings in our set with an arbitrary character. + * + * See https://github.com/mozilla/source-map/pull/31 and + * https://github.com/mozilla/source-map/issues/30 + * + * @param String aStr + */ + function toSetString(aStr) { + return '$' + aStr; + } + + exports.toSetString = toSetString; + + function fromSetString(aStr) { + return aStr.substr(1); + } + + exports.fromSetString = fromSetString; + + function relative(aRoot, aPath) { + aRoot = aRoot.replace(/\/$/, ''); + + var url = urlParse(aRoot); + if (aPath.charAt(0) == "/" && url && url.path == "/") { + return aPath.slice(1); + } + + return aPath.indexOf(aRoot + '/') === 0 + ? aPath.substr(aRoot.length + 1) + : aPath; + } + + exports.relative = relative; + + function strcmp(aStr1, aStr2) { + var s1 = aStr1 || ""; + var s2 = aStr2 || ""; + return (s1 > s2) - (s1 < s2); + } + + /** + * Comparator between two mappings where the original positions are compared. + * + * Optionally pass in `true` as `onlyCompareGenerated` to consider two + * mappings with the same original source/line/column, but different generated + * line and column the same. Useful when searching for a mapping with a + * stubbed out mapping. + */ + function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) { + var cmp; + + cmp = strcmp(mappingA.source, mappingB.source); + if (cmp) { + return cmp; + } + + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp) { + return cmp; + } + + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp || onlyCompareOriginal) { + return cmp; + } + + cmp = strcmp(mappingA.name, mappingB.name); + if (cmp) { + return cmp; + } + + cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp) { + return cmp; + } + + return mappingA.generatedColumn - mappingB.generatedColumn; + }; + exports.compareByOriginalPositions = compareByOriginalPositions; + + /** + * Comparator between two mappings where the generated positions are + * compared. + * + * Optionally pass in `true` as `onlyCompareGenerated` to consider two + * mappings with the same generated line and column, but different + * source/name/original line and column the same. Useful when searching for a + * mapping with a stubbed out mapping. + */ + function compareByGeneratedPositions(mappingA, mappingB, onlyCompareGenerated) { + var cmp; + + cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp) { + return cmp; + } + + cmp = mappingA.generatedColumn - mappingB.generatedColumn; + if (cmp || onlyCompareGenerated) { + return cmp; + } + + cmp = strcmp(mappingA.source, mappingB.source); + if (cmp) { + return cmp; + } + + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp) { + return cmp; + } + + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp) { + return cmp; + } + + return strcmp(mappingA.name, mappingB.name); + }; + exports.compareByGeneratedPositions = compareByGeneratedPositions; + + }); + /* -*- Mode: js; js-indent-level: 2; -*- */ + /* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + define('source-map/array-set', ['require', 'exports', 'module', 'source-map/util'], function (require, exports, module) { + + var util = require('./util'); + + /** + * A data structure which is a combination of an array and a set. Adding a new + * member is O(1), testing for membership is O(1), and finding the index of an + * element is O(1). Removing elements from the set is not supported. Only + * strings are supported for membership. + */ + function ArraySet() { + this._array = []; + this._set = {}; + } + + /** + * Static method for creating ArraySet instances from an existing array. + */ + ArraySet.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) { + var set = new ArraySet(); + for (var i = 0, len = aArray.length; i < len; i++) { + set.add(aArray[i], aAllowDuplicates); + } + return set; + }; + + /** + * Add the given string to this set. + * + * @param String aStr + */ + ArraySet.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) { + var isDuplicate = this.has(aStr); + var idx = this._array.length; + if (!isDuplicate || aAllowDuplicates) { + this._array.push(aStr); + } + if (!isDuplicate) { + this._set[util.toSetString(aStr)] = idx; + } + }; + + /** + * Is the given string a member of this set? + * + * @param String aStr + */ + ArraySet.prototype.has = function ArraySet_has(aStr) { + return Object.prototype.hasOwnProperty.call(this._set, + util.toSetString(aStr)); + }; + + /** + * What is the index of the given string in the array? + * + * @param String aStr + */ + ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) { + if (this.has(aStr)) { + return this._set[util.toSetString(aStr)]; + } + throw new Error('"' + aStr + '" is not in the set.'); + }; + + /** + * What is the element at the given index? + * + * @param Number aIdx + */ + ArraySet.prototype.at = function ArraySet_at(aIdx) { + if (aIdx >= 0 && aIdx < this._array.length) { + return this._array[aIdx]; + } + throw new Error('No element indexed by ' + aIdx); + }; + + /** + * Returns the array representation of this set (which has the proper indices + * indicated by indexOf). Note that this is a copy of the internal array used + * for storing the members so that no one can mess with internal state. + */ + ArraySet.prototype.toArray = function ArraySet_toArray() { + return this._array.slice(); + }; + + exports.ArraySet = ArraySet; + + }); + /* -*- Mode: js; js-indent-level: 2; -*- */ + /* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + define('source-map/source-map-consumer', ['require', 'exports', 'module', 'source-map/util', 'source-map/binary-search', 'source-map/array-set', 'source-map/base64-vlq'], function (require, exports, module) { + + var util = require('./util'); + var binarySearch = require('./binary-search'); + var ArraySet = require('./array-set').ArraySet; + var base64VLQ = require('./base64-vlq'); + + /** + * A SourceMapConsumer instance represents a parsed source map which we can + * query for information about the original file positions by giving it a file + * position in the generated source. + * + * The only parameter is the raw source map (either as a JSON string, or + * already parsed to an object). According to the spec, source maps have the + * following attributes: + * + * - version: Which version of the source map spec this map is following. + * - sources: An array of URLs to the original source files. + * - names: An array of identifiers which can be referrenced by individual mappings. + * - sourceRoot: Optional. The URL root from which all sources are relative. + * - sourcesContent: Optional. An array of contents of the original source files. + * - mappings: A string of base64 VLQs which contain the actual mappings. + * - file: The generated file this source map is associated with. + * + * Here is an example source map, taken from the source map spec[0]: + * + * { + * version : 3, + * file: "out.js", + * sourceRoot : "", + * sources: ["foo.js", "bar.js"], + * names: ["src", "maps", "are", "fun"], + * mappings: "AA,AB;;ABCDE;" + * } + * + * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1# + */ + function SourceMapConsumer(aSourceMap) { + var sourceMap = aSourceMap; + if (typeof aSourceMap === 'string') { + sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); + } + + var version = util.getArg(sourceMap, 'version'); + var sources = util.getArg(sourceMap, 'sources'); + // Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which + // requires the array) to play nice here. + var names = util.getArg(sourceMap, 'names', []); + var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null); + var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null); + var mappings = util.getArg(sourceMap, 'mappings'); + var file = util.getArg(sourceMap, 'file', null); + + // Once again, Sass deviates from the spec and supplies the version as a + // string rather than a number, so we use loose equality checking here. + if (version != this._version) { + throw new Error('Unsupported version: ' + version); + } + + // Pass `true` below to allow duplicate names and sources. While source maps + // are intended to be compressed and deduplicated, the TypeScript compiler + // sometimes generates source maps with duplicates in them. See Github issue + // #72 and bugzil.la/889492. + this._names = ArraySet.fromArray(names, true); + this._sources = ArraySet.fromArray(sources, true); + + this.sourceRoot = sourceRoot; + this.sourcesContent = sourcesContent; + this._mappings = mappings; + this.file = file; + } + + /** + * Create a SourceMapConsumer from a SourceMapGenerator. + * + * @param SourceMapGenerator aSourceMap + * The source map that will be consumed. + * @returns SourceMapConsumer + */ + SourceMapConsumer.fromSourceMap = + function SourceMapConsumer_fromSourceMap(aSourceMap) { + var smc = Object.create(SourceMapConsumer.prototype); + + smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true); + smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true); + smc.sourceRoot = aSourceMap._sourceRoot; + smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(), + smc.sourceRoot); + smc.file = aSourceMap._file; + + smc.__generatedMappings = aSourceMap._mappings.slice() + .sort(util.compareByGeneratedPositions); + smc.__originalMappings = aSourceMap._mappings.slice() + .sort(util.compareByOriginalPositions); + + return smc; + }; + + /** + * The version of the source mapping spec that we are consuming. + */ + SourceMapConsumer.prototype._version = 3; + + /** + * The list of original sources. + */ + Object.defineProperty(SourceMapConsumer.prototype, 'sources', { + get: function () { + return this._sources.toArray().map(function (s) { + return this.sourceRoot ? util.join(this.sourceRoot, s) : s; + }, this); + } + }); + + // `__generatedMappings` and `__originalMappings` are arrays that hold the + // parsed mapping coordinates from the source map's "mappings" attribute. They + // are lazily instantiated, accessed via the `_generatedMappings` and + // `_originalMappings` getters respectively, and we only parse the mappings + // and create these arrays once queried for a source location. We jump through + // these hoops because there can be many thousands of mappings, and parsing + // them is expensive, so we only want to do it if we must. + // + // Each object in the arrays is of the form: + // + // { + // generatedLine: The line number in the generated code, + // generatedColumn: The column number in the generated code, + // source: The path to the original source file that generated this + // chunk of code, + // originalLine: The line number in the original source that + // corresponds to this chunk of generated code, + // originalColumn: The column number in the original source that + // corresponds to this chunk of generated code, + // name: The name of the original symbol which generated this chunk of + // code. + // } + // + // All properties except for `generatedLine` and `generatedColumn` can be + // `null`. + // + // `_generatedMappings` is ordered by the generated positions. + // + // `_originalMappings` is ordered by the original positions. + + SourceMapConsumer.prototype.__generatedMappings = null; + Object.defineProperty(SourceMapConsumer.prototype, '_generatedMappings', { + get: function () { + if (!this.__generatedMappings) { + this.__generatedMappings = []; + this.__originalMappings = []; + this._parseMappings(this._mappings, this.sourceRoot); + } + + return this.__generatedMappings; + } + }); + + SourceMapConsumer.prototype.__originalMappings = null; + Object.defineProperty(SourceMapConsumer.prototype, '_originalMappings', { + get: function () { + if (!this.__originalMappings) { + this.__generatedMappings = []; + this.__originalMappings = []; + this._parseMappings(this._mappings, this.sourceRoot); + } + + return this.__originalMappings; + } + }); + + /** + * Parse the mappings in a string in to a data structure which we can easily + * query (the ordered arrays in the `this.__generatedMappings` and + * `this.__originalMappings` properties). + */ + SourceMapConsumer.prototype._parseMappings = + function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { + var generatedLine = 1; + var previousGeneratedColumn = 0; + var previousOriginalLine = 0; + var previousOriginalColumn = 0; + var previousSource = 0; + var previousName = 0; + var mappingSeparator = /^[,;]/; + var str = aStr; + var mapping; + var temp; + + while (str.length > 0) { + if (str.charAt(0) === ';') { + generatedLine++; + str = str.slice(1); + previousGeneratedColumn = 0; + } + else if (str.charAt(0) === ',') { + str = str.slice(1); + } + else { + mapping = {}; + mapping.generatedLine = generatedLine; + + // Generated column. + temp = base64VLQ.decode(str); + mapping.generatedColumn = previousGeneratedColumn + temp.value; + previousGeneratedColumn = mapping.generatedColumn; + str = temp.rest; + + if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) { + // Original source. + temp = base64VLQ.decode(str); + mapping.source = this._sources.at(previousSource + temp.value); + previousSource += temp.value; + str = temp.rest; + if (str.length === 0 || mappingSeparator.test(str.charAt(0))) { + throw new Error('Found a source, but no line and column'); + } + + // Original line. + temp = base64VLQ.decode(str); + mapping.originalLine = previousOriginalLine + temp.value; + previousOriginalLine = mapping.originalLine; + // Lines are stored 0-based + mapping.originalLine += 1; + str = temp.rest; + if (str.length === 0 || mappingSeparator.test(str.charAt(0))) { + throw new Error('Found a source and line, but no column'); + } + + // Original column. + temp = base64VLQ.decode(str); + mapping.originalColumn = previousOriginalColumn + temp.value; + previousOriginalColumn = mapping.originalColumn; + str = temp.rest; + + if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) { + // Original name. + temp = base64VLQ.decode(str); + mapping.name = this._names.at(previousName + temp.value); + previousName += temp.value; + str = temp.rest; + } + } + + this.__generatedMappings.push(mapping); + if (typeof mapping.originalLine === 'number') { + this.__originalMappings.push(mapping); + } + } + } + + this.__originalMappings.sort(util.compareByOriginalPositions); + }; + + /** + * Find the mapping that best matches the hypothetical "needle" mapping that + * we are searching for in the given "haystack" of mappings. + */ + SourceMapConsumer.prototype._findMapping = + function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName, + aColumnName, aComparator) { + // To return the position we are searching for, we must first find the + // mapping for the given position and then return the opposite position it + // points to. Because the mappings are sorted, we can use binary search to + // find the best mapping. + + if (aNeedle[aLineName] <= 0) { + throw new TypeError('Line must be greater than or equal to 1, got ' + + aNeedle[aLineName]); + } + if (aNeedle[aColumnName] < 0) { + throw new TypeError('Column must be greater than or equal to 0, got ' + + aNeedle[aColumnName]); + } + + return binarySearch.search(aNeedle, aMappings, aComparator); + }; + + /** + * Returns the original source, line, and column information for the generated + * source's line and column positions provided. The only argument is an object + * with the following properties: + * + * - line: The line number in the generated source. + * - column: The column number in the generated source. + * + * and an object is returned with the following properties: + * + * - source: The original source file, or null. + * - line: The line number in the original source, or null. + * - column: The column number in the original source, or null. + * - name: The original identifier, or null. + */ + SourceMapConsumer.prototype.originalPositionFor = + function SourceMapConsumer_originalPositionFor(aArgs) { + var needle = { + generatedLine: util.getArg(aArgs, 'line'), + generatedColumn: util.getArg(aArgs, 'column') + }; + + var mapping = this._findMapping(needle, + this._generatedMappings, + "generatedLine", + "generatedColumn", + util.compareByGeneratedPositions); + + if (mapping) { + var source = util.getArg(mapping, 'source', null); + if (source && this.sourceRoot) { + source = util.join(this.sourceRoot, source); + } + return { + source: source, + line: util.getArg(mapping, 'originalLine', null), + column: util.getArg(mapping, 'originalColumn', null), + name: util.getArg(mapping, 'name', null) + }; + } + + return { + source: null, + line: null, + column: null, + name: null + }; + }; + + /** + * Returns the original source content. The only argument is the url of the + * original source file. Returns null if no original source content is + * availible. + */ + SourceMapConsumer.prototype.sourceContentFor = + function SourceMapConsumer_sourceContentFor(aSource) { + if (!this.sourcesContent) { + return null; + } + + if (this.sourceRoot) { + aSource = util.relative(this.sourceRoot, aSource); + } + + if (this._sources.has(aSource)) { + return this.sourcesContent[this._sources.indexOf(aSource)]; + } + + var url; + if (this.sourceRoot + && (url = util.urlParse(this.sourceRoot))) { + // XXX: file:// URIs and absolute paths lead to unexpected behavior for + // many users. We can help them out when they expect file:// URIs to + // behave like it would if they were running a local HTTP server. See + // https://bugzilla.mozilla.org/show_bug.cgi?id=885597. + var fileUriAbsPath = aSource.replace(/^file:\/\//, ""); + if (url.scheme == "file" + && this._sources.has(fileUriAbsPath)) { + return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)] + } + + if ((!url.path || url.path == "/") + && this._sources.has("/" + aSource)) { + return this.sourcesContent[this._sources.indexOf("/" + aSource)]; + } + } + + throw new Error('"' + aSource + '" is not in the SourceMap.'); + }; + + /** + * Returns the generated line and column information for the original source, + * line, and column positions provided. The only argument is an object with + * the following properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. + * - column: The column number in the original source. + * + * and an object is returned with the following properties: + * + * - line: The line number in the generated source, or null. + * - column: The column number in the generated source, or null. + */ + SourceMapConsumer.prototype.generatedPositionFor = + function SourceMapConsumer_generatedPositionFor(aArgs) { + var needle = { + source: util.getArg(aArgs, 'source'), + originalLine: util.getArg(aArgs, 'line'), + originalColumn: util.getArg(aArgs, 'column') + }; + + if (this.sourceRoot) { + needle.source = util.relative(this.sourceRoot, needle.source); + } + + var mapping = this._findMapping(needle, + this._originalMappings, + "originalLine", + "originalColumn", + util.compareByOriginalPositions); + + if (mapping) { + return { + line: util.getArg(mapping, 'generatedLine', null), + column: util.getArg(mapping, 'generatedColumn', null) + }; + } + + return { + line: null, + column: null + }; + }; + + SourceMapConsumer.GENERATED_ORDER = 1; + SourceMapConsumer.ORIGINAL_ORDER = 2; + + /** + * Iterate over each mapping between an original source/line/column and a + * generated line/column in this source map. + * + * @param Function aCallback + * The function that is called with each mapping. + * @param Object aContext + * Optional. If specified, this object will be the value of `this` every + * time that `aCallback` is called. + * @param aOrder + * Either `SourceMapConsumer.GENERATED_ORDER` or + * `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to + * iterate over the mappings sorted by the generated file's line/column + * order or the original's source/line/column order, respectively. Defaults to + * `SourceMapConsumer.GENERATED_ORDER`. + */ + SourceMapConsumer.prototype.eachMapping = + function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) { + var context = aContext || null; + var order = aOrder || SourceMapConsumer.GENERATED_ORDER; + + var mappings; + switch (order) { + case SourceMapConsumer.GENERATED_ORDER: + mappings = this._generatedMappings; + break; + case SourceMapConsumer.ORIGINAL_ORDER: + mappings = this._originalMappings; + break; + default: + throw new Error("Unknown order of iteration."); + } + + var sourceRoot = this.sourceRoot; + mappings.map(function (mapping) { + var source = mapping.source; + if (source && sourceRoot) { + source = util.join(sourceRoot, source); + } + return { + source: source, + generatedLine: mapping.generatedLine, + generatedColumn: mapping.generatedColumn, + originalLine: mapping.originalLine, + originalColumn: mapping.originalColumn, + name: mapping.name + }; + }).forEach(aCallback, context); + }; + + exports.SourceMapConsumer = SourceMapConsumer; + + }); + /* -*- Mode: js; js-indent-level: 2; -*- */ + /* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + define('source-map/binary-search', ['require', 'exports', 'module',], function (require, exports, module) { + + /** + * Recursive implementation of binary search. + * + * @param aLow Indices here and lower do not contain the needle. + * @param aHigh Indices here and higher do not contain the needle. + * @param aNeedle The element being searched for. + * @param aHaystack The non-empty array being searched. + * @param aCompare Function which takes two elements and returns -1, 0, or 1. + */ + function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare) { + // This function terminates when one of the following is true: + // + // 1. We find the exact element we are looking for. + // + // 2. We did not find the exact element, but we can return the next + // closest element that is less than that element. + // + // 3. We did not find the exact element, and there is no next-closest + // element which is less than the one we are searching for, so we + // return null. + var mid = Math.floor((aHigh - aLow) / 2) + aLow; + var cmp = aCompare(aNeedle, aHaystack[mid], true); + if (cmp === 0) { + // Found the element we are looking for. + return aHaystack[mid]; + } + else if (cmp > 0) { + // aHaystack[mid] is greater than our needle. + if (aHigh - mid > 1) { + // The element is in the upper half. + return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare); + } + // We did not find an exact match, return the next closest one + // (termination case 2). + return aHaystack[mid]; + } + else { + // aHaystack[mid] is less than our needle. + if (mid - aLow > 1) { + // The element is in the lower half. + return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare); + } + // The exact needle element was not found in this haystack. Determine if + // we are in termination case (2) or (3) and return the appropriate thing. + return aLow < 0 + ? null + : aHaystack[aLow]; + } + } + + /** + * This is an implementation of binary search which will always try and return + * the next lowest value checked if there is no exact hit. This is because + * mappings between original and generated line/col pairs are single points, + * and there is an implicit region between each of them, so a miss just means + * that you aren't on the very start of a region. + * + * @param aNeedle The element you are looking for. + * @param aHaystack The array that is being searched. + * @param aCompare A function which takes the needle and an element in the + * array and returns -1, 0, or 1 depending on whether the needle is less + * than, equal to, or greater than the element, respectively. + */ + exports.search = function search(aNeedle, aHaystack, aCompare) { + return aHaystack.length > 0 + ? recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, aCompare) + : null; + }; + + }); + /* -*- Mode: js; js-indent-level: 2; -*- */ + /* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + define('source-map/source-node', ['require', 'exports', 'module', 'source-map/source-map-generator', 'source-map/util'], function (require, exports, module) { + + var SourceMapGenerator = require('./source-map-generator').SourceMapGenerator; + var util = require('./util'); + + /** + * SourceNodes provide a way to abstract over interpolating/concatenating + * snippets of generated JavaScript source code while maintaining the line and + * column information associated with the original source code. + * + * @param aLine The original line number. + * @param aColumn The original column number. + * @param aSource The original source's filename. + * @param aChunks Optional. An array of strings which are snippets of + * generated JS, or other SourceNodes. + * @param aName The original identifier. + */ + function SourceNode(aLine, aColumn, aSource, aChunks, aName) { + this.children = []; + this.sourceContents = {}; + this.line = aLine === undefined ? null : aLine; + this.column = aColumn === undefined ? null : aColumn; + this.source = aSource === undefined ? null : aSource; + this.name = aName === undefined ? null : aName; + if (aChunks != null) this.add(aChunks); + } + + /** + * Creates a SourceNode from generated code and a SourceMapConsumer. + * + * @param aGeneratedCode The generated code + * @param aSourceMapConsumer The SourceMap for the generated code + */ + SourceNode.fromStringWithSourceMap = + function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer) { + // The SourceNode we want to fill with the generated code + // and the SourceMap + var node = new SourceNode(); + + // The generated code + // Processed fragments are removed from this array. + var remainingLines = aGeneratedCode.split('\n'); + + // We need to remember the position of "remainingLines" + var lastGeneratedLine = 1, lastGeneratedColumn = 0; + + // The generate SourceNodes we need a code range. + // To extract it current and last mapping is used. + // Here we store the last mapping. + var lastMapping = null; + + aSourceMapConsumer.eachMapping(function (mapping) { + if (lastMapping === null) { + // We add the generated code until the first mapping + // to the SourceNode without any mapping. + // Each line is added as separate string. + while (lastGeneratedLine < mapping.generatedLine) { + node.add(remainingLines.shift() + "\n"); + lastGeneratedLine++; + } + if (lastGeneratedColumn < mapping.generatedColumn) { + var nextLine = remainingLines[0]; + node.add(nextLine.substr(0, mapping.generatedColumn)); + remainingLines[0] = nextLine.substr(mapping.generatedColumn); + lastGeneratedColumn = mapping.generatedColumn; + } + } else { + // We add the code from "lastMapping" to "mapping": + // First check if there is a new line in between. + if (lastGeneratedLine < mapping.generatedLine) { + var code = ""; + // Associate full lines with "lastMapping" + do { + code += remainingLines.shift() + "\n"; + lastGeneratedLine++; + lastGeneratedColumn = 0; + } while (lastGeneratedLine < mapping.generatedLine); + // When we reached the correct line, we add code until we + // reach the correct column too. + if (lastGeneratedColumn < mapping.generatedColumn) { + var nextLine = remainingLines[0]; + code += nextLine.substr(0, mapping.generatedColumn); + remainingLines[0] = nextLine.substr(mapping.generatedColumn); + lastGeneratedColumn = mapping.generatedColumn; + } + // Create the SourceNode. + addMappingWithCode(lastMapping, code); + } else { + // There is no new line in between. + // Associate the code between "lastGeneratedColumn" and + // "mapping.generatedColumn" with "lastMapping" + var nextLine = remainingLines[0]; + var code = nextLine.substr(0, mapping.generatedColumn - + lastGeneratedColumn); + remainingLines[0] = nextLine.substr(mapping.generatedColumn - + lastGeneratedColumn); + lastGeneratedColumn = mapping.generatedColumn; + addMappingWithCode(lastMapping, code); + } + } + lastMapping = mapping; + }, this); + // We have processed all mappings. + // Associate the remaining code in the current line with "lastMapping" + // and add the remaining lines without any mapping + addMappingWithCode(lastMapping, remainingLines.join("\n")); + + // Copy sourcesContent into SourceNode + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content) { + node.setSourceContent(sourceFile, content); + } + }); + + return node; + + function addMappingWithCode(mapping, code) { + if (mapping === null || mapping.source === undefined) { + node.add(code); + } else { + node.add(new SourceNode(mapping.originalLine, + mapping.originalColumn, + mapping.source, + code, + mapping.name)); + } + } + }; + + /** + * Add a chunk of generated JS to this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ + SourceNode.prototype.add = function SourceNode_add(aChunk) { + if (Array.isArray(aChunk)) { + aChunk.forEach(function (chunk) { + this.add(chunk); + }, this); + } + else if (aChunk instanceof SourceNode || typeof aChunk === "string") { + if (aChunk) { + this.children.push(aChunk); + } + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; + }; + + /** + * Add a chunk of generated JS to the beginning of this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ + SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) { + if (Array.isArray(aChunk)) { + for (var i = aChunk.length - 1; i >= 0; i--) { + this.prepend(aChunk[i]); + } + } + else if (aChunk instanceof SourceNode || typeof aChunk === "string") { + this.children.unshift(aChunk); + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; + }; + + /** + * Walk over the tree of JS snippets in this node and its children. The + * walking function is called once for each snippet of JS and is passed that + * snippet and the its original associated source's line/column location. + * + * @param aFn The traversal function. + */ + SourceNode.prototype.walk = function SourceNode_walk(aFn) { + var chunk; + for (var i = 0, len = this.children.length; i < len; i++) { + chunk = this.children[i]; + if (chunk instanceof SourceNode) { + chunk.walk(aFn); + } + else { + if (chunk !== '') { + aFn(chunk, { + source: this.source, + line: this.line, + column: this.column, + name: this.name + }); + } + } + } + }; + + /** + * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between + * each of `this.children`. + * + * @param aSep The separator. + */ + SourceNode.prototype.join = function SourceNode_join(aSep) { + var newChildren; + var i; + var len = this.children.length; + if (len > 0) { + newChildren = []; + for (i = 0; i < len - 1; i++) { + newChildren.push(this.children[i]); + newChildren.push(aSep); + } + newChildren.push(this.children[i]); + this.children = newChildren; + } + return this; + }; + + /** + * Call String.prototype.replace on the very right-most source snippet. Useful + * for trimming whitespace from the end of a source node, etc. + * + * @param aPattern The pattern to replace. + * @param aReplacement The thing to replace the pattern with. + */ + SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) { + var lastChild = this.children[this.children.length - 1]; + if (lastChild instanceof SourceNode) { + lastChild.replaceRight(aPattern, aReplacement); + } + else if (typeof lastChild === 'string') { + this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement); + } + else { + this.children.push(''.replace(aPattern, aReplacement)); + } + return this; + }; + + /** + * Set the source content for a source file. This will be added to the SourceMapGenerator + * in the sourcesContent field. + * + * @param aSourceFile The filename of the source file + * @param aSourceContent The content of the source file + */ + SourceNode.prototype.setSourceContent = + function SourceNode_setSourceContent(aSourceFile, aSourceContent) { + this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent; + }; + + /** + * Walk over the tree of SourceNodes. The walking function is called for each + * source file content and is passed the filename and source content. + * + * @param aFn The traversal function. + */ + SourceNode.prototype.walkSourceContents = + function SourceNode_walkSourceContents(aFn) { + for (var i = 0, len = this.children.length; i < len; i++) { + if (this.children[i] instanceof SourceNode) { + this.children[i].walkSourceContents(aFn); + } + } + + var sources = Object.keys(this.sourceContents); + for (var i = 0, len = sources.length; i < len; i++) { + aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]); + } + }; + + /** + * Return the string representation of this source node. Walks over the tree + * and concatenates all the various snippets together to one string. + */ + SourceNode.prototype.toString = function SourceNode_toString() { + var str = ""; + this.walk(function (chunk) { + str += chunk; + }); + return str; + }; + + /** + * Returns the string representation of this source node along with a source + * map. + */ + SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) { + var generated = { + code: "", + line: 1, + column: 0 + }; + var map = new SourceMapGenerator(aArgs); + var sourceMappingActive = false; + var lastOriginalSource = null; + var lastOriginalLine = null; + var lastOriginalColumn = null; + var lastOriginalName = null; + this.walk(function (chunk, original) { + generated.code += chunk; + if (original.source !== null + && original.line !== null + && original.column !== null) { + if (lastOriginalSource !== original.source + || lastOriginalLine !== original.line + || lastOriginalColumn !== original.column + || lastOriginalName !== original.name) { + map.addMapping({ + source: original.source, + original: { + line: original.line, + column: original.column + }, + generated: { + line: generated.line, + column: generated.column + }, + name: original.name + }); + } + lastOriginalSource = original.source; + lastOriginalLine = original.line; + lastOriginalColumn = original.column; + lastOriginalName = original.name; + sourceMappingActive = true; + } else if (sourceMappingActive) { + map.addMapping({ + generated: { + line: generated.line, + column: generated.column + } + }); + lastOriginalSource = null; + sourceMappingActive = false; + } + chunk.split('').forEach(function (ch) { + if (ch === '\n') { + generated.line++; + generated.column = 0; + } else { + generated.column++; + } + }); + }); + this.walkSourceContents(function (sourceFile, sourceContent) { + map.setSourceContent(sourceFile, sourceContent); + }); + + return {code: generated.code, map: map}; + }; + + exports.SourceNode = SourceNode; + + }); + /* -*- Mode: js; js-indent-level: 2; -*- */ +/////////////////////////////////////////////////////////////////////////////// + + this.sourceMap = { + SourceMapConsumer: require('source-map/source-map-consumer').SourceMapConsumer, + SourceMapGenerator: require('source-map/source-map-generator').SourceMapGenerator, + SourceNode: require('source-map/source-node').SourceNode + }; + +// footer to wrap "source-map" module + return this.sourceMap; + }(); +})(); + + +/* Less.js v1.7.5 RHINO | Copyright (c) 2009-2014, Alexis Sellier */ + +/*global name:true, less, loadStyleSheet, os */ + +function formatError(ctx, options) { + options = options || {}; + + var message = ""; + var extract = ctx.extract; + var error = []; + +// var stylize = options.color ? require('./lessc_helper').stylize : function (str) { return str; }; + var stylize = function (str) { + return str; + }; + + // only output a stack if it isn't a less error + if (ctx.stack && !ctx.type) { + return stylize(ctx.stack, 'red'); + } + + if (!ctx.hasOwnProperty('index') || !extract) { + return ctx.stack || ctx.message; + } + + if (typeof(extract[0]) === 'string') { + error.push(stylize((ctx.line - 1) + ' ' + extract[0], 'grey')); + } + + if (typeof(extract[1]) === 'string') { + var errorTxt = ctx.line + ' '; + if (extract[1]) { + errorTxt += extract[1].slice(0, ctx.column) + + stylize(stylize(stylize(extract[1][ctx.column], 'bold') + + extract[1].slice(ctx.column + 1), 'red'), 'inverse'); + } + error.push(errorTxt); + } + + if (typeof(extract[2]) === 'string') { + error.push(stylize((ctx.line + 1) + ' ' + extract[2], 'grey')); + } + error = error.join('\n') + stylize('', 'reset') + '\n'; + + message += stylize(ctx.type + 'Error: ' + ctx.message, 'red'); + if (ctx.filename) { + message += stylize(' in ', 'red') + ctx.filename + + stylize(' on line ' + ctx.line + ', column ' + (ctx.column + 1) + ':', 'grey'); + } + + message += '\n' + error; + + if (ctx.callLine) { + message += stylize('from ', 'red') + (ctx.filename || '') + '/n'; + message += stylize(ctx.callLine, 'grey') + ' ' + ctx.callExtract + '/n'; + } + + return message; +} + +function writeError(ctx, options) { + options = options || {}; + if (options.silent) { + return; + } + var message = formatError(ctx, options); + throw new Error(message); +} + +function loadStyleSheet(sheet, callback, reload, remaining) { + var endOfPath = Math.max(name.lastIndexOf('/'), name.lastIndexOf('\\')), + sheetName = name.slice(0, endOfPath + 1) + sheet.href, + contents = sheet.contents || {}, + input = readFile(sheetName); + + input = input.replace(/^\xEF\xBB\xBF/, ''); + + contents[sheetName] = input; + + var parser = new less.Parser({ + paths: [sheet.href.replace(/[\w\.-]+$/, '')], + contents: contents + }); + parser.parse(input, function (e, root) { + if (e) { + return writeError(e); + } + //try { + callback(e, root, input, sheet, {local: false, lastModified: 0, remaining: remaining}, sheetName); + //} catch (e) { + //writeError(e); + //log.error(e); + //} + }); +} + +less.Parser.fileLoader = function (file, currentFileInfo, callback, env) { + + var href = file; + if (currentFileInfo && currentFileInfo.currentDirectory && !/^\//.test(file)) { + href = less.modules.path.join(currentFileInfo.currentDirectory, file); + } + + var path = less.modules.path.dirname(href); + + var newFileInfo = { + currentDirectory: path + '/', + filename: href + }; + + if (currentFileInfo) { + newFileInfo.entryPath = currentFileInfo.entryPath; + newFileInfo.rootpath = currentFileInfo.rootpath; + newFileInfo.rootFilename = currentFileInfo.rootFilename; + newFileInfo.relativeUrls = currentFileInfo.relativeUrls; + } else { + newFileInfo.entryPath = path; + newFileInfo.rootpath = less.rootpath || path; + newFileInfo.rootFilename = href; + newFileInfo.relativeUrls = env.relativeUrls; + } + + var j = file.lastIndexOf('/'); + if (newFileInfo.relativeUrls && !/^(?:[a-z-]+:|\/)/.test(file) && j != -1) { + var relativeSubDirectory = file.slice(0, j + 1); + newFileInfo.rootpath = newFileInfo.rootpath + relativeSubDirectory; // append (sub|sup) directory path of imported file + } + newFileInfo.currentDirectory = path; + newFileInfo.filename = href; + + var data = null; + try { + data = readFile(href); + } catch (e) { + log.error(e); + callback({type: 'File', message: "'" + less.modules.path.basename(href) + "' wasn't found"}); + return; + } + + try { + callback(null, data, href, newFileInfo, {lastModified: 0}); + } catch (e) { + callback(e, null, href); + } +}; + + +function writeFile(filename, content) { + var f = new File(filename); + f.open('w'); + f.write(content); + f.close(); +} + +// Command line integration via Rhino +var compile = function (args) { + + var options = { + depends: false, + compress: false, + cleancss: false, + max_line_len: -1, + optimization: 1, + silent: false, + verbose: false, + lint: false, + paths: [], + color: true, + strictImports: false, + rootpath: '', + relativeUrls: false, + ieCompat: true, + strictMath: false, + strictUnits: false + }; + var continueProcessing = true, + currentErrorcode; + + var checkArgFunc = function (arg, option) { + if (!option) { + print(arg + " option requires a parameter"); + continueProcessing = false; + return false; + } + return true; + }; + + var checkBooleanArg = function (arg) { + var onOff = /^((on|t|true|y|yes)|(off|f|false|n|no))$/i.exec(arg); + if (!onOff) { + print(" unable to parse " + arg + " as a boolean. use one of on/t/true/y/yes/off/f/false/n/no"); + continueProcessing = false; + return false; + } + return Boolean(onOff[2]); + }; + + var warningMessages = ""; + var sourceMapFileInline = false; + + args = args.filter(function (arg) { + var match = arg.match(/^-I(.+)$/); + + if (match) { + options.paths.push(match[1]); + return false; + } + + match = arg.match(/^--?([a-z][0-9a-z-]*)(?:=(.*))?$/i); + if (match) { + arg = match[1]; + } // was (?:=([^\s]*)), check! + else { + return arg; + } + + switch (arg) { + case 'v': + case 'version': + console.log("lessc " + less.version.join('.') + " (Less Compiler) [JavaScript]"); + continueProcessing = false; + break; + case 'verbose': + options.verbose = true; + break; + case 's': + case 'silent': + options.silent = true; + break; + case 'l': + case 'lint': + options.lint = true; + break; + case 'strict-imports': + options.strictImports = true; + break; + case 'h': + case 'help': + //TODO +// require('../lib/less/lessc_helper').printUsage(); + continueProcessing = false; + break; + case 'x': + case 'compress': + options.compress = true; + break; + case 'M': + case 'depends': + options.depends = true; + break; + case 'yui-compress': + warningMessages += "yui-compress option has been removed. assuming clean-css."; + options.cleancss = true; + break; + case 'clean-css': + options.cleancss = true; + break; + case 'max-line-len': + if (checkArgFunc(arg, match[2])) { + options.maxLineLen = parseInt(match[2], 10); + if (options.maxLineLen <= 0) { + options.maxLineLen = -1; + } + } + break; + case 'no-color': + options.color = false; + break; + case 'no-ie-compat': + options.ieCompat = false; + break; + case 'no-js': + options.javascriptEnabled = false; + break; + case 'include-path': + if (checkArgFunc(arg, match[2])) { + options.paths = match[2].split(os.type().match(/Windows/) ? ';' : ':') + .map(function (p) { + if (p) { +// return path.resolve(process.cwd(), p); + return p; + } + }); + } + break; + case 'O0': + options.optimization = 0; + break; + case 'O1': + options.optimization = 1; + break; + case 'O2': + options.optimization = 2; + break; + case 'line-numbers': + if (checkArgFunc(arg, match[2])) { + options.dumpLineNumbers = match[2]; + } + break; + case 'source-map': + if (!match[2]) { + options.sourceMap = true; + } else { + options.sourceMap = match[2]; + } + break; + case 'source-map-rootpath': + if (checkArgFunc(arg, match[2])) { + options.sourceMapRootpath = match[2]; + } + break; + case 'source-map-basepath': + if (checkArgFunc(arg, match[2])) { + options.sourceMapBasepath = match[2]; + } + break; + case 'source-map-map-inline': + sourceMapFileInline = true; + options.sourceMap = true; + break; + case 'source-map-less-inline': + options.outputSourceFiles = true; + break; + case 'source-map-url': + if (checkArgFunc(arg, match[2])) { + options.sourceMapURL = match[2]; + } + break; + case 'source-map-output-map-file': + if (checkArgFunc(arg, match[2])) { + options.writeSourceMap = function (sourceMapContent) { + writeFile(match[2], sourceMapContent); + }; + } + break; + case 'rp': + case 'rootpath': + if (checkArgFunc(arg, match[2])) { + options.rootpath = match[2].replace(/\\/g, '/'); + } + break; + case "ru": + case "relative-urls": + options.relativeUrls = true; + break; + case "sm": + case "strict-math": + if (checkArgFunc(arg, match[2])) { + options.strictMath = checkBooleanArg(match[2]); + } + break; + case "su": + case "strict-units": + if (checkArgFunc(arg, match[2])) { + options.strictUnits = checkBooleanArg(match[2]); + } + break; + default: + console.log('invalid option ' + arg); + continueProcessing = false; + } + }); + + if (!continueProcessing) { + return; + } + + var name = args[0]; + if (name && name != '-') { +// name = path.resolve(process.cwd(), name); + } + var output = args[1]; + var outputbase = args[1]; + if (output) { + options.sourceMapOutputFilename = output; +// output = path.resolve(process.cwd(), output); + if (warningMessages) { + console.log(warningMessages); + } + } + +// options.sourceMapBasepath = process.cwd(); +// options.sourceMapBasepath = ''; + + if (options.sourceMap === true) { + console.log("output: " + output); + if (!output && !sourceMapFileInline) { + console.log("the sourcemap option only has an optional filename if the css filename is given"); + return; + } + options.sourceMapFullFilename = options.sourceMapOutputFilename + ".map"; + options.sourceMap = less.modules.path.basename(options.sourceMapFullFilename); + } else if (options.sourceMap) { + options.sourceMapOutputFilename = options.sourceMap; + } + + + if (!name) { + console.log("lessc: no inout files"); + console.log(""); + // TODO +// require('../lib/less/lessc_helper').printUsage(); + currentErrorcode = 1; + return; + } + +// var ensureDirectory = function (filepath) { +// var dir = path.dirname(filepath), +// cmd, +// existsSync = fs.existsSync || path.existsSync; +// if (!existsSync(dir)) { +// if (mkdirp === undefined) { +// try {mkdirp = require('mkdirp');} +// catch(e) { mkdirp = null; } +// } +// cmd = mkdirp && mkdirp.sync || fs.mkdirSync; +// cmd(dir); +// } +// }; + + if (options.depends) { + if (!outputbase) { + console.log("option --depends requires an output path to be specified"); + return; + } + console.log(outputbase + ": "); + } + + if (!name) { + console.log('No files present in the fileset'); + quit(1); + } + + var input = null; + try { + input = readFile(name, 'utf-8'); + } catch (e) { + log.error(e); + quit(1); + } + + options.filename = name; + var result; + var parser = new less.Parser(options); + parser.parse(input, function (e, root) { + if (e) { + log.info(e); + writeError(e, options); + quit(1); + } else { + result = root.toCSS(options); + if (output) { + writeFile(output, result); + console.log("Written to " + output); + } else { + print(result); + } + quit(0); + } + }, { + globalVars: {'self-class': fuseState.currentUnit + '-unit'} + }); +}; diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/lib/login.jag b/modules/distribution/src/repository/jaggeryapps/sensebot/lib/login.jag new file mode 100755 index 00000000..7b93c3c7 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/lib/login.jag @@ -0,0 +1,36 @@ +<% +/* + * 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. + */ +(function(){ + var constants = require('/modules/constants.js'); + if (!session.get(constants.USER_SESSION_KEY)) { + var dataConfig = require('/config/dc-props.js').config(); + var sso = require('/modules/sso.js').sso; + var keyStoreParams = { + keyStoreName : dataConfig.ssoConfiguration.keyStoreName, + keyStorePassword : dataConfig.ssoConfiguration.keyStorePassword, + identityAlias : dataConfig.ssoConfiguration.identityAlias + } + sso.configure(dataConfig.ssoConfiguration.issuer, dataConfig.ssoConfiguration.appName, keyStoreParams, + dataConfig.ssoConfiguration.identityProviderURL); + sso.login(); + }else{ + response.sendRedirect(dataConfig.appContext); + } +}()); +%> diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/lib/logout.jag b/modules/distribution/src/repository/jaggeryapps/sensebot/lib/logout.jag new file mode 100755 index 00000000..4ae365d9 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/lib/logout.jag @@ -0,0 +1,37 @@ +<% +/* + * 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 = require('/modules/constants.js'); +var user = session.get(constants.USER_SESSION_KEY); +var dataConfig = require('/config/dc-props.js').config(); +var log = new Log(); +if (user === null) { + log.debug("Cannot perform logout. No user session found."); + response.sendRedirect(dataConfig.appContext+'dashboard'); +} else { + var sso = require('/modules/sso.js').sso; + var keyStoreParams = { + keyStoreName: dataConfig.ssoConfiguration.keyStoreName, + keyStorePassword: dataConfig.ssoConfiguration.keyStorePassword, + identityAlias: dataConfig.ssoConfiguration.identityAlias + } + sso.configure(dataConfig.ssoConfiguration.issuer, dataConfig.ssoConfiguration.appName, keyStoreParams, + dataConfig.ssoConfiguration.identityProviderURL); + sso.logout(user); +} +%> \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/modules/constants.js b/modules/distribution/src/repository/jaggeryapps/sensebot/modules/constants.js new file mode 100755 index 00000000..182d319e --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/modules/constants.js @@ -0,0 +1,26 @@ +/* + * 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 WEB_APP_TITLE = "WSO2 DC - Device Cloud"; +var WEB_APP_CONTEXT = "/iot"; +var USER_SESSION_KEY = "USER"; +var UNSPECIFIED = "Unspecified"; + +var ERRORS = { + "USER_NOT_FOUND": "USER_NOT_FOUND" + }; diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/modules/download.js b/modules/distribution/src/repository/jaggeryapps/sensebot/modules/download.js new file mode 100755 index 00000000..5394c8bf --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/modules/download.js @@ -0,0 +1,68 @@ +/* + * 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 downloadModule; +var Handlebars = require('../lib/handlebars-v2.0.0.js').Handlebars; +downloadModule = function () { + var log = new Log("modules/download.js"); + + var constants = require("/modules/constants.js"); + + var publicMethods = {}; + var privateMethods = {}; + + /** + * Downloading a specified sketch file. + * + * @param file File name or file object of the downloading file + * @param replaceParams + */ + publicMethods.downloadSketch = function (file, response, replaceParams) { + var file = new File("../sketch/" + file); + + file.open('r'); + log.debug("Reading file '" + file.getPath() + "'"); + var content = file.readAll().trim(); + file.close(); + + var downloadFile = privateMethods.allReplace(content,replaceParams); + + response.contentType = "application/octet-stream"; + response.addHeader("Content-Disposition", "attachment; filename='sketch.hbs'"); + response.addHeader("Content-Length", String(downloadFile.length)); + response.content = downloadFile; + }; + + /** + * Find and replace all occurrences. + * @param inStr input string + * @param replaceParams key value array + * @returns retStr replaced string + */ + privateMethods.allReplace = function (inStr, replaceParams) { + var retStr = inStr; + for (var x in replaceParams) { + retStr = retStr.replace(new RegExp(x, 'g'), replaceParams[x]) + } + return retStr; + }; + + return publicMethods; +}(); + + diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/modules/pinch.min.js b/modules/distribution/src/repository/jaggeryapps/sensebot/modules/pinch.min.js new file mode 100755 index 00000000..feccd2da --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/modules/pinch.min.js @@ -0,0 +1,27 @@ +/* +* Copyright (c) 2011 František Hába +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of +* this software and associated documentation files (the 'Software'), to deal in +* the Software without restriction, including without limitation the rights to use, +* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +* Software, and to permit persons to whom the Software is furnished to do so, +* subject to the following conditions: +* The above copyright notice and this permission notice shall be included in all +* copies or substantial portions of the Software. + +* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Reference:- https://github.com/Baggz/Pinch +* Pinch is a small JavaScript utility which is able to replace any data in a JavaScript object (or JSON). +* */ +(function(){var k=function(a,c){return a.length!==c.length?!1:a.every(function(a,b){return c[b]===a})},j=function(a,c,d){var b,e;if("[object Array]"===Object.prototype.toString.call(a)){b=0;for(e=a.length;b

You are now being redirected to SSO Provider. If the redirection fails, please click on the "+ + "button below.

" + + ""); + }; + + sso.logout = function (user) { + var sso_sessions = getSSOSessions(); + sso.sessionId = session.getId(); + sso.sessionIndex = sso_sessions[sso.sessionId]; + + var referer = request.getHeader("referer"); + sso.relayState = (referer ? referer : sso.relayState); + sso.relayState = sso.relayState + request.getQueryString(); // append query string + sso.encodedSAMLLogoutRequest = ssoMod.client.getEncodedSAMLLogoutRequest(user, sso.sessionIndex, sso.issuer); + var postUrl = sso.address + sso.ssoService; + + if (log.isDebugEnabled()) { + sso.log.debug("Logout request recieved from session id ::: " + sso.sessionId); + } + print("

You are now redirected to Stratos Identity. If theredirection fails, please click the post " + + "button.

"); + }; + + sso.acs = function (loginCallback, logoutCallback) { + var sso_sessions = getSSOSessions(); + sso.sessionId = session.getId(); + var samlResponse = request.getParameter('SAMLResponse'); + var samlRequest = request.getParameter('SAMLRequest'); + var relayState = request.getParameter('RelayState'); + var samlRespObj; + + if (samlResponse != null) { + samlRespObj = ssoMod.client.getSamlObject(samlResponse); + if (ssoMod.client.isLogoutResponse(samlRespObj)) { + logoutCallback(); + if (log.isDebugEnabled()) { + sso.log.debug('Session Id Invalidated :::' + sso.sessionId); + } + // Invalidating the session after the callback + session.invalidate(); + } else { + if (log.isDebugEnabled()) { + sso.log.debug("Login request"); + } + // validating the signature + if (sso.responseSign) { + if (ssoMod.client.validateSignature(samlRespObj, sso.keyStoreProps)) { + var sessionObj = ssoMod.client.decodeSAMLLoginResponse(samlRespObj, samlResponse, + sso.sessionId); + if (log.isDebugEnabled()) { + sso.log.debug("Saml object session ID :::" + sessionObj.sessionId); + } + if (sessionObj.sessionIndex != null || sessionObj.sessionIndex != 'undefined') { + sso_sessions[sso_sessions[sessionObj.sessionIndex] = sessionObj.sessionId] = + sessionObj.sessionIndex; + if (log.isDebugEnabled()) { + sso.log.debug("Login successful"); + sso.log.debug('User is set :::' + sessionObj.loggedInUser); + } + loginCallback(sessionObj.loggedInUser); + } else { + sso.log.error("Session index invalid"); + } + } else { + sso.log.error("Response Signing failed"); + } + } else { + if (log.isDebugEnabled()) { + sso.log.debug("Response Signing is disabled"); + } + } + } + } + /* + Executed for single logout requests + */ + if (samlRequest != null) { + var index = ssoMod.client.decodeSAMLLogoutRequest(ssoMod.client.getSamlObject(samlRequest)); + var jSessionId = getSSOSessions()[index]; + delete getSSOSessions()[index]; + if (log.isDebugEnabled()) { + sso.log.debug('Backend logout received from store. The index is :::' + index); + sso.log.debug('Session Id Invalidated :::' + jSessionId); + } + session.invalidate(); + } + } +})(); \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/modules/user.js b/modules/distribution/src/repository/jaggeryapps/sensebot/modules/user.js new file mode 100755 index 00000000..2dfff33e --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/modules/user.js @@ -0,0 +1,299 @@ +/* + * 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 userModule; +userModule = function () { + var log = new Log("modules/user.js"); + + var constants = require("/modules/constants.js"); + var utility = require("/modules/utility.js").utility; + + //var userManagementService = utility.getUserManagementService(); + + var publicMethods = {}; + var privateMethods = {}; + + /** + * Authenticate a user when he or she attempts to login to DC. + * + * @param username Username of the user + * @param password Password of the user + * @param successCallback Function to be called at the event of successful authentication + * @param failureCallback Function to be called at the event of failed authentication + */ + publicMethods.login = function (username, password, successCallback, failureCallback) { + var carbonModule = require("carbon"); + var carbonServer = application.get("carbonServer"); + try { + // get tenant specific full user name. + username = username + "@" + carbonModule.server.tenantDomain(); + // check if the user is an authenticated user. + var isAuthenticated = carbonServer.authenticate(username, password); + if (isAuthenticated) { + var tenantUser = carbonModule.server.tenantUser(username); + session.put(constants.USER_SESSION_KEY, tenantUser); + successCallback(tenantUser); + } else { + failureCallback(); + } + } catch (e) { + throw e; + } + }; + + /** + * Register user to dc-user-store. + * + * @param username Username of the user + * @param firstname First name of the user + * @param lastname Last name of the user + * @param emailAddress Email address of the user + * @param password Password of the user + * @param userRoles Roles assigned to the user + * + * @returns {number} HTTP Status code 201 if succeeded, 409 if user already exists + */ + publicMethods.registerUser = function (username, firstname, lastname, emailAddress, password, userRoles) { + var carbon = require('carbon'); + var tenantId = carbon.server.tenantId(); + var url = carbon.server.address('https') + "/admin/services"; + var server = new carbon.server.Server(url); + var userManager = new carbon.user.UserManager(server, tenantId); + + try { + if (userManager.userExists(username)) { + if (log.isDebugEnabled()) { + log.debug("A user with name '" + username + "' already exists."); + } + // http status code 409 refers to - conflict. + return 409; + } else { + var defaultUserClaims = privateMethods.buildDefaultUserClaims(firstname, lastname, emailAddress); + + userManager.addUser(username, password, userRoles, defaultUserClaims, "default"); + if (log.isDebugEnabled()) { + log.debug("A new user with name '" + username + "' was created."); + } + // http status code 201 refers to - created. + return 201; + } + } catch (e) { + throw e; + } + }; + + /** + * Add user to dc-user-store. + * + * @param username Username of the user + * @param firstname First name of the user + * @param lastname Last name of the user + * @param emailAddress Email address of the user + * @param userRoles Roles assigned to the user + * + * @returns {number} HTTP Status code 201 if succeeded, 409 if user already exists + */ + publicMethods.addUser = function (username, firstname, lastname, emailAddress, userRoles) { + var carbon = require('carbon'); + var tenantId = carbon.server.tenantId(); + var url = carbon.server.address('https') + "/admin/services"; + var server = new carbon.server.Server(url); + var userManager = new carbon.user.UserManager(server, tenantId); + + try { + if (userManager.userExists(username)) { + if (log.isDebugEnabled()) { + log.debug("A user with name '" + username + "' already exists."); + } + // http status code 409 refers to - conflict. + return 409; + } else { + var initialUserPassword = privateMethods.generateInitialUserPassword(); + var defaultUserClaims = privateMethods.buildDefaultUserClaims(firstname, lastname, emailAddress); + + userManager.addUser(username, initialUserPassword, userRoles, defaultUserClaims, "default"); + privateMethods.inviteUserToEnroll(username, initialUserPassword); + if (log.isDebugEnabled()) { + log.debug("A new user with name '" + username + "' was created."); + } + // http status code 201 refers to - created. + return 201; + } + } catch (e) { + throw e; + } + }; + + /** + * Remove an existing user from mdm-user-store. + * + * @param username Username of the user + * @returns {number} HTTP Status code 200 if succeeded, 409 if the user does not exist + */ + publicMethods.removeUser = function (username) { + var carbon = require('carbon'); + var tenantId = carbon.server.tenantId(); + var url = carbon.server.address('https') + "/admin/services"; + var server = new carbon.server.Server(url); + var userManager = new carbon.user.UserManager(server, tenantId); + + try { + if (userManager.userExists(username)) { + userManager.removeUser(username); + if (log.isDebugEnabled()) { + log.debug("An existing user with name '" + username + "' was removed."); + } + // http status code 200 refers to - success. + return 200; + } else { + if (log.isDebugEnabled()) { + log.debug("A user with name '" + username + "' does not exist to remove."); + } + // http status code 409 refers to - conflict. + return 409; + } + } catch (e) { + throw e; + } + }; + + /** + * Private method to be used by addUser() to + * generate an initial user password for a user. + * This will be the password used by a user for his initial login to the system. + * + * @returns {string} Initial User Password + */ + privateMethods.generateInitialUserPassword = function () { + var passwordLength = 6; + //defining the pool of characters to be used for initial password generation + var lowerCaseCharset = "abcdefghijklmnopqrstuvwxyz"; + var upperCaseCharset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + var numericCharset = "0123456789"; + + var totalCharset = lowerCaseCharset + upperCaseCharset + numericCharset; + var totalCharsetLength = totalCharset.length; + + var initialUserPassword = ""; + for (var i = 0; i < passwordLength; ++i) { + initialUserPassword += totalCharset.charAt(Math.floor(Math.random() * totalCharsetLength)); + } + if (log.isDebugEnabled()) { + log.debug("Initial password created for new user : " + initialUserPassword); + } + return String(initialUserPassword); + }; + + /** + * Build default user claims. + * + * @param firstname First name of the user + * @param lastname Last name of the user + * @param emailAddress Email address of the user + * + * @returns {Object} Default user claims to be provided + */ + privateMethods.buildDefaultUserClaims = function (firstname, lastname, emailAddress) { + var defaultUserClaims = { + "http://wso2.org/claims/givenname": firstname, + "http://wso2.org/claims/lastname": lastname, + "http://wso2.org/claims/emailaddress": emailAddress + }; + if (log.isDebugEnabled()) { + log.debug("ClaimMap created for new user : " + stringify(defaultUserClaims)); + } + return defaultUserClaims; + }; + + publicMethods.addPermissions = function (permissionList, path, init) { + var carbonModule = require("carbon"); + var carbonServer = application.get("carbonServer"); + var options = {system: true}; + if (init == "login") { + var carbonUser = session.get(constants.USER_SESSION_KEY); + if (carbonUser) { + options.tenantId = carbonUser.tenantId; + } + } + var registry = new carbonModule.registry.Registry(carbonServer, options); + var i, permission, resource; + for (i = 0; i < permissionList.length; i++) { + permission = permissionList[i]; + resource = { + collection : true, + name : permission.name, + properties : { + name : permission.name + } + }; + registry.put("/_system/governance/permission/" + path + "/" + permission.key, resource); + } + }; + + //publicMethods.getUsers = function () { + // var carbon = require('carbon'); + // + // var carbonUser = session.get(constants.USER_SESSION_KEY); + // if (!carbonUser) { + // log.error("User object was not found in the session"); + // throw constants.ERRORS.USER_NOT_FOUND; + // } + // + // var userList; + // try{ + // userList = userManagementService.getUsersForTenant(carbonUser.tenantId); + // }catch(e){ + // log.error("Error occurred while reading all users"); + // return []; + // } + // + // var users = []; + // var i, userObject; + // for (i = 0; i < userList.size(); i++) { + // userObject = userList.get(i); + // users.push({ + // "username" : userObject.getUserName(), + // "email" : userObject.getEmail(), + // "name" : userObject.getFirstName() + " " + userObject.getLastName() + // }); + // } + // return users; + //}; + + publicMethods.isAuthorized = function (permission) { + var carbonModule = require("carbon"); + var carbonServer = application.get("carbonServer"); + var carbonUser = session.get(constants.USER_SESSION_KEY); + if (!carbonUser) { + log.error("User object was not found in the session"); + throw constants.ERRORS.USER_NOT_FOUND; + } + var userManager = new carbonModule.user.UserManager(carbonServer, carbonUser.tenantId); + var user = new carbonModule.user.User(userManager, carbonUser.username); + return user.isAuthorized(permission, "ui.execute"); + }; + + publicMethods.logout = function (successCallback) { + session.invalidate(); + successCallback(); + }; + + return publicMethods; +}(); + + diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/modules/utility.js b/modules/distribution/src/repository/jaggeryapps/sensebot/modules/utility.js new file mode 100755 index 00000000..6286701b --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/modules/utility.js @@ -0,0 +1,59 @@ +/* + * 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 utility; +utility = function () { + //var JavaClass = Packages.java.lang.Class; + //var PrivilegedCarbonContext = Packages.org.wso2.carbon.context.PrivilegedCarbonContext; + + //var getOsgiService = function (className) { + // var log = new Log(); + // log.info("###### Current Class : "+className); + // return PrivilegedCarbonContext.getThreadLocalCarbonContext().getOSGiService(JavaClass.forName(className)); + //}; + + var publicMethods = {}; + + //publicMethods.getUserManagementService = function () { + // return getOsgiService('org.wso2.carbon.device.mgt.user.core.service.UserManagementService'); + //}; + + publicMethods.insertAppPermissions = function (userModule, type) { + userModule.addPermissions([{key: "device-mgt", name: "Device Management"}], "", type); + userModule.addPermissions([{key: "admin", name: "Device Management Admin"}], "device-mgt", type); + userModule.addPermissions([{key: "user", name: "Device Management User"}], "device-mgt", type); + + userModule.addPermissions([{key: "devices", name: "Devices"}], "device-mgt/admin", type); + userModule.addPermissions([{key: "devices/list", name: "List Devices"}], "device-mgt/admin", type); + userModule.addPermissions([{key: "devices/operation", name: "Perform Operation"}], "device-mgt/admin", type); + + userModule.addPermissions([{key: "users", name: "Users"}], "device-mgt/admin", type); + userModule.addPermissions([{key: "users/add", name: "Add New Users"}], "device-mgt/admin", type); + userModule.addPermissions([{key: "users/invite", name: "Invite Users"}], "device-mgt/admin", type); + userModule.addPermissions([{key: "users/list", name: "List Users"}], "device-mgt/admin", type); + userModule.addPermissions([{key: "users/remove", name: "Remove Users"}], "device-mgt/admin", type); + + userModule.addPermissions([{key: "devices", name: "Devices"}], "device-mgt/user", type); + userModule.addPermissions([{key: "devices/list", name: "List Devices"}], "device-mgt/user", type); + userModule.addPermissions([{key: "devices/operation", name: "Perform Operation"}], "device-mgt/user", "init"); + }; + + return publicMethods; +}(); + + diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/pages/index.hbs b/modules/distribution/src/repository/jaggeryapps/sensebot/pages/index.hbs new file mode 100755 index 00000000..c9b64db9 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/pages/index.hbs @@ -0,0 +1,8 @@ +{{layout "fluid"}} +{{#zone "title"}} + WSO2 DC | Device Cloud +{{/zone}} +{{#zone "body"}} + {{unit "appbar"}} + {{unit "mydevice"}} +{{/zone}} \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/pages/mydevice.hbs b/modules/distribution/src/repository/jaggeryapps/sensebot/pages/mydevice.hbs new file mode 100755 index 00000000..3f8b077d --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/pages/mydevice.hbs @@ -0,0 +1,9 @@ +{{authorized}} +{{layout "fluid"}} +{{#zone "title"}} + WSO2 DC | FireAlarm +{{/zone}} +{{#zone "body"}} + {{unit "appbar"}} + {{unit "mydevice"}} +{{/zone}} \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/test/testExecutor.jag b/modules/distribution/src/repository/jaggeryapps/sensebot/test/testExecutor.jag new file mode 100755 index 00000000..8701e7ba --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/test/testExecutor.jag @@ -0,0 +1,20 @@ +<% +/* + * 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. + */ +require("jaggery-test").test.run(); +%> \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/tmp/cached_theme_less_base.css b/modules/distribution/src/repository/jaggeryapps/sensebot/tmp/cached_theme_less_base.css new file mode 100755 index 00000000..6edb4b23 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/tmp/cached_theme_less_base.css @@ -0,0 +1,6293 @@ +/*! normalize.css v3.0.2 | MIT License | git.io/normalize */ +html { + font-family: sans-serif; + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; +} +body { + margin: 0; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} +audio, +canvas, +progress, +video { + display: inline-block; + vertical-align: baseline; +} +audio:not([controls]) { + display: none; + height: 0; +} +[hidden], +template { + display: none; +} +a { + background-color: transparent; +} +a:active, +a:hover { + outline: 0; +} +abbr[title] { + border-bottom: 1px dotted; +} +b, +strong { + font-weight: bold; +} +dfn { + font-style: italic; +} +h1 { + font-size: 2em; + margin: 0.67em 0; +} +mark { + background: #ff0; + color: #000; +} +small { + font-size: 80%; +} +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} +sup { + top: -0.5em; +} +sub { + bottom: -0.25em; +} +img { + border: 0; +} +svg:not(:root) { + overflow: hidden; +} +figure { + margin: 1em 40px; +} +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} +pre { + overflow: auto; +} +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} +button, +input, +optgroup, +select, +textarea { + color: inherit; + font: inherit; + margin: 0; +} +button { + overflow: visible; +} +button, +select { + text-transform: none; +} +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; +} +button[disabled], +html input[disabled] { + cursor: default; +} +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} +input { + line-height: normal; +} +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; + padding: 0; +} +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} +input[type="search"] { + -webkit-appearance: textfield; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; +} +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} +legend { + border: 0; + padding: 0; +} +textarea { + overflow: auto; +} +optgroup { + font-weight: bold; +} +table { + border-collapse: collapse; + border-spacing: 0; +} +td, +th { + padding: 0; +} +/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ +@media print { + *, + *:before, + *:after { + background: transparent !important; + color: #000 !important; + box-shadow: none !important; + text-shadow: none !important; + } + a, + a:visited { + text-decoration: underline; + } + a[href]:after { + content: " (" attr(href) ")"; + } + abbr[title]:after { + content: " (" attr(title) ")"; + } + a[href^="#"]:after, + a[href^="javascript:"]:after { + content: ""; + } + pre, + blockquote { + border: 1px solid #999; + page-break-inside: avoid; + } + thead { + display: table-header-group; + } + tr, + img { + page-break-inside: avoid; + } + img { + max-width: 100% !important; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } + select { + background: #fff !important; + } + .navbar { + display: none; + } + .btn > .caret, + .dropup > .btn > .caret { + border-top-color: #000 !important; + } + .label { + border: 1px solid #000; + } + .table { + border-collapse: collapse !important; + } + .table td, + .table th { + background-color: #fff !important; + } + .table-bordered th, + .table-bordered td { + border: 1px solid #ddd !important; + } +} +@font-face { + font-family: 'Glyphicons Halflings'; + src: url('../fonts/glyphicons-halflings-regular.eot'); + src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); +} +.glyphicon { + position: relative; + top: 1px; + display: inline-block; + font-family: 'Glyphicons Halflings'; + font-style: normal; + font-weight: normal; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +.glyphicon-asterisk:before { + content: "\2a"; +} +.glyphicon-plus:before { + content: "\2b"; +} +.glyphicon-euro:before, +.glyphicon-eur:before { + content: "\20ac"; +} +.glyphicon-minus:before { + content: "\2212"; +} +.glyphicon-cloud:before { + content: "\2601"; +} +.glyphicon-envelope:before { + content: "\2709"; +} +.glyphicon-pencil:before { + content: "\270f"; +} +.glyphicon-glass:before { + content: "\e001"; +} +.glyphicon-music:before { + content: "\e002"; +} +.glyphicon-search:before { + content: "\e003"; +} +.glyphicon-heart:before { + content: "\e005"; +} +.glyphicon-star:before { + content: "\e006"; +} +.glyphicon-star-empty:before { + content: "\e007"; +} +.glyphicon-user:before { + content: "\e008"; +} +.glyphicon-film:before { + content: "\e009"; +} +.glyphicon-th-large:before { + content: "\e010"; +} +.glyphicon-th:before { + content: "\e011"; +} +.glyphicon-th-list:before { + content: "\e012"; +} +.glyphicon-ok:before { + content: "\e013"; +} +.glyphicon-remove:before { + content: "\e014"; +} +.glyphicon-zoom-in:before { + content: "\e015"; +} +.glyphicon-zoom-out:before { + content: "\e016"; +} +.glyphicon-off:before { + content: "\e017"; +} +.glyphicon-signal:before { + content: "\e018"; +} +.glyphicon-cog:before { + content: "\e019"; +} +.glyphicon-trash:before { + content: "\e020"; +} +.glyphicon-home:before { + content: "\e021"; +} +.glyphicon-file:before { + content: "\e022"; +} +.glyphicon-time:before { + content: "\e023"; +} +.glyphicon-road:before { + content: "\e024"; +} +.glyphicon-download-alt:before { + content: "\e025"; +} +.glyphicon-download:before { + content: "\e026"; +} +.glyphicon-upload:before { + content: "\e027"; +} +.glyphicon-inbox:before { + content: "\e028"; +} +.glyphicon-play-circle:before { + content: "\e029"; +} +.glyphicon-repeat:before { + content: "\e030"; +} +.glyphicon-refresh:before { + content: "\e031"; +} +.glyphicon-list-alt:before { + content: "\e032"; +} +.glyphicon-lock:before { + content: "\e033"; +} +.glyphicon-flag:before { + content: "\e034"; +} +.glyphicon-headphones:before { + content: "\e035"; +} +.glyphicon-volume-off:before { + content: "\e036"; +} +.glyphicon-volume-down:before { + content: "\e037"; +} +.glyphicon-volume-up:before { + content: "\e038"; +} +.glyphicon-qrcode:before { + content: "\e039"; +} +.glyphicon-barcode:before { + content: "\e040"; +} +.glyphicon-tag:before { + content: "\e041"; +} +.glyphicon-tags:before { + content: "\e042"; +} +.glyphicon-book:before { + content: "\e043"; +} +.glyphicon-bookmark:before { + content: "\e044"; +} +.glyphicon-print:before { + content: "\e045"; +} +.glyphicon-camera:before { + content: "\e046"; +} +.glyphicon-font:before { + content: "\e047"; +} +.glyphicon-bold:before { + content: "\e048"; +} +.glyphicon-italic:before { + content: "\e049"; +} +.glyphicon-text-height:before { + content: "\e050"; +} +.glyphicon-text-width:before { + content: "\e051"; +} +.glyphicon-align-left:before { + content: "\e052"; +} +.glyphicon-align-center:before { + content: "\e053"; +} +.glyphicon-align-right:before { + content: "\e054"; +} +.glyphicon-align-justify:before { + content: "\e055"; +} +.glyphicon-list:before { + content: "\e056"; +} +.glyphicon-indent-left:before { + content: "\e057"; +} +.glyphicon-indent-right:before { + content: "\e058"; +} +.glyphicon-facetime-video:before { + content: "\e059"; +} +.glyphicon-picture:before { + content: "\e060"; +} +.glyphicon-map-marker:before { + content: "\e062"; +} +.glyphicon-adjust:before { + content: "\e063"; +} +.glyphicon-tint:before { + content: "\e064"; +} +.glyphicon-edit:before { + content: "\e065"; +} +.glyphicon-share:before { + content: "\e066"; +} +.glyphicon-check:before { + content: "\e067"; +} +.glyphicon-move:before { + content: "\e068"; +} +.glyphicon-step-backward:before { + content: "\e069"; +} +.glyphicon-fast-backward:before { + content: "\e070"; +} +.glyphicon-backward:before { + content: "\e071"; +} +.glyphicon-play:before { + content: "\e072"; +} +.glyphicon-pause:before { + content: "\e073"; +} +.glyphicon-stop:before { + content: "\e074"; +} +.glyphicon-forward:before { + content: "\e075"; +} +.glyphicon-fast-forward:before { + content: "\e076"; +} +.glyphicon-step-forward:before { + content: "\e077"; +} +.glyphicon-eject:before { + content: "\e078"; +} +.glyphicon-chevron-left:before { + content: "\e079"; +} +.glyphicon-chevron-right:before { + content: "\e080"; +} +.glyphicon-plus-sign:before { + content: "\e081"; +} +.glyphicon-minus-sign:before { + content: "\e082"; +} +.glyphicon-remove-sign:before { + content: "\e083"; +} +.glyphicon-ok-sign:before { + content: "\e084"; +} +.glyphicon-question-sign:before { + content: "\e085"; +} +.glyphicon-info-sign:before { + content: "\e086"; +} +.glyphicon-screenshot:before { + content: "\e087"; +} +.glyphicon-remove-circle:before { + content: "\e088"; +} +.glyphicon-ok-circle:before { + content: "\e089"; +} +.glyphicon-ban-circle:before { + content: "\e090"; +} +.glyphicon-arrow-left:before { + content: "\e091"; +} +.glyphicon-arrow-right:before { + content: "\e092"; +} +.glyphicon-arrow-up:before { + content: "\e093"; +} +.glyphicon-arrow-down:before { + content: "\e094"; +} +.glyphicon-share-alt:before { + content: "\e095"; +} +.glyphicon-resize-full:before { + content: "\e096"; +} +.glyphicon-resize-small:before { + content: "\e097"; +} +.glyphicon-exclamation-sign:before { + content: "\e101"; +} +.glyphicon-gift:before { + content: "\e102"; +} +.glyphicon-leaf:before { + content: "\e103"; +} +.glyphicon-fire:before { + content: "\e104"; +} +.glyphicon-eye-open:before { + content: "\e105"; +} +.glyphicon-eye-close:before { + content: "\e106"; +} +.glyphicon-warning-sign:before { + content: "\e107"; +} +.glyphicon-plane:before { + content: "\e108"; +} +.glyphicon-calendar:before { + content: "\e109"; +} +.glyphicon-random:before { + content: "\e110"; +} +.glyphicon-comment:before { + content: "\e111"; +} +.glyphicon-magnet:before { + content: "\e112"; +} +.glyphicon-chevron-up:before { + content: "\e113"; +} +.glyphicon-chevron-down:before { + content: "\e114"; +} +.glyphicon-retweet:before { + content: "\e115"; +} +.glyphicon-shopping-cart:before { + content: "\e116"; +} +.glyphicon-folder-close:before { + content: "\e117"; +} +.glyphicon-folder-open:before { + content: "\e118"; +} +.glyphicon-resize-vertical:before { + content: "\e119"; +} +.glyphicon-resize-horizontal:before { + content: "\e120"; +} +.glyphicon-hdd:before { + content: "\e121"; +} +.glyphicon-bullhorn:before { + content: "\e122"; +} +.glyphicon-bell:before { + content: "\e123"; +} +.glyphicon-certificate:before { + content: "\e124"; +} +.glyphicon-thumbs-up:before { + content: "\e125"; +} +.glyphicon-thumbs-down:before { + content: "\e126"; +} +.glyphicon-hand-right:before { + content: "\e127"; +} +.glyphicon-hand-left:before { + content: "\e128"; +} +.glyphicon-hand-up:before { + content: "\e129"; +} +.glyphicon-hand-down:before { + content: "\e130"; +} +.glyphicon-circle-arrow-right:before { + content: "\e131"; +} +.glyphicon-circle-arrow-left:before { + content: "\e132"; +} +.glyphicon-circle-arrow-up:before { + content: "\e133"; +} +.glyphicon-circle-arrow-down:before { + content: "\e134"; +} +.glyphicon-globe:before { + content: "\e135"; +} +.glyphicon-wrench:before { + content: "\e136"; +} +.glyphicon-tasks:before { + content: "\e137"; +} +.glyphicon-filter:before { + content: "\e138"; +} +.glyphicon-briefcase:before { + content: "\e139"; +} +.glyphicon-fullscreen:before { + content: "\e140"; +} +.glyphicon-dashboard:before { + content: "\e141"; +} +.glyphicon-paperclip:before { + content: "\e142"; +} +.glyphicon-heart-empty:before { + content: "\e143"; +} +.glyphicon-link:before { + content: "\e144"; +} +.glyphicon-phone:before { + content: "\e145"; +} +.glyphicon-pushpin:before { + content: "\e146"; +} +.glyphicon-usd:before { + content: "\e148"; +} +.glyphicon-gbp:before { + content: "\e149"; +} +.glyphicon-sort:before { + content: "\e150"; +} +.glyphicon-sort-by-alphabet:before { + content: "\e151"; +} +.glyphicon-sort-by-alphabet-alt:before { + content: "\e152"; +} +.glyphicon-sort-by-order:before { + content: "\e153"; +} +.glyphicon-sort-by-order-alt:before { + content: "\e154"; +} +.glyphicon-sort-by-attributes:before { + content: "\e155"; +} +.glyphicon-sort-by-attributes-alt:before { + content: "\e156"; +} +.glyphicon-unchecked:before { + content: "\e157"; +} +.glyphicon-expand:before { + content: "\e158"; +} +.glyphicon-collapse-down:before { + content: "\e159"; +} +.glyphicon-collapse-up:before { + content: "\e160"; +} +.glyphicon-log-in:before { + content: "\e161"; +} +.glyphicon-flash:before { + content: "\e162"; +} +.glyphicon-log-out:before { + content: "\e163"; +} +.glyphicon-new-window:before { + content: "\e164"; +} +.glyphicon-record:before { + content: "\e165"; +} +.glyphicon-save:before { + content: "\e166"; +} +.glyphicon-open:before { + content: "\e167"; +} +.glyphicon-saved:before { + content: "\e168"; +} +.glyphicon-import:before { + content: "\e169"; +} +.glyphicon-export:before { + content: "\e170"; +} +.glyphicon-send:before { + content: "\e171"; +} +.glyphicon-floppy-disk:before { + content: "\e172"; +} +.glyphicon-floppy-saved:before { + content: "\e173"; +} +.glyphicon-floppy-remove:before { + content: "\e174"; +} +.glyphicon-floppy-save:before { + content: "\e175"; +} +.glyphicon-floppy-open:before { + content: "\e176"; +} +.glyphicon-credit-card:before { + content: "\e177"; +} +.glyphicon-transfer:before { + content: "\e178"; +} +.glyphicon-cutlery:before { + content: "\e179"; +} +.glyphicon-header:before { + content: "\e180"; +} +.glyphicon-compressed:before { + content: "\e181"; +} +.glyphicon-earphone:before { + content: "\e182"; +} +.glyphicon-phone-alt:before { + content: "\e183"; +} +.glyphicon-tower:before { + content: "\e184"; +} +.glyphicon-stats:before { + content: "\e185"; +} +.glyphicon-sd-video:before { + content: "\e186"; +} +.glyphicon-hd-video:before { + content: "\e187"; +} +.glyphicon-subtitles:before { + content: "\e188"; +} +.glyphicon-sound-stereo:before { + content: "\e189"; +} +.glyphicon-sound-dolby:before { + content: "\e190"; +} +.glyphicon-sound-5-1:before { + content: "\e191"; +} +.glyphicon-sound-6-1:before { + content: "\e192"; +} +.glyphicon-sound-7-1:before { + content: "\e193"; +} +.glyphicon-copyright-mark:before { + content: "\e194"; +} +.glyphicon-registration-mark:before { + content: "\e195"; +} +.glyphicon-cloud-download:before { + content: "\e197"; +} +.glyphicon-cloud-upload:before { + content: "\e198"; +} +.glyphicon-tree-conifer:before { + content: "\e199"; +} +.glyphicon-tree-deciduous:before { + content: "\e200"; +} +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +*:before, +*:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +html { + font-size: 10px; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.42857143; + color: #333333; + background-color: #ffffff; +} +input, +button, +select, +textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} +a { + color: #337ab7; + text-decoration: none; +} +a:hover, +a:focus { + color: #23527c; + text-decoration: underline; +} +a:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +figure { + margin: 0; +} +img { + vertical-align: middle; +} +.img-responsive, +.thumbnail > img, +.thumbnail a > img, +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + max-width: 100%; + height: auto; +} +.img-rounded { + border-radius: 6px; +} +.img-thumbnail { + padding: 4px; + line-height: 1.42857143; + background-color: #ffffff; + border: 1px solid #dddddd; + border-radius: 4px; + -webkit-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + display: inline-block; + max-width: 100%; + height: auto; +} +.img-circle { + border-radius: 50%; +} +hr { + margin-top: 20px; + margin-bottom: 20px; + border: 0; + border-top: 1px solid #eeeeee; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} +.sr-only-focusable:active, +.sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; +} +h1, +h2, +h3, +h4, +h5, +h6, +.h1, +.h2, +.h3, +.h4, +.h5, +.h6 { + font-family: inherit; + font-weight: 500; + line-height: 1.1; + color: inherit; +} +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small, +.h1 small, +.h2 small, +.h3 small, +.h4 small, +.h5 small, +.h6 small, +h1 .small, +h2 .small, +h3 .small, +h4 .small, +h5 .small, +h6 .small, +.h1 .small, +.h2 .small, +.h3 .small, +.h4 .small, +.h5 .small, +.h6 .small { + font-weight: normal; + line-height: 1; + color: #777777; +} +h1, +.h1, +h2, +.h2, +h3, +.h3 { + margin-top: 20px; + margin-bottom: 10px; +} +h1 small, +.h1 small, +h2 small, +.h2 small, +h3 small, +.h3 small, +h1 .small, +.h1 .small, +h2 .small, +.h2 .small, +h3 .small, +.h3 .small { + font-size: 65%; +} +h4, +.h4, +h5, +.h5, +h6, +.h6 { + margin-top: 10px; + margin-bottom: 10px; +} +h4 small, +.h4 small, +h5 small, +.h5 small, +h6 small, +.h6 small, +h4 .small, +.h4 .small, +h5 .small, +.h5 .small, +h6 .small, +.h6 .small { + font-size: 75%; +} +h1, +.h1 { + font-size: 36px; +} +h2, +.h2 { + font-size: 30px; +} +h3, +.h3 { + font-size: 24px; +} +h4, +.h4 { + font-size: 18px; +} +h5, +.h5 { + font-size: 14px; +} +h6, +.h6 { + font-size: 12px; +} +p { + margin: 0 0 10px; +} +.lead { + margin-bottom: 20px; + font-size: 16px; + font-weight: 300; + line-height: 1.4; +} +@media (min-width: 768px) { + .lead { + font-size: 21px; + } +} +small, +.small { + font-size: 85%; +} +mark, +.mark { + background-color: #fcf8e3; + padding: .2em; +} +.text-left { + text-align: left; +} +.text-right { + text-align: right; +} +.text-center { + text-align: center; +} +.text-justify { + text-align: justify; +} +.text-nowrap { + white-space: nowrap; +} +.text-lowercase { + text-transform: lowercase; +} +.text-uppercase { + text-transform: uppercase; +} +.text-capitalize { + text-transform: capitalize; +} +.text-muted { + color: #777777; +} +.text-primary { + color: #337ab7; +} +a.text-primary:hover { + color: #286090; +} +.text-success { + color: #3c763d; +} +a.text-success:hover { + color: #2b542c; +} +.text-info { + color: #31708f; +} +a.text-info:hover { + color: #245269; +} +.text-warning { + color: #8a6d3b; +} +a.text-warning:hover { + color: #66512c; +} +.text-danger { + color: #a94442; +} +a.text-danger:hover { + color: #843534; +} +.bg-primary { + color: #fff; + background-color: #337ab7; +} +a.bg-primary:hover { + background-color: #286090; +} +.bg-success { + background-color: #dff0d8; +} +a.bg-success:hover { + background-color: #c1e2b3; +} +.bg-info { + background-color: #d9edf7; +} +a.bg-info:hover { + background-color: #afd9ee; +} +.bg-warning { + background-color: #fcf8e3; +} +a.bg-warning:hover { + background-color: #f7ecb5; +} +.bg-danger { + background-color: #f2dede; +} +a.bg-danger:hover { + background-color: #e4b9b9; +} +.page-header { + padding-bottom: 9px; + margin: 40px 0 20px; + border-bottom: 1px solid #eeeeee; +} +ul, +ol { + margin-top: 0; + margin-bottom: 10px; +} +ul ul, +ol ul, +ul ol, +ol ol { + margin-bottom: 0; +} +.list-unstyled { + padding-left: 0; + list-style: none; +} +.list-inline { + padding-left: 0; + list-style: none; + margin-left: -5px; +} +.list-inline > li { + display: inline-block; + padding-left: 5px; + padding-right: 5px; +} +dl { + margin-top: 0; + margin-bottom: 20px; +} +dt, +dd { + line-height: 1.42857143; +} +dt { + font-weight: bold; +} +dd { + margin-left: 0; +} +@media (min-width: 768px) { + .dl-horizontal dt { + float: left; + width: 160px; + clear: left; + text-align: right; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + .dl-horizontal dd { + margin-left: 180px; + } +} +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #777777; +} +.initialism { + font-size: 90%; + text-transform: uppercase; +} +blockquote { + padding: 10px 20px; + margin: 0 0 20px; + font-size: 17.5px; + border-left: 5px solid #eeeeee; +} +blockquote p:last-child, +blockquote ul:last-child, +blockquote ol:last-child { + margin-bottom: 0; +} +blockquote footer, +blockquote small, +blockquote .small { + display: block; + font-size: 80%; + line-height: 1.42857143; + color: #777777; +} +blockquote footer:before, +blockquote small:before, +blockquote .small:before { + content: '\2014 \00A0'; +} +.blockquote-reverse, +blockquote.pull-right { + padding-right: 15px; + padding-left: 0; + border-right: 5px solid #eeeeee; + border-left: 0; + text-align: right; +} +.blockquote-reverse footer:before, +blockquote.pull-right footer:before, +.blockquote-reverse small:before, +blockquote.pull-right small:before, +.blockquote-reverse .small:before, +blockquote.pull-right .small:before { + content: ''; +} +.blockquote-reverse footer:after, +blockquote.pull-right footer:after, +.blockquote-reverse small:after, +blockquote.pull-right small:after, +.blockquote-reverse .small:after, +blockquote.pull-right .small:after { + content: '\00A0 \2014'; +} +address { + margin-bottom: 20px; + font-style: normal; + line-height: 1.42857143; +} +code, +kbd, +pre, +samp { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; +} +code { + padding: 2px 4px; + font-size: 90%; + color: #c7254e; + background-color: #f9f2f4; + border-radius: 4px; +} +kbd { + padding: 2px 4px; + font-size: 90%; + color: #ffffff; + background-color: #333333; + border-radius: 3px; + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25); +} +kbd kbd { + padding: 0; + font-size: 100%; + font-weight: bold; + box-shadow: none; +} +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 1.42857143; + word-break: break-all; + word-wrap: break-word; + color: #333333; + background-color: #f5f5f5; + border: 1px solid #cccccc; + border-radius: 4px; +} +pre code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; +} +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} +.container { + margin-right: auto; + margin-left: auto; + padding-left: 15px; + padding-right: 15px; +} +@media (min-width: 768px) { + .container { + width: 750px; + } +} +@media (min-width: 992px) { + .container { + width: 970px; + } +} +@media (min-width: 1200px) { + .container { + width: 1170px; + } +} +.container-fluid { + margin-right: auto; + margin-left: auto; + padding-left: 15px; + padding-right: 15px; +} +.row { + margin-left: -15px; + margin-right: -15px; +} +.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { + position: relative; + min-height: 1px; + padding-left: 15px; + padding-right: 15px; +} +.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { + float: left; +} +.col-xs-12 { + width: 100%; +} +.col-xs-11 { + width: 91.66666667%; +} +.col-xs-10 { + width: 83.33333333%; +} +.col-xs-9 { + width: 75%; +} +.col-xs-8 { + width: 66.66666667%; +} +.col-xs-7 { + width: 58.33333333%; +} +.col-xs-6 { + width: 50%; +} +.col-xs-5 { + width: 41.66666667%; +} +.col-xs-4 { + width: 33.33333333%; +} +.col-xs-3 { + width: 25%; +} +.col-xs-2 { + width: 16.66666667%; +} +.col-xs-1 { + width: 8.33333333%; +} +.col-xs-pull-12 { + right: 100%; +} +.col-xs-pull-11 { + right: 91.66666667%; +} +.col-xs-pull-10 { + right: 83.33333333%; +} +.col-xs-pull-9 { + right: 75%; +} +.col-xs-pull-8 { + right: 66.66666667%; +} +.col-xs-pull-7 { + right: 58.33333333%; +} +.col-xs-pull-6 { + right: 50%; +} +.col-xs-pull-5 { + right: 41.66666667%; +} +.col-xs-pull-4 { + right: 33.33333333%; +} +.col-xs-pull-3 { + right: 25%; +} +.col-xs-pull-2 { + right: 16.66666667%; +} +.col-xs-pull-1 { + right: 8.33333333%; +} +.col-xs-pull-0 { + right: auto; +} +.col-xs-push-12 { + left: 100%; +} +.col-xs-push-11 { + left: 91.66666667%; +} +.col-xs-push-10 { + left: 83.33333333%; +} +.col-xs-push-9 { + left: 75%; +} +.col-xs-push-8 { + left: 66.66666667%; +} +.col-xs-push-7 { + left: 58.33333333%; +} +.col-xs-push-6 { + left: 50%; +} +.col-xs-push-5 { + left: 41.66666667%; +} +.col-xs-push-4 { + left: 33.33333333%; +} +.col-xs-push-3 { + left: 25%; +} +.col-xs-push-2 { + left: 16.66666667%; +} +.col-xs-push-1 { + left: 8.33333333%; +} +.col-xs-push-0 { + left: auto; +} +.col-xs-offset-12 { + margin-left: 100%; +} +.col-xs-offset-11 { + margin-left: 91.66666667%; +} +.col-xs-offset-10 { + margin-left: 83.33333333%; +} +.col-xs-offset-9 { + margin-left: 75%; +} +.col-xs-offset-8 { + margin-left: 66.66666667%; +} +.col-xs-offset-7 { + margin-left: 58.33333333%; +} +.col-xs-offset-6 { + margin-left: 50%; +} +.col-xs-offset-5 { + margin-left: 41.66666667%; +} +.col-xs-offset-4 { + margin-left: 33.33333333%; +} +.col-xs-offset-3 { + margin-left: 25%; +} +.col-xs-offset-2 { + margin-left: 16.66666667%; +} +.col-xs-offset-1 { + margin-left: 8.33333333%; +} +.col-xs-offset-0 { + margin-left: 0%; +} +@media (min-width: 768px) { + .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { + float: left; + } + .col-sm-12 { + width: 100%; + } + .col-sm-11 { + width: 91.66666667%; + } + .col-sm-10 { + width: 83.33333333%; + } + .col-sm-9 { + width: 75%; + } + .col-sm-8 { + width: 66.66666667%; + } + .col-sm-7 { + width: 58.33333333%; + } + .col-sm-6 { + width: 50%; + } + .col-sm-5 { + width: 41.66666667%; + } + .col-sm-4 { + width: 33.33333333%; + } + .col-sm-3 { + width: 25%; + } + .col-sm-2 { + width: 16.66666667%; + } + .col-sm-1 { + width: 8.33333333%; + } + .col-sm-pull-12 { + right: 100%; + } + .col-sm-pull-11 { + right: 91.66666667%; + } + .col-sm-pull-10 { + right: 83.33333333%; + } + .col-sm-pull-9 { + right: 75%; + } + .col-sm-pull-8 { + right: 66.66666667%; + } + .col-sm-pull-7 { + right: 58.33333333%; + } + .col-sm-pull-6 { + right: 50%; + } + .col-sm-pull-5 { + right: 41.66666667%; + } + .col-sm-pull-4 { + right: 33.33333333%; + } + .col-sm-pull-3 { + right: 25%; + } + .col-sm-pull-2 { + right: 16.66666667%; + } + .col-sm-pull-1 { + right: 8.33333333%; + } + .col-sm-pull-0 { + right: auto; + } + .col-sm-push-12 { + left: 100%; + } + .col-sm-push-11 { + left: 91.66666667%; + } + .col-sm-push-10 { + left: 83.33333333%; + } + .col-sm-push-9 { + left: 75%; + } + .col-sm-push-8 { + left: 66.66666667%; + } + .col-sm-push-7 { + left: 58.33333333%; + } + .col-sm-push-6 { + left: 50%; + } + .col-sm-push-5 { + left: 41.66666667%; + } + .col-sm-push-4 { + left: 33.33333333%; + } + .col-sm-push-3 { + left: 25%; + } + .col-sm-push-2 { + left: 16.66666667%; + } + .col-sm-push-1 { + left: 8.33333333%; + } + .col-sm-push-0 { + left: auto; + } + .col-sm-offset-12 { + margin-left: 100%; + } + .col-sm-offset-11 { + margin-left: 91.66666667%; + } + .col-sm-offset-10 { + margin-left: 83.33333333%; + } + .col-sm-offset-9 { + margin-left: 75%; + } + .col-sm-offset-8 { + margin-left: 66.66666667%; + } + .col-sm-offset-7 { + margin-left: 58.33333333%; + } + .col-sm-offset-6 { + margin-left: 50%; + } + .col-sm-offset-5 { + margin-left: 41.66666667%; + } + .col-sm-offset-4 { + margin-left: 33.33333333%; + } + .col-sm-offset-3 { + margin-left: 25%; + } + .col-sm-offset-2 { + margin-left: 16.66666667%; + } + .col-sm-offset-1 { + margin-left: 8.33333333%; + } + .col-sm-offset-0 { + margin-left: 0%; + } +} +@media (min-width: 992px) { + .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { + float: left; + } + .col-md-12 { + width: 100%; + } + .col-md-11 { + width: 91.66666667%; + } + .col-md-10 { + width: 83.33333333%; + } + .col-md-9 { + width: 75%; + } + .col-md-8 { + width: 66.66666667%; + } + .col-md-7 { + width: 58.33333333%; + } + .col-md-6 { + width: 50%; + } + .col-md-5 { + width: 41.66666667%; + } + .col-md-4 { + width: 33.33333333%; + } + .col-md-3 { + width: 25%; + } + .col-md-2 { + width: 16.66666667%; + } + .col-md-1 { + width: 8.33333333%; + } + .col-md-pull-12 { + right: 100%; + } + .col-md-pull-11 { + right: 91.66666667%; + } + .col-md-pull-10 { + right: 83.33333333%; + } + .col-md-pull-9 { + right: 75%; + } + .col-md-pull-8 { + right: 66.66666667%; + } + .col-md-pull-7 { + right: 58.33333333%; + } + .col-md-pull-6 { + right: 50%; + } + .col-md-pull-5 { + right: 41.66666667%; + } + .col-md-pull-4 { + right: 33.33333333%; + } + .col-md-pull-3 { + right: 25%; + } + .col-md-pull-2 { + right: 16.66666667%; + } + .col-md-pull-1 { + right: 8.33333333%; + } + .col-md-pull-0 { + right: auto; + } + .col-md-push-12 { + left: 100%; + } + .col-md-push-11 { + left: 91.66666667%; + } + .col-md-push-10 { + left: 83.33333333%; + } + .col-md-push-9 { + left: 75%; + } + .col-md-push-8 { + left: 66.66666667%; + } + .col-md-push-7 { + left: 58.33333333%; + } + .col-md-push-6 { + left: 50%; + } + .col-md-push-5 { + left: 41.66666667%; + } + .col-md-push-4 { + left: 33.33333333%; + } + .col-md-push-3 { + left: 25%; + } + .col-md-push-2 { + left: 16.66666667%; + } + .col-md-push-1 { + left: 8.33333333%; + } + .col-md-push-0 { + left: auto; + } + .col-md-offset-12 { + margin-left: 100%; + } + .col-md-offset-11 { + margin-left: 91.66666667%; + } + .col-md-offset-10 { + margin-left: 83.33333333%; + } + .col-md-offset-9 { + margin-left: 75%; + } + .col-md-offset-8 { + margin-left: 66.66666667%; + } + .col-md-offset-7 { + margin-left: 58.33333333%; + } + .col-md-offset-6 { + margin-left: 50%; + } + .col-md-offset-5 { + margin-left: 41.66666667%; + } + .col-md-offset-4 { + margin-left: 33.33333333%; + } + .col-md-offset-3 { + margin-left: 25%; + } + .col-md-offset-2 { + margin-left: 16.66666667%; + } + .col-md-offset-1 { + margin-left: 8.33333333%; + } + .col-md-offset-0 { + margin-left: 0%; + } +} +@media (min-width: 1200px) { + .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { + float: left; + } + .col-lg-12 { + width: 100%; + } + .col-lg-11 { + width: 91.66666667%; + } + .col-lg-10 { + width: 83.33333333%; + } + .col-lg-9 { + width: 75%; + } + .col-lg-8 { + width: 66.66666667%; + } + .col-lg-7 { + width: 58.33333333%; + } + .col-lg-6 { + width: 50%; + } + .col-lg-5 { + width: 41.66666667%; + } + .col-lg-4 { + width: 33.33333333%; + } + .col-lg-3 { + width: 25%; + } + .col-lg-2 { + width: 16.66666667%; + } + .col-lg-1 { + width: 8.33333333%; + } + .col-lg-pull-12 { + right: 100%; + } + .col-lg-pull-11 { + right: 91.66666667%; + } + .col-lg-pull-10 { + right: 83.33333333%; + } + .col-lg-pull-9 { + right: 75%; + } + .col-lg-pull-8 { + right: 66.66666667%; + } + .col-lg-pull-7 { + right: 58.33333333%; + } + .col-lg-pull-6 { + right: 50%; + } + .col-lg-pull-5 { + right: 41.66666667%; + } + .col-lg-pull-4 { + right: 33.33333333%; + } + .col-lg-pull-3 { + right: 25%; + } + .col-lg-pull-2 { + right: 16.66666667%; + } + .col-lg-pull-1 { + right: 8.33333333%; + } + .col-lg-pull-0 { + right: auto; + } + .col-lg-push-12 { + left: 100%; + } + .col-lg-push-11 { + left: 91.66666667%; + } + .col-lg-push-10 { + left: 83.33333333%; + } + .col-lg-push-9 { + left: 75%; + } + .col-lg-push-8 { + left: 66.66666667%; + } + .col-lg-push-7 { + left: 58.33333333%; + } + .col-lg-push-6 { + left: 50%; + } + .col-lg-push-5 { + left: 41.66666667%; + } + .col-lg-push-4 { + left: 33.33333333%; + } + .col-lg-push-3 { + left: 25%; + } + .col-lg-push-2 { + left: 16.66666667%; + } + .col-lg-push-1 { + left: 8.33333333%; + } + .col-lg-push-0 { + left: auto; + } + .col-lg-offset-12 { + margin-left: 100%; + } + .col-lg-offset-11 { + margin-left: 91.66666667%; + } + .col-lg-offset-10 { + margin-left: 83.33333333%; + } + .col-lg-offset-9 { + margin-left: 75%; + } + .col-lg-offset-8 { + margin-left: 66.66666667%; + } + .col-lg-offset-7 { + margin-left: 58.33333333%; + } + .col-lg-offset-6 { + margin-left: 50%; + } + .col-lg-offset-5 { + margin-left: 41.66666667%; + } + .col-lg-offset-4 { + margin-left: 33.33333333%; + } + .col-lg-offset-3 { + margin-left: 25%; + } + .col-lg-offset-2 { + margin-left: 16.66666667%; + } + .col-lg-offset-1 { + margin-left: 8.33333333%; + } + .col-lg-offset-0 { + margin-left: 0%; + } +} +table { + background-color: transparent; +} +caption { + padding-top: 8px; + padding-bottom: 8px; + color: #777777; + text-align: left; +} +th { + text-align: left; +} +.table { + width: 100%; + max-width: 100%; + margin-bottom: 20px; +} +.table > thead > tr > th, +.table > tbody > tr > th, +.table > tfoot > tr > th, +.table > thead > tr > td, +.table > tbody > tr > td, +.table > tfoot > tr > td { + padding: 8px; + line-height: 1.42857143; + vertical-align: top; + border-top: 1px solid #dddddd; +} +.table > thead > tr > th { + vertical-align: bottom; + border-bottom: 2px solid #dddddd; +} +.table > caption + thead > tr:first-child > th, +.table > colgroup + thead > tr:first-child > th, +.table > thead:first-child > tr:first-child > th, +.table > caption + thead > tr:first-child > td, +.table > colgroup + thead > tr:first-child > td, +.table > thead:first-child > tr:first-child > td { + border-top: 0; +} +.table > tbody + tbody { + border-top: 2px solid #dddddd; +} +.table .table { + background-color: #ffffff; +} +.table-condensed > thead > tr > th, +.table-condensed > tbody > tr > th, +.table-condensed > tfoot > tr > th, +.table-condensed > thead > tr > td, +.table-condensed > tbody > tr > td, +.table-condensed > tfoot > tr > td { + padding: 5px; +} +.table-bordered { + border: 1px solid #dddddd; +} +.table-bordered > thead > tr > th, +.table-bordered > tbody > tr > th, +.table-bordered > tfoot > tr > th, +.table-bordered > thead > tr > td, +.table-bordered > tbody > tr > td, +.table-bordered > tfoot > tr > td { + border: 1px solid #dddddd; +} +.table-bordered > thead > tr > th, +.table-bordered > thead > tr > td { + border-bottom-width: 2px; +} +.table-striped > tbody > tr:nth-child(odd) { + background-color: #f9f9f9; +} +.table-hover > tbody > tr:hover { + background-color: #f5f5f5; +} +table col[class*="col-"] { + position: static; + float: none; + display: table-column; +} +table td[class*="col-"], +table th[class*="col-"] { + position: static; + float: none; + display: table-cell; +} +.table > thead > tr > td.active, +.table > tbody > tr > td.active, +.table > tfoot > tr > td.active, +.table > thead > tr > th.active, +.table > tbody > tr > th.active, +.table > tfoot > tr > th.active, +.table > thead > tr.active > td, +.table > tbody > tr.active > td, +.table > tfoot > tr.active > td, +.table > thead > tr.active > th, +.table > tbody > tr.active > th, +.table > tfoot > tr.active > th { + background-color: #f5f5f5; +} +.table-hover > tbody > tr > td.active:hover, +.table-hover > tbody > tr > th.active:hover, +.table-hover > tbody > tr.active:hover > td, +.table-hover > tbody > tr:hover > .active, +.table-hover > tbody > tr.active:hover > th { + background-color: #e8e8e8; +} +.table > thead > tr > td.success, +.table > tbody > tr > td.success, +.table > tfoot > tr > td.success, +.table > thead > tr > th.success, +.table > tbody > tr > th.success, +.table > tfoot > tr > th.success, +.table > thead > tr.success > td, +.table > tbody > tr.success > td, +.table > tfoot > tr.success > td, +.table > thead > tr.success > th, +.table > tbody > tr.success > th, +.table > tfoot > tr.success > th { + background-color: #dff0d8; +} +.table-hover > tbody > tr > td.success:hover, +.table-hover > tbody > tr > th.success:hover, +.table-hover > tbody > tr.success:hover > td, +.table-hover > tbody > tr:hover > .success, +.table-hover > tbody > tr.success:hover > th { + background-color: #d0e9c6; +} +.table > thead > tr > td.info, +.table > tbody > tr > td.info, +.table > tfoot > tr > td.info, +.table > thead > tr > th.info, +.table > tbody > tr > th.info, +.table > tfoot > tr > th.info, +.table > thead > tr.info > td, +.table > tbody > tr.info > td, +.table > tfoot > tr.info > td, +.table > thead > tr.info > th, +.table > tbody > tr.info > th, +.table > tfoot > tr.info > th { + background-color: #d9edf7; +} +.table-hover > tbody > tr > td.info:hover, +.table-hover > tbody > tr > th.info:hover, +.table-hover > tbody > tr.info:hover > td, +.table-hover > tbody > tr:hover > .info, +.table-hover > tbody > tr.info:hover > th { + background-color: #c4e3f3; +} +.table > thead > tr > td.warning, +.table > tbody > tr > td.warning, +.table > tfoot > tr > td.warning, +.table > thead > tr > th.warning, +.table > tbody > tr > th.warning, +.table > tfoot > tr > th.warning, +.table > thead > tr.warning > td, +.table > tbody > tr.warning > td, +.table > tfoot > tr.warning > td, +.table > thead > tr.warning > th, +.table > tbody > tr.warning > th, +.table > tfoot > tr.warning > th { + background-color: #fcf8e3; +} +.table-hover > tbody > tr > td.warning:hover, +.table-hover > tbody > tr > th.warning:hover, +.table-hover > tbody > tr.warning:hover > td, +.table-hover > tbody > tr:hover > .warning, +.table-hover > tbody > tr.warning:hover > th { + background-color: #faf2cc; +} +.table > thead > tr > td.danger, +.table > tbody > tr > td.danger, +.table > tfoot > tr > td.danger, +.table > thead > tr > th.danger, +.table > tbody > tr > th.danger, +.table > tfoot > tr > th.danger, +.table > thead > tr.danger > td, +.table > tbody > tr.danger > td, +.table > tfoot > tr.danger > td, +.table > thead > tr.danger > th, +.table > tbody > tr.danger > th, +.table > tfoot > tr.danger > th { + background-color: #f2dede; +} +.table-hover > tbody > tr > td.danger:hover, +.table-hover > tbody > tr > th.danger:hover, +.table-hover > tbody > tr.danger:hover > td, +.table-hover > tbody > tr:hover > .danger, +.table-hover > tbody > tr.danger:hover > th { + background-color: #ebcccc; +} +.table-responsive { + overflow-x: auto; + min-height: 0.01%; +} +@media screen and (max-width: 767px) { + .table-responsive { + width: 100%; + margin-bottom: 15px; + overflow-y: hidden; + -ms-overflow-style: -ms-autohiding-scrollbar; + border: 1px solid #dddddd; + } + .table-responsive > .table { + margin-bottom: 0; + } + .table-responsive > .table > thead > tr > th, + .table-responsive > .table > tbody > tr > th, + .table-responsive > .table > tfoot > tr > th, + .table-responsive > .table > thead > tr > td, + .table-responsive > .table > tbody > tr > td, + .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; + } + .table-responsive > .table-bordered { + border: 0; + } + .table-responsive > .table-bordered > thead > tr > th:first-child, + .table-responsive > .table-bordered > tbody > tr > th:first-child, + .table-responsive > .table-bordered > tfoot > tr > th:first-child, + .table-responsive > .table-bordered > thead > tr > td:first-child, + .table-responsive > .table-bordered > tbody > tr > td:first-child, + .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + .table-responsive > .table-bordered > thead > tr > th:last-child, + .table-responsive > .table-bordered > tbody > tr > th:last-child, + .table-responsive > .table-bordered > tfoot > tr > th:last-child, + .table-responsive > .table-bordered > thead > tr > td:last-child, + .table-responsive > .table-bordered > tbody > tr > td:last-child, + .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + .table-responsive > .table-bordered > tbody > tr:last-child > th, + .table-responsive > .table-bordered > tfoot > tr:last-child > th, + .table-responsive > .table-bordered > tbody > tr:last-child > td, + .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; + } +} +fieldset { + padding: 0; + margin: 0; + border: 0; + min-width: 0; +} +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: inherit; + color: #333333; + border: 0; + border-bottom: 1px solid #e5e5e5; +} +label { + display: inline-block; + max-width: 100%; + margin-bottom: 5px; + font-weight: bold; +} +input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + line-height: normal; +} +input[type="file"] { + display: block; +} +input[type="range"] { + display: block; + width: 100%; +} +select[multiple], +select[size] { + height: auto; +} +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +output { + display: block; + padding-top: 7px; + font-size: 14px; + line-height: 1.42857143; + color: #555555; +} +.form-control { + display: block; + width: 100%; + height: 34px; + padding: 6px 12px; + font-size: 14px; + line-height: 1.42857143; + color: #555555; + background-color: #ffffff; + background-image: none; + border: 1px solid #cccccc; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; +} +.form-control:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); + box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); +} +.form-control::-moz-placeholder { + color: #999999; + opacity: 1; +} +.form-control:-ms-input-placeholder { + color: #999999; +} +.form-control::-webkit-input-placeholder { + color: #999999; +} +.form-control[disabled], +.form-control[readonly], +fieldset[disabled] .form-control { + cursor: not-allowed; + background-color: #eeeeee; + opacity: 1; +} +textarea.form-control { + height: auto; +} +input[type="search"] { + -webkit-appearance: none; +} +@media screen and (-webkit-min-device-pixel-ratio: 0) { + input[type="date"], + input[type="time"], + input[type="datetime-local"], + input[type="month"] { + line-height: 34px; + } + input[type="date"].input-sm, + input[type="time"].input-sm, + input[type="datetime-local"].input-sm, + input[type="month"].input-sm { + line-height: 30px; + } + input[type="date"].input-lg, + input[type="time"].input-lg, + input[type="datetime-local"].input-lg, + input[type="month"].input-lg { + line-height: 46px; + } +} +.form-group { + margin-bottom: 15px; +} +.radio, +.checkbox { + position: relative; + display: block; + margin-top: 10px; + margin-bottom: 10px; +} +.radio label, +.checkbox label { + min-height: 20px; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + cursor: pointer; +} +.radio input[type="radio"], +.radio-inline input[type="radio"], +.checkbox input[type="checkbox"], +.checkbox-inline input[type="checkbox"] { + position: absolute; + margin-left: -20px; + margin-top: 4px \9; +} +.radio + .radio, +.checkbox + .checkbox { + margin-top: -5px; +} +.radio-inline, +.checkbox-inline { + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + vertical-align: middle; + font-weight: normal; + cursor: pointer; +} +.radio-inline + .radio-inline, +.checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; +} +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"].disabled, +input[type="checkbox"].disabled, +fieldset[disabled] input[type="radio"], +fieldset[disabled] input[type="checkbox"] { + cursor: not-allowed; +} +.radio-inline.disabled, +.checkbox-inline.disabled, +fieldset[disabled] .radio-inline, +fieldset[disabled] .checkbox-inline { + cursor: not-allowed; +} +.radio.disabled label, +.checkbox.disabled label, +fieldset[disabled] .radio label, +fieldset[disabled] .checkbox label { + cursor: not-allowed; +} +.form-control-static { + padding-top: 7px; + padding-bottom: 7px; + margin-bottom: 0; +} +.form-control-static.input-lg, +.form-control-static.input-sm { + padding-left: 0; + padding-right: 0; +} +.input-sm, +.form-group-sm .form-control { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-sm, +select.form-group-sm .form-control { + height: 30px; + line-height: 30px; +} +textarea.input-sm, +textarea.form-group-sm .form-control, +select[multiple].input-sm, +select[multiple].form-group-sm .form-control { + height: auto; +} +.input-lg, +.form-group-lg .form-control { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} +select.input-lg, +select.form-group-lg .form-control { + height: 46px; + line-height: 46px; +} +textarea.input-lg, +textarea.form-group-lg .form-control, +select[multiple].input-lg, +select[multiple].form-group-lg .form-control { + height: auto; +} +.has-feedback { + position: relative; +} +.has-feedback .form-control { + padding-right: 42.5px; +} +.form-control-feedback { + position: absolute; + top: 0; + right: 0; + z-index: 2; + display: block; + width: 34px; + height: 34px; + line-height: 34px; + text-align: center; + pointer-events: none; +} +.input-lg + .form-control-feedback { + width: 46px; + height: 46px; + line-height: 46px; +} +.input-sm + .form-control-feedback { + width: 30px; + height: 30px; + line-height: 30px; +} +.has-success .help-block, +.has-success .control-label, +.has-success .radio, +.has-success .checkbox, +.has-success .radio-inline, +.has-success .checkbox-inline, +.has-success.radio label, +.has-success.checkbox label, +.has-success.radio-inline label, +.has-success.checkbox-inline label { + color: #3c763d; +} +.has-success .form-control { + border-color: #3c763d; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-success .form-control:focus { + border-color: #2b542c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; +} +.has-success .input-group-addon { + color: #3c763d; + border-color: #3c763d; + background-color: #dff0d8; +} +.has-success .form-control-feedback { + color: #3c763d; +} +.has-warning .help-block, +.has-warning .control-label, +.has-warning .radio, +.has-warning .checkbox, +.has-warning .radio-inline, +.has-warning .checkbox-inline, +.has-warning.radio label, +.has-warning.checkbox label, +.has-warning.radio-inline label, +.has-warning.checkbox-inline label { + color: #8a6d3b; +} +.has-warning .form-control { + border-color: #8a6d3b; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-warning .form-control:focus { + border-color: #66512c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; +} +.has-warning .input-group-addon { + color: #8a6d3b; + border-color: #8a6d3b; + background-color: #fcf8e3; +} +.has-warning .form-control-feedback { + color: #8a6d3b; +} +.has-error .help-block, +.has-error .control-label, +.has-error .radio, +.has-error .checkbox, +.has-error .radio-inline, +.has-error .checkbox-inline, +.has-error.radio label, +.has-error.checkbox label, +.has-error.radio-inline label, +.has-error.checkbox-inline label { + color: #a94442; +} +.has-error .form-control { + border-color: #a94442; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-error .form-control:focus { + border-color: #843534; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; +} +.has-error .input-group-addon { + color: #a94442; + border-color: #a94442; + background-color: #f2dede; +} +.has-error .form-control-feedback { + color: #a94442; +} +.has-feedback label ~ .form-control-feedback { + top: 25px; +} +.has-feedback label.sr-only ~ .form-control-feedback { + top: 0; +} +.help-block { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #737373; +} +@media (min-width: 768px) { + .form-inline .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .form-inline .form-control-static { + display: inline-block; + } + .form-inline .input-group { + display: inline-table; + vertical-align: middle; + } + .form-inline .input-group .input-group-addon, + .form-inline .input-group .input-group-btn, + .form-inline .input-group .form-control { + width: auto; + } + .form-inline .input-group > .form-control { + width: 100%; + } + .form-inline .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio, + .form-inline .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio label, + .form-inline .checkbox label { + padding-left: 0; + } + .form-inline .radio input[type="radio"], + .form-inline .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .form-inline .has-feedback .form-control-feedback { + top: 0; + } +} +.form-horizontal .radio, +.form-horizontal .checkbox, +.form-horizontal .radio-inline, +.form-horizontal .checkbox-inline { + margin-top: 0; + margin-bottom: 0; + padding-top: 7px; +} +.form-horizontal .radio, +.form-horizontal .checkbox { + min-height: 27px; +} +.form-horizontal .form-group { + margin-left: -15px; + margin-right: -15px; +} +@media (min-width: 768px) { + .form-horizontal .control-label { + text-align: right; + margin-bottom: 0; + padding-top: 7px; + } +} +.form-horizontal .has-feedback .form-control-feedback { + right: 15px; +} +@media (min-width: 768px) { + .form-horizontal .form-group-lg .control-label { + padding-top: 14.3px; + } +} +@media (min-width: 768px) { + .form-horizontal .form-group-sm .control-label { + padding-top: 6px; + } +} +.btn { + display: inline-block; + margin-bottom: 0; + font-weight: normal; + text-align: center; + vertical-align: middle; + touch-action: manipulation; + cursor: pointer; + background-image: none; + border: 1px solid transparent; + white-space: nowrap; + padding: 6px 12px; + font-size: 14px; + line-height: 1.42857143; + border-radius: 4px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.btn:focus, +.btn:active:focus, +.btn.active:focus, +.btn.focus, +.btn:active.focus, +.btn.active.focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.btn:hover, +.btn:focus, +.btn.focus { + color: #333333; + text-decoration: none; +} +.btn:active, +.btn.active { + outline: 0; + background-image: none; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} +.btn.disabled, +.btn[disabled], +fieldset[disabled] .btn { + cursor: not-allowed; + pointer-events: none; + opacity: 0.65; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-default { + color: #333333; + background-color: #ffffff; + border-color: #cccccc; +} +.btn-default:hover, +.btn-default:focus, +.btn-default.focus, +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + color: #333333; + background-color: #e6e6e6; + border-color: #adadad; +} +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + background-image: none; +} +.btn-default.disabled, +.btn-default[disabled], +fieldset[disabled] .btn-default, +.btn-default.disabled:hover, +.btn-default[disabled]:hover, +fieldset[disabled] .btn-default:hover, +.btn-default.disabled:focus, +.btn-default[disabled]:focus, +fieldset[disabled] .btn-default:focus, +.btn-default.disabled.focus, +.btn-default[disabled].focus, +fieldset[disabled] .btn-default.focus, +.btn-default.disabled:active, +.btn-default[disabled]:active, +fieldset[disabled] .btn-default:active, +.btn-default.disabled.active, +.btn-default[disabled].active, +fieldset[disabled] .btn-default.active { + background-color: #ffffff; + border-color: #cccccc; +} +.btn-default .badge { + color: #ffffff; + background-color: #333333; +} +.btn-primary { + color: #ffffff; + background-color: #337ab7; + border-color: #2e6da4; +} +.btn-primary:hover, +.btn-primary:focus, +.btn-primary.focus, +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + color: #ffffff; + background-color: #286090; + border-color: #204d74; +} +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + background-image: none; +} +.btn-primary.disabled, +.btn-primary[disabled], +fieldset[disabled] .btn-primary, +.btn-primary.disabled:hover, +.btn-primary[disabled]:hover, +fieldset[disabled] .btn-primary:hover, +.btn-primary.disabled:focus, +.btn-primary[disabled]:focus, +fieldset[disabled] .btn-primary:focus, +.btn-primary.disabled.focus, +.btn-primary[disabled].focus, +fieldset[disabled] .btn-primary.focus, +.btn-primary.disabled:active, +.btn-primary[disabled]:active, +fieldset[disabled] .btn-primary:active, +.btn-primary.disabled.active, +.btn-primary[disabled].active, +fieldset[disabled] .btn-primary.active { + background-color: #337ab7; + border-color: #2e6da4; +} +.btn-primary .badge { + color: #337ab7; + background-color: #ffffff; +} +.btn-success { + color: #ffffff; + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success:hover, +.btn-success:focus, +.btn-success.focus, +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + color: #ffffff; + background-color: #449d44; + border-color: #398439; +} +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + background-image: none; +} +.btn-success.disabled, +.btn-success[disabled], +fieldset[disabled] .btn-success, +.btn-success.disabled:hover, +.btn-success[disabled]:hover, +fieldset[disabled] .btn-success:hover, +.btn-success.disabled:focus, +.btn-success[disabled]:focus, +fieldset[disabled] .btn-success:focus, +.btn-success.disabled.focus, +.btn-success[disabled].focus, +fieldset[disabled] .btn-success.focus, +.btn-success.disabled:active, +.btn-success[disabled]:active, +fieldset[disabled] .btn-success:active, +.btn-success.disabled.active, +.btn-success[disabled].active, +fieldset[disabled] .btn-success.active { + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success .badge { + color: #5cb85c; + background-color: #ffffff; +} +.btn-info { + color: #ffffff; + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info:hover, +.btn-info:focus, +.btn-info.focus, +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + color: #ffffff; + background-color: #31b0d5; + border-color: #269abc; +} +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + background-image: none; +} +.btn-info.disabled, +.btn-info[disabled], +fieldset[disabled] .btn-info, +.btn-info.disabled:hover, +.btn-info[disabled]:hover, +fieldset[disabled] .btn-info:hover, +.btn-info.disabled:focus, +.btn-info[disabled]:focus, +fieldset[disabled] .btn-info:focus, +.btn-info.disabled.focus, +.btn-info[disabled].focus, +fieldset[disabled] .btn-info.focus, +.btn-info.disabled:active, +.btn-info[disabled]:active, +fieldset[disabled] .btn-info:active, +.btn-info.disabled.active, +.btn-info[disabled].active, +fieldset[disabled] .btn-info.active { + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info .badge { + color: #5bc0de; + background-color: #ffffff; +} +.btn-warning { + color: #ffffff; + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning:hover, +.btn-warning:focus, +.btn-warning.focus, +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + color: #ffffff; + background-color: #ec971f; + border-color: #d58512; +} +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + background-image: none; +} +.btn-warning.disabled, +.btn-warning[disabled], +fieldset[disabled] .btn-warning, +.btn-warning.disabled:hover, +.btn-warning[disabled]:hover, +fieldset[disabled] .btn-warning:hover, +.btn-warning.disabled:focus, +.btn-warning[disabled]:focus, +fieldset[disabled] .btn-warning:focus, +.btn-warning.disabled.focus, +.btn-warning[disabled].focus, +fieldset[disabled] .btn-warning.focus, +.btn-warning.disabled:active, +.btn-warning[disabled]:active, +fieldset[disabled] .btn-warning:active, +.btn-warning.disabled.active, +.btn-warning[disabled].active, +fieldset[disabled] .btn-warning.active { + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning .badge { + color: #f0ad4e; + background-color: #ffffff; +} +.btn-danger { + color: #ffffff; + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger:hover, +.btn-danger:focus, +.btn-danger.focus, +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + color: #ffffff; + background-color: #c9302c; + border-color: #ac2925; +} +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + background-image: none; +} +.btn-danger.disabled, +.btn-danger[disabled], +fieldset[disabled] .btn-danger, +.btn-danger.disabled:hover, +.btn-danger[disabled]:hover, +fieldset[disabled] .btn-danger:hover, +.btn-danger.disabled:focus, +.btn-danger[disabled]:focus, +fieldset[disabled] .btn-danger:focus, +.btn-danger.disabled.focus, +.btn-danger[disabled].focus, +fieldset[disabled] .btn-danger.focus, +.btn-danger.disabled:active, +.btn-danger[disabled]:active, +fieldset[disabled] .btn-danger:active, +.btn-danger.disabled.active, +.btn-danger[disabled].active, +fieldset[disabled] .btn-danger.active { + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger .badge { + color: #d9534f; + background-color: #ffffff; +} +.btn-link { + color: #337ab7; + font-weight: normal; + border-radius: 0; +} +.btn-link, +.btn-link:active, +.btn-link.active, +.btn-link[disabled], +fieldset[disabled] .btn-link { + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-link, +.btn-link:hover, +.btn-link:focus, +.btn-link:active { + border-color: transparent; +} +.btn-link:hover, +.btn-link:focus { + color: #23527c; + text-decoration: underline; + background-color: transparent; +} +.btn-link[disabled]:hover, +fieldset[disabled] .btn-link:hover, +.btn-link[disabled]:focus, +fieldset[disabled] .btn-link:focus { + color: #777777; + text-decoration: none; +} +.btn-lg, +.btn-group-lg > .btn { + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} +.btn-sm, +.btn-group-sm > .btn { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-xs, +.btn-group-xs > .btn { + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-block { + display: block; + width: 100%; +} +.btn-block + .btn-block { + margin-top: 5px; +} +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} +.fade { + opacity: 0; + -webkit-transition: opacity 0.15s linear; + -o-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; +} +.fade.in { + opacity: 1; +} +.collapse { + display: none; + visibility: hidden; +} +.collapse.in { + display: block; + visibility: visible; +} +tr.collapse.in { + display: table-row; +} +tbody.collapse.in { + display: table-row-group; +} +.collapsing { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition-property: height, visibility; + transition-property: height, visibility; + -webkit-transition-duration: 0.35s; + transition-duration: 0.35s; + -webkit-transition-timing-function: ease; + transition-timing-function: ease; +} +.caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: 4px solid; + border-right: 4px solid transparent; + border-left: 4px solid transparent; +} +.dropdown { + position: relative; +} +.dropdown-toggle:focus { + outline: 0; +} +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + list-style: none; + font-size: 14px; + text-align: left; + background-color: #ffffff; + border: 1px solid #cccccc; + border: 1px solid rgba(0, 0, 0, 0.15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + background-clip: padding-box; +} +.dropdown-menu.pull-right { + right: 0; + left: auto; +} +.dropdown-menu .divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.42857143; + color: #333333; + white-space: nowrap; +} +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus { + text-decoration: none; + color: #262626; + background-color: #f5f5f5; +} +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #ffffff; + text-decoration: none; + outline: 0; + background-color: #337ab7; +} +.dropdown-menu > .disabled > a, +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + color: #777777; +} +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + text-decoration: none; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + cursor: not-allowed; +} +.open > .dropdown-menu { + display: block; +} +.open > a { + outline: 0; +} +.dropdown-menu-right { + left: auto; + right: 0; +} +.dropdown-menu-left { + left: 0; + right: auto; +} +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.42857143; + color: #777777; + white-space: nowrap; +} +.dropdown-backdrop { + position: fixed; + left: 0; + right: 0; + bottom: 0; + top: 0; + z-index: 990; +} +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + border-top: 0; + border-bottom: 4px solid; + content: ""; +} +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 1px; +} +@media (min-width: 768px) { + .navbar-right .dropdown-menu { + left: auto; + right: 0; + } + .navbar-right .dropdown-menu-left { + left: 0; + right: auto; + } +} +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-block; + vertical-align: middle; +} +.btn-group > .btn, +.btn-group-vertical > .btn { + position: relative; + float: left; +} +.btn-group > .btn:hover, +.btn-group-vertical > .btn:hover, +.btn-group > .btn:focus, +.btn-group-vertical > .btn:focus, +.btn-group > .btn:active, +.btn-group-vertical > .btn:active, +.btn-group > .btn.active, +.btn-group-vertical > .btn.active { + z-index: 2; +} +.btn-group .btn + .btn, +.btn-group .btn + .btn-group, +.btn-group .btn-group + .btn, +.btn-group .btn-group + .btn-group { + margin-left: -1px; +} +.btn-toolbar { + margin-left: -5px; +} +.btn-toolbar .btn-group, +.btn-toolbar .input-group { + float: left; +} +.btn-toolbar > .btn, +.btn-toolbar > .btn-group, +.btn-toolbar > .input-group { + margin-left: 5px; +} +.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { + border-radius: 0; +} +.btn-group > .btn:first-child { + margin-left: 0; +} +.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.btn-group > .btn:last-child:not(:first-child), +.btn-group > .dropdown-toggle:not(:first-child) { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.btn-group > .btn-group { + float: left; +} +.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group > .btn-group:first-child > .btn:last-child, +.btn-group > .btn-group:first-child > .dropdown-toggle { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.btn-group > .btn-group:last-child > .btn:first-child { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} +.btn-group > .btn + .dropdown-toggle { + padding-left: 8px; + padding-right: 8px; +} +.btn-group > .btn-lg + .dropdown-toggle { + padding-left: 12px; + padding-right: 12px; +} +.btn-group.open .dropdown-toggle { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} +.btn-group.open .dropdown-toggle.btn-link { + -webkit-box-shadow: none; + box-shadow: none; +} +.btn .caret { + margin-left: 0; +} +.btn-lg .caret { + border-width: 5px 5px 0; + border-bottom-width: 0; +} +.dropup .btn-lg .caret { + border-width: 0 5px 5px; +} +.btn-group-vertical > .btn, +.btn-group-vertical > .btn-group, +.btn-group-vertical > .btn-group > .btn { + display: block; + float: none; + width: 100%; + max-width: 100%; +} +.btn-group-vertical > .btn-group > .btn { + float: none; +} +.btn-group-vertical > .btn + .btn, +.btn-group-vertical > .btn + .btn-group, +.btn-group-vertical > .btn-group + .btn, +.btn-group-vertical > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; +} +.btn-group-vertical > .btn:not(:first-child):not(:last-child) { + border-radius: 0; +} +.btn-group-vertical > .btn:first-child:not(:last-child) { + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn:last-child:not(:first-child) { + border-bottom-left-radius: 4px; + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.btn-group-justified { + display: table; + width: 100%; + table-layout: fixed; + border-collapse: separate; +} +.btn-group-justified > .btn, +.btn-group-justified > .btn-group { + float: none; + display: table-cell; + width: 1%; +} +.btn-group-justified > .btn-group .btn { + width: 100%; +} +.btn-group-justified > .btn-group .dropdown-menu { + left: auto; +} +[data-toggle="buttons"] > .btn input[type="radio"], +[data-toggle="buttons"] > .btn-group > .btn input[type="radio"], +[data-toggle="buttons"] > .btn input[type="checkbox"], +[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] { + position: absolute; + clip: rect(0, 0, 0, 0); + pointer-events: none; +} +.input-group { + position: relative; + display: table; + border-collapse: separate; +} +.input-group[class*="col-"] { + float: none; + padding-left: 0; + padding-right: 0; +} +.input-group .form-control { + position: relative; + z-index: 2; + float: left; + width: 100%; + margin-bottom: 0; +} +.input-group-lg > .form-control, +.input-group-lg > .input-group-addon, +.input-group-lg > .input-group-btn > .btn { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} +select.input-group-lg > .form-control, +select.input-group-lg > .input-group-addon, +select.input-group-lg > .input-group-btn > .btn { + height: 46px; + line-height: 46px; +} +textarea.input-group-lg > .form-control, +textarea.input-group-lg > .input-group-addon, +textarea.input-group-lg > .input-group-btn > .btn, +select[multiple].input-group-lg > .form-control, +select[multiple].input-group-lg > .input-group-addon, +select[multiple].input-group-lg > .input-group-btn > .btn { + height: auto; +} +.input-group-sm > .form-control, +.input-group-sm > .input-group-addon, +.input-group-sm > .input-group-btn > .btn { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-group-sm > .form-control, +select.input-group-sm > .input-group-addon, +select.input-group-sm > .input-group-btn > .btn { + height: 30px; + line-height: 30px; +} +textarea.input-group-sm > .form-control, +textarea.input-group-sm > .input-group-addon, +textarea.input-group-sm > .input-group-btn > .btn, +select[multiple].input-group-sm > .form-control, +select[multiple].input-group-sm > .input-group-addon, +select[multiple].input-group-sm > .input-group-btn > .btn { + height: auto; +} +.input-group-addon, +.input-group-btn, +.input-group .form-control { + display: table-cell; +} +.input-group-addon:not(:first-child):not(:last-child), +.input-group-btn:not(:first-child):not(:last-child), +.input-group .form-control:not(:first-child):not(:last-child) { + border-radius: 0; +} +.input-group-addon, +.input-group-btn { + width: 1%; + white-space: nowrap; + vertical-align: middle; +} +.input-group-addon { + padding: 6px 12px; + font-size: 14px; + font-weight: normal; + line-height: 1; + color: #555555; + text-align: center; + background-color: #eeeeee; + border: 1px solid #cccccc; + border-radius: 4px; +} +.input-group-addon.input-sm { + padding: 5px 10px; + font-size: 12px; + border-radius: 3px; +} +.input-group-addon.input-lg { + padding: 10px 16px; + font-size: 18px; + border-radius: 6px; +} +.input-group-addon input[type="radio"], +.input-group-addon input[type="checkbox"] { + margin-top: 0; +} +.input-group .form-control:first-child, +.input-group-addon:first-child, +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group > .btn, +.input-group-btn:first-child > .dropdown-toggle, +.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), +.input-group-btn:last-child > .btn-group:not(:last-child) > .btn { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.input-group-addon:first-child { + border-right: 0; +} +.input-group .form-control:last-child, +.input-group-addon:last-child, +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group > .btn, +.input-group-btn:last-child > .dropdown-toggle, +.input-group-btn:first-child > .btn:not(:first-child), +.input-group-btn:first-child > .btn-group:not(:first-child) > .btn { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.input-group-addon:last-child { + border-left: 0; +} +.input-group-btn { + position: relative; + font-size: 0; + white-space: nowrap; +} +.input-group-btn > .btn { + position: relative; +} +.input-group-btn > .btn + .btn { + margin-left: -1px; +} +.input-group-btn > .btn:hover, +.input-group-btn > .btn:focus, +.input-group-btn > .btn:active { + z-index: 2; +} +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group { + margin-right: -1px; +} +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group { + margin-left: -1px; +} +.nav { + margin-bottom: 0; + padding-left: 0; + list-style: none; +} +.nav > li { + position: relative; + display: block; +} +.nav > li > a { + position: relative; + display: block; + padding: 10px 15px; +} +.nav > li > a:hover, +.nav > li > a:focus { + text-decoration: none; + background-color: #eeeeee; +} +.nav > li.disabled > a { + color: #777777; +} +.nav > li.disabled > a:hover, +.nav > li.disabled > a:focus { + color: #777777; + text-decoration: none; + background-color: transparent; + cursor: not-allowed; +} +.nav .open > a, +.nav .open > a:hover, +.nav .open > a:focus { + background-color: #eeeeee; + border-color: #337ab7; +} +.nav .nav-divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.nav > li > a > img { + max-width: none; +} +.nav-tabs { + border-bottom: 1px solid #dddddd; +} +.nav-tabs > li { + float: left; + margin-bottom: -1px; +} +.nav-tabs > li > a { + margin-right: 2px; + line-height: 1.42857143; + border: 1px solid transparent; + border-radius: 4px 4px 0 0; +} +.nav-tabs > li > a:hover { + border-color: #eeeeee #eeeeee #dddddd; +} +.nav-tabs > li.active > a, +.nav-tabs > li.active > a:hover, +.nav-tabs > li.active > a:focus { + color: #555555; + background-color: #ffffff; + border: 1px solid #dddddd; + border-bottom-color: transparent; + cursor: default; +} +.nav-tabs.nav-justified { + width: 100%; + border-bottom: 0; +} +.nav-tabs.nav-justified > li { + float: none; +} +.nav-tabs.nav-justified > li > a { + text-align: center; + margin-bottom: 5px; +} +.nav-tabs.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-tabs.nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs.nav-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs.nav-justified > .active > a, +.nav-tabs.nav-justified > .active > a:hover, +.nav-tabs.nav-justified > .active > a:focus { + border: 1px solid #dddddd; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li > a { + border-bottom: 1px solid #dddddd; + border-radius: 4px 4px 0 0; + } + .nav-tabs.nav-justified > .active > a, + .nav-tabs.nav-justified > .active > a:hover, + .nav-tabs.nav-justified > .active > a:focus { + border-bottom-color: #ffffff; + } +} +.nav-pills > li { + float: left; +} +.nav-pills > li > a { + border-radius: 4px; +} +.nav-pills > li + li { + margin-left: 2px; +} +.nav-pills > li.active > a, +.nav-pills > li.active > a:hover, +.nav-pills > li.active > a:focus { + color: #ffffff; + background-color: #337ab7; +} +.nav-stacked > li { + float: none; +} +.nav-stacked > li + li { + margin-top: 2px; + margin-left: 0; +} +.nav-justified { + width: 100%; +} +.nav-justified > li { + float: none; +} +.nav-justified > li > a { + text-align: center; + margin-bottom: 5px; +} +.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs-justified { + border-bottom: 0; +} +.nav-tabs-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs-justified > .active > a, +.nav-tabs-justified > .active > a:hover, +.nav-tabs-justified > .active > a:focus { + border: 1px solid #dddddd; +} +@media (min-width: 768px) { + .nav-tabs-justified > li > a { + border-bottom: 1px solid #dddddd; + border-radius: 4px 4px 0 0; + } + .nav-tabs-justified > .active > a, + .nav-tabs-justified > .active > a:hover, + .nav-tabs-justified > .active > a:focus { + border-bottom-color: #ffffff; + } +} +.tab-content > .tab-pane { + display: none; + visibility: hidden; +} +.tab-content > .active { + display: block; + visibility: visible; +} +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.navbar { + position: relative; + min-height: 70px; + margin-bottom: 20px; + border: 1px solid transparent; +} +@media (min-width: 768px) { + .navbar { + border-radius: 4px; + } +} +@media (min-width: 768px) { + .navbar-header { + float: left; + } +} +.navbar-collapse { + overflow-x: visible; + padding-right: 15px; + padding-left: 15px; + border-top: 1px solid transparent; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); + -webkit-overflow-scrolling: touch; +} +.navbar-collapse.in { + overflow-y: auto; +} +@media (min-width: 768px) { + .navbar-collapse { + width: auto; + border-top: 0; + box-shadow: none; + } + .navbar-collapse.collapse { + display: block !important; + visibility: visible !important; + height: auto !important; + padding-bottom: 0; + overflow: visible !important; + } + .navbar-collapse.in { + overflow-y: visible; + } + .navbar-fixed-top .navbar-collapse, + .navbar-static-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + padding-left: 0; + padding-right: 0; + } +} +.navbar-fixed-top .navbar-collapse, +.navbar-fixed-bottom .navbar-collapse { + max-height: 340px; +} +@media (max-device-width: 480px) and (orientation: landscape) { + .navbar-fixed-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + max-height: 200px; + } +} +.container > .navbar-header, +.container-fluid > .navbar-header, +.container > .navbar-collapse, +.container-fluid > .navbar-collapse { + margin-right: -15px; + margin-left: -15px; +} +@media (min-width: 768px) { + .container > .navbar-header, + .container-fluid > .navbar-header, + .container > .navbar-collapse, + .container-fluid > .navbar-collapse { + margin-right: 0; + margin-left: 0; + } +} +.navbar-static-top { + z-index: 1000; + border-width: 0 0 1px; +} +@media (min-width: 768px) { + .navbar-static-top { + border-radius: 0; + } +} +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; +} +@media (min-width: 768px) { + .navbar-fixed-top, + .navbar-fixed-bottom { + border-radius: 0; + } +} +.navbar-fixed-top { + top: 0; + border-width: 0 0 1px; +} +.navbar-fixed-bottom { + bottom: 0; + margin-bottom: 0; + border-width: 1px 0 0; +} +.navbar-brand { + float: left; + padding: 25px 15px; + font-size: 18px; + line-height: 20px; + height: 70px; +} +.navbar-brand:hover, +.navbar-brand:focus { + text-decoration: none; +} +.navbar-brand > img { + display: block; +} +@media (min-width: 768px) { + .navbar > .container .navbar-brand, + .navbar > .container-fluid .navbar-brand { + margin-left: -15px; + } +} +.navbar-toggle { + position: relative; + float: right; + margin-right: 15px; + padding: 9px 10px; + margin-top: 18px; + margin-bottom: 18px; + background-color: transparent; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} +.navbar-toggle:focus { + outline: 0; +} +.navbar-toggle .icon-bar { + display: block; + width: 22px; + height: 2px; + border-radius: 1px; +} +.navbar-toggle .icon-bar + .icon-bar { + margin-top: 4px; +} +@media (min-width: 768px) { + .navbar-toggle { + display: none; + } +} +.navbar-nav { + margin: 12.5px -15px; +} +.navbar-nav > li > a { + padding-top: 10px; + padding-bottom: 10px; + line-height: 20px; +} +@media (max-width: 767px) { + .navbar-nav .open .dropdown-menu { + position: static; + float: none; + width: auto; + margin-top: 0; + background-color: transparent; + border: 0; + box-shadow: none; + } + .navbar-nav .open .dropdown-menu > li > a, + .navbar-nav .open .dropdown-menu .dropdown-header { + padding: 5px 15px 5px 25px; + } + .navbar-nav .open .dropdown-menu > li > a { + line-height: 20px; + } + .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-nav .open .dropdown-menu > li > a:focus { + background-image: none; + } +} +@media (min-width: 768px) { + .navbar-nav { + float: left; + margin: 0; + } + .navbar-nav > li { + float: left; + } + .navbar-nav > li > a { + padding-top: 25px; + padding-bottom: 25px; + } +} +.navbar-form { + margin-left: -15px; + margin-right: -15px; + padding: 10px 15px; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + margin-top: 18px; + margin-bottom: 18px; +} +@media (min-width: 768px) { + .navbar-form .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .navbar-form .form-control-static { + display: inline-block; + } + .navbar-form .input-group { + display: inline-table; + vertical-align: middle; + } + .navbar-form .input-group .input-group-addon, + .navbar-form .input-group .input-group-btn, + .navbar-form .input-group .form-control { + width: auto; + } + .navbar-form .input-group > .form-control { + width: 100%; + } + .navbar-form .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio, + .navbar-form .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio label, + .navbar-form .checkbox label { + padding-left: 0; + } + .navbar-form .radio input[type="radio"], + .navbar-form .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .navbar-form .has-feedback .form-control-feedback { + top: 0; + } +} +@media (max-width: 767px) { + .navbar-form .form-group { + margin-bottom: 5px; + } + .navbar-form .form-group:last-child { + margin-bottom: 0; + } +} +@media (min-width: 768px) { + .navbar-form { + width: auto; + border: 0; + margin-left: 0; + margin-right: 0; + padding-top: 0; + padding-bottom: 0; + -webkit-box-shadow: none; + box-shadow: none; + } +} +.navbar-nav > li > .dropdown-menu { + margin-top: 0; + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { + border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.navbar-btn { + margin-top: 18px; + margin-bottom: 18px; +} +.navbar-btn.btn-sm { + margin-top: 20px; + margin-bottom: 20px; +} +.navbar-btn.btn-xs { + margin-top: 24px; + margin-bottom: 24px; +} +.navbar-text { + margin-top: 25px; + margin-bottom: 25px; +} +@media (min-width: 768px) { + .navbar-text { + float: left; + margin-left: 15px; + margin-right: 15px; + } +} +@media (min-width: 768px) { + .navbar-left { + float: left !important; + } + .navbar-right { + float: right !important; + margin-right: -15px; + } + .navbar-right ~ .navbar-right { + margin-right: 0; + } +} +.navbar-default { + background-color: #f8f8f8; + border-color: #e7e7e7; +} +.navbar-default .navbar-brand { + color: #777777; +} +.navbar-default .navbar-brand:hover, +.navbar-default .navbar-brand:focus { + color: #5e5e5e; + background-color: transparent; +} +.navbar-default .navbar-text { + color: #777777; +} +.navbar-default .navbar-nav > li > a { + color: #777777; +} +.navbar-default .navbar-nav > li > a:hover, +.navbar-default .navbar-nav > li > a:focus { + color: #333333; + background-color: transparent; +} +.navbar-default .navbar-nav > .active > a, +.navbar-default .navbar-nav > .active > a:hover, +.navbar-default .navbar-nav > .active > a:focus { + color: #555555; + background-color: #e7e7e7; +} +.navbar-default .navbar-nav > .disabled > a, +.navbar-default .navbar-nav > .disabled > a:hover, +.navbar-default .navbar-nav > .disabled > a:focus { + color: #cccccc; + background-color: transparent; +} +.navbar-default .navbar-toggle { + border-color: #dddddd; +} +.navbar-default .navbar-toggle:hover, +.navbar-default .navbar-toggle:focus { + background-color: #dddddd; +} +.navbar-default .navbar-toggle .icon-bar { + background-color: #888888; +} +.navbar-default .navbar-collapse, +.navbar-default .navbar-form { + border-color: #e7e7e7; +} +.navbar-default .navbar-nav > .open > a, +.navbar-default .navbar-nav > .open > a:hover, +.navbar-default .navbar-nav > .open > a:focus { + background-color: #e7e7e7; + color: #555555; +} +@media (max-width: 767px) { + .navbar-default .navbar-nav .open .dropdown-menu > li > a { + color: #777777; + } + .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { + color: #333333; + background-color: transparent; + } + .navbar-default .navbar-nav .open .dropdown-menu > .active > a, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #555555; + background-color: #e7e7e7; + } + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #cccccc; + background-color: transparent; + } +} +.navbar-default .navbar-link { + color: #777777; +} +.navbar-default .navbar-link:hover { + color: #333333; +} +.navbar-default .btn-link { + color: #777777; +} +.navbar-default .btn-link:hover, +.navbar-default .btn-link:focus { + color: #333333; +} +.navbar-default .btn-link[disabled]:hover, +fieldset[disabled] .navbar-default .btn-link:hover, +.navbar-default .btn-link[disabled]:focus, +fieldset[disabled] .navbar-default .btn-link:focus { + color: #cccccc; +} +.navbar-inverse { + background-color: #222222; + border-color: #080808; +} +.navbar-inverse .navbar-brand { + color: #9d9d9d; +} +.navbar-inverse .navbar-brand:hover, +.navbar-inverse .navbar-brand:focus { + color: #ffffff; + background-color: transparent; +} +.navbar-inverse .navbar-text { + color: #9d9d9d; +} +.navbar-inverse .navbar-nav > li > a { + color: #9d9d9d; +} +.navbar-inverse .navbar-nav > li > a:hover, +.navbar-inverse .navbar-nav > li > a:focus { + color: #ffffff; + background-color: transparent; +} +.navbar-inverse .navbar-nav > .active > a, +.navbar-inverse .navbar-nav > .active > a:hover, +.navbar-inverse .navbar-nav > .active > a:focus { + color: #ffffff; + background-color: #080808; +} +.navbar-inverse .navbar-nav > .disabled > a, +.navbar-inverse .navbar-nav > .disabled > a:hover, +.navbar-inverse .navbar-nav > .disabled > a:focus { + color: #444444; + background-color: transparent; +} +.navbar-inverse .navbar-toggle { + border-color: #333333; +} +.navbar-inverse .navbar-toggle:hover, +.navbar-inverse .navbar-toggle:focus { + background-color: #333333; +} +.navbar-inverse .navbar-toggle .icon-bar { + background-color: #ffffff; +} +.navbar-inverse .navbar-collapse, +.navbar-inverse .navbar-form { + border-color: #101010; +} +.navbar-inverse .navbar-nav > .open > a, +.navbar-inverse .navbar-nav > .open > a:hover, +.navbar-inverse .navbar-nav > .open > a:focus { + background-color: #080808; + color: #ffffff; +} +@media (max-width: 767px) { + .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { + border-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu .divider { + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { + color: #9d9d9d; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { + color: #ffffff; + background-color: transparent; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #ffffff; + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #444444; + background-color: transparent; + } +} +.navbar-inverse .navbar-link { + color: #9d9d9d; +} +.navbar-inverse .navbar-link:hover { + color: #ffffff; +} +.navbar-inverse .btn-link { + color: #9d9d9d; +} +.navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link:focus { + color: #ffffff; +} +.navbar-inverse .btn-link[disabled]:hover, +fieldset[disabled] .navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link[disabled]:focus, +fieldset[disabled] .navbar-inverse .btn-link:focus { + color: #444444; +} +.breadcrumb { + padding: 8px 15px; + margin-bottom: 20px; + list-style: none; + background-color: #f5f5f5; + border-radius: 4px; +} +.breadcrumb > li { + display: inline-block; +} +.breadcrumb > li + li:before { + content: "/\00a0"; + padding: 0 5px; + color: #cccccc; +} +.breadcrumb > .active { + color: #777777; +} +.pagination { + display: inline-block; + padding-left: 0; + margin: 20px 0; + border-radius: 4px; +} +.pagination > li { + display: inline; +} +.pagination > li > a, +.pagination > li > span { + position: relative; + float: left; + padding: 6px 12px; + line-height: 1.42857143; + text-decoration: none; + color: #337ab7; + background-color: #ffffff; + border: 1px solid #dddddd; + margin-left: -1px; +} +.pagination > li:first-child > a, +.pagination > li:first-child > span { + margin-left: 0; + border-bottom-left-radius: 4px; + border-top-left-radius: 4px; +} +.pagination > li:last-child > a, +.pagination > li:last-child > span { + border-bottom-right-radius: 4px; + border-top-right-radius: 4px; +} +.pagination > li > a:hover, +.pagination > li > span:hover, +.pagination > li > a:focus, +.pagination > li > span:focus { + color: #23527c; + background-color: #eeeeee; + border-color: #dddddd; +} +.pagination > .active > a, +.pagination > .active > span, +.pagination > .active > a:hover, +.pagination > .active > span:hover, +.pagination > .active > a:focus, +.pagination > .active > span:focus { + z-index: 2; + color: #ffffff; + background-color: #337ab7; + border-color: #337ab7; + cursor: default; +} +.pagination > .disabled > span, +.pagination > .disabled > span:hover, +.pagination > .disabled > span:focus, +.pagination > .disabled > a, +.pagination > .disabled > a:hover, +.pagination > .disabled > a:focus { + color: #777777; + background-color: #ffffff; + border-color: #dddddd; + cursor: not-allowed; +} +.pagination-lg > li > a, +.pagination-lg > li > span { + padding: 10px 16px; + font-size: 18px; +} +.pagination-lg > li:first-child > a, +.pagination-lg > li:first-child > span { + border-bottom-left-radius: 6px; + border-top-left-radius: 6px; +} +.pagination-lg > li:last-child > a, +.pagination-lg > li:last-child > span { + border-bottom-right-radius: 6px; + border-top-right-radius: 6px; +} +.pagination-sm > li > a, +.pagination-sm > li > span { + padding: 5px 10px; + font-size: 12px; +} +.pagination-sm > li:first-child > a, +.pagination-sm > li:first-child > span { + border-bottom-left-radius: 3px; + border-top-left-radius: 3px; +} +.pagination-sm > li:last-child > a, +.pagination-sm > li:last-child > span { + border-bottom-right-radius: 3px; + border-top-right-radius: 3px; +} +.pager { + padding-left: 0; + margin: 20px 0; + list-style: none; + text-align: center; +} +.pager li { + display: inline; +} +.pager li > a, +.pager li > span { + display: inline-block; + padding: 5px 14px; + background-color: #ffffff; + border: 1px solid #dddddd; + border-radius: 15px; +} +.pager li > a:hover, +.pager li > a:focus { + text-decoration: none; + background-color: #eeeeee; +} +.pager .next > a, +.pager .next > span { + float: right; +} +.pager .previous > a, +.pager .previous > span { + float: left; +} +.pager .disabled > a, +.pager .disabled > a:hover, +.pager .disabled > a:focus, +.pager .disabled > span { + color: #777777; + background-color: #ffffff; + cursor: not-allowed; +} +.label { + display: inline; + padding: .2em .6em .3em; + font-size: 75%; + font-weight: bold; + line-height: 1; + color: #ffffff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: .25em; +} +a.label:hover, +a.label:focus { + color: #ffffff; + text-decoration: none; + cursor: pointer; +} +.label:empty { + display: none; +} +.btn .label { + position: relative; + top: -1px; +} +.label-default { + background-color: #777777; +} +.label-default[href]:hover, +.label-default[href]:focus { + background-color: #5e5e5e; +} +.label-primary { + background-color: #337ab7; +} +.label-primary[href]:hover, +.label-primary[href]:focus { + background-color: #286090; +} +.label-success { + background-color: #5cb85c; +} +.label-success[href]:hover, +.label-success[href]:focus { + background-color: #449d44; +} +.label-info { + background-color: #5bc0de; +} +.label-info[href]:hover, +.label-info[href]:focus { + background-color: #31b0d5; +} +.label-warning { + background-color: #f0ad4e; +} +.label-warning[href]:hover, +.label-warning[href]:focus { + background-color: #ec971f; +} +.label-danger { + background-color: #d9534f; +} +.label-danger[href]:hover, +.label-danger[href]:focus { + background-color: #c9302c; +} +.badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: bold; + color: #ffffff; + line-height: 1; + vertical-align: baseline; + white-space: nowrap; + text-align: center; + background-color: #777777; + border-radius: 10px; +} +.badge:empty { + display: none; +} +.btn .badge { + position: relative; + top: -1px; +} +.btn-xs .badge { + top: 0; + padding: 1px 5px; +} +a.badge:hover, +a.badge:focus { + color: #ffffff; + text-decoration: none; + cursor: pointer; +} +.list-group-item.active > .badge, +.nav-pills > .active > a > .badge { + color: #337ab7; + background-color: #ffffff; +} +.list-group-item > .badge { + float: right; +} +.list-group-item > .badge + .badge { + margin-right: 5px; +} +.nav-pills > li > a > .badge { + margin-left: 3px; +} +.jumbotron { + padding: 30px 15px; + margin-bottom: 30px; + color: inherit; + background-color: #eeeeee; +} +.jumbotron h1, +.jumbotron .h1 { + color: inherit; +} +.jumbotron p { + margin-bottom: 15px; + font-size: 21px; + font-weight: 200; +} +.jumbotron > hr { + border-top-color: #d5d5d5; +} +.container .jumbotron, +.container-fluid .jumbotron { + border-radius: 6px; +} +.jumbotron .container { + max-width: 100%; +} +@media screen and (min-width: 768px) { + .jumbotron { + padding: 48px 0; + } + .container .jumbotron, + .container-fluid .jumbotron { + padding-left: 60px; + padding-right: 60px; + } + .jumbotron h1, + .jumbotron .h1 { + font-size: 63px; + } +} +.thumbnail { + display: block; + padding: 4px; + margin-bottom: 20px; + line-height: 1.42857143; + background-color: #ffffff; + border: 1px solid #dddddd; + border-radius: 4px; + -webkit-transition: border 0.2s ease-in-out; + -o-transition: border 0.2s ease-in-out; + transition: border 0.2s ease-in-out; +} +.thumbnail > img, +.thumbnail a > img { + margin-left: auto; + margin-right: auto; +} +a.thumbnail:hover, +a.thumbnail:focus, +a.thumbnail.active { + border-color: #337ab7; +} +.thumbnail .caption { + padding: 9px; + color: #333333; +} +.alert { + padding: 15px; + margin-bottom: 20px; + border: 1px solid transparent; + border-radius: 4px; +} +.alert h4 { + margin-top: 0; + color: inherit; +} +.alert .alert-link { + font-weight: bold; +} +.alert > p, +.alert > ul { + margin-bottom: 0; +} +.alert > p + p { + margin-top: 5px; +} +.alert-dismissable, +.alert-dismissible { + padding-right: 35px; +} +.alert-dismissable .close, +.alert-dismissible .close { + position: relative; + top: -2px; + right: -21px; + color: inherit; +} +.alert-success { + background-color: #dff0d8; + border-color: #d6e9c6; + color: #3c763d; +} +.alert-success hr { + border-top-color: #c9e2b3; +} +.alert-success .alert-link { + color: #2b542c; +} +.alert-info { + background-color: #d9edf7; + border-color: #bce8f1; + color: #31708f; +} +.alert-info hr { + border-top-color: #a6e1ec; +} +.alert-info .alert-link { + color: #245269; +} +.alert-warning { + background-color: #fcf8e3; + border-color: #faebcc; + color: #8a6d3b; +} +.alert-warning hr { + border-top-color: #f7e1b5; +} +.alert-warning .alert-link { + color: #66512c; +} +.alert-danger { + background-color: #f2dede; + border-color: #ebccd1; + color: #a94442; +} +.alert-danger hr { + border-top-color: #e4b9c0; +} +.alert-danger .alert-link { + color: #843534; +} +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +.progress { + overflow: hidden; + height: 20px; + margin-bottom: 20px; + background-color: #f5f5f5; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); +} +.progress-bar { + float: left; + width: 0%; + height: 100%; + font-size: 12px; + line-height: 20px; + color: #ffffff; + text-align: center; + background-color: #337ab7; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -webkit-transition: width 0.6s ease; + -o-transition: width 0.6s ease; + transition: width 0.6s ease; +} +.progress-striped .progress-bar, +.progress-bar-striped { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-size: 40px 40px; +} +.progress.active .progress-bar, +.progress-bar.active { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} +.progress-bar-success { + background-color: #5cb85c; +} +.progress-striped .progress-bar-success { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.progress-bar-info { + background-color: #5bc0de; +} +.progress-striped .progress-bar-info { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.progress-bar-warning { + background-color: #f0ad4e; +} +.progress-striped .progress-bar-warning { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.progress-bar-danger { + background-color: #d9534f; +} +.progress-striped .progress-bar-danger { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.media { + margin-top: 15px; +} +.media:first-child { + margin-top: 0; +} +.media-right, +.media > .pull-right { + padding-left: 10px; +} +.media-left, +.media > .pull-left { + padding-right: 10px; +} +.media-left, +.media-right, +.media-body { + display: table-cell; + vertical-align: top; +} +.media-middle { + vertical-align: middle; +} +.media-bottom { + vertical-align: bottom; +} +.media-heading { + margin-top: 0; + margin-bottom: 5px; +} +.media-list { + padding-left: 0; + list-style: none; +} +.list-group { + margin-bottom: 20px; + padding-left: 0; +} +.list-group-item { + position: relative; + display: block; + padding: 10px 15px; + margin-bottom: -1px; + background-color: #ffffff; + border: 1px solid #dddddd; +} +.list-group-item:first-child { + border-top-right-radius: 4px; + border-top-left-radius: 4px; +} +.list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; +} +a.list-group-item { + color: #555555; +} +a.list-group-item .list-group-item-heading { + color: #333333; +} +a.list-group-item:hover, +a.list-group-item:focus { + text-decoration: none; + color: #555555; + background-color: #f5f5f5; +} +.list-group-item.disabled, +.list-group-item.disabled:hover, +.list-group-item.disabled:focus { + background-color: #eeeeee; + color: #777777; + cursor: not-allowed; +} +.list-group-item.disabled .list-group-item-heading, +.list-group-item.disabled:hover .list-group-item-heading, +.list-group-item.disabled:focus .list-group-item-heading { + color: inherit; +} +.list-group-item.disabled .list-group-item-text, +.list-group-item.disabled:hover .list-group-item-text, +.list-group-item.disabled:focus .list-group-item-text { + color: #777777; +} +.list-group-item.active, +.list-group-item.active:hover, +.list-group-item.active:focus { + z-index: 2; + color: #ffffff; + background-color: #337ab7; + border-color: #337ab7; +} +.list-group-item.active .list-group-item-heading, +.list-group-item.active:hover .list-group-item-heading, +.list-group-item.active:focus .list-group-item-heading, +.list-group-item.active .list-group-item-heading > small, +.list-group-item.active:hover .list-group-item-heading > small, +.list-group-item.active:focus .list-group-item-heading > small, +.list-group-item.active .list-group-item-heading > .small, +.list-group-item.active:hover .list-group-item-heading > .small, +.list-group-item.active:focus .list-group-item-heading > .small { + color: inherit; +} +.list-group-item.active .list-group-item-text, +.list-group-item.active:hover .list-group-item-text, +.list-group-item.active:focus .list-group-item-text { + color: #c7ddef; +} +.list-group-item-success { + color: #3c763d; + background-color: #dff0d8; +} +a.list-group-item-success { + color: #3c763d; +} +a.list-group-item-success .list-group-item-heading { + color: inherit; +} +a.list-group-item-success:hover, +a.list-group-item-success:focus { + color: #3c763d; + background-color: #d0e9c6; +} +a.list-group-item-success.active, +a.list-group-item-success.active:hover, +a.list-group-item-success.active:focus { + color: #fff; + background-color: #3c763d; + border-color: #3c763d; +} +.list-group-item-info { + color: #31708f; + background-color: #d9edf7; +} +a.list-group-item-info { + color: #31708f; +} +a.list-group-item-info .list-group-item-heading { + color: inherit; +} +a.list-group-item-info:hover, +a.list-group-item-info:focus { + color: #31708f; + background-color: #c4e3f3; +} +a.list-group-item-info.active, +a.list-group-item-info.active:hover, +a.list-group-item-info.active:focus { + color: #fff; + background-color: #31708f; + border-color: #31708f; +} +.list-group-item-warning { + color: #8a6d3b; + background-color: #fcf8e3; +} +a.list-group-item-warning { + color: #8a6d3b; +} +a.list-group-item-warning .list-group-item-heading { + color: inherit; +} +a.list-group-item-warning:hover, +a.list-group-item-warning:focus { + color: #8a6d3b; + background-color: #faf2cc; +} +a.list-group-item-warning.active, +a.list-group-item-warning.active:hover, +a.list-group-item-warning.active:focus { + color: #fff; + background-color: #8a6d3b; + border-color: #8a6d3b; +} +.list-group-item-danger { + color: #a94442; + background-color: #f2dede; +} +a.list-group-item-danger { + color: #a94442; +} +a.list-group-item-danger .list-group-item-heading { + color: inherit; +} +a.list-group-item-danger:hover, +a.list-group-item-danger:focus { + color: #a94442; + background-color: #ebcccc; +} +a.list-group-item-danger.active, +a.list-group-item-danger.active:hover, +a.list-group-item-danger.active:focus { + color: #fff; + background-color: #a94442; + border-color: #a94442; +} +.list-group-item-heading { + margin-top: 0; + margin-bottom: 5px; +} +.list-group-item-text { + margin-bottom: 0; + line-height: 1.3; +} +.panel { + margin-bottom: 20px; + background-color: #ffffff; + border: 1px solid transparent; + border-radius: 4px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); +} +.panel-body { + padding: 15px; +} +.panel-heading { + padding: 10px 15px; + border-bottom: 1px solid transparent; + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} +.panel-heading > .dropdown .dropdown-toggle { + color: inherit; +} +.panel-title { + margin-top: 0; + margin-bottom: 0; + font-size: 16px; + color: inherit; +} +.panel-title > a { + color: inherit; +} +.panel-footer { + padding: 10px 15px; + background-color: #f5f5f5; + border-top: 1px solid #dddddd; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .list-group, +.panel > .panel-collapse > .list-group { + margin-bottom: 0; +} +.panel > .list-group .list-group-item, +.panel > .panel-collapse > .list-group .list-group-item { + border-width: 1px 0; + border-radius: 0; +} +.panel > .list-group:first-child .list-group-item:first-child, +.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child { + border-top: 0; + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} +.panel > .list-group:last-child .list-group-item:last-child, +.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child { + border-bottom: 0; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel-heading + .list-group .list-group-item:first-child { + border-top-width: 0; +} +.list-group + .panel-footer { + border-top-width: 0; +} +.panel > .table, +.panel > .table-responsive > .table, +.panel > .panel-collapse > .table { + margin-bottom: 0; +} +.panel > .table caption, +.panel > .table-responsive > .table caption, +.panel > .panel-collapse > .table caption { + padding-left: 15px; + padding-right: 15px; +} +.panel > .table:first-child, +.panel > .table-responsive:first-child > .table:first-child { + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child { + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child { + border-top-left-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child { + border-top-right-radius: 3px; +} +.panel > .table:last-child, +.panel > .table-responsive:last-child > .table:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child { + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child { + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child { + border-bottom-right-radius: 3px; +} +.panel > .panel-body + .table, +.panel > .panel-body + .table-responsive, +.panel > .table + .panel-body, +.panel > .table-responsive + .panel-body { + border-top: 1px solid #dddddd; +} +.panel > .table > tbody:first-child > tr:first-child th, +.panel > .table > tbody:first-child > tr:first-child td { + border-top: 0; +} +.panel > .table-bordered, +.panel > .table-responsive > .table-bordered { + border: 0; +} +.panel > .table-bordered > thead > tr > th:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:first-child, +.panel > .table-bordered > tbody > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, +.panel > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-bordered > thead > tr > td:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:first-child, +.panel > .table-bordered > tbody > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, +.panel > .table-bordered > tfoot > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; +} +.panel > .table-bordered > thead > tr > th:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:last-child, +.panel > .table-bordered > tbody > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, +.panel > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-bordered > thead > tr > td:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:last-child, +.panel > .table-bordered > tbody > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, +.panel > .table-bordered > tfoot > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; +} +.panel > .table-bordered > thead > tr:first-child > td, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > td, +.panel > .table-bordered > tbody > tr:first-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td, +.panel > .table-bordered > thead > tr:first-child > th, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > th, +.panel > .table-bordered > tbody > tr:first-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th { + border-bottom: 0; +} +.panel > .table-bordered > tbody > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, +.panel > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-bordered > tbody > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, +.panel > .table-bordered > tfoot > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th { + border-bottom: 0; +} +.panel > .table-responsive { + border: 0; + margin-bottom: 0; +} +.panel-group { + margin-bottom: 20px; +} +.panel-group .panel { + margin-bottom: 0; + border-radius: 4px; +} +.panel-group .panel + .panel { + margin-top: 5px; +} +.panel-group .panel-heading { + border-bottom: 0; +} +.panel-group .panel-heading + .panel-collapse > .panel-body, +.panel-group .panel-heading + .panel-collapse > .list-group { + border-top: 1px solid #dddddd; +} +.panel-group .panel-footer { + border-top: 0; +} +.panel-group .panel-footer + .panel-collapse .panel-body { + border-bottom: 1px solid #dddddd; +} +.panel-default { + border-color: #dddddd; +} +.panel-default > .panel-heading { + color: #333333; + background-color: #f5f5f5; + border-color: #dddddd; +} +.panel-default > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #dddddd; +} +.panel-default > .panel-heading .badge { + color: #f5f5f5; + background-color: #333333; +} +.panel-default > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #dddddd; +} +.panel-primary { + border-color: #337ab7; +} +.panel-primary > .panel-heading { + color: #ffffff; + background-color: #337ab7; + border-color: #337ab7; +} +.panel-primary > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #337ab7; +} +.panel-primary > .panel-heading .badge { + color: #337ab7; + background-color: #ffffff; +} +.panel-primary > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #337ab7; +} +.panel-success { + border-color: #d6e9c6; +} +.panel-success > .panel-heading { + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; +} +.panel-success > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #d6e9c6; +} +.panel-success > .panel-heading .badge { + color: #dff0d8; + background-color: #3c763d; +} +.panel-success > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #d6e9c6; +} +.panel-info { + border-color: #bce8f1; +} +.panel-info > .panel-heading { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; +} +.panel-info > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #bce8f1; +} +.panel-info > .panel-heading .badge { + color: #d9edf7; + background-color: #31708f; +} +.panel-info > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #bce8f1; +} +.panel-warning { + border-color: #faebcc; +} +.panel-warning > .panel-heading { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; +} +.panel-warning > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #faebcc; +} +.panel-warning > .panel-heading .badge { + color: #fcf8e3; + background-color: #8a6d3b; +} +.panel-warning > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #faebcc; +} +.panel-danger { + border-color: #ebccd1; +} +.panel-danger > .panel-heading { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; +} +.panel-danger > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ebccd1; +} +.panel-danger > .panel-heading .badge { + color: #f2dede; + background-color: #a94442; +} +.panel-danger > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ebccd1; +} +.embed-responsive { + position: relative; + display: block; + height: 0; + padding: 0; + overflow: hidden; +} +.embed-responsive .embed-responsive-item, +.embed-responsive iframe, +.embed-responsive embed, +.embed-responsive object, +.embed-responsive video { + position: absolute; + top: 0; + left: 0; + bottom: 0; + height: 100%; + width: 100%; + border: 0; +} +.embed-responsive.embed-responsive-16by9 { + padding-bottom: 56.25%; +} +.embed-responsive.embed-responsive-4by3 { + padding-bottom: 75%; +} +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #e3e3e3; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); +} +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, 0.15); +} +.well-lg { + padding: 24px; + border-radius: 6px; +} +.well-sm { + padding: 9px; + border-radius: 3px; +} +.close { + float: right; + font-size: 21px; + font-weight: bold; + line-height: 1; + color: #000000; + text-shadow: 0 1px 0 #ffffff; + opacity: 0.2; + filter: alpha(opacity=20); +} +.close:hover, +.close:focus { + color: #000000; + text-decoration: none; + cursor: pointer; + opacity: 0.5; + filter: alpha(opacity=50); +} +button.close { + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none; +} +.modal-open { + overflow: hidden; +} +.modal { + display: none; + overflow: hidden; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + -webkit-overflow-scrolling: touch; + outline: 0; +} +.modal.fade .modal-dialog { + -webkit-transform: translate(0, -25%); + -ms-transform: translate(0, -25%); + -o-transform: translate(0, -25%); + transform: translate(0, -25%); + -webkit-transition: -webkit-transform 0.3s ease-out; + -moz-transition: -moz-transform 0.3s ease-out; + -o-transition: -o-transform 0.3s ease-out; + transition: transform 0.3s ease-out; +} +.modal.in .modal-dialog { + -webkit-transform: translate(0, 0); + -ms-transform: translate(0, 0); + -o-transform: translate(0, 0); + transform: translate(0, 0); +} +.modal-open .modal { + overflow-x: hidden; + overflow-y: auto; +} +.modal-dialog { + position: relative; + width: auto; + margin: 10px; +} +.modal-content { + position: relative; + background-color: #ffffff; + border: 1px solid #999999; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 6px; + -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + background-clip: padding-box; + outline: 0; +} +.modal-backdrop { + position: absolute; + top: 0; + right: 0; + left: 0; + background-color: #000000; +} +.modal-backdrop.fade { + opacity: 0; + filter: alpha(opacity=0); +} +.modal-backdrop.in { + opacity: 0.5; + filter: alpha(opacity=50); +} +.modal-header { + padding: 15px; + border-bottom: 1px solid #e5e5e5; + min-height: 16.42857143px; +} +.modal-header .close { + margin-top: -2px; +} +.modal-title { + margin: 0; + line-height: 1.42857143; +} +.modal-body { + position: relative; + padding: 15px; +} +.modal-footer { + padding: 15px; + text-align: right; + border-top: 1px solid #e5e5e5; +} +.modal-footer .btn + .btn { + margin-left: 5px; + margin-bottom: 0; +} +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} +.modal-footer .btn-block + .btn-block { + margin-left: 0; +} +.modal-scrollbar-measure { + position: absolute; + top: -9999px; + width: 50px; + height: 50px; + overflow: scroll; +} +@media (min-width: 768px) { + .modal-dialog { + width: 600px; + margin: 30px auto; + } + .modal-content { + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + } + .modal-sm { + width: 300px; + } +} +@media (min-width: 992px) { + .modal-lg { + width: 900px; + } +} +.tooltip { + position: absolute; + z-index: 1070; + display: block; + visibility: visible; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 12px; + font-weight: normal; + line-height: 1.4; + opacity: 0; + filter: alpha(opacity=0); +} +.tooltip.in { + opacity: 0.9; + filter: alpha(opacity=90); +} +.tooltip.top { + margin-top: -3px; + padding: 5px 0; +} +.tooltip.right { + margin-left: 3px; + padding: 0 5px; +} +.tooltip.bottom { + margin-top: 3px; + padding: 5px 0; +} +.tooltip.left { + margin-left: -3px; + padding: 0 5px; +} +.tooltip-inner { + max-width: 200px; + padding: 3px 8px; + color: #ffffff; + text-align: center; + text-decoration: none; + background-color: #000000; + border-radius: 4px; +} +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-width: 5px 5px 0; + border-top-color: #000000; +} +.tooltip.top-left .tooltip-arrow { + bottom: 0; + right: 5px; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000000; +} +.tooltip.top-right .tooltip-arrow { + bottom: 0; + left: 5px; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000000; +} +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-width: 5px 5px 5px 0; + border-right-color: #000000; +} +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-width: 5px 0 5px 5px; + border-left-color: #000000; +} +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000000; +} +.tooltip.bottom-left .tooltip-arrow { + top: 0; + right: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000000; +} +.tooltip.bottom-right .tooltip-arrow { + top: 0; + left: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000000; +} +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1060; + display: none; + max-width: 276px; + padding: 1px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + font-weight: normal; + line-height: 1.42857143; + text-align: left; + background-color: #ffffff; + background-clip: padding-box; + border: 1px solid #cccccc; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + white-space: normal; +} +.popover.top { + margin-top: -10px; +} +.popover.right { + margin-left: 10px; +} +.popover.bottom { + margin-top: 10px; +} +.popover.left { + margin-left: -10px; +} +.popover-title { + margin: 0; + padding: 8px 14px; + font-size: 14px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + border-radius: 5px 5px 0 0; +} +.popover-content { + padding: 9px 14px; +} +.popover > .arrow, +.popover > .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.popover > .arrow { + border-width: 11px; +} +.popover > .arrow:after { + border-width: 10px; + content: ""; +} +.popover.top > .arrow { + left: 50%; + margin-left: -11px; + border-bottom-width: 0; + border-top-color: #999999; + border-top-color: rgba(0, 0, 0, 0.25); + bottom: -11px; +} +.popover.top > .arrow:after { + content: " "; + bottom: 1px; + margin-left: -10px; + border-bottom-width: 0; + border-top-color: #ffffff; +} +.popover.right > .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-left-width: 0; + border-right-color: #999999; + border-right-color: rgba(0, 0, 0, 0.25); +} +.popover.right > .arrow:after { + content: " "; + left: 1px; + bottom: -10px; + border-left-width: 0; + border-right-color: #ffffff; +} +.popover.bottom > .arrow { + left: 50%; + margin-left: -11px; + border-top-width: 0; + border-bottom-color: #999999; + border-bottom-color: rgba(0, 0, 0, 0.25); + top: -11px; +} +.popover.bottom > .arrow:after { + content: " "; + top: 1px; + margin-left: -10px; + border-top-width: 0; + border-bottom-color: #ffffff; +} +.popover.left > .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-right-width: 0; + border-left-color: #999999; + border-left-color: rgba(0, 0, 0, 0.25); +} +.popover.left > .arrow:after { + content: " "; + right: 1px; + border-right-width: 0; + border-left-color: #ffffff; + bottom: -10px; +} +.carousel { + position: relative; +} +.carousel-inner { + position: relative; + overflow: hidden; + width: 100%; +} +.carousel-inner > .item { + display: none; + position: relative; + -webkit-transition: 0.6s ease-in-out left; + -o-transition: 0.6s ease-in-out left; + transition: 0.6s ease-in-out left; +} +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + line-height: 1; +} +@media all and (transform-3d), (-webkit-transform-3d) { + .carousel-inner > .item { + transition: transform 0.6s ease-in-out; + backface-visibility: hidden; + perspective: 1000; + } + .carousel-inner > .item.next, + .carousel-inner > .item.active.right { + transform: translate3d(100%, 0, 0); + left: 0; + } + .carousel-inner > .item.prev, + .carousel-inner > .item.active.left { + transform: translate3d(-100%, 0, 0); + left: 0; + } + .carousel-inner > .item.next.left, + .carousel-inner > .item.prev.right, + .carousel-inner > .item.active { + transform: translate3d(0, 0, 0); + left: 0; + } +} +.carousel-inner > .active, +.carousel-inner > .next, +.carousel-inner > .prev { + display: block; +} +.carousel-inner > .active { + left: 0; +} +.carousel-inner > .next, +.carousel-inner > .prev { + position: absolute; + top: 0; + width: 100%; +} +.carousel-inner > .next { + left: 100%; +} +.carousel-inner > .prev { + left: -100%; +} +.carousel-inner > .next.left, +.carousel-inner > .prev.right { + left: 0; +} +.carousel-inner > .active.left { + left: -100%; +} +.carousel-inner > .active.right { + left: 100%; +} +.carousel-control { + position: absolute; + top: 0; + left: 0; + bottom: 0; + width: 15%; + opacity: 0.5; + filter: alpha(opacity=50); + font-size: 20px; + color: #ffffff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); +} +.carousel-control.left { + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); +} +.carousel-control.right { + left: auto; + right: 0; + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); +} +.carousel-control:hover, +.carousel-control:focus { + outline: 0; + color: #ffffff; + text-decoration: none; + opacity: 0.9; + filter: alpha(opacity=90); +} +.carousel-control .icon-prev, +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-left, +.carousel-control .glyphicon-chevron-right { + position: absolute; + top: 50%; + z-index: 5; + display: inline-block; +} +.carousel-control .icon-prev, +.carousel-control .glyphicon-chevron-left { + left: 50%; + margin-left: -10px; +} +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-right { + right: 50%; + margin-right: -10px; +} +.carousel-control .icon-prev, +.carousel-control .icon-next { + width: 20px; + height: 20px; + margin-top: -10px; + font-family: serif; +} +.carousel-control .icon-prev:before { + content: '\2039'; +} +.carousel-control .icon-next:before { + content: '\203a'; +} +.carousel-indicators { + position: absolute; + bottom: 10px; + left: 50%; + z-index: 15; + width: 60%; + margin-left: -30%; + padding-left: 0; + list-style: none; + text-align: center; +} +.carousel-indicators li { + display: inline-block; + width: 10px; + height: 10px; + margin: 1px; + text-indent: -999px; + border: 1px solid #ffffff; + border-radius: 10px; + cursor: pointer; + background-color: #000 \9; + background-color: rgba(0, 0, 0, 0); +} +.carousel-indicators .active { + margin: 0; + width: 12px; + height: 12px; + background-color: #ffffff; +} +.carousel-caption { + position: absolute; + left: 15%; + right: 15%; + bottom: 20px; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #ffffff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); +} +.carousel-caption .btn { + text-shadow: none; +} +@media screen and (min-width: 768px) { + .carousel-control .glyphicon-chevron-left, + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-prev, + .carousel-control .icon-next { + width: 30px; + height: 30px; + margin-top: -15px; + font-size: 30px; + } + .carousel-control .glyphicon-chevron-left, + .carousel-control .icon-prev { + margin-left: -15px; + } + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-next { + margin-right: -15px; + } + .carousel-caption { + left: 20%; + right: 20%; + padding-bottom: 30px; + } + .carousel-indicators { + bottom: 20px; + } +} +.clearfix:before, +.clearfix:after, +.dl-horizontal dd:before, +.dl-horizontal dd:after, +.container:before, +.container:after, +.container-fluid:before, +.container-fluid:after, +.row:before, +.row:after, +.form-horizontal .form-group:before, +.form-horizontal .form-group:after, +.btn-toolbar:before, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:before, +.btn-group-vertical > .btn-group:after, +.nav:before, +.nav:after, +.navbar:before, +.navbar:after, +.navbar-header:before, +.navbar-header:after, +.navbar-collapse:before, +.navbar-collapse:after, +.pager:before, +.pager:after, +.panel-body:before, +.panel-body:after, +.modal-footer:before, +.modal-footer:after { + content: " "; + display: table; +} +.clearfix:after, +.dl-horizontal dd:after, +.container:after, +.container-fluid:after, +.row:after, +.form-horizontal .form-group:after, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:after, +.nav:after, +.navbar:after, +.navbar-header:after, +.navbar-collapse:after, +.pager:after, +.panel-body:after, +.modal-footer:after { + clear: both; +} +.center-block { + display: block; + margin-left: auto; + margin-right: auto; +} +.pull-right { + float: right !important; +} +.pull-left { + float: left !important; +} +.hide { + display: none !important; +} +.show { + display: block !important; +} +.invisible { + visibility: hidden; +} +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} +.hidden { + display: none !important; + visibility: hidden !important; +} +.affix { + position: fixed; +} +@-ms-viewport { + width: device-width; +} +.visible-xs, +.visible-sm, +.visible-md, +.visible-lg { + display: none !important; +} +.visible-xs-block, +.visible-xs-inline, +.visible-xs-inline-block, +.visible-sm-block, +.visible-sm-inline, +.visible-sm-inline-block, +.visible-md-block, +.visible-md-inline, +.visible-md-inline-block, +.visible-lg-block, +.visible-lg-inline, +.visible-lg-inline-block { + display: none !important; +} +@media (max-width: 767px) { + .visible-xs { + display: block !important; + } + table.visible-xs { + display: table; + } + tr.visible-xs { + display: table-row !important; + } + th.visible-xs, + td.visible-xs { + display: table-cell !important; + } +} +@media (max-width: 767px) { + .visible-xs-block { + display: block !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline { + display: inline !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline-block { + display: inline-block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm { + display: block !important; + } + table.visible-sm { + display: table; + } + tr.visible-sm { + display: table-row !important; + } + th.visible-sm, + td.visible-sm { + display: table-cell !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-block { + display: block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline { + display: inline !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline-block { + display: inline-block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md { + display: block !important; + } + table.visible-md { + display: table; + } + tr.visible-md { + display: table-row !important; + } + th.visible-md, + td.visible-md { + display: table-cell !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-block { + display: block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline { + display: inline !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline-block { + display: inline-block !important; + } +} +@media (min-width: 1200px) { + .visible-lg { + display: block !important; + } + table.visible-lg { + display: table; + } + tr.visible-lg { + display: table-row !important; + } + th.visible-lg, + td.visible-lg { + display: table-cell !important; + } +} +@media (min-width: 1200px) { + .visible-lg-block { + display: block !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline { + display: inline !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline-block { + display: inline-block !important; + } +} +@media (max-width: 767px) { + .hidden-xs { + display: none !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .hidden-sm { + display: none !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-md { + display: none !important; + } +} +@media (min-width: 1200px) { + .hidden-lg { + display: none !important; + } +} +.visible-print { + display: none !important; +} +@media print { + .visible-print { + display: block !important; + } + table.visible-print { + display: table; + } + tr.visible-print { + display: table-row !important; + } + th.visible-print, + td.visible-print { + display: table-cell !important; + } +} +.visible-print-block { + display: none !important; +} +@media print { + .visible-print-block { + display: block !important; + } +} +.visible-print-inline { + display: none !important; +} +@media print { + .visible-print-inline { + display: inline !important; + } +} +.visible-print-inline-block { + display: none !important; +} +@media print { + .visible-print-inline-block { + display: inline-block !important; + } +} +@media print { + .hidden-print { + display: none !important; + } +} +#wrap { + padding-top: 70px; +} +.navbar-nav.navbar-right:last-child { + margin-right: 0; +} diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/appbar/appbar.hbs b/modules/distribution/src/repository/jaggeryapps/sensebot/units/appbar/appbar.hbs new file mode 100755 index 00000000..b4575ac8 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/appbar/appbar.hbs @@ -0,0 +1,141 @@ +{{#zone "main"}} + +
+
+ + +
+
+
+
Register

+
+ +
+
+
+ First Name +
+
+ +
+
+
+
+ Last Name +
+
+ +
+
+
+
+ Username +
+
+ +
+
+
+
+ Email +
+
+ +
+
+
+
+ Password +
+
+ +
+
+
+
+ Confirm Password +
+
+ +
+
+
+ + I Agree by Clicking register, you agree to the Terms and Conditions set out by this site +
+ +
+ + +
+
+
+ +
+ +
+
+ +{{/zone}} \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/appbar/appbar.js b/modules/distribution/src/repository/jaggeryapps/sensebot/units/appbar/appbar.js new file mode 100755 index 00000000..be564964 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/appbar/appbar.js @@ -0,0 +1,19 @@ +function onRequest(context){ + var dcProps = require('/config/dc-props.js').config(); + if (dcProps.ssoConfiguration.enabled) { + response.sendRedirect(dcProps.appContext + "sso/login"); + exit(); + }else{ + context.loginPath = "api/user/login"; + } + + var constants = require("/modules/constants.js"); + var localLogoutURL = dcProps.appContext + "api/user/logout"; + var ssoLogoutURL = dcProps.appContext + "sso/logout"; + context.logoutURL = dcProps.ssoConfiguration.enabled? ssoLogoutURL : localLogoutURL; + context.user = session.get(constants.USER_SESSION_KEY); + + context.viewonly = !context.user; + + return context; +} diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/appbar/appbar.json b/modules/distribution/src/repository/jaggeryapps/sensebot/units/appbar/appbar.json new file mode 100755 index 00000000..6240cff5 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/appbar/appbar.json @@ -0,0 +1,3 @@ +{ + "predicate": "false" +} \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/appbar/public/images/logo.png b/modules/distribution/src/repository/jaggeryapps/sensebot/units/appbar/public/images/logo.png new file mode 100755 index 00000000..91cc5d3f Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/appbar/public/images/logo.png differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/mydevice.hbs b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/mydevice.hbs new file mode 100755 index 00000000..97498a91 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/mydevice.hbs @@ -0,0 +1,77 @@ +{{#zone "topCss"}} + + +{{/zone}} +{{#zone "topJs"}} + + + + + + +{{/zone}} +{{#zone "main"}} +
+
+
+
+

Sense Bot

+
+
+
+
+
+ + +
+
+ +
+ +
+
+

Temperature

+
+ +
+
+
+
+
+
+

Light

+
+ +
+
+
+
+
+

Motion

+
+ +
+
+
+
+
+

Sonar

+
+ +
+
+
+
+
+ + + + + + + +{{/zone}} diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/mydevice.js b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/mydevice.js new file mode 100755 index 00000000..fc57dc19 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/mydevice.js @@ -0,0 +1,4 @@ +function onRequest(context){ + context.sketchPath = "api/device/sketch"; + return context; +} \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/mydevice.json b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/mydevice.json new file mode 100755 index 00000000..795898d0 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/mydevice.json @@ -0,0 +1,3 @@ +{ + "predicate": "true" +} \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/css/daterangepicker.css b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/css/daterangepicker.css new file mode 100755 index 00000000..030b3386 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/css/daterangepicker.css @@ -0,0 +1,232 @@ +.date-picker +{ + width:170px; + height:25px; + padding:0; + border:0; + line-height:25px; + padding-left:10px; + font-size:12px; + font-family:Arial; + font-weight:bold; + cursor:pointer; + color:#303030; + position:relative; + z-index:2; +} +.date-picker-wrapper +{ + position:absolute; + z-index:1; + border:1px solid #bfbfbf; + background-color:#efefef; + width:428px; + padding: 5px 12px; + font-size:12px; + line-height:20px; + color:#aaa; + font-family:Arial; + box-shadow:3px 3px 10px rgba(0,0,0,0.5); +} +.date-picker-wrapper.single-date { + width:auto; +} +.date-picker-wrapper.no-shortcuts { padding-bottom:12px;} +.date-picker-wrapper .footer +{ + font-size:11px; + padding-top: 3px; +} +.date-picker-wrapper b +{ + color:#666; + font-weight:700; +} +.date-picker-wrapper a +{ + color: rgb(107, 180, 214); + text-decoration:underline; +} +.date-picker-wrapper .month-name +{ + text-transform: uppercase; +} +.date-picker-wrapper .month-wrapper +{ + border:1px solid #bfbfbf; + border-radius:3px; + background-color:#fff; + padding:5px; + cursor:default; + position:relative; + _overflow:hidden; +} +.date-picker-wrapper .month-wrapper table +{ + width:190px; + float:left; +} +.date-picker-wrapper .month-wrapper table.month2 +{ + width:190px; + float:right; +} +.date-picker-wrapper .month-wrapper table th, +.date-picker-wrapper .month-wrapper table td +{ + vertical-align:middle; + text-align:center; + line-height:14px; + margin : 0px; + padding : 0px; +} +.date-picker-wrapper .month-wrapper table .day +{ + height:19px; + line-height:19px; + font-size:12px; + margin-bottom:1px; + color:#999; + cursor:default; +} +.date-picker-wrapper .month-wrapper table div.day.lastMonth, +.date-picker-wrapper .month-wrapper table div.day.nextMonth +{ + color:#999; + cursor:default; +} +.date-picker-wrapper .month-wrapper table .day.checked +{ + background-color: rgba(156, 219, 247, 0.5); +} +.date-picker-wrapper .month-wrapper table .week-name +{ + height:20px; + line-height:20px; + font-weight:100; + text-transform: uppercase; +} + +.date-picker-wrapper .month-wrapper table .day.has-tooltip { cursor:help !important;} + +.date-picker-wrapper .month-wrapper table .day.toMonth.valid +{ + color:#333; + cursor:pointer; +} + +.date-picker-wrapper .month-wrapper table .day.real-today { background-color: rgb(255, 230, 132); } +.date-picker-wrapper .month-wrapper table .day.real-today.checked { background-color: rgb(112, 204, 213); } + + +.date-picker-wrapper table .caption +{ + height:40px; +} +.date-picker-wrapper table .caption .next, +.date-picker-wrapper table .caption .prev +{ + padding:0 5px; + cursor:pointer; +} +.date-picker-wrapper table .caption .next:hover, +.date-picker-wrapper table .caption .prev:hover +{ + background-color:#ccc; + color:white; +} +.date-picker-wrapper .gap +{ + position:absolute; + display:none; + top:0px; + left:204px; + z-index: 1; + width:15px; + height: 100%; + background-color:red; + font-size:0; + line-height:0; +} +.date-picker-wrapper .gap .gap-lines { height: 100%; overflow:hidden; } +.date-picker-wrapper .gap .gap-line { height:15px;width:15px; position:relative; } +.date-picker-wrapper .gap .gap-line .gap-1 { z-index:1; height:0; border-left:8px solid white; border-top:8px solid #eee;border-bottom:8px solid #eee; } +.date-picker-wrapper .gap .gap-line .gap-2 { position:absolute; right:0; top:0px; z-index:2; height:0; border-left:8px solid transparent; border-top:8px solid white; } +.date-picker-wrapper .gap .gap-line .gap-3 { position:absolute; right:0; top:8px; z-index:2; height:0; border-left:8px solid transparent; border-bottom:8px solid white; } +.date-picker-wrapper .gap .gap-top-mask { width: 6px; height:1px; position:absolute; top: -1px; left: 1px; background-color: #eee; z-index:3; } +.date-picker-wrapper .gap .gap-bottom-mask { width: 6px; height:1px; position:absolute; bottom: -1px; left: 7px; background-color: #eee; z-index:3; } + +.date-picker-wrapper .selected-days +{ + display:none; +} +.date-picker-wrapper .drp_top-bar +{ + line-height:40px; + height:40px; + position:relative; +} +.date-picker-wrapper .drp_top-bar .error-top { display:none; } +.date-picker-wrapper .drp_top-bar .normal-top { display:none; } +.date-picker-wrapper .drp_top-bar .default-top { display:block; } + +.date-picker-wrapper .drp_top-bar.error .default-top { display:none; } +.date-picker-wrapper .drp_top-bar.error .error-top { display:block; color:red; } + +.date-picker-wrapper .drp_top-bar.normal .default-top { display:none; } +.date-picker-wrapper .drp_top-bar.normal .normal-top { display:block; } + +.date-picker-wrapper .drp_top-bar .apply-btn +{ + position:absolute; + right: 0px; + top: 6px; + padding:3px 5px; + margin:0; + font-size:12px; + border-radius:4px; + cursor:pointer; + + color: #d9eef7; + border: solid 1px #0076a3; + background: #0095cd; + background: -webkit-gradient(linear, left top, left bottom, from(#00adee), to(#0078a5)); + background: -moz-linear-gradient(top, #00adee, #0078a5); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00adee', endColorstr='#0078a5'); + color:white; +} + +.date-picker-wrapper .drp_top-bar .apply-btn.disabled +{ + cursor: pointer; + color: #606060; + border: solid 1px #b7b7b7; + background: #fff; + background: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#ededed)); + background: -moz-linear-gradient(top, #fff, #ededed); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#ededed'); +} +/*time styling*/ +.time { + position: relative; +} +.time input[type=range] { + vertical-align: middle; +} +.time1, .time2 { + width: 180px; + padding: 0 5px; + text-align: center; +} +.time1 { + float: left; +} +.time2 { + float: right; +} +.hour, .minute { + text-align: right; +} +.hide { + display: none; +} diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/css/nv.d3.css b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/css/nv.d3.css new file mode 100755 index 00000000..26453e88 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/css/nv.d3.css @@ -0,0 +1,645 @@ +/******************** + * SVG CSS + */ + + +svg { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + /* Trying to get SVG to act like a greedy block in all browsers */ + display: block; + width:100%; + height:100%; +} + +/******************** + Default CSS for an svg element nvd3 used +*/ +svg.nvd3-svg { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -ms-user-select: none; + -moz-user-select: none; + user-select: none; + display: block; +} + +/******************** + Box shadow and border radius styling +*/ +.nvtooltip.with-3d-shadow, .with-3d-shadow .nvtooltip { + -moz-box-shadow: 0 5px 10px rgba(0,0,0,.2); + -webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2); + box-shadow: 0 5px 10px rgba(0,0,0,.2); + + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; +} + +/******************** + * TOOLTIP CSS + */ + +.nvtooltip { + position: absolute; + background-color: rgba(255,255,255,1.0); + padding: 1px; + border: 1px solid rgba(0,0,0,.2); + z-index: 10000; + + font-family: Arial; + font-size: 13px; + text-align: left; + pointer-events: none; + + white-space: nowrap; + + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +/*Give tooltips that old fade in transition by + putting a "with-transitions" class on the container div. +*/ +.nvtooltip.with-transitions, .with-transitions .nvtooltip { + transition: opacity 50ms linear; + -moz-transition: opacity 50ms linear; + -webkit-transition: opacity 50ms linear; + + transition-delay: 200ms; + -moz-transition-delay: 200ms; + -webkit-transition-delay: 200ms; +} + +.nvtooltip.x-nvtooltip, +.nvtooltip.y-nvtooltip { + padding: 8px; +} + +.nvtooltip h3 { + margin: 0; + padding: 4px 14px; + line-height: 18px; + font-weight: normal; + background-color: rgba(247,247,247,0.75); + text-align: center; + + border-bottom: 1px solid #ebebeb; + + -webkit-border-radius: 5px 5px 0 0; + -moz-border-radius: 5px 5px 0 0; + border-radius: 1px 5px 0 0; +} + +.nvtooltip p { + margin: 0; + padding: 5px 14px; + text-align: center; +} + +.nvtooltip span { + display: inline-block; + margin: 2px 0; +} + +.nvtooltip table { + margin: 6px; + border-spacing:0; +} + + +.nvtooltip table td { + padding: 2px 9px 2px 0; + vertical-align: middle; +} + +.nvtooltip table td.key { + font-weight:normal; +} +.nvtooltip table td.value { + text-align: right; + font-weight: bold; +} + +.nvtooltip table tr.highlight td { + padding: 1px 9px 1px 0; + border-bottom-style: solid; + border-bottom-width: 1px; + border-top-style: solid; + border-top-width: 1px; +} + +.nvtooltip table td.legend-color-guide div { + width: 8px; + height: 8px; + vertical-align: middle; +} + +.nvtooltip .footer { + padding: 3px; + text-align: center; +} + +.nvtooltip-pending-removal { + position: absolute; + pointer-events: none; +} + +.nvd3 text { + font: normal 12px Arial; +} + +.nvd3 .title { + font: bold 14px Arial; +} + +.nvd3 .nv-background { + fill: white; + fill-opacity: 0; +} + +.nvd3.nv-noData { + font-size: 18px; + font-weight: bold; +} + + +/********** +* Brush +*/ + +.nv-brush .extent { + fill-opacity: .125; + shape-rendering: crispEdges; +} + + +/********** +* Legend +*/ + +.nvd3 .nv-legend .nv-series { + cursor: pointer; +} + +.nvd3 .nv-legend .nv-disabled circle { + fill-opacity: 0; +} + + +/********** +* Axes +*/ + +.axis { + opacity: 1; +} + +.axis.nv-disabled { + opacity: 0; +} + +.nvd3 .nv-axis { + pointer-events:none; +} + +.nvd3 .nv-axis path { + fill: none; + stroke: #000; + stroke-opacity: .75; + shape-rendering: crispEdges; +} + +.nvd3 .nv-axis path.domain { + stroke-opacity: .75; +} + +.nvd3 .nv-axis.nv-x path.domain { + stroke-opacity: 0; +} + +.nvd3 .nv-axis line { + fill: none; + stroke: #e5e5e5; + shape-rendering: crispEdges; +} + +.nvd3 .nv-axis .zero line, +/*this selector may not be necessary*/ .nvd3 .nv-axis line.zero { + stroke-opacity: .75; +} + +.nvd3 .nv-axis .nv-axisMaxMin text { + font-weight: bold; +} + +.nvd3 .x .nv-axis .nv-axisMaxMin text, +.nvd3 .x2 .nv-axis .nv-axisMaxMin text, +.nvd3 .x3 .nv-axis .nv-axisMaxMin text { + text-anchor: middle +} + + +/********** +* Brush +*/ + +.nv-brush .resize path { + fill: #eee; + stroke: #666; +} + + +/********** +* Bars +*/ + +.nvd3 .nv-bars .negative rect { + zfill: brown; +} + +.nvd3 .nv-bars rect { + zfill: steelblue; + fill-opacity: .75; + + transition: fill-opacity 250ms linear; + -moz-transition: fill-opacity 250ms linear; + -webkit-transition: fill-opacity 250ms linear; +} + +.nvd3 .nv-bars rect.hover { + fill-opacity: 1; +} + +.nvd3 .nv-bars .hover rect { + fill: lightblue; +} + +.nvd3 .nv-bars text { + fill: rgba(0,0,0,0); +} + +.nvd3 .nv-bars .hover text { + fill: rgba(0,0,0,1); +} + + +/********** +* Bars +*/ + +.nvd3 .nv-multibar .nv-groups rect, +.nvd3 .nv-multibarHorizontal .nv-groups rect, +.nvd3 .nv-discretebar .nv-groups rect { + stroke-opacity: 0; + + transition: fill-opacity 250ms linear; + -moz-transition: fill-opacity 250ms linear; + -webkit-transition: fill-opacity 250ms linear; +} + +.nvd3 .nv-multibar .nv-groups rect:hover, +.nvd3 .nv-multibarHorizontal .nv-groups rect:hover, +.nvd3 .nv-discretebar .nv-groups rect:hover { + fill-opacity: 1; +} + +.nvd3 .nv-discretebar .nv-groups text, +.nvd3 .nv-multibarHorizontal .nv-groups text { + font-weight: bold; + fill: rgba(0,0,0,1); + stroke: rgba(0,0,0,0); +} + +/*********** +* Pie Chart +*/ + +.nvd3.nv-pie path { + stroke-opacity: 0; + transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear; + -moz-transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear; + -webkit-transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear; + +} + +.nvd3.nv-pie .nv-pie-title { + font-size: 24px; + fill: rgba(19, 196, 249, 0.59); +} + +.nvd3.nv-pie .nv-slice text { + stroke: #000; + stroke-width: 0; +} + +.nvd3.nv-pie path { + stroke: #fff; + stroke-width: 1px; + stroke-opacity: 1; +} + +.nvd3.nv-pie .hover path { + fill-opacity: .7; +} +.nvd3.nv-pie .nv-label { + pointer-events: none; +} +.nvd3.nv-pie .nv-label rect { + fill-opacity: 0; + stroke-opacity: 0; +} + +/********** +* Lines +*/ + +.nvd3 .nv-groups path.nv-line { + fill: none; + stroke-width: 1.5px; +} + +.nvd3 .nv-groups path.nv-line.nv-thin-line { + stroke-width: 1px; +} + + +.nvd3 .nv-groups path.nv-area { + stroke: none; +} + +.nvd3 .nv-line.hover path { + stroke-width: 6px; +} + +.nvd3.nv-line .nvd3.nv-scatter .nv-groups .nv-point { + fill-opacity: 0; + stroke-opacity: 0; +} + +.nvd3.nv-scatter.nv-single-point .nv-groups .nv-point { + fill-opacity: .5 !important; + stroke-opacity: .5 !important; +} + + +.with-transitions .nvd3 .nv-groups .nv-point { + transition: stroke-width 250ms linear, stroke-opacity 250ms linear; + -moz-transition: stroke-width 250ms linear, stroke-opacity 250ms linear; + -webkit-transition: stroke-width 250ms linear, stroke-opacity 250ms linear; + +} + +.nvd3.nv-scatter .nv-groups .nv-point.hover, +.nvd3 .nv-groups .nv-point.hover { + stroke-width: 7px; + fill-opacity: .95 !important; + stroke-opacity: .95 !important; +} + + +.nvd3 .nv-point-paths path { + stroke: #aaa; + stroke-opacity: 0; + fill: #eee; + fill-opacity: 0; +} + + + +.nvd3 .nv-indexLine { + cursor: ew-resize; +} + + +/********** +* Distribution +*/ + +.nvd3 .nv-distribution { + pointer-events: none; +} + + +/********** +* Scatter +*/ + +.nvd3 .nv-groups .nv-point.hover { + stroke-width: 20px; + stroke-opacity: .5; +} + +.nvd3 .nv-scatter .nv-point.hover { + fill-opacity: 1; +} + + +/********** +* Stacked Area +*/ + +.nvd3.nv-stackedarea path.nv-area { + fill-opacity: .7; + stroke-opacity: 0; + transition: fill-opacity 250ms linear, stroke-opacity 250ms linear; + -moz-transition: fill-opacity 250ms linear, stroke-opacity 250ms linear; + -webkit-transition: fill-opacity 250ms linear, stroke-opacity 250ms linear; +} + +.nvd3.nv-stackedarea path.nv-area.hover { + fill-opacity: .9; +} + + +.nvd3.nv-stackedarea .nv-groups .nv-point { + stroke-opacity: 0; + fill-opacity: 0; +} + + +/********** +* Line Plus Bar +*/ + +.nvd3.nv-linePlusBar .nv-bar rect { + fill-opacity: .75; +} + +.nvd3.nv-linePlusBar .nv-bar rect:hover { + fill-opacity: 1; +} + + +/********** +* Bullet +*/ + +.nvd3.nv-bullet { font: 10px sans-serif; } +.nvd3.nv-bullet .nv-measure { fill-opacity: .8; } +.nvd3.nv-bullet .nv-measure:hover { fill-opacity: 1; } +.nvd3.nv-bullet .nv-marker { stroke: #000; stroke-width: 2px; } +.nvd3.nv-bullet .nv-markerTriangle { stroke: #000; fill: #fff; stroke-width: 1.5px; } +.nvd3.nv-bullet .nv-tick line { stroke: #666; stroke-width: .5px; } +.nvd3.nv-bullet .nv-range.nv-s0 { fill: #eee; } +.nvd3.nv-bullet .nv-range.nv-s1 { fill: #ddd; } +.nvd3.nv-bullet .nv-range.nv-s2 { fill: #ccc; } +.nvd3.nv-bullet .nv-title { font-size: 14px; font-weight: bold; } +.nvd3.nv-bullet .nv-subtitle { fill: #999; } + + +.nvd3.nv-bullet .nv-range { + fill: #bababa; + fill-opacity: .4; +} +.nvd3.nv-bullet .nv-range:hover { + fill-opacity: .7; +} + + +/********** +* Sparkline +*/ + +.nvd3.nv-sparkline path { + fill: none; +} + +.nvd3.nv-sparklineplus g.nv-hoverValue { + pointer-events: none; +} + +.nvd3.nv-sparklineplus .nv-hoverValue line { + stroke: #333; + stroke-width: 1.5px; + } + +.nvd3.nv-sparklineplus, +.nvd3.nv-sparklineplus g { + pointer-events: all; +} + +.nvd3 .nv-hoverArea { + fill-opacity: 0; + stroke-opacity: 0; +} + +.nvd3.nv-sparklineplus .nv-xValue, +.nvd3.nv-sparklineplus .nv-yValue { + stroke-width: 0; + font-size: .9em; + font-weight: normal; +} + +.nvd3.nv-sparklineplus .nv-yValue { + stroke: #f66; +} + +.nvd3.nv-sparklineplus .nv-maxValue { + stroke: #2ca02c; + fill: #2ca02c; +} + +.nvd3.nv-sparklineplus .nv-minValue { + stroke: #d62728; + fill: #d62728; +} + +.nvd3.nv-sparklineplus .nv-currentValue { + font-weight: bold; + font-size: 1.1em; +} + +/********** +* historical stock +*/ + +.nvd3.nv-ohlcBar .nv-ticks .nv-tick { + stroke-width: 1px; +} + +.nvd3.nv-ohlcBar .nv-ticks .nv-tick.hover { + stroke-width: 2px; +} + +.nvd3.nv-ohlcBar .nv-ticks .nv-tick.positive { + stroke: #2ca02c; +} + +.nvd3.nv-ohlcBar .nv-ticks .nv-tick.negative { + stroke: #d62728; +} + +.nvd3.nv-historicalStockChart .nv-axis .nv-axislabel { + font-weight: bold; +} + +.nvd3.nv-historicalStockChart .nv-dragTarget { + fill-opacity: 0; + stroke: none; + cursor: move; +} + +.nvd3 .nv-brush .extent { + fill-opacity: 0 !important; +} + +.nvd3 .nv-brushBackground rect { + stroke: #000; + stroke-width: .4; + fill: #fff; + fill-opacity: .7; +} + + +/********** +* Parallel Coordinates +*/ + +.nvd3 .background path { + fill: none; + stroke: #EEE; + stroke-opacity: .4; + shape-rendering: crispEdges; +} + +.nvd3 .foreground path { + fill: none; + stroke-opacity: .7; +} + +.nvd3 .brush .extent { + fill-opacity: .3; + stroke: #fff; + shape-rendering: crispEdges; +} + +.nvd3 .axis line, .axis path { + fill: none; + stroke: #000; + shape-rendering: crispEdges; +} + +.nvd3 .axis text { + text-shadow: 0 1px 0 #fff; +} + +/**** +Interactive Layer +*/ +.nvd3 .nv-interactiveGuideLine { + pointer-events:none; +} +.nvd3 line.nv-guideline { + stroke: #ccc; +} \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/images/bulb-off.png b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/images/bulb-off.png new file mode 100755 index 00000000..59f7aea5 Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/images/bulb-off.png differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/images/bulb-on.png b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/images/bulb-on.png new file mode 100755 index 00000000..fc7bae5a Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/images/bulb-on.png differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/images/fan.png b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/images/fan.png new file mode 100755 index 00000000..04fdc33c Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/images/fan.png differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/images/temp.png b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/images/temp.png new file mode 100755 index 00000000..0e0b58ba Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/images/temp.png differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/bulb.js b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/bulb.js new file mode 100755 index 00000000..72c40fd7 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/bulb.js @@ -0,0 +1,10 @@ +function changeImage() { + var image = document.getElementById('myImage'); + if (image.src.match("bulb-on")) { + + image.src = "/iot/public/mydevice/images/bulb-off.png"; + } else { + + image.src = "/iot/public/mydevice/images/bulb-on.png"; + } +} \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/cumulativelinechart.js b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/cumulativelinechart.js new file mode 100755 index 00000000..e69de29b diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/d3.min.js b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/d3.min.js new file mode 100755 index 00000000..99b5c909 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/d3.min.js @@ -0,0 +1,5 @@ +!function(){function n(n,t){return t>n?-1:n>t?1:n>=t?0:0/0}function t(n){return null===n?0/0:+n}function e(n){return!isNaN(n)}function r(n){return{left:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;n(t[i],e)<0?r=i+1:u=i}return r},right:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;n(t[i],e)>0?u=i:r=i+1}return r}}}function u(n){return n.length}function i(n){for(var t=1;n*t%1;)t*=10;return t}function o(n,t){for(var e in t)Object.defineProperty(n.prototype,e,{value:t[e],enumerable:!1})}function a(){this._=Object.create(null)}function c(n){return(n+="")===da||n[0]===ma?ma+n:n}function l(n){return(n+="")[0]===ma?n.slice(1):n}function s(n){return c(n)in this._}function f(n){return(n=c(n))in this._&&delete this._[n]}function h(){var n=[];for(var t in this._)n.push(l(t));return n}function g(){var n=0;for(var t in this._)++n;return n}function p(){for(var n in this._)return!1;return!0}function v(){this._=Object.create(null)}function d(n,t,e){return function(){var r=e.apply(t,arguments);return r===t?n:r}}function m(n,t){if(t in n)return t;t=t.charAt(0).toUpperCase()+t.slice(1);for(var e=0,r=ya.length;r>e;++e){var u=ya[e]+t;if(u in n)return u}}function y(){}function M(){}function x(n){function t(){for(var t,r=e,u=-1,i=r.length;++ue;e++)for(var u,i=n[e],o=0,a=i.length;a>o;o++)(u=i[o])&&t(u,o,e);return n}function O(n){return xa(n,Aa),n}function Y(n){var t,e;return function(r,u,i){var o,a=n[i].update,c=a.length;for(i!=e&&(e=i,t=0),u>=t&&(t=u+1);!(o=a[t])&&++t0&&(n=n.slice(0,a));var l=Ca.get(n);return l&&(n=l,c=V),a?t?u:r:t?y:i}function Z(n,t){return function(e){var r=ta.event;ta.event=e,t[0]=this.__data__;try{n.apply(this,t)}finally{ta.event=r}}}function V(n,t){var e=Z(n,t);return function(n){var t=this,r=n.relatedTarget;r&&(r===t||8&r.compareDocumentPosition(t))||e.call(t,n)}}function X(){var n=".dragsuppress-"+ ++qa,t="click"+n,e=ta.select(oa).on("touchmove"+n,b).on("dragstart"+n,b).on("selectstart"+n,b);if(za){var r=ia.style,u=r[za];r[za]="none"}return function(i){if(e.on(n,null),za&&(r[za]=u),i){var o=function(){e.on(t,null)};e.on(t,function(){b(),o()},!0),setTimeout(o,0)}}}function $(n,t){t.changedTouches&&(t=t.changedTouches[0]);var e=n.ownerSVGElement||n;if(e.createSVGPoint){var r=e.createSVGPoint();if(0>La&&(oa.scrollX||oa.scrollY)){e=ta.select("body").append("svg").style({position:"absolute",top:0,left:0,margin:0,padding:0,border:"none"},"important");var u=e[0][0].getScreenCTM();La=!(u.f||u.e),e.remove()}return La?(r.x=t.pageX,r.y=t.pageY):(r.x=t.clientX,r.y=t.clientY),r=r.matrixTransform(n.getScreenCTM().inverse()),[r.x,r.y]}var i=n.getBoundingClientRect();return[t.clientX-i.left-n.clientLeft,t.clientY-i.top-n.clientTop]}function B(){return ta.event.changedTouches[0].identifier}function W(){return ta.event.target}function J(){return oa}function G(n){return n>0?1:0>n?-1:0}function K(n,t,e){return(t[0]-n[0])*(e[1]-n[1])-(t[1]-n[1])*(e[0]-n[0])}function Q(n){return n>1?0:-1>n?Da:Math.acos(n)}function nt(n){return n>1?ja:-1>n?-ja:Math.asin(n)}function tt(n){return((n=Math.exp(n))-1/n)/2}function et(n){return((n=Math.exp(n))+1/n)/2}function rt(n){return((n=Math.exp(2*n))-1)/(n+1)}function ut(n){return(n=Math.sin(n/2))*n}function it(){}function ot(n,t,e){return this instanceof ot?(this.h=+n,this.s=+t,void(this.l=+e)):arguments.length<2?n instanceof ot?new ot(n.h,n.s,n.l):xt(""+n,bt,ot):new ot(n,t,e)}function at(n,t,e){function r(n){return n>360?n-=360:0>n&&(n+=360),60>n?i+(o-i)*n/60:180>n?o:240>n?i+(o-i)*(240-n)/60:i}function u(n){return Math.round(255*r(n))}var i,o;return n=isNaN(n)?0:(n%=360)<0?n+360:n,t=isNaN(t)?0:0>t?0:t>1?1:t,e=0>e?0:e>1?1:e,o=.5>=e?e*(1+t):e+t-e*t,i=2*e-o,new dt(u(n+120),u(n),u(n-120))}function ct(n,t,e){return this instanceof ct?(this.h=+n,this.c=+t,void(this.l=+e)):arguments.length<2?n instanceof ct?new ct(n.h,n.c,n.l):n instanceof st?ht(n.l,n.a,n.b):ht((n=_t((n=ta.rgb(n)).r,n.g,n.b)).l,n.a,n.b):new ct(n,t,e)}function lt(n,t,e){return isNaN(n)&&(n=0),isNaN(t)&&(t=0),new st(e,Math.cos(n*=Fa)*t,Math.sin(n)*t)}function st(n,t,e){return this instanceof st?(this.l=+n,this.a=+t,void(this.b=+e)):arguments.length<2?n instanceof st?new st(n.l,n.a,n.b):n instanceof ct?lt(n.h,n.c,n.l):_t((n=dt(n)).r,n.g,n.b):new st(n,t,e)}function ft(n,t,e){var r=(n+16)/116,u=r+t/500,i=r-e/200;return u=gt(u)*Ja,r=gt(r)*Ga,i=gt(i)*Ka,new dt(vt(3.2404542*u-1.5371385*r-.4985314*i),vt(-.969266*u+1.8760108*r+.041556*i),vt(.0556434*u-.2040259*r+1.0572252*i))}function ht(n,t,e){return n>0?new ct(Math.atan2(e,t)*Ha,Math.sqrt(t*t+e*e),n):new ct(0/0,0/0,n)}function gt(n){return n>.206893034?n*n*n:(n-4/29)/7.787037}function pt(n){return n>.008856?Math.pow(n,1/3):7.787037*n+4/29}function vt(n){return Math.round(255*(.00304>=n?12.92*n:1.055*Math.pow(n,1/2.4)-.055))}function dt(n,t,e){return this instanceof dt?(this.r=~~n,this.g=~~t,void(this.b=~~e)):arguments.length<2?n instanceof dt?new dt(n.r,n.g,n.b):xt(""+n,dt,at):new dt(n,t,e)}function mt(n){return new dt(n>>16,255&n>>8,255&n)}function yt(n){return mt(n)+""}function Mt(n){return 16>n?"0"+Math.max(0,n).toString(16):Math.min(255,n).toString(16)}function xt(n,t,e){var r,u,i,o=0,a=0,c=0;if(r=/([a-z]+)\((.*)\)/i.exec(n))switch(u=r[2].split(","),r[1]){case"hsl":return e(parseFloat(u[0]),parseFloat(u[1])/100,parseFloat(u[2])/100);case"rgb":return t(St(u[0]),St(u[1]),St(u[2]))}return(i=tc.get(n))?t(i.r,i.g,i.b):(null==n||"#"!==n.charAt(0)||isNaN(i=parseInt(n.slice(1),16))||(4===n.length?(o=(3840&i)>>4,o=o>>4|o,a=240&i,a=a>>4|a,c=15&i,c=c<<4|c):7===n.length&&(o=(16711680&i)>>16,a=(65280&i)>>8,c=255&i)),t(o,a,c))}function bt(n,t,e){var r,u,i=Math.min(n/=255,t/=255,e/=255),o=Math.max(n,t,e),a=o-i,c=(o+i)/2;return a?(u=.5>c?a/(o+i):a/(2-o-i),r=n==o?(t-e)/a+(e>t?6:0):t==o?(e-n)/a+2:(n-t)/a+4,r*=60):(r=0/0,u=c>0&&1>c?0:r),new ot(r,u,c)}function _t(n,t,e){n=wt(n),t=wt(t),e=wt(e);var r=pt((.4124564*n+.3575761*t+.1804375*e)/Ja),u=pt((.2126729*n+.7151522*t+.072175*e)/Ga),i=pt((.0193339*n+.119192*t+.9503041*e)/Ka);return st(116*u-16,500*(r-u),200*(u-i))}function wt(n){return(n/=255)<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4)}function St(n){var t=parseFloat(n);return"%"===n.charAt(n.length-1)?Math.round(2.55*t):t}function kt(n){return"function"==typeof n?n:function(){return n}}function Et(n){return n}function At(n){return function(t,e,r){return 2===arguments.length&&"function"==typeof e&&(r=e,e=null),Nt(t,e,n,r)}}function Nt(n,t,e,r){function u(){var n,t=c.status;if(!t&&zt(c)||t>=200&&300>t||304===t){try{n=e.call(i,c)}catch(r){return o.error.call(i,r),void 0}o.load.call(i,n)}else o.error.call(i,c)}var i={},o=ta.dispatch("beforesend","progress","load","error"),a={},c=new XMLHttpRequest,l=null;return!oa.XDomainRequest||"withCredentials"in c||!/^(http(s)?:)?\/\//.test(n)||(c=new XDomainRequest),"onload"in c?c.onload=c.onerror=u:c.onreadystatechange=function(){c.readyState>3&&u()},c.onprogress=function(n){var t=ta.event;ta.event=n;try{o.progress.call(i,c)}finally{ta.event=t}},i.header=function(n,t){return n=(n+"").toLowerCase(),arguments.length<2?a[n]:(null==t?delete a[n]:a[n]=t+"",i)},i.mimeType=function(n){return arguments.length?(t=null==n?null:n+"",i):t},i.responseType=function(n){return arguments.length?(l=n,i):l},i.response=function(n){return e=n,i},["get","post"].forEach(function(n){i[n]=function(){return i.send.apply(i,[n].concat(ra(arguments)))}}),i.send=function(e,r,u){if(2===arguments.length&&"function"==typeof r&&(u=r,r=null),c.open(e,n,!0),null==t||"accept"in a||(a.accept=t+",*/*"),c.setRequestHeader)for(var s in a)c.setRequestHeader(s,a[s]);return null!=t&&c.overrideMimeType&&c.overrideMimeType(t),null!=l&&(c.responseType=l),null!=u&&i.on("error",u).on("load",function(n){u(null,n)}),o.beforesend.call(i,c),c.send(null==r?null:r),i},i.abort=function(){return c.abort(),i},ta.rebind(i,o,"on"),null==r?i:i.get(Ct(r))}function Ct(n){return 1===n.length?function(t,e){n(null==t?e:null)}:n}function zt(n){var t=n.responseType;return t&&"text"!==t?n.response:n.responseText}function qt(){var n=Lt(),t=Tt()-n;t>24?(isFinite(t)&&(clearTimeout(ic),ic=setTimeout(qt,t)),uc=0):(uc=1,ac(qt))}function Lt(){var n=Date.now();for(oc=ec;oc;)n>=oc.t&&(oc.f=oc.c(n-oc.t)),oc=oc.n;return n}function Tt(){for(var n,t=ec,e=1/0;t;)t.f?t=n?n.n=t.n:ec=t.n:(t.t8?function(n){return n/e}:function(n){return n*e},symbol:n}}function Pt(n){var t=n.decimal,e=n.thousands,r=n.grouping,u=n.currency,i=r&&e?function(n,t){for(var u=n.length,i=[],o=0,a=r[0],c=0;u>0&&a>0&&(c+a+1>t&&(a=Math.max(1,t-c)),i.push(n.substring(u-=a,u+a)),!((c+=a+1)>t));)a=r[o=(o+1)%r.length];return i.reverse().join(e)}:Et;return function(n){var e=lc.exec(n),r=e[1]||" ",o=e[2]||">",a=e[3]||"-",c=e[4]||"",l=e[5],s=+e[6],f=e[7],h=e[8],g=e[9],p=1,v="",d="",m=!1,y=!0;switch(h&&(h=+h.substring(1)),(l||"0"===r&&"="===o)&&(l=r="0",o="="),g){case"n":f=!0,g="g";break;case"%":p=100,d="%",g="f";break;case"p":p=100,d="%",g="r";break;case"b":case"o":case"x":case"X":"#"===c&&(v="0"+g.toLowerCase());case"c":y=!1;case"d":m=!0,h=0;break;case"s":p=-1,g="r"}"$"===c&&(v=u[0],d=u[1]),"r"!=g||h||(g="g"),null!=h&&("g"==g?h=Math.max(1,Math.min(21,h)):("e"==g||"f"==g)&&(h=Math.max(0,Math.min(20,h)))),g=sc.get(g)||Ut;var M=l&&f;return function(n){var e=d;if(m&&n%1)return"";var u=0>n||0===n&&0>1/n?(n=-n,"-"):"-"===a?"":a;if(0>p){var c=ta.formatPrefix(n,h);n=c.scale(n),e=c.symbol+d}else n*=p;n=g(n,h);var x,b,_=n.lastIndexOf(".");if(0>_){var w=y?n.lastIndexOf("e"):-1;0>w?(x=n,b=""):(x=n.substring(0,w),b=n.substring(w))}else x=n.substring(0,_),b=t+n.substring(_+1);!l&&f&&(x=i(x,1/0));var S=v.length+x.length+b.length+(M?0:u.length),k=s>S?new Array(S=s-S+1).join(r):"";return M&&(x=i(k+x,k.length?s-b.length:1/0)),u+=v,n=x+b,("<"===o?u+n+k:">"===o?k+u+n:"^"===o?k.substring(0,S>>=1)+u+n+k.substring(S):u+(M?n:k+n))+e}}}function Ut(n){return n+""}function jt(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function Ft(n,t,e){function r(t){var e=n(t),r=i(e,1);return r-t>t-e?e:r}function u(e){return t(e=n(new hc(e-1)),1),e}function i(n,e){return t(n=new hc(+n),e),n}function o(n,r,i){var o=u(n),a=[];if(i>1)for(;r>o;)e(o)%i||a.push(new Date(+o)),t(o,1);else for(;r>o;)a.push(new Date(+o)),t(o,1);return a}function a(n,t,e){try{hc=jt;var r=new jt;return r._=n,o(r,t,e)}finally{hc=Date}}n.floor=n,n.round=r,n.ceil=u,n.offset=i,n.range=o;var c=n.utc=Ht(n);return c.floor=c,c.round=Ht(r),c.ceil=Ht(u),c.offset=Ht(i),c.range=a,n}function Ht(n){return function(t,e){try{hc=jt;var r=new jt;return r._=t,n(r,e)._}finally{hc=Date}}}function Ot(n){function t(n){function t(t){for(var e,u,i,o=[],a=-1,c=0;++aa;){if(r>=l)return-1;if(u=t.charCodeAt(a++),37===u){if(o=t.charAt(a++),i=C[o in pc?t.charAt(a++):o],!i||(r=i(n,e,r))<0)return-1}else if(u!=e.charCodeAt(r++))return-1}return r}function r(n,t,e){_.lastIndex=0;var r=_.exec(t.slice(e));return r?(n.w=w.get(r[0].toLowerCase()),e+r[0].length):-1}function u(n,t,e){x.lastIndex=0;var r=x.exec(t.slice(e));return r?(n.w=b.get(r[0].toLowerCase()),e+r[0].length):-1}function i(n,t,e){E.lastIndex=0;var r=E.exec(t.slice(e));return r?(n.m=A.get(r[0].toLowerCase()),e+r[0].length):-1}function o(n,t,e){S.lastIndex=0;var r=S.exec(t.slice(e));return r?(n.m=k.get(r[0].toLowerCase()),e+r[0].length):-1}function a(n,t,r){return e(n,N.c.toString(),t,r)}function c(n,t,r){return e(n,N.x.toString(),t,r)}function l(n,t,r){return e(n,N.X.toString(),t,r)}function s(n,t,e){var r=M.get(t.slice(e,e+=2).toLowerCase());return null==r?-1:(n.p=r,e)}var f=n.dateTime,h=n.date,g=n.time,p=n.periods,v=n.days,d=n.shortDays,m=n.months,y=n.shortMonths;t.utc=function(n){function e(n){try{hc=jt;var t=new hc;return t._=n,r(t)}finally{hc=Date}}var r=t(n);return e.parse=function(n){try{hc=jt;var t=r.parse(n);return t&&t._}finally{hc=Date}},e.toString=r.toString,e},t.multi=t.utc.multi=ae;var M=ta.map(),x=It(v),b=Zt(v),_=It(d),w=Zt(d),S=It(m),k=Zt(m),E=It(y),A=Zt(y);p.forEach(function(n,t){M.set(n.toLowerCase(),t)});var N={a:function(n){return d[n.getDay()]},A:function(n){return v[n.getDay()]},b:function(n){return y[n.getMonth()]},B:function(n){return m[n.getMonth()]},c:t(f),d:function(n,t){return Yt(n.getDate(),t,2)},e:function(n,t){return Yt(n.getDate(),t,2)},H:function(n,t){return Yt(n.getHours(),t,2)},I:function(n,t){return Yt(n.getHours()%12||12,t,2)},j:function(n,t){return Yt(1+fc.dayOfYear(n),t,3)},L:function(n,t){return Yt(n.getMilliseconds(),t,3)},m:function(n,t){return Yt(n.getMonth()+1,t,2)},M:function(n,t){return Yt(n.getMinutes(),t,2)},p:function(n){return p[+(n.getHours()>=12)]},S:function(n,t){return Yt(n.getSeconds(),t,2)},U:function(n,t){return Yt(fc.sundayOfYear(n),t,2)},w:function(n){return n.getDay()},W:function(n,t){return Yt(fc.mondayOfYear(n),t,2)},x:t(h),X:t(g),y:function(n,t){return Yt(n.getFullYear()%100,t,2)},Y:function(n,t){return Yt(n.getFullYear()%1e4,t,4)},Z:ie,"%":function(){return"%"}},C={a:r,A:u,b:i,B:o,c:a,d:Qt,e:Qt,H:te,I:te,j:ne,L:ue,m:Kt,M:ee,p:s,S:re,U:Xt,w:Vt,W:$t,x:c,X:l,y:Wt,Y:Bt,Z:Jt,"%":oe};return t}function Yt(n,t,e){var r=0>n?"-":"",u=(r?-n:n)+"",i=u.length;return r+(e>i?new Array(e-i+1).join(t)+u:u)}function It(n){return new RegExp("^(?:"+n.map(ta.requote).join("|")+")","i")}function Zt(n){for(var t=new a,e=-1,r=n.length;++e68?1900:2e3)}function Kt(n,t,e){vc.lastIndex=0;var r=vc.exec(t.slice(e,e+2));return r?(n.m=r[0]-1,e+r[0].length):-1}function Qt(n,t,e){vc.lastIndex=0;var r=vc.exec(t.slice(e,e+2));return r?(n.d=+r[0],e+r[0].length):-1}function ne(n,t,e){vc.lastIndex=0;var r=vc.exec(t.slice(e,e+3));return r?(n.j=+r[0],e+r[0].length):-1}function te(n,t,e){vc.lastIndex=0;var r=vc.exec(t.slice(e,e+2));return r?(n.H=+r[0],e+r[0].length):-1}function ee(n,t,e){vc.lastIndex=0;var r=vc.exec(t.slice(e,e+2));return r?(n.M=+r[0],e+r[0].length):-1}function re(n,t,e){vc.lastIndex=0;var r=vc.exec(t.slice(e,e+2));return r?(n.S=+r[0],e+r[0].length):-1}function ue(n,t,e){vc.lastIndex=0;var r=vc.exec(t.slice(e,e+3));return r?(n.L=+r[0],e+r[0].length):-1}function ie(n){var t=n.getTimezoneOffset(),e=t>0?"-":"+",r=0|va(t)/60,u=va(t)%60;return e+Yt(r,"0",2)+Yt(u,"0",2)}function oe(n,t,e){dc.lastIndex=0;var r=dc.exec(t.slice(e,e+1));return r?e+r[0].length:-1}function ae(n){for(var t=n.length,e=-1;++e=0?1:-1,a=o*e,c=Math.cos(t),l=Math.sin(t),s=i*l,f=u*c+s*Math.cos(a),h=s*o*Math.sin(a);_c.add(Math.atan2(h,f)),r=n,u=c,i=l}var t,e,r,u,i;wc.point=function(o,a){wc.point=n,r=(t=o)*Fa,u=Math.cos(a=(e=a)*Fa/2+Da/4),i=Math.sin(a)},wc.lineEnd=function(){n(t,e)}}function pe(n){var t=n[0],e=n[1],r=Math.cos(e);return[r*Math.cos(t),r*Math.sin(t),Math.sin(e)]}function ve(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]}function de(n,t){return[n[1]*t[2]-n[2]*t[1],n[2]*t[0]-n[0]*t[2],n[0]*t[1]-n[1]*t[0]]}function me(n,t){n[0]+=t[0],n[1]+=t[1],n[2]+=t[2]}function ye(n,t){return[n[0]*t,n[1]*t,n[2]*t]}function Me(n){var t=Math.sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);n[0]/=t,n[1]/=t,n[2]/=t}function xe(n){return[Math.atan2(n[1],n[0]),nt(n[2])]}function be(n,t){return va(n[0]-t[0])a;++a)u.point((e=n[a])[0],e[1]);return u.lineEnd(),void 0}var c=new qe(e,n,null,!0),l=new qe(e,null,c,!1);c.o=l,i.push(c),o.push(l),c=new qe(r,n,null,!1),l=new qe(r,null,c,!0),c.o=l,i.push(c),o.push(l)}}),o.sort(t),ze(i),ze(o),i.length){for(var a=0,c=e,l=o.length;l>a;++a)o[a].e=c=!c;for(var s,f,h=i[0];;){for(var g=h,p=!0;g.v;)if((g=g.n)===h)return;s=g.z,u.lineStart();do{if(g.v=g.o.v=!0,g.e){if(p)for(var a=0,l=s.length;l>a;++a)u.point((f=s[a])[0],f[1]);else r(g.x,g.n.x,1,u);g=g.n}else{if(p){s=g.p.z;for(var a=s.length-1;a>=0;--a)u.point((f=s[a])[0],f[1])}else r(g.x,g.p.x,-1,u);g=g.p}g=g.o,s=g.z,p=!p}while(!g.v);u.lineEnd()}}}function ze(n){if(t=n.length){for(var t,e,r=0,u=n[0];++r0){for(b||(i.polygonStart(),b=!0),i.lineStart();++o1&&2&t&&e.push(e.pop().concat(e.shift())),g.push(e.filter(Te))}var g,p,v,d=t(i),m=u.invert(r[0],r[1]),y={point:o,lineStart:c,lineEnd:l,polygonStart:function(){y.point=s,y.lineStart=f,y.lineEnd=h,g=[],p=[]},polygonEnd:function(){y.point=o,y.lineStart=c,y.lineEnd=l,g=ta.merge(g);var n=Fe(m,p);g.length?(b||(i.polygonStart(),b=!0),Ce(g,De,n,e,i)):n&&(b||(i.polygonStart(),b=!0),i.lineStart(),e(null,null,1,i),i.lineEnd()),b&&(i.polygonEnd(),b=!1),g=p=null},sphere:function(){i.polygonStart(),i.lineStart(),e(null,null,1,i),i.lineEnd(),i.polygonEnd()}},M=Re(),x=t(M),b=!1;return y}}function Te(n){return n.length>1}function Re(){var n,t=[];return{lineStart:function(){t.push(n=[])},point:function(t,e){n.push([t,e])},lineEnd:y,buffer:function(){var e=t;return t=[],n=null,e},rejoin:function(){t.length>1&&t.push(t.pop().concat(t.shift()))}}}function De(n,t){return((n=n.x)[0]<0?n[1]-ja-Ta:ja-n[1])-((t=t.x)[0]<0?t[1]-ja-Ta:ja-t[1])}function Pe(n){var t,e=0/0,r=0/0,u=0/0;return{lineStart:function(){n.lineStart(),t=1},point:function(i,o){var a=i>0?Da:-Da,c=va(i-e);va(c-Da)0?ja:-ja),n.point(u,r),n.lineEnd(),n.lineStart(),n.point(a,r),n.point(i,r),t=0):u!==a&&c>=Da&&(va(e-u)Ta?Math.atan((Math.sin(t)*(i=Math.cos(r))*Math.sin(e)-Math.sin(r)*(u=Math.cos(t))*Math.sin(n))/(u*i*o)):(t+r)/2}function je(n,t,e,r){var u;if(null==n)u=e*ja,r.point(-Da,u),r.point(0,u),r.point(Da,u),r.point(Da,0),r.point(Da,-u),r.point(0,-u),r.point(-Da,-u),r.point(-Da,0),r.point(-Da,u);else if(va(n[0]-t[0])>Ta){var i=n[0]a;++a){var l=t[a],s=l.length;if(s)for(var f=l[0],h=f[0],g=f[1]/2+Da/4,p=Math.sin(g),v=Math.cos(g),d=1;;){d===s&&(d=0),n=l[d];var m=n[0],y=n[1]/2+Da/4,M=Math.sin(y),x=Math.cos(y),b=m-h,_=b>=0?1:-1,w=_*b,S=w>Da,k=p*M;if(_c.add(Math.atan2(k*_*Math.sin(w),v*x+k*Math.cos(w))),i+=S?b+_*Pa:b,S^h>=e^m>=e){var E=de(pe(f),pe(n));Me(E);var A=de(u,E);Me(A);var N=(S^b>=0?-1:1)*nt(A[2]);(r>N||r===N&&(E[0]||E[1]))&&(o+=S^b>=0?1:-1)}if(!d++)break;h=m,p=M,v=x,f=n}}return(-Ta>i||Ta>i&&0>_c)^1&o}function He(n){function t(n,t){return Math.cos(n)*Math.cos(t)>i}function e(n){var e,i,c,l,s;return{lineStart:function(){l=c=!1,s=1},point:function(f,h){var g,p=[f,h],v=t(f,h),d=o?v?0:u(f,h):v?u(f+(0>f?Da:-Da),h):0;if(!e&&(l=c=v)&&n.lineStart(),v!==c&&(g=r(e,p),(be(e,g)||be(p,g))&&(p[0]+=Ta,p[1]+=Ta,v=t(p[0],p[1]))),v!==c)s=0,v?(n.lineStart(),g=r(p,e),n.point(g[0],g[1])):(g=r(e,p),n.point(g[0],g[1]),n.lineEnd()),e=g;else if(a&&e&&o^v){var m;d&i||!(m=r(p,e,!0))||(s=0,o?(n.lineStart(),n.point(m[0][0],m[0][1]),n.point(m[1][0],m[1][1]),n.lineEnd()):(n.point(m[1][0],m[1][1]),n.lineEnd(),n.lineStart(),n.point(m[0][0],m[0][1])))}!v||e&&be(e,p)||n.point(p[0],p[1]),e=p,c=v,i=d},lineEnd:function(){c&&n.lineEnd(),e=null},clean:function(){return s|(l&&c)<<1}}}function r(n,t,e){var r=pe(n),u=pe(t),o=[1,0,0],a=de(r,u),c=ve(a,a),l=a[0],s=c-l*l;if(!s)return!e&&n;var f=i*c/s,h=-i*l/s,g=de(o,a),p=ye(o,f),v=ye(a,h);me(p,v);var d=g,m=ve(p,d),y=ve(d,d),M=m*m-y*(ve(p,p)-1);if(!(0>M)){var x=Math.sqrt(M),b=ye(d,(-m-x)/y);if(me(b,p),b=xe(b),!e)return b;var _,w=n[0],S=t[0],k=n[1],E=t[1];w>S&&(_=w,w=S,S=_);var A=S-w,N=va(A-Da)A;if(!N&&k>E&&(_=k,k=E,E=_),C?N?k+E>0^b[1]<(va(b[0]-w)Da^(w<=b[0]&&b[0]<=S)){var z=ye(d,(-m+x)/y);return me(z,p),[b,xe(z)]}}}function u(t,e){var r=o?n:Da-n,u=0;return-r>t?u|=1:t>r&&(u|=2),-r>e?u|=4:e>r&&(u|=8),u}var i=Math.cos(n),o=i>0,a=va(i)>Ta,c=gr(n,6*Fa);return Le(t,e,c,o?[0,-n]:[-Da,n-Da])}function Oe(n,t,e,r){return function(u){var i,o=u.a,a=u.b,c=o.x,l=o.y,s=a.x,f=a.y,h=0,g=1,p=s-c,v=f-l;if(i=n-c,p||!(i>0)){if(i/=p,0>p){if(h>i)return;g>i&&(g=i)}else if(p>0){if(i>g)return;i>h&&(h=i)}if(i=e-c,p||!(0>i)){if(i/=p,0>p){if(i>g)return;i>h&&(h=i)}else if(p>0){if(h>i)return;g>i&&(g=i)}if(i=t-l,v||!(i>0)){if(i/=v,0>v){if(h>i)return;g>i&&(g=i)}else if(v>0){if(i>g)return;i>h&&(h=i)}if(i=r-l,v||!(0>i)){if(i/=v,0>v){if(i>g)return;i>h&&(h=i)}else if(v>0){if(h>i)return;g>i&&(g=i)}return h>0&&(u.a={x:c+h*p,y:l+h*v}),1>g&&(u.b={x:c+g*p,y:l+g*v}),u}}}}}}function Ye(n,t,e,r){function u(r,u){return va(r[0]-n)0?0:3:va(r[0]-e)0?2:1:va(r[1]-t)0?1:0:u>0?3:2}function i(n,t){return o(n.x,t.x)}function o(n,t){var e=u(n,1),r=u(t,1);return e!==r?e-r:0===e?t[1]-n[1]:1===e?n[0]-t[0]:2===e?n[1]-t[1]:t[0]-n[0]}return function(a){function c(n){for(var t=0,e=d.length,r=n[1],u=0;e>u;++u)for(var i,o=1,a=d[u],c=a.length,l=a[0];c>o;++o)i=a[o],l[1]<=r?i[1]>r&&K(l,i,n)>0&&++t:i[1]<=r&&K(l,i,n)<0&&--t,l=i;return 0!==t}function l(i,a,c,l){var s=0,f=0;if(null==i||(s=u(i,c))!==(f=u(a,c))||o(i,a)<0^c>0){do l.point(0===s||3===s?n:e,s>1?r:t);while((s=(s+c+4)%4)!==f)}else l.point(a[0],a[1])}function s(u,i){return u>=n&&e>=u&&i>=t&&r>=i}function f(n,t){s(n,t)&&a.point(n,t)}function h(){C.point=p,d&&d.push(m=[]),S=!0,w=!1,b=_=0/0}function g(){v&&(p(y,M),x&&w&&A.rejoin(),v.push(A.buffer())),C.point=f,w&&a.lineEnd()}function p(n,t){n=Math.max(-Uc,Math.min(Uc,n)),t=Math.max(-Uc,Math.min(Uc,t));var e=s(n,t);if(d&&m.push([n,t]),S)y=n,M=t,x=e,S=!1,e&&(a.lineStart(),a.point(n,t));else if(e&&w)a.point(n,t);else{var r={a:{x:b,y:_},b:{x:n,y:t}};N(r)?(w||(a.lineStart(),a.point(r.a.x,r.a.y)),a.point(r.b.x,r.b.y),e||a.lineEnd(),k=!1):e&&(a.lineStart(),a.point(n,t),k=!1)}b=n,_=t,w=e}var v,d,m,y,M,x,b,_,w,S,k,E=a,A=Re(),N=Oe(n,t,e,r),C={point:f,lineStart:h,lineEnd:g,polygonStart:function(){a=A,v=[],d=[],k=!0},polygonEnd:function(){a=E,v=ta.merge(v);var t=c([n,r]),e=k&&t,u=v.length;(e||u)&&(a.polygonStart(),e&&(a.lineStart(),l(null,null,1,a),a.lineEnd()),u&&Ce(v,i,t,l,a),a.polygonEnd()),v=d=m=null}};return C}}function Ie(n){var t=0,e=Da/3,r=ir(n),u=r(t,e);return u.parallels=function(n){return arguments.length?r(t=n[0]*Da/180,e=n[1]*Da/180):[180*(t/Da),180*(e/Da)]},u}function Ze(n,t){function e(n,t){var e=Math.sqrt(i-2*u*Math.sin(t))/u;return[e*Math.sin(n*=u),o-e*Math.cos(n)]}var r=Math.sin(n),u=(r+Math.sin(t))/2,i=1+r*(2*u-r),o=Math.sqrt(i)/u;return e.invert=function(n,t){var e=o-t;return[Math.atan2(n,e)/u,nt((i-(n*n+e*e)*u*u)/(2*u))]},e}function Ve(){function n(n,t){Fc+=u*n-r*t,r=n,u=t}var t,e,r,u;Zc.point=function(i,o){Zc.point=n,t=r=i,e=u=o},Zc.lineEnd=function(){n(t,e)}}function Xe(n,t){Hc>n&&(Hc=n),n>Yc&&(Yc=n),Oc>t&&(Oc=t),t>Ic&&(Ic=t)}function $e(){function n(n,t){o.push("M",n,",",t,i)}function t(n,t){o.push("M",n,",",t),a.point=e}function e(n,t){o.push("L",n,",",t)}function r(){a.point=n}function u(){o.push("Z")}var i=Be(4.5),o=[],a={point:n,lineStart:function(){a.point=t},lineEnd:r,polygonStart:function(){a.lineEnd=u},polygonEnd:function(){a.lineEnd=r,a.point=n},pointRadius:function(n){return i=Be(n),a},result:function(){if(o.length){var n=o.join("");return o=[],n}}};return a}function Be(n){return"m0,"+n+"a"+n+","+n+" 0 1,1 0,"+-2*n+"a"+n+","+n+" 0 1,1 0,"+2*n+"z"}function We(n,t){Ec+=n,Ac+=t,++Nc}function Je(){function n(n,r){var u=n-t,i=r-e,o=Math.sqrt(u*u+i*i);Cc+=o*(t+n)/2,zc+=o*(e+r)/2,qc+=o,We(t=n,e=r)}var t,e;Xc.point=function(r,u){Xc.point=n,We(t=r,e=u)}}function Ge(){Xc.point=We}function Ke(){function n(n,t){var e=n-r,i=t-u,o=Math.sqrt(e*e+i*i);Cc+=o*(r+n)/2,zc+=o*(u+t)/2,qc+=o,o=u*n-r*t,Lc+=o*(r+n),Tc+=o*(u+t),Rc+=3*o,We(r=n,u=t)}var t,e,r,u;Xc.point=function(i,o){Xc.point=n,We(t=r=i,e=u=o)},Xc.lineEnd=function(){n(t,e)}}function Qe(n){function t(t,e){n.moveTo(t+o,e),n.arc(t,e,o,0,Pa)}function e(t,e){n.moveTo(t,e),a.point=r}function r(t,e){n.lineTo(t,e)}function u(){a.point=t}function i(){n.closePath()}var o=4.5,a={point:t,lineStart:function(){a.point=e},lineEnd:u,polygonStart:function(){a.lineEnd=i},polygonEnd:function(){a.lineEnd=u,a.point=t},pointRadius:function(n){return o=n,a},result:y};return a}function nr(n){function t(n){return(a?r:e)(n)}function e(t){return rr(t,function(e,r){e=n(e,r),t.point(e[0],e[1])})}function r(t){function e(e,r){e=n(e,r),t.point(e[0],e[1])}function r(){M=0/0,S.point=i,t.lineStart()}function i(e,r){var i=pe([e,r]),o=n(e,r);u(M,x,y,b,_,w,M=o[0],x=o[1],y=e,b=i[0],_=i[1],w=i[2],a,t),t.point(M,x)}function o(){S.point=e,t.lineEnd()}function c(){r(),S.point=l,S.lineEnd=s}function l(n,t){i(f=n,h=t),g=M,p=x,v=b,d=_,m=w,S.point=i}function s(){u(M,x,y,b,_,w,g,p,f,v,d,m,a,t),S.lineEnd=o,o()}var f,h,g,p,v,d,m,y,M,x,b,_,w,S={point:e,lineStart:r,lineEnd:o,polygonStart:function(){t.polygonStart(),S.lineStart=c},polygonEnd:function(){t.polygonEnd(),S.lineStart=r}};return S}function u(t,e,r,a,c,l,s,f,h,g,p,v,d,m){var y=s-t,M=f-e,x=y*y+M*M;if(x>4*i&&d--){var b=a+g,_=c+p,w=l+v,S=Math.sqrt(b*b+_*_+w*w),k=Math.asin(w/=S),E=va(va(w)-1)i||va((y*z+M*q)/x-.5)>.3||o>a*g+c*p+l*v)&&(u(t,e,r,a,c,l,N,C,E,b/=S,_/=S,w,d,m),m.point(N,C),u(N,C,E,b,_,w,s,f,h,g,p,v,d,m))}}var i=.5,o=Math.cos(30*Fa),a=16;return t.precision=function(n){return arguments.length?(a=(i=n*n)>0&&16,t):Math.sqrt(i)},t}function tr(n){var t=nr(function(t,e){return n([t*Ha,e*Ha])});return function(n){return or(t(n))}}function er(n){this.stream=n}function rr(n,t){return{point:t,sphere:function(){n.sphere()},lineStart:function(){n.lineStart()},lineEnd:function(){n.lineEnd()},polygonStart:function(){n.polygonStart()},polygonEnd:function(){n.polygonEnd()}}}function ur(n){return ir(function(){return n})()}function ir(n){function t(n){return n=a(n[0]*Fa,n[1]*Fa),[n[0]*h+c,l-n[1]*h]}function e(n){return n=a.invert((n[0]-c)/h,(l-n[1])/h),n&&[n[0]*Ha,n[1]*Ha]}function r(){a=Ae(o=lr(m,y,M),i);var n=i(v,d);return c=g-n[0]*h,l=p+n[1]*h,u()}function u(){return s&&(s.valid=!1,s=null),t}var i,o,a,c,l,s,f=nr(function(n,t){return n=i(n,t),[n[0]*h+c,l-n[1]*h]}),h=150,g=480,p=250,v=0,d=0,m=0,y=0,M=0,x=Pc,b=Et,_=null,w=null;return t.stream=function(n){return s&&(s.valid=!1),s=or(x(o,f(b(n)))),s.valid=!0,s},t.clipAngle=function(n){return arguments.length?(x=null==n?(_=n,Pc):He((_=+n)*Fa),u()):_},t.clipExtent=function(n){return arguments.length?(w=n,b=n?Ye(n[0][0],n[0][1],n[1][0],n[1][1]):Et,u()):w},t.scale=function(n){return arguments.length?(h=+n,r()):h},t.translate=function(n){return arguments.length?(g=+n[0],p=+n[1],r()):[g,p]},t.center=function(n){return arguments.length?(v=n[0]%360*Fa,d=n[1]%360*Fa,r()):[v*Ha,d*Ha]},t.rotate=function(n){return arguments.length?(m=n[0]%360*Fa,y=n[1]%360*Fa,M=n.length>2?n[2]%360*Fa:0,r()):[m*Ha,y*Ha,M*Ha]},ta.rebind(t,f,"precision"),function(){return i=n.apply(this,arguments),t.invert=i.invert&&e,r()}}function or(n){return rr(n,function(t,e){n.point(t*Fa,e*Fa)})}function ar(n,t){return[n,t]}function cr(n,t){return[n>Da?n-Pa:-Da>n?n+Pa:n,t]}function lr(n,t,e){return n?t||e?Ae(fr(n),hr(t,e)):fr(n):t||e?hr(t,e):cr}function sr(n){return function(t,e){return t+=n,[t>Da?t-Pa:-Da>t?t+Pa:t,e]}}function fr(n){var t=sr(n);return t.invert=sr(-n),t}function hr(n,t){function e(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,l=Math.sin(t),s=l*r+a*u;return[Math.atan2(c*i-s*o,a*r-l*u),nt(s*i+c*o)]}var r=Math.cos(n),u=Math.sin(n),i=Math.cos(t),o=Math.sin(t);return e.invert=function(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,l=Math.sin(t),s=l*i-c*o;return[Math.atan2(c*i+l*o,a*r+s*u),nt(s*r-a*u)]},e}function gr(n,t){var e=Math.cos(n),r=Math.sin(n);return function(u,i,o,a){var c=o*t;null!=u?(u=pr(e,u),i=pr(e,i),(o>0?i>u:u>i)&&(u+=o*Pa)):(u=n+o*Pa,i=n-.5*c);for(var l,s=u;o>0?s>i:i>s;s-=c)a.point((l=xe([e,-r*Math.cos(s),-r*Math.sin(s)]))[0],l[1])}}function pr(n,t){var e=pe(t);e[0]-=n,Me(e);var r=Q(-e[1]);return((-e[2]<0?-r:r)+2*Math.PI-Ta)%(2*Math.PI)}function vr(n,t,e){var r=ta.range(n,t-Ta,e).concat(t);return function(n){return r.map(function(t){return[n,t]})}}function dr(n,t,e){var r=ta.range(n,t-Ta,e).concat(t);return function(n){return r.map(function(t){return[t,n]})}}function mr(n){return n.source}function yr(n){return n.target}function Mr(n,t,e,r){var u=Math.cos(t),i=Math.sin(t),o=Math.cos(r),a=Math.sin(r),c=u*Math.cos(n),l=u*Math.sin(n),s=o*Math.cos(e),f=o*Math.sin(e),h=2*Math.asin(Math.sqrt(ut(r-t)+u*o*ut(e-n))),g=1/Math.sin(h),p=h?function(n){var t=Math.sin(n*=h)*g,e=Math.sin(h-n)*g,r=e*c+t*s,u=e*l+t*f,o=e*i+t*a;return[Math.atan2(u,r)*Ha,Math.atan2(o,Math.sqrt(r*r+u*u))*Ha]}:function(){return[n*Ha,t*Ha]};return p.distance=h,p}function xr(){function n(n,u){var i=Math.sin(u*=Fa),o=Math.cos(u),a=va((n*=Fa)-t),c=Math.cos(a);$c+=Math.atan2(Math.sqrt((a=o*Math.sin(a))*a+(a=r*i-e*o*c)*a),e*i+r*o*c),t=n,e=i,r=o}var t,e,r;Bc.point=function(u,i){t=u*Fa,e=Math.sin(i*=Fa),r=Math.cos(i),Bc.point=n},Bc.lineEnd=function(){Bc.point=Bc.lineEnd=y}}function br(n,t){function e(t,e){var r=Math.cos(t),u=Math.cos(e),i=n(r*u);return[i*u*Math.sin(t),i*Math.sin(e)]}return e.invert=function(n,e){var r=Math.sqrt(n*n+e*e),u=t(r),i=Math.sin(u),o=Math.cos(u);return[Math.atan2(n*i,r*o),Math.asin(r&&e*i/r)]},e}function _r(n,t){function e(n,t){o>0?-ja+Ta>t&&(t=-ja+Ta):t>ja-Ta&&(t=ja-Ta);var e=o/Math.pow(u(t),i);return[e*Math.sin(i*n),o-e*Math.cos(i*n)]}var r=Math.cos(n),u=function(n){return Math.tan(Da/4+n/2)},i=n===t?Math.sin(n):Math.log(r/Math.cos(t))/Math.log(u(t)/u(n)),o=r*Math.pow(u(n),i)/i;return i?(e.invert=function(n,t){var e=o-t,r=G(i)*Math.sqrt(n*n+e*e);return[Math.atan2(n,e)/i,2*Math.atan(Math.pow(o/r,1/i))-ja]},e):Sr}function wr(n,t){function e(n,t){var e=i-t;return[e*Math.sin(u*n),i-e*Math.cos(u*n)]}var r=Math.cos(n),u=n===t?Math.sin(n):(r-Math.cos(t))/(t-n),i=r/u+n;return va(u)u;u++){for(;r>1&&K(n[e[r-2]],n[e[r-1]],n[u])<=0;)--r;e[r++]=u}return e.slice(0,r)}function zr(n,t){return n[0]-t[0]||n[1]-t[1]}function qr(n,t,e){return(e[0]-t[0])*(n[1]-t[1])<(e[1]-t[1])*(n[0]-t[0])}function Lr(n,t,e,r){var u=n[0],i=e[0],o=t[0]-u,a=r[0]-i,c=n[1],l=e[1],s=t[1]-c,f=r[1]-l,h=(a*(c-l)-f*(u-i))/(f*o-a*s);return[u+h*o,c+h*s]}function Tr(n){var t=n[0],e=n[n.length-1];return!(t[0]-e[0]||t[1]-e[1])}function Rr(){tu(this),this.edge=this.site=this.circle=null}function Dr(n){var t=ol.pop()||new Rr;return t.site=n,t}function Pr(n){Xr(n),rl.remove(n),ol.push(n),tu(n)}function Ur(n){var t=n.circle,e=t.x,r=t.cy,u={x:e,y:r},i=n.P,o=n.N,a=[n];Pr(n);for(var c=i;c.circle&&va(e-c.circle.x)s;++s)l=a[s],c=a[s-1],Kr(l.edge,c.site,l.site,u);c=a[0],l=a[f-1],l.edge=Jr(c.site,l.site,null,u),Vr(c),Vr(l)}function jr(n){for(var t,e,r,u,i=n.x,o=n.y,a=rl._;a;)if(r=Fr(a,o)-i,r>Ta)a=a.L;else{if(u=i-Hr(a,o),!(u>Ta)){r>-Ta?(t=a.P,e=a):u>-Ta?(t=a,e=a.N):t=e=a;break}if(!a.R){t=a;break}a=a.R}var c=Dr(n);if(rl.insert(t,c),t||e){if(t===e)return Xr(t),e=Dr(t.site),rl.insert(c,e),c.edge=e.edge=Jr(t.site,c.site),Vr(t),Vr(e),void 0;if(!e)return c.edge=Jr(t.site,c.site),void 0;Xr(t),Xr(e);var l=t.site,s=l.x,f=l.y,h=n.x-s,g=n.y-f,p=e.site,v=p.x-s,d=p.y-f,m=2*(h*d-g*v),y=h*h+g*g,M=v*v+d*d,x={x:(d*y-g*M)/m+s,y:(h*M-v*y)/m+f};Kr(e.edge,l,p,x),c.edge=Jr(l,n,null,x),e.edge=Jr(n,p,null,x),Vr(t),Vr(e)}}function Fr(n,t){var e=n.site,r=e.x,u=e.y,i=u-t;if(!i)return r;var o=n.P;if(!o)return-1/0;e=o.site;var a=e.x,c=e.y,l=c-t;if(!l)return a;var s=a-r,f=1/i-1/l,h=s/l;return f?(-h+Math.sqrt(h*h-2*f*(s*s/(-2*l)-c+l/2+u-i/2)))/f+r:(r+a)/2}function Hr(n,t){var e=n.N;if(e)return Fr(e,t);var r=n.site;return r.y===t?r.x:1/0}function Or(n){this.site=n,this.edges=[]}function Yr(n){for(var t,e,r,u,i,o,a,c,l,s,f=n[0][0],h=n[1][0],g=n[0][1],p=n[1][1],v=el,d=v.length;d--;)if(i=v[d],i&&i.prepare())for(a=i.edges,c=a.length,o=0;c>o;)s=a[o].end(),r=s.x,u=s.y,l=a[++o%c].start(),t=l.x,e=l.y,(va(r-t)>Ta||va(u-e)>Ta)&&(a.splice(o,0,new Qr(Gr(i.site,s,va(r-f)Ta?{x:f,y:va(t-f)Ta?{x:va(e-p)Ta?{x:h,y:va(t-h)Ta?{x:va(e-g)=-Ra)){var g=c*c+l*l,p=s*s+f*f,v=(f*g-l*p)/h,d=(c*p-s*g)/h,f=d+a,m=al.pop()||new Zr;m.arc=n,m.site=u,m.x=v+o,m.y=f+Math.sqrt(v*v+d*d),m.cy=f,n.circle=m;for(var y=null,M=il._;M;)if(m.yd||d>=a)return;if(h>p){if(i){if(i.y>=l)return}else i={x:d,y:c};e={x:d,y:l}}else{if(i){if(i.yr||r>1)if(h>p){if(i){if(i.y>=l)return}else i={x:(c-u)/r,y:c};e={x:(l-u)/r,y:l}}else{if(i){if(i.yg){if(i){if(i.x>=a)return}else i={x:o,y:r*o+u};e={x:a,y:r*a+u}}else{if(i){if(i.xi||f>o||r>h||u>g)){if(p=n.point){var p,v=t-p[0],d=e-p[1],m=v*v+d*d;if(c>m){var y=Math.sqrt(c=m);r=t-y,u=e-y,i=t+y,o=e+y,a=p}}for(var M=n.nodes,x=.5*(s+h),b=.5*(f+g),_=t>=x,w=e>=b,S=w<<1|_,k=S+4;k>S;++S)if(n=M[3&S])switch(3&S){case 0:l(n,s,f,x,b);break;case 1:l(n,x,f,h,b);break;case 2:l(n,s,b,x,g);break;case 3:l(n,x,b,h,g)}}}(n,r,u,i,o),a}function gu(n,t){n=ta.rgb(n),t=ta.rgb(t);var e=n.r,r=n.g,u=n.b,i=t.r-e,o=t.g-r,a=t.b-u;return function(n){return"#"+Mt(Math.round(e+i*n))+Mt(Math.round(r+o*n))+Mt(Math.round(u+a*n))}}function pu(n,t){var e,r={},u={};for(e in n)e in t?r[e]=mu(n[e],t[e]):u[e]=n[e];for(e in t)e in n||(u[e]=t[e]);return function(n){for(e in r)u[e]=r[e](n);return u}}function vu(n,t){return n=+n,t=+t,function(e){return n*(1-e)+t*e}}function du(n,t){var e,r,u,i=ll.lastIndex=sl.lastIndex=0,o=-1,a=[],c=[];for(n+="",t+="";(e=ll.exec(n))&&(r=sl.exec(t));)(u=r.index)>i&&(u=t.slice(i,u),a[o]?a[o]+=u:a[++o]=u),(e=e[0])===(r=r[0])?a[o]?a[o]+=r:a[++o]=r:(a[++o]=null,c.push({i:o,x:vu(e,r)})),i=sl.lastIndex;return ir;++r)a[(e=c[r]).i]=e.x(n);return a.join("")})}function mu(n,t){for(var e,r=ta.interpolators.length;--r>=0&&!(e=ta.interpolators[r](n,t)););return e}function yu(n,t){var e,r=[],u=[],i=n.length,o=t.length,a=Math.min(n.length,t.length);for(e=0;a>e;++e)r.push(mu(n[e],t[e]));for(;i>e;++e)u[e]=n[e];for(;o>e;++e)u[e]=t[e];return function(n){for(e=0;a>e;++e)u[e]=r[e](n);return u}}function Mu(n){return function(t){return 0>=t?0:t>=1?1:n(t)}}function xu(n){return function(t){return 1-n(1-t)}}function bu(n){return function(t){return.5*(.5>t?n(2*t):2-n(2-2*t))}}function _u(n){return n*n}function wu(n){return n*n*n}function Su(n){if(0>=n)return 0;if(n>=1)return 1;var t=n*n,e=t*n;return 4*(.5>n?e:3*(n-t)+e-.75)}function ku(n){return function(t){return Math.pow(t,n)}}function Eu(n){return 1-Math.cos(n*ja)}function Au(n){return Math.pow(2,10*(n-1))}function Nu(n){return 1-Math.sqrt(1-n*n)}function Cu(n,t){var e;return arguments.length<2&&(t=.45),arguments.length?e=t/Pa*Math.asin(1/n):(n=1,e=t/4),function(r){return 1+n*Math.pow(2,-10*r)*Math.sin((r-e)*Pa/t)}}function zu(n){return n||(n=1.70158),function(t){return t*t*((n+1)*t-n)}}function qu(n){return 1/2.75>n?7.5625*n*n:2/2.75>n?7.5625*(n-=1.5/2.75)*n+.75:2.5/2.75>n?7.5625*(n-=2.25/2.75)*n+.9375:7.5625*(n-=2.625/2.75)*n+.984375}function Lu(n,t){n=ta.hcl(n),t=ta.hcl(t);var e=n.h,r=n.c,u=n.l,i=t.h-e,o=t.c-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.c:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return lt(e+i*n,r+o*n,u+a*n)+""}}function Tu(n,t){n=ta.hsl(n),t=ta.hsl(t);var e=n.h,r=n.s,u=n.l,i=t.h-e,o=t.s-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.s:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return at(e+i*n,r+o*n,u+a*n)+""}}function Ru(n,t){n=ta.lab(n),t=ta.lab(t);var e=n.l,r=n.a,u=n.b,i=t.l-e,o=t.a-r,a=t.b-u;return function(n){return ft(e+i*n,r+o*n,u+a*n)+""}}function Du(n,t){return t-=n,function(e){return Math.round(n+t*e)}}function Pu(n){var t=[n.a,n.b],e=[n.c,n.d],r=ju(t),u=Uu(t,e),i=ju(Fu(e,t,-u))||0;t[0]*e[1]180?s+=360:s-l>180&&(l+=360),u.push({i:r.push(r.pop()+"rotate(",null,")")-2,x:vu(l,s)})):s&&r.push(r.pop()+"rotate("+s+")"),f!=h?u.push({i:r.push(r.pop()+"skewX(",null,")")-2,x:vu(f,h)}):h&&r.push(r.pop()+"skewX("+h+")"),g[0]!=p[0]||g[1]!=p[1]?(e=r.push(r.pop()+"scale(",null,",",null,")"),u.push({i:e-4,x:vu(g[0],p[0])},{i:e-2,x:vu(g[1],p[1])})):(1!=p[0]||1!=p[1])&&r.push(r.pop()+"scale("+p+")"),e=u.length,function(n){for(var t,i=-1;++i=0;)e.push(u[r])}function Qu(n,t){for(var e=[n],r=[];null!=(n=e.pop());)if(r.push(n),(i=n.children)&&(u=i.length))for(var u,i,o=-1;++oe;++e)(t=n[e][1])>u&&(r=e,u=t);return r}function si(n){return n.reduce(fi,0)}function fi(n,t){return n+t[1]}function hi(n,t){return gi(n,Math.ceil(Math.log(t.length)/Math.LN2+1))}function gi(n,t){for(var e=-1,r=+n[0],u=(n[1]-r)/t,i=[];++e<=t;)i[e]=u*e+r;return i}function pi(n){return[ta.min(n),ta.max(n)]}function vi(n,t){return n.value-t.value}function di(n,t){var e=n._pack_next;n._pack_next=t,t._pack_prev=n,t._pack_next=e,e._pack_prev=t}function mi(n,t){n._pack_next=t,t._pack_prev=n}function yi(n,t){var e=t.x-n.x,r=t.y-n.y,u=n.r+t.r;return.999*u*u>e*e+r*r}function Mi(n){function t(n){s=Math.min(n.x-n.r,s),f=Math.max(n.x+n.r,f),h=Math.min(n.y-n.r,h),g=Math.max(n.y+n.r,g)}if((e=n.children)&&(l=e.length)){var e,r,u,i,o,a,c,l,s=1/0,f=-1/0,h=1/0,g=-1/0;if(e.forEach(xi),r=e[0],r.x=-r.r,r.y=0,t(r),l>1&&(u=e[1],u.x=u.r,u.y=0,t(u),l>2))for(i=e[2],wi(r,u,i),t(i),di(r,i),r._pack_prev=i,di(i,u),u=r._pack_next,o=3;l>o;o++){wi(r,u,i=e[o]);var p=0,v=1,d=1;for(a=u._pack_next;a!==u;a=a._pack_next,v++)if(yi(a,i)){p=1;break}if(1==p)for(c=r._pack_prev;c!==a._pack_prev&&!yi(c,i);c=c._pack_prev,d++);p?(d>v||v==d&&u.ro;o++)i=e[o],i.x-=m,i.y-=y,M=Math.max(M,i.r+Math.sqrt(i.x*i.x+i.y*i.y));n.r=M,e.forEach(bi)}}function xi(n){n._pack_next=n._pack_prev=n}function bi(n){delete n._pack_next,delete n._pack_prev}function _i(n,t,e,r){var u=n.children;if(n.x=t+=r*n.x,n.y=e+=r*n.y,n.r*=r,u)for(var i=-1,o=u.length;++i=0;)t=u[i],t.z+=e,t.m+=e,e+=t.s+(r+=t.c)}function Ci(n,t,e){return n.a.parent===t.parent?n.a:e}function zi(n){return 1+ta.max(n,function(n){return n.y})}function qi(n){return n.reduce(function(n,t){return n+t.x},0)/n.length}function Li(n){var t=n.children;return t&&t.length?Li(t[0]):n}function Ti(n){var t,e=n.children;return e&&(t=e.length)?Ti(e[t-1]):n}function Ri(n){return{x:n.x,y:n.y,dx:n.dx,dy:n.dy}}function Di(n,t){var e=n.x+t[3],r=n.y+t[0],u=n.dx-t[1]-t[3],i=n.dy-t[0]-t[2];return 0>u&&(e+=u/2,u=0),0>i&&(r+=i/2,i=0),{x:e,y:r,dx:u,dy:i}}function Pi(n){var t=n[0],e=n[n.length-1];return e>t?[t,e]:[e,t]}function Ui(n){return n.rangeExtent?n.rangeExtent():Pi(n.range())}function ji(n,t,e,r){var u=e(n[0],n[1]),i=r(t[0],t[1]);return function(n){return i(u(n))}}function Fi(n,t){var e,r=0,u=n.length-1,i=n[r],o=n[u];return i>o&&(e=r,r=u,u=e,e=i,i=o,o=e),n[r]=t.floor(i),n[u]=t.ceil(o),n}function Hi(n){return n?{floor:function(t){return Math.floor(t/n)*n},ceil:function(t){return Math.ceil(t/n)*n}}:bl}function Oi(n,t,e,r){var u=[],i=[],o=0,a=Math.min(n.length,t.length)-1;for(n[a]2?Oi:ji,c=r?Yu:Ou;return o=u(n,t,c,e),a=u(t,n,c,mu),i}function i(n){return o(n)}var o,a;return i.invert=function(n){return a(n)},i.domain=function(t){return arguments.length?(n=t.map(Number),u()):n},i.range=function(n){return arguments.length?(t=n,u()):t},i.rangeRound=function(n){return i.range(n).interpolate(Du)},i.clamp=function(n){return arguments.length?(r=n,u()):r},i.interpolate=function(n){return arguments.length?(e=n,u()):e},i.ticks=function(t){return Xi(n,t)},i.tickFormat=function(t,e){return $i(n,t,e)},i.nice=function(t){return Zi(n,t),u()},i.copy=function(){return Yi(n,t,e,r)},u()}function Ii(n,t){return ta.rebind(n,t,"range","rangeRound","interpolate","clamp")}function Zi(n,t){return Fi(n,Hi(Vi(n,t)[2]))}function Vi(n,t){null==t&&(t=10);var e=Pi(n),r=e[1]-e[0],u=Math.pow(10,Math.floor(Math.log(r/t)/Math.LN10)),i=t/r*u;return.15>=i?u*=10:.35>=i?u*=5:.75>=i&&(u*=2),e[0]=Math.ceil(e[0]/u)*u,e[1]=Math.floor(e[1]/u)*u+.5*u,e[2]=u,e}function Xi(n,t){return ta.range.apply(ta,Vi(n,t))}function $i(n,t,e){var r=Vi(n,t);if(e){var u=lc.exec(e);if(u.shift(),"s"===u[8]){var i=ta.formatPrefix(Math.max(va(r[0]),va(r[1])));return u[7]||(u[7]="."+Bi(i.scale(r[2]))),u[8]="f",e=ta.format(u.join("")),function(n){return e(i.scale(n))+i.symbol}}u[7]||(u[7]="."+Wi(u[8],r)),e=u.join("")}else e=",."+Bi(r[2])+"f";return ta.format(e)}function Bi(n){return-Math.floor(Math.log(n)/Math.LN10+.01)}function Wi(n,t){var e=Bi(t[2]);return n in _l?Math.abs(e-Bi(Math.max(va(t[0]),va(t[1]))))+ +("e"!==n):e-2*("%"===n)}function Ji(n,t,e,r){function u(n){return(e?Math.log(0>n?0:n):-Math.log(n>0?0:-n))/Math.log(t)}function i(n){return e?Math.pow(t,n):-Math.pow(t,-n)}function o(t){return n(u(t))}return o.invert=function(t){return i(n.invert(t))},o.domain=function(t){return arguments.length?(e=t[0]>=0,n.domain((r=t.map(Number)).map(u)),o):r},o.base=function(e){return arguments.length?(t=+e,n.domain(r.map(u)),o):t},o.nice=function(){var t=Fi(r.map(u),e?Math:Sl);return n.domain(t),r=t.map(i),o},o.ticks=function(){var n=Pi(r),o=[],a=n[0],c=n[1],l=Math.floor(u(a)),s=Math.ceil(u(c)),f=t%1?2:t;if(isFinite(s-l)){if(e){for(;s>l;l++)for(var h=1;f>h;h++)o.push(i(l)*h);o.push(i(l))}else for(o.push(i(l));l++0;h--)o.push(i(l)*h);for(l=0;o[l]c;s--);o=o.slice(l,s)}return o},o.tickFormat=function(n,t){if(!arguments.length)return wl;arguments.length<2?t=wl:"function"!=typeof t&&(t=ta.format(t));var r,a=Math.max(.1,n/o.ticks().length),c=e?(r=1e-12,Math.ceil):(r=-1e-12,Math.floor);return function(n){return n/i(c(u(n)+r))<=a?t(n):""}},o.copy=function(){return Ji(n.copy(),t,e,r)},Ii(o,n)}function Gi(n,t,e){function r(t){return n(u(t))}var u=Ki(t),i=Ki(1/t);return r.invert=function(t){return i(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain((e=t.map(Number)).map(u)),r):e},r.ticks=function(n){return Xi(e,n)},r.tickFormat=function(n,t){return $i(e,n,t)},r.nice=function(n){return r.domain(Zi(e,n))},r.exponent=function(o){return arguments.length?(u=Ki(t=o),i=Ki(1/t),n.domain(e.map(u)),r):t},r.copy=function(){return Gi(n.copy(),t,e)},Ii(r,n)}function Ki(n){return function(t){return 0>t?-Math.pow(-t,n):Math.pow(t,n)}}function Qi(n,t){function e(e){return i[((u.get(e)||("range"===t.t?u.set(e,n.push(e)):0/0))-1)%i.length]}function r(t,e){return ta.range(n.length).map(function(n){return t+e*n})}var u,i,o;return e.domain=function(r){if(!arguments.length)return n;n=[],u=new a;for(var i,o=-1,c=r.length;++on?[0/0,0/0]:[n>0?a[n-1]:r[0],nt?0/0:t/i+n,[t,t+1/i]},r.copy=function(){return to(n,t,e)},u()}function eo(n,t){function e(e){return e>=e?t[ta.bisect(n,e)]:void 0}return e.domain=function(t){return arguments.length?(n=t,e):n},e.range=function(n){return arguments.length?(t=n,e):t},e.invertExtent=function(e){return e=t.indexOf(e),[n[e-1],n[e]]},e.copy=function(){return eo(n,t)},e}function ro(n){function t(n){return+n}return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=e.map(t),t):n},t.ticks=function(t){return Xi(n,t)},t.tickFormat=function(t,e){return $i(n,t,e)},t.copy=function(){return ro(n)},t}function uo(){return 0}function io(n){return n.innerRadius}function oo(n){return n.outerRadius}function ao(n){return n.startAngle}function co(n){return n.endAngle}function lo(n){return n&&n.padAngle}function so(n,t,e,r){return(n-e)*t-(t-r)*n>0?0:1}function fo(n,t,e,r,u){var i=n[0]-t[0],o=n[1]-t[1],a=(u?r:-r)/Math.sqrt(i*i+o*o),c=a*o,l=-a*i,s=n[0]+c,f=n[1]+l,h=t[0]+c,g=t[1]+l,p=(s+h)/2,v=(f+g)/2,d=h-s,m=g-f,y=d*d+m*m,M=e-r,x=s*g-h*f,b=(0>m?-1:1)*Math.sqrt(M*M*y-x*x),_=(x*m-d*b)/y,w=(-x*d-m*b)/y,S=(x*m+d*b)/y,k=(-x*d+m*b)/y,E=_-p,A=w-v,N=S-p,C=k-v;return E*E+A*A>N*N+C*C&&(_=S,w=k),[[_-c,w-l],[_*e/M,w*e/M]]}function ho(n){function t(t){function o(){l.push("M",i(n(s),a))}for(var c,l=[],s=[],f=-1,h=t.length,g=kt(e),p=kt(r);++f1&&u.push("H",r[0]),u.join("")}function mo(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t1){a=t[1],i=n[c],c++,r+="C"+(u[0]+o[0])+","+(u[1]+o[1])+","+(i[0]-a[0])+","+(i[1]-a[1])+","+i[0]+","+i[1];for(var l=2;l9&&(u=3*t/Math.sqrt(u),o[a]=u*e,o[a+1]=u*r));for(a=-1;++a<=c;)u=(n[Math.min(c,a+1)][0]-n[Math.max(0,a-1)][0])/(6*(1+o[a]*o[a])),i.push([u||0,o[a]*u||0]);return i}function To(n){return n.length<3?go(n):n[0]+_o(n,Lo(n))}function Ro(n){for(var t,e,r,u=-1,i=n.length;++ur)return s();var u=i[i.active];u&&(--i.count,delete i[i.active],u.event&&u.event.interrupt.call(n,n.__data__,u.index)),i.active=r,o.event&&o.event.start.call(n,n.__data__,t),o.tween.forEach(function(e,r){(r=r.call(n,n.__data__,t))&&v.push(r)}),h=o.ease,f=o.duration,ta.timer(function(){return p.c=l(e||1)?Ne:l,1},0,c)}function l(e){if(i.active!==r)return 1;for(var u=e/f,a=h(u),c=v.length;c>0;)v[--c].call(n,a);return u>=1?(o.event&&o.event.end.call(n,n.__data__,t),s()):void 0}function s(){return--i.count?delete i[r]:delete n[e],1}var f,h,g=o.delay,p=oc,v=[];return p.t=g+c,u>=g?a(u-g):(p.c=a,void 0)},0,c)}}function Bo(n,t,e){n.attr("transform",function(n){var r=t(n);return"translate("+(isFinite(r)?r:e(n))+",0)"})}function Wo(n,t,e){n.attr("transform",function(n){var r=t(n);return"translate(0,"+(isFinite(r)?r:e(n))+")"})}function Jo(n){return n.toISOString()}function Go(n,t,e){function r(t){return n(t)}function u(n,e){var r=n[1]-n[0],u=r/e,i=ta.bisect(Wl,u);return i==Wl.length?[t.year,Vi(n.map(function(n){return n/31536e6}),e)[2]]:i?t[u/Wl[i-1]1?{floor:function(t){for(;e(t=n.floor(t));)t=Ko(t-1);return t},ceil:function(t){for(;e(t=n.ceil(t));)t=Ko(+t+1);return t}}:n))},r.ticks=function(n,t){var e=Pi(r.domain()),i=null==n?u(e,10):"number"==typeof n?u(e,n):!n.range&&[{range:n},t];return i&&(n=i[0],t=i[1]),n.range(e[0],Ko(+e[1]+1),1>t?1:t)},r.tickFormat=function(){return e},r.copy=function(){return Go(n.copy(),t,e)},Ii(r,n)}function Ko(n){return new Date(n)}function Qo(n){return JSON.parse(n.responseText)}function na(n){var t=ua.createRange();return t.selectNode(ua.body),t.createContextualFragment(n.responseText)}var ta={version:"3.5.2"};Date.now||(Date.now=function(){return+new Date});var ea=[].slice,ra=function(n){return ea.call(n)},ua=document,ia=ua.documentElement,oa=window;try{ra(ia.childNodes)[0].nodeType}catch(aa){ra=function(n){for(var t=n.length,e=new Array(t);t--;)e[t]=n[t];return e}}try{ua.createElement("div").style.setProperty("opacity",0,"")}catch(ca){var la=oa.Element.prototype,sa=la.setAttribute,fa=la.setAttributeNS,ha=oa.CSSStyleDeclaration.prototype,ga=ha.setProperty;la.setAttribute=function(n,t){sa.call(this,n,t+"")},la.setAttributeNS=function(n,t,e){fa.call(this,n,t,e+"")},ha.setProperty=function(n,t,e){ga.call(this,n,t+"",e)}}ta.ascending=n,ta.descending=function(n,t){return n>t?-1:t>n?1:t>=n?0:0/0},ta.min=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u=r){e=r;break}for(;++ur&&(e=r)}else{for(;++u=r){e=r;break}for(;++ur&&(e=r)}return e},ta.max=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u=r){e=r;break}for(;++ue&&(e=r)}else{for(;++u=r){e=r;break}for(;++ue&&(e=r)}return e},ta.extent=function(n,t){var e,r,u,i=-1,o=n.length;if(1===arguments.length){for(;++i=r){e=u=r;break}for(;++ir&&(e=r),r>u&&(u=r))}else{for(;++i=r){e=u=r;break}for(;++ir&&(e=r),r>u&&(u=r))}return[e,u]},ta.sum=function(n,t){var r,u=0,i=n.length,o=-1;if(1===arguments.length)for(;++o1?c/(s-1):void 0},ta.deviation=function(){var n=ta.variance.apply(this,arguments);return n?Math.sqrt(n):n};var pa=r(n);ta.bisectLeft=pa.left,ta.bisect=ta.bisectRight=pa.right,ta.bisector=function(t){return r(1===t.length?function(e,r){return n(t(e),r)}:t)},ta.shuffle=function(n,t,e){(i=arguments.length)<3&&(e=n.length,2>i&&(t=0));for(var r,u,i=e-t;i;)u=0|Math.random()*i--,r=n[i+t],n[i+t]=n[u+t],n[u+t]=r;return n},ta.permute=function(n,t){for(var e=t.length,r=new Array(e);e--;)r[e]=n[t[e]];return r},ta.pairs=function(n){for(var t,e=0,r=n.length-1,u=n[0],i=new Array(0>r?0:r);r>e;)i[e]=[t=u,u=n[++e]];return i},ta.zip=function(){if(!(r=arguments.length))return[];for(var n=-1,t=ta.min(arguments,u),e=new Array(t);++n=0;)for(r=n[u],t=r.length;--t>=0;)e[--o]=r[t];return e};var va=Math.abs;ta.range=function(n,t,e){if(arguments.length<3&&(e=1,arguments.length<2&&(t=n,n=0)),1/0===(t-n)/e)throw new Error("infinite range");var r,u=[],o=i(va(e)),a=-1;if(n*=o,t*=o,e*=o,0>e)for(;(r=n+e*++a)>t;)u.push(r/o);else for(;(r=n+e*++a)=i.length)return r?r.call(u,o):e?o.sort(e):o;for(var l,s,f,h,g=-1,p=o.length,v=i[c++],d=new a;++g=i.length)return n;var r=[],u=o[e++];return n.forEach(function(n,u){r.push({key:n,values:t(u,e)})}),u?r.sort(function(n,t){return u(n.key,t.key)}):r}var e,r,u={},i=[],o=[];return u.map=function(t,e){return n(e,t,0)},u.entries=function(e){return t(n(ta.map,e,0),0)},u.key=function(n){return i.push(n),u},u.sortKeys=function(n){return o[i.length-1]=n,u},u.sortValues=function(n){return e=n,u},u.rollup=function(n){return r=n,u},u},ta.set=function(n){var t=new v;if(n)for(var e=0,r=n.length;r>e;++e)t.add(n[e]);return t},o(v,{has:s,add:function(n){return this._[c(n+="")]=!0,n},remove:f,values:h,size:g,empty:p,forEach:function(n){for(var t in this._)n.call(this,l(t))}}),ta.behavior={},ta.rebind=function(n,t){for(var e,r=1,u=arguments.length;++r=0&&(r=n.slice(e+1),n=n.slice(0,e)),n)return arguments.length<2?this[n].on(r):this[n].on(r,t);if(2===arguments.length){if(null==t)for(n in this)this.hasOwnProperty(n)&&this[n].on(r,null);return this}},ta.event=null,ta.requote=function(n){return n.replace(Ma,"\\$&")};var Ma=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g,xa={}.__proto__?function(n,t){n.__proto__=t}:function(n,t){for(var e in t)n[e]=t[e]},ba=function(n,t){return t.querySelector(n)},_a=function(n,t){return t.querySelectorAll(n)},wa=ia.matches||ia[m(ia,"matchesSelector")],Sa=function(n,t){return wa.call(n,t)};"function"==typeof Sizzle&&(ba=function(n,t){return Sizzle(n,t)[0]||null},_a=Sizzle,Sa=Sizzle.matchesSelector),ta.selection=function(){return Na};var ka=ta.selection.prototype=[];ka.select=function(n){var t,e,r,u,i=[];n=k(n);for(var o=-1,a=this.length;++o=0&&(e=n.slice(0,t),n=n.slice(t+1)),Ea.hasOwnProperty(e)?{space:Ea[e],local:n}:n}},ka.attr=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node();return n=ta.ns.qualify(n),n.local?e.getAttributeNS(n.space,n.local):e.getAttribute(n)}for(t in n)this.each(A(t,n[t]));return this}return this.each(A(n,t))},ka.classed=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node(),r=(n=z(n)).length,u=-1;if(t=e.classList){for(;++ur){if("string"!=typeof n){2>r&&(t="");for(e in n)this.each(T(e,n[e],t));return this}if(2>r)return oa.getComputedStyle(this.node(),null).getPropertyValue(n);e=""}return this.each(T(n,t,e))},ka.property=function(n,t){if(arguments.length<2){if("string"==typeof n)return this.node()[n];for(t in n)this.each(R(t,n[t]));return this}return this.each(R(n,t))},ka.text=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.textContent=null==t?"":t}:null==n?function(){this.textContent=""}:function(){this.textContent=n}):this.node().textContent},ka.html=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.innerHTML=null==t?"":t}:null==n?function(){this.innerHTML=""}:function(){this.innerHTML=n}):this.node().innerHTML},ka.append=function(n){return n=D(n),this.select(function(){return this.appendChild(n.apply(this,arguments))})},ka.insert=function(n,t){return n=D(n),t=k(t),this.select(function(){return this.insertBefore(n.apply(this,arguments),t.apply(this,arguments)||null)})},ka.remove=function(){return this.each(P)},ka.data=function(n,t){function e(n,e){var r,u,i,o=n.length,f=e.length,h=Math.min(o,f),g=new Array(f),p=new Array(f),v=new Array(o);if(t){var d,m=new a,y=new Array(o);for(r=-1;++rr;++r)p[r]=U(e[r]);for(;o>r;++r)v[r]=n[r]}p.update=g,p.parentNode=g.parentNode=v.parentNode=n.parentNode,c.push(p),l.push(g),s.push(v)}var r,u,i=-1,o=this.length;if(!arguments.length){for(n=new Array(o=(r=this[0]).length);++ii;i++){u.push(t=[]),t.parentNode=(e=this[i]).parentNode;for(var a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a,i)&&t.push(r)}return S(u)},ka.order=function(){for(var n=-1,t=this.length;++n=0;)(e=r[u])&&(i&&i!==e.nextSibling&&i.parentNode.insertBefore(e,i),i=e);return this},ka.sort=function(n){n=F.apply(this,arguments);for(var t=-1,e=this.length;++tn;n++)for(var e=this[n],r=0,u=e.length;u>r;r++){var i=e[r];if(i)return i}return null},ka.size=function(){var n=0;return H(this,function(){++n}),n};var Aa=[];ta.selection.enter=O,ta.selection.enter.prototype=Aa,Aa.append=ka.append,Aa.empty=ka.empty,Aa.node=ka.node,Aa.call=ka.call,Aa.size=ka.size,Aa.select=function(n){for(var t,e,r,u,i,o=[],a=-1,c=this.length;++ar){if("string"!=typeof n){2>r&&(t=!1);for(e in n)this.each(I(e,n[e],t));return this}if(2>r)return(r=this.node()["__on"+n])&&r._;e=!1}return this.each(I(n,t,e))};var Ca=ta.map({mouseenter:"mouseover",mouseleave:"mouseout"});Ca.forEach(function(n){"on"+n in ua&&Ca.remove(n)});var za="onselectstart"in ua?null:m(ia.style,"userSelect"),qa=0;ta.mouse=function(n){return $(n,_())};var La=/WebKit/.test(oa.navigator.userAgent)?-1:0;ta.touch=function(n,t,e){if(arguments.length<3&&(e=t,t=_().changedTouches),t)for(var r,u=0,i=t.length;i>u;++u)if((r=t[u]).identifier===e)return $(n,r)},ta.behavior.drag=function(){function n(){this.on("mousedown.drag",u).on("touchstart.drag",i)}function t(n,t,u,i,o){return function(){function a(){var n,e,r=t(h,v);r&&(n=r[0]-M[0],e=r[1]-M[1],p|=n|e,M=r,g({type:"drag",x:r[0]+l[0],y:r[1]+l[1],dx:n,dy:e}))}function c(){t(h,v)&&(m.on(i+d,null).on(o+d,null),y(p&&ta.event.target===f),g({type:"dragend"}))}var l,s=this,f=ta.event.target,h=s.parentNode,g=e.of(s,arguments),p=0,v=n(),d=".drag"+(null==v?"":"-"+v),m=ta.select(u()).on(i+d,a).on(o+d,c),y=X(),M=t(h,v);r?(l=r.apply(s,arguments),l=[l.x-M[0],l.y-M[1]]):l=[0,0],g({type:"dragstart"})}}var e=w(n,"drag","dragstart","dragend"),r=null,u=t(y,ta.mouse,J,"mousemove","mouseup"),i=t(B,ta.touch,W,"touchmove","touchend");return n.origin=function(t){return arguments.length?(r=t,n):r},ta.rebind(n,e,"on")},ta.touches=function(n,t){return arguments.length<2&&(t=_().touches),t?ra(t).map(function(t){var e=$(n,t);return e.identifier=t.identifier,e}):[]};var Ta=1e-6,Ra=Ta*Ta,Da=Math.PI,Pa=2*Da,Ua=Pa-Ta,ja=Da/2,Fa=Da/180,Ha=180/Da,Oa=Math.SQRT2,Ya=2,Ia=4;ta.interpolateZoom=function(n,t){function e(n){var t=n*y;if(m){var e=et(v),o=i/(Ya*h)*(e*rt(Oa*t+v)-tt(v));return[r+o*l,u+o*s,i*e/et(Oa*t+v)]}return[r+n*l,u+n*s,i*Math.exp(Oa*t)]}var r=n[0],u=n[1],i=n[2],o=t[0],a=t[1],c=t[2],l=o-r,s=a-u,f=l*l+s*s,h=Math.sqrt(f),g=(c*c-i*i+Ia*f)/(2*i*Ya*h),p=(c*c-i*i-Ia*f)/(2*c*Ya*h),v=Math.log(Math.sqrt(g*g+1)-g),d=Math.log(Math.sqrt(p*p+1)-p),m=d-v,y=(m||Math.log(c/i))/Oa;return e.duration=1e3*y,e},ta.behavior.zoom=function(){function n(n){n.on(z,s).on(Xa+".zoom",h).on("dblclick.zoom",g).on(T,f)}function t(n){return[(n[0]-k.x)/k.k,(n[1]-k.y)/k.k]}function e(n){return[n[0]*k.k+k.x,n[1]*k.k+k.y]}function r(n){k.k=Math.max(A[0],Math.min(A[1],n))}function u(n,t){t=e(t),k.x+=n[0]-t[0],k.y+=n[1]-t[1]}function i(t,e,i,o){t.__chart__={x:k.x,y:k.y,k:k.k},r(Math.pow(2,o)),u(v=e,i),t=ta.select(t),N>0&&(t=t.transition().duration(N)),t.call(n.event)}function o(){x&&x.domain(M.range().map(function(n){return(n-k.x)/k.k}).map(M.invert)),S&&S.domain(_.range().map(function(n){return(n-k.y)/k.k}).map(_.invert))}function a(n){C++||n({type:"zoomstart"})}function c(n){o(),n({type:"zoom",scale:k.k,translate:[k.x,k.y]})}function l(n){--C||n({type:"zoomend"}),v=null}function s(){function n(){s=1,u(ta.mouse(r),h),c(o)}function e(){f.on(q,null).on(L,null),g(s&&ta.event.target===i),l(o)}var r=this,i=ta.event.target,o=R.of(r,arguments),s=0,f=ta.select(oa).on(q,n).on(L,e),h=t(ta.mouse(r)),g=X();Fl.call(r),a(o)}function f(){function n(){var n=ta.touches(p);return g=k.k,n.forEach(function(n){n.identifier in d&&(d[n.identifier]=t(n))}),n}function e(){var t=ta.event.target;ta.select(t).on(x,o).on(_,h),w.push(t);for(var e=ta.event.changedTouches,r=0,u=e.length;u>r;++r)d[e[r].identifier]=null;var a=n(),c=Date.now();if(1===a.length){if(500>c-y){var l=a[0];i(p,l,d[l.identifier],Math.floor(Math.log(k.k)/Math.LN2)+1),b()}y=c}else if(a.length>1){var l=a[0],s=a[1],f=l[0]-s[0],g=l[1]-s[1];m=f*f+g*g}}function o(){var n,t,e,i,o=ta.touches(p);Fl.call(p);for(var a=0,l=o.length;l>a;++a,i=null)if(e=o[a],i=d[e.identifier]){if(t)break;n=e,t=i}if(i){var s=(s=e[0]-n[0])*s+(s=e[1]-n[1])*s,f=m&&Math.sqrt(s/m);n=[(n[0]+e[0])/2,(n[1]+e[1])/2],t=[(t[0]+i[0])/2,(t[1]+i[1])/2],r(f*g)}y=null,u(n,t),c(v)}function h(){if(ta.event.touches.length){for(var t=ta.event.changedTouches,e=0,r=t.length;r>e;++e)delete d[t[e].identifier];for(var u in d)return void n()}ta.selectAll(w).on(M,null),S.on(z,s).on(T,f),E(),l(v)}var g,p=this,v=R.of(p,arguments),d={},m=0,M=".zoom-"+ta.event.changedTouches[0].identifier,x="touchmove"+M,_="touchend"+M,w=[],S=ta.select(p),E=X();e(),a(v),S.on(z,null).on(T,e)}function h(){var n=R.of(this,arguments);m?clearTimeout(m):(p=t(v=d||ta.mouse(this)),Fl.call(this),a(n)),m=setTimeout(function(){m=null,l(n)},50),b(),r(Math.pow(2,.002*Za())*k.k),u(v,p),c(n)}function g(){var n=ta.mouse(this),e=Math.log(k.k)/Math.LN2;i(this,n,t(n),ta.event.shiftKey?Math.ceil(e)-1:Math.floor(e)+1)}var p,v,d,m,y,M,x,_,S,k={x:0,y:0,k:1},E=[960,500],A=Va,N=250,C=0,z="mousedown.zoom",q="mousemove.zoom",L="mouseup.zoom",T="touchstart.zoom",R=w(n,"zoomstart","zoom","zoomend");return n.event=function(n){n.each(function(){var n=R.of(this,arguments),t=k;Ul?ta.select(this).transition().each("start.zoom",function(){k=this.__chart__||{x:0,y:0,k:1},a(n)}).tween("zoom:zoom",function(){var e=E[0],r=E[1],u=v?v[0]:e/2,i=v?v[1]:r/2,o=ta.interpolateZoom([(u-k.x)/k.k,(i-k.y)/k.k,e/k.k],[(u-t.x)/t.k,(i-t.y)/t.k,e/t.k]);return function(t){var r=o(t),a=e/r[2];this.__chart__=k={x:u-r[0]*a,y:i-r[1]*a,k:a},c(n)}}).each("interrupt.zoom",function(){l(n)}).each("end.zoom",function(){l(n)}):(this.__chart__=k,a(n),c(n),l(n))})},n.translate=function(t){return arguments.length?(k={x:+t[0],y:+t[1],k:k.k},o(),n):[k.x,k.y]},n.scale=function(t){return arguments.length?(k={x:k.x,y:k.y,k:+t},o(),n):k.k},n.scaleExtent=function(t){return arguments.length?(A=null==t?Va:[+t[0],+t[1]],n):A},n.center=function(t){return arguments.length?(d=t&&[+t[0],+t[1]],n):d},n.size=function(t){return arguments.length?(E=t&&[+t[0],+t[1]],n):E},n.duration=function(t){return arguments.length?(N=+t,n):N},n.x=function(t){return arguments.length?(x=t,M=t.copy(),k={x:0,y:0,k:1},n):x},n.y=function(t){return arguments.length?(S=t,_=t.copy(),k={x:0,y:0,k:1},n):S},ta.rebind(n,R,"on")};var Za,Va=[0,1/0],Xa="onwheel"in ua?(Za=function(){return-ta.event.deltaY*(ta.event.deltaMode?120:1)},"wheel"):"onmousewheel"in ua?(Za=function(){return ta.event.wheelDelta},"mousewheel"):(Za=function(){return-ta.event.detail},"MozMousePixelScroll");ta.color=it,it.prototype.toString=function(){return this.rgb()+""},ta.hsl=ot;var $a=ot.prototype=new it;$a.brighter=function(n){return n=Math.pow(.7,arguments.length?n:1),new ot(this.h,this.s,this.l/n)},$a.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new ot(this.h,this.s,n*this.l)},$a.rgb=function(){return at(this.h,this.s,this.l)},ta.hcl=ct;var Ba=ct.prototype=new it;Ba.brighter=function(n){return new ct(this.h,this.c,Math.min(100,this.l+Wa*(arguments.length?n:1)))},Ba.darker=function(n){return new ct(this.h,this.c,Math.max(0,this.l-Wa*(arguments.length?n:1)))},Ba.rgb=function(){return lt(this.h,this.c,this.l).rgb()},ta.lab=st;var Wa=18,Ja=.95047,Ga=1,Ka=1.08883,Qa=st.prototype=new it;Qa.brighter=function(n){return new st(Math.min(100,this.l+Wa*(arguments.length?n:1)),this.a,this.b)},Qa.darker=function(n){return new st(Math.max(0,this.l-Wa*(arguments.length?n:1)),this.a,this.b)},Qa.rgb=function(){return ft(this.l,this.a,this.b)},ta.rgb=dt;var nc=dt.prototype=new it;nc.brighter=function(n){n=Math.pow(.7,arguments.length?n:1);var t=this.r,e=this.g,r=this.b,u=30;return t||e||r?(t&&u>t&&(t=u),e&&u>e&&(e=u),r&&u>r&&(r=u),new dt(Math.min(255,t/n),Math.min(255,e/n),Math.min(255,r/n))):new dt(u,u,u)},nc.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new dt(n*this.r,n*this.g,n*this.b)},nc.hsl=function(){return bt(this.r,this.g,this.b)},nc.toString=function(){return"#"+Mt(this.r)+Mt(this.g)+Mt(this.b)};var tc=ta.map({aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074});tc.forEach(function(n,t){tc.set(n,mt(t))}),ta.functor=kt,ta.xhr=At(Et),ta.dsv=function(n,t){function e(n,e,i){arguments.length<3&&(i=e,e=null);var o=Nt(n,t,null==e?r:u(e),i);return o.row=function(n){return arguments.length?o.response(null==(e=n)?r:u(n)):e},o}function r(n){return e.parse(n.responseText)}function u(n){return function(t){return e.parse(t.responseText,n)}}function i(t){return t.map(o).join(n)}function o(n){return a.test(n)?'"'+n.replace(/\"/g,'""')+'"':n}var a=new RegExp('["'+n+"\n]"),c=n.charCodeAt(0);return e.parse=function(n,t){var r;return e.parseRows(n,function(n,e){if(r)return r(n,e-1);var u=new Function("d","return {"+n.map(function(n,t){return JSON.stringify(n)+": d["+t+"]"}).join(",")+"}");r=t?function(n,e){return t(u(n),e)}:u})},e.parseRows=function(n,t){function e(){if(s>=l)return o;if(u)return u=!1,i;var t=s;if(34===n.charCodeAt(t)){for(var e=t;e++s;){var r=n.charCodeAt(s++),a=1;if(10===r)u=!0;else if(13===r)u=!0,10===n.charCodeAt(s)&&(++s,++a);else if(r!==c)continue;return n.slice(t,s-a)}return n.slice(t)}for(var r,u,i={},o={},a=[],l=n.length,s=0,f=0;(r=e())!==o;){for(var h=[];r!==i&&r!==o;)h.push(r),r=e();t&&null==(h=t(h,f++))||a.push(h)}return a},e.format=function(t){if(Array.isArray(t[0]))return e.formatRows(t);var r=new v,u=[];return t.forEach(function(n){for(var t in n)r.has(t)||u.push(r.add(t))}),[u.map(o).join(n)].concat(t.map(function(t){return u.map(function(n){return o(t[n])}).join(n)})).join("\n")},e.formatRows=function(n){return n.map(i).join("\n")},e},ta.csv=ta.dsv(",","text/csv"),ta.tsv=ta.dsv(" ","text/tab-separated-values");var ec,rc,uc,ic,oc,ac=oa[m(oa,"requestAnimationFrame")]||function(n){setTimeout(n,17)};ta.timer=function(n,t,e){var r=arguments.length;2>r&&(t=0),3>r&&(e=Date.now());var u=e+t,i={c:n,t:u,f:!1,n:null};rc?rc.n=i:ec=i,rc=i,uc||(ic=clearTimeout(ic),uc=1,ac(qt))},ta.timer.flush=function(){Lt(),Tt()},ta.round=function(n,t){return t?Math.round(n*(t=Math.pow(10,t)))/t:Math.round(n)};var cc=["y","z","a","f","p","n","\xb5","m","","k","M","G","T","P","E","Z","Y"].map(Dt);ta.formatPrefix=function(n,t){var e=0;return n&&(0>n&&(n*=-1),t&&(n=ta.round(n,Rt(n,t))),e=1+Math.floor(1e-12+Math.log(n)/Math.LN10),e=Math.max(-24,Math.min(24,3*Math.floor((e-1)/3)))),cc[8+e/3]};var lc=/(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i,sc=ta.map({b:function(n){return n.toString(2)},c:function(n){return String.fromCharCode(n)},o:function(n){return n.toString(8)},x:function(n){return n.toString(16)},X:function(n){return n.toString(16).toUpperCase()},g:function(n,t){return n.toPrecision(t)},e:function(n,t){return n.toExponential(t)},f:function(n,t){return n.toFixed(t)},r:function(n,t){return(n=ta.round(n,Rt(n,t))).toFixed(Math.max(0,Math.min(20,Rt(n*(1+1e-15),t))))}}),fc=ta.time={},hc=Date;jt.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){gc.setUTCDate.apply(this._,arguments)},setDay:function(){gc.setUTCDay.apply(this._,arguments)},setFullYear:function(){gc.setUTCFullYear.apply(this._,arguments)},setHours:function(){gc.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){gc.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){gc.setUTCMinutes.apply(this._,arguments)},setMonth:function(){gc.setUTCMonth.apply(this._,arguments)},setSeconds:function(){gc.setUTCSeconds.apply(this._,arguments)},setTime:function(){gc.setTime.apply(this._,arguments)}};var gc=Date.prototype;fc.year=Ft(function(n){return n=fc.day(n),n.setMonth(0,1),n},function(n,t){n.setFullYear(n.getFullYear()+t)},function(n){return n.getFullYear()}),fc.years=fc.year.range,fc.years.utc=fc.year.utc.range,fc.day=Ft(function(n){var t=new hc(2e3,0);return t.setFullYear(n.getFullYear(),n.getMonth(),n.getDate()),t},function(n,t){n.setDate(n.getDate()+t)},function(n){return n.getDate()-1}),fc.days=fc.day.range,fc.days.utc=fc.day.utc.range,fc.dayOfYear=function(n){var t=fc.year(n);return Math.floor((n-t-6e4*(n.getTimezoneOffset()-t.getTimezoneOffset()))/864e5)},["sunday","monday","tuesday","wednesday","thursday","friday","saturday"].forEach(function(n,t){t=7-t;var e=fc[n]=Ft(function(n){return(n=fc.day(n)).setDate(n.getDate()-(n.getDay()+t)%7),n},function(n,t){n.setDate(n.getDate()+7*Math.floor(t))},function(n){var e=fc.year(n).getDay();return Math.floor((fc.dayOfYear(n)+(e+t)%7)/7)-(e!==t)});fc[n+"s"]=e.range,fc[n+"s"].utc=e.utc.range,fc[n+"OfYear"]=function(n){var e=fc.year(n).getDay();return Math.floor((fc.dayOfYear(n)+(e+t)%7)/7)}}),fc.week=fc.sunday,fc.weeks=fc.sunday.range,fc.weeks.utc=fc.sunday.utc.range,fc.weekOfYear=fc.sundayOfYear;var pc={"-":"",_:" ",0:"0"},vc=/^\s*\d+/,dc=/^%/;ta.locale=function(n){return{numberFormat:Pt(n),timeFormat:Ot(n)}};var mc=ta.locale({decimal:".",thousands:",",grouping:[3],currency:["$",""],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"]});ta.format=mc.numberFormat,ta.geo={},ce.prototype={s:0,t:0,add:function(n){le(n,this.t,yc),le(yc.s,this.s,this),this.s?this.t+=yc.t:this.s=yc.t},reset:function(){this.s=this.t=0},valueOf:function(){return this.s}};var yc=new ce;ta.geo.stream=function(n,t){n&&Mc.hasOwnProperty(n.type)?Mc[n.type](n,t):se(n,t)};var Mc={Feature:function(n,t){se(n.geometry,t)},FeatureCollection:function(n,t){for(var e=n.features,r=-1,u=e.length;++rn?4*Da+n:n,wc.lineStart=wc.lineEnd=wc.point=y}};ta.geo.bounds=function(){function n(n,t){M.push(x=[s=n,h=n]),f>t&&(f=t),t>g&&(g=t)}function t(t,e){var r=pe([t*Fa,e*Fa]);if(m){var u=de(m,r),i=[u[1],-u[0],0],o=de(i,u);Me(o),o=xe(o);var c=t-p,l=c>0?1:-1,v=o[0]*Ha*l,d=va(c)>180;if(d^(v>l*p&&l*t>v)){var y=o[1]*Ha;y>g&&(g=y)}else if(v=(v+360)%360-180,d^(v>l*p&&l*t>v)){var y=-o[1]*Ha;f>y&&(f=y)}else f>e&&(f=e),e>g&&(g=e);d?p>t?a(s,t)>a(s,h)&&(h=t):a(t,h)>a(s,h)&&(s=t):h>=s?(s>t&&(s=t),t>h&&(h=t)):t>p?a(s,t)>a(s,h)&&(h=t):a(t,h)>a(s,h)&&(s=t)}else n(t,e);m=r,p=t}function e(){b.point=t}function r(){x[0]=s,x[1]=h,b.point=n,m=null}function u(n,e){if(m){var r=n-p;y+=va(r)>180?r+(r>0?360:-360):r}else v=n,d=e;wc.point(n,e),t(n,e)}function i(){wc.lineStart()}function o(){u(v,d),wc.lineEnd(),va(y)>Ta&&(s=-(h=180)),x[0]=s,x[1]=h,m=null}function a(n,t){return(t-=n)<0?t+360:t}function c(n,t){return n[0]-t[0]}function l(n,t){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:n_c?(s=-(h=180),f=-(g=90)):y>Ta?g=90:-Ta>y&&(f=-90),x[0]=s,x[1]=h}};return function(n){g=h=-(s=f=1/0),M=[],ta.geo.stream(n,b);var t=M.length;if(t){M.sort(c);for(var e,r=1,u=M[0],i=[u];t>r;++r)e=M[r],l(e[0],u)||l(e[1],u)?(a(u[0],e[1])>a(u[0],u[1])&&(u[1]=e[1]),a(e[0],u[1])>a(u[0],u[1])&&(u[0]=e[0])):i.push(u=e);for(var o,e,p=-1/0,t=i.length-1,r=0,u=i[t];t>=r;u=e,++r)e=i[r],(o=a(u[1],e[0]))>p&&(p=o,s=e[0],h=u[1])}return M=x=null,1/0===s||1/0===f?[[0/0,0/0],[0/0,0/0]]:[[s,f],[h,g]]}}(),ta.geo.centroid=function(n){Sc=kc=Ec=Ac=Nc=Cc=zc=qc=Lc=Tc=Rc=0,ta.geo.stream(n,Dc);var t=Lc,e=Tc,r=Rc,u=t*t+e*e+r*r;return Ra>u&&(t=Cc,e=zc,r=qc,Ta>kc&&(t=Ec,e=Ac,r=Nc),u=t*t+e*e+r*r,Ra>u)?[0/0,0/0]:[Math.atan2(e,t)*Ha,nt(r/Math.sqrt(u))*Ha]};var Sc,kc,Ec,Ac,Nc,Cc,zc,qc,Lc,Tc,Rc,Dc={sphere:y,point:_e,lineStart:Se,lineEnd:ke,polygonStart:function(){Dc.lineStart=Ee},polygonEnd:function(){Dc.lineStart=Se}},Pc=Le(Ne,Pe,je,[-Da,-Da/2]),Uc=1e9;ta.geo.clipExtent=function(){var n,t,e,r,u,i,o={stream:function(n){return u&&(u.valid=!1),u=i(n),u.valid=!0,u},extent:function(a){return arguments.length?(i=Ye(n=+a[0][0],t=+a[0][1],e=+a[1][0],r=+a[1][1]),u&&(u.valid=!1,u=null),o):[[n,t],[e,r]]}};return o.extent([[0,0],[960,500]])},(ta.geo.conicEqualArea=function(){return Ie(Ze)}).raw=Ze,ta.geo.albers=function(){return ta.geo.conicEqualArea().rotate([96,0]).center([-.6,38.7]).parallels([29.5,45.5]).scale(1070)},ta.geo.albersUsa=function(){function n(n){var i=n[0],o=n[1];return t=null,e(i,o),t||(r(i,o),t)||u(i,o),t}var t,e,r,u,i=ta.geo.albers(),o=ta.geo.conicEqualArea().rotate([154,0]).center([-2,58.5]).parallels([55,65]),a=ta.geo.conicEqualArea().rotate([157,0]).center([-3,19.9]).parallels([8,18]),c={point:function(n,e){t=[n,e]}};return n.invert=function(n){var t=i.scale(),e=i.translate(),r=(n[0]-e[0])/t,u=(n[1]-e[1])/t;return(u>=.12&&.234>u&&r>=-.425&&-.214>r?o:u>=.166&&.234>u&&r>=-.214&&-.115>r?a:i).invert(n)},n.stream=function(n){var t=i.stream(n),e=o.stream(n),r=a.stream(n);return{point:function(n,u){t.point(n,u),e.point(n,u),r.point(n,u)},sphere:function(){t.sphere(),e.sphere(),r.sphere()},lineStart:function(){t.lineStart(),e.lineStart(),r.lineStart()},lineEnd:function(){t.lineEnd(),e.lineEnd(),r.lineEnd()},polygonStart:function(){t.polygonStart(),e.polygonStart(),r.polygonStart()},polygonEnd:function(){t.polygonEnd(),e.polygonEnd(),r.polygonEnd()}}},n.precision=function(t){return arguments.length?(i.precision(t),o.precision(t),a.precision(t),n):i.precision()},n.scale=function(t){return arguments.length?(i.scale(t),o.scale(.35*t),a.scale(t),n.translate(i.translate())):i.scale()},n.translate=function(t){if(!arguments.length)return i.translate();var l=i.scale(),s=+t[0],f=+t[1];return e=i.translate(t).clipExtent([[s-.455*l,f-.238*l],[s+.455*l,f+.238*l]]).stream(c).point,r=o.translate([s-.307*l,f+.201*l]).clipExtent([[s-.425*l+Ta,f+.12*l+Ta],[s-.214*l-Ta,f+.234*l-Ta]]).stream(c).point,u=a.translate([s-.205*l,f+.212*l]).clipExtent([[s-.214*l+Ta,f+.166*l+Ta],[s-.115*l-Ta,f+.234*l-Ta]]).stream(c).point,n},n.scale(1070)};var jc,Fc,Hc,Oc,Yc,Ic,Zc={point:y,lineStart:y,lineEnd:y,polygonStart:function(){Fc=0,Zc.lineStart=Ve},polygonEnd:function(){Zc.lineStart=Zc.lineEnd=Zc.point=y,jc+=va(Fc/2)}},Vc={point:Xe,lineStart:y,lineEnd:y,polygonStart:y,polygonEnd:y},Xc={point:We,lineStart:Je,lineEnd:Ge,polygonStart:function(){Xc.lineStart=Ke},polygonEnd:function(){Xc.point=We,Xc.lineStart=Je,Xc.lineEnd=Ge}};ta.geo.path=function(){function n(n){return n&&("function"==typeof a&&i.pointRadius(+a.apply(this,arguments)),o&&o.valid||(o=u(i)),ta.geo.stream(n,o)),i.result()}function t(){return o=null,n}var e,r,u,i,o,a=4.5;return n.area=function(n){return jc=0,ta.geo.stream(n,u(Zc)),jc},n.centroid=function(n){return Ec=Ac=Nc=Cc=zc=qc=Lc=Tc=Rc=0,ta.geo.stream(n,u(Xc)),Rc?[Lc/Rc,Tc/Rc]:qc?[Cc/qc,zc/qc]:Nc?[Ec/Nc,Ac/Nc]:[0/0,0/0]},n.bounds=function(n){return Yc=Ic=-(Hc=Oc=1/0),ta.geo.stream(n,u(Vc)),[[Hc,Oc],[Yc,Ic]]},n.projection=function(n){return arguments.length?(u=(e=n)?n.stream||tr(n):Et,t()):e},n.context=function(n){return arguments.length?(i=null==(r=n)?new $e:new Qe(n),"function"!=typeof a&&i.pointRadius(a),t()):r},n.pointRadius=function(t){return arguments.length?(a="function"==typeof t?t:(i.pointRadius(+t),+t),n):a},n.projection(ta.geo.albersUsa()).context(null)},ta.geo.transform=function(n){return{stream:function(t){var e=new er(t);for(var r in n)e[r]=n[r];return e}}},er.prototype={point:function(n,t){this.stream.point(n,t)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}},ta.geo.projection=ur,ta.geo.projectionMutator=ir,(ta.geo.equirectangular=function(){return ur(ar)}).raw=ar.invert=ar,ta.geo.rotation=function(n){function t(t){return t=n(t[0]*Fa,t[1]*Fa),t[0]*=Ha,t[1]*=Ha,t}return n=lr(n[0]%360*Fa,n[1]*Fa,n.length>2?n[2]*Fa:0),t.invert=function(t){return t=n.invert(t[0]*Fa,t[1]*Fa),t[0]*=Ha,t[1]*=Ha,t},t},cr.invert=ar,ta.geo.circle=function(){function n(){var n="function"==typeof r?r.apply(this,arguments):r,t=lr(-n[0]*Fa,-n[1]*Fa,0).invert,u=[];return e(null,null,1,{point:function(n,e){u.push(n=t(n,e)),n[0]*=Ha,n[1]*=Ha}}),{type:"Polygon",coordinates:[u]}}var t,e,r=[0,0],u=6;return n.origin=function(t){return arguments.length?(r=t,n):r},n.angle=function(r){return arguments.length?(e=gr((t=+r)*Fa,u*Fa),n):t},n.precision=function(r){return arguments.length?(e=gr(t*Fa,(u=+r)*Fa),n):u},n.angle(90)},ta.geo.distance=function(n,t){var e,r=(t[0]-n[0])*Fa,u=n[1]*Fa,i=t[1]*Fa,o=Math.sin(r),a=Math.cos(r),c=Math.sin(u),l=Math.cos(u),s=Math.sin(i),f=Math.cos(i);return Math.atan2(Math.sqrt((e=f*o)*e+(e=l*s-c*f*a)*e),c*s+l*f*a)},ta.geo.graticule=function(){function n(){return{type:"MultiLineString",coordinates:t()}}function t(){return ta.range(Math.ceil(i/d)*d,u,d).map(h).concat(ta.range(Math.ceil(l/m)*m,c,m).map(g)).concat(ta.range(Math.ceil(r/p)*p,e,p).filter(function(n){return va(n%d)>Ta}).map(s)).concat(ta.range(Math.ceil(a/v)*v,o,v).filter(function(n){return va(n%m)>Ta}).map(f))}var e,r,u,i,o,a,c,l,s,f,h,g,p=10,v=p,d=90,m=360,y=2.5;return n.lines=function(){return t().map(function(n){return{type:"LineString",coordinates:n}})},n.outline=function(){return{type:"Polygon",coordinates:[h(i).concat(g(c).slice(1),h(u).reverse().slice(1),g(l).reverse().slice(1))]}},n.extent=function(t){return arguments.length?n.majorExtent(t).minorExtent(t):n.minorExtent()},n.majorExtent=function(t){return arguments.length?(i=+t[0][0],u=+t[1][0],l=+t[0][1],c=+t[1][1],i>u&&(t=i,i=u,u=t),l>c&&(t=l,l=c,c=t),n.precision(y)):[[i,l],[u,c]]},n.minorExtent=function(t){return arguments.length?(r=+t[0][0],e=+t[1][0],a=+t[0][1],o=+t[1][1],r>e&&(t=r,r=e,e=t),a>o&&(t=a,a=o,o=t),n.precision(y)):[[r,a],[e,o]]},n.step=function(t){return arguments.length?n.majorStep(t).minorStep(t):n.minorStep()},n.majorStep=function(t){return arguments.length?(d=+t[0],m=+t[1],n):[d,m]},n.minorStep=function(t){return arguments.length?(p=+t[0],v=+t[1],n):[p,v]},n.precision=function(t){return arguments.length?(y=+t,s=vr(a,o,90),f=dr(r,e,y),h=vr(l,c,90),g=dr(i,u,y),n):y},n.majorExtent([[-180,-90+Ta],[180,90-Ta]]).minorExtent([[-180,-80-Ta],[180,80+Ta]])},ta.geo.greatArc=function(){function n(){return{type:"LineString",coordinates:[t||r.apply(this,arguments),e||u.apply(this,arguments)]}}var t,e,r=mr,u=yr;return n.distance=function(){return ta.geo.distance(t||r.apply(this,arguments),e||u.apply(this,arguments))},n.source=function(e){return arguments.length?(r=e,t="function"==typeof e?null:e,n):r},n.target=function(t){return arguments.length?(u=t,e="function"==typeof t?null:t,n):u},n.precision=function(){return arguments.length?n:0},n},ta.geo.interpolate=function(n,t){return Mr(n[0]*Fa,n[1]*Fa,t[0]*Fa,t[1]*Fa)},ta.geo.length=function(n){return $c=0,ta.geo.stream(n,Bc),$c};var $c,Bc={sphere:y,point:y,lineStart:xr,lineEnd:y,polygonStart:y,polygonEnd:y},Wc=br(function(n){return Math.sqrt(2/(1+n))},function(n){return 2*Math.asin(n/2)});(ta.geo.azimuthalEqualArea=function(){return ur(Wc)}).raw=Wc;var Jc=br(function(n){var t=Math.acos(n);return t&&t/Math.sin(t)},Et);(ta.geo.azimuthalEquidistant=function(){return ur(Jc)}).raw=Jc,(ta.geo.conicConformal=function(){return Ie(_r)}).raw=_r,(ta.geo.conicEquidistant=function(){return Ie(wr)}).raw=wr;var Gc=br(function(n){return 1/n},Math.atan);(ta.geo.gnomonic=function(){return ur(Gc)}).raw=Gc,Sr.invert=function(n,t){return[n,2*Math.atan(Math.exp(t))-ja]},(ta.geo.mercator=function(){return kr(Sr)}).raw=Sr;var Kc=br(function(){return 1},Math.asin);(ta.geo.orthographic=function(){return ur(Kc)}).raw=Kc;var Qc=br(function(n){return 1/(1+n)},function(n){return 2*Math.atan(n)});(ta.geo.stereographic=function(){return ur(Qc)}).raw=Qc,Er.invert=function(n,t){return[-t,2*Math.atan(Math.exp(n))-ja]},(ta.geo.transverseMercator=function(){var n=kr(Er),t=n.center,e=n.rotate;return n.center=function(n){return n?t([-n[1],n[0]]):(n=t(),[n[1],-n[0]])},n.rotate=function(n){return n?e([n[0],n[1],n.length>2?n[2]+90:90]):(n=e(),[n[0],n[1],n[2]-90])},e([0,0,90])}).raw=Er,ta.geom={},ta.geom.hull=function(n){function t(n){if(n.length<3)return[];var t,u=kt(e),i=kt(r),o=n.length,a=[],c=[];for(t=0;o>t;t++)a.push([+u.call(this,n[t],t),+i.call(this,n[t],t),t]);for(a.sort(zr),t=0;o>t;t++)c.push([a[t][0],-a[t][1]]);var l=Cr(a),s=Cr(c),f=s[0]===l[0],h=s[s.length-1]===l[l.length-1],g=[];for(t=l.length-1;t>=0;--t)g.push(n[a[l[t]][2]]);for(t=+f;t=r&&l.x<=i&&l.y>=u&&l.y<=o?[[r,o],[i,o],[i,u],[r,u]]:[];s.point=n[a]}),t}function e(n){return n.map(function(n,t){return{x:Math.round(i(n,t)/Ta)*Ta,y:Math.round(o(n,t)/Ta)*Ta,i:t}})}var r=Ar,u=Nr,i=r,o=u,a=cl;return n?t(n):(t.links=function(n){return iu(e(n)).edges.filter(function(n){return n.l&&n.r}).map(function(t){return{source:n[t.l.i],target:n[t.r.i]}})},t.triangles=function(n){var t=[];return iu(e(n)).cells.forEach(function(e,r){for(var u,i,o=e.site,a=e.edges.sort(Ir),c=-1,l=a.length,s=a[l-1].edge,f=s.l===o?s.r:s.l;++c=l,h=r>=s,g=h<<1|f;n.leaf=!1,n=n.nodes[g]||(n.nodes[g]=su()),f?u=l:a=l,h?o=s:c=s,i(n,t,e,r,u,o,a,c)}var s,f,h,g,p,v,d,m,y,M=kt(a),x=kt(c);if(null!=t)v=t,d=e,m=r,y=u;else if(m=y=-(v=d=1/0),f=[],h=[],p=n.length,o)for(g=0;p>g;++g)s=n[g],s.xm&&(m=s.x),s.y>y&&(y=s.y),f.push(s.x),h.push(s.y);else for(g=0;p>g;++g){var b=+M(s=n[g],g),_=+x(s,g);v>b&&(v=b),d>_&&(d=_),b>m&&(m=b),_>y&&(y=_),f.push(b),h.push(_)}var w=m-v,S=y-d;w>S?y=d+w:m=v+S;var k=su();if(k.add=function(n){i(k,n,+M(n,++g),+x(n,g),v,d,m,y)},k.visit=function(n){fu(n,k,v,d,m,y)},k.find=function(n){return hu(k,n[0],n[1],v,d,m,y)},g=-1,null==t){for(;++g=0?n.slice(0,t):n,r=t>=0?n.slice(t+1):"in";return e=hl.get(e)||fl,r=gl.get(r)||Et,Mu(r(e.apply(null,ea.call(arguments,1))))},ta.interpolateHcl=Lu,ta.interpolateHsl=Tu,ta.interpolateLab=Ru,ta.interpolateRound=Du,ta.transform=function(n){var t=ua.createElementNS(ta.ns.prefix.svg,"g");return(ta.transform=function(n){if(null!=n){t.setAttribute("transform",n);var e=t.transform.baseVal.consolidate()}return new Pu(e?e.matrix:pl)})(n)},Pu.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var pl={a:1,b:0,c:0,d:1,e:0,f:0};ta.interpolateTransform=Hu,ta.layout={},ta.layout.bundle=function(){return function(n){for(var t=[],e=-1,r=n.length;++ea*a/d){if(p>c){var l=t.charge/c;n.px-=i*l,n.py-=o*l}return!0}if(t.point&&c&&p>c){var l=t.pointCharge/c;n.px-=i*l,n.py-=o*l}}return!t.charge}}function t(n){n.px=ta.event.x,n.py=ta.event.y,a.resume()}var e,r,u,i,o,a={},c=ta.dispatch("start","tick","end"),l=[1,1],s=.9,f=vl,h=dl,g=-30,p=ml,v=.1,d=.64,m=[],y=[];return a.tick=function(){if((r*=.99)<.005)return c.end({type:"end",alpha:r=0}),!0;var t,e,a,f,h,p,d,M,x,b=m.length,_=y.length;for(e=0;_>e;++e)a=y[e],f=a.source,h=a.target,M=h.x-f.x,x=h.y-f.y,(p=M*M+x*x)&&(p=r*i[e]*((p=Math.sqrt(p))-u[e])/p,M*=p,x*=p,h.x-=M*(d=f.weight/(h.weight+f.weight)),h.y-=x*d,f.x+=M*(d=1-d),f.y+=x*d);if((d=r*v)&&(M=l[0]/2,x=l[1]/2,e=-1,d))for(;++e0?n:0:n>0&&(c.start({type:"start",alpha:r=n}),ta.timer(a.tick)),a):r},a.start=function(){function n(n,r){if(!e){for(e=new Array(c),a=0;c>a;++a)e[a]=[];for(a=0;l>a;++a){var u=y[a];e[u.source.index].push(u.target),e[u.target.index].push(u.source)}}for(var i,o=e[t],a=-1,l=o.length;++at;++t)(r=m[t]).index=t,r.weight=0;for(t=0;s>t;++t)r=y[t],"number"==typeof r.source&&(r.source=m[r.source]),"number"==typeof r.target&&(r.target=m[r.target]),++r.source.weight,++r.target.weight;for(t=0;c>t;++t)r=m[t],isNaN(r.x)&&(r.x=n("x",p)),isNaN(r.y)&&(r.y=n("y",v)),isNaN(r.px)&&(r.px=r.x),isNaN(r.py)&&(r.py=r.y);if(u=[],"function"==typeof f)for(t=0;s>t;++t)u[t]=+f.call(this,y[t],t);else for(t=0;s>t;++t)u[t]=f;if(i=[],"function"==typeof h)for(t=0;s>t;++t)i[t]=+h.call(this,y[t],t);else for(t=0;s>t;++t)i[t]=h;if(o=[],"function"==typeof g)for(t=0;c>t;++t)o[t]=+g.call(this,m[t],t);else for(t=0;c>t;++t)o[t]=g;return a.resume()},a.resume=function(){return a.alpha(.1)},a.stop=function(){return a.alpha(0)},a.drag=function(){return e||(e=ta.behavior.drag().origin(Et).on("dragstart.force",Xu).on("drag.force",t).on("dragend.force",$u)),arguments.length?(this.on("mouseover.force",Bu).on("mouseout.force",Wu).call(e),void 0):e},ta.rebind(a,c,"on")};var vl=20,dl=1,ml=1/0;ta.layout.hierarchy=function(){function n(u){var i,o=[u],a=[];for(u.depth=0;null!=(i=o.pop());)if(a.push(i),(l=e.call(n,i,i.depth))&&(c=l.length)){for(var c,l,s;--c>=0;)o.push(s=l[c]),s.parent=i,s.depth=i.depth+1;r&&(i.value=0),i.children=l}else r&&(i.value=+r.call(n,i,i.depth)||0),delete i.children;return Qu(u,function(n){var e,u;t&&(e=n.children)&&e.sort(t),r&&(u=n.parent)&&(u.value+=n.value)}),a}var t=ei,e=ni,r=ti;return n.sort=function(e){return arguments.length?(t=e,n):t},n.children=function(t){return arguments.length?(e=t,n):e},n.value=function(t){return arguments.length?(r=t,n):r},n.revalue=function(t){return r&&(Ku(t,function(n){n.children&&(n.value=0)}),Qu(t,function(t){var e;t.children||(t.value=+r.call(n,t,t.depth)||0),(e=t.parent)&&(e.value+=t.value)})),t},n},ta.layout.partition=function(){function n(t,e,r,u){var i=t.children;if(t.x=e,t.y=t.depth*u,t.dx=r,t.dy=u,i&&(o=i.length)){var o,a,c,l=-1;for(r=t.value?r/t.value:0;++lf?-1:1),p=(f-c*g)/ta.sum(l),v=ta.range(c),d=[];return null!=e&&v.sort(e===yl?function(n,t){return l[t]-l[n]}:function(n,t){return e(o[n],o[t])}),v.forEach(function(n){d[n]={data:o[n],value:a=l[n],startAngle:s,endAngle:s+=a*p+g,padAngle:h}}),d}var t=Number,e=yl,r=0,u=Pa,i=0;return n.value=function(e){return arguments.length?(t=e,n):t},n.sort=function(t){return arguments.length?(e=t,n):e},n.startAngle=function(t){return arguments.length?(r=t,n):r},n.endAngle=function(t){return arguments.length?(u=t,n):u},n.padAngle=function(t){return arguments.length?(i=t,n):i},n};var yl={};ta.layout.stack=function(){function n(a,c){if(!(h=a.length))return a;var l=a.map(function(e,r){return t.call(n,e,r)}),s=l.map(function(t){return t.map(function(t,e){return[i.call(n,t,e),o.call(n,t,e)]})}),f=e.call(n,s,c);l=ta.permute(l,f),s=ta.permute(s,f);var h,g,p,v,d=r.call(n,s,c),m=l[0].length;for(p=0;m>p;++p)for(u.call(n,l[0][p],v=d[p],s[0][p][1]),g=1;h>g;++g)u.call(n,l[g][p],v+=s[g-1][p][1],s[g][p][1]);return a}var t=Et,e=ai,r=ci,u=oi,i=ui,o=ii;return n.values=function(e){return arguments.length?(t=e,n):t},n.order=function(t){return arguments.length?(e="function"==typeof t?t:Ml.get(t)||ai,n):e},n.offset=function(t){return arguments.length?(r="function"==typeof t?t:xl.get(t)||ci,n):r},n.x=function(t){return arguments.length?(i=t,n):i},n.y=function(t){return arguments.length?(o=t,n):o},n.out=function(t){return arguments.length?(u=t,n):u},n};var Ml=ta.map({"inside-out":function(n){var t,e,r=n.length,u=n.map(li),i=n.map(si),o=ta.range(r).sort(function(n,t){return u[n]-u[t]}),a=0,c=0,l=[],s=[];for(t=0;r>t;++t)e=o[t],c>a?(a+=i[e],l.push(e)):(c+=i[e],s.push(e));return s.reverse().concat(l)},reverse:function(n){return ta.range(n.length).reverse()},"default":ai}),xl=ta.map({silhouette:function(n){var t,e,r,u=n.length,i=n[0].length,o=[],a=0,c=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];r>a&&(a=r),o.push(r)}for(e=0;i>e;++e)c[e]=(a-o[e])/2;return c},wiggle:function(n){var t,e,r,u,i,o,a,c,l,s=n.length,f=n[0],h=f.length,g=[];for(g[0]=c=l=0,e=1;h>e;++e){for(t=0,u=0;s>t;++t)u+=n[t][e][1];for(t=0,i=0,a=f[e][0]-f[e-1][0];s>t;++t){for(r=0,o=(n[t][e][1]-n[t][e-1][1])/(2*a);t>r;++r)o+=(n[r][e][1]-n[r][e-1][1])/a;i+=o*n[t][e][1]}g[e]=c-=u?i/u*a:0,l>c&&(l=c)}for(e=0;h>e;++e)g[e]-=l;return g},expand:function(n){var t,e,r,u=n.length,i=n[0].length,o=1/u,a=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];if(r)for(t=0;u>t;t++)n[t][e][1]/=r;else for(t=0;u>t;t++)n[t][e][1]=o}for(e=0;i>e;++e)a[e]=0;return a},zero:ci});ta.layout.histogram=function(){function n(n,i){for(var o,a,c=[],l=n.map(e,this),s=r.call(this,l,i),f=u.call(this,s,l,i),i=-1,h=l.length,g=f.length-1,p=t?1:1/h;++i0)for(i=-1;++i=s[0]&&a<=s[1]&&(o=c[ta.bisect(f,a,1,g)-1],o.y+=p,o.push(n[i]));return c}var t=!0,e=Number,r=pi,u=hi;return n.value=function(t){return arguments.length?(e=t,n):e},n.range=function(t){return arguments.length?(r=kt(t),n):r},n.bins=function(t){return arguments.length?(u="number"==typeof t?function(n){return gi(n,t)}:kt(t),n):u},n.frequency=function(e){return arguments.length?(t=!!e,n):t},n},ta.layout.pack=function(){function n(n,i){var o=e.call(this,n,i),a=o[0],c=u[0],l=u[1],s=null==t?Math.sqrt:"function"==typeof t?t:function(){return t};if(a.x=a.y=0,Qu(a,function(n){n.r=+s(n.value)}),Qu(a,Mi),r){var f=r*(t?1:Math.max(2*a.r/c,2*a.r/l))/2;Qu(a,function(n){n.r+=f}),Qu(a,Mi),Qu(a,function(n){n.r-=f})}return _i(a,c/2,l/2,t?1:1/Math.max(2*a.r/c,2*a.r/l)),o}var t,e=ta.layout.hierarchy().sort(vi),r=0,u=[1,1];return n.size=function(t){return arguments.length?(u=t,n):u},n.radius=function(e){return arguments.length?(t=null==e||"function"==typeof e?e:+e,n):t},n.padding=function(t){return arguments.length?(r=+t,n):r},Gu(n,e)},ta.layout.tree=function(){function n(n,u){var s=o.call(this,n,u),f=s[0],h=t(f);if(Qu(h,e),h.parent.m=-h.z,Ku(h,r),l)Ku(f,i);else{var g=f,p=f,v=f;Ku(f,function(n){n.xp.x&&(p=n),n.depth>v.depth&&(v=n)});var d=a(g,p)/2-g.x,m=c[0]/(p.x+a(p,g)/2+d),y=c[1]/(v.depth||1);Ku(f,function(n){n.x=(n.x+d)*m,n.y=n.depth*y})}return s}function t(n){for(var t,e={A:null,children:[n]},r=[e];null!=(t=r.pop());)for(var u,i=t.children,o=0,a=i.length;a>o;++o)r.push((i[o]=u={_:i[o],parent:t,children:(u=i[o].children)&&u.slice()||[],A:null,a:null,z:0,m:0,c:0,s:0,t:null,i:o}).a=u);return e.children[0]}function e(n){var t=n.children,e=n.parent.children,r=n.i?e[n.i-1]:null;if(t.length){Ni(n);var i=(t[0].z+t[t.length-1].z)/2;r?(n.z=r.z+a(n._,r._),n.m=n.z-i):n.z=i}else r&&(n.z=r.z+a(n._,r._));n.parent.A=u(n,r,n.parent.A||e[0])}function r(n){n._.x=n.z+n.parent.m,n.m+=n.parent.m}function u(n,t,e){if(t){for(var r,u=n,i=n,o=t,c=u.parent.children[0],l=u.m,s=i.m,f=o.m,h=c.m;o=Ei(o),u=ki(u),o&&u;)c=ki(c),i=Ei(i),i.a=n,r=o.z+f-u.z-l+a(o._,u._),r>0&&(Ai(Ci(o,n,e),n,r),l+=r,s+=r),f+=o.m,l+=u.m,h+=c.m,s+=i.m;o&&!Ei(i)&&(i.t=o,i.m+=f-s),u&&!ki(c)&&(c.t=u,c.m+=l-h,e=n)}return e}function i(n){n.x*=c[0],n.y=n.depth*c[1]}var o=ta.layout.hierarchy().sort(null).value(null),a=Si,c=[1,1],l=null;return n.separation=function(t){return arguments.length?(a=t,n):a},n.size=function(t){return arguments.length?(l=null==(c=t)?i:null,n):l?null:c},n.nodeSize=function(t){return arguments.length?(l=null==(c=t)?null:i,n):l?c:null},Gu(n,o)},ta.layout.cluster=function(){function n(n,i){var o,a=t.call(this,n,i),c=a[0],l=0;Qu(c,function(n){var t=n.children;t&&t.length?(n.x=qi(t),n.y=zi(t)):(n.x=o?l+=e(n,o):0,n.y=0,o=n)});var s=Li(c),f=Ti(c),h=s.x-e(s,f)/2,g=f.x+e(f,s)/2;return Qu(c,u?function(n){n.x=(n.x-c.x)*r[0],n.y=(c.y-n.y)*r[1]}:function(n){n.x=(n.x-h)/(g-h)*r[0],n.y=(1-(c.y?n.y/c.y:1))*r[1]}),a}var t=ta.layout.hierarchy().sort(null).value(null),e=Si,r=[1,1],u=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(u=null==(r=t),n):u?null:r},n.nodeSize=function(t){return arguments.length?(u=null!=(r=t),n):u?r:null},Gu(n,t)},ta.layout.treemap=function(){function n(n,t){for(var e,r,u=-1,i=n.length;++ut?0:t),e.area=isNaN(r)||0>=r?0:r}function t(e){var i=e.children;if(i&&i.length){var o,a,c,l=f(e),s=[],h=i.slice(),p=1/0,v="slice"===g?l.dx:"dice"===g?l.dy:"slice-dice"===g?1&e.depth?l.dy:l.dx:Math.min(l.dx,l.dy);for(n(h,l.dx*l.dy/e.value),s.area=0;(c=h.length)>0;)s.push(o=h[c-1]),s.area+=o.area,"squarify"!==g||(a=r(s,v))<=p?(h.pop(),p=a):(s.area-=s.pop().area,u(s,v,l,!1),v=Math.min(l.dx,l.dy),s.length=s.area=0,p=1/0);s.length&&(u(s,v,l,!0),s.length=s.area=0),i.forEach(t)}}function e(t){var r=t.children;if(r&&r.length){var i,o=f(t),a=r.slice(),c=[];for(n(a,o.dx*o.dy/t.value),c.area=0;i=a.pop();)c.push(i),c.area+=i.area,null!=i.z&&(u(c,i.z?o.dx:o.dy,o,!a.length),c.length=c.area=0);r.forEach(e)}}function r(n,t){for(var e,r=n.area,u=0,i=1/0,o=-1,a=n.length;++oe&&(i=e),e>u&&(u=e));return r*=r,t*=t,r?Math.max(t*u*p/r,r/(t*i*p)):1/0}function u(n,t,e,r){var u,i=-1,o=n.length,a=e.x,l=e.y,s=t?c(n.area/t):0;if(t==e.dx){for((r||s>e.dy)&&(s=e.dy);++ie.dx)&&(s=e.dx);++ie&&(t=1),1>e&&(n=0),function(){var e,r,u;do e=2*Math.random()-1,r=2*Math.random()-1,u=e*e+r*r;while(!u||u>1);return n+t*e*Math.sqrt(-2*Math.log(u)/u)}},logNormal:function(){var n=ta.random.normal.apply(ta,arguments);return function(){return Math.exp(n())}},bates:function(n){var t=ta.random.irwinHall(n);return function(){return t()/n}},irwinHall:function(n){return function(){for(var t=0,e=0;n>e;e++)t+=Math.random();return t}}},ta.scale={};var bl={floor:Et,ceil:Et};ta.scale.linear=function(){return Yi([0,1],[0,1],mu,!1)};var _l={s:1,g:1,p:1,r:1,e:1};ta.scale.log=function(){return Ji(ta.scale.linear().domain([0,1]),10,!0,[1,10])};var wl=ta.format(".0e"),Sl={floor:function(n){return-Math.ceil(-n)},ceil:function(n){return-Math.floor(-n)}};ta.scale.pow=function(){return Gi(ta.scale.linear(),1,[0,1])},ta.scale.sqrt=function(){return ta.scale.pow().exponent(.5)},ta.scale.ordinal=function(){return Qi([],{t:"range",a:[[]]})},ta.scale.category10=function(){return ta.scale.ordinal().range(kl)},ta.scale.category20=function(){return ta.scale.ordinal().range(El)},ta.scale.category20b=function(){return ta.scale.ordinal().range(Al)},ta.scale.category20c=function(){return ta.scale.ordinal().range(Nl)};var kl=[2062260,16744206,2924588,14034728,9725885,9197131,14907330,8355711,12369186,1556175].map(yt),El=[2062260,11454440,16744206,16759672,2924588,10018698,14034728,16750742,9725885,12955861,9197131,12885140,14907330,16234194,8355711,13092807,12369186,14408589,1556175,10410725].map(yt),Al=[3750777,5395619,7040719,10264286,6519097,9216594,11915115,13556636,9202993,12426809,15186514,15190932,8666169,11356490,14049643,15177372,8077683,10834324,13528509,14589654].map(yt),Nl=[3244733,7057110,10406625,13032431,15095053,16616764,16625259,16634018,3253076,7652470,10607003,13101504,7695281,10394312,12369372,14342891,6513507,9868950,12434877,14277081].map(yt);ta.scale.quantile=function(){return no([],[])},ta.scale.quantize=function(){return to(0,1,[0,1])},ta.scale.threshold=function(){return eo([.5],[0,1])},ta.scale.identity=function(){return ro([0,1])},ta.svg={},ta.svg.arc=function(){function n(){var n=Math.max(0,+e.apply(this,arguments)),l=Math.max(0,+r.apply(this,arguments)),s=o.apply(this,arguments)-ja,f=a.apply(this,arguments)-ja,h=Math.abs(f-s),g=s>f?0:1;if(n>l&&(p=l,l=n,n=p),h>=Ua)return t(l,g)+(n?t(n,1-g):"")+"Z";var p,v,d,m,y,M,x,b,_,w,S,k,E=0,A=0,N=[];if((m=(+c.apply(this,arguments)||0)/2)&&(d=i===Cl?Math.sqrt(n*n+l*l):+i.apply(this,arguments),g||(A*=-1),l&&(A=nt(d/l*Math.sin(m))),n&&(E=nt(d/n*Math.sin(m)))),l){y=l*Math.cos(s+A),M=l*Math.sin(s+A),x=l*Math.cos(f-A),b=l*Math.sin(f-A);var C=Math.abs(f-s-2*A)<=Da?0:1;if(A&&so(y,M,x,b)===g^C){var z=(s+f)/2;y=l*Math.cos(z),M=l*Math.sin(z),x=b=null}}else y=M=0;if(n){_=n*Math.cos(f-E),w=n*Math.sin(f-E),S=n*Math.cos(s+E),k=n*Math.sin(s+E);var q=Math.abs(s-f+2*E)<=Da?0:1;if(E&&so(_,w,S,k)===1-g^q){var L=(s+f)/2;_=n*Math.cos(L),w=n*Math.sin(L),S=k=null}}else _=w=0;if((p=Math.min(Math.abs(l-n)/2,+u.apply(this,arguments)))>.001){v=l>n^g?0:1;var T=null==S?[_,w]:null==x?[y,M]:Lr([y,M],[S,k],[x,b],[_,w]),R=y-T[0],D=M-T[1],P=x-T[0],U=b-T[1],j=1/Math.sin(Math.acos((R*P+D*U)/(Math.sqrt(R*R+D*D)*Math.sqrt(P*P+U*U)))/2),F=Math.sqrt(T[0]*T[0]+T[1]*T[1]);if(null!=x){var H=Math.min(p,(l-F)/(j+1)),O=fo(null==S?[_,w]:[S,k],[y,M],l,H,g),Y=fo([x,b],[_,w],l,H,g);p===H?N.push("M",O[0],"A",H,",",H," 0 0,",v," ",O[1],"A",l,",",l," 0 ",1-g^so(O[1][0],O[1][1],Y[1][0],Y[1][1]),",",g," ",Y[1],"A",H,",",H," 0 0,",v," ",Y[0]):N.push("M",O[0],"A",H,",",H," 0 1,",v," ",Y[0])}else N.push("M",y,",",M);if(null!=S){var I=Math.min(p,(n-F)/(j-1)),Z=fo([y,M],[S,k],n,-I,g),V=fo([_,w],null==x?[y,M]:[x,b],n,-I,g);p===I?N.push("L",V[0],"A",I,",",I," 0 0,",v," ",V[1],"A",n,",",n," 0 ",g^so(V[1][0],V[1][1],Z[1][0],Z[1][1]),",",1-g," ",Z[1],"A",I,",",I," 0 0,",v," ",Z[0]):N.push("L",V[0],"A",I,",",I," 0 0,",v," ",Z[0])}else N.push("L",_,",",w)}else N.push("M",y,",",M),null!=x&&N.push("A",l,",",l," 0 ",C,",",g," ",x,",",b),N.push("L",_,",",w),null!=S&&N.push("A",n,",",n," 0 ",q,",",1-g," ",S,",",k);return N.push("Z"),N.join("")}function t(n,t){return"M0,"+n+"A"+n+","+n+" 0 1,"+t+" 0,"+-n+"A"+n+","+n+" 0 1,"+t+" 0,"+n}var e=io,r=oo,u=uo,i=Cl,o=ao,a=co,c=lo;return n.innerRadius=function(t){return arguments.length?(e=kt(t),n):e},n.outerRadius=function(t){return arguments.length?(r=kt(t),n):r},n.cornerRadius=function(t){return arguments.length?(u=kt(t),n):u},n.padRadius=function(t){return arguments.length?(i=t==Cl?Cl:kt(t),n):i},n.startAngle=function(t){return arguments.length?(o=kt(t),n):o},n.endAngle=function(t){return arguments.length?(a=kt(t),n):a},n.padAngle=function(t){return arguments.length?(c=kt(t),n):c},n.centroid=function(){var n=(+e.apply(this,arguments)+ +r.apply(this,arguments))/2,t=(+o.apply(this,arguments)+ +a.apply(this,arguments))/2-ja;return[Math.cos(t)*n,Math.sin(t)*n]},n};var Cl="auto";ta.svg.line=function(){return ho(Et)};var zl=ta.map({linear:go,"linear-closed":po,step:vo,"step-before":mo,"step-after":yo,basis:So,"basis-open":ko,"basis-closed":Eo,bundle:Ao,cardinal:bo,"cardinal-open":Mo,"cardinal-closed":xo,monotone:To});zl.forEach(function(n,t){t.key=n,t.closed=/-closed$/.test(n)});var ql=[0,2/3,1/3,0],Ll=[0,1/3,2/3,0],Tl=[0,1/6,2/3,1/6];ta.svg.line.radial=function(){var n=ho(Ro);return n.radius=n.x,delete n.x,n.angle=n.y,delete n.y,n},mo.reverse=yo,yo.reverse=mo,ta.svg.area=function(){return Do(Et)},ta.svg.area.radial=function(){var n=Do(Ro);return n.radius=n.x,delete n.x,n.innerRadius=n.x0,delete n.x0,n.outerRadius=n.x1,delete n.x1,n.angle=n.y,delete n.y,n.startAngle=n.y0,delete n.y0,n.endAngle=n.y1,delete n.y1,n},ta.svg.chord=function(){function n(n,a){var c=t(this,i,n,a),l=t(this,o,n,a);return"M"+c.p0+r(c.r,c.p1,c.a1-c.a0)+(e(c,l)?u(c.r,c.p1,c.r,c.p0):u(c.r,c.p1,l.r,l.p0)+r(l.r,l.p1,l.a1-l.a0)+u(l.r,l.p1,c.r,c.p0))+"Z"}function t(n,t,e,r){var u=t.call(n,e,r),i=a.call(n,u,r),o=c.call(n,u,r)-ja,s=l.call(n,u,r)-ja;return{r:i,a0:o,a1:s,p0:[i*Math.cos(o),i*Math.sin(o)],p1:[i*Math.cos(s),i*Math.sin(s)]}}function e(n,t){return n.a0==t.a0&&n.a1==t.a1}function r(n,t,e){return"A"+n+","+n+" 0 "+ +(e>Da)+",1 "+t}function u(n,t,e,r){return"Q 0,0 "+r}var i=mr,o=yr,a=Po,c=ao,l=co;return n.radius=function(t){return arguments.length?(a=kt(t),n):a},n.source=function(t){return arguments.length?(i=kt(t),n):i},n.target=function(t){return arguments.length?(o=kt(t),n):o},n.startAngle=function(t){return arguments.length?(c=kt(t),n):c},n.endAngle=function(t){return arguments.length?(l=kt(t),n):l},n},ta.svg.diagonal=function(){function n(n,u){var i=t.call(this,n,u),o=e.call(this,n,u),a=(i.y+o.y)/2,c=[i,{x:i.x,y:a},{x:o.x,y:a},o];return c=c.map(r),"M"+c[0]+"C"+c[1]+" "+c[2]+" "+c[3]}var t=mr,e=yr,r=Uo;return n.source=function(e){return arguments.length?(t=kt(e),n):t},n.target=function(t){return arguments.length?(e=kt(t),n):e},n.projection=function(t){return arguments.length?(r=t,n):r},n},ta.svg.diagonal.radial=function(){var n=ta.svg.diagonal(),t=Uo,e=n.projection;return n.projection=function(n){return arguments.length?e(jo(t=n)):t},n},ta.svg.symbol=function(){function n(n,r){return(Rl.get(t.call(this,n,r))||Oo)(e.call(this,n,r))}var t=Ho,e=Fo;return n.type=function(e){return arguments.length?(t=kt(e),n):t},n.size=function(t){return arguments.length?(e=kt(t),n):e},n};var Rl=ta.map({circle:Oo,cross:function(n){var t=Math.sqrt(n/5)/2;return"M"+-3*t+","+-t+"H"+-t+"V"+-3*t+"H"+t+"V"+-t+"H"+3*t+"V"+t+"H"+t+"V"+3*t+"H"+-t+"V"+t+"H"+-3*t+"Z"},diamond:function(n){var t=Math.sqrt(n/(2*Pl)),e=t*Pl;return"M0,"+-t+"L"+e+",0"+" 0,"+t+" "+-e+",0"+"Z"},square:function(n){var t=Math.sqrt(n)/2;return"M"+-t+","+-t+"L"+t+","+-t+" "+t+","+t+" "+-t+","+t+"Z"},"triangle-down":function(n){var t=Math.sqrt(n/Dl),e=t*Dl/2;return"M0,"+e+"L"+t+","+-e+" "+-t+","+-e+"Z"},"triangle-up":function(n){var t=Math.sqrt(n/Dl),e=t*Dl/2;return"M0,"+-e+"L"+t+","+e+" "+-t+","+e+"Z"}});ta.svg.symbolTypes=Rl.keys();var Dl=Math.sqrt(3),Pl=Math.tan(30*Fa);ka.transition=function(n){for(var t,e,r=Ul||++Ol,u=Xo(n),i=[],o=jl||{time:Date.now(),ease:Su,delay:0,duration:250},a=-1,c=this.length;++ai;i++){u.push(t=[]);for(var e=this[i],a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a,i)&&t.push(r)}return Io(u,this.namespace,this.id)},Hl.tween=function(n,t){var e=this.id,r=this.namespace;return arguments.length<2?this.node()[r][e].tween.get(n):H(this,null==t?function(t){t[r][e].tween.remove(n)}:function(u){u[r][e].tween.set(n,t)})},Hl.attr=function(n,t){function e(){this.removeAttribute(a)}function r(){this.removeAttributeNS(a.space,a.local)}function u(n){return null==n?e:(n+="",function(){var t,e=this.getAttribute(a);return e!==n&&(t=o(e,n),function(n){this.setAttribute(a,t(n))})})}function i(n){return null==n?r:(n+="",function(){var t,e=this.getAttributeNS(a.space,a.local);return e!==n&&(t=o(e,n),function(n){this.setAttributeNS(a.space,a.local,t(n))})})}if(arguments.length<2){for(t in n)this.attr(t,n[t]);return this}var o="transform"==n?Hu:mu,a=ta.ns.qualify(n);return Zo(this,"attr."+n,t,a.local?i:u)},Hl.attrTween=function(n,t){function e(n,e){var r=t.call(this,n,e,this.getAttribute(u));return r&&function(n){this.setAttribute(u,r(n))}}function r(n,e){var r=t.call(this,n,e,this.getAttributeNS(u.space,u.local));return r&&function(n){this.setAttributeNS(u.space,u.local,r(n))}}var u=ta.ns.qualify(n);return this.tween("attr."+n,u.local?r:e)},Hl.style=function(n,t,e){function r(){this.style.removeProperty(n)}function u(t){return null==t?r:(t+="",function(){var r,u=oa.getComputedStyle(this,null).getPropertyValue(n);return u!==t&&(r=mu(u,t),function(t){this.style.setProperty(n,r(t),e)})})}var i=arguments.length;if(3>i){if("string"!=typeof n){2>i&&(t="");for(e in n)this.style(e,n[e],t);return this}e=""}return Zo(this,"style."+n,t,u)},Hl.styleTween=function(n,t,e){function r(r,u){var i=t.call(this,r,u,oa.getComputedStyle(this,null).getPropertyValue(n));return i&&function(t){this.style.setProperty(n,i(t),e)}}return arguments.length<3&&(e=""),this.tween("style."+n,r)},Hl.text=function(n){return Zo(this,"text",n,Vo)},Hl.remove=function(){var n=this.namespace;return this.each("end.transition",function(){var t;this[n].count<2&&(t=this.parentNode)&&t.removeChild(this)})},Hl.ease=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].ease:("function"!=typeof n&&(n=ta.ease.apply(ta,arguments)),H(this,function(r){r[e][t].ease=n}))},Hl.delay=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].delay:H(this,"function"==typeof n?function(r,u,i){r[e][t].delay=+n.call(r,r.__data__,u,i)}:(n=+n,function(r){r[e][t].delay=n}))},Hl.duration=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].duration:H(this,"function"==typeof n?function(r,u,i){r[e][t].duration=Math.max(1,n.call(r,r.__data__,u,i))}:(n=Math.max(1,n),function(r){r[e][t].duration=n}))},Hl.each=function(n,t){var e=this.id,r=this.namespace;if(arguments.length<2){var u=jl,i=Ul;try{Ul=e,H(this,function(t,u,i){jl=t[r][e],n.call(t,t.__data__,u,i)})}finally{jl=u,Ul=i}}else H(this,function(u){var i=u[r][e];(i.event||(i.event=ta.dispatch("start","end","interrupt"))).on(n,t)});return this},Hl.transition=function(){for(var n,t,e,r,u=this.id,i=++Ol,o=this.namespace,a=[],c=0,l=this.length;l>c;c++){a.push(n=[]);for(var t=this[c],s=0,f=t.length;f>s;s++)(e=t[s])&&(r=e[o][u],$o(e,s,o,i,{time:r.time,ease:r.ease,delay:r.delay+r.duration,duration:r.duration})),n.push(e)}return Io(a,o,i)},ta.svg.axis=function(){function n(n){n.each(function(){var n,l=ta.select(this),s=this.__chart__||e,f=this.__chart__=e.copy(),h=null==c?f.ticks?f.ticks.apply(f,a):f.domain():c,g=null==t?f.tickFormat?f.tickFormat.apply(f,a):Et:t,p=l.selectAll(".tick").data(h,f),v=p.enter().insert("g",".domain").attr("class","tick").style("opacity",Ta),d=ta.transition(p.exit()).style("opacity",Ta).remove(),m=ta.transition(p.order()).style("opacity",1),y=Math.max(u,0)+o,M=Ui(f),x=l.selectAll(".domain").data([0]),b=(x.enter().append("path").attr("class","domain"),ta.transition(x));v.append("line"),v.append("text");var _,w,S,k,E=v.select("line"),A=m.select("line"),N=p.select("text").text(g),C=v.select("text"),z=m.select("text"),q="top"===r||"left"===r?-1:1;if("bottom"===r||"top"===r?(n=Bo,_="x",S="y",w="x2",k="y2",N.attr("dy",0>q?"0em":".71em").style("text-anchor","middle"),b.attr("d","M"+M[0]+","+q*i+"V0H"+M[1]+"V"+q*i)):(n=Wo,_="y",S="x",w="y2",k="x2",N.attr("dy",".32em").style("text-anchor",0>q?"end":"start"),b.attr("d","M"+q*i+","+M[0]+"H0V"+M[1]+"H"+q*i)),E.attr(k,q*u),C.attr(S,q*y),A.attr(w,0).attr(k,q*u),z.attr(_,0).attr(S,q*y),f.rangeBand){var L=f,T=L.rangeBand()/2;s=f=function(n){return L(n)+T}}else s.rangeBand?s=f:d.call(n,f,s);v.call(n,s,f),m.call(n,f,f)})}var t,e=ta.scale.linear(),r=Yl,u=6,i=6,o=3,a=[10],c=null;return n.scale=function(t){return arguments.length?(e=t,n):e},n.orient=function(t){return arguments.length?(r=t in Il?t+"":Yl,n):r},n.ticks=function(){return arguments.length?(a=arguments,n):a},n.tickValues=function(t){return arguments.length?(c=t,n):c},n.tickFormat=function(e){return arguments.length?(t=e,n):t},n.tickSize=function(t){var e=arguments.length;return e?(u=+t,i=+arguments[e-1],n):u},n.innerTickSize=function(t){return arguments.length?(u=+t,n):u},n.outerTickSize=function(t){return arguments.length?(i=+t,n):i},n.tickPadding=function(t){return arguments.length?(o=+t,n):o},n.tickSubdivide=function(){return arguments.length&&n},n};var Yl="bottom",Il={top:1,right:1,bottom:1,left:1};ta.svg.brush=function(){function n(i){i.each(function(){var i=ta.select(this).style("pointer-events","all").style("-webkit-tap-highlight-color","rgba(0,0,0,0)").on("mousedown.brush",u).on("touchstart.brush",u),o=i.selectAll(".background").data([0]);o.enter().append("rect").attr("class","background").style("visibility","hidden").style("cursor","crosshair"),i.selectAll(".extent").data([0]).enter().append("rect").attr("class","extent").style("cursor","move");var a=i.selectAll(".resize").data(p,Et);a.exit().remove(),a.enter().append("g").attr("class",function(n){return"resize "+n}).style("cursor",function(n){return Zl[n]}).append("rect").attr("x",function(n){return/[ew]$/.test(n)?-3:null}).attr("y",function(n){return/^[ns]/.test(n)?-3:null}).attr("width",6).attr("height",6).style("visibility","hidden"),a.style("display",n.empty()?"none":null);var s,f=ta.transition(i),h=ta.transition(o);c&&(s=Ui(c),h.attr("x",s[0]).attr("width",s[1]-s[0]),e(f)),l&&(s=Ui(l),h.attr("y",s[0]).attr("height",s[1]-s[0]),r(f)),t(f)})}function t(n){n.selectAll(".resize").attr("transform",function(n){return"translate("+s[+/e$/.test(n)]+","+f[+/^s/.test(n)]+")"})}function e(n){n.select(".extent").attr("x",s[0]),n.selectAll(".extent,.n>rect,.s>rect").attr("width",s[1]-s[0])}function r(n){n.select(".extent").attr("y",f[0]),n.selectAll(".extent,.e>rect,.w>rect").attr("height",f[1]-f[0])}function u(){function u(){32==ta.event.keyCode&&(N||(y=null,z[0]-=s[1],z[1]-=f[1],N=2),b())}function p(){32==ta.event.keyCode&&2==N&&(z[0]+=s[1],z[1]+=f[1],N=0,b())}function v(){var n=ta.mouse(x),u=!1;M&&(n[0]+=M[0],n[1]+=M[1]),N||(ta.event.altKey?(y||(y=[(s[0]+s[1])/2,(f[0]+f[1])/2]),z[0]=s[+(n[0]p?(u=r,r=p):u=p),v[0]!=r||v[1]!=u?(e?o=null:i=null,v[0]=r,v[1]=u,!0):void 0}function m(){v(),S.style("pointer-events","all").selectAll(".resize").style("display",n.empty()?"none":null),ta.select("body").style("cursor",null),q.on("mousemove.brush",null).on("mouseup.brush",null).on("touchmove.brush",null).on("touchend.brush",null).on("keydown.brush",null).on("keyup.brush",null),C(),w({type:"brushend"})}var y,M,x=this,_=ta.select(ta.event.target),w=a.of(x,arguments),S=ta.select(x),k=_.datum(),E=!/^(n|s)$/.test(k)&&c,A=!/^(e|w)$/.test(k)&&l,N=_.classed("extent"),C=X(),z=ta.mouse(x),q=ta.select(oa).on("keydown.brush",u).on("keyup.brush",p);if(ta.event.changedTouches?q.on("touchmove.brush",v).on("touchend.brush",m):q.on("mousemove.brush",v).on("mouseup.brush",m),S.interrupt().selectAll("*").interrupt(),N)z[0]=s[0]-z[0],z[1]=f[0]-z[1];else if(k){var L=+/w$/.test(k),T=+/^n/.test(k);M=[s[1-L]-z[0],f[1-T]-z[1]],z[0]=s[L],z[1]=f[T]}else ta.event.altKey&&(y=z.slice());S.style("pointer-events","none").selectAll(".resize").style("display",null),ta.select("body").style("cursor",_.style("cursor")),w({type:"brushstart"}),v()}var i,o,a=w(n,"brushstart","brush","brushend"),c=null,l=null,s=[0,0],f=[0,0],h=!0,g=!0,p=Vl[0];return n.event=function(n){n.each(function(){var n=a.of(this,arguments),t={x:s,y:f,i:i,j:o},e=this.__chart__||t;this.__chart__=t,Ul?ta.select(this).transition().each("start.brush",function(){i=e.i,o=e.j,s=e.x,f=e.y,n({type:"brushstart"})}).tween("brush:brush",function(){var e=yu(s,t.x),r=yu(f,t.y);return i=o=null,function(u){s=t.x=e(u),f=t.y=r(u),n({type:"brush",mode:"resize"})}}).each("end.brush",function(){i=t.i,o=t.j,n({type:"brush",mode:"resize"}),n({type:"brushend"})}):(n({type:"brushstart"}),n({type:"brush",mode:"resize"}),n({type:"brushend"}))})},n.x=function(t){return arguments.length?(c=t,p=Vl[!c<<1|!l],n):c},n.y=function(t){return arguments.length?(l=t,p=Vl[!c<<1|!l],n):l},n.clamp=function(t){return arguments.length?(c&&l?(h=!!t[0],g=!!t[1]):c?h=!!t:l&&(g=!!t),n):c&&l?[h,g]:c?h:l?g:null},n.extent=function(t){var e,r,u,a,h;return arguments.length?(c&&(e=t[0],r=t[1],l&&(e=e[0],r=r[0]),i=[e,r],c.invert&&(e=c(e),r=c(r)),e>r&&(h=e,e=r,r=h),(e!=s[0]||r!=s[1])&&(s=[e,r])),l&&(u=t[0],a=t[1],c&&(u=u[1],a=a[1]),o=[u,a],l.invert&&(u=l(u),a=l(a)),u>a&&(h=u,u=a,a=h),(u!=f[0]||a!=f[1])&&(f=[u,a])),n):(c&&(i?(e=i[0],r=i[1]):(e=s[0],r=s[1],c.invert&&(e=c.invert(e),r=c.invert(r)),e>r&&(h=e,e=r,r=h))),l&&(o?(u=o[0],a=o[1]):(u=f[0],a=f[1],l.invert&&(u=l.invert(u),a=l.invert(a)),u>a&&(h=u,u=a,a=h))),c&&l?[[e,u],[r,a]]:c?[e,r]:l&&[u,a])},n.clear=function(){return n.empty()||(s=[0,0],f=[0,0],i=o=null),n},n.empty=function(){return!!c&&s[0]==s[1]||!!l&&f[0]==f[1]},ta.rebind(n,a,"on")};var Zl={n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},Vl=[["n","e","s","w","nw","ne","se","sw"],["e","w"],["n","s"],[]],Xl=fc.format=mc.timeFormat,$l=Xl.utc,Bl=$l("%Y-%m-%dT%H:%M:%S.%LZ");Xl.iso=Date.prototype.toISOString&&+new Date("2000-01-01T00:00:00.000Z")?Jo:Bl,Jo.parse=function(n){var t=new Date(n);return isNaN(t)?null:t},Jo.toString=Bl.toString,fc.second=Ft(function(n){return new hc(1e3*Math.floor(n/1e3))},function(n,t){n.setTime(n.getTime()+1e3*Math.floor(t))},function(n){return n.getSeconds()}),fc.seconds=fc.second.range,fc.seconds.utc=fc.second.utc.range,fc.minute=Ft(function(n){return new hc(6e4*Math.floor(n/6e4))},function(n,t){n.setTime(n.getTime()+6e4*Math.floor(t))},function(n){return n.getMinutes()}),fc.minutes=fc.minute.range,fc.minutes.utc=fc.minute.utc.range,fc.hour=Ft(function(n){var t=n.getTimezoneOffset()/60;return new hc(36e5*(Math.floor(n/36e5-t)+t))},function(n,t){n.setTime(n.getTime()+36e5*Math.floor(t))},function(n){return n.getHours()}),fc.hours=fc.hour.range,fc.hours.utc=fc.hour.utc.range,fc.month=Ft(function(n){return n=fc.day(n),n.setDate(1),n},function(n,t){n.setMonth(n.getMonth()+t)},function(n){return n.getMonth()}),fc.months=fc.month.range,fc.months.utc=fc.month.utc.range;var Wl=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],Jl=[[fc.second,1],[fc.second,5],[fc.second,15],[fc.second,30],[fc.minute,1],[fc.minute,5],[fc.minute,15],[fc.minute,30],[fc.hour,1],[fc.hour,3],[fc.hour,6],[fc.hour,12],[fc.day,1],[fc.day,2],[fc.week,1],[fc.month,1],[fc.month,3],[fc.year,1]],Gl=Xl.multi([[".%L",function(n){return n.getMilliseconds()}],[":%S",function(n){return n.getSeconds()}],["%I:%M",function(n){return n.getMinutes()}],["%I %p",function(n){return n.getHours()}],["%a %d",function(n){return n.getDay()&&1!=n.getDate()}],["%b %d",function(n){return 1!=n.getDate()}],["%B",function(n){return n.getMonth()}],["%Y",Ne]]),Kl={range:function(n,t,e){return ta.range(Math.ceil(n/e)*e,+t,e).map(Ko)},floor:Et,ceil:Et};Jl.year=fc.year,fc.scale=function(){return Go(ta.scale.linear(),Jl,Gl)};var Ql=Jl.map(function(n){return[n[0].utc,n[1]]}),ns=$l.multi([[".%L",function(n){return n.getUTCMilliseconds()}],[":%S",function(n){return n.getUTCSeconds()}],["%I:%M",function(n){return n.getUTCMinutes()}],["%I %p",function(n){return n.getUTCHours()}],["%a %d",function(n){return n.getUTCDay()&&1!=n.getUTCDate()}],["%b %d",function(n){return 1!=n.getUTCDate()}],["%B",function(n){return n.getUTCMonth()}],["%Y",Ne]]);Ql.year=fc.year.utc,fc.scale.utc=function(){return Go(ta.scale.linear(),Ql,ns)},ta.text=At(function(n){return n.responseText}),ta.json=function(n,t){return Nt(n,"application/json",Qo,t)},ta.html=function(n,t){return Nt(n,"text/html",na,t)},ta.xml=At(function(n){return n.responseXML}),"function"==typeof define&&define.amd?define(ta):"object"==typeof module&&module.exports&&(module.exports=ta),this.d3=ta}(); \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/date-range.js b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/date-range.js new file mode 100755 index 00000000..e69de29b diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/discretebarchart.js b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/discretebarchart.js new file mode 100755 index 00000000..e69de29b diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/graph_util.js b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/graph_util.js new file mode 100755 index 00000000..e0ab53c4 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/graph_util.js @@ -0,0 +1,116 @@ +var fromDate; +var toDate; + +var configObject = { + + format: 'DD.MM.YYYY HH:mm', + separator: ' to ', + language: 'auto', + startOfWeek: 'sunday',// or sunday + getValue: function () { + return this.value; + }, + setValue: function (s) { + this.value = s; + }, + startDate: false, + endDate: false, + minDays: 0, + maxDays: 0, + showShortcuts: true, + time: { + enabled: true + }, + shortcuts: { + //'prev-days': [1,3,5,7], + 'next-days': [3, 5, 7], + //'prev' : ['week','month','year'], + 'next': ['week', 'month', 'year'] + }, + customShortcuts: [], + inline: false, + container: 'body', + alwaysOpen: false, + singleDate: false, + batchMode: false, + stickyMonths: false +}; + +$('#date-range1').dateRangePicker(configObject) + .bind('datepicker-apply', function (event, dateRange) { + fromDate = dateRange.date1 != "Invalid Date" ? dateRange.date1.getTime() / 1000 : null; + toDate = dateRange.date2 != "Invalid Date" ? dateRange.date2.getTime() / 1000 : null; + }); + +$('#btn-draw-graphs').on('click', function () { + var deviceId = $('#device-id').val(); + getStats(deviceId, fromDate, toDate); +}); + +function getStats(deviceId, from, to) { + + var requestData = new Object(); + + requestData['deviceId'] = getUrlParameter('deviceId'); + + if (from) { + requestData['from'] = from; + } + + if (to) { + requestData['to'] = to; + } + + var getStatsRequest = $.ajax({ + url: "api/stats", + method: "GET", + data: requestData + }); + + getStatsRequest.done(function (stats) { + updateGraphs(JSON.parse(stats)); + }); + + getStatsRequest.fail(function (jqXHR, textStatus) { + alert("Request failed: " + textStatus); + }); + +} + +function getUrlParameter(paramName) { + var pageURL = window.location.search.substring(1); + var urlVariables = pageURL.split('&'); + for (var i = 0; i < urlVariables.length; i++) { + var parameterName = urlVariables[i].split('='); + if (parameterName[0] == paramName) { + return parameterName[1]; + } + } +} + +function updateGraphs(stats) { + + var temperatureData = stats['temperatureData']; + updateTemperatureGraph(convertStatsToGraphData(temperatureData)); + + var lightData = stats['lightData']; + updateLightGraph(convertStatsToGraphData(lightData)); + + var motionData = stats['motionData']; + updateMotionGraph(convertStatsToGraphData(motionData)); + + var sonarData = stats['sonarData']; + updateSonarGraph(convertStatsToGraphData(sonarData)); + +} + +function convertStatsToGraphData(stats) { + + var graphData = new Array(); + + for (var i = 0; i < stats.length; i++) { + graphData.push({x: parseInt(stats[i]['time']) * 1000, y: stats[i]['value']}) + } + + return graphData; +} \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/jquery.daterangepicker.js b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/jquery.daterangepicker.js new file mode 100755 index 00000000..0d8ee556 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/jquery.daterangepicker.js @@ -0,0 +1,1627 @@ +// daterangepicker.js +// version : 0.0.5 +// author : Chunlong Liu +// last updated at: 2014-05-27 +// license : MIT +// www.jszen.com + +(function (factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(['jquery', 'moment'], factory); + } else if (typeof exports === 'object' && typeof module !== 'undefined') { + // CommonJS. Register as a module + module.exports = factory(require('jquery'), require('moment')); + } else { + // Browser globals + factory(jQuery, moment); + } +}(function ($, moment) +{ + + $.dateRangePickerLanguages = + { + 'az': + { + 'selected': 'Seçildi:', + 'day':' gün', + 'days': ' gün', + 'apply': 'tətbiq', + 'week-1' : '1', + 'week-2' : '2', + 'week-3' : '3', + 'week-4' : '4', + 'week-5' : '5', + 'week-6' : '6', + 'week-7' : '7', + 'month-name': ['yanvar','fevral','mart','aprel','may','iyun','iyul','avqust','sentyabr','oktyabr','noyabr','dekabr'], + 'shortcuts' : 'Qısayollar', + 'past': 'Keçmiş', + 'following':'Növbəti', + 'previous' : '   ', + 'prev-week' : 'Öncəki həftə', + 'prev-month' : 'Öncəki ay', + 'prev-year' : 'Öncəki il', + 'next': '   ', + 'next-week':'Növbəti həftə', + 'next-month':'Növbəti ay', + 'next-year':'Növbəti il', + 'less-than' : 'Tarix aralığı %d gündən çox olmamalıdır', + 'more-than' : 'Tarix aralığı %d gündən az olmamalıdır', + 'default-more' : '%d gündən çox bir tarix seçin', + 'default-single' : 'Tarix seçin', + 'default-less' : '%d gündən az bir tarix seçin', + 'default-range' : '%d və %d gün aralığında tarixlər seçin', + 'default-default': 'Tarix aralığı seçin' + }, + 'cn': + { + 'selected': '已选择:', + 'day':'天', + 'days': '天', + 'apply': '确定', + 'week-1' : '一', + 'week-2' : '二', + 'week-3' : '三', + 'week-4' : '四', + 'week-5' : '五', + 'week-6' : '六', + 'week-7' : '日', + 'month-name': ['一月','二月','三月','四月','五月','六月','七月','八月','九月','十月','十一月','十二月'], + 'shortcuts' : '快捷选择', + 'past': '过去', + 'following':'将来', + 'previous' : '   ', + 'prev-week' : '上周', + 'prev-month' : '上个月', + 'prev-year' : '去年', + 'next': '   ', + 'next-week':'下周', + 'next-month':'下个月', + 'next-year':'明年', + 'less-than' : '所选日期范围不能大于%d天', + 'more-than' : '所选日期范围不能小于%d天', + 'default-more' : '请选择大于%d天的日期范围', + 'default-less' : '请选择小于%d天的日期范围', + 'default-range' : '请选择%d天到%d天的日期范围', + 'default-single':'请选择一个日期', + 'default-default': '请选择一个日期范围' + }, + 'cz': + { + 'selected': 'Vybráno:', + 'day':'Den', + 'days': 'Dny', + 'apply': 'Zavřít', + 'week-1' : 'po', + 'week-2' : 'út', + 'week-3' : 'st', + 'week-4' : 'čt', + 'week-5' : 'pá', + 'week-6' : 'so', + 'week-7' : 'ne', + 'month-name': ['leden','únor','březen','duben','květen','červen','červenec','srpen','září','říjen','listopad','prosinec'], + 'shortcuts' : 'Zkratky', + 'past': 'po', + 'following':'následující', + 'previous' : 'předchozí', + 'prev-week' : 'týden', + 'prev-month' : 'měsíc', + 'prev-year' : 'rok', + 'next':'další', + 'next-week':'týden', + 'next-month':'měsíc', + 'next-year':'rok', + 'less-than' : 'Rozsah data by neměl být větší než %d dnů', + 'more-than' : 'Rozsah data by neměl být menší než %d dnů', + 'default-more' : 'Prosím zvolte rozsah data větší než %d dnů', + 'default-single' : 'Prosím zvolte datum', + 'default-less' : 'Prosím zvolte rozsah data menší než %d dnů', + 'default-range' : 'Prosím zvolte rozsah data mezi %d a %d dny', + 'default-default': 'Prosím zvolte rozsah data' + }, + 'en': + { + 'selected': 'Selected:', + 'day':'Day', + 'days': 'Days', + 'apply': 'Close', + 'week-1' : 'mo', + 'week-2' : 'tu', + 'week-3' : 'we', + 'week-4' : 'th', + 'week-5' : 'fr', + 'week-6' : 'sa', + 'week-7' : 'su', + 'month-name': ['january','february','march','april','may','june','july','august','september','october','november','december'], + 'shortcuts' : 'Shortcuts', + 'custom-values': 'Custom Values', + 'past': 'Past', + 'following':'Following', + 'previous' : 'Previous', + 'prev-week' : 'Week', + 'prev-month' : 'Month', + 'prev-year' : 'Year', + 'next':'Next', + 'next-week':'Week', + 'next-month':'Month', + 'next-year':'Year', + 'less-than' : 'Date range should not be more than %d days', + 'more-than' : 'Date range should not be less than %d days', + 'default-more' : 'Please select a date range longer than %d days', + 'default-single' : 'Please select a date', + 'default-less' : 'Please select a date range less than %d days', + 'default-range' : 'Please select a date range between %d and %d days', + 'default-default': 'Please select a date range' + }, + 'it': + { + 'selected': 'Selezionati:', + 'day':'Giorno', + 'days': 'Giorni', + 'apply': 'Chiudi', + 'week-1' : 'lu', + 'week-2' : 'ma', + 'week-3' : 'me', + 'week-4' : 'gi', + 'week-5' : 've', + 'week-6' : 'sa', + 'week-7' : 'do', + 'month-name': ['gennaio','febbraio','marzo','aprile','maggio','giugno','luglio','agosto','settembre','ottobre','novembre','dicembre'], + 'shortcuts' : 'Scorciatoie', + 'past': 'Scorso', + 'following':'Successivo', + 'previous' : 'Precedente', + 'prev-week' : 'Settimana', + 'prev-month' : 'Mese', + 'prev-year' : 'Anno', + 'next':'Prossimo', + 'next-week':'Settimana', + 'next-month':'Mese', + 'next-year':'Anno', + 'less-than' : 'L\'intervallo non dev\'essere maggiore di %d giorni', + 'more-than' : 'L\'intervallo non dev\'essere minore di %d giorni', + 'default-more' : 'Seleziona un intervallo maggiore di %d giorni', + 'default-single' : 'Seleziona una data', + 'default-less' : 'Seleziona un intervallo minore di %d giorni', + 'default-range' : 'Seleziona un intervallo compreso tra i %d e i %d giorni', + 'default-default': 'Seleziona un intervallo di date' + }, + 'es': + { + 'selected': 'Seleccionado:', + 'day':'Dia', + 'days': 'Dias', + 'apply': 'Cerrar', + 'week-1' : 'lu', + 'week-2' : 'ma', + 'week-3' : 'mi', + 'week-4' : 'ju', + 'week-5' : 'vi', + 'week-6' : 'sa', + 'week-7' : 'do', + 'month-name': ['enero','febrero','marzo','abril','mayo','junio','julio','agosto','septiembre','octubre','noviembre','diciembre'], + 'shortcuts' : 'Accesos directos', + 'past': 'Pasado', + 'following':'Siguiente', + 'previous' : 'Anterior', + 'prev-week' : 'Semana', + 'prev-month' : 'Mes', + 'prev-year' : 'Año', + 'next':'Siguiente', + 'next-week':'Semana', + 'next-month':'Mes', + 'next-year':'Año', + 'less-than' : 'El rango no deberia ser mayor de %d dias', + 'more-than' : 'El rango no deberia ser menor de %d dias', + 'default-more' : 'Por favor selecciona un rango mayor a %d dias', + 'default-single' : 'Por favor selecciona un dia', + 'default-less' : 'Por favor selecciona un rango menor a %d dias', + 'default-range' : 'Por favor selecciona un rango entre %d y %d dias', + 'default-default': 'Por favor selecciona un rango de fechas.' + }, + 'de': + { + 'selected': 'Auswahl:', + 'day':'Tag', + 'days': 'Tage', + 'apply': 'Schließen', + 'week-1' : 'mo', + 'week-2' : 'di', + 'week-3' : 'mi', + 'week-4' : 'do', + 'week-5' : 'fr', + 'week-6' : 'sa', + 'week-7' : 'so', + 'month-name': ['januar','februar','märz','april','mai','juni','juli','august','september','oktober','november','dezember'], + 'shortcuts' : 'Schnellwahl', + 'past': 'Vorherige', + 'following':'Folgende', + 'previous' : 'Vorherige', + 'prev-week' : 'Woche', + 'prev-month' : 'Monat', + 'prev-year' : 'Jahr', + 'next':'Nächste', + 'next-week':'Woche', + 'next-month':'Monat', + 'next-year':'Jahr', + 'less-than' : 'Datumsbereich darf nicht größer sein als %d Tage', + 'more-than' : 'Datumsbereich darf nicht kleiner sein als %d Tage', + 'default-more' : 'Bitte mindestens %d Tage auswählen', + 'default-single' : 'Bitte ein Datum auswählen', + 'default-less' : 'Bitte weniger als %d Tage auswählen', + 'default-range' : 'Bitte einen Datumsbereich zwischen %d und %d Tagen auswählen', + 'default-default': 'Bitte ein Start- und Enddatum auswählen' + }, + 'ru': + { + 'selected': 'Выбрано:', + 'day': 'День', + 'days': 'Дней', + 'apply': 'Закрыть', + 'week-1': 'пн', + 'week-2': 'вт', + 'week-3': 'ср', + 'week-4': 'чт', + 'week-5': 'пт', + 'week-6': 'сб', + 'week-7': 'вс', + 'month-name': ['январь','февраль','март','апрель','май','июнь','июль','август','сентябрь','октябрь','ноябрь','декабрь'], + 'shortcuts': 'Быстрый выбор', + 'past': 'Прошедшие', + 'following': 'Следующие', + 'previous': '   ', + 'prev-week': 'Неделя', + 'prev-month': 'Месяц', + 'prev-year': 'Год', + 'next': '   ', + 'next-week': 'Неделя', + 'next-month': 'Месяц', + 'next-year': 'Год', + 'less-than': 'Диапазон не может быть больше %d дней', + 'more-than': 'Диапазон не может быть меньше %d дней', + 'default-more': 'Пожалуйста выберите диапазон больше %d дней', + 'default-single': 'Пожалуйста выберите дату', + 'default-less': 'Пожалуйста выберите диапазон меньше %d дней', + 'default-range': 'Пожалуйста выберите диапазон между %d и %d днями', + 'default-default': 'Пожалуйста выберите диапазон' + }, + 'fr': + { + 'selected': 'Sélection:', + 'day':'Jour', + 'days': 'Jours', + 'apply': 'Fermer', + 'week-1' : 'lu', + 'week-2' : 'ma', + 'week-3' : 'me', + 'week-4' : 'je', + 'week-5' : 've', + 'week-6' : 'sa', + 'week-7' : 'di', + 'month-name': ['janvier','février','mars','avril','mai','juin','juillet','août','septembre','octobre','novembre','décembre'], + 'shortcuts' : 'Raccourcis', + 'past': 'Passé', + 'following':'Suivant', + 'previous' : 'Précédent', + 'prev-week' : 'Semaine', + 'prev-month' : 'Mois', + 'prev-year' : 'Année', + 'next':'Suivant', + 'next-week':'Semaine', + 'next-month':'Mois', + 'next-year':'Année', + 'less-than' : 'L\'intervalle ne doit pas être supérieure à %d jours', + 'more-than' : 'L\'intervalle ne doit pas être inférieure à %d jours', + 'default-more' : 'Merci de choisir une intervalle supérieure à %d jours', + 'default-single' : 'Merci de choisir une date', + 'default-less' : 'Merci de choisir une intervalle inférieure %d jours', + 'default-range' : 'Merci de choisir une intervalle comprise entre %d et %d jours', + 'default-default': 'Merci de choisir une date' + }, + 'hu': + { + 'selected': 'Kiválasztva:', + 'day':'Nap', + 'days': 'Nap', + 'apply': 'Ok', + 'week-1' : 'h', + 'week-2' : 'k', + 'week-3' : 'sz', + 'week-4' : 'cs', + 'week-5' : 'p', + 'week-6' : 'sz', + 'week-7' : 'v', + 'month-name': ['január','február','március','április','május','június','július','augusztus','szeptember','október','november','december'], + 'shortcuts' : 'Gyorsválasztó', + 'past': 'Múlt', + 'following':'Következő', + 'previous' : 'Előző', + 'prev-week' : 'Hét', + 'prev-month' : 'Hónap', + 'prev-year' : 'Év', + 'next':'Következő', + 'next-week':'Hét', + 'next-month':'Hónap', + 'next-year':'Év', + 'less-than' : 'A kiválasztás nem lehet több %d napnál', + 'more-than' : 'A kiválasztás nem lehet több %d napnál', + 'default-more' : 'Válassz ki egy időszakot ami hosszabb mint %d nap', + 'default-single' : 'Válassz egy napot', + 'default-less' : 'Válassz ki egy időszakot ami rövidebb mint %d nap', + 'default-range' : 'Válassz ki egy %d - %d nap hosszú időszakot', + 'default-default': 'Válassz ki egy időszakot' + } + }; + + $.fn.dateRangePicker = function(opt) + { + if (!opt) opt = {}; + opt = $.extend(true, + { + autoClose: false, + format: 'YYYY-MM-DD', + separator: ' to ', + language: 'auto', + startOfWeek: 'sunday',// or monday + getValue: function() + { + return $(this).val(); + }, + setValue: function(s) + { + if(!$(this).attr('readonly') && !$(this).is(':disabled')){ + $(this).val(s); + } + }, + startDate: false, + endDate: false, + time: { + enabled: false + }, + minDays: 0, + maxDays: 0, + showShortcuts: true, + shortcuts: + { + //'prev-days': [1,3,5,7], + 'next-days': [3,5,7], + //'prev' : ['week','month','year'], + 'next' : ['week','month','year'] + }, + customShortcuts : [], + inline:false, + container:'body', + alwaysOpen:false, + singleDate:false, + lookBehind: false, + batchMode: false, + duration: 200, + stickyMonths: false, + dayDivAttrs: [], + dayTdAttrs: [], + applyBtnClass: '' + },opt); + + opt.start = false; + opt.end = false; + + if (opt.startDate && typeof opt.startDate == 'string') opt.startDate = moment(opt.startDate,opt.format).toDate(); + if (opt.endDate && typeof opt.endDate == 'string') opt.endDate = moment(opt.endDate,opt.format).toDate(); + + var langs = getLanguages(); + var box; + var initiated = false; + var self = this; + var selfDom = $(self).get(0); + + $(this).unbind('.datepicker').bind('click.datepicker',function(evt) + { + var isOpen = box.is(':visible'); + $(document).trigger('click.datepicker'); + evt.stopPropagation(); + if(!isOpen) open(opt.duration); + }); + + init_datepicker.call(this); + + if (opt.alwaysOpen) + { + open(0); + } + + // expose some api + $(this).data('dateRangePicker', + { + setDateRange : function(d1,d2,silent) + { + if (typeof d1 == 'string' && typeof d2 == 'string') + { + d1 = moment(d1,opt.format).toDate(); + d2 = moment(d2,opt.format).toDate(); + } + setDateRange(d1,d2,silent); + }, + clear: clearSelection, + close: closeDatePicker, + open: open, + getDatePicker: getDatePicker, + destroy: function() + { + $(self).unbind('.datepicker'); + $(self).data('dateRangePicker',''); + box.remove(); + $(window).unbind('resize.datepicker',calcPosition); + $(document).unbind('click.datepicker',closeDatePicker); + } + }); + + $(window).bind('resize.datepicker',calcPosition); + + return this; + + + function init_datepicker() + { + var self = this; + + if ($(this).data('date-picker-opened')) + { + closeDatePicker(); + return; + } + $(this).data('date-picker-opened',true); + + + box = createDom().hide(); + $(opt.container).append(box); + + if (!opt.inline) + { + calcPosition(); + } + else + { + box.addClass("inline-wrapper").css({position:'static'}); + } + + if (opt.alwaysOpen) + { + box.find('.apply-btn').hide(); + } + + var defaultTime = opt.defaultTime ? opt.defaultTime : new Date(); + if (opt.lookBehind) { + if (opt.startDate && compare_month(defaultTime, opt.startDate) < 0 ) defaultTime = nextMonth(moment(opt.startDate).toDate()); + if (opt.endDate && compare_month(defaultTime,opt.endDate) > 0 ) defaultTime = moment(opt.endDate).toDate(); + + showMonth(prevMonth(defaultTime),'month1'); + showMonth(defaultTime,'month2'); + + } else { + if (opt.startDate && compare_month(defaultTime,opt.startDate) < 0 ) defaultTime = moment(opt.startDate).toDate(); + if (opt.endDate && compare_month(nextMonth(defaultTime),opt.endDate) > 0 ) defaultTime = prevMonth(moment(opt.endDate).toDate()); + + showMonth(defaultTime,'month1'); + showMonth(nextMonth(defaultTime),'month2'); + } + + if (opt.time.enabled) { + if ((opt.startDate && opt.endDate) || (opt.start && opt.end)) { + showTime(moment(opt.start || opt.startDate).toDate(),'time1'); + showTime(moment(opt.end || opt.endDate).toDate(),'time2'); + } else { + showTime(defaultTime,'time1'); + showTime(defaultTime,'time2'); + } + } + + //showSelectedInfo(); + + + var defaultTopText = ''; + if (opt.singleDate) + defaultTopText = lang('default-single'); + else if (opt.minDays && opt.maxDays) + defaultTopText = lang('default-range'); + else if (opt.minDays) + defaultTopText = lang('default-more'); + else if (opt.maxDays) + defaultTopText = lang('default-less'); + else + defaultTopText = lang('default-default'); + + box.find('.default-top').html( defaultTopText.replace(/\%d/,opt.minDays).replace(/\%d/,opt.maxDays)); + + + setTimeout(function() + { + initiated = true; + },0); + + box.click(function(evt) + { + evt.stopPropagation(); + }); + + $(document).bind('click.datepicker',closeDatePicker); + + box.find('.next').click(function() + { + if(!opt.stickyMonths) gotoNextMonth(this); + else gotoNextMonth_stickily(this) + }); + + function gotoNextMonth(self) { + var isMonth2 = $(self).parents('table').hasClass('month2'); + var month = isMonth2 ? opt.month2 : opt.month1; + month = nextMonth(month); + if (!opt.singleDate && !isMonth2 && compare_month(month,opt.month2) >= 0 || isMonthOutOfBounds(month)) return; + showMonth(month,isMonth2 ? 'month2' : 'month1'); + showGap(); + } + + function gotoNextMonth_stickily(self) { + var nextMonth1 = nextMonth(opt.month1); + + var nextMonth2 = nextMonth(opt.month2); + + if(isMonthOutOfBounds(nextMonth2)) return; + if (!opt.singleDate && compare_month(nextMonth1,nextMonth2) >= 0) return; + showMonth(nextMonth1, 'month1'); + showMonth(nextMonth2, 'month2'); + } + + + box.find('.prev').click(function() + { + if(!opt.stickyMonths) gotoPrevMonth(this); + else gotoPrevMonth_stickily(this); + }); + + function gotoPrevMonth(self) { + var isMonth2 = $(self).parents('table').hasClass('month2'); + var month = isMonth2 ? opt.month2 : opt.month1; + month = prevMonth(month); + //if (isMonth2 && month.getFullYear()+''+month.getMonth() <= opt.month1.getFullYear()+''+opt.month1.getMonth()) return; + if (isMonth2 && compare_month(month,opt.month1) <= 0 || isMonthOutOfBounds(month)) return; + showMonth(month,isMonth2 ? 'month2' : 'month1'); + showGap(); + } + + function gotoPrevMonth_stickily(self) { + var prevMonth1 = prevMonth(opt.month1); + + var prevMonth2 = prevMonth(opt.month2); + + if(isMonthOutOfBounds(prevMonth1)) return; + if(!opt.singleDate && compare_month(prevMonth2,prevMonth1) <= 0) return; + showMonth(prevMonth2, 'month2'); + showMonth(prevMonth1, 'month1'); + } + + + box.bind('click',function(evt) + { + if ($(evt.target).hasClass('day')) + { + dayClicked($(evt.target)); + } + }); + + box.attr('unselectable', 'on') + .css('user-select', 'none') + .bind('selectstart', function(e) + { + e.preventDefault(); return false; + }); + + box.find('.apply-btn').click(function() + { + closeDatePicker(); + var dateRange = getDateString(new Date(opt.start))+ opt.separator +getDateString(new Date(opt.end)); + $(self).trigger('datepicker-apply', + { + 'value': dateRange, + 'date1' : new Date(opt.start), + 'date2' : new Date(opt.end) + }); + }); + + box.find('[custom]').click(function() + { + var valueName = $(this).attr('custom'); + opt.start = false; + opt.end = false; + box.find('.day.checked').removeClass('checked'); + opt.setValue.call(selfDom, valueName); + checkSelectionValid(); + showSelectedInfo(true); + showSelectedDays(); + if (opt.autoClose) closeDatePicker(); + }); + + box.find('[shortcut]').click(function() + { + var shortcut = $(this).attr('shortcut'); + var end = new Date(),start = false; + if (shortcut.indexOf('day') != -1) + { + var day = parseInt(shortcut.split(',',2)[1],10); + start = new Date(new Date().getTime() + 86400000*day); + end = new Date(end.getTime() + 86400000*(day>0?1:-1) ); + } + else if (shortcut.indexOf('week')!= -1) + { + var dir = shortcut.indexOf('prev,') != -1 ? -1 : 1; + + if (dir == 1) + var stopDay = opt.startOfWeek == 'monday' ? 1 : 0; + else + var stopDay = opt.startOfWeek == 'monday' ? 0 : 6; + + end = new Date(end.getTime() - 86400000); + while(end.getDay() != stopDay) end = new Date(end.getTime() + dir*86400000); + start = new Date(end.getTime() + dir*86400000*6); + } + else if (shortcut.indexOf('month') != -1) + { + var dir = shortcut.indexOf('prev,') != -1 ? -1 : 1; + if (dir == 1) + start = nextMonth(end); + else + start = prevMonth(end); + start.setDate(1); + end = nextMonth(start); + end.setDate(1); + end = new Date(end.getTime() - 86400000); + } + else if (shortcut.indexOf('year') != -1) + { + var dir = shortcut.indexOf('prev,') != -1 ? -1 : 1; + start = new Date(); + start.setFullYear(end.getFullYear() + dir); + start.setMonth(0); + start.setDate(1); + end.setFullYear(end.getFullYear() + dir); + end.setMonth(11); + end.setDate(31); + } + else if (shortcut == 'custom') + { + var name = $(this).html(); + if (opt.customShortcuts && opt.customShortcuts.length > 0) + { + for(var i=0;i=2)) + { + var ___format = opt.format; + if (___format.match(/Do/)) + { + + ___format = ___format.replace(/Do/,'D'); + defaults[0] = defaults[0].replace(/(\d+)(th|nd|st)/,'$1'); + if(defaults.length >= 2){ + defaults[1] = defaults[1].replace(/(\d+)(th|nd|st)/,'$1'); + } + } + // set initiated to avoid triggerring datepicker-change event + initiated = false; + if(defaults.length >= 2){ + setDateRange(moment(defaults[0], ___format, moment.locale(opt.language)).toDate(),moment(defaults[1], ___format, moment.locale(opt.language)).toDate()); + } + else if(defaults.length==1 && opt.singleDate){ + setSingleDate(moment(defaults[0], ___format, moment.locale(opt.language)).toDate()); + } + + initiated = true; + } + box.slideDown(animationTime, function(){ + $(self).trigger('datepicker-opened', {relatedTarget: box}); + }); + $(self).trigger('datepicker-open', {relatedTarget: box}); + } + + + function renderTime (name, date) { + box.find("." + name + " input[type=range].hour-range").val(moment(date).hours()); + box.find("." + name + " input[type=range].minute-range").val(moment(date).minutes()); + setTime(name, moment(date).format("HH"), moment(date).format("mm")); + } + + function changeTime (name, date) { + opt[name] = parseInt( + moment(parseInt(date)) + .startOf('day') + .add(moment(opt[name + "Time"]).format("HH"), 'h') + .add(moment(opt[name + "Time"]).format("mm"), 'm').valueOf() + ); + } + + function swapTime () { + renderTime("time1", opt.start); + renderTime("time2", opt.end); + } + + function setTime (name, hour, minute) { + hour && (box.find("." + name + " .hour-val").text(hour)); + minute && (box.find("." + name + " .minute-val").text(minute)); + switch (name) { + case "time1": + if (opt.start) { + setRange("start", moment(opt.start)); + } + setRange("startTime", moment(opt.startTime || moment().valueOf())); + break; + case "time2": + if (opt.end) { + setRange("end", moment(opt.end)); + } + setRange("endTime", moment(opt.endTime || moment().valueOf())); + break; + } + function setRange(name, timePoint) { + var h = timePoint.format("HH"), + m = timePoint.format("mm"); + opt[name] = timePoint + .startOf('day') + .add(hour || h, "h") + .add(minute || m, "m") + .valueOf(); + } + checkSelectionValid(); + showSelectedInfo(); + showSelectedDays(); + } + + function clearSelection() + { + opt.start = false; + opt.end = false; + box.find('.day.checked').removeClass('checked'); + opt.setValue.call(selfDom, ''); + checkSelectionValid(); + showSelectedInfo(); + showSelectedDays(); + } + + function handleStart(time) + { + var r = time; + if (opt.batchMode === 'week-range') { + if (opt.startOfWeek === 'monday') { + r = moment(parseInt(time)).startOf('isoweek').valueOf(); + } else { + r = moment(parseInt(time)).startOf('week').valueOf(); + } + } else if (opt.batchMode === 'month-range') { + r = moment(parseInt(time)).startOf('month').valueOf(); + } + + return r; + } + + function handleEnd(time) + { + var r = time; + if (opt.batchMode === 'week-range') { + if (opt.startOfWeek === 'monday') { + r = moment(parseInt(time)).endOf('isoweek').valueOf(); + } else { + r = moment(parseInt(time)).endOf('week').valueOf(); + } + } else if (opt.batchMode === 'month') { + r = moment(parseInt(time)).endOf('month').valueOf(); + } + + return r; + } + + + function dayClicked(day) + { + if (day.hasClass('invalid')) return; + var time = day.attr('time'); + day.addClass('checked'); + if ( opt.singleDate ) + { + opt.start = time; + opt.end = false; + if (opt.time.enabled) { + changeTime("start", opt.start); + } + } + else if (opt.batchMode === 'week') + { + if (opt.startOfWeek === 'monday') { + opt.start = moment(parseInt(time)).startOf('isoweek').valueOf(); + opt.end = moment(parseInt(time)).endOf('isoweek').valueOf(); + } else { + opt.end = moment(parseInt(time)).endOf('week').valueOf(); + opt.start = moment(parseInt(time)).startOf('week').valueOf(); + } + } + else if (opt.batchMode === 'month') + { + opt.start = moment(parseInt(time)).startOf('month').valueOf(); + opt.end = moment(parseInt(time)).endOf('month').valueOf(); + } + else if ((opt.start && opt.end) || (!opt.start && !opt.end) ) + { + opt.start = handleStart(time); + opt.end = false; + if (opt.time.enabled) { + changeTime("start", opt.start); + } + } + else if (opt.start) + { + opt.end = handleEnd(time); + if (opt.time.enabled) { + changeTime("end", opt.end); + } + } + + if (!opt.singleDate && opt.start && opt.end && opt.start > opt.end) + { + var tmp = opt.end; + opt.end = handleEnd(opt.start); + opt.start = handleStart(tmp); + if (opt.time.enabled) { + swapTime(); + } + } + + opt.start = parseInt(opt.start); + opt.end = parseInt(opt.end); + + checkSelectionValid(); + showSelectedInfo(); + showSelectedDays(); + autoclose(); + } + + function autoclose () { + if (opt.singleDate === true) { + if (initiated && opt.start ) + { + if (opt.autoClose) closeDatePicker(); + } + } else { + if (initiated && opt.start && opt.end) + { + if (opt.autoClose) closeDatePicker(); + } + } + } + + function checkSelectionValid() + { + var days = Math.ceil( (opt.end - opt.start) / 86400000 ) + 1; + if (opt.singleDate) { // Validate if only start is there + if (opt.start && !opt.end) + box.find('.drp_top-bar').removeClass('error').addClass('normal'); + else + box.find('.drp_top-bar').removeClass('error').removeClass('normal'); + } + else if ( opt.maxDays && days > opt.maxDays) + { + opt.start = false; + opt.end = false; + box.find('.day').removeClass('checked'); + box.find('.drp_top-bar').removeClass('normal').addClass('error').find('.error-top').html( lang('less-than').replace('%d',opt.maxDays) ); + } + else if ( opt.minDays && days < opt.minDays) + { + opt.start = false; + opt.end = false; + box.find('.day').removeClass('checked'); + box.find('.drp_top-bar').removeClass('normal').addClass('error').find('.error-top').html( lang('more-than').replace('%d',opt.minDays) ); + } + else + { + if (opt.start || opt.end) + box.find('.drp_top-bar').removeClass('error').addClass('normal'); + else + box.find('.drp_top-bar').removeClass('error').removeClass('normal'); + } + + if ( (opt.singleDate && opt.start && !opt.end) || (!opt.singleDate && opt.start && opt.end) ) + { + box.find('.apply-btn').removeClass('disabled'); + } + else + { + box.find('.apply-btn').addClass('disabled'); + } + + if (opt.batchMode) + { + if ( (opt.start && opt.startDate && compare_day(opt.start, opt.startDate) < 0) + || (opt.end && opt.endDate && compare_day(opt.end, opt.endDate) > 0) ) + { + opt.start = false; + opt.end = false; + box.find('.day').removeClass('checked'); + } + } + } + + function showSelectedInfo(forceValid,silent) + { + box.find('.start-day').html('...'); + box.find('.end-day').html('...'); + box.find('.selected-days').hide(); + if (opt.start) + { + box.find('.start-day').html(getDateString(new Date(parseInt(opt.start)))); + } + if (opt.end) + { + box.find('.end-day').html(getDateString(new Date(parseInt(opt.end)))); + } + + if (opt.start && opt.singleDate) + { + box.find('.apply-btn').removeClass('disabled'); + var dateRange = getDateString(new Date(opt.start)); + opt.setValue.call(selfDom, dateRange, getDateString(new Date(opt.start)), getDateString(new Date(opt.end))); + + if (initiated) + { + $(self).trigger('datepicker-change', + { + 'value': dateRange, + 'date1' : new Date(opt.start) + }); + } + } + else if (opt.start && opt.end) + { + box.find('.selected-days').show().find('.selected-days-num').html(Math.round((opt.end-opt.start)/86400000)+1); + box.find('.apply-btn').removeClass('disabled'); + var dateRange = getDateString(new Date(opt.start))+ opt.separator +getDateString(new Date(opt.end)); + opt.setValue.call(selfDom,dateRange, getDateString(new Date(opt.start)), getDateString(new Date(opt.end))); + if (initiated && !silent) + { + $(self).trigger('datepicker-change', + { + 'value': dateRange, + 'date1' : new Date(opt.start), + 'date2' : new Date(opt.end) + }); + } + } + else if (forceValid) + { + box.find('.apply-btn').removeClass('disabled'); + } + else + { + box.find('.apply-btn').addClass('disabled'); + } + } + + function setDateRange(date1,date2,silent) + { + if (date1.getTime() > date2.getTime()) + { + var tmp = date2; + date2 = date1; + date1 = tmp; + tmp = null; + } + var valid = true; + if (opt.startDate && compare_day(date1,opt.startDate) < 0) valid = false; + if (opt.endDate && compare_day(date2,opt.endDate) > 0) valid = false; + if (!valid) + { + showMonth(opt.startDate,'month1'); + showMonth(nextMonth(opt.startDate),'month2'); + showGap(); + return; + } + + opt.start = date1.getTime(); + opt.end = date2.getTime(); + if (opt.stickyMonths || (compare_day(date1,date2) > 0 && compare_month(date1,date2) == 0)) + { + if (opt.lookBehind) { + date1 = prevMonth(date2); + } else { + date2 = nextMonth(date1); + } + } + + if(opt.stickyMonths && compare_month(date2,opt.endDate) > 0) { + date1 = prevMonth(date1); + date2 = prevMonth(date2); + } + + if (!opt.stickyMonths) { + if (compare_month(date1,date2) == 0) + { + if (opt.lookBehind) { + date1 = prevMonth(date2); + } else { + date2 = nextMonth(date1); + } + } + } + + if (opt.time.enabled) { + renderTime("time1", date1); + renderTime("time2", date2); + } + showMonth(date1,'month1'); + showMonth(date2,'month2'); + showGap(); + showSelectedInfo(false,silent); + autoclose(); + } + + function setSingleDate(date1) + { + + var valid = true; + if (opt.startDate && compare_day(date1,opt.startDate) < 0) valid = false; + if (opt.endDate && compare_day(date1,opt.endDate) > 0) valid = false; + if (!valid) + { + showMonth(opt.startDate,'month1'); + + //showGap(); + return; + } + + opt.start = date1.getTime(); + + + if (opt.time.enabled) { + renderTime("time1", date1); + + } + showMonth(date1,'month1'); + //showMonth(date2,'month2'); + showGap(); + showSelectedInfo(); + autoclose(); + } + + function showSelectedDays() + { + if (!opt.start && !opt.end) return; + box.find('.day').each(function() + { + var time = parseInt($(this).attr('time')), + start = opt.start, + end = opt.end; + if (opt.time.enabled) { + time = moment(time).startOf('day').valueOf(); + start = moment(start || moment().valueOf()).startOf('day').valueOf(); + end = moment(end || moment().valueOf()).startOf('day').valueOf(); + } + if ( + (opt.start && opt.end && end >= time && start <= time ) + || ( opt.start && !opt.end && moment(start).format('YYYY-MM-DD') == moment(time).format('YYYY-MM-DD') ) + ) + { + $(this).addClass('checked'); + } + else + { + $(this).removeClass('checked'); + } + }); + } + + function showMonth(date,month) + { + date = moment(date).toDate(); + var monthName = nameMonth(date.getMonth()); + box.find('.'+month+' .month-name').html(monthName+' '+date.getFullYear()); + box.find('.'+month+' tbody').html(createMonthHTML(date)); + opt[month] = date; + } + + function showTime(date,name) + { + box.find('.' + name).append(getTimeHTML()); + renderTime(name, date); + } + + function nameMonth(m) + { + return lang('month-name')[m]; + } + + function getDateString(d) + { + return moment(d).format(opt.format); + } + + function showGap() + { + showSelectedDays(); + var m1 = parseInt(moment(opt.month1).format('YYYYMM')); + var m2 = parseInt(moment(opt.month2).format('YYYYMM')); + var p = Math.abs(m1 - m2); + var shouldShow = (p > 1 && p !=89); + if (shouldShow) + box.find('.gap').show(); + else + box.find('.gap').hide(); + } + + function closeDatePicker() + { + if (opt.alwaysOpen) return; + $(box).slideUp(opt.duration,function() + { + $(self).data('date-picker-opened',false); + $(self).trigger('datepicker-closed', {relatedTarget: box}); + }); + //$(document).unbind('.datepicker'); + $(self).trigger('datepicker-close', {relatedTarget: box}); + } + + function compare_month(m1,m2) + { + var p = parseInt(moment(m1).format('YYYYMM')) - parseInt(moment(m2).format('YYYYMM')); + if (p > 0 ) return 1; + if (p == 0) return 0; + return -1; + } + + function compare_day(m1,m2) + { + var p = parseInt(moment(m1).format('YYYYMMDD')) - parseInt(moment(m2).format('YYYYMMDD')); + if (p > 0 ) return 1; + if (p == 0) return 0; + return -1; + } + + function nextMonth(month) + { + month = moment(month).toDate(); + var toMonth = month.getMonth(); + while(month.getMonth() == toMonth) month = new Date(month.getTime()+86400000); + return month; + } + + function prevMonth(month) + { + month = moment(month).toDate(); + var toMonth = month.getMonth(); + while(month.getMonth() == toMonth) month = new Date(month.getTime()-86400000); + return month; + } + + function getTimeHTML() + { + var timeHtml = '
' + +'Time: 00:00' + +'
' + +'
' + +'' + +'
' + +'
' + +'' + +'
'; + return timeHtml; + } + + function createDom() + { + var html = '
' + +'
\ +
\ + '+lang('selected')+' ...' + if ( ! opt.singleDate ) { + html += ' '+opt.separator+' ... (3 '+lang('days')+')' + } + html += '
\ +
error
\ +
default
\ + \ +
' + +'
' + +''+getWeekHead()+'
<January, 2011' + (opt.singleDate || !opt.stickyMonths ? '>': '') + '
' + if ( ! opt.singleDate ) { + html += '
'+getGapHTML()+'
' + +''+getWeekHead()+'
' + (!opt.stickyMonths ? '<': '') + 'January, 2011>
' + } + //+'
' + html += '
' + +'
' + +'
' + if ( ! opt.singleDate ) { + html += '
' + } + html += '
' + +'
' + +'
'; + + html += ''; + + + return $(html); + } + + function getApplyBtnClass() + { + klass = '' + if (opt.autoClose === true) { + klass += ' hide'; + } + if (opt.applyBtnClass !== '') { + klass += ' ' + opt.applyBtnClass; + } + return klass; + } + + function getWeekHead() + { + if (opt.startOfWeek == 'monday') + { + return ''+lang('week-1')+'\ + '+lang('week-2')+'\ + '+lang('week-3')+'\ + '+lang('week-4')+'\ + '+lang('week-5')+'\ + '+lang('week-6')+'\ + '+lang('week-7')+''; + } + else + { + return ''+lang('week-7')+'\ + '+lang('week-1')+'\ + '+lang('week-2')+'\ + '+lang('week-3')+'\ + '+lang('week-4')+'\ + '+lang('week-5')+'\ + '+lang('week-6')+''; + } + } + function isMonthOutOfBounds(month) + { + var month = moment(month); + if (opt.startDate && month.endOf('month').isBefore(opt.startDate)) + { + return true; + } + if (opt.endDate && month.startOf('month').isAfter(opt.endDate)) + { + return true; + } + return false; + } + + function getGapHTML() + { + var html = ['
']; + for(var i=0;i<20;i++) + { + html.push('
\ +
\ +
\ +
\ +
'); + } + html.push('
'); + return html.join(''); + } + + function attributesCallbacks(initialObject,callbacksArray,today) + { + var resultObject = jQuery.extend(true, {}, initialObject); + + callbacksArray.forEach(function(cbAttr,cbAttrIndex,cbAttrArray){ + var addAttributes = cbAttr(this); + for(var attr in addAttributes){ + if(resultObject.hasOwnProperty(attr)){ + resultObject[attr] += addAttributes[attr]; + }else{ + resultObject[attr] = addAttributes[attr]; + } + } + },today); + + attrString = ''; + + for(var attr in resultObject){ + if(resultObject.hasOwnProperty(attr)){ + attrString += attr + '="' + resultObject[attr] + '" '; + } + } + + return attrString; + } + + function createMonthHTML(d) + { + var days = []; + d.setDate(1); + var lastMonth = new Date(d.getTime() - 86400000); + var now = new Date(); + + var dayOfWeek = d.getDay(); + if((dayOfWeek == 0) && (opt.startOfWeek == 'monday')) { + // add one week + dayOfWeek = 7; + } + + if (dayOfWeek > 0) + { + for (var i = dayOfWeek; i > 0; i--) + { + var day = new Date(d.getTime() - 86400000*i); + var valid = true; + if (opt.startDate && compare_day(day,opt.startDate) < 0) valid = false; + if (opt.endDate && compare_day(day,opt.endDate) > 0) valid = false; + days.push({type:'lastMonth',day: day.getDate(),time:day.getTime(), valid:valid }); + } + } + var toMonth = d.getMonth(); + for(var i=0; i<40; i++) + { + var today = moment(d).add(i, 'days').toDate(); + var valid = true; + if (opt.startDate && compare_day(today,opt.startDate) < 0) valid = false; + if (opt.endDate && compare_day(today,opt.endDate) > 0) valid = false; + days.push({type: today.getMonth() == toMonth ? 'toMonth' : 'nextMonth',day: today.getDate(),time:today.getTime(), valid:valid }); + } + var html = []; + for(var week=0; week<6; week++) + { + if (days[week*7].type == 'nextMonth') break; + html.push(''); + for(var day = 0; day<7; day++) + { + var _day = (opt.startOfWeek == 'monday') ? day+1 : day; + var today = days[week*7+_day]; + var highlightToday = moment(today.time).format('L') == moment(now).format('L'); + today.extraClass = ''; + today.tooltip = ''; + if(opt.beforeShowDay && typeof opt.beforeShowDay == 'function') + { + var _r = opt.beforeShowDay(moment(today.time).toDate()); + today.valid = _r[0]; + today.extraClass = _r[1] || ''; + today.tooltip = _r[2] || ''; + if (today.tooltip != '') today.extraClass += ' has-tooltip '; + } + + todayDivAttr = { + time: today.time, + title: today.tooltip, + 'class': 'day '+today.type+' '+today.extraClass+' '+(today.valid ? 'valid' : 'invalid')+' '+(highlightToday?'real-today':'') + }; + + html.push('
'+today.day+'
'); + } + html.push(''); + } + return html.join(''); + } + + function getLanguages() + { + if (opt.language == 'auto') + { + var language = navigator.language ? navigator.language : navigator.browserLanguage; + if (!language) return $.dateRangePickerLanguages['en']; + var language = language.toLowerCase(); + for(var key in $.dateRangePickerLanguages) + { + if (language.indexOf(key) != -1) + { + return $.dateRangePickerLanguages[key]; + } + } + return $.dateRangePickerLanguages['en']; + } + else if ( opt.language && opt.language in $.dateRangePickerLanguages) + { + return $.dateRangePickerLanguages[opt.language]; + } + else + { + return $.dateRangePickerLanguages['en']; + } + } + + function lang(t) + { + return (t in langs)? langs[t] : t; + } + + + }; +})); diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/light_graph.js b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/light_graph.js new file mode 100755 index 00000000..a20420a2 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/light_graph.js @@ -0,0 +1,60 @@ +var lightChart; + +nv.addGraph(function () { + + lightChart = nv.models.lineChart() + .interpolate("linear") + .options({ + transitionDuration: 300, + useInteractiveGuideline: true + }) + ; + + lightChart.xScale(d3.time.scale()); + + // chart sub-models (ie. xAxis, yAxis, etc) when accessed directly, return themselves, not the parent chart, so need to chain separately + lightChart.xAxis + .axisLabel("Date/Time") + .ticks(d3.time.seconds) + .tickFormat(function (d) { + return d3.time.format('%m/%d/%Y %I:%M:%S %p')(new Date(d)) + }) + .staggerLabels(true) + ; + + lightChart.yAxis + .axisLabel('Light') + ; + + d3.select('.chart2 svg') + .datum(getLightChartData()) + .call(lightChart); + + nv.utils.windowResize(lightChart.update); + + return lightChart; +}); + +function getLightChartData() { + + return [ + { + area: true, + values: [], + key: "Light", + color: "#34500e" + } + ]; + +} + +function updateLightGraph(lightData) { + + var chartData = getLightChartData(); + chartData[0]['values'] = lightData; + + d3.select('.chart2 svg') + .datum(chartData) + .transition().duration(500) + .call(lightChart); +} \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/linewithfocuschart.js b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/linewithfocuschart.js new file mode 100755 index 00000000..e69de29b diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/moment.min.js b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/moment.min.js new file mode 100755 index 00000000..d0b48f73 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/moment.min.js @@ -0,0 +1,7 @@ +//! moment.js +//! version : 2.10.2 +//! authors : Tim Wood, Iskren Chernev, Moment.js contributors +//! license : MIT +//! momentjs.com +!function(a,b){"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):a.moment=b()}(this,function(){"use strict";function a(){return Ac.apply(null,arguments)}function b(a){Ac=a}function c(){return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1}}function d(a){return"[object Array]"===Object.prototype.toString.call(a)}function e(a){return"[object Date]"===Object.prototype.toString.call(a)||a instanceof Date}function f(a,b){var c,d=[];for(c=0;c0)for(c in Cc)d=Cc[c],e=b[d],"undefined"!=typeof e&&(a[d]=e);return a}function m(b){l(this,b),this._d=new Date(+b._d),Dc===!1&&(Dc=!0,a.updateOffset(this),Dc=!1)}function n(a){return a instanceof m||null!=a&&g(a,"_isAMomentObject")}function o(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=b>=0?Math.floor(b):Math.ceil(b)),c}function p(a,b,c){var d,e=Math.min(a.length,b.length),f=Math.abs(a.length-b.length),g=0;for(d=0;e>d;d++)(c&&a[d]!==b[d]||!c&&o(a[d])!==o(b[d]))&&g++;return g+f}function q(){}function r(a){return a?a.toLowerCase().replace("_","-"):a}function s(a){for(var b,c,d,e,f=0;f0;){if(d=t(e.slice(0,b).join("-")))return d;if(c&&c.length>=b&&p(e,c,!0)>=b-1)break;b--}f++}return null}function t(a){var b=null;if(!Ec[a]&&"undefined"!=typeof module&&module&&module.exports)try{b=Bc._abbr,require("./locale/"+a),u(b)}catch(c){}return Ec[a]}function u(a,b){var c;return a&&(c="undefined"==typeof b?w(a):v(a,b),c&&(Bc=c)),Bc._abbr}function v(a,b){return null!==b?(b.abbr=a,Ec[a]||(Ec[a]=new q),Ec[a].set(b),u(a),Ec[a]):(delete Ec[a],null)}function w(a){var b;if(a&&a._locale&&a._locale._abbr&&(a=a._locale._abbr),!a)return Bc;if(!d(a)){if(b=t(a))return b;a=[a]}return s(a)}function x(a,b){var c=a.toLowerCase();Fc[c]=Fc[c+"s"]=Fc[b]=a}function y(a){return"string"==typeof a?Fc[a]||Fc[a.toLowerCase()]:void 0}function z(a){var b,c,d={};for(c in a)g(a,c)&&(b=y(c),b&&(d[b]=a[c]));return d}function A(b,c){return function(d){return null!=d?(C(this,b,d),a.updateOffset(this,c),this):B(this,b)}}function B(a,b){return a._d["get"+(a._isUTC?"UTC":"")+b]()}function C(a,b,c){return a._d["set"+(a._isUTC?"UTC":"")+b](c)}function D(a,b){var c;if("object"==typeof a)for(c in a)this.set(c,a[c]);else if(a=y(a),"function"==typeof this[a])return this[a](b);return this}function E(a,b,c){for(var d=""+Math.abs(a),e=a>=0;d.lengthb;b++)d[b]=Jc[d[b]]?Jc[d[b]]:G(d[b]);return function(e){var f="";for(b=0;c>b;b++)f+=d[b]instanceof Function?d[b].call(e,a):d[b];return f}}function I(a,b){return a.isValid()?(b=J(b,a.localeData()),Ic[b]||(Ic[b]=H(b)),Ic[b](a)):a.localeData().invalidDate()}function J(a,b){function c(a){return b.longDateFormat(a)||a}var d=5;for(Hc.lastIndex=0;d>=0&&Hc.test(a);)a=a.replace(Hc,c),Hc.lastIndex=0,d-=1;return a}function K(a,b,c){Yc[a]="function"==typeof b?b:function(a){return a&&c?c:b}}function L(a,b){return g(Yc,a)?Yc[a](b._strict,b._locale):new RegExp(M(a))}function M(a){return a.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(a,b,c,d,e){return b||c||d||e}).replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function N(a,b){var c,d=b;for("string"==typeof a&&(a=[a]),"number"==typeof b&&(d=function(a,c){c[b]=o(a)}),c=0;cd;d++){if(e=i([2e3,d]),c&&!this._longMonthsParse[d]&&(this._longMonthsParse[d]=new RegExp("^"+this.months(e,"").replace(".","")+"$","i"),this._shortMonthsParse[d]=new RegExp("^"+this.monthsShort(e,"").replace(".","")+"$","i")),c||this._monthsParse[d]||(f="^"+this.months(e,"")+"|^"+this.monthsShort(e,""),this._monthsParse[d]=new RegExp(f.replace(".",""),"i")),c&&"MMMM"===b&&this._longMonthsParse[d].test(a))return d;if(c&&"MMM"===b&&this._shortMonthsParse[d].test(a))return d;if(!c&&this._monthsParse[d].test(a))return d}}function U(a,b){var c;return"string"==typeof b&&(b=a.localeData().monthsParse(b),"number"!=typeof b)?a:(c=Math.min(a.date(),Q(a.year(),b)),a._d["set"+(a._isUTC?"UTC":"")+"Month"](b,c),a)}function V(b){return null!=b?(U(this,b),a.updateOffset(this,!0),this):B(this,"Month")}function W(){return Q(this.year(),this.month())}function X(a){var b,c=a._a;return c&&-2===a._pf.overflow&&(b=c[_c]<0||c[_c]>11?_c:c[ad]<1||c[ad]>Q(c[$c],c[_c])?ad:c[bd]<0||c[bd]>24||24===c[bd]&&(0!==c[cd]||0!==c[dd]||0!==c[ed])?bd:c[cd]<0||c[cd]>59?cd:c[dd]<0||c[dd]>59?dd:c[ed]<0||c[ed]>999?ed:-1,a._pf._overflowDayOfYear&&($c>b||b>ad)&&(b=ad),a._pf.overflow=b),a}function Y(b){a.suppressDeprecationWarnings===!1&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+b)}function Z(a,b){var c=!0;return h(function(){return c&&(Y(a),c=!1),b.apply(this,arguments)},b)}function $(a,b){hd[a]||(Y(b),hd[a]=!0)}function _(a){var b,c,d=a._i,e=id.exec(d);if(e){for(a._pf.iso=!0,b=0,c=jd.length;c>b;b++)if(jd[b][1].exec(d)){a._f=jd[b][0]+(e[6]||" ");break}for(b=0,c=kd.length;c>b;b++)if(kd[b][1].exec(d)){a._f+=kd[b][0];break}d.match(Vc)&&(a._f+="Z"),sa(a)}else a._isValid=!1}function aa(b){var c=ld.exec(b._i);return null!==c?void(b._d=new Date(+c[1])):(_(b),void(b._isValid===!1&&(delete b._isValid,a.createFromInputFallback(b))))}function ba(a,b,c,d,e,f,g){var h=new Date(a,b,c,d,e,f,g);return 1970>a&&h.setFullYear(a),h}function ca(a){var b=new Date(Date.UTC.apply(null,arguments));return 1970>a&&b.setUTCFullYear(a),b}function da(a){return ea(a)?366:365}function ea(a){return a%4===0&&a%100!==0||a%400===0}function fa(){return ea(this.year())}function ga(a,b,c){var d,e=c-b,f=c-a.day();return f>e&&(f-=7),e-7>f&&(f+=7),d=za(a).add(f,"d"),{week:Math.ceil(d.dayOfYear()/7),year:d.year()}}function ha(a){return ga(a,this._week.dow,this._week.doy).week}function ia(){return this._week.dow}function ja(){return this._week.doy}function ka(a){var b=this.localeData().week(this);return null==a?b:this.add(7*(a-b),"d")}function la(a){var b=ga(this,1,4).week;return null==a?b:this.add(7*(a-b),"d")}function ma(a,b,c,d,e){var f,g,h=ca(a,0,1).getUTCDay();return h=0===h?7:h,c=null!=c?c:e,f=e-h+(h>d?7:0)-(e>h?7:0),g=7*(b-1)+(c-e)+f+1,{year:g>0?a:a-1,dayOfYear:g>0?g:da(a-1)+g}}function na(a){var b=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==a?b:this.add(a-b,"d")}function oa(a,b,c){return null!=a?a:null!=b?b:c}function pa(a){var b=new Date;return a._useUTC?[b.getUTCFullYear(),b.getUTCMonth(),b.getUTCDate()]:[b.getFullYear(),b.getMonth(),b.getDate()]}function qa(a){var b,c,d,e,f=[];if(!a._d){for(d=pa(a),a._w&&null==a._a[ad]&&null==a._a[_c]&&ra(a),a._dayOfYear&&(e=oa(a._a[$c],d[$c]),a._dayOfYear>da(e)&&(a._pf._overflowDayOfYear=!0),c=ca(e,0,a._dayOfYear),a._a[_c]=c.getUTCMonth(),a._a[ad]=c.getUTCDate()),b=0;3>b&&null==a._a[b];++b)a._a[b]=f[b]=d[b];for(;7>b;b++)a._a[b]=f[b]=null==a._a[b]?2===b?1:0:a._a[b];24===a._a[bd]&&0===a._a[cd]&&0===a._a[dd]&&0===a._a[ed]&&(a._nextDay=!0,a._a[bd]=0),a._d=(a._useUTC?ca:ba).apply(null,f),null!=a._tzm&&a._d.setUTCMinutes(a._d.getUTCMinutes()-a._tzm),a._nextDay&&(a._a[bd]=24)}}function ra(a){var b,c,d,e,f,g,h;b=a._w,null!=b.GG||null!=b.W||null!=b.E?(f=1,g=4,c=oa(b.GG,a._a[$c],ga(za(),1,4).year),d=oa(b.W,1),e=oa(b.E,1)):(f=a._locale._week.dow,g=a._locale._week.doy,c=oa(b.gg,a._a[$c],ga(za(),f,g).year),d=oa(b.w,1),null!=b.d?(e=b.d,f>e&&++d):e=null!=b.e?b.e+f:f),h=ma(c,d,e,g,f),a._a[$c]=h.year,a._dayOfYear=h.dayOfYear}function sa(b){if(b._f===a.ISO_8601)return void _(b);b._a=[],b._pf.empty=!0;var c,d,e,f,g,h=""+b._i,i=h.length,j=0;for(e=J(b._f,b._locale).match(Gc)||[],c=0;c0&&b._pf.unusedInput.push(g),h=h.slice(h.indexOf(d)+d.length),j+=d.length),Jc[f]?(d?b._pf.empty=!1:b._pf.unusedTokens.push(f),P(f,d,b)):b._strict&&!d&&b._pf.unusedTokens.push(f);b._pf.charsLeftOver=i-j,h.length>0&&b._pf.unusedInput.push(h),b._pf.bigHour===!0&&b._a[bd]<=12&&(b._pf.bigHour=void 0),b._a[bd]=ta(b._locale,b._a[bd],b._meridiem),qa(b),X(b)}function ta(a,b,c){var d;return null==c?b:null!=a.meridiemHour?a.meridiemHour(b,c):null!=a.isPM?(d=a.isPM(c),d&&12>b&&(b+=12),d||12!==b||(b=0),b):b}function ua(a){var b,d,e,f,g;if(0===a._f.length)return a._pf.invalidFormat=!0,void(a._d=new Date(0/0));for(f=0;fg)&&(e=g,d=b));h(a,d||b)}function va(a){if(!a._d){var b=z(a._i);a._a=[b.year,b.month,b.day||b.date,b.hour,b.minute,b.second,b.millisecond],qa(a)}}function wa(a){var b,c=a._i,e=a._f;return a._locale=a._locale||w(a._l),null===c||void 0===e&&""===c?k({nullInput:!0}):("string"==typeof c&&(a._i=c=a._locale.preparse(c)),n(c)?new m(X(c)):(d(e)?ua(a):e?sa(a):xa(a),b=new m(X(a)),b._nextDay&&(b.add(1,"d"),b._nextDay=void 0),b))}function xa(b){var c=b._i;void 0===c?b._d=new Date:e(c)?b._d=new Date(+c):"string"==typeof c?aa(b):d(c)?(b._a=f(c.slice(0),function(a){return parseInt(a,10)}),qa(b)):"object"==typeof c?va(b):"number"==typeof c?b._d=new Date(c):a.createFromInputFallback(b)}function ya(a,b,d,e,f){var g={};return"boolean"==typeof d&&(e=d,d=void 0),g._isAMomentObject=!0,g._useUTC=g._isUTC=f,g._l=d,g._i=a,g._f=b,g._strict=e,g._pf=c(),wa(g)}function za(a,b,c,d){return ya(a,b,c,d,!1)}function Aa(a,b){var c,e;if(1===b.length&&d(b[0])&&(b=b[0]),!b.length)return za();for(c=b[0],e=1;ea&&(a=-a,c="-"),c+E(~~(a/60),2)+b+E(~~a%60,2)})}function Ga(a){var b=(a||"").match(Vc)||[],c=b[b.length-1]||[],d=(c+"").match(qd)||["-",0,0],e=+(60*d[1])+o(d[2]);return"+"===d[0]?e:-e}function Ha(b,c){var d,f;return c._isUTC?(d=c.clone(),f=(n(b)||e(b)?+b:+za(b))-+d,d._d.setTime(+d._d+f),a.updateOffset(d,!1),d):za(b).local();return c._isUTC?za(b).zone(c._offset||0):za(b).local()}function Ia(a){return 15*-Math.round(a._d.getTimezoneOffset()/15)}function Ja(b,c){var d,e=this._offset||0;return null!=b?("string"==typeof b&&(b=Ga(b)),Math.abs(b)<16&&(b=60*b),!this._isUTC&&c&&(d=Ia(this)),this._offset=b,this._isUTC=!0,null!=d&&this.add(d,"m"),e!==b&&(!c||this._changeInProgress?Za(this,Ua(b-e,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,a.updateOffset(this,!0),this._changeInProgress=null)),this):this._isUTC?e:Ia(this)}function Ka(a,b){return null!=a?("string"!=typeof a&&(a=-a),this.utcOffset(a,b),this):-this.utcOffset()}function La(a){return this.utcOffset(0,a)}function Ma(a){return this._isUTC&&(this.utcOffset(0,a),this._isUTC=!1,a&&this.subtract(Ia(this),"m")),this}function Na(){return this._tzm?this.utcOffset(this._tzm):"string"==typeof this._i&&this.utcOffset(Ga(this._i)),this}function Oa(a){return a=a?za(a).utcOffset():0,(this.utcOffset()-a)%60===0}function Pa(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function Qa(){if(this._a){var a=this._isUTC?i(this._a):za(this._a);return this.isValid()&&p(this._a,a.toArray())>0}return!1}function Ra(){return!this._isUTC}function Sa(){return this._isUTC}function Ta(){return this._isUTC&&0===this._offset}function Ua(a,b){var c,d,e,f=a,h=null;return Ea(a)?f={ms:a._milliseconds,d:a._days,M:a._months}:"number"==typeof a?(f={},b?f[b]=a:f.milliseconds=a):(h=rd.exec(a))?(c="-"===h[1]?-1:1,f={y:0,d:o(h[ad])*c,h:o(h[bd])*c,m:o(h[cd])*c,s:o(h[dd])*c,ms:o(h[ed])*c}):(h=sd.exec(a))?(c="-"===h[1]?-1:1,f={y:Va(h[2],c),M:Va(h[3],c),d:Va(h[4],c),h:Va(h[5],c),m:Va(h[6],c),s:Va(h[7],c),w:Va(h[8],c)}):null==f?f={}:"object"==typeof f&&("from"in f||"to"in f)&&(e=Xa(za(f.from),za(f.to)),f={},f.ms=e.milliseconds,f.M=e.months),d=new Da(f),Ea(a)&&g(a,"_locale")&&(d._locale=a._locale),d}function Va(a,b){var c=a&&parseFloat(a.replace(",","."));return(isNaN(c)?0:c)*b}function Wa(a,b){var c={milliseconds:0,months:0};return c.months=b.month()-a.month()+12*(b.year()-a.year()),a.clone().add(c.months,"M").isAfter(b)&&--c.months,c.milliseconds=+b-+a.clone().add(c.months,"M"),c}function Xa(a,b){var c;return b=Ha(b,a),a.isBefore(b)?c=Wa(a,b):(c=Wa(b,a),c.milliseconds=-c.milliseconds,c.months=-c.months),c}function Ya(a,b){return function(c,d){var e,f;return null===d||isNaN(+d)||($(b,"moment()."+b+"(period, number) is deprecated. Please use moment()."+b+"(number, period)."),f=c,c=d,d=f),c="string"==typeof c?+c:c,e=Ua(c,d),Za(this,e,a),this}}function Za(b,c,d,e){var f=c._milliseconds,g=c._days,h=c._months;e=null==e?!0:e,f&&b._d.setTime(+b._d+f*d),g&&C(b,"Date",B(b,"Date")+g*d),h&&U(b,B(b,"Month")+h*d),e&&a.updateOffset(b,g||h)}function $a(a){var b=a||za(),c=Ha(b,this).startOf("day"),d=this.diff(c,"days",!0),e=-6>d?"sameElse":-1>d?"lastWeek":0>d?"lastDay":1>d?"sameDay":2>d?"nextDay":7>d?"nextWeek":"sameElse";return this.format(this.localeData().calendar(e,this,za(b)))}function _a(){return new m(this)}function ab(a,b){var c;return b=y("undefined"!=typeof b?b:"millisecond"),"millisecond"===b?(a=n(a)?a:za(a),+this>+a):(c=n(a)?+a:+za(a),c<+this.clone().startOf(b))}function bb(a,b){var c;return b=y("undefined"!=typeof b?b:"millisecond"),"millisecond"===b?(a=n(a)?a:za(a),+a>+this):(c=n(a)?+a:+za(a),+this.clone().endOf(b)a?Math.ceil(a):Math.floor(a)}function fb(a,b,c){var d,e,f=Ha(a,this),g=6e4*(f.utcOffset()-this.utcOffset());return b=y(b),"year"===b||"month"===b||"quarter"===b?(e=gb(this,f),"quarter"===b?e/=3:"year"===b&&(e/=12)):(d=this-f,e="second"===b?d/1e3:"minute"===b?d/6e4:"hour"===b?d/36e5:"day"===b?(d-g)/864e5:"week"===b?(d-g)/6048e5:d),c?e:eb(e)}function gb(a,b){var c,d,e=12*(b.year()-a.year())+(b.month()-a.month()),f=a.clone().add(e,"months");return 0>b-f?(c=a.clone().add(e-1,"months"),d=(b-f)/(f-c)):(c=a.clone().add(e+1,"months"),d=(b-f)/(c-f)),-(e+d)}function hb(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")}function ib(){var a=this.clone().utc();return 0b;b++)if(this._weekdaysParse[b]||(c=za([2e3,1]).day(b),d="^"+this.weekdays(c,"")+"|^"+this.weekdaysShort(c,"")+"|^"+this.weekdaysMin(c,""),this._weekdaysParse[b]=new RegExp(d.replace(".",""),"i")),this._weekdaysParse[b].test(a))return b}function Jb(a){var b=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=a?(a=Eb(a,this.localeData()),this.add(a-b,"d")):b}function Kb(a){var b=(this.day()+7-this.localeData()._week.dow)%7;return null==a?b:this.add(a-b,"d")}function Lb(a){return null==a?this.day()||7:this.day(this.day()%7?a:a-7)}function Mb(a,b){F(a,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),b)})}function Nb(a,b){return b._meridiemParse}function Ob(a){return"p"===(a+"").toLowerCase().charAt(0)}function Pb(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"}function Qb(a){F(0,[a,3],0,"millisecond")}function Rb(){return this._isUTC?"UTC":""}function Sb(){return this._isUTC?"Coordinated Universal Time":""}function Tb(a){return za(1e3*a)}function Ub(){return za.apply(null,arguments).parseZone()}function Vb(a,b,c){var d=this._calendar[a];return"function"==typeof d?d.call(b,c):d}function Wb(a){var b=this._longDateFormat[a];return!b&&this._longDateFormat[a.toUpperCase()]&&(b=this._longDateFormat[a.toUpperCase()].replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a]=b),b}function Xb(){return this._invalidDate}function Yb(a){return this._ordinal.replace("%d",a)}function Zb(a){return a}function $b(a,b,c,d){var e=this._relativeTime[c];return"function"==typeof e?e(a,b,c,d):e.replace(/%d/i,a)}function _b(a,b){var c=this._relativeTime[a>0?"future":"past"];return"function"==typeof c?c(b):c.replace(/%s/i,b)}function ac(a){var b,c;for(c in a)b=a[c],"function"==typeof b?this[c]=b:this["_"+c]=b;this._ordinalParseLenient=new RegExp(this._ordinalParse.source+"|"+/\d{1,2}/.source)}function bc(a,b,c,d){var e=w(),f=i().set(d,b);return e[c](f,a)}function cc(a,b,c,d,e){if("number"==typeof a&&(b=a,a=void 0),a=a||"",null!=b)return bc(a,b,c,e);var f,g=[];for(f=0;d>f;f++)g[f]=bc(a,f,c,e);return g}function dc(a,b){return cc(a,b,"months",12,"month")}function ec(a,b){return cc(a,b,"monthsShort",12,"month")}function fc(a,b){return cc(a,b,"weekdays",7,"day")}function gc(a,b){return cc(a,b,"weekdaysShort",7,"day")}function hc(a,b){return cc(a,b,"weekdaysMin",7,"day")}function ic(){var a=this._data;return this._milliseconds=Od(this._milliseconds),this._days=Od(this._days),this._months=Od(this._months),a.milliseconds=Od(a.milliseconds),a.seconds=Od(a.seconds),a.minutes=Od(a.minutes),a.hours=Od(a.hours),a.months=Od(a.months),a.years=Od(a.years),this}function jc(a,b,c,d){var e=Ua(b,c);return a._milliseconds+=d*e._milliseconds,a._days+=d*e._days,a._months+=d*e._months,a._bubble()}function kc(a,b){return jc(this,a,b,1)}function lc(a,b){return jc(this,a,b,-1)}function mc(){var a,b,c,d=this._milliseconds,e=this._days,f=this._months,g=this._data,h=0;return g.milliseconds=d%1e3,a=eb(d/1e3),g.seconds=a%60,b=eb(a/60),g.minutes=b%60,c=eb(b/60),g.hours=c%24,e+=eb(c/24),h=eb(nc(e)),e-=eb(oc(h)),f+=eb(e/30),e%=30,h+=eb(f/12),f%=12,g.days=e,g.months=f,g.years=h,this}function nc(a){return 400*a/146097}function oc(a){return 146097*a/400}function pc(a){var b,c,d=this._milliseconds;if(a=y(a),"month"===a||"year"===a)return b=this._days+d/864e5,c=this._months+12*nc(b),"month"===a?c:c/12;switch(b=this._days+Math.round(oc(this._months/12)),a){case"week":return b/7+d/6048e5;case"day":return b+d/864e5;case"hour":return 24*b+d/36e5;case"minute":return 24*b*60+d/6e4;case"second":return 24*b*60*60+d/1e3;case"millisecond":return Math.floor(24*b*60*60*1e3)+d;default:throw new Error("Unknown unit "+a)}}function qc(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*o(this._months/12)}function rc(a){return function(){return this.as(a)}}function sc(a){return a=y(a),this[a+"s"]()}function tc(a){return function(){return this._data[a]}}function uc(){return eb(this.days()/7)}function vc(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function wc(a,b,c){var d=Ua(a).abs(),e=ce(d.as("s")),f=ce(d.as("m")),g=ce(d.as("h")),h=ce(d.as("d")),i=ce(d.as("M")),j=ce(d.as("y")),k=e0,k[4]=c,vc.apply(null,k)}function xc(a,b){return void 0===de[a]?!1:void 0===b?de[a]:(de[a]=b,!0)}function yc(a){var b=this.localeData(),c=wc(this,!a,b);return a&&(c=b.pastFuture(+this,c)),b.postformat(c)}function zc(){var a=ee(this.years()),b=ee(this.months()),c=ee(this.days()),d=ee(this.hours()),e=ee(this.minutes()),f=ee(this.seconds()+this.milliseconds()/1e3),g=this.asSeconds();return g?(0>g?"-":"")+"P"+(a?a+"Y":"")+(b?b+"M":"")+(c?c+"D":"")+(d||e||f?"T":"")+(d?d+"H":"")+(e?e+"M":"")+(f?f+"S":""):"P0D"}var Ac,Bc,Cc=a.momentProperties=[],Dc=!1,Ec={},Fc={},Gc=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|x|X|zz?|ZZ?|.)/g,Hc=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,Ic={},Jc={},Kc=/\d/,Lc=/\d\d/,Mc=/\d{3}/,Nc=/\d{4}/,Oc=/[+-]?\d{6}/,Pc=/\d\d?/,Qc=/\d{1,3}/,Rc=/\d{1,4}/,Sc=/[+-]?\d{1,6}/,Tc=/\d+/,Uc=/[+-]?\d+/,Vc=/Z|[+-]\d\d:?\d\d/gi,Wc=/[+-]?\d+(\.\d{1,3})?/,Xc=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,Yc={},Zc={},$c=0,_c=1,ad=2,bd=3,cd=4,dd=5,ed=6;F("M",["MM",2],"Mo",function(){return this.month()+1}),F("MMM",0,0,function(a){return this.localeData().monthsShort(this,a)}),F("MMMM",0,0,function(a){return this.localeData().months(this,a)}),x("month","M"),K("M",Pc),K("MM",Pc,Lc),K("MMM",Xc),K("MMMM",Xc),N(["M","MM"],function(a,b){b[_c]=o(a)-1}),N(["MMM","MMMM"],function(a,b,c,d){var e=c._locale.monthsParse(a,d,c._strict);null!=e?b[_c]=e:c._pf.invalidMonth=a});var fd="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),gd="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),hd={};a.suppressDeprecationWarnings=!1;var id=/^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,jd=[["YYYYYY-MM-DD",/[+-]\d{6}-\d{2}-\d{2}/],["YYYY-MM-DD",/\d{4}-\d{2}-\d{2}/],["GGGG-[W]WW-E",/\d{4}-W\d{2}-\d/],["GGGG-[W]WW",/\d{4}-W\d{2}/],["YYYY-DDD",/\d{4}-\d{3}/]],kd=[["HH:mm:ss.SSSS",/(T| )\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss",/(T| )\d\d:\d\d:\d\d/],["HH:mm",/(T| )\d\d:\d\d/],["HH",/(T| )\d\d/]],ld=/^\/?Date\((\-?\d+)/i;a.createFromInputFallback=Z("moment construction falls back to js Date. This is discouraged and will be removed in upcoming major release. Please refer to https://github.com/moment/moment/issues/1407 for more info.",function(a){a._d=new Date(a._i+(a._useUTC?" UTC":""))}),F(0,["YY",2],0,function(){return this.year()%100}),F(0,["YYYY",4],0,"year"),F(0,["YYYYY",5],0,"year"),F(0,["YYYYYY",6,!0],0,"year"),x("year","y"),K("Y",Uc),K("YY",Pc,Lc),K("YYYY",Rc,Nc),K("YYYYY",Sc,Oc),K("YYYYYY",Sc,Oc),N(["YYYY","YYYYY","YYYYYY"],$c),N("YY",function(b,c){c[$c]=a.parseTwoDigitYear(b)}),a.parseTwoDigitYear=function(a){return o(a)+(o(a)>68?1900:2e3)};var md=A("FullYear",!1);F("w",["ww",2],"wo","week"),F("W",["WW",2],"Wo","isoWeek"),x("week","w"),x("isoWeek","W"),K("w",Pc),K("ww",Pc,Lc),K("W",Pc),K("WW",Pc,Lc),O(["w","ww","W","WW"],function(a,b,c,d){b[d.substr(0,1)]=o(a)});var nd={dow:0,doy:6};F("DDD",["DDDD",3],"DDDo","dayOfYear"),x("dayOfYear","DDD"),K("DDD",Qc),K("DDDD",Mc),N(["DDD","DDDD"],function(a,b,c){c._dayOfYear=o(a)}),a.ISO_8601=function(){};var od=Z("moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548",function(){var a=za.apply(null,arguments);return this>a?this:a}),pd=Z("moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548",function(){var a=za.apply(null,arguments);return a>this?this:a});Fa("Z",":"),Fa("ZZ",""),K("Z",Vc),K("ZZ",Vc),N(["Z","ZZ"],function(a,b,c){c._useUTC=!0,c._tzm=Ga(a)});var qd=/([\+\-]|\d\d)/gi;a.updateOffset=function(){};var rd=/(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,sd=/^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/;Ua.fn=Da.prototype;var td=Ya(1,"add"),ud=Ya(-1,"subtract");a.defaultFormat="YYYY-MM-DDTHH:mm:ssZ";var vd=Z("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(a){return void 0===a?this.localeData():this.locale(a)});F(0,["gg",2],0,function(){return this.weekYear()%100}),F(0,["GG",2],0,function(){return this.isoWeekYear()%100}),xb("gggg","weekYear"),xb("ggggg","weekYear"),xb("GGGG","isoWeekYear"),xb("GGGGG","isoWeekYear"),x("weekYear","gg"),x("isoWeekYear","GG"),K("G",Uc),K("g",Uc),K("GG",Pc,Lc),K("gg",Pc,Lc),K("GGGG",Rc,Nc),K("gggg",Rc,Nc),K("GGGGG",Sc,Oc),K("ggggg",Sc,Oc),O(["gggg","ggggg","GGGG","GGGGG"],function(a,b,c,d){b[d.substr(0,2)]=o(a)}),O(["gg","GG"],function(b,c,d,e){c[e]=a.parseTwoDigitYear(b)}),F("Q",0,0,"quarter"),x("quarter","Q"),K("Q",Kc),N("Q",function(a,b){b[_c]=3*(o(a)-1)}),F("D",["DD",2],"Do","date"),x("date","D"),K("D",Pc),K("DD",Pc,Lc),K("Do",function(a,b){return a?b._ordinalParse:b._ordinalParseLenient}),N(["D","DD"],ad),N("Do",function(a,b){b[ad]=o(a.match(Pc)[0],10)});var wd=A("Date",!0);F("d",0,"do","day"),F("dd",0,0,function(a){return this.localeData().weekdaysMin(this,a)}),F("ddd",0,0,function(a){return this.localeData().weekdaysShort(this,a)}),F("dddd",0,0,function(a){return this.localeData().weekdays(this,a)}),F("e",0,0,"weekday"),F("E",0,0,"isoWeekday"),x("day","d"),x("weekday","e"),x("isoWeekday","E"),K("d",Pc),K("e",Pc),K("E",Pc),K("dd",Xc),K("ddd",Xc),K("dddd",Xc),O(["dd","ddd","dddd"],function(a,b,c){var d=c._locale.weekdaysParse(a);null!=d?b.d=d:c._pf.invalidWeekday=a}),O(["d","e","E"],function(a,b,c,d){b[d]=o(a)});var xd="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),yd="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),zd="Su_Mo_Tu_We_Th_Fr_Sa".split("_");F("H",["HH",2],0,"hour"),F("h",["hh",2],0,function(){return this.hours()%12||12}),Mb("a",!0),Mb("A",!1),x("hour","h"),K("a",Nb),K("A",Nb),K("H",Pc),K("h",Pc),K("HH",Pc,Lc),K("hh",Pc,Lc),N(["H","HH"],bd),N(["a","A"],function(a,b,c){c._isPm=c._locale.isPM(a),c._meridiem=a}),N(["h","hh"],function(a,b,c){b[bd]=o(a),c._pf.bigHour=!0});var Ad=/[ap]\.?m?\.?/i,Bd=A("Hours",!0);F("m",["mm",2],0,"minute"),x("minute","m"),K("m",Pc),K("mm",Pc,Lc),N(["m","mm"],cd);var Cd=A("Minutes",!1);F("s",["ss",2],0,"second"),x("second","s"),K("s",Pc),K("ss",Pc,Lc),N(["s","ss"],dd);var Dd=A("Seconds",!1);F("S",0,0,function(){return~~(this.millisecond()/100)}),F(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),Qb("SSS"),Qb("SSSS"),x("millisecond","ms"),K("S",Qc,Kc),K("SS",Qc,Lc),K("SSS",Qc,Mc),K("SSSS",Tc),N(["S","SS","SSS","SSSS"],function(a,b){b[ed]=o(1e3*("0."+a))});var Ed=A("Milliseconds",!1);F("z",0,0,"zoneAbbr"),F("zz",0,0,"zoneName");var Fd=m.prototype;Fd.add=td,Fd.calendar=$a,Fd.clone=_a,Fd.diff=fb,Fd.endOf=pb,Fd.format=jb,Fd.from=kb,Fd.fromNow=lb,Fd.get=D,Fd.invalidAt=wb,Fd.isAfter=ab,Fd.isBefore=bb,Fd.isBetween=cb,Fd.isSame=db,Fd.isValid=ub,Fd.lang=vd,Fd.locale=mb,Fd.localeData=nb,Fd.max=pd,Fd.min=od,Fd.parsingFlags=vb,Fd.set=D,Fd.startOf=ob,Fd.subtract=ud,Fd.toArray=tb,Fd.toDate=sb,Fd.toISOString=ib,Fd.toJSON=ib,Fd.toString=hb,Fd.unix=rb,Fd.valueOf=qb,Fd.year=md,Fd.isLeapYear=fa,Fd.weekYear=zb,Fd.isoWeekYear=Ab,Fd.quarter=Fd.quarters=Db,Fd.month=V,Fd.daysInMonth=W,Fd.week=Fd.weeks=ka,Fd.isoWeek=Fd.isoWeeks=la,Fd.weeksInYear=Cb,Fd.isoWeeksInYear=Bb,Fd.date=wd,Fd.day=Fd.days=Jb,Fd.weekday=Kb,Fd.isoWeekday=Lb,Fd.dayOfYear=na,Fd.hour=Fd.hours=Bd,Fd.minute=Fd.minutes=Cd,Fd.second=Fd.seconds=Dd,Fd.millisecond=Fd.milliseconds=Ed,Fd.utcOffset=Ja,Fd.utc=La,Fd.local=Ma,Fd.parseZone=Na,Fd.hasAlignedHourOffset=Oa,Fd.isDST=Pa,Fd.isDSTShifted=Qa,Fd.isLocal=Ra,Fd.isUtcOffset=Sa,Fd.isUtc=Ta,Fd.isUTC=Ta,Fd.zoneAbbr=Rb,Fd.zoneName=Sb,Fd.dates=Z("dates accessor is deprecated. Use date instead.",wd),Fd.months=Z("months accessor is deprecated. Use month instead",V),Fd.years=Z("years accessor is deprecated. Use year instead",md),Fd.zone=Z("moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779",Ka);var Gd=Fd,Hd={sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},Id={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY LT",LLLL:"dddd, MMMM D, YYYY LT"},Jd="Invalid date",Kd="%d",Ld=/\d{1,2}/,Md={future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},Nd=q.prototype;Nd._calendar=Hd,Nd.calendar=Vb,Nd._longDateFormat=Id,Nd.longDateFormat=Wb,Nd._invalidDate=Jd,Nd.invalidDate=Xb,Nd._ordinal=Kd,Nd.ordinal=Yb,Nd._ordinalParse=Ld, +Nd.preparse=Zb,Nd.postformat=Zb,Nd._relativeTime=Md,Nd.relativeTime=$b,Nd.pastFuture=_b,Nd.set=ac,Nd.months=R,Nd._months=fd,Nd.monthsShort=S,Nd._monthsShort=gd,Nd.monthsParse=T,Nd.week=ha,Nd._week=nd,Nd.firstDayOfYear=ja,Nd.firstDayOfWeek=ia,Nd.weekdays=Fb,Nd._weekdays=xd,Nd.weekdaysMin=Hb,Nd._weekdaysMin=zd,Nd.weekdaysShort=Gb,Nd._weekdaysShort=yd,Nd.weekdaysParse=Ib,Nd.isPM=Ob,Nd._meridiemParse=Ad,Nd.meridiem=Pb,u("en",{ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(a){var b=a%10,c=1===o(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}}),a.lang=Z("moment.lang is deprecated. Use moment.locale instead.",u),a.langData=Z("moment.langData is deprecated. Use moment.localeData instead.",w);var Od=Math.abs,Pd=rc("ms"),Qd=rc("s"),Rd=rc("m"),Sd=rc("h"),Td=rc("d"),Ud=rc("w"),Vd=rc("M"),Wd=rc("y"),Xd=tc("milliseconds"),Yd=tc("seconds"),Zd=tc("minutes"),$d=tc("hours"),_d=tc("days"),ae=tc("months"),be=tc("years"),ce=Math.round,de={s:45,m:45,h:22,d:26,M:11},ee=Math.abs,fe=Da.prototype;fe.abs=ic,fe.add=kc,fe.subtract=lc,fe.as=pc,fe.asMilliseconds=Pd,fe.asSeconds=Qd,fe.asMinutes=Rd,fe.asHours=Sd,fe.asDays=Td,fe.asWeeks=Ud,fe.asMonths=Vd,fe.asYears=Wd,fe.valueOf=qc,fe._bubble=mc,fe.get=sc,fe.milliseconds=Xd,fe.seconds=Yd,fe.minutes=Zd,fe.hours=$d,fe.days=_d,fe.weeks=uc,fe.months=ae,fe.years=be,fe.humanize=yc,fe.toISOString=zc,fe.toString=zc,fe.toJSON=zc,fe.locale=mb,fe.localeData=nb,fe.toIsoString=Z("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",zc),fe.lang=vd,F("X",0,0,"unix"),F("x",0,0,"valueOf"),K("x",Uc),K("X",Wc),N("X",function(a,b,c){c._d=new Date(1e3*parseFloat(a,10))}),N("x",function(a,b,c){c._d=new Date(o(a))}),a.version="2.10.2",b(za),a.fn=Gd,a.min=Ba,a.max=Ca,a.utc=i,a.unix=Tb,a.months=dc,a.isDate=e,a.locale=u,a.invalid=k,a.duration=Ua,a.isMoment=n,a.weekdays=fc,a.parseZone=Ub,a.localeData=w,a.isDuration=Ea,a.monthsShort=ec,a.weekdaysMin=hc,a.defineLocale=v,a.weekdaysShort=gc,a.normalizeUnits=y,a.relativeTimeThreshold=xc;var ge=a;return ge}); \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/motion_graph.js b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/motion_graph.js new file mode 100755 index 00000000..7b91a456 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/motion_graph.js @@ -0,0 +1,60 @@ +var motionChart; + +nv.addGraph(function () { + + motionChart = nv.models.lineChart() + .interpolate("linear") + .options({ + transitionDuration: 300, + useInteractiveGuideline: true + }) + ; + + motionChart.xScale(d3.time.scale()); + + // chart sub-models (ie. xAxis, yAxis, etc) when accessed directly, return themselves, not the parent chart, so need to chain separately + motionChart.xAxis + .axisLabel("Date/Time") + .ticks(d3.time.seconds) + .tickFormat(function (d) { + return d3.time.format('%m/%d/%Y %I:%M:%S %p')(new Date(d)) + }) + .staggerLabels(true) + ; + + motionChart.yAxis + .axisLabel('Motion') + ; + + d3.select('.chart3 svg') + .datum(getMotionChartData()) + .call(motionChart); + + nv.utils.windowResize(motionChart.update); + + return motionChart; +}); + +function getMotionChartData() { + + return [ + { + area: true, + values: [], + key: "Motion", + color: "#34500e" + } + ]; + +} + +function updateMotionGraph(motionData) { + + var chartData = getMotionChartData(); + chartData[0]['values'] = motionData; + + d3.select('.chart3 svg') + .datum(chartData) + .transition().duration(500) + .call(motionChart); +} \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/nv.d3.js b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/nv.d3.js new file mode 100755 index 00000000..a302d512 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/nv.d3.js @@ -0,0 +1,11357 @@ +/* nvd3 version 1.7.1(https://github.com/novus/nvd3) 2015-02-08 */ +(function(){ + +// set up main nv object on window +var nv = window.nv || {}; +window.nv = nv; + +// the major global objects under the nv namespace +nv.dev = false; //set false when in production +nv.tooltip = nv.tooltip || {}; // For the tooltip system +nv.utils = nv.utils || {}; // Utility subsystem +nv.models = nv.models || {}; //stores all the possible models/components +nv.charts = {}; //stores all the ready to use charts +nv.graphs = []; //stores all the graphs currently on the page +nv.logs = {}; //stores some statistics and potential error messages + +nv.dispatch = d3.dispatch('render_start', 'render_end'); + +// Function bind polyfill +// Needed ONLY for phantomJS as it's missing until version 2.0 which is unreleased as of this comment +// https://github.com/ariya/phantomjs/issues/10522 +// http://kangax.github.io/compat-table/es5/#Function.prototype.bind +// phantomJS is used for running the test suite +if (!Function.prototype.bind) { + Function.prototype.bind = function (oThis) { + if (typeof this !== "function") { + // closest thing possible to the ECMAScript 5 internal IsCallable function + throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable"); + } + + var aArgs = Array.prototype.slice.call(arguments, 1), + fToBind = this, + fNOP = function () {}, + fBound = function () { + return fToBind.apply(this instanceof fNOP && oThis + ? this + : oThis, + aArgs.concat(Array.prototype.slice.call(arguments))); + }; + + fNOP.prototype = this.prototype; + fBound.prototype = new fNOP(); + return fBound; + }; +} + +// Development render timers - disabled if dev = false +if (nv.dev) { + nv.dispatch.on('render_start', function(e) { + nv.logs.startTime = +new Date(); + }); + + nv.dispatch.on('render_end', function(e) { + nv.logs.endTime = +new Date(); + nv.logs.totalTime = nv.logs.endTime - nv.logs.startTime; + nv.log('total', nv.logs.totalTime); // used for development, to keep track of graph generation times + }); +} + +// Logs all arguments, and returns the last so you can test things in place +// Note: in IE8 console.log is an object not a function, and if modernizr is used +// then calling Function.prototype.bind with with anything other than a function +// causes a TypeError to be thrown. +nv.log = function() { + if (nv.dev && window.console && console.log && console.log.apply) + console.log.apply(console, arguments); + else if (nv.dev && window.console && typeof console.log == "function" && Function.prototype.bind) { + var log = Function.prototype.bind.call(console.log, console); + log.apply(console, arguments); + } + return arguments[arguments.length - 1]; +}; + +// print console warning, should be used by deprecated functions +nv.deprecated = function(name) { + if (nv.dev && console && console.warn) { + console.warn('`' + name + '` has been deprecated.'); + } +}; + +// render function is used to queue up chart rendering +// in non-blocking timeout functions +nv.render = function render(step) { + // number of graphs to generate in each timeout loop + step = step || 1; + + nv.render.active = true; + nv.dispatch.render_start(); + + setTimeout(function() { + var chart, graph; + + for (var i = 0; i < step && (graph = nv.render.queue[i]); i++) { + chart = graph.generate(); + if (typeof graph.callback == typeof(Function)) graph.callback(chart); + nv.graphs.push(chart); + } + + nv.render.queue.splice(0, i); + + if (nv.render.queue.length) setTimeout(arguments.callee, 0); + else { + nv.dispatch.render_end(); + nv.render.active = false; + } + }, 0); +}; + +nv.render.active = false; +nv.render.queue = []; + +// main function to use when adding a new graph, see examples +nv.addGraph = function(obj) { + if (typeof arguments[0] === typeof(Function)) { + obj = {generate: arguments[0], callback: arguments[1]}; + } + + nv.render.queue.push(obj); + + if (!nv.render.active) { + nv.render(); + } +};/* Utility class to handle creation of an interactive layer. + This places a rectangle on top of the chart. When you mouse move over it, it sends a dispatch + containing the X-coordinate. It can also render a vertical line where the mouse is located. + + dispatch.elementMousemove is the important event to latch onto. It is fired whenever the mouse moves over + the rectangle. The dispatch is given one object which contains the mouseX/Y location. + It also has 'pointXValue', which is the conversion of mouseX to the x-axis scale. + */ +nv.interactiveGuideline = function() { + "use strict"; + + var tooltip = nv.models.tooltip(); + + //Public settings + var width = null; + var height = null; + + //Please pass in the bounding chart's top and left margins + //This is important for calculating the correct mouseX/Y positions. + var margin = {left: 0, top: 0} + , xScale = d3.scale.linear() + , yScale = d3.scale.linear() + , dispatch = d3.dispatch('elementMousemove', 'elementMouseout', 'elementClick', 'elementDblclick') + , showGuideLine = true; + //Must pass in the bounding chart's container. + //The mousemove event is attached to this container. + var svgContainer = null; + + // check if IE by looking for activeX + var isMSIE = "ActiveXObject" in window; + + + function layer(selection) { + selection.each(function(data) { + var container = d3.select(this); + var availableWidth = (width || 960), availableHeight = (height || 400); + var wrap = container.selectAll("g.nv-wrap.nv-interactiveLineLayer") + .data([data]); + var wrapEnter = wrap.enter() + .append("g").attr("class", " nv-wrap nv-interactiveLineLayer"); + wrapEnter.append("g").attr("class","nv-interactiveGuideLine"); + + if (!svgContainer) { + return; + } + + function mouseHandler() { + var d3mouse = d3.mouse(this); + var mouseX = d3mouse[0]; + var mouseY = d3mouse[1]; + var subtractMargin = true; + var mouseOutAnyReason = false; + if (isMSIE) { + /* + D3.js (or maybe SVG.getScreenCTM) has a nasty bug in Internet Explorer 10. + d3.mouse() returns incorrect X,Y mouse coordinates when mouse moving + over a rect in IE 10. + However, d3.event.offsetX/Y also returns the mouse coordinates + relative to the triggering . So we use offsetX/Y on IE. + */ + mouseX = d3.event.offsetX; + mouseY = d3.event.offsetY; + + /* + On IE, if you attach a mouse event listener to the container, + it will actually trigger it for all the child elements (like , , etc). + When this happens on IE, the offsetX/Y is set to where ever the child element + is located. + As a result, we do NOT need to subtract margins to figure out the mouse X/Y + position under this scenario. Removing the line below *will* cause + the interactive layer to not work right on IE. + */ + if(d3.event.target.tagName !== "svg") { + subtractMargin = false; + } + + if (d3.event.target.className.baseVal.match("nv-legend")) { + mouseOutAnyReason = true; + } + + } + + if(subtractMargin) { + mouseX -= margin.left; + mouseY -= margin.top; + } + + /* If mouseX/Y is outside of the chart's bounds, + trigger a mouseOut event. + */ + if (mouseX < 0 || mouseY < 0 + || mouseX > availableWidth || mouseY > availableHeight + || (d3.event.relatedTarget && d3.event.relatedTarget.ownerSVGElement === undefined) + || mouseOutAnyReason + ) { + + if (isMSIE) { + if (d3.event.relatedTarget + && d3.event.relatedTarget.ownerSVGElement === undefined + && d3.event.relatedTarget.className.match(tooltip.nvPointerEventsClass)) { + + return; + } + } + dispatch.elementMouseout({ + mouseX: mouseX, + mouseY: mouseY + }); + layer.renderGuideLine(null); //hide the guideline + return; + } + + var pointXValue = xScale.invert(mouseX); + dispatch.elementMousemove({ + mouseX: mouseX, + mouseY: mouseY, + pointXValue: pointXValue + }); + + //If user double clicks the layer, fire a elementDblclick + if (d3.event.type === "dblclick") { + dispatch.elementDblclick({ + mouseX: mouseX, + mouseY: mouseY, + pointXValue: pointXValue + }); + } + + // if user single clicks the layer, fire elementClick + if (d3.event.type === 'click') { + dispatch.elementClick({ + mouseX: mouseX, + mouseY: mouseY, + pointXValue: pointXValue + }); + } + } + + svgContainer + .on("mousemove",mouseHandler, true) + .on("mouseout" ,mouseHandler,true) + .on("dblclick" ,mouseHandler) + .on("click", mouseHandler) + ; + + //Draws a vertical guideline at the given X postion. + layer.renderGuideLine = function(x) { + if (!showGuideLine) return; + var line = wrap.select(".nv-interactiveGuideLine") + .selectAll("line") + .data((x != null) ? [nv.utils.NaNtoZero(x)] : [], String); + + line.enter() + .append("line") + .attr("class", "nv-guideline") + .attr("x1", function(d) { return d;}) + .attr("x2", function(d) { return d;}) + .attr("y1", availableHeight) + .attr("y2",0) + ; + line.exit().remove(); + + } + }); + } + + layer.dispatch = dispatch; + layer.tooltip = tooltip; + + layer.margin = function(_) { + if (!arguments.length) return margin; + margin.top = typeof _.top != 'undefined' ? _.top : margin.top; + margin.left = typeof _.left != 'undefined' ? _.left : margin.left; + return layer; + }; + + layer.width = function(_) { + if (!arguments.length) return width; + width = _; + return layer; + }; + + layer.height = function(_) { + if (!arguments.length) return height; + height = _; + return layer; + }; + + layer.xScale = function(_) { + if (!arguments.length) return xScale; + xScale = _; + return layer; + }; + + layer.showGuideLine = function(_) { + if (!arguments.length) return showGuideLine; + showGuideLine = _; + return layer; + }; + + layer.svgContainer = function(_) { + if (!arguments.length) return svgContainer; + svgContainer = _; + return layer; + }; + + return layer; +}; + +/* Utility class that uses d3.bisect to find the index in a given array, where a search value can be inserted. + This is different from normal bisectLeft; this function finds the nearest index to insert the search value. + + For instance, lets say your array is [1,2,3,5,10,30], and you search for 28. + Normal d3.bisectLeft will return 4, because 28 is inserted after the number 10. But interactiveBisect will return 5 + because 28 is closer to 30 than 10. + + Unit tests can be found in: interactiveBisectTest.html + + Has the following known issues: + * Will not work if the data points move backwards (ie, 10,9,8,7, etc) or if the data points are in random order. + * Won't work if there are duplicate x coordinate values. + */ +nv.interactiveBisect = function (values, searchVal, xAccessor) { + "use strict"; + if (! (values instanceof Array)) { + return null; + } + if (typeof xAccessor !== 'function') { + xAccessor = function(d,i) { + return d.x; + } + } + + var bisect = d3.bisector(xAccessor).left; + var index = d3.max([0, bisect(values,searchVal) - 1]); + var currentValue = xAccessor(values[index], index); + + if (typeof currentValue === 'undefined') { + currentValue = index; + } + + if (currentValue === searchVal) { + return index; //found exact match + } + + var nextIndex = d3.min([index+1, values.length - 1]); + var nextValue = xAccessor(values[nextIndex], nextIndex); + + if (typeof nextValue === 'undefined') { + nextValue = nextIndex; + } + + if (Math.abs(nextValue - searchVal) >= Math.abs(currentValue - searchVal)) { + return index; + } else { + return nextIndex + } +}; + +/* + Returns the index in the array "values" that is closest to searchVal. + Only returns an index if searchVal is within some "threshold". + Otherwise, returns null. + */ +nv.nearestValueIndex = function (values, searchVal, threshold) { + "use strict"; + var yDistMax = Infinity, indexToHighlight = null; + values.forEach(function(d,i) { + var delta = Math.abs(searchVal - d); + if ( delta <= yDistMax && delta < threshold) { + yDistMax = delta; + indexToHighlight = i; + } + }); + return indexToHighlight; +}; +/* Tooltip rendering model for nvd3 charts. + window.nv.models.tooltip is the updated,new way to render tooltips. + + window.nv.tooltip.show is the old tooltip code. + window.nv.tooltip.* also has various helper methods. + */ +(function() { + "use strict"; + window.nv.tooltip = {}; + + /* Model which can be instantiated to handle tooltip rendering. + Example usage: + var tip = nv.models.tooltip().gravity('w').distance(23) + .data(myDataObject); + + tip(); //just invoke the returned function to render tooltip. + */ + window.nv.models.tooltip = function() { + //HTML contents of the tooltip. If null, the content is generated via the data variable. + var content = null; + + /* + Tooltip data. If data is given in the proper format, a consistent tooltip is generated. + Example Format of data: + { + key: "Date", + value: "August 2009", + series: [ + {key: "Series 1", value: "Value 1", color: "#000"}, + {key: "Series 2", value: "Value 2", color: "#00f"} + ] + } + */ + var data = null; + + var gravity = 'w' //Can be 'n','s','e','w'. Determines how tooltip is positioned. + ,distance = 50 //Distance to offset tooltip from the mouse location. + ,snapDistance = 25 //Tolerance allowed before tooltip is moved from its current position (creates 'snapping' effect) + , fixedTop = null //If not null, this fixes the top position of the tooltip. + , classes = null //Attaches additional CSS classes to the tooltip DIV that is created. + , chartContainer = null //Parent DIV, of the SVG Container that holds the chart. + , tooltipElem = null //actual DOM element representing the tooltip. + , position = {left: null, top: null} //Relative position of the tooltip inside chartContainer. + , enabled = true; //True -> tooltips are rendered. False -> don't render tooltips. + + //Generates a unique id when you create a new tooltip() object + var id = "nvtooltip-" + Math.floor(Math.random() * 100000); + + //CSS class to specify whether element should not have mouse events. + var nvPointerEventsClass = "nv-pointer-events-none"; + + //Format function for the tooltip values column + var valueFormatter = function(d,i) { + return d; + }; + + //Format function for the tooltip header value. + var headerFormatter = function(d) { + return d; + }; + + //By default, the tooltip model renders a beautiful table inside a DIV. + //You can override this function if a custom tooltip is desired. + var contentGenerator = function(d) { + if (content != null) { + return content; + } + + if (d == null) { + return ''; + } + + var table = d3.select(document.createElement("table")); + var theadEnter = table.selectAll("thead") + .data([d]) + .enter().append("thead"); + + theadEnter.append("tr") + .append("td") + .attr("colspan",3) + .append("strong") + .classed("x-value",true) + .html(headerFormatter(d.value)); + + var tbodyEnter = table.selectAll("tbody") + .data([d]) + .enter().append("tbody"); + + var trowEnter = tbodyEnter.selectAll("tr") + .data(function(p) { return p.series}) + .enter() + .append("tr") + .classed("highlight", function(p) { return p.highlight}); + + trowEnter.append("td") + .classed("legend-color-guide",true) + .append("div") + .style("background-color", function(p) { return p.color}); + + trowEnter.append("td") + .classed("key",true) + .html(function(p) {return p.key}); + + trowEnter.append("td") + .classed("value",true) + .html(function(p,i) { return valueFormatter(p.value,i) }); + + + trowEnter.selectAll("td").each(function(p) { + if (p.highlight) { + var opacityScale = d3.scale.linear().domain([0,1]).range(["#fff",p.color]); + var opacity = 0.6; + d3.select(this) + .style("border-bottom-color", opacityScale(opacity)) + .style("border-top-color", opacityScale(opacity)) + ; + } + }); + + var html = table.node().outerHTML; + if (d.footer !== undefined) + html += ""; + return html; + + }; + + var dataSeriesExists = function(d) { + if (d && d.series && d.series.length > 0) { + return true; + } + return false; + }; + + //In situations where the chart is in a 'viewBox', re-position the tooltip based on how far chart is zoomed. + function convertViewBoxRatio() { + if (chartContainer) { + var svg = d3.select(chartContainer); + if (svg.node().tagName !== "svg") { + svg = svg.select("svg"); + } + var viewBox = (svg.node()) ? svg.attr('viewBox') : null; + if (viewBox) { + viewBox = viewBox.split(' '); + var ratio = parseInt(svg.style('width')) / viewBox[2]; + + position.left = position.left * ratio; + position.top = position.top * ratio; + } + } + } + + //Creates new tooltip container, or uses existing one on DOM. + function getTooltipContainer(newContent) { + var body; + if (chartContainer) { + body = d3.select(chartContainer); + } else { + body = d3.select("body"); + } + + var container = body.select(".nvtooltip"); + if (container.node() === null) { + //Create new tooltip div if it doesn't exist on DOM. + container = body.append("div") + .attr("class", "nvtooltip " + (classes? classes: "xy-tooltip")) + .attr("id",id) + ; + } + + container.node().innerHTML = newContent; + container.style("top",0).style("left",0).style("opacity",0); + container.selectAll("div, table, td, tr").classed(nvPointerEventsClass,true) + container.classed(nvPointerEventsClass,true); + return container.node(); + } + + //Draw the tooltip onto the DOM. + function nvtooltip() { + if (!enabled) return; + if (!dataSeriesExists(data)) return; + + convertViewBoxRatio(); + + var left = position.left; + var top = (fixedTop != null) ? fixedTop : position.top; + var container = getTooltipContainer(contentGenerator(data)); + tooltipElem = container; + if (chartContainer) { + var svgComp = chartContainer.getElementsByTagName("svg")[0]; + var boundRect = (svgComp) ? svgComp.getBoundingClientRect() : chartContainer.getBoundingClientRect(); + var svgOffset = {left:0,top:0}; + if (svgComp) { + var svgBound = svgComp.getBoundingClientRect(); + var chartBound = chartContainer.getBoundingClientRect(); + var svgBoundTop = svgBound.top; + + //Defensive code. Sometimes, svgBoundTop can be a really negative + // number, like -134254. That's a bug. + // If such a number is found, use zero instead. FireFox bug only + if (svgBoundTop < 0) { + var containerBound = chartContainer.getBoundingClientRect(); + svgBoundTop = (Math.abs(svgBoundTop) > containerBound.height) ? 0 : svgBoundTop; + } + svgOffset.top = Math.abs(svgBoundTop - chartBound.top); + svgOffset.left = Math.abs(svgBound.left - chartBound.left); + } + //If the parent container is an overflow
with scrollbars, subtract the scroll offsets. + //You need to also add any offset between the element and its containing
+ //Finally, add any offset of the containing
on the whole page. + left += chartContainer.offsetLeft + svgOffset.left - 2*chartContainer.scrollLeft; + top += chartContainer.offsetTop + svgOffset.top - 2*chartContainer.scrollTop; + } + + if (snapDistance && snapDistance > 0) { + top = Math.floor(top/snapDistance) * snapDistance; + } + + nv.tooltip.calcTooltipPosition([left,top], gravity, distance, container); + return nvtooltip; + } + + nvtooltip.nvPointerEventsClass = nvPointerEventsClass; + + nvtooltip.content = function(_) { + if (!arguments.length) return content; + content = _; + return nvtooltip; + }; + + //Returns tooltipElem...not able to set it. + nvtooltip.tooltipElem = function() { + return tooltipElem; + }; + + nvtooltip.contentGenerator = function(_) { + if (!arguments.length) return contentGenerator; + if (typeof _ === 'function') { + contentGenerator = _; + } + return nvtooltip; + }; + + nvtooltip.data = function(_) { + if (!arguments.length) return data; + data = _; + return nvtooltip; + }; + + nvtooltip.gravity = function(_) { + if (!arguments.length) return gravity; + gravity = _; + return nvtooltip; + }; + + nvtooltip.distance = function(_) { + if (!arguments.length) return distance; + distance = _; + return nvtooltip; + }; + + nvtooltip.snapDistance = function(_) { + if (!arguments.length) return snapDistance; + snapDistance = _; + return nvtooltip; + }; + + nvtooltip.classes = function(_) { + if (!arguments.length) return classes; + classes = _; + return nvtooltip; + }; + + nvtooltip.chartContainer = function(_) { + if (!arguments.length) return chartContainer; + chartContainer = _; + return nvtooltip; + }; + + nvtooltip.position = function(_) { + if (!arguments.length) return position; + position.left = (typeof _.left !== 'undefined') ? _.left : position.left; + position.top = (typeof _.top !== 'undefined') ? _.top : position.top; + return nvtooltip; + }; + + nvtooltip.fixedTop = function(_) { + if (!arguments.length) return fixedTop; + fixedTop = _; + return nvtooltip; + }; + + nvtooltip.enabled = function(_) { + if (!arguments.length) return enabled; + enabled = _; + return nvtooltip; + }; + + nvtooltip.valueFormatter = function(_) { + if (!arguments.length) return valueFormatter; + if (typeof _ === 'function') { + valueFormatter = _; + } + return nvtooltip; + }; + + nvtooltip.headerFormatter = function(_) { + if (!arguments.length) return headerFormatter; + if (typeof _ === 'function') { + headerFormatter = _; + } + return nvtooltip; + }; + + //id() is a read-only function. You can't use it to set the id. + nvtooltip.id = function() { + return id; + }; + + return nvtooltip; + }; + + //Original tooltip.show function. Kept for backward compatibility. + // pos = [left,top] + nv.tooltip.show = function(pos, content, gravity, dist, parentContainer, classes) { + + //Create new tooltip div if it doesn't exist on DOM. + var container = document.createElement('div'); + container.className = 'nvtooltip ' + (classes ? classes : 'xy-tooltip'); + + var body = parentContainer; + if ( !parentContainer || parentContainer.tagName.match(/g|svg/i)) { + //If the parent element is an SVG element, place tooltip in the element. + body = document.getElementsByTagName('body')[0]; + } + + container.style.left = 0; + container.style.top = 0; + container.style.opacity = 0; + // Content can also be dom element + if (typeof content !== 'string') + container.appendChild(content); + else + container.innerHTML = content; + body.appendChild(container); + + //If the parent container is an overflow
with scrollbars, subtract the scroll offsets. + if (parentContainer) { + pos[0] = pos[0] - parentContainer.scrollLeft; + pos[1] = pos[1] - parentContainer.scrollTop; + } + nv.tooltip.calcTooltipPosition(pos, gravity, dist, container); + }; + + //Looks up the ancestry of a DOM element, and returns the first NON-svg node. + nv.tooltip.findFirstNonSVGParent = function(Elem) { + while(Elem.tagName.match(/^g|svg$/i) !== null) { + Elem = Elem.parentNode; + } + return Elem; + }; + + //Finds the total offsetTop of a given DOM element. + //Looks up the entire ancestry of an element, up to the first relatively positioned element. + nv.tooltip.findTotalOffsetTop = function ( Elem, initialTop ) { + var offsetTop = initialTop; + + do { + if( !isNaN( Elem.offsetTop ) ) { + offsetTop += (Elem.offsetTop); + } + } while( Elem = Elem.offsetParent ); + return offsetTop; + }; + + //Finds the total offsetLeft of a given DOM element. + //Looks up the entire ancestry of an element, up to the first relatively positioned element. + nv.tooltip.findTotalOffsetLeft = function ( Elem, initialLeft) { + var offsetLeft = initialLeft; + + do { + if( !isNaN( Elem.offsetLeft ) ) { + offsetLeft += (Elem.offsetLeft); + } + } while( Elem = Elem.offsetParent ); + return offsetLeft; + }; + + //Global utility function to render a tooltip on the DOM. + //pos = [left,top] coordinates of where to place the tooltip, relative to the SVG chart container. + //gravity = how to orient the tooltip + //dist = how far away from the mouse to place tooltip + //container = tooltip DIV + nv.tooltip.calcTooltipPosition = function(pos, gravity, dist, container) { + + var height = parseInt(container.offsetHeight), + width = parseInt(container.offsetWidth), + windowWidth = nv.utils.windowSize().width, + windowHeight = nv.utils.windowSize().height, + scrollTop = window.pageYOffset, + scrollLeft = window.pageXOffset, + left, top; + + windowHeight = window.innerWidth >= document.body.scrollWidth ? windowHeight : windowHeight - 16; + windowWidth = window.innerHeight >= document.body.scrollHeight ? windowWidth : windowWidth - 16; + + gravity = gravity || 's'; + dist = dist || 20; + + var tooltipTop = function ( Elem ) { + return nv.tooltip.findTotalOffsetTop(Elem, top); + }; + + var tooltipLeft = function ( Elem ) { + return nv.tooltip.findTotalOffsetLeft(Elem,left); + }; + + switch (gravity) { + case 'e': + left = pos[0] - width - dist; + top = pos[1] - (height / 2); + var tLeft = tooltipLeft(container); + var tTop = tooltipTop(container); + if (tLeft < scrollLeft) left = pos[0] + dist > scrollLeft ? pos[0] + dist : scrollLeft - tLeft + left; + if (tTop < scrollTop) top = scrollTop - tTop + top; + if (tTop + height > scrollTop + windowHeight) top = scrollTop + windowHeight - tTop + top - height; + break; + case 'w': + left = pos[0] + dist; + top = pos[1] - (height / 2); + var tLeft = tooltipLeft(container); + var tTop = tooltipTop(container); + if (tLeft + width > windowWidth) left = pos[0] - width - dist; + if (tTop < scrollTop) top = scrollTop + 5; + if (tTop + height > scrollTop + windowHeight) top = scrollTop + windowHeight - tTop + top - height; + break; + case 'n': + left = pos[0] - (width / 2) - 5; + top = pos[1] + dist; + var tLeft = tooltipLeft(container); + var tTop = tooltipTop(container); + if (tLeft < scrollLeft) left = scrollLeft + 5; + if (tLeft + width > windowWidth) left = left - width/2 + 5; + if (tTop + height > scrollTop + windowHeight) top = scrollTop + windowHeight - tTop + top - height; + break; + case 's': + left = pos[0] - (width / 2); + top = pos[1] - height - dist; + var tLeft = tooltipLeft(container); + var tTop = tooltipTop(container); + if (tLeft < scrollLeft) left = scrollLeft + 5; + if (tLeft + width > windowWidth) left = left - width/2 + 5; + if (scrollTop > tTop) top = scrollTop; + break; + case 'none': + left = pos[0]; + top = pos[1] - dist; + var tLeft = tooltipLeft(container); + var tTop = tooltipTop(container); + break; + } + + container.style.left = left+'px'; + container.style.top = top+'px'; + container.style.opacity = 1; + container.style.position = 'absolute'; + + return container; + }; + + //Global utility function to remove tooltips from the DOM. + nv.tooltip.cleanup = function() { + + // Find the tooltips, mark them for removal by this class (so others cleanups won't find it) + var tooltips = document.getElementsByClassName('nvtooltip'); + var purging = []; + while(tooltips.length) { + purging.push(tooltips[0]); + tooltips[0].style.transitionDelay = '0 !important'; + tooltips[0].style.opacity = 0; + tooltips[0].className = 'nvtooltip-pending-removal'; + } + + setTimeout(function() { + + while (purging.length) { + var removeMe = purging.pop(); + removeMe.parentNode.removeChild(removeMe); + } + }, 500); + }; + +})(); + + +/* +Gets the browser window size + +Returns object with height and width properties + */ +nv.utils.windowSize = function() { + // Sane defaults + var size = {width: 640, height: 480}; + + // Earlier IE uses Doc.body + if (document.body && document.body.offsetWidth) { + size.width = document.body.offsetWidth; + size.height = document.body.offsetHeight; + } + + // IE can use depending on mode it is in + if (document.compatMode=='CSS1Compat' && + document.documentElement && + document.documentElement.offsetWidth ) { + + size.width = document.documentElement.offsetWidth; + size.height = document.documentElement.offsetHeight; + } + + // Most recent browsers use + if (window.innerWidth && window.innerHeight) { + size.width = window.innerWidth; + size.height = window.innerHeight; + } + return (size); +}; + + +/* +Binds callback function to run when window is resized + */ +nv.utils.windowResize = function(handler) { + if (window.addEventListener) { + window.addEventListener('resize', handler); + } else { + nv.log("ERROR: Failed to bind to window.resize with: ", handler); + } + // return object with clear function to remove the single added callback. + return { + callback: handler, + clear: function() { + window.removeEventListener('resize', handler); + } + } +}; + + +/* +Backwards compatible way to implement more d3-like coloring of graphs. +If passed an array, wrap it in a function which implements the old behavior +Else return what was passed in +*/ +nv.utils.getColor = function(color) { + //if you pass in nothing, get default colors back + if (!arguments.length) { + return nv.utils.defaultColor(); + + //if passed an array, wrap it in a function + } else if(color instanceof Array) { + return function(d, i) { return d.color || color[i % color.length]; }; + + //if passed a function, return the function, or whatever it may be + //external libs, such as angularjs-nvd3-directives use this + } else { + //can't really help it if someone passes rubbish as color + return color; + } +}; + + +/* +Default color chooser uses the index of an object as before. + */ +nv.utils.defaultColor = function() { + var colors = d3.scale.category20().range(); + return function(d, i) { + return d.color || colors[i % colors.length] + }; +}; + + +/* +Returns a color function that takes the result of 'getKey' for each series and +looks for a corresponding color from the dictionary +*/ +nv.utils.customTheme = function(dictionary, getKey, defaultColors) { + // use default series.key if getKey is undefined + getKey = getKey || function(series) { return series.key }; + defaultColors = defaultColors || d3.scale.category20().range(); + + // start at end of default color list and walk back to index 0 + var defIndex = defaultColors.length; + + return function(series, index) { + var key = getKey(series); + if (typeof dictionary[key] === 'function') { + return dictionary[key](); + } else if (dictionary[key] !== undefined) { + return dictionary[key]; + } else { + // no match in dictionary, use a default color + if (!defIndex) { + // used all the default colors, start over + defIndex = defaultColors.length; + } + defIndex = defIndex - 1; + return defaultColors[defIndex]; + } + }; +}; + + +/* +From the PJAX example on d3js.org, while this is not really directly needed +it's a very cool method for doing pjax, I may expand upon it a little bit, +open to suggestions on anything that may be useful +*/ +nv.utils.pjax = function(links, content) { + + var load = function(href) { + d3.html(href, function(fragment) { + var target = d3.select(content).node(); + target.parentNode.replaceChild( + d3.select(fragment).select(content).node(), + target); + nv.utils.pjax(links, content); + }); + }; + + d3.selectAll(links).on("click", function() { + history.pushState(this.href, this.textContent, this.href); + load(this.href); + d3.event.preventDefault(); + }); + + d3.select(window).on("popstate", function() { + if (d3.event.state) { + load(d3.event.state); + } + }); +}; + + +/* +For when we want to approximate the width in pixels for an SVG:text element. +Most common instance is when the element is in a display:none; container. +Forumla is : text.length * font-size * constant_factor +*/ +nv.utils.calcApproxTextWidth = function (svgTextElem) { + if (typeof svgTextElem.style === 'function' + && typeof svgTextElem.text === 'function') { + + var fontSize = parseInt(svgTextElem.style("font-size").replace("px","")); + var textLength = svgTextElem.text().length; + return textLength * fontSize * 0.5; + } + return 0; +}; + + +/* +Numbers that are undefined, null or NaN, convert them to zeros. +*/ +nv.utils.NaNtoZero = function(n) { + if (typeof n !== 'number' + || isNaN(n) + || n === null + || n === Infinity + || n === -Infinity) { + + return 0; + } + return n; +}; + +/* +Add a way to watch for d3 transition ends to d3 +*/ +d3.selection.prototype.watchTransition = function(renderWatch){ + var args = [this].concat([].slice.call(arguments, 1)); + return renderWatch.transition.apply(renderWatch, args); +}; + + +/* +Helper object to watch when d3 has rendered something +*/ +nv.utils.renderWatch = function(dispatch, duration) { + if (!(this instanceof nv.utils.renderWatch)) { + return new nv.utils.renderWatch(dispatch, duration); + } + + var _duration = duration !== undefined ? duration : 250; + var renderStack = []; + var self = this; + + this.models = function(models) { + models = [].slice.call(arguments, 0); + models.forEach(function(model){ + model.__rendered = false; + (function(m){ + m.dispatch.on('renderEnd', function(arg){ + m.__rendered = true; + self.renderEnd('model'); + }); + })(model); + + if (renderStack.indexOf(model) < 0) { + renderStack.push(model); + } + }); + return this; + }; + + this.reset = function(duration) { + if (duration !== undefined) { + _duration = duration; + } + renderStack = []; + }; + + this.transition = function(selection, args, duration) { + args = arguments.length > 1 ? [].slice.call(arguments, 1) : []; + + if (args.length > 1) { + duration = args.pop(); + } else { + duration = _duration !== undefined ? _duration : 250; + } + selection.__rendered = false; + + if (renderStack.indexOf(selection) < 0) { + renderStack.push(selection); + } + + if (duration === 0) { + selection.__rendered = true; + selection.delay = function() { return this; }; + selection.duration = function() { return this; }; + return selection; + } else { + if (selection.length === 0) { + selection.__rendered = true; + } else if (selection.every( function(d){ return !d.length; } )) { + selection.__rendered = true; + } else { + selection.__rendered = false; + } + + var n = 0; + return selection + .transition() + .duration(duration) + .each(function(){ ++n; }) + .each('end', function(d, i) { + if (--n === 0) { + selection.__rendered = true; + self.renderEnd.apply(this, args); + } + }); + } + }; + + this.renderEnd = function() { + if (renderStack.every( function(d){ return d.__rendered; } )) { + renderStack.forEach( function(d){ d.__rendered = false; }); + dispatch.renderEnd.apply(this, arguments); + } + } + +}; + + +/* +Takes multiple objects and combines them into the first one (dst) +example: nv.utils.deepExtend({a: 1}, {a: 2, b: 3}, {c: 4}); +gives: {a: 2, b: 3, c: 4} +*/ +nv.utils.deepExtend = function(dst){ + var sources = arguments.length > 1 ? [].slice.call(arguments, 1) : []; + sources.forEach(function(source) { + for (key in source) { + var isArray = dst[key] instanceof Array; + var isObject = typeof dst[key] === 'object'; + var srcObj = typeof source[key] === 'object'; + + if (isObject && !isArray && srcObj) { + nv.utils.deepExtend(dst[key], source[key]); + } else { + dst[key] = source[key]; + } + } + }); +}; + + +/* +state utility object, used to track d3 states in the models +*/ +nv.utils.state = function(){ + if (!(this instanceof nv.utils.state)) { + return new nv.utils.state(); + } + var state = {}; + var _self = this; + var _setState = function(){}; + var _getState = function(){ return {}; }; + var init = null; + var changed = null; + + this.dispatch = d3.dispatch('change', 'set'); + + this.dispatch.on('set', function(state){ + _setState(state, true); + }); + + this.getter = function(fn){ + _getState = fn; + return this; + }; + + this.setter = function(fn, callback) { + if (!callback) { + callback = function(){}; + } + _setState = function(state, update){ + fn(state); + if (update) { + callback(); + } + }; + return this; + }; + + this.init = function(state){ + init = init || {}; + nv.utils.deepExtend(init, state); + }; + + var _set = function(){ + var settings = _getState(); + + if (JSON.stringify(settings) === JSON.stringify(state)) { + return false; + } + + for (var key in settings) { + if (state[key] === undefined) { + state[key] = {}; + } + state[key] = settings[key]; + changed = true; + } + return true; + }; + + this.update = function(){ + if (init) { + _setState(init, false); + init = null; + } + if (_set.call(this)) { + this.dispatch.change(state); + } + }; + +}; + + +/* +Snippet of code you can insert into each nv.models.* to give you the ability to +do things like: +chart.options({ + showXAxis: true, + tooltips: true +}); + +To enable in the chart: +chart.options = nv.utils.optionsFunc.bind(chart); +*/ +nv.utils.optionsFunc = function(args) { + nv.deprecated('nv.utils.optionsFunc'); + if (args) { + d3.map(args).forEach((function(key,value) { + if (typeof this[key] === "function") { + this[key](value); + } + }).bind(this)); + } + return this; +}; + + +/* +numTicks: requested number of ticks +data: the chart data + +returns the number of ticks to actually use on X axis, based on chart data +to avoid duplicate ticks with the same value +*/ +nv.utils.calcTicksX = function(numTicks, data) { + // find max number of values from all data streams + var numValues = 1; + var i = 0; + for (i; i < data.length; i += 1) { + var stream_len = data[i] && data[i].values ? data[i].values.length : 0; + numValues = stream_len > numValues ? stream_len : numValues; + } + nv.log("Requested number of ticks: ", numTicks); + nv.log("Calculated max values to be: ", numValues); + // make sure we don't have more ticks than values to avoid duplicates + numTicks = numTicks > numValues ? numTicks = numValues - 1 : numTicks; + // make sure we have at least one tick + numTicks = numTicks < 1 ? 1 : numTicks; + // make sure it's an integer + numTicks = Math.floor(numTicks); + nv.log("Calculating tick count as: ", numTicks); + return numTicks; +}; + + +/* +returns number of ticks to actually use on Y axis, based on chart data +*/ +nv.utils.calcTicksY = function(numTicks, data) { + // currently uses the same logic but we can adjust here if needed later + return nv.utils.calcTicksX(numTicks, data); +}; + + +/* +Add a particular option from an options object onto chart +Options exposed on a chart are a getter/setter function that returns chart +on set to mimic typical d3 option chaining, e.g. svg.option1('a').option2('b'); + +option objects should be generated via Object.create() to provide +the option of manipulating data via get/set functions. +*/ +nv.utils.initOption = function(chart, name) { + // if it's a call option, just call it directly, otherwise do get/set + if (chart._calls && chart._calls[name]) { + chart[name] = chart._calls[name]; + } else { + chart[name] = function (_) { + if (!arguments.length) return chart._options[name]; + chart._options[name] = _; + return chart; + }; + } +}; + + +/* +Add all options in an options object to the chart +*/ +nv.utils.initOptions = function(chart) { + var ops = Object.getOwnPropertyNames(chart._options || {}); + var calls = Object.getOwnPropertyNames(chart._calls || {}); + ops = ops.concat(calls); + for (var i in ops) { + nv.utils.initOption(chart, ops[i]); + } +}; + + +/* +Inherit options from a D3 object +d3.rebind makes calling the function on target actually call it on source +Also use _d3options so we can track what we inherit for documentation and chained inheritance +*/ +nv.utils.inheritOptionsD3 = function(target, d3_source, oplist) { + target._d3options = oplist.concat(target._d3options || []); + oplist.unshift(d3_source); + oplist.unshift(target); + d3.rebind.apply(this, oplist); +}; + + +/* +Remove duplicates from an array +*/ +nv.utils.arrayUnique = function(a) { + return a.sort().filter(function(item, pos) { + return !pos || item != a[pos - 1]; + }); +}; + + +/* +Keeps a list of custom symbols to draw from in addition to d3.svg.symbol +Necessary since d3 doesn't let you extend its list -_- +Add new symbols by doing nv.utils.symbols.set('name', function(size){...}); +*/ +nv.utils.symbolMap = d3.map(); + + +/* +Replaces d3.svg.symbol so that we can look both there and our own map + */ +nv.utils.symbol = function() { + var type, + size = 64; + function symbol(d,i) { + var t = type.call(this,d,i); + var s = size.call(this,d,i); + if (d3.svg.symbolTypes.indexOf(t) !== -1) { + return d3.svg.symbol().type(t).size(s)(); + } else { + return nv.utils.symbolMap.get(t)(s); + } + } + symbol.type = function(_) { + if (!arguments.length) return type; + type = d3.functor(_); + return symbol; + }; + symbol.size = function(_) { + if (!arguments.length) return size; + size = d3.functor(_); + return symbol; + }; + return symbol; +}; + + +/* +Inherit option getter/setter functions from source to target +d3.rebind makes calling the function on target actually call it on source +Also track via _inherited and _d3options so we can track what we inherit +for documentation generation purposes and chained inheritance +*/ +nv.utils.inheritOptions = function(target, source) { + // inherit all the things + var ops = Object.getOwnPropertyNames(source._options || {}); + var calls = Object.getOwnPropertyNames(source._calls || {}); + var inherited = source._inherited || []; + var d3ops = source._d3options || []; + var args = ops.concat(calls).concat(inherited).concat(d3ops); + args.unshift(source); + args.unshift(target); + d3.rebind.apply(this, args); + // pass along the lists to keep track of them, don't allow duplicates + target._inherited = nv.utils.arrayUnique(ops.concat(calls).concat(inherited).concat(ops).concat(target._inherited || [])); + target._d3options = nv.utils.arrayUnique(d3ops.concat(target._d3options || [])); +}; + + +/* +Runs common initialize code on the svg before the chart builds +*/ +nv.utils.initSVG = function(svg) { + svg.classed({'nvd3-svg':true}); +};nv.models.axis = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var axis = d3.svg.axis(); + var scale = d3.scale.linear(); + + var margin = {top: 0, right: 0, bottom: 0, left: 0} + , width = 75 //only used for tickLabel currently + , height = 60 //only used for tickLabel currently + , axisLabelText = null + , showMaxMin = true //TODO: showMaxMin should be disabled on all ordinal scaled axes + , highlightZero = true + , rotateLabels = 0 + , rotateYLabel = true + , staggerLabels = false + , isOrdinal = false + , ticks = null + , axisLabelDistance = 0 + , duration = 250 + , dispatch = d3.dispatch('renderEnd') + , axisRendered = false + , maxMinRendered = false + ; + axis + .scale(scale) + .orient('bottom') + .tickFormat(function(d) { return d }) + ; + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var scale0; + var renderWatch = nv.utils.renderWatch(dispatch, duration); + + function chart(selection) { + renderWatch.reset(); + selection.each(function(data) { + var container = d3.select(this); + nv.utils.initSVG(container); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-axis').data([data]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-axis'); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g') + + if (ticks !== null) + axis.ticks(ticks); + else if (axis.orient() == 'top' || axis.orient() == 'bottom') + axis.ticks(Math.abs(scale.range()[1] - scale.range()[0]) / 100); + + //TODO: consider calculating width/height based on whether or not label is added, for reference in charts using this component + g.watchTransition(renderWatch, 'axis').call(axis); + + scale0 = scale0 || axis.scale(); + + var fmt = axis.tickFormat(); + if (fmt == null) { + fmt = scale0.tickFormat(); + } + + var axisLabel = g.selectAll('text.nv-axislabel') + .data([axisLabelText || null]); + axisLabel.exit().remove(); + + switch (axis.orient()) { + case 'top': + axisLabel.enter().append('text').attr('class', 'nv-axislabel'); + var w; + if (scale.range().length < 2) { + w = 0; + } else if (scale.range().length === 2) { + w = scale.range()[1]; + } else { + w = scale.range()[scale.range().length-1]+(scale.range()[1]-scale.range()[0]); + } + axisLabel + .attr('text-anchor', 'middle') + .attr('y', 0) + .attr('x', w/2); + if (showMaxMin) { + var axisMaxMin = wrap.selectAll('g.nv-axisMaxMin') + .data(scale.domain()); + axisMaxMin.enter().append('g').attr('class', 'nv-axisMaxMin').append('text'); + axisMaxMin.exit().remove(); + axisMaxMin + .attr('transform', function(d,i) { + return 'translate(' + nv.utils.NaNtoZero(scale(d)) + ',0)' + }) + .select('text') + .attr('dy', '-0.5em') + .attr('y', -axis.tickPadding()) + .attr('text-anchor', 'middle') + .text(function(d,i) { + var v = fmt(d); + return ('' + v).match('NaN') ? '' : v; + }); + axisMaxMin.watchTransition(renderWatch, 'min-max top') + .attr('transform', function(d,i) { + return 'translate(' + nv.utils.NaNtoZero(scale.range()[i]) + ',0)' + }); + } + break; + case 'bottom': + var xLabelMargin = axisLabelDistance + 36; + var maxTextWidth = 30; + var xTicks = g.selectAll('g').select("text"); + if (rotateLabels%360) { + //Calculate the longest xTick width + xTicks.each(function(d,i){ + var width = this.getBoundingClientRect().width; + if(width > maxTextWidth) maxTextWidth = width; + }); + //Convert to radians before calculating sin. Add 30 to margin for healthy padding. + var sin = Math.abs(Math.sin(rotateLabels*Math.PI/180)); + var xLabelMargin = (sin ? sin*maxTextWidth : maxTextWidth)+30; + //Rotate all xTicks + xTicks + .attr('transform', function(d,i,j) { return 'rotate(' + rotateLabels + ' 0,0)' }) + .style('text-anchor', rotateLabels%360 > 0 ? 'start' : 'end'); + } + axisLabel.enter().append('text').attr('class', 'nv-axislabel'); + var w; + if (scale.range().length < 2) { + w = 0; + } else if (scale.range().length === 2) { + w = scale.range()[1]; + } else { + w = scale.range()[scale.range().length-1]+(scale.range()[1]-scale.range()[0]); + } + axisLabel + .attr('text-anchor', 'middle') + .attr('y', xLabelMargin) + .attr('x', w/2); + if (showMaxMin) { + //if (showMaxMin && !isOrdinal) { + var axisMaxMin = wrap.selectAll('g.nv-axisMaxMin') + //.data(scale.domain()) + .data([scale.domain()[0], scale.domain()[scale.domain().length - 1]]); + axisMaxMin.enter().append('g').attr('class', 'nv-axisMaxMin').append('text'); + axisMaxMin.exit().remove(); + axisMaxMin + .attr('transform', function(d,i) { + return 'translate(' + nv.utils.NaNtoZero((scale(d) + (isOrdinal ? scale.rangeBand() / 2 : 0))) + ',0)' + }) + .select('text') + .attr('dy', '.71em') + .attr('y', axis.tickPadding()) + .attr('transform', function(d,i,j) { return 'rotate(' + rotateLabels + ' 0,0)' }) + .style('text-anchor', rotateLabels ? (rotateLabels%360 > 0 ? 'start' : 'end') : 'middle') + .text(function(d,i) { + var v = fmt(d); + return ('' + v).match('NaN') ? '' : v; + }); + axisMaxMin.watchTransition(renderWatch, 'min-max bottom') + .attr('transform', function(d,i) { + return 'translate(' + nv.utils.NaNtoZero((scale(d) + (isOrdinal ? scale.rangeBand() / 2 : 0))) + ',0)' + }); + } + if (staggerLabels) + xTicks + .attr('transform', function(d,i) { + return 'translate(0,' + (i % 2 == 0 ? '0' : '12') + ')' + }); + + break; + case 'right': + axisLabel.enter().append('text').attr('class', 'nv-axislabel'); + axisLabel + .style('text-anchor', rotateYLabel ? 'middle' : 'begin') + .attr('transform', rotateYLabel ? 'rotate(90)' : '') + .attr('y', rotateYLabel ? (-Math.max(margin.right,width) + 12) : -10) //TODO: consider calculating this based on largest tick width... OR at least expose this on chart + .attr('x', rotateYLabel ? (scale.range()[0] / 2) : axis.tickPadding()); + if (showMaxMin) { + var axisMaxMin = wrap.selectAll('g.nv-axisMaxMin') + .data(scale.domain()); + axisMaxMin.enter().append('g').attr('class', 'nv-axisMaxMin').append('text') + .style('opacity', 0); + axisMaxMin.exit().remove(); + axisMaxMin + .attr('transform', function(d,i) { + return 'translate(0,' + nv.utils.NaNtoZero(scale(d)) + ')' + }) + .select('text') + .attr('dy', '.32em') + .attr('y', 0) + .attr('x', axis.tickPadding()) + .style('text-anchor', 'start') + .text(function(d,i) { + var v = fmt(d); + return ('' + v).match('NaN') ? '' : v; + }); + axisMaxMin.watchTransition(renderWatch, 'min-max right') + .attr('transform', function(d,i) { + return 'translate(0,' + nv.utils.NaNtoZero(scale.range()[i]) + ')' + }) + .select('text') + .style('opacity', 1); + } + break; + case 'left': + /* + //For dynamically placing the label. Can be used with dynamically-sized chart axis margins + var yTicks = g.selectAll('g').select("text"); + yTicks.each(function(d,i){ + var labelPadding = this.getBoundingClientRect().width + axis.tickPadding() + 16; + if(labelPadding > width) width = labelPadding; + }); + */ + axisLabel.enter().append('text').attr('class', 'nv-axislabel'); + axisLabel + .style('text-anchor', rotateYLabel ? 'middle' : 'end') + .attr('transform', rotateYLabel ? 'rotate(-90)' : '') + .attr('y', rotateYLabel ? (-Math.max(margin.left,width) + 25 - (axisLabelDistance || 0)) : -10) + .attr('x', rotateYLabel ? (-scale.range()[0] / 2) : -axis.tickPadding()); + if (showMaxMin) { + var axisMaxMin = wrap.selectAll('g.nv-axisMaxMin') + .data(scale.domain()); + axisMaxMin.enter().append('g').attr('class', 'nv-axisMaxMin').append('text') + .style('opacity', 0); + axisMaxMin.exit().remove(); + axisMaxMin + .attr('transform', function(d,i) { + return 'translate(0,' + nv.utils.NaNtoZero(scale0(d)) + ')' + }) + .select('text') + .attr('dy', '.32em') + .attr('y', 0) + .attr('x', -axis.tickPadding()) + .attr('text-anchor', 'end') + .text(function(d,i) { + var v = fmt(d); + return ('' + v).match('NaN') ? '' : v; + }); + axisMaxMin.watchTransition(renderWatch, 'min-max right') + .attr('transform', function(d,i) { + return 'translate(0,' + nv.utils.NaNtoZero(scale.range()[i]) + ')' + }) + .select('text') + .style('opacity', 1); + } + break; + } + axisLabel.text(function(d) { return d }); + + if (showMaxMin && (axis.orient() === 'left' || axis.orient() === 'right')) { + //check if max and min overlap other values, if so, hide the values that overlap + g.selectAll('g') // the g's wrapping each tick + .each(function(d,i) { + d3.select(this).select('text').attr('opacity', 1); + if (scale(d) < scale.range()[1] + 10 || scale(d) > scale.range()[0] - 10) { // 10 is assuming text height is 16... if d is 0, leave it! + if (d > 1e-10 || d < -1e-10) // accounts for minor floating point errors... though could be problematic if the scale is EXTREMELY SMALL + d3.select(this).attr('opacity', 0); + + d3.select(this).select('text').attr('opacity', 0); // Don't remove the ZERO line!! + } + }); + + //if Max and Min = 0 only show min, Issue #281 + if (scale.domain()[0] == scale.domain()[1] && scale.domain()[0] == 0) { + wrap.selectAll('g.nv-axisMaxMin').style('opacity', function (d, i) { + return !i ? 1 : 0 + }); + } + } + + if (showMaxMin && (axis.orient() === 'top' || axis.orient() === 'bottom')) { + var maxMinRange = []; + wrap.selectAll('g.nv-axisMaxMin') + .each(function(d,i) { + try { + if (i) // i== 1, max position + maxMinRange.push(scale(d) - this.getBoundingClientRect().width - 4) //assuming the max and min labels are as wide as the next tick (with an extra 4 pixels just in case) + else // i==0, min position + maxMinRange.push(scale(d) + this.getBoundingClientRect().width + 4) + }catch (err) { + if (i) // i== 1, max position + maxMinRange.push(scale(d) - 4); //assuming the max and min labels are as wide as the next tick (with an extra 4 pixels just in case) + else // i==0, min position + maxMinRange.push(scale(d) + 4); + } + }); + // the g's wrapping each tick + g.selectAll('g').each(function(d,i) { + if (scale(d) < maxMinRange[0] || scale(d) > maxMinRange[1]) { + if (d > 1e-10 || d < -1e-10) // accounts for minor floating point errors... though could be problematic if the scale is EXTREMELY SMALL + d3.select(this).remove(); + else + d3.select(this).select('text').remove(); // Don't remove the ZERO line!! + } + }); + } + + //highlight zero line ... Maybe should not be an option and should just be in CSS? + if (highlightZero) { + g.selectAll('.tick') + .filter(function (d) { + return !parseFloat(Math.round(this.__data__ * 100000) / 1000000) && (this.__data__ !== undefined) + }) //this is because sometimes the 0 tick is a very small fraction, TODO: think of cleaner technique + .classed('zero', true); + } + //store old scales for use in transitions on update + scale0 = scale.copy(); + + }); + + renderWatch.renderEnd('axis immediate'); + return chart; + } + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + // expose chart's sub-components + chart.axis = axis; + chart.dispatch = dispatch; + + chart.options = nv.utils.optionsFunc.bind(chart); + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + axisLabelDistance: {get: function(){return axisLabelDistance;}, set: function(_){axisLabelDistance=_;}}, + staggerLabels: {get: function(){return staggerLabels;}, set: function(_){staggerLabels=_;}}, + rotateLabels: {get: function(){return rotateLabels;}, set: function(_){rotateLabels=_;}}, + rotateYLabel: {get: function(){return rotateYLabel;}, set: function(_){rotateYLabel=_;}}, + highlightZero: {get: function(){return highlightZero;}, set: function(_){highlightZero=_;}}, + showMaxMin: {get: function(){return showMaxMin;}, set: function(_){showMaxMin=_;}}, + axisLabel: {get: function(){return axisLabelText;}, set: function(_){axisLabelText=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + ticks: {get: function(){return ticks;}, set: function(_){ticks=_;}}, + width: {get: function(){return width;}, set: function(_){width=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration=_; + renderWatch.reset(duration); + }}, + scale: {get: function(){return scale;}, set: function(_){ + scale = _; + axis.scale(scale); + isOrdinal = typeof scale.rangeBands === 'function'; + nv.utils.inheritOptionsD3(chart, scale, ['domain', 'range', 'rangeBand', 'rangeBands']); + }} + }); + + nv.utils.initOptions(chart); + nv.utils.inheritOptionsD3(chart, axis, ['orient', 'tickValues', 'tickSubdivide', 'tickSize', 'tickPadding', 'tickFormat']); + nv.utils.inheritOptionsD3(chart, scale, ['domain', 'range', 'rangeBand', 'rangeBands']); + + return chart; +}; + +// Chart design based on the recommendations of Stephen Few. Implementation +// based on the work of Clint Ivy, Jamie Love, and Jason Davies. +// http://projects.instantcognition.com/protovis/bulletchart/ + +nv.models.bullet = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 0, right: 0, bottom: 0, left: 0} + , orient = 'left' // TODO top & bottom + , reverse = false + , ranges = function(d) { return d.ranges } + , markers = function(d) { return d.markers ? d.markers : [0] } + , measures = function(d) { return d.measures } + , rangeLabels = function(d) { return d.rangeLabels ? d.rangeLabels : [] } + , markerLabels = function(d) { return d.markerLabels ? d.markerLabels : [] } + , measureLabels = function(d) { return d.measureLabels ? d.measureLabels : [] } + , forceX = [0] // List of numbers to Force into the X scale (ie. 0, or a max / min, etc.) + , width = 380 + , height = 30 + , tickFormat = null + , color = nv.utils.getColor(['#1f77b4']) + , dispatch = d3.dispatch('elementMouseover', 'elementMouseout') + ; + + function chart(selection) { + selection.each(function(d, i) { + var availableWidth = width - margin.left - margin.right, + availableHeight = height - margin.top - margin.bottom, + container = d3.select(this); + nv.utils.initSVG(container); + + var rangez = ranges.call(this, d, i).slice().sort(d3.descending), + markerz = markers.call(this, d, i).slice().sort(d3.descending), + measurez = measures.call(this, d, i).slice().sort(d3.descending), + rangeLabelz = rangeLabels.call(this, d, i).slice(), + markerLabelz = markerLabels.call(this, d, i).slice(), + measureLabelz = measureLabels.call(this, d, i).slice(); + + // Setup Scales + // Compute the new x-scale. + var x1 = d3.scale.linear() + .domain( d3.extent(d3.merge([forceX, rangez])) ) + .range(reverse ? [availableWidth, 0] : [0, availableWidth]); + + // Retrieve the old x-scale, if this is an update. + var x0 = this.__chart__ || d3.scale.linear() + .domain([0, Infinity]) + .range(x1.range()); + + // Stash the new scale. + this.__chart__ = x1; + + var rangeMin = d3.min(rangez), //rangez[2] + rangeMax = d3.max(rangez), //rangez[0] + rangeAvg = rangez[1]; + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-bullet').data([d]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-bullet'); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g'); + + gEnter.append('rect').attr('class', 'nv-range nv-rangeMax'); + gEnter.append('rect').attr('class', 'nv-range nv-rangeAvg'); + gEnter.append('rect').attr('class', 'nv-range nv-rangeMin'); + gEnter.append('rect').attr('class', 'nv-measure'); + gEnter.append('path').attr('class', 'nv-markerTriangle'); + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + var w0 = function(d) { return Math.abs(x0(d) - x0(0)) }, // TODO: could optimize by precalculating x0(0) and x1(0) + w1 = function(d) { return Math.abs(x1(d) - x1(0)) }; + var xp0 = function(d) { return d < 0 ? x0(d) : x0(0) }, + xp1 = function(d) { return d < 0 ? x1(d) : x1(0) }; + + g.select('rect.nv-rangeMax') + .attr('height', availableHeight) + .attr('width', w1(rangeMax > 0 ? rangeMax : rangeMin)) + .attr('x', xp1(rangeMax > 0 ? rangeMax : rangeMin)) + .datum(rangeMax > 0 ? rangeMax : rangeMin) + + g.select('rect.nv-rangeAvg') + .attr('height', availableHeight) + .attr('width', w1(rangeAvg)) + .attr('x', xp1(rangeAvg)) + .datum(rangeAvg) + + g.select('rect.nv-rangeMin') + .attr('height', availableHeight) + .attr('width', w1(rangeMax)) + .attr('x', xp1(rangeMax)) + .attr('width', w1(rangeMax > 0 ? rangeMin : rangeMax)) + .attr('x', xp1(rangeMax > 0 ? rangeMin : rangeMax)) + .datum(rangeMax > 0 ? rangeMin : rangeMax) + + g.select('rect.nv-measure') + .style('fill', color) + .attr('height', availableHeight / 3) + .attr('y', availableHeight / 3) + .attr('width', measurez < 0 ? + x1(0) - x1(measurez[0]) + : x1(measurez[0]) - x1(0)) + .attr('x', xp1(measurez)) + .on('mouseover', function() { + dispatch.elementMouseover({ + value: measurez[0], + label: measureLabelz[0] || 'Current', + pos: [x1(measurez[0]), availableHeight/2] + }) + }) + .on('mouseout', function() { + dispatch.elementMouseout({ + value: measurez[0], + label: measureLabelz[0] || 'Current' + }) + }); + + var h3 = availableHeight / 6; + if (markerz[0]) { + g.selectAll('path.nv-markerTriangle') + .attr('transform', function(d) { return 'translate(' + x1(markerz[0]) + ',' + (availableHeight / 2) + ')' }) + .attr('d', 'M0,' + h3 + 'L' + h3 + ',' + (-h3) + ' ' + (-h3) + ',' + (-h3) + 'Z') + .on('mouseover', function() { + dispatch.elementMouseover({ + value: markerz[0], + label: markerLabelz[0] || 'Previous', + pos: [x1(markerz[0]), availableHeight/2] + }) + }) + .on('mouseout', function() { + dispatch.elementMouseout({ + value: markerz[0], + label: markerLabelz[0] || 'Previous' + }) + }); + } else { + g.selectAll('path.nv-markerTriangle').remove(); + } + + wrap.selectAll('.nv-range') + .on('mouseover', function(d,i) { + var label = rangeLabelz[i] || (!i ? "Maximum" : i == 1 ? "Mean" : "Minimum"); + + dispatch.elementMouseover({ + value: d, + label: label, + pos: [x1(d), availableHeight/2] + }) + }) + .on('mouseout', function(d,i) { + var label = rangeLabelz[i] || (!i ? "Maximum" : i == 1 ? "Mean" : "Minimum"); + + dispatch.elementMouseout({ + value: d, + label: label + }) + }); + }); + + return chart; + } + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + ranges: {get: function(){return ranges;}, set: function(_){ranges=_;}}, // ranges (bad, satisfactory, good) + markers: {get: function(){return markers;}, set: function(_){markers=_;}}, // markers (previous, goal) + measures: {get: function(){return measures;}, set: function(_){measures=_;}}, // measures (actual, forecast) + forceX: {get: function(){return forceX;}, set: function(_){forceX=_;}}, + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + tickFormat: {get: function(){return tickFormat;}, set: function(_){tickFormat=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + orient: {get: function(){return orient;}, set: function(_){ // left, right, top, bottom + orient = _; + reverse = orient == 'right' || orient == 'bottom'; + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + }} + }); + + nv.utils.initOptions(chart); + return chart; +}; + + + +// Chart design based on the recommendations of Stephen Few. Implementation +// based on the work of Clint Ivy, Jamie Love, and Jason Davies. +// http://projects.instantcognition.com/protovis/bulletchart/ +nv.models.bulletChart = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var bullet = nv.models.bullet() + ; + + var orient = 'left' // TODO top & bottom + , reverse = false + , margin = {top: 5, right: 40, bottom: 20, left: 120} + , ranges = function(d) { return d.ranges } + , markers = function(d) { return d.markers ? d.markers : [0] } + , measures = function(d) { return d.measures } + , width = null + , height = 55 + , tickFormat = null + , tooltips = true + , tooltip = function(key, x, y, e, graph) { + return '

' + x + '

' + + '

' + y + '

' + } + , noData = 'No Data Available.' + , dispatch = d3.dispatch('tooltipShow', 'tooltipHide') + ; + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var showTooltip = function(e, offsetElement) { + var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ) + margin.left, + top = e.pos[1] + ( offsetElement.offsetTop || 0) + margin.top, + content = tooltip(e.key, e.label, e.value, e, chart); + + nv.tooltip.show([left, top], content, e.value < 0 ? 'e' : 'w', null, offsetElement); + }; + + function chart(selection) { + selection.each(function(d, i) { + var container = d3.select(this); + nv.utils.initSVG(container); + + var availableWidth = (width || parseInt(container.style('width')) || 960) + - margin.left - margin.right, + availableHeight = height - margin.top - margin.bottom, + that = this; + + chart.update = function() { chart(selection) }; + chart.container = this; + + // Display No Data message if there's nothing to show. + if (!d || !ranges.call(this, d, i)) { + var noDataText = container.selectAll('.nv-noData').data([noData]); + + noDataText.enter().append('text') + .attr('class', 'nvd3 nv-noData') + .attr('dy', '-.7em') + .style('text-anchor', 'middle'); + + noDataText + .attr('x', margin.left + availableWidth / 2) + .attr('y', 18 + margin.top + availableHeight / 2) + .text(function(d) { return d }); + + return chart; + } else { + container.selectAll('.nv-noData').remove(); + } + + var rangez = ranges.call(this, d, i).slice().sort(d3.descending), + markerz = markers.call(this, d, i).slice().sort(d3.descending), + measurez = measures.call(this, d, i).slice().sort(d3.descending); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-bulletChart').data([d]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-bulletChart'); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-bulletWrap'); + gEnter.append('g').attr('class', 'nv-titles'); + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + // Compute the new x-scale. + var x1 = d3.scale.linear() + .domain([0, Math.max(rangez[0], markerz[0], measurez[0])]) // TODO: need to allow forceX and forceY, and xDomain, yDomain + .range(reverse ? [availableWidth, 0] : [0, availableWidth]); + + // Retrieve the old x-scale, if this is an update. + var x0 = this.__chart__ || d3.scale.linear() + .domain([0, Infinity]) + .range(x1.range()); + + // Stash the new scale. + this.__chart__ = x1; + + var w0 = function(d) { return Math.abs(x0(d) - x0(0)) }, // TODO: could optimize by precalculating x0(0) and x1(0) + w1 = function(d) { return Math.abs(x1(d) - x1(0)) }; + + var title = gEnter.select('.nv-titles').append('g') + .attr('text-anchor', 'end') + .attr('transform', 'translate(-6,' + (height - margin.top - margin.bottom) / 2 + ')'); + title.append('text') + .attr('class', 'nv-title') + .text(function(d) { return d.title; }); + + title.append('text') + .attr('class', 'nv-subtitle') + .attr('dy', '1em') + .text(function(d) { return d.subtitle; }); + + bullet + .width(availableWidth) + .height(availableHeight) + + var bulletWrap = g.select('.nv-bulletWrap'); + d3.transition(bulletWrap).call(bullet); + + // Compute the tick format. + var format = tickFormat || x1.tickFormat( availableWidth / 100 ); + + // Update the tick groups. + var tick = g.selectAll('g.nv-tick') + .data(x1.ticks( availableWidth / 50 ), function(d) { + return this.textContent || format(d); + }); + + // Initialize the ticks with the old scale, x0. + var tickEnter = tick.enter().append('g') + .attr('class', 'nv-tick') + .attr('transform', function(d) { return 'translate(' + x0(d) + ',0)' }) + .style('opacity', 1e-6); + + tickEnter.append('line') + .attr('y1', availableHeight) + .attr('y2', availableHeight * 7 / 6); + + tickEnter.append('text') + .attr('text-anchor', 'middle') + .attr('dy', '1em') + .attr('y', availableHeight * 7 / 6) + .text(format); + + // Transition the updating ticks to the new scale, x1. + var tickUpdate = d3.transition(tick) + .attr('transform', function(d) { return 'translate(' + x1(d) + ',0)' }) + .style('opacity', 1); + + tickUpdate.select('line') + .attr('y1', availableHeight) + .attr('y2', availableHeight * 7 / 6); + + tickUpdate.select('text') + .attr('y', availableHeight * 7 / 6); + + // Transition the exiting ticks to the new scale, x1. + d3.transition(tick.exit()) + .attr('transform', function(d) { return 'translate(' + x1(d) + ',0)' }) + .style('opacity', 1e-6) + .remove(); + + //============================================================ + // Event Handling/Dispatching (in chart's scope) + //------------------------------------------------------------ + + dispatch.on('tooltipShow', function(e) { + e.key = d.title; + if (tooltips) showTooltip(e, that.parentNode); + }); + + }); + + d3.timer.flush(); + return chart; + } + + //============================================================ + // Event Handling/Dispatching (out of chart's scope) + //------------------------------------------------------------ + + bullet.dispatch.on('elementMouseover.tooltip', function(e) { + dispatch.tooltipShow(e); + }); + + bullet.dispatch.on('elementMouseout.tooltip', function(e) { + dispatch.tooltipHide(e); + }); + + dispatch.on('tooltipHide', function() { + if (tooltips) nv.tooltip.cleanup(); + }); + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.bullet = bullet; + chart.dispatch = dispatch; + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + ranges: {get: function(){return ranges;}, set: function(_){ranges=_;}}, // ranges (bad, satisfactory, good) + markers: {get: function(){return markers;}, set: function(_){markers=_;}}, // markers (previous, goal) + measures: {get: function(){return measures;}, set: function(_){measures=_;}}, // measures (actual, forecast) + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + tickFormat: {get: function(){return tickFormat;}, set: function(_){tickFormat=_;}}, + tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, + tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, + noData: {get: function(){return noData;}, set: function(_){noData=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + orient: {get: function(){return orient;}, set: function(_){ // left, right, top, bottom + orient = _; + reverse = orient == 'right' || orient == 'bottom'; + }} + }); + + nv.utils.inheritOptions(chart, bullet); + nv.utils.initOptions(chart); + + return chart; +}; + + + +nv.models.cumulativeLineChart = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var lines = nv.models.line() + , xAxis = nv.models.axis() + , yAxis = nv.models.axis() + , legend = nv.models.legend() + , controls = nv.models.legend() + , interactiveLayer = nv.interactiveGuideline() + ; + + var margin = {top: 30, right: 30, bottom: 50, left: 60} + , color = nv.utils.defaultColor() + , width = null + , height = null + , showLegend = true + , showXAxis = true + , showYAxis = true + , rightAlignYAxis = false + , tooltips = true + , showControls = true + , useInteractiveGuideline = false + , rescaleY = true + , tooltip = function(key, x, y, e, graph) { + return '

' + key + '

' + + '

' + y + ' at ' + x + '

' + } + , x //can be accessed via chart.xScale() + , y //can be accessed via chart.yScale() + , id = lines.id() + , state = nv.utils.state() + , defaultState = null + , noData = 'No Data Available.' + , average = function(d) { return d.average } + , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState', 'renderEnd') + , transitionDuration = 250 + , duration = 250 + , noErrorCheck = false //if set to TRUE, will bypass an error check in the indexify function. + ; + + state.index = 0; + state.rescaleY = rescaleY; + + xAxis + .orient('bottom') + .tickPadding(7) + ; + yAxis + .orient((rightAlignYAxis) ? 'right' : 'left') + ; + + controls.updateState(false); + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var dx = d3.scale.linear() + , index = {i: 0, x: 0} + , renderWatch = nv.utils.renderWatch(dispatch, duration) + ; + + var showTooltip = function(e, offsetElement) { + var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ), + top = e.pos[1] + ( offsetElement.offsetTop || 0), + x = xAxis.tickFormat()(lines.x()(e.point, e.pointIndex)), + y = yAxis.tickFormat()(lines.y()(e.point, e.pointIndex)), + content = tooltip(e.series.key, x, y, e, chart); + + nv.tooltip.show([left, top], content, null, null, offsetElement); + }; + + var stateGetter = function(data) { + return function(){ + return { + active: data.map(function(d) { return !d.disabled }), + index: index.i, + rescaleY: rescaleY + }; + } + }; + + var stateSetter = function(data) { + return function(state) { + if (state.index !== undefined) + index.i = state.index; + if (state.rescaleY !== undefined) + rescaleY = state.rescaleY; + if (state.active !== undefined) + data.forEach(function(series,i) { + series.disabled = !state.active[i]; + }); + } + }; + + function chart(selection) { + renderWatch.reset(); + renderWatch.models(lines); + if (showXAxis) renderWatch.models(xAxis); + if (showYAxis) renderWatch.models(yAxis); + selection.each(function(data) { + var container = d3.select(this); + nv.utils.initSVG(container); + container.classed('nv-chart-' + id, true); + var that = this; + + var availableWidth = (width || parseInt(container.style('width')) || 960) + - margin.left - margin.right, + availableHeight = (height || parseInt(container.style('height')) || 400) + - margin.top - margin.bottom; + + chart.update = function() { + if (duration === 0) + container.call(chart); + else + container.transition().duration(duration).call(chart) + }; + chart.container = this; + + state + .setter(stateSetter(data), chart.update) + .getter(stateGetter(data)) + .update(); + + // DEPRECATED set state.disableddisabled + state.disabled = data.map(function(d) { return !!d.disabled }); + + if (!defaultState) { + var key; + defaultState = {}; + for (key in state) { + if (state[key] instanceof Array) + defaultState[key] = state[key].slice(0); + else + defaultState[key] = state[key]; + } + } + + var indexDrag = d3.behavior.drag() + .on('dragstart', dragStart) + .on('drag', dragMove) + .on('dragend', dragEnd); + + + function dragStart(d,i) { + d3.select(chart.container) + .style('cursor', 'ew-resize'); + } + + function dragMove(d,i) { + index.x = d3.event.x; + index.i = Math.round(dx.invert(index.x)); + updateZero(); + } + + function dragEnd(d,i) { + d3.select(chart.container) + .style('cursor', 'auto'); + + // update state and send stateChange with new index + state.index = index.i; + dispatch.stateChange(state); + } + + // Display No Data message if there's nothing to show. + if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { + var noDataText = container.selectAll('.nv-noData').data([noData]); + + noDataText.enter().append('text') + .attr('class', 'nvd3 nv-noData') + .attr('dy', '-.7em') + .style('text-anchor', 'middle'); + + noDataText + .attr('x', margin.left + availableWidth / 2) + .attr('y', margin.top + availableHeight / 2) + .text(function(d) { return d }); + + return chart; + } else { + container.selectAll('.nv-noData').remove(); + } + + // Setup Scales + x = lines.xScale(); + y = lines.yScale(); + + if (!rescaleY) { + var seriesDomains = data + .filter(function(series) { return !series.disabled }) + .map(function(series,i) { + var initialDomain = d3.extent(series.values, lines.y()); + + //account for series being disabled when losing 95% or more + if (initialDomain[0] < -.95) initialDomain[0] = -.95; + + return [ + (initialDomain[0] - initialDomain[1]) / (1 + initialDomain[1]), + (initialDomain[1] - initialDomain[0]) / (1 + initialDomain[0]) + ]; + }); + + var completeDomain = [ + d3.min(seriesDomains, function(d) { return d[0] }), + d3.max(seriesDomains, function(d) { return d[1] }) + ]; + + lines.yDomain(completeDomain); + } else { + lines.yDomain(null); + } + + dx.domain([0, data[0].values.length - 1]) //Assumes all series have same length + .range([0, availableWidth]) + .clamp(true); + + var data = indexify(index.i, data); + + // Setup containers and skeleton of chart + var interactivePointerEvents = (useInteractiveGuideline) ? "none" : "all"; + var wrap = container.selectAll('g.nv-wrap.nv-cumulativeLine').data([data]); + var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-cumulativeLine').append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-interactive'); + gEnter.append('g').attr('class', 'nv-x nv-axis').style("pointer-events","none"); + gEnter.append('g').attr('class', 'nv-y nv-axis'); + gEnter.append('g').attr('class', 'nv-background'); + gEnter.append('g').attr('class', 'nv-linesWrap').style("pointer-events",interactivePointerEvents); + gEnter.append('g').attr('class', 'nv-avgLinesWrap').style("pointer-events","none"); + gEnter.append('g').attr('class', 'nv-legendWrap'); + gEnter.append('g').attr('class', 'nv-controlsWrap'); + + // Legend + if (showLegend) { + legend.width(availableWidth); + + g.select('.nv-legendWrap') + .datum(data) + .call(legend); + + if ( margin.top != legend.height()) { + margin.top = legend.height(); + availableHeight = (height || parseInt(container.style('height')) || 400) + - margin.top - margin.bottom; + } + + g.select('.nv-legendWrap') + .attr('transform', 'translate(0,' + (-margin.top) +')') + } + + // Controls + if (showControls) { + var controlsData = [ + { key: 'Re-scale y-axis', disabled: !rescaleY } + ]; + + controls + .width(140) + .color(['#444', '#444', '#444']) + .rightAlign(false) + .margin({top: 5, right: 0, bottom: 5, left: 20}) + ; + + g.select('.nv-controlsWrap') + .datum(controlsData) + .attr('transform', 'translate(0,' + (-margin.top) +')') + .call(controls); + } + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + if (rightAlignYAxis) { + g.select(".nv-y.nv-axis") + .attr("transform", "translate(" + availableWidth + ",0)"); + } + + // Show error if series goes below 100% + var tempDisabled = data.filter(function(d) { return d.tempDisabled }); + + wrap.select('.tempDisabled').remove(); //clean-up and prevent duplicates + if (tempDisabled.length) { + wrap.append('text').attr('class', 'tempDisabled') + .attr('x', availableWidth / 2) + .attr('y', '-.71em') + .style('text-anchor', 'end') + .text(tempDisabled.map(function(d) { return d.key }).join(', ') + ' values cannot be calculated for this time period.'); + } + + //Set up interactive layer + if (useInteractiveGuideline) { + interactiveLayer + .width(availableWidth) + .height(availableHeight) + .margin({left:margin.left,top:margin.top}) + .svgContainer(container) + .xScale(x); + wrap.select(".nv-interactive").call(interactiveLayer); + } + + gEnter.select('.nv-background') + .append('rect'); + + g.select('.nv-background rect') + .attr('width', availableWidth) + .attr('height', availableHeight); + + lines + //.x(function(d) { return d.x }) + .y(function(d) { return d.display.y }) + .width(availableWidth) + .height(availableHeight) + .color(data.map(function(d,i) { + return d.color || color(d, i); + }).filter(function(d,i) { return !data[i].disabled && !data[i].tempDisabled; })); + + var linesWrap = g.select('.nv-linesWrap') + .datum(data.filter(function(d) { return !d.disabled && !d.tempDisabled })); + + linesWrap.call(lines); + + //Store a series index number in the data array. + data.forEach(function(d,i) { + d.seriesIndex = i; + }); + + var avgLineData = data.filter(function(d) { + return !d.disabled && !!average(d); + }); + + var avgLines = g.select(".nv-avgLinesWrap").selectAll("line") + .data(avgLineData, function(d) { return d.key; }); + + var getAvgLineY = function(d) { + //If average lines go off the svg element, clamp them to the svg bounds. + var yVal = y(average(d)); + if (yVal < 0) return 0; + if (yVal > availableHeight) return availableHeight; + return yVal; + }; + + avgLines.enter() + .append('line') + .style('stroke-width',2) + .style('stroke-dasharray','10,10') + .style('stroke',function (d,i) { + return lines.color()(d,d.seriesIndex); + }) + .attr('x1',0) + .attr('x2',availableWidth) + .attr('y1', getAvgLineY) + .attr('y2', getAvgLineY); + + avgLines + .style('stroke-opacity',function(d){ + //If average lines go offscreen, make them transparent + var yVal = y(average(d)); + if (yVal < 0 || yVal > availableHeight) return 0; + return 1; + }) + .attr('x1',0) + .attr('x2',availableWidth) + .attr('y1', getAvgLineY) + .attr('y2', getAvgLineY); + + avgLines.exit().remove(); + + //Create index line + var indexLine = linesWrap.selectAll('.nv-indexLine') + .data([index]); + indexLine.enter().append('rect').attr('class', 'nv-indexLine') + .attr('width', 3) + .attr('x', -2) + .attr('fill', 'red') + .attr('fill-opacity', .5) + .style("pointer-events","all") + .call(indexDrag); + + indexLine + .attr('transform', function(d) { return 'translate(' + dx(d.i) + ',0)' }) + .attr('height', availableHeight); + + // Setup Axes + if (showXAxis) { + xAxis + .scale(x) + .ticks( nv.utils.calcTicksX(availableWidth/70, data) ) + .tickSize(-availableHeight, 0); + + g.select('.nv-x.nv-axis') + .attr('transform', 'translate(0,' + y.range()[0] + ')'); + g.select('.nv-x.nv-axis') + .call(xAxis); + } + + if (showYAxis) { + yAxis + .scale(y) + .ticks( nv.utils.calcTicksY(availableHeight/36, data) ) + .tickSize( -availableWidth, 0); + + g.select('.nv-y.nv-axis') + .call(yAxis); + } + + //============================================================ + // Event Handling/Dispatching (in chart's scope) + //------------------------------------------------------------ + + function updateZero() { + indexLine + .data([index]); + + //When dragging the index line, turn off line transitions. + // Then turn them back on when done dragging. + var oldDuration = chart.duration(); + chart.duration(0); + chart.update(); + chart.duration(oldDuration); + } + + g.select('.nv-background rect') + .on('click', function() { + index.x = d3.mouse(this)[0]; + index.i = Math.round(dx.invert(index.x)); + + // update state and send stateChange with new index + state.index = index.i; + dispatch.stateChange(state); + + updateZero(); + }); + + lines.dispatch.on('elementClick', function(e) { + index.i = e.pointIndex; + index.x = dx(index.i); + + // update state and send stateChange with new index + state.index = index.i; + dispatch.stateChange(state); + + updateZero(); + }); + + controls.dispatch.on('legendClick', function(d,i) { + d.disabled = !d.disabled; + rescaleY = !d.disabled; + + state.rescaleY = rescaleY; + dispatch.stateChange(state); + chart.update(); + }); + + legend.dispatch.on('stateChange', function(newState) { + for (var key in newState) + state[key] = newState[key]; + dispatch.stateChange(state); + chart.update(); + }); + + interactiveLayer.dispatch.on('elementMousemove', function(e) { + lines.clearHighlights(); + var singlePoint, pointIndex, pointXLocation, allData = []; + + data + .filter(function(series, i) { + series.seriesIndex = i; + return !series.disabled; + }) + .forEach(function(series,i) { + pointIndex = nv.interactiveBisect(series.values, e.pointXValue, chart.x()); + lines.highlightPoint(i, pointIndex, true); + var point = series.values[pointIndex]; + if (typeof point === 'undefined') return; + if (typeof singlePoint === 'undefined') singlePoint = point; + if (typeof pointXLocation === 'undefined') pointXLocation = chart.xScale()(chart.x()(point,pointIndex)); + allData.push({ + key: series.key, + value: chart.y()(point, pointIndex), + color: color(series,series.seriesIndex) + }); + }); + + //Highlight the tooltip entry based on which point the mouse is closest to. + if (allData.length > 2) { + var yValue = chart.yScale().invert(e.mouseY); + var domainExtent = Math.abs(chart.yScale().domain()[0] - chart.yScale().domain()[1]); + var threshold = 0.03 * domainExtent; + var indexToHighlight = nv.nearestValueIndex(allData.map(function(d){return d.value}),yValue,threshold); + if (indexToHighlight !== null) + allData[indexToHighlight].highlight = true; + } + + var xValue = xAxis.tickFormat()(chart.x()(singlePoint,pointIndex), pointIndex); + interactiveLayer.tooltip + .position({left: pointXLocation + margin.left, top: e.mouseY + margin.top}) + .chartContainer(that.parentNode) + .enabled(tooltips) + .valueFormatter(function(d,i) { + return yAxis.tickFormat()(d); + }) + .data( + { + value: xValue, + series: allData + } + )(); + + interactiveLayer.renderGuideLine(pointXLocation); + }); + + interactiveLayer.dispatch.on("elementMouseout",function(e) { + dispatch.tooltipHide(); + lines.clearHighlights(); + }); + + dispatch.on('tooltipShow', function(e) { + if (tooltips) showTooltip(e, that.parentNode); + }); + + // Update chart from a state object passed to event handler + dispatch.on('changeState', function(e) { + + if (typeof e.disabled !== 'undefined') { + data.forEach(function(series,i) { + series.disabled = e.disabled[i]; + }); + + state.disabled = e.disabled; + } + + if (typeof e.index !== 'undefined') { + index.i = e.index; + index.x = dx(index.i); + + state.index = e.index; + + indexLine + .data([index]); + } + + if (typeof e.rescaleY !== 'undefined') { + rescaleY = e.rescaleY; + } + + chart.update(); + }); + + }); + + renderWatch.renderEnd('cumulativeLineChart immediate'); + + return chart; + } + + //============================================================ + // Event Handling/Dispatching (out of chart's scope) + //------------------------------------------------------------ + + lines.dispatch.on('elementMouseover.tooltip', function(e) { + e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; + dispatch.tooltipShow(e); + }); + + lines.dispatch.on('elementMouseout.tooltip', function(e) { + dispatch.tooltipHide(e); + }); + + dispatch.on('tooltipHide', function() { + if (tooltips) nv.tooltip.cleanup(); + }); + + //============================================================ + // Functions + //------------------------------------------------------------ + + var indexifyYGetter = null; + /* Normalize the data according to an index point. */ + function indexify(idx, data) { + if (!indexifyYGetter) indexifyYGetter = lines.y(); + return data.map(function(line, i) { + if (!line.values) { + return line; + } + var indexValue = line.values[idx]; + if (indexValue == null) { + return line; + } + var v = indexifyYGetter(indexValue, idx); + + //TODO: implement check below, and disable series if series loses 100% or more cause divide by 0 issue + if (v < -.95 && !noErrorCheck) { + //if a series loses more than 100%, calculations fail.. anything close can cause major distortion (but is mathematically correct till it hits 100) + + line.tempDisabled = true; + return line; + } + + line.tempDisabled = false; + + line.values = line.values.map(function(point, pointIndex) { + point.display = {'y': (indexifyYGetter(point, pointIndex) - v) / (1 + v) }; + return point; + }); + + return line; + }) + } + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + // expose chart's sub-components + chart.dispatch = dispatch; + chart.lines = lines; + chart.legend = legend; + chart.xAxis = xAxis; + chart.yAxis = yAxis; + chart.interactiveLayer = interactiveLayer; + chart.state = state; + + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + rescaleY: {get: function(){return rescaleY;}, set: function(_){rescaleY=_;}}, + showControls: {get: function(){return showControls;}, set: function(_){showControls=_;}}, + showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, + average: {get: function(){return average;}, set: function(_){average=_;}}, + tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, + tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, + defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, + noData: {get: function(){return noData;}, set: function(_){noData=_;}}, + showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}}, + showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}}, + noErrorCheck: {get: function(){return noErrorCheck;}, set: function(_){noErrorCheck=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + legend.color(color); + }}, + useInteractiveGuideline: {get: function(){return useInteractiveGuideline;}, set: function(_){ + useInteractiveGuideline = _; + if (_ === true) { + chart.interactive(false); + chart.useVoronoi(false); + } + }}, + rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){ + rightAlignYAxis = _; + yAxis.orient( (_) ? 'right' : 'left'); + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration = _; + lines.duration(duration); + xAxis.duration(duration); + yAxis.duration(duration); + renderWatch.reset(duration); + }} + }); + + nv.utils.inheritOptions(chart, lines); + nv.utils.initOptions(chart); + + return chart; +};//TODO: consider deprecating by adding necessary features to multiBar model +nv.models.discreteBar = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 0, right: 0, bottom: 0, left: 0} + , width = 960 + , height = 500 + , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one + , x = d3.scale.ordinal() + , y = d3.scale.linear() + , getX = function(d) { return d.x } + , getY = function(d) { return d.y } + , forceY = [0] // 0 is forced by default.. this makes sense for the majority of bar graphs... user can always do chart.forceY([]) to remove + , color = nv.utils.defaultColor() + , showValues = false + , valueFormat = d3.format(',.2f') + , xDomain + , yDomain + , xRange + , yRange + , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout','renderEnd') + , rectClass = 'discreteBar' + , duration = 250 + ; + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var x0, y0; + var renderWatch = nv.utils.renderWatch(dispatch, duration); + + function chart(selection) { + renderWatch.reset(); + selection.each(function(data) { + var availableWidth = width - margin.left - margin.right, + availableHeight = height - margin.top - margin.bottom, + container = d3.select(this); + nv.utils.initSVG(container); + + //add series index to each data point for reference + data.forEach(function(series, i) { + series.values.forEach(function(point) { + point.series = i; + }); + }); + + // Setup Scales + // remap and flatten the data for use in calculating the scales' domains + var seriesData = (xDomain && yDomain) ? [] : // if we know xDomain and yDomain, no need to calculate + data.map(function(d) { + return d.values.map(function(d,i) { + return { x: getX(d,i), y: getY(d,i), y0: d.y0 } + }) + }); + + x .domain(xDomain || d3.merge(seriesData).map(function(d) { return d.x })) + .rangeBands(xRange || [0, availableWidth], .1); + y .domain(yDomain || d3.extent(d3.merge(seriesData).map(function(d) { return d.y }).concat(forceY))); + + // If showValues, pad the Y axis range to account for label height + if (showValues) y.range(yRange || [availableHeight - (y.domain()[0] < 0 ? 12 : 0), y.domain()[1] > 0 ? 12 : 0]); + else y.range(yRange || [availableHeight, 0]); + + //store old scales if they exist + x0 = x0 || x; + y0 = y0 || y.copy().range([y(0),y(0)]); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-discretebar').data([data]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-discretebar'); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-groups'); + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + //TODO: by definition, the discrete bar should not have multiple groups, will modify/remove later + var groups = wrap.select('.nv-groups').selectAll('.nv-group') + .data(function(d) { return d }, function(d) { return d.key }); + groups.enter().append('g') + .style('stroke-opacity', 1e-6) + .style('fill-opacity', 1e-6); + groups.exit() + .watchTransition(renderWatch, 'discreteBar: exit groups') + .style('stroke-opacity', 1e-6) + .style('fill-opacity', 1e-6) + .remove(); + groups + .attr('class', function(d,i) { return 'nv-group nv-series-' + i }) + .classed('hover', function(d) { return d.hover }); + groups + .watchTransition(renderWatch, 'discreteBar: groups') + .style('stroke-opacity', 1) + .style('fill-opacity', .75); + + var bars = groups.selectAll('g.nv-bar') + .data(function(d) { return d.values }); + bars.exit().remove(); + + var barsEnter = bars.enter().append('g') + .attr('transform', function(d,i,j) { + return 'translate(' + (x(getX(d,i)) + x.rangeBand() * .05 ) + ', ' + y(0) + ')' + }) + .on('mouseover', function(d,i) { //TODO: figure out why j works above, but not here + d3.select(this).classed('hover', true); + dispatch.elementMouseover({ + value: getY(d,i), + point: d, + series: data[d.series], + pos: [x(getX(d,i)) + (x.rangeBand() * (d.series + .5) / data.length), y(getY(d,i))], // TODO: Figure out why the value appears to be shifted + pointIndex: i, + seriesIndex: d.series, + e: d3.event + }); + }) + .on('mouseout', function(d,i) { + d3.select(this).classed('hover', false); + dispatch.elementMouseout({ + value: getY(d,i), + point: d, + series: data[d.series], + pointIndex: i, + seriesIndex: d.series, + e: d3.event + }); + }) + .on('click', function(d,i) { + dispatch.elementClick({ + value: getY(d,i), + point: d, + series: data[d.series], + pos: [x(getX(d,i)) + (x.rangeBand() * (d.series + .5) / data.length), y(getY(d,i))], // TODO: Figure out why the value appears to be shifted + pointIndex: i, + seriesIndex: d.series, + e: d3.event + }); + d3.event.stopPropagation(); + }) + .on('dblclick', function(d,i) { + dispatch.elementDblClick({ + value: getY(d,i), + point: d, + series: data[d.series], + pos: [x(getX(d,i)) + (x.rangeBand() * (d.series + .5) / data.length), y(getY(d,i))], // TODO: Figure out why the value appears to be shifted + pointIndex: i, + seriesIndex: d.series, + e: d3.event + }); + d3.event.stopPropagation(); + }); + + barsEnter.append('rect') + .attr('height', 0) + .attr('width', x.rangeBand() * .9 / data.length ) + + if (showValues) { + barsEnter.append('text') + .attr('text-anchor', 'middle') + ; + + bars.select('text') + .text(function(d,i) { return valueFormat(getY(d,i)) }) + .watchTransition(renderWatch, 'discreteBar: bars text') + .attr('x', x.rangeBand() * .9 / 2) + .attr('y', function(d,i) { return getY(d,i) < 0 ? y(getY(d,i)) - y(0) + 12 : -4 }) + + ; + } else { + bars.selectAll('text').remove(); + } + + bars + .attr('class', function(d,i) { return getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive' }) + .style('fill', function(d,i) { return d.color || color(d,i) }) + .style('stroke', function(d,i) { return d.color || color(d,i) }) + .select('rect') + .attr('class', rectClass) + .watchTransition(renderWatch, 'discreteBar: bars rect') + .attr('width', x.rangeBand() * .9 / data.length); + bars.watchTransition(renderWatch, 'discreteBar: bars') + //.delay(function(d,i) { return i * 1200 / data[0].values.length }) + .attr('transform', function(d,i) { + var left = x(getX(d,i)) + x.rangeBand() * .05, + top = getY(d,i) < 0 ? + y(0) : + y(0) - y(getY(d,i)) < 1 ? + y(0) - 1 : //make 1 px positive bars show up above y=0 + y(getY(d,i)); + + return 'translate(' + left + ', ' + top + ')' + }) + .select('rect') + .attr('height', function(d,i) { + return Math.max(Math.abs(y(getY(d,i)) - y((yDomain && yDomain[0]) || 0)) || 1) + }); + + + //store old scales for use in transitions on update + x0 = x.copy(); + y0 = y.copy(); + + }); + + renderWatch.renderEnd('discreteBar immediate'); + return chart; + } + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + forceY: {get: function(){return forceY;}, set: function(_){forceY=_;}}, + showValues: {get: function(){return showValues;}, set: function(_){showValues=_;}}, + x: {get: function(){return getX;}, set: function(_){getX=_;}}, + y: {get: function(){return getY;}, set: function(_){getY=_;}}, + xScale: {get: function(){return x;}, set: function(_){x=_;}}, + yScale: {get: function(){return y;}, set: function(_){y=_;}}, + xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}}, + yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}}, + xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}}, + yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}}, + valueFormat: {get: function(){return valueFormat;}, set: function(_){valueFormat=_;}}, + id: {get: function(){return id;}, set: function(_){id=_;}}, + rectClass: {get: function(){return rectClass;}, set: function(_){rectClass=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration = _; + renderWatch.reset(duration); + }} + }); + + nv.utils.initOptions(chart); + + return chart; +}; + +nv.models.discreteBarChart = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var discretebar = nv.models.discreteBar() + , xAxis = nv.models.axis() + , yAxis = nv.models.axis() + ; + + var margin = {top: 15, right: 10, bottom: 50, left: 60} + , width = null + , height = null + , color = nv.utils.getColor() + , showXAxis = true + , showYAxis = true + , rightAlignYAxis = false + , staggerLabels = false + , tooltips = true + , tooltip = function(key, x, y, e, graph) { + return '

' + x + '

' + + '

' + y + '

' + } + , x + , y + , noData = "No Data Available." + , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'beforeUpdate','renderEnd') + , duration = 250 + ; + + xAxis + .orient('bottom') + .highlightZero(false) + .showMaxMin(false) + .tickFormat(function(d) { return d }) + ; + yAxis + .orient((rightAlignYAxis) ? 'right' : 'left') + .tickFormat(d3.format(',.1f')) + ; + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var showTooltip = function(e, offsetElement) { + var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ), + top = e.pos[1] + ( offsetElement.offsetTop || 0), + x = xAxis.tickFormat()(discretebar.x()(e.point, e.pointIndex)), + y = yAxis.tickFormat()(discretebar.y()(e.point, e.pointIndex)), + content = tooltip(e.series.key, x, y, e, chart); + + nv.tooltip.show([left, top], content, e.value < 0 ? 'n' : 's', null, offsetElement); + }; + + var renderWatch = nv.utils.renderWatch(dispatch, duration); + + function chart(selection) { + renderWatch.reset(); + renderWatch.models(discretebar); + if (showXAxis) renderWatch.models(xAxis); + if (showYAxis) renderWatch.models(yAxis); + + selection.each(function(data) { + var container = d3.select(this), + that = this; + nv.utils.initSVG(container); + var availableWidth = (width || parseInt(container.style('width')) || 960) + - margin.left - margin.right, + availableHeight = (height || parseInt(container.style('height')) || 400) + - margin.top - margin.bottom; + + chart.update = function() { + dispatch.beforeUpdate(); + container.transition().duration(duration).call(chart); + }; + chart.container = this; + + // Display No Data message if there's nothing to show. + if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { + var noDataText = container.selectAll('.nv-noData').data([noData]); + + noDataText.enter().append('text') + .attr('class', 'nvd3 nv-noData') + .attr('dy', '-.7em') + .style('text-anchor', 'middle'); + + noDataText + .attr('x', margin.left + availableWidth / 2) + .attr('y', margin.top + availableHeight / 2) + .text(function(d) { return d }); + + return chart; + } else { + container.selectAll('.nv-noData').remove(); + } + + // Setup Scales + x = discretebar.xScale(); + y = discretebar.yScale().clamp(true); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-discreteBarWithAxes').data([data]); + var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-discreteBarWithAxes').append('g'); + var defsEnter = gEnter.append('defs'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-x nv-axis'); + gEnter.append('g').attr('class', 'nv-y nv-axis') + .append('g').attr('class', 'nv-zeroLine') + .append('line'); + + gEnter.append('g').attr('class', 'nv-barsWrap'); + + g.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + if (rightAlignYAxis) { + g.select(".nv-y.nv-axis") + .attr("transform", "translate(" + availableWidth + ",0)"); + } + + // Main Chart Component(s) + discretebar + .width(availableWidth) + .height(availableHeight); + + var barsWrap = g.select('.nv-barsWrap') + .datum(data.filter(function(d) { return !d.disabled })) + + barsWrap.transition().call(discretebar); + + + defsEnter.append('clipPath') + .attr('id', 'nv-x-label-clip-' + discretebar.id()) + .append('rect'); + + g.select('#nv-x-label-clip-' + discretebar.id() + ' rect') + .attr('width', x.rangeBand() * (staggerLabels ? 2 : 1)) + .attr('height', 16) + .attr('x', -x.rangeBand() / (staggerLabels ? 1 : 2 )); + + // Setup Axes + if (showXAxis) { + xAxis + .scale(x) + .ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + .tickSize(-availableHeight, 0); + + g.select('.nv-x.nv-axis') + .attr('transform', 'translate(0,' + (y.range()[0] + ((discretebar.showValues() && y.domain()[0] < 0) ? 16 : 0)) + ')'); + g.select('.nv-x.nv-axis').call(xAxis); + + var xTicks = g.select('.nv-x.nv-axis').selectAll('g'); + if (staggerLabels) { + xTicks + .selectAll('text') + .attr('transform', function(d,i,j) { return 'translate(0,' + (j % 2 == 0 ? '5' : '17') + ')' }) + } + } + + if (showYAxis) { + yAxis + .scale(y) + .ticks( nv.utils.calcTicksY(availableHeight/36, data) ) + .tickSize( -availableWidth, 0); + + g.select('.nv-y.nv-axis').call(yAxis); + } + + // Zero line + g.select(".nv-zeroLine line") + .attr("x1",0) + .attr("x2",availableWidth) + .attr("y1", y(0)) + .attr("y2", y(0)) + ; + + //============================================================ + // Event Handling/Dispatching (in chart's scope) + //------------------------------------------------------------ + + dispatch.on('tooltipShow', function(e) { + if (tooltips) showTooltip(e, that.parentNode); + }); + + }); + + renderWatch.renderEnd('discreteBar chart immediate'); + return chart; + } + + //============================================================ + // Event Handling/Dispatching (out of chart's scope) + //------------------------------------------------------------ + + discretebar.dispatch.on('elementMouseover.tooltip', function(e) { + e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; + dispatch.tooltipShow(e); + }); + + discretebar.dispatch.on('elementMouseout.tooltip', function(e) { + dispatch.tooltipHide(e); + }); + + dispatch.on('tooltipHide', function() { + if (tooltips) nv.tooltip.cleanup(); + }); + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.discretebar = discretebar; + chart.xAxis = xAxis; + chart.yAxis = yAxis; + + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + staggerLabels: {get: function(){return staggerLabels;}, set: function(_){staggerLabels=_;}}, + showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}}, + showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}}, + tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, + tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, + noData: {get: function(){return noData;}, set: function(_){noData=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration = _; + renderWatch.reset(duration); + discretebar.duration(duration); + xAxis.duration(duration); + yAxis.duration(duration); + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + discretebar.color(color); + }}, + rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){ + rightAlignYAxis = _; + yAxis.orient( (_) ? 'right' : 'left'); + }} + }); + + nv.utils.inheritOptions(chart, discretebar); + nv.utils.initOptions(chart); + + return chart; +} + +nv.models.distribution = function() { + "use strict"; + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 0, right: 0, bottom: 0, left: 0} + , width = 400 //technically width or height depending on x or y.... + , size = 8 + , axis = 'x' // 'x' or 'y'... horizontal or vertical + , getData = function(d) { return d[axis] } // defaults d.x or d.y + , color = nv.utils.defaultColor() + , scale = d3.scale.linear() + , domain + , duration = 250 + , dispatch = d3.dispatch('renderEnd') + ; + + //============================================================ + + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var scale0; + var renderWatch = nv.utils.renderWatch(dispatch, duration); + + //============================================================ + + + function chart(selection) { + renderWatch.reset(); + selection.each(function(data) { + var availableLength = width - (axis === 'x' ? margin.left + margin.right : margin.top + margin.bottom), + naxis = axis == 'x' ? 'y' : 'x', + container = d3.select(this); + nv.utils.initSVG(container); + + //------------------------------------------------------------ + // Setup Scales + + scale0 = scale0 || scale; + + //------------------------------------------------------------ + + + //------------------------------------------------------------ + // Setup containers and skeleton of chart + + var wrap = container.selectAll('g.nv-distribution').data([data]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-distribution'); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g'); + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')') + + //------------------------------------------------------------ + + + var distWrap = g.selectAll('g.nv-dist') + .data(function(d) { return d }, function(d) { return d.key }); + + distWrap.enter().append('g'); + distWrap + .attr('class', function(d,i) { return 'nv-dist nv-series-' + i }) + .style('stroke', function(d,i) { return color(d, i) }); + + var dist = distWrap.selectAll('line.nv-dist' + axis) + .data(function(d) { return d.values }) + dist.enter().append('line') + .attr(axis + '1', function(d,i) { return scale0(getData(d,i)) }) + .attr(axis + '2', function(d,i) { return scale0(getData(d,i)) }) + renderWatch.transition(distWrap.exit().selectAll('line.nv-dist' + axis), 'dist exit') + // .transition() + .attr(axis + '1', function(d,i) { return scale(getData(d,i)) }) + .attr(axis + '2', function(d,i) { return scale(getData(d,i)) }) + .style('stroke-opacity', 0) + .remove(); + dist + .attr('class', function(d,i) { return 'nv-dist' + axis + ' nv-dist' + axis + '-' + i }) + .attr(naxis + '1', 0) + .attr(naxis + '2', size); + renderWatch.transition(dist, 'dist') + // .transition() + .attr(axis + '1', function(d,i) { return scale(getData(d,i)) }) + .attr(axis + '2', function(d,i) { return scale(getData(d,i)) }) + + + scale0 = scale.copy(); + + }); + renderWatch.renderEnd('distribution immediate'); + return chart; + } + + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + chart.options = nv.utils.optionsFunc.bind(chart); + chart.dispatch = dispatch; + + chart.margin = function(_) { + if (!arguments.length) return margin; + margin.top = typeof _.top != 'undefined' ? _.top : margin.top; + margin.right = typeof _.right != 'undefined' ? _.right : margin.right; + margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom; + margin.left = typeof _.left != 'undefined' ? _.left : margin.left; + return chart; + }; + + chart.width = function(_) { + if (!arguments.length) return width; + width = _; + return chart; + }; + + chart.axis = function(_) { + if (!arguments.length) return axis; + axis = _; + return chart; + }; + + chart.size = function(_) { + if (!arguments.length) return size; + size = _; + return chart; + }; + + chart.getData = function(_) { + if (!arguments.length) return getData; + getData = d3.functor(_); + return chart; + }; + + chart.scale = function(_) { + if (!arguments.length) return scale; + scale = _; + return chart; + }; + + chart.color = function(_) { + if (!arguments.length) return color; + color = nv.utils.getColor(_); + return chart; + }; + + chart.duration = function(_) { + if (!arguments.length) return duration; + duration = _; + renderWatch.reset(duration); + return chart; + }; + //============================================================ + + + return chart; +} +//TODO: consider deprecating and using multibar with single series for this +nv.models.historicalBar = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 0, right: 0, bottom: 0, left: 0} + , width = null + , height = null + , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one + , x = d3.scale.linear() + , y = d3.scale.linear() + , getX = function(d) { return d.x } + , getY = function(d) { return d.y } + , forceX = [] + , forceY = [0] + , padData = false + , clipEdge = true + , color = nv.utils.defaultColor() + , xDomain + , yDomain + , xRange + , yRange + , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'renderEnd') + , interactive = true + ; + + var renderWatch = nv.utils.renderWatch(dispatch, 0); + + function chart(selection) { + selection.each(function(data) { + renderWatch.reset(); + + var container = d3.select(this); + var availableWidth = (width || parseInt(container.style('width')) || 960) + - margin.left - margin.right; + var availableHeight = (height || parseInt(container.style('height')) || 400) + - margin.top - margin.bottom; + + nv.utils.initSVG(container); + + // Setup Scales + x.domain(xDomain || d3.extent(data[0].values.map(getX).concat(forceX) )); + + if (padData) + x.range(xRange || [availableWidth * .5 / data[0].values.length, availableWidth * (data[0].values.length - .5) / data[0].values.length ]); + else + x.range(xRange || [0, availableWidth]); + + y.domain(yDomain || d3.extent(data[0].values.map(getY).concat(forceY) )) + .range(yRange || [availableHeight, 0]); + + // If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point + if (x.domain()[0] === x.domain()[1]) + x.domain()[0] ? + x.domain([x.domain()[0] - x.domain()[0] * 0.01, x.domain()[1] + x.domain()[1] * 0.01]) + : x.domain([-1,1]); + + if (y.domain()[0] === y.domain()[1]) + y.domain()[0] ? + y.domain([y.domain()[0] + y.domain()[0] * 0.01, y.domain()[1] - y.domain()[1] * 0.01]) + : y.domain([-1,1]); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-historicalBar-' + id).data([data[0].values]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-historicalBar-' + id); + var defsEnter = wrapEnter.append('defs'); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-bars'); + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + container + .on('click', function(d,i) { + dispatch.chartClick({ + data: d, + index: i, + pos: d3.event, + id: id + }); + }); + + defsEnter.append('clipPath') + .attr('id', 'nv-chart-clip-path-' + id) + .append('rect'); + + wrap.select('#nv-chart-clip-path-' + id + ' rect') + .attr('width', availableWidth) + .attr('height', availableHeight); + + g.attr('clip-path', clipEdge ? 'url(#nv-chart-clip-path-' + id + ')' : ''); + + var bars = wrap.select('.nv-bars').selectAll('.nv-bar') + .data(function(d) { return d }, function(d,i) {return getX(d,i)}); + bars.exit().remove(); + + var barsEnter = bars.enter().append('rect') + .attr('x', 0 ) + .attr('y', function(d,i) { return nv.utils.NaNtoZero(y(Math.max(0, getY(d,i)))) }) + .attr('height', function(d,i) { return nv.utils.NaNtoZero(Math.abs(y(getY(d,i)) - y(0))) }) + .attr('transform', function(d,i) { return 'translate(' + (x(getX(d,i)) - availableWidth / data[0].values.length * .45) + ',0)'; }) + .on('mouseover', function(d,i) { + if (!interactive) return; + d3.select(this).classed('hover', true); + dispatch.elementMouseover({ + point: d, + series: data[0], + pos: [x(getX(d,i)), y(getY(d,i))], // TODO: Figure out why the value appears to be shifted + pointIndex: i, + seriesIndex: 0, + e: d3.event + }); + + }) + .on('mouseout', function(d,i) { + if (!interactive) return; + d3.select(this).classed('hover', false); + dispatch.elementMouseout({ + point: d, + series: data[0], + pointIndex: i, + seriesIndex: 0, + e: d3.event + }); + }) + .on('click', function(d,i) { + if (!interactive) return; + dispatch.elementClick({ + //label: d[label], + value: getY(d,i), + data: d, + index: i, + pos: [x(getX(d,i)), y(getY(d,i))], + e: d3.event, + id: id + }); + d3.event.stopPropagation(); + }) + .on('dblclick', function(d,i) { + if (!interactive) return; + dispatch.elementDblClick({ + //label: d[label], + value: getY(d,i), + data: d, + index: i, + pos: [x(getX(d,i)), y(getY(d,i))], + e: d3.event, + id: id + }); + d3.event.stopPropagation(); + }); + + bars + .attr('fill', function(d,i) { return color(d, i); }) + .attr('class', function(d,i,j) { return (getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive') + ' nv-bar-' + j + '-' + i }) + .watchTransition(renderWatch, 'bars') + .attr('transform', function(d,i) { return 'translate(' + (x(getX(d,i)) - availableWidth / data[0].values.length * .45) + ',0)'; }) + //TODO: better width calculations that don't assume always uniform data spacing;w + .attr('width', (availableWidth / data[0].values.length) * .9 ); + + bars.watchTransition(renderWatch, 'bars') + .attr('y', function(d,i) { + var rval = getY(d,i) < 0 ? + y(0) : + y(0) - y(getY(d,i)) < 1 ? + y(0) - 1 : + y(getY(d,i)); + return nv.utils.NaNtoZero(rval); + }) + .attr('height', function(d,i) { return nv.utils.NaNtoZero(Math.max(Math.abs(y(getY(d,i)) - y(0)),1)) }); + + }); + + renderWatch.renderEnd('historicalBar immediate'); + return chart; + } + + //Create methods to allow outside functions to highlight a specific bar. + chart.highlightPoint = function(pointIndex, isHoverOver) { + d3.select(".nv-historicalBar-" + id) + .select(".nv-bars .nv-bar-0-" + pointIndex) + .classed("hover", isHoverOver) + ; + }; + + chart.clearHighlights = function() { + d3.select(".nv-historicalBar-" + id) + .select(".nv-bars .nv-bar.hover") + .classed("hover", false) + ; + }; + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + forceX: {get: function(){return forceX;}, set: function(_){forceX=_;}}, + forceY: {get: function(){return forceY;}, set: function(_){forceY=_;}}, + padData: {get: function(){return padData;}, set: function(_){padData=_;}}, + x: {get: function(){return getX;}, set: function(_){getX=_;}}, + y: {get: function(){return getY;}, set: function(_){getY=_;}}, + xScale: {get: function(){return x;}, set: function(_){x=_;}}, + yScale: {get: function(){return y;}, set: function(_){y=_;}}, + xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}}, + yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}}, + xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}}, + yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}}, + clipEdge: {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}}, + id: {get: function(){return id;}, set: function(_){id=_;}}, + interactive: {get: function(){return interactive;}, set: function(_){interactive=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + }} + }); + + nv.utils.initOptions(chart); + + return chart; +}; + +nv.models.historicalBarChart = function(bar_model) { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var bars = bar_model || nv.models.historicalBar() + , xAxis = nv.models.axis() + , yAxis = nv.models.axis() + , legend = nv.models.legend() + , interactiveLayer = nv.interactiveGuideline() + ; + + + var margin = {top: 30, right: 90, bottom: 50, left: 90} + , color = nv.utils.defaultColor() + , width = null + , height = null + , showLegend = false + , showXAxis = true + , showYAxis = true + , rightAlignYAxis = false + , useInteractiveGuideline = false + , tooltips = true + , tooltip = function(key, x, y, e, graph) { + return '

' + key + '

' + + '

' + y + ' at ' + x + '

' + } + , x + , y + , state = {} + , defaultState = null + , noData = 'No Data Available.' + , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState', 'renderEnd') + , transitionDuration = 250 + ; + + xAxis + .orient('bottom') + .tickPadding(7) + ; + yAxis + .orient( (rightAlignYAxis) ? 'right' : 'left') + ; + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var showTooltip = function(e, offsetElement) { + + // New addition to calculate position if SVG is scaled with viewBox, may move TODO: consider implementing everywhere else + if (offsetElement) { + var svg = d3.select(offsetElement).select('svg'); + var viewBox = (svg.node()) ? svg.attr('viewBox') : null; + if (viewBox) { + viewBox = viewBox.split(' '); + var ratio = parseInt(svg.style('width')) / viewBox[2]; + e.pos[0] = e.pos[0] * ratio; + e.pos[1] = e.pos[1] * ratio; + } + } + + var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ), + top = e.pos[1] + ( offsetElement.offsetTop || 0), + x = xAxis.tickFormat()(bars.x()(e.point, e.pointIndex)), + y = yAxis.tickFormat()(bars.y()(e.point, e.pointIndex)), + content = tooltip(e.series.key, x, y, e, chart); + + nv.tooltip.show([left, top], content, null, null, offsetElement); + }; + var renderWatch = nv.utils.renderWatch(dispatch, 0); + + function chart(selection) { + selection.each(function(data) { + renderWatch.reset(); + renderWatch.models(bars); + if (showXAxis) renderWatch.models(xAxis); + if (showYAxis) renderWatch.models(yAxis); + + var container = d3.select(this), + that = this; + nv.utils.initSVG(container); + var availableWidth = (width || parseInt(container.style('width')) || 960) + - margin.left - margin.right, + availableHeight = (height || parseInt(container.style('height')) || 400) + - margin.top - margin.bottom; + + + chart.update = function() { container.transition().duration(transitionDuration).call(chart) }; + chart.container = this; + + //set state.disabled + state.disabled = data.map(function(d) { return !!d.disabled }); + + if (!defaultState) { + var key; + defaultState = {}; + for (key in state) { + if (state[key] instanceof Array) + defaultState[key] = state[key].slice(0); + else + defaultState[key] = state[key]; + } + } + + // Display noData message if there's nothing to show. + if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { + var noDataText = container.selectAll('.nv-noData').data([noData]); + + noDataText.enter().append('text') + .attr('class', 'nvd3 nv-noData') + .attr('dy', '-.7em') + .style('text-anchor', 'middle'); + + noDataText + .attr('x', margin.left + availableWidth / 2) + .attr('y', margin.top + availableHeight / 2) + .text(function(d) { return d }); + + return chart; + } else { + container.selectAll('.nv-noData').remove(); + } + + // Setup Scales + x = bars.xScale(); + y = bars.yScale(); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-historicalBarChart').data([data]); + var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-historicalBarChart').append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-x nv-axis'); + gEnter.append('g').attr('class', 'nv-y nv-axis'); + gEnter.append('g').attr('class', 'nv-barsWrap'); + gEnter.append('g').attr('class', 'nv-legendWrap'); + gEnter.append('g').attr('class', 'nv-interactive'); + + // Legend + if (showLegend) { + legend.width(availableWidth); + + g.select('.nv-legendWrap') + .datum(data) + .call(legend); + + if ( margin.top != legend.height()) { + margin.top = legend.height(); + availableHeight = (height || parseInt(container.style('height')) || 400) + - margin.top - margin.bottom; + } + + wrap.select('.nv-legendWrap') + .attr('transform', 'translate(0,' + (-margin.top) +')') + } + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + if (rightAlignYAxis) { + g.select(".nv-y.nv-axis") + .attr("transform", "translate(" + availableWidth + ",0)"); + } + + //Set up interactive layer + if (useInteractiveGuideline) { + interactiveLayer + .width(availableWidth) + .height(availableHeight) + .margin({left:margin.left, top:margin.top}) + .svgContainer(container) + .xScale(x); + wrap.select(".nv-interactive").call(interactiveLayer); + } + bars + .width(availableWidth) + .height(availableHeight) + .color(data.map(function(d,i) { + return d.color || color(d, i); + }).filter(function(d,i) { return !data[i].disabled })); + + var barsWrap = g.select('.nv-barsWrap') + .datum(data.filter(function(d) { return !d.disabled })); + barsWrap.transition().call(bars); + + // Setup Axes + if (showXAxis) { + xAxis + .scale(x) + .tickSize(-availableHeight, 0); + + g.select('.nv-x.nv-axis') + .attr('transform', 'translate(0,' + y.range()[0] + ')'); + g.select('.nv-x.nv-axis') + .transition() + .call(xAxis); + } + + if (showYAxis) { + yAxis + .scale(y) + .ticks( nv.utils.calcTicksY(availableHeight/36, data) ) + .tickSize( -availableWidth, 0); + + g.select('.nv-y.nv-axis') + .transition() + .call(yAxis); + } + + //============================================================ + // Event Handling/Dispatching (in chart's scope) + //------------------------------------------------------------ + + interactiveLayer.dispatch.on('elementMousemove', function(e) { + bars.clearHighlights(); + + var singlePoint, pointIndex, pointXLocation, allData = []; + data + .filter(function(series, i) { + series.seriesIndex = i; + return !series.disabled; + }) + .forEach(function(series,i) { + pointIndex = nv.interactiveBisect(series.values, e.pointXValue, chart.x()); + bars.highlightPoint(pointIndex,true); + var point = series.values[pointIndex]; + if (typeof point === 'undefined') return; + if (typeof singlePoint === 'undefined') singlePoint = point; + if (typeof pointXLocation === 'undefined') pointXLocation = chart.xScale()(chart.x()(point,pointIndex)); + allData.push({ + key: series.key, + value: chart.y()(point, pointIndex), + color: color(series,series.seriesIndex), + data: series.values[pointIndex] + }); + }); + + var xValue = xAxis.tickFormat()(chart.x()(singlePoint,pointIndex)); + interactiveLayer.tooltip + .position({left: pointXLocation + margin.left, top: e.mouseY + margin.top}) + .chartContainer(that.parentNode) + .enabled(tooltips) + .valueFormatter(function(d,i) { + return yAxis.tickFormat()(d); + }) + .data( + { + value: xValue, + series: allData + } + )(); + + interactiveLayer.renderGuideLine(pointXLocation); + + }); + + interactiveLayer.dispatch.on("elementMouseout",function(e) { + dispatch.tooltipHide(); + bars.clearHighlights(); + }); + + legend.dispatch.on('legendClick', function(d,i) { + d.disabled = !d.disabled; + + if (!data.filter(function(d) { return !d.disabled }).length) { + data.map(function(d) { + d.disabled = false; + wrap.selectAll('.nv-series').classed('disabled', false); + return d; + }); + } + + state.disabled = data.map(function(d) { return !!d.disabled }); + dispatch.stateChange(state); + + selection.transition().call(chart); + }); + + legend.dispatch.on('legendDblclick', function(d) { + //Double clicking should always enable current series, and disabled all others. + data.forEach(function(d) { + d.disabled = true; + }); + d.disabled = false; + + state.disabled = data.map(function(d) { return !!d.disabled }); + dispatch.stateChange(state); + chart.update(); + }); + + dispatch.on('tooltipShow', function(e) { + if (tooltips) showTooltip(e, that.parentNode); + }); + + dispatch.on('changeState', function(e) { + + if (typeof e.disabled !== 'undefined') { + data.forEach(function(series,i) { + series.disabled = e.disabled[i]; + }); + + state.disabled = e.disabled; + } + + chart.update(); + }); + }); + + renderWatch.renderEnd('historicalBarChart immediate'); + return chart; + } + + //============================================================ + // Event Handling/Dispatching (out of chart's scope) + //------------------------------------------------------------ + + bars.dispatch.on('elementMouseover.tooltip', function(e) { + e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; + dispatch.tooltipShow(e); + }); + + bars.dispatch.on('elementMouseout.tooltip', function(e) { + dispatch.tooltipHide(e); + }); + + dispatch.on('tooltipHide', function() { + if (tooltips) nv.tooltip.cleanup(); + }); + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + // expose chart's sub-components + chart.dispatch = dispatch; + chart.bars = bars; + chart.legend = legend; + chart.xAxis = xAxis; + chart.yAxis = yAxis; + chart.interactiveLayer = interactiveLayer; + + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, + showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}}, + showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}}, + tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, + tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, + defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, + noData: {get: function(){return noData;}, set: function(_){noData=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + legend.color(color); + bars.color(color); + }}, + duration: {get: function(){return transitionDuration;}, set: function(_){ + transitionDuration=_; + renderWatch.reset(transitionDuration); + yAxis.duration(transitionDuration); + xAxis.duration(transitionDuration); + }}, + rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){ + rightAlignYAxis = _; + yAxis.orient( (_) ? 'right' : 'left'); + }}, + useInteractiveGuideline: {get: function(){return useInteractiveGuideline;}, set: function(_){ + useInteractiveGuideline = _; + if (_ === true) { + chart.interactive(false); + } + }} + }); + + nv.utils.inheritOptions(chart, bars); + nv.utils.initOptions(chart); + + return chart; +}; + + +// ohlcChart is just a historical chart with oclc bars and some tweaks +nv.models.ohlcBarChart = function() { + var chart = nv.models.historicalBarChart(nv.models.ohlcBar()); + + // special default tooltip since we show multiple values per x + chart.useInteractiveGuideline(true); + chart.interactiveLayer.tooltip.contentGenerator(function(data) { + // we assume only one series exists for this chart + var d = data.series[0].data; + // match line colors as defined in nv.d3.css + var color = d.open < d.close ? "2ca02c" : "d62728"; + return '' + + '

' + data.value + '

' + + '' + + '' + + '' + + '' + + '' + + '
open:' + chart.yAxis.tickFormat()(d.open) + '
close:' + chart.yAxis.tickFormat()(d.close) + '
high' + chart.yAxis.tickFormat()(d.high) + '
low:' + chart.yAxis.tickFormat()(d.low) + '
'; + }); + return chart; +};nv.models.legend = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 5, right: 0, bottom: 5, left: 0} + , width = 400 + , height = 20 + , getKey = function(d) { return d.key } + , color = nv.utils.defaultColor() + , align = true + , rightAlign = true + , updateState = true //If true, legend will update data.disabled and trigger a 'stateChange' dispatch. + , radioButtonMode = false //If true, clicking legend items will cause it to behave like a radio button. (only one can be selected at a time) + , dispatch = d3.dispatch('legendClick', 'legendDblclick', 'legendMouseover', 'legendMouseout', 'stateChange') + ; + + function chart(selection) { + selection.each(function(data) { + var availableWidth = width - margin.left - margin.right, + container = d3.select(this); + nv.utils.initSVG(container); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-legend').data([data]); + var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-legend').append('g'); + var g = wrap.select('g'); + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + var series = g.selectAll('.nv-series') + .data(function(d) { return d }); + var seriesEnter = series.enter().append('g').attr('class', 'nv-series') + .on('mouseover', function(d,i) { + dispatch.legendMouseover(d,i); //TODO: Make consistent with other event objects + }) + .on('mouseout', function(d,i) { + dispatch.legendMouseout(d,i); + }) + .on('click', function(d,i) { + dispatch.legendClick(d,i); + if (updateState) { + if (radioButtonMode) { + //Radio button mode: set every series to disabled, + // and enable the clicked series. + data.forEach(function(series) { series.disabled = true}); + d.disabled = false; + } + else { + d.disabled = !d.disabled; + if (data.every(function(series) { return series.disabled})) { + //the default behavior of NVD3 legends is, if every single series + // is disabled, turn all series' back on. + data.forEach(function(series) { series.disabled = false}); + } + } + dispatch.stateChange({ + disabled: data.map(function(d) { return !!d.disabled }) + }); + } + }) + .on('dblclick', function(d,i) { + dispatch.legendDblclick(d,i); + if (updateState) { + //the default behavior of NVD3 legends, when double clicking one, + // is to set all other series' to false, and make the double clicked series enabled. + data.forEach(function(series) { + series.disabled = true; + }); + d.disabled = false; + dispatch.stateChange({ + disabled: data.map(function(d) { return !!d.disabled }) + }); + } + }); + seriesEnter.append('circle') + .style('stroke-width', 2) + .attr('class','nv-legend-symbol') + .attr('r', 5); + seriesEnter.append('text') + .attr('text-anchor', 'start') + .attr('class','nv-legend-text') + .attr('dy', '.32em') + .attr('dx', '8'); + series.classed('nv-disabled', function(d) { return d.disabled }); + series.exit().remove(); + series.select('circle') + .style('fill', function(d,i) { return d.color || color(d,i)}) + .style('stroke', function(d,i) { return d.color || color(d, i) }); + series.select('text').text(getKey); + + //TODO: implement fixed-width and max-width options (max-width is especially useful with the align option) + // NEW ALIGNING CODE, TODO: clean up + if (align) { + + var seriesWidths = []; + series.each(function(d,i) { + var legendText = d3.select(this).select('text'); + var nodeTextLength; + try { + nodeTextLength = legendText.node().getComputedTextLength(); + // If the legendText is display:none'd (nodeTextLength == 0), simulate an error so we approximate, instead + if(nodeTextLength <= 0) throw Error(); + } + catch(e) { + nodeTextLength = nv.utils.calcApproxTextWidth(legendText); + } + + seriesWidths.push(nodeTextLength + 28); // 28 is ~ the width of the circle plus some padding + }); + + var seriesPerRow = 0; + var legendWidth = 0; + var columnWidths = []; + + while ( legendWidth < availableWidth && seriesPerRow < seriesWidths.length) { + columnWidths[seriesPerRow] = seriesWidths[seriesPerRow]; + legendWidth += seriesWidths[seriesPerRow++]; + } + if (seriesPerRow === 0) seriesPerRow = 1; //minimum of one series per row + + while ( legendWidth > availableWidth && seriesPerRow > 1 ) { + columnWidths = []; + seriesPerRow--; + + for (var k = 0; k < seriesWidths.length; k++) { + if (seriesWidths[k] > (columnWidths[k % seriesPerRow] || 0) ) + columnWidths[k % seriesPerRow] = seriesWidths[k]; + } + + legendWidth = columnWidths.reduce(function(prev, cur, index, array) { + return prev + cur; + }); + } + + var xPositions = []; + for (var i = 0, curX = 0; i < seriesPerRow; i++) { + xPositions[i] = curX; + curX += columnWidths[i]; + } + + series + .attr('transform', function(d, i) { + return 'translate(' + xPositions[i % seriesPerRow] + ',' + (5 + Math.floor(i / seriesPerRow) * 20) + ')'; + }); + + //position legend as far right as possible within the total width + if (rightAlign) { + g.attr('transform', 'translate(' + (width - margin.right - legendWidth) + ',' + margin.top + ')'); + } + else { + g.attr('transform', 'translate(0' + ',' + margin.top + ')'); + } + + height = margin.top + margin.bottom + (Math.ceil(seriesWidths.length / seriesPerRow) * 20); + + } else { + + var ypos = 5, + newxpos = 5, + maxwidth = 0, + xpos; + series + .attr('transform', function(d, i) { + var length = d3.select(this).select('text').node().getComputedTextLength() + 28; + xpos = newxpos; + + if (width < margin.left + margin.right + xpos + length) { + newxpos = xpos = 5; + ypos += 20; + } + + newxpos += length; + if (newxpos > maxwidth) maxwidth = newxpos; + + return 'translate(' + xpos + ',' + ypos + ')'; + }); + + //position legend as far right as possible within the total width + g.attr('transform', 'translate(' + (width - margin.right - maxwidth) + ',' + margin.top + ')'); + + height = margin.top + margin.bottom + ypos + 15; + } + }); + + return chart; + } + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + key: {get: function(){return getKey;}, set: function(_){getKey=_;}}, + align: {get: function(){return align;}, set: function(_){align=_;}}, + rightAlign: {get: function(){return rightAlign;}, set: function(_){rightAlign=_;}}, + updateState: {get: function(){return updateState;}, set: function(_){updateState=_;}}, + radioButtonMode: {get: function(){return radioButtonMode;}, set: function(_){radioButtonMode=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + }} + }); + + nv.utils.initOptions(chart); + + return chart; +}; + +nv.models.line = function() { + "use strict"; + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var scatter = nv.models.scatter() + ; + + var margin = {top: 0, right: 0, bottom: 0, left: 0} + , width = 960 + , height = 500 + , color = nv.utils.defaultColor() // a function that returns a color + , getX = function(d) { return d.x } // accessor to get the x value from a data point + , getY = function(d) { return d.y } // accessor to get the y value from a data point + , defined = function(d,i) { return !isNaN(getY(d,i)) && getY(d,i) !== null } // allows a line to be not continuous when it is not defined + , isArea = function(d) { return d.area } // decides if a line is an area or just a line + , clipEdge = false // if true, masks lines within x and y scale + , x //can be accessed via chart.xScale() + , y //can be accessed via chart.yScale() + , interpolate = "linear" // controls the line interpolation + , duration = 250 + , dispatch = d3.dispatch('elementClick', 'elementMouseover', 'elementMouseout', 'renderEnd') + ; + + scatter + .pointSize(16) // default size + .pointDomain([16,256]) //set to speed up calculation, needs to be unset if there is a custom size accessor + ; + + //============================================================ + + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var x0, y0 //used to store previous scales + , renderWatch = nv.utils.renderWatch(dispatch, duration) + ; + + //============================================================ + + + function chart(selection) { + renderWatch.reset(); + renderWatch.models(scatter); + selection.each(function(data) { + var availableWidth = width - margin.left - margin.right, + availableHeight = height - margin.top - margin.bottom, + container = d3.select(this); + nv.utils.initSVG(container); + + // Setup Scales + x = scatter.xScale(); + y = scatter.yScale(); + + x0 = x0 || x; + y0 = y0 || y; + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-line').data([data]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-line'); + var defsEnter = wrapEnter.append('defs'); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-groups'); + gEnter.append('g').attr('class', 'nv-scatterWrap'); + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + scatter + .width(availableWidth) + .height(availableHeight); + + var scatterWrap = wrap.select('.nv-scatterWrap'); + scatterWrap.call(scatter); + + defsEnter.append('clipPath') + .attr('id', 'nv-edge-clip-' + scatter.id()) + .append('rect'); + + wrap.select('#nv-edge-clip-' + scatter.id() + ' rect') + .attr('width', availableWidth) + .attr('height', (availableHeight > 0) ? availableHeight : 0); + + g .attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + scatter.id() + ')' : ''); + scatterWrap + .attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + scatter.id() + ')' : ''); + + var groups = wrap.select('.nv-groups').selectAll('.nv-group') + .data(function(d) { return d }, function(d) { return d.key }); + groups.enter().append('g') + .style('stroke-opacity', 1e-6) + .style('fill-opacity', 1e-6); + + groups.exit().remove(); + + groups + .attr('class', function(d,i) { return 'nv-group nv-series-' + i }) + .classed('hover', function(d) { return d.hover }) + .style('fill', function(d,i){ return color(d, i) }) + .style('stroke', function(d,i){ return color(d, i)}); + groups.watchTransition(renderWatch, 'line: groups') + .style('stroke-opacity', 1) + .style('fill-opacity', .5); + + var areaPaths = groups.selectAll('path.nv-area') + .data(function(d) { return isArea(d) ? [d] : [] }); // this is done differently than lines because I need to check if series is an area + areaPaths.enter().append('path') + .attr('class', 'nv-area') + .attr('d', function(d) { + return d3.svg.area() + .interpolate(interpolate) + .defined(defined) + .x(function(d,i) { return nv.utils.NaNtoZero(x0(getX(d,i))) }) + .y0(function(d,i) { return nv.utils.NaNtoZero(y0(getY(d,i))) }) + .y1(function(d,i) { return y0( y.domain()[0] <= 0 ? y.domain()[1] >= 0 ? 0 : y.domain()[1] : y.domain()[0] ) }) + //.y1(function(d,i) { return y0(0) }) //assuming 0 is within y domain.. may need to tweak this + .apply(this, [d.values]) + }); + groups.exit().selectAll('path.nv-area') + .remove(); + + areaPaths.watchTransition(renderWatch, 'line: areaPaths') + .attr('d', function(d) { + return d3.svg.area() + .interpolate(interpolate) + .defined(defined) + .x(function(d,i) { return nv.utils.NaNtoZero(x(getX(d,i))) }) + .y0(function(d,i) { return nv.utils.NaNtoZero(y(getY(d,i))) }) + .y1(function(d,i) { return y( y.domain()[0] <= 0 ? y.domain()[1] >= 0 ? 0 : y.domain()[1] : y.domain()[0] ) }) + //.y1(function(d,i) { return y0(0) }) //assuming 0 is within y domain.. may need to tweak this + .apply(this, [d.values]) + }); + + var linePaths = groups.selectAll('path.nv-line') + .data(function(d) { return [d.values] }); + linePaths.enter().append('path') + .attr('class', 'nv-line') + .attr('d', + d3.svg.line() + .interpolate(interpolate) + .defined(defined) + .x(function(d,i) { return nv.utils.NaNtoZero(x0(getX(d,i))) }) + .y(function(d,i) { return nv.utils.NaNtoZero(y0(getY(d,i))) }) + ); + + linePaths.watchTransition(renderWatch, 'line: linePaths') + .attr('d', + d3.svg.line() + .interpolate(interpolate) + .defined(defined) + .x(function(d,i) { return nv.utils.NaNtoZero(x(getX(d,i))) }) + .y(function(d,i) { return nv.utils.NaNtoZero(y(getY(d,i))) }) + ); + + //store old scales for use in transitions on update + x0 = x.copy(); + y0 = y.copy(); + }); + renderWatch.renderEnd('line immediate'); + return chart; + } + + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.scatter = scatter; + // Pass through events + scatter.dispatch.on('elementClick', function(){ dispatch.elementClick.apply(this, arguments); }) + scatter.dispatch.on('elementMouseover', function(){ dispatch.elementMouseover.apply(this, arguments); }) + scatter.dispatch.on('elementMouseout', function(){ dispatch.elementMouseout.apply(this, arguments); }) + + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + defined: {get: function(){return defined;}, set: function(_){defined=_;}}, + interpolate: {get: function(){return interpolate;}, set: function(_){interpolate=_;}}, + clipEdge: {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration = _; + renderWatch.reset(duration); + scatter.duration(duration); + }}, + isArea: {get: function(){return isArea;}, set: function(_){ + isArea = d3.functor(_); + }}, + x: {get: function(){return getX;}, set: function(_){ + getX = _; + scatter.x(_); + }}, + y: {get: function(){return getY;}, set: function(_){ + getY = _; + scatter.y(_); + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + scatter.color(color); + }} + }); + + nv.utils.inheritOptions(chart, scatter); + nv.utils.initOptions(chart); + + return chart; +}; +nv.models.lineChart = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var lines = nv.models.line() + , xAxis = nv.models.axis() + , yAxis = nv.models.axis() + , legend = nv.models.legend() + , interactiveLayer = nv.interactiveGuideline() + ; + + var margin = {top: 30, right: 20, bottom: 50, left: 60} + , color = nv.utils.defaultColor() + , width = null + , height = null + , showLegend = true + , showXAxis = true + , showYAxis = true + , rightAlignYAxis = false + , useInteractiveGuideline = false + , tooltips = true + , tooltip = function(key, x, y, e, graph) { + return '

' + key + '

' + + '

' + y + ' at ' + x + '

' + } + , x + , y + , state = nv.utils.state() + , defaultState = null + , noData = 'No Data Available.' + , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState', 'renderEnd') + , duration = 250 + ; + + xAxis + .orient('bottom') + .tickPadding(7) + ; + yAxis + .orient((rightAlignYAxis) ? 'right' : 'left') + ; + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var showTooltip = function(e, offsetElement) { + var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ), + top = e.pos[1] + ( offsetElement.offsetTop || 0), + x = xAxis.tickFormat()(lines.x()(e.point, e.pointIndex)), + y = yAxis.tickFormat()(lines.y()(e.point, e.pointIndex)), + content = tooltip(e.series.key, x, y, e, chart); + + nv.tooltip.show([left, top], content, null, null, offsetElement); + }; + + var renderWatch = nv.utils.renderWatch(dispatch, duration); + + var stateGetter = function(data) { + return function(){ + return { + active: data.map(function(d) { return !d.disabled }) + }; + } + }; + + var stateSetter = function(data) { + return function(state) { + if (state.active !== undefined) + data.forEach(function(series,i) { + series.disabled = !state.active[i]; + }); + } + }; + + function chart(selection) { + renderWatch.reset(); + renderWatch.models(lines); + if (showXAxis) renderWatch.models(xAxis); + if (showYAxis) renderWatch.models(yAxis); + + selection.each(function(data) { + var container = d3.select(this), + that = this; + nv.utils.initSVG(container); + var availableWidth = (width || parseInt(container.style('width')) || 960) + - margin.left - margin.right, + availableHeight = (height || parseInt(container.style('height')) || 400) + - margin.top - margin.bottom; + + + chart.update = function() { + if (duration === 0) + container.call(chart); + else + container.transition().duration(duration).call(chart) + }; + chart.container = this; + + state + .setter(stateSetter(data), chart.update) + .getter(stateGetter(data)) + .update(); + + // DEPRECATED set state.disableddisabled + state.disabled = data.map(function(d) { return !!d.disabled }); + + if (!defaultState) { + var key; + defaultState = {}; + for (key in state) { + if (state[key] instanceof Array) + defaultState[key] = state[key].slice(0); + else + defaultState[key] = state[key]; + } + } + + // Display noData message if there's nothing to show. + if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { + var noDataText = container.selectAll('.nv-noData').data([noData]); + + noDataText.enter().append('text') + .attr('class', 'nvd3 nv-noData') + .attr('dy', '-.7em') + .style('text-anchor', 'middle'); + + noDataText + .attr('x', margin.left + availableWidth / 2) + .attr('y', margin.top + availableHeight / 2) + .text(function(d) { return d }); + + return chart; + } else { + container.selectAll('.nv-noData').remove(); + } + + + // Setup Scales + x = lines.xScale(); + y = lines.yScale(); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-lineChart').data([data]); + var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-lineChart').append('g'); + var g = wrap.select('g'); + + gEnter.append("rect").style("opacity",0); + gEnter.append('g').attr('class', 'nv-x nv-axis'); + gEnter.append('g').attr('class', 'nv-y nv-axis'); + gEnter.append('g').attr('class', 'nv-linesWrap'); + gEnter.append('g').attr('class', 'nv-legendWrap'); + gEnter.append('g').attr('class', 'nv-interactive'); + + g.select("rect") + .attr("width",availableWidth) + .attr("height",(availableHeight > 0) ? availableHeight : 0); + + // Legend + if (showLegend) { + legend.width(availableWidth); + + g.select('.nv-legendWrap') + .datum(data) + .call(legend); + + if ( margin.top != legend.height()) { + margin.top = legend.height(); + availableHeight = (height || parseInt(container.style('height')) || 400) + - margin.top - margin.bottom; + } + + wrap.select('.nv-legendWrap') + .attr('transform', 'translate(0,' + (-margin.top) +')') + } + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + if (rightAlignYAxis) { + g.select(".nv-y.nv-axis") + .attr("transform", "translate(" + availableWidth + ",0)"); + } + + //Set up interactive layer + if (useInteractiveGuideline) { + interactiveLayer + .width(availableWidth) + .height(availableHeight) + .margin({left:margin.left, top:margin.top}) + .svgContainer(container) + .xScale(x); + wrap.select(".nv-interactive").call(interactiveLayer); + } + + lines + .width(availableWidth) + .height(availableHeight) + .color(data.map(function(d,i) { + return d.color || color(d, i); + }).filter(function(d,i) { return !data[i].disabled })); + + + var linesWrap = g.select('.nv-linesWrap') + .datum(data.filter(function(d) { return !d.disabled })); + + linesWrap.call(lines); + + // Setup Axes + if (showXAxis) { + xAxis + .scale(x) + .ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + .tickSize(-availableHeight, 0); + + g.select('.nv-x.nv-axis') + .attr('transform', 'translate(0,' + y.range()[0] + ')'); + g.select('.nv-x.nv-axis') + .call(xAxis); + } + + if (showYAxis) { + yAxis + .scale(y) + .ticks( nv.utils.calcTicksY(availableHeight/36, data) ) + .tickSize( -availableWidth, 0); + + g.select('.nv-y.nv-axis') + .call(yAxis); + } + + //============================================================ + // Event Handling/Dispatching (in chart's scope) + //------------------------------------------------------------ + + legend.dispatch.on('stateChange', function(newState) { + for (var key in newState) + state[key] = newState[key]; + dispatch.stateChange(state); + chart.update(); + }); + + interactiveLayer.dispatch.on('elementMousemove', function(e) { + lines.clearHighlights(); + var singlePoint, pointIndex, pointXLocation, allData = []; + data + .filter(function(series, i) { + series.seriesIndex = i; + return !series.disabled; + }) + .forEach(function(series,i) { + pointIndex = nv.interactiveBisect(series.values, e.pointXValue, chart.x()); + lines.highlightPoint(i, pointIndex, true); + var point = series.values[pointIndex]; + if (typeof point === 'undefined') return; + if (typeof singlePoint === 'undefined') singlePoint = point; + if (typeof pointXLocation === 'undefined') pointXLocation = chart.xScale()(chart.x()(point,pointIndex)); + allData.push({ + key: series.key, + value: chart.y()(point, pointIndex), + color: color(series,series.seriesIndex) + }); + }); + //Highlight the tooltip entry based on which point the mouse is closest to. + if (allData.length > 2) { + var yValue = chart.yScale().invert(e.mouseY); + var domainExtent = Math.abs(chart.yScale().domain()[0] - chart.yScale().domain()[1]); + var threshold = 0.03 * domainExtent; + var indexToHighlight = nv.nearestValueIndex(allData.map(function(d){return d.value}),yValue,threshold); + if (indexToHighlight !== null) + allData[indexToHighlight].highlight = true; + } + + var xValue = xAxis.tickFormat()(chart.x()(singlePoint,pointIndex)); + interactiveLayer.tooltip + .position({left: pointXLocation + margin.left, top: e.mouseY + margin.top}) + .chartContainer(that.parentNode) + .enabled(tooltips) + .valueFormatter(function(d,i) { + return yAxis.tickFormat()(d); + }) + .data( + { + value: xValue, + series: allData + } + )(); + + interactiveLayer.renderGuideLine(pointXLocation); + + }); + + interactiveLayer.dispatch.on('elementClick', function(e) { + var pointXLocation, allData = []; + + data.filter(function(series, i) { + series.seriesIndex = i; + return !series.disabled; + }).forEach(function(series) { + var pointIndex = nv.interactiveBisect(series.values, e.pointXValue, chart.x()); + var point = series.values[pointIndex]; + if (typeof point === 'undefined') return; + if (typeof pointXLocation === 'undefined') pointXLocation = chart.xScale()(chart.x()(point,pointIndex)); + var yPos = chart.yScale()(chart.y()(point,pointIndex)); + allData.push({ + point: point, + pointIndex: pointIndex, + pos: [pointXLocation, yPos], + seriesIndex: series.seriesIndex, + series: series + }); + }); + + lines.dispatch.elementClick(allData); + }); + + interactiveLayer.dispatch.on("elementMouseout",function(e) { + dispatch.tooltipHide(); + lines.clearHighlights(); + }); + + dispatch.on('tooltipShow', function(e) { + if (tooltips) showTooltip(e, that.parentNode); + }); + + dispatch.on('changeState', function(e) { + + if (typeof e.disabled !== 'undefined' && data.length === e.disabled.length) { + data.forEach(function(series,i) { + series.disabled = e.disabled[i]; + }); + + state.disabled = e.disabled; + } + + chart.update(); + }); + + }); + + renderWatch.renderEnd('lineChart immediate'); + return chart; + } + + //============================================================ + // Event Handling/Dispatching (out of chart's scope) + //------------------------------------------------------------ + + lines.dispatch.on('elementMouseover.tooltip', function(e) { + e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; + dispatch.tooltipShow(e); + }); + + lines.dispatch.on('elementMouseout.tooltip', function(e) { + dispatch.tooltipHide(e); + }); + + dispatch.on('tooltipHide', function() { + if (tooltips) nv.tooltip.cleanup(); + }); + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + // expose chart's sub-components + chart.dispatch = dispatch; + chart.lines = lines; + chart.legend = legend; + chart.xAxis = xAxis; + chart.yAxis = yAxis; + chart.interactiveLayer = interactiveLayer; + + chart.dispatch = dispatch; + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, + showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}}, + showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}}, + tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, + tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, + defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, + noData: {get: function(){return noData;}, set: function(_){noData=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration = _; + renderWatch.reset(duration); + lines.duration(duration); + xAxis.duration(duration); + yAxis.duration(duration); + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + legend.color(color); + lines.color(color); + }}, + rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){ + rightAlignYAxis = _; + yAxis.orient( rightAlignYAxis ? 'right' : 'left'); + }}, + useInteractiveGuideline: {get: function(){return useInteractiveGuideline;}, set: function(_){ + useInteractiveGuideline = _; + if (useInteractiveGuideline) { + lines.interactive(false); + lines.useVoronoi(false); + } + }} + }); + + nv.utils.inheritOptions(chart, lines); + nv.utils.initOptions(chart); + + return chart; +}; +nv.models.linePlusBarChart = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var lines = nv.models.line() + , lines2 = nv.models.line() + , bars = nv.models.historicalBar() + , bars2 = nv.models.historicalBar() + , xAxis = nv.models.axis() + , x2Axis = nv.models.axis() + , y1Axis = nv.models.axis() + , y2Axis = nv.models.axis() + , y3Axis = nv.models.axis() + , y4Axis = nv.models.axis() + , legend = nv.models.legend() + , brush = d3.svg.brush() + ; + + var margin = {top: 30, right: 30, bottom: 30, left: 60} + , margin2 = {top: 0, right: 30, bottom: 20, left: 60} + , width = null + , height = null + , getX = function(d) { return d.x } + , getY = function(d) { return d.y } + , color = nv.utils.defaultColor() + , showLegend = true + , focusEnable = true + , focusShowAxisY = false + , focusShowAxisX = true + , focusHeight = 50 + , extent + , brushExtent = null + , tooltips = true + , tooltip = function(key, x, y, e, graph) { + return '

' + key + '

' + + '

' + y + ' at ' + x + '

'; + } + , x + , x2 + , y1 + , y2 + , y3 + , y4 + , noData = "No Data Available." + , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'brush', 'stateChange', 'changeState') + , transitionDuration = 0 + , state = nv.utils.state() + , defaultState = null + , legendLeftAxisHint = ' (left axis)' + , legendRightAxisHint = ' (right axis)' + ; + + lines + .clipEdge(true) + ; + lines2 + .interactive(false) + ; + xAxis + .orient('bottom') + .tickPadding(5) + ; + y1Axis + .orient('left') + ; + y2Axis + .orient('right') + ; + x2Axis + .orient('bottom') + .tickPadding(5) + ; + y3Axis + .orient('left') + ; + y4Axis + .orient('right') + ; + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var showTooltip = function(e, offsetElement) { + if (extent) { + e.pointIndex += Math.ceil(extent[0]); + } + var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ), + top = e.pos[1] + ( offsetElement.offsetTop || 0), + x = xAxis.tickFormat()(lines.x()(e.point, e.pointIndex)), + y = (e.series.bar ? y1Axis : y2Axis).tickFormat()(lines.y()(e.point, e.pointIndex)), + content = tooltip(e.series.key, x, y, e, chart); + + nv.tooltip.show([left, top], content, e.value < 0 ? 'n' : 's', null, offsetElement); + }; + + var stateGetter = function(data) { + return function(){ + return { + active: data.map(function(d) { return !d.disabled }) + }; + } + }; + + var stateSetter = function(data) { + return function(state) { + if (state.active !== undefined) + data.forEach(function(series,i) { + series.disabled = !state.active[i]; + }); + } + }; + + function chart(selection) { + selection.each(function(data) { + var container = d3.select(this), + that = this; + nv.utils.initSVG(container); + var availableWidth = (width || parseInt(container.style('width')) || 960) + - margin.left - margin.right, + availableHeight1 = (height || parseInt(container.style('height')) || 400) + - margin.top - margin.bottom - (focusEnable ? focusHeight : 0) , + availableHeight2 = focusHeight - margin2.top - margin2.bottom; + + chart.update = function() { container.transition().duration(transitionDuration).call(chart); }; + chart.container = this; + + state + .setter(stateSetter(data), chart.update) + .getter(stateGetter(data)) + .update(); + + // DEPRECATED set state.disableddisabled + state.disabled = data.map(function(d) { return !!d.disabled }); + + if (!defaultState) { + var key; + defaultState = {}; + for (key in state) { + if (state[key] instanceof Array) + defaultState[key] = state[key].slice(0); + else + defaultState[key] = state[key]; + } + } + + // Display No Data message if there's nothing to show. + if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { + var noDataText = container.selectAll('.nv-noData').data([noData]); + + noDataText.enter().append('text') + .attr('class', 'nvd3 nv-noData') + .attr('dy', '-.7em') + .style('text-anchor', 'middle'); + + noDataText + .attr('x', margin.left + availableWidth / 2) + .attr('y', margin.top + availableHeight1 / 2) + .text(function(d) { return d }); + + return chart; + } else { + container.selectAll('.nv-noData').remove(); + } + + // Setup Scales + var dataBars = data.filter(function(d) { return !d.disabled && d.bar }); + var dataLines = data.filter(function(d) { return !d.bar }); // removed the !d.disabled clause here to fix Issue #240 + + x = bars.xScale(); + x2 = x2Axis.scale(); + y1 = bars.yScale(); + y2 = lines.yScale(); + y3 = bars2.yScale(); + y4 = lines2.yScale(); + + var series1 = data + .filter(function(d) { return !d.disabled && d.bar }) + .map(function(d) { + return d.values.map(function(d,i) { + return { x: getX(d,i), y: getY(d,i) } + }) + }); + + var series2 = data + .filter(function(d) { return !d.disabled && !d.bar }) + .map(function(d) { + return d.values.map(function(d,i) { + return { x: getX(d,i), y: getY(d,i) } + }) + }); + + x.range([0, availableWidth]); + + x2 .domain(d3.extent(d3.merge(series1.concat(series2)), function(d) { return d.x } )) + .range([0, availableWidth]); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-linePlusBar').data([data]); + var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-linePlusBar').append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-legendWrap'); + + // this is the main chart + var focusEnter = gEnter.append('g').attr('class', 'nv-focus'); + focusEnter.append('g').attr('class', 'nv-x nv-axis'); + focusEnter.append('g').attr('class', 'nv-y1 nv-axis'); + focusEnter.append('g').attr('class', 'nv-y2 nv-axis'); + focusEnter.append('g').attr('class', 'nv-barsWrap'); + focusEnter.append('g').attr('class', 'nv-linesWrap'); + + // context chart is where you can focus in + var contextEnter = gEnter.append('g').attr('class', 'nv-context'); + contextEnter.append('g').attr('class', 'nv-x nv-axis'); + contextEnter.append('g').attr('class', 'nv-y1 nv-axis'); + contextEnter.append('g').attr('class', 'nv-y2 nv-axis'); + contextEnter.append('g').attr('class', 'nv-barsWrap'); + contextEnter.append('g').attr('class', 'nv-linesWrap'); + contextEnter.append('g').attr('class', 'nv-brushBackground'); + contextEnter.append('g').attr('class', 'nv-x nv-brush'); + + //============================================================ + // Legend + //------------------------------------------------------------ + + if (showLegend) { + legend.width( availableWidth / 2 ); + + g.select('.nv-legendWrap') + .datum(data.map(function(series) { + series.originalKey = series.originalKey === undefined ? series.key : series.originalKey; + series.key = series.originalKey + (series.bar ? legendLeftAxisHint : legendRightAxisHint); + return series; + })) + .call(legend); + + if ( margin.top != legend.height()) { + margin.top = legend.height(); + availableHeight1 = (height || parseInt(container.style('height')) || 400) + - margin.top - margin.bottom - focusHeight; + } + + g.select('.nv-legendWrap') + .attr('transform', 'translate(' + ( availableWidth / 2 ) + ',' + (-margin.top) +')'); + } + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + //============================================================ + // Context chart (focus chart) components + //------------------------------------------------------------ + + // hide or show the focus context chart + g.select('.nv-context').style('display', focusEnable ? 'initial' : 'none'); + + bars2 + .width(availableWidth) + .height(availableHeight2) + .color(data.map(function (d, i) { + return d.color || color(d, i); + }).filter(function (d, i) { + return !data[i].disabled && data[i].bar + })); + lines2 + .width(availableWidth) + .height(availableHeight2) + .color(data.map(function (d, i) { + return d.color || color(d, i); + }).filter(function (d, i) { + return !data[i].disabled && !data[i].bar + })); + + var bars2Wrap = g.select('.nv-context .nv-barsWrap') + .datum(dataBars.length ? dataBars : [ + {values: []} + ]); + var lines2Wrap = g.select('.nv-context .nv-linesWrap') + .datum(!dataLines[0].disabled ? dataLines : [ + {values: []} + ]); + + g.select('.nv-context') + .attr('transform', 'translate(0,' + ( availableHeight1 + margin.bottom + margin2.top) + ')'); + + bars2Wrap.transition().call(bars2); + lines2Wrap.transition().call(lines2); + + // context (focus chart) axis controls + if (focusShowAxisX) { + x2Axis + .ticks(nv.utils.calcTicksX(availableWidth / 100, data)) + .tickSize(-availableHeight2, 0); + g.select('.nv-context .nv-x.nv-axis') + .attr('transform', 'translate(0,' + y3.range()[0] + ')'); + g.select('.nv-context .nv-x.nv-axis').transition() + .call(x2Axis); + } + + if (focusShowAxisY) { + y3Axis + .scale(y3) + .ticks( availableHeight2 / 36 ) + .tickSize( -availableWidth, 0); + y4Axis + .scale(y4) + .ticks( availableHeight2 / 36 ) + .tickSize(dataBars.length ? 0 : -availableWidth, 0); // Show the y2 rules only if y1 has none + + g.select('.nv-context .nv-y3.nv-axis') + .style('opacity', dataBars.length ? 1 : 0) + .attr('transform', 'translate(0,' + x2.range()[0] + ')'); + g.select('.nv-context .nv-y2.nv-axis') + .style('opacity', dataLines.length ? 1 : 0) + .attr('transform', 'translate(' + x2.range()[1] + ',0)'); + + g.select('.nv-context .nv-y1.nv-axis').transition() + .call(y3Axis); + g.select('.nv-context .nv-y2.nv-axis').transition() + .call(y4Axis); + } + + // Setup Brush + brush.x(x2).on('brush', onBrush); + + if (brushExtent) brush.extent(brushExtent); + + var brushBG = g.select('.nv-brushBackground').selectAll('g') + .data([brushExtent || brush.extent()]); + + var brushBGenter = brushBG.enter() + .append('g'); + + brushBGenter.append('rect') + .attr('class', 'left') + .attr('x', 0) + .attr('y', 0) + .attr('height', availableHeight2); + + brushBGenter.append('rect') + .attr('class', 'right') + .attr('x', 0) + .attr('y', 0) + .attr('height', availableHeight2); + + var gBrush = g.select('.nv-x.nv-brush') + .call(brush); + gBrush.selectAll('rect') + //.attr('y', -5) + .attr('height', availableHeight2); + gBrush.selectAll('.resize').append('path').attr('d', resizePath); + + //============================================================ + // Event Handling/Dispatching (in chart's scope) + //------------------------------------------------------------ + + legend.dispatch.on('stateChange', function(newState) { + for (var key in newState) + state[key] = newState[key]; + dispatch.stateChange(state); + chart.update(); + }); + + dispatch.on('tooltipShow', function(e) { + if (tooltips) showTooltip(e, that.parentNode); + }); + + // Update chart from a state object passed to event handler + dispatch.on('changeState', function(e) { + if (typeof e.disabled !== 'undefined') { + data.forEach(function(series,i) { + series.disabled = e.disabled[i]; + }); + state.disabled = e.disabled; + } + chart.update(); + }); + + //============================================================ + // Functions + //------------------------------------------------------------ + + // Taken from crossfilter (http://square.github.com/crossfilter/) + function resizePath(d) { + var e = +(d == 'e'), + x = e ? 1 : -1, + y = availableHeight2 / 3; + return 'M' + (.5 * x) + ',' + y + + 'A6,6 0 0 ' + e + ' ' + (6.5 * x) + ',' + (y + 6) + + 'V' + (2 * y - 6) + + 'A6,6 0 0 ' + e + ' ' + (.5 * x) + ',' + (2 * y) + + 'Z' + + 'M' + (2.5 * x) + ',' + (y + 8) + + 'V' + (2 * y - 8) + + 'M' + (4.5 * x) + ',' + (y + 8) + + 'V' + (2 * y - 8); + } + + + function updateBrushBG() { + if (!brush.empty()) brush.extent(brushExtent); + brushBG + .data([brush.empty() ? x2.domain() : brushExtent]) + .each(function(d,i) { + var leftWidth = x2(d[0]) - x2.range()[0], + rightWidth = x2.range()[1] - x2(d[1]); + d3.select(this).select('.left') + .attr('width', leftWidth < 0 ? 0 : leftWidth); + + d3.select(this).select('.right') + .attr('x', x2(d[1])) + .attr('width', rightWidth < 0 ? 0 : rightWidth); + }); + } + + function onBrush() { + brushExtent = brush.empty() ? null : brush.extent(); + extent = brush.empty() ? x2.domain() : brush.extent(); + dispatch.brush({extent: extent, brush: brush}); + updateBrushBG(); + + // Prepare Main (Focus) Bars and Lines + bars + .width(availableWidth) + .height(availableHeight1) + .color(data.map(function(d,i) { + return d.color || color(d, i); + }).filter(function(d,i) { return !data[i].disabled && data[i].bar })); + + lines + .width(availableWidth) + .height(availableHeight1) + .color(data.map(function(d,i) { + return d.color || color(d, i); + }).filter(function(d,i) { return !data[i].disabled && !data[i].bar })); + + var focusBarsWrap = g.select('.nv-focus .nv-barsWrap') + .datum(!dataBars.length ? [{values:[]}] : + dataBars + .map(function(d,i) { + return { + key: d.key, + values: d.values.filter(function(d,i) { + return bars.x()(d,i) >= extent[0] && bars.x()(d,i) <= extent[1]; + }) + } + }) + ); + + var focusLinesWrap = g.select('.nv-focus .nv-linesWrap') + .datum(dataLines[0].disabled ? [{values:[]}] : + dataLines + .map(function(d,i) { + return { + key: d.key, + values: d.values.filter(function(d,i) { + return lines.x()(d,i) >= extent[0] && lines.x()(d,i) <= extent[1]; + }) + } + }) + ); + + // Update Main (Focus) X Axis + if (dataBars.length) { + x = bars.xScale(); + } else { + x = lines.xScale(); + } + + xAxis + .scale(x) + .ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + .tickSize(-availableHeight1, 0); + + xAxis.domain([Math.ceil(extent[0]), Math.floor(extent[1])]); + + g.select('.nv-x.nv-axis').transition().duration(transitionDuration) + .call(xAxis); + + // Update Main (Focus) Bars and Lines + focusBarsWrap.transition().duration(transitionDuration).call(bars); + focusLinesWrap.transition().duration(transitionDuration).call(lines); + + // Setup and Update Main (Focus) Y Axes + g.select('.nv-focus .nv-x.nv-axis') + .attr('transform', 'translate(0,' + y1.range()[0] + ')'); + + y1Axis + .scale(y1) + .ticks( nv.utils.calcTicksY(availableHeight1/36, data) ) + .tickSize(-availableWidth, 0); + y2Axis + .scale(y2) + .ticks( nv.utils.calcTicksY(availableHeight1/36, data) ) + .tickSize(dataBars.length ? 0 : -availableWidth, 0); // Show the y2 rules only if y1 has none + + g.select('.nv-focus .nv-y1.nv-axis') + .style('opacity', dataBars.length ? 1 : 0); + g.select('.nv-focus .nv-y2.nv-axis') + .style('opacity', dataLines.length && !dataLines[0].disabled ? 1 : 0) + .attr('transform', 'translate(' + x.range()[1] + ',0)'); + + g.select('.nv-focus .nv-y1.nv-axis').transition().duration(transitionDuration) + .call(y1Axis); + g.select('.nv-focus .nv-y2.nv-axis').transition().duration(transitionDuration) + .call(y2Axis); + } + + onBrush(); + + }); + + return chart; + } + + //============================================================ + // Event Handling/Dispatching (out of chart's scope) + //------------------------------------------------------------ + + lines.dispatch.on('elementMouseover.tooltip', function(e) { + e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; + dispatch.tooltipShow(e); + }); + + lines.dispatch.on('elementMouseout.tooltip', function(e) { + dispatch.tooltipHide(e); + }); + + bars.dispatch.on('elementMouseover.tooltip', function(e) { + e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; + dispatch.tooltipShow(e); + }); + + bars.dispatch.on('elementMouseout.tooltip', function(e) { + dispatch.tooltipHide(e); + }); + + dispatch.on('tooltipHide', function() { + if (tooltips) nv.tooltip.cleanup(); + }); + + //============================================================ + + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + // expose chart's sub-components + chart.dispatch = dispatch; + chart.legend = legend; + chart.lines = lines; + chart.lines2 = lines2; + chart.bars = bars; + chart.bars2 = bars2; + chart.xAxis = xAxis; + chart.x2Axis = x2Axis; + chart.y1Axis = y1Axis; + chart.y2Axis = y2Axis; + chart.y3Axis = y3Axis; + chart.y4Axis = y4Axis; + + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, + tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, + tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, + brushExtent: {get: function(){return brushExtent;}, set: function(_){brushExtent=_;}}, + noData: {get: function(){return noData;}, set: function(_){noData=_;}}, + focusEnable: {get: function(){return focusEnable;}, set: function(_){focusEnable=_;}}, + focusHeight: {get: function(){return focusHeight;}, set: function(_){focusHeight=_;}}, + focusShowAxisX: {get: function(){return focusShowAxisX;}, set: function(_){focusShowAxisX=_;}}, + focusShowAxisY: {get: function(){return focusShowAxisY;}, set: function(_){focusShowAxisY=_;}}, + legendLeftAxisHint: {get: function(){return legendLeftAxisHint;}, set: function(_){legendLeftAxisHint=_;}}, + legendRightAxisHint: {get: function(){return legendRightAxisHint;}, set: function(_){legendRightAxisHint=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + duration: {get: function(){return transitionDuration;}, set: function(_){ + transitionDuration = _; + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + legend.color(color); + }}, + x: {get: function(){return getX;}, set: function(_){ + getX = _; + lines.x(_); + lines2.x(_); + bars.x(_); + bars2.x(_); + }}, + y: {get: function(){return getY;}, set: function(_){ + getY = _; + lines.y(_); + lines2.y(_); + bars.y(_); + bars2.y(_); + }} + }); + + nv.utils.inheritOptions(chart, lines); + nv.utils.initOptions(chart); + + return chart; +}; +nv.models.lineWithFocusChart = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var lines = nv.models.line() + , lines2 = nv.models.line() + , xAxis = nv.models.axis() + , yAxis = nv.models.axis() + , x2Axis = nv.models.axis() + , y2Axis = nv.models.axis() + , legend = nv.models.legend() + , brush = d3.svg.brush() + ; + + var margin = {top: 30, right: 30, bottom: 30, left: 60} + , margin2 = {top: 0, right: 30, bottom: 20, left: 60} + , color = nv.utils.defaultColor() + , width = null + , height = null + , height2 = 100 + , x + , y + , x2 + , y2 + , showLegend = true + , brushExtent = null + , tooltips = true + , tooltip = function(key, x, y, e, graph) { + return '

' + key + '

' + + '

' + y + ' at ' + x + '

' + } + , noData = "No Data Available." + , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'brush', 'stateChange', 'changeState') + , transitionDuration = 250 + , state = nv.utils.state() + , defaultState = null + ; + + lines + .clipEdge(true) + ; + lines2 + .interactive(false) + ; + xAxis + .orient('bottom') + .tickPadding(5) + ; + yAxis + .orient('left') + ; + x2Axis + .orient('bottom') + .tickPadding(5) + ; + y2Axis + .orient('left') + ; + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var showTooltip = function(e, offsetElement) { + var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ), + top = e.pos[1] + ( offsetElement.offsetTop || 0), + x = xAxis.tickFormat()(lines.x()(e.point, e.pointIndex)), + y = yAxis.tickFormat()(lines.y()(e.point, e.pointIndex)), + content = tooltip(e.series.key, x, y, e, chart); + + nv.tooltip.show([left, top], content, null, null, offsetElement); + }; + + var stateGetter = function(data) { + return function(){ + return { + active: data.map(function(d) { return !d.disabled }) + }; + } + }; + + var stateSetter = function(data) { + return function(state) { + if (state.active !== undefined) + data.forEach(function(series,i) { + series.disabled = !state.active[i]; + }); + } + }; + + function chart(selection) { + selection.each(function(data) { + var container = d3.select(this), + that = this; + nv.utils.initSVG(container); + var availableWidth = (width || parseInt(container.style('width')) || 960) + - margin.left - margin.right, + availableHeight1 = (height || parseInt(container.style('height')) || 400) + - margin.top - margin.bottom - height2, + availableHeight2 = height2 - margin2.top - margin2.bottom; + + chart.update = function() { container.transition().duration(transitionDuration).call(chart) }; + chart.container = this; + + state + .setter(stateSetter(data), chart.update) + .getter(stateGetter(data)) + .update(); + + // DEPRECATED set state.disableddisabled + state.disabled = data.map(function(d) { return !!d.disabled }); + + if (!defaultState) { + var key; + defaultState = {}; + for (key in state) { + if (state[key] instanceof Array) + defaultState[key] = state[key].slice(0); + else + defaultState[key] = state[key]; + } + } + + // Display No Data message if there's nothing to show. + if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { + var noDataText = container.selectAll('.nv-noData').data([noData]); + + noDataText.enter().append('text') + .attr('class', 'nvd3 nv-noData') + .attr('dy', '-.7em') + .style('text-anchor', 'middle'); + + noDataText + .attr('x', margin.left + availableWidth / 2) + .attr('y', margin.top + availableHeight1 / 2) + .text(function(d) { return d }); + + return chart; + } else { + container.selectAll('.nv-noData').remove(); + } + + // Setup Scales + x = lines.xScale(); + y = lines.yScale(); + x2 = lines2.xScale(); + y2 = lines2.yScale(); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-lineWithFocusChart').data([data]); + var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-lineWithFocusChart').append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-legendWrap'); + + var focusEnter = gEnter.append('g').attr('class', 'nv-focus'); + focusEnter.append('g').attr('class', 'nv-x nv-axis'); + focusEnter.append('g').attr('class', 'nv-y nv-axis'); + focusEnter.append('g').attr('class', 'nv-linesWrap'); + + var contextEnter = gEnter.append('g').attr('class', 'nv-context'); + contextEnter.append('g').attr('class', 'nv-x nv-axis'); + contextEnter.append('g').attr('class', 'nv-y nv-axis'); + contextEnter.append('g').attr('class', 'nv-linesWrap'); + contextEnter.append('g').attr('class', 'nv-brushBackground'); + contextEnter.append('g').attr('class', 'nv-x nv-brush'); + + // Legend + if (showLegend) { + legend.width(availableWidth); + + g.select('.nv-legendWrap') + .datum(data) + .call(legend); + + if ( margin.top != legend.height()) { + margin.top = legend.height(); + availableHeight1 = (height || parseInt(container.style('height')) || 400) + - margin.top - margin.bottom - height2; + } + + g.select('.nv-legendWrap') + .attr('transform', 'translate(0,' + (-margin.top) +')') + } + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + // Main Chart Component(s) + lines + .width(availableWidth) + .height(availableHeight1) + .color( + data + .map(function(d,i) { + return d.color || color(d, i); + }) + .filter(function(d,i) { + return !data[i].disabled; + }) + ); + + lines2 + .defined(lines.defined()) + .width(availableWidth) + .height(availableHeight2) + .color( + data + .map(function(d,i) { + return d.color || color(d, i); + }) + .filter(function(d,i) { + return !data[i].disabled; + }) + ); + + g.select('.nv-context') + .attr('transform', 'translate(0,' + ( availableHeight1 + margin.bottom + margin2.top) + ')') + + var contextLinesWrap = g.select('.nv-context .nv-linesWrap') + .datum(data.filter(function(d) { return !d.disabled })) + + d3.transition(contextLinesWrap).call(lines2); + + // Setup Main (Focus) Axes + xAxis + .scale(x) + .ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + .tickSize(-availableHeight1, 0); + + yAxis + .scale(y) + .ticks( nv.utils.calcTicksY(availableHeight1/36, data) ) + .tickSize( -availableWidth, 0); + + g.select('.nv-focus .nv-x.nv-axis') + .attr('transform', 'translate(0,' + availableHeight1 + ')'); + + // Setup Brush + brush + .x(x2) + .on('brush', function() { + //When brushing, turn off transitions because chart needs to change immediately. + var oldTransition = chart.duration(); + chart.duration(0); + onBrush(); + chart.duration(oldTransition); + }); + + if (brushExtent) brush.extent(brushExtent); + + var brushBG = g.select('.nv-brushBackground').selectAll('g') + .data([brushExtent || brush.extent()]) + + var brushBGenter = brushBG.enter() + .append('g'); + + brushBGenter.append('rect') + .attr('class', 'left') + .attr('x', 0) + .attr('y', 0) + .attr('height', availableHeight2); + + brushBGenter.append('rect') + .attr('class', 'right') + .attr('x', 0) + .attr('y', 0) + .attr('height', availableHeight2); + + var gBrush = g.select('.nv-x.nv-brush') + .call(brush); + gBrush.selectAll('rect') + //.attr('y', -5) + .attr('height', availableHeight2); + gBrush.selectAll('.resize').append('path').attr('d', resizePath); + + onBrush(); + + // Setup Secondary (Context) Axes + x2Axis + .scale(x2) + .ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + .tickSize(-availableHeight2, 0); + + g.select('.nv-context .nv-x.nv-axis') + .attr('transform', 'translate(0,' + y2.range()[0] + ')'); + d3.transition(g.select('.nv-context .nv-x.nv-axis')) + .call(x2Axis); + + y2Axis + .scale(y2) + .ticks( nv.utils.calcTicksY(availableHeight2/36, data) ) + .tickSize( -availableWidth, 0); + + d3.transition(g.select('.nv-context .nv-y.nv-axis')) + .call(y2Axis); + + g.select('.nv-context .nv-x.nv-axis') + .attr('transform', 'translate(0,' + y2.range()[0] + ')'); + + //============================================================ + // Event Handling/Dispatching (in chart's scope) + //------------------------------------------------------------ + + legend.dispatch.on('stateChange', function(newState) { + for (var key in newState) + state[key] = newState[key]; + dispatch.stateChange(state); + chart.update(); + }); + + dispatch.on('tooltipShow', function(e) { + if (tooltips) showTooltip(e, that.parentNode); + }); + + dispatch.on('changeState', function(e) { + if (typeof e.disabled !== 'undefined') { + data.forEach(function(series,i) { + series.disabled = e.disabled[i]; + }); + } + chart.update(); + }); + + //============================================================ + // Functions + //------------------------------------------------------------ + + // Taken from crossfilter (http://square.github.com/crossfilter/) + function resizePath(d) { + var e = +(d == 'e'), + x = e ? 1 : -1, + y = availableHeight2 / 3; + return 'M' + (.5 * x) + ',' + y + + 'A6,6 0 0 ' + e + ' ' + (6.5 * x) + ',' + (y + 6) + + 'V' + (2 * y - 6) + + 'A6,6 0 0 ' + e + ' ' + (.5 * x) + ',' + (2 * y) + + 'Z' + + 'M' + (2.5 * x) + ',' + (y + 8) + + 'V' + (2 * y - 8) + + 'M' + (4.5 * x) + ',' + (y + 8) + + 'V' + (2 * y - 8); + } + + + function updateBrushBG() { + if (!brush.empty()) brush.extent(brushExtent); + brushBG + .data([brush.empty() ? x2.domain() : brushExtent]) + .each(function(d,i) { + var leftWidth = x2(d[0]) - x.range()[0], + rightWidth = x.range()[1] - x2(d[1]); + d3.select(this).select('.left') + .attr('width', leftWidth < 0 ? 0 : leftWidth); + + d3.select(this).select('.right') + .attr('x', x2(d[1])) + .attr('width', rightWidth < 0 ? 0 : rightWidth); + }); + } + + + function onBrush() { + brushExtent = brush.empty() ? null : brush.extent(); + var extent = brush.empty() ? x2.domain() : brush.extent(); + + //The brush extent cannot be less than one. If it is, don't update the line chart. + if (Math.abs(extent[0] - extent[1]) <= 1) { + return; + } + + dispatch.brush({extent: extent, brush: brush}); + + + updateBrushBG(); + + // Update Main (Focus) + var focusLinesWrap = g.select('.nv-focus .nv-linesWrap') + .datum( + data + .filter(function(d) { return !d.disabled }) + .map(function(d,i) { + return { + key: d.key, + area: d.area, + values: d.values.filter(function(d,i) { + return lines.x()(d,i) >= extent[0] && lines.x()(d,i) <= extent[1]; + }) + } + }) + ); + focusLinesWrap.transition().duration(transitionDuration).call(lines); + + + // Update Main (Focus) Axes + g.select('.nv-focus .nv-x.nv-axis').transition().duration(transitionDuration) + .call(xAxis); + g.select('.nv-focus .nv-y.nv-axis').transition().duration(transitionDuration) + .call(yAxis); + } + }); + + return chart; + } + + //============================================================ + // Event Handling/Dispatching (out of chart's scope) + //------------------------------------------------------------ + + lines.dispatch.on('elementMouseover.tooltip', function(e) { + e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; + dispatch.tooltipShow(e); + }); + + lines.dispatch.on('elementMouseout.tooltip', function(e) { + dispatch.tooltipHide(e); + }); + + dispatch.on('tooltipHide', function() { + if (tooltips) nv.tooltip.cleanup(); + }); + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + // expose chart's sub-components + chart.dispatch = dispatch; + chart.legend = legend; + chart.lines = lines; + chart.lines2 = lines2; + chart.xAxis = xAxis; + chart.yAxis = yAxis; + chart.x2Axis = x2Axis; + chart.y2Axis = y2Axis; + + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + focusHeight: {get: function(){return height2;}, set: function(_){height2=_;}}, + showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, + brushExtent: {get: function(){return brushExtent;}, set: function(_){brushExtent=_;}}, + tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, + tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, + defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, + noData: {get: function(){return noData;}, set: function(_){noData=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + legend.color(color); + // line color is handled above? + }}, + interpolate: {get: function(){return lines.interpolate();}, set: function(_){ + lines.interpolate(_); + lines2.interpolate(_); + }}, + xTickFormat: {get: function(){return xAxis.xTickFormat();}, set: function(_){ + xAxis.xTickFormat(_); + x2Axis.xTickFormat(_); + }}, + yTickFormat: {get: function(){return yAxis.yTickFormat();}, set: function(_){ + yAxis.yTickFormat(_); + y2Axis.yTickFormat(_); + }}, + duration: {get: function(){return transitionDuration;}, set: function(_){ + transitionDuration=_; + yAxis.duration(transitionDuration); + xAxis.duration(transitionDuration); + }}, + x: {get: function(){return lines.x();}, set: function(_){ + lines.x(_); + lines2.x(_); + }}, + y: {get: function(){return lines.y();}, set: function(_){ + lines.y(_); + lines2.y(_); + }} + }); + + nv.utils.inheritOptions(chart, lines); + nv.utils.initOptions(chart); + + return chart; +}; + +nv.models.multiBar = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 0, right: 0, bottom: 0, left: 0} + , width = 960 + , height = 500 + , x = d3.scale.ordinal() + , y = d3.scale.linear() + , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one + , getX = function(d) { return d.x } + , getY = function(d) { return d.y } + , forceY = [0] // 0 is forced by default.. this makes sense for the majority of bar graphs... user can always do chart.forceY([]) to remove + , clipEdge = true + , stacked = false + , stackOffset = 'zero' // options include 'silhouette', 'wiggle', 'expand', 'zero', or a custom function + , color = nv.utils.defaultColor() + , hideable = false + , barColor = null // adding the ability to set the color for each rather than the whole group + , disabled // used in conjunction with barColor to communicate from multiBarHorizontalChart what series are disabled + , duration = 500 + , xDomain + , yDomain + , xRange + , yRange + , groupSpacing = 0.1 + , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'renderEnd') + ; + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var x0, y0 //used to store previous scales + , renderWatch = nv.utils.renderWatch(dispatch, duration) + ; + + var last_datalength = 0; + + function chart(selection) { + renderWatch.reset(); + selection.each(function(data) { + var availableWidth = width - margin.left - margin.right, + availableHeight = height - margin.top - margin.bottom, + container = d3.select(this); + nv.utils.initSVG(container); + + // This function defines the requirements for render complete + var endFn = function(d, i) { + if (d.series === data.length - 1 && i === data[0].values.length - 1) + return true; + return false; + }; + + if(hideable && data.length) hideable = [{ + values: data[0].values.map(function(d) { + return { + x: d.x, + y: 0, + series: d.series, + size: 0.01 + };} + )}]; + + if (stacked) + data = d3.layout.stack() + .offset(stackOffset) + .values(function(d){ return d.values }) + .y(getY) + (!data.length && hideable ? hideable : data); + + + //add series index to each data point for reference + data.forEach(function(series, i) { + series.values.forEach(function(point) { + point.series = i; + }); + }); + + // HACK for negative value stacking + if (stacked) + data[0].values.map(function(d,i) { + var posBase = 0, negBase = 0; + data.map(function(d) { + var f = d.values[i] + f.size = Math.abs(f.y); + if (f.y<0) { + f.y1 = negBase; + negBase = negBase - f.size; + } else + { + f.y1 = f.size + posBase; + posBase = posBase + f.size; + } + }); + }); + + // Setup Scales + // remap and flatten the data for use in calculating the scales' domains + var seriesData = (xDomain && yDomain) ? [] : // if we know xDomain and yDomain, no need to calculate + data.map(function(d) { + return d.values.map(function(d,i) { + return { x: getX(d,i), y: getY(d,i), y0: d.y0, y1: d.y1 } + }) + }); + + x.domain(xDomain || d3.merge(seriesData).map(function(d) { return d.x })) + .rangeBands(xRange || [0, availableWidth], groupSpacing); + + y.domain(yDomain || d3.extent(d3.merge(seriesData).map(function(d) { return stacked ? (d.y > 0 ? d.y1 : d.y1 + d.y ) : d.y }).concat(forceY))) + .range(yRange || [availableHeight, 0]); + + // If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point + if (x.domain()[0] === x.domain()[1]) + x.domain()[0] ? + x.domain([x.domain()[0] - x.domain()[0] * 0.01, x.domain()[1] + x.domain()[1] * 0.01]) + : x.domain([-1,1]); + + if (y.domain()[0] === y.domain()[1]) + y.domain()[0] ? + y.domain([y.domain()[0] + y.domain()[0] * 0.01, y.domain()[1] - y.domain()[1] * 0.01]) + : y.domain([-1,1]); + + x0 = x0 || x; + y0 = y0 || y; + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-multibar').data([data]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-multibar'); + var defsEnter = wrapEnter.append('defs'); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g') + + gEnter.append('g').attr('class', 'nv-groups'); + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + defsEnter.append('clipPath') + .attr('id', 'nv-edge-clip-' + id) + .append('rect'); + wrap.select('#nv-edge-clip-' + id + ' rect') + .attr('width', availableWidth) + .attr('height', availableHeight); + + g.attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + id + ')' : ''); + + var groups = wrap.select('.nv-groups').selectAll('.nv-group') + .data(function(d) { return d }, function(d,i) { return i }); + groups.enter().append('g') + .style('stroke-opacity', 1e-6) + .style('fill-opacity', 1e-6); + + var exitTransition = renderWatch + .transition(groups.exit().selectAll('rect.nv-bar'), 'multibarExit', Math.min(100, duration)) + .attr('y', function(d) { return (stacked ? y0(d.y0) : y0(0)) || 0 }) + .attr('height', 0) + .remove(); + if (exitTransition.delay) + exitTransition.delay(function(d,i) { + var delay = i * (duration / (last_datalength + 1)) - i; + return delay; + }); + groups + .attr('class', function(d,i) { return 'nv-group nv-series-' + i }) + .classed('hover', function(d) { return d.hover }) + .style('fill', function(d,i){ return color(d, i) }) + .style('stroke', function(d,i){ return color(d, i) }); + groups + .style('stroke-opacity', 1) + .style('fill-opacity', 0.75); + + var bars = groups.selectAll('rect.nv-bar') + .data(function(d) { return (hideable && !data.length) ? hideable.values : d.values }); + bars.exit().remove(); + + var barsEnter = bars.enter().append('rect') + .attr('class', function(d,i) { return getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive'}) + .attr('x', function(d,i,j) { + return stacked ? 0 : (j * x.rangeBand() / data.length ) + }) + .attr('y', function(d) { return y0(stacked ? d.y0 : 0) || 0 }) + .attr('height', 0) + .attr('width', x.rangeBand() / (stacked ? 1 : data.length) ) + .attr('transform', function(d,i) { return 'translate(' + x(getX(d,i)) + ',0)'; }) + ; + bars + .style('fill', function(d,i,j){ return color(d, j, i); }) + .style('stroke', function(d,i,j){ return color(d, j, i); }) + .on('mouseover', function(d,i) { //TODO: figure out why j works above, but not here + d3.select(this).classed('hover', true); + dispatch.elementMouseover({ + value: getY(d,i), + point: d, + series: data[d.series], + pos: [x(getX(d,i)) + (x.rangeBand() * (stacked ? data.length / 2 : d.series + .5) / data.length), y(getY(d,i) + (stacked ? d.y0 : 0))], // TODO: Figure out why the value appears to be shifted + pointIndex: i, + seriesIndex: d.series, + e: d3.event + }); + }) + .on('mouseout', function(d,i) { + d3.select(this).classed('hover', false); + dispatch.elementMouseout({ + value: getY(d,i), + point: d, + series: data[d.series], + pointIndex: i, + seriesIndex: d.series, + e: d3.event + }); + }) + .on('click', function(d,i) { + dispatch.elementClick({ + value: getY(d,i), + point: d, + series: data[d.series], + pos: [x(getX(d,i)) + (x.rangeBand() * (stacked ? data.length / 2 : d.series + .5) / data.length), y(getY(d,i) + (stacked ? d.y0 : 0))], // TODO: Figure out why the value appears to be shifted + pointIndex: i, + seriesIndex: d.series, + e: d3.event + }); + d3.event.stopPropagation(); + }) + .on('dblclick', function(d,i) { + dispatch.elementDblClick({ + value: getY(d,i), + point: d, + series: data[d.series], + pos: [x(getX(d,i)) + (x.rangeBand() * (stacked ? data.length / 2 : d.series + .5) / data.length), y(getY(d,i) + (stacked ? d.y0 : 0))], // TODO: Figure out why the value appears to be shifted + pointIndex: i, + seriesIndex: d.series, + e: d3.event + }); + d3.event.stopPropagation(); + }); + bars + .attr('class', function(d,i) { return getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive'}) + .attr('transform', function(d,i) { return 'translate(' + x(getX(d,i)) + ',0)'; }) + + if (barColor) { + if (!disabled) disabled = data.map(function() { return true }); + bars + .style('fill', function(d,i,j) { return d3.rgb(barColor(d,i)).darker( disabled.map(function(d,i) { return i }).filter(function(d,i){ return !disabled[i] })[j] ).toString(); }) + .style('stroke', function(d,i,j) { return d3.rgb(barColor(d,i)).darker( disabled.map(function(d,i) { return i }).filter(function(d,i){ return !disabled[i] })[j] ).toString(); }); + } + + var barSelection = + bars.watchTransition(renderWatch, 'multibar', Math.min(250, duration)) + .delay(function(d,i) { + return i * duration / data[0].values.length; + }); + if (stacked) + barSelection + .attr('y', function(d,i) { + return y((stacked ? d.y1 : 0)); + }) + .attr('height', function(d,i) { + return Math.max(Math.abs(y(d.y + (stacked ? d.y0 : 0)) - y((stacked ? d.y0 : 0))),1); + }) + .attr('x', function(d,i) { + return stacked ? 0 : (d.series * x.rangeBand() / data.length ) + }) + .attr('width', x.rangeBand() / (stacked ? 1 : data.length) ); + else + barSelection + .attr('x', function(d,i) { + return d.series * x.rangeBand() / data.length + }) + .attr('width', x.rangeBand() / data.length) + .attr('y', function(d,i) { + return getY(d,i) < 0 ? + y(0) : + y(0) - y(getY(d,i)) < 1 ? + y(0) - 1 : + y(getY(d,i)) || 0; + }) + .attr('height', function(d,i) { + return Math.max(Math.abs(y(getY(d,i)) - y(0)),1) || 0; + }); + + //store old scales for use in transitions on update + x0 = x.copy(); + y0 = y.copy(); + + // keep track of the last data value length for transition calculations + if (data[0] && data[0].values) { + last_datalength = data[0].values.length; + } + + }); + + renderWatch.renderEnd('multibar immediate'); + + return chart; + } + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + x: {get: function(){return getX;}, set: function(_){getX=_;}}, + y: {get: function(){return getY;}, set: function(_){getY=_;}}, + xScale: {get: function(){return x;}, set: function(_){x=_;}}, + yScale: {get: function(){return y;}, set: function(_){y=_;}}, + xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}}, + yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}}, + xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}}, + yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}}, + forceY: {get: function(){return forceY;}, set: function(_){forceY=_;}}, + stacked: {get: function(){return stacked;}, set: function(_){stacked=_;}}, + stackOffset: {get: function(){return stackOffset;}, set: function(_){stackOffset=_;}}, + clipEdge: {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}}, + disabled: {get: function(){return disabled;}, set: function(_){disabled=_;}}, + id: {get: function(){return id;}, set: function(_){id=_;}}, + hideable: {get: function(){return hideable;}, set: function(_){hideable=_;}}, + groupSpacing:{get: function(){return groupSpacing;}, set: function(_){groupSpacing=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration = _; + renderWatch.reset(duration); + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + }}, + barColor: {get: function(){return barColor;}, set: function(_){ + barColor = nv.utils.getColor(_); + }} + }); + + nv.utils.initOptions(chart); + + return chart; +}; + +nv.models.multiBarChart = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var multibar = nv.models.multiBar() + , xAxis = nv.models.axis() + , yAxis = nv.models.axis() + , legend = nv.models.legend() + , controls = nv.models.legend() + ; + + var margin = {top: 30, right: 20, bottom: 50, left: 60} + , width = null + , height = null + , color = nv.utils.defaultColor() + , showControls = true + , controlLabels = {} + , showLegend = true + , showXAxis = true + , showYAxis = true + , rightAlignYAxis = false + , reduceXTicks = true // if false a tick will show for every data point + , staggerLabels = false + , rotateLabels = 0 + , tooltips = true + , tooltip = function(key, x, y, e, graph) { + return '

' + key + '

' + + '

' + y + ' on ' + x + '

' + } + , x //can be accessed via chart.xScale() + , y //can be accessed via chart.yScale() + , state = nv.utils.state() + , defaultState = null + , noData = "No Data Available." + , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState', 'renderEnd') + , controlWidth = function() { return showControls ? 180 : 0 } + , duration = 250 + ; + + state.stacked = false // DEPRECATED Maintained for backward compatibility + + multibar + .stacked(false) + ; + xAxis + .orient('bottom') + .tickPadding(7) + .highlightZero(true) + .showMaxMin(false) + .tickFormat(function(d) { return d }) + ; + yAxis + .orient((rightAlignYAxis) ? 'right' : 'left') + .tickFormat(d3.format(',.1f')) + ; + + controls.updateState(false); + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var renderWatch = nv.utils.renderWatch(dispatch); + var stacked = false; + + var showTooltip = function(e, offsetElement) { + var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ), + top = e.pos[1] + ( offsetElement.offsetTop || 0), + x = xAxis.tickFormat()(multibar.x()(e.point, e.pointIndex)), + y = yAxis.tickFormat()(multibar.y()(e.point, e.pointIndex)), + content = tooltip(e.series.key, x, y, e, chart); + + nv.tooltip.show([left, top], content, e.value < 0 ? 'n' : 's', null, offsetElement); + }; + + var stateGetter = function(data) { + return function(){ + return { + active: data.map(function(d) { return !d.disabled }), + stacked: stacked + }; + } + }; + + var stateSetter = function(data) { + return function(state) { + if (state.stacked !== undefined) + stacked = state.stacked; + if (state.active !== undefined) + data.forEach(function(series,i) { + series.disabled = !state.active[i]; + }); + } + }; + + function chart(selection) { + renderWatch.reset(); + renderWatch.models(multibar); + if (showXAxis) renderWatch.models(xAxis); + if (showYAxis) renderWatch.models(yAxis); + + selection.each(function(data) { + var container = d3.select(this), + that = this; + nv.utils.initSVG(container); + var availableWidth = (width || parseInt(container.style('width')) || 960) + - margin.left - margin.right, + availableHeight = (height || parseInt(container.style('height')) || 400) + - margin.top - margin.bottom; + + chart.update = function() { + if (duration === 0) + container.call(chart); + else + container.transition() + .duration(duration) + .call(chart); + }; + chart.container = this; + + state + .setter(stateSetter(data), chart.update) + .getter(stateGetter(data)) + .update(); + + // DEPRECATED set state.disableddisabled + state.disabled = data.map(function(d) { return !!d.disabled }); + + if (!defaultState) { + var key; + defaultState = {}; + for (key in state) { + if (state[key] instanceof Array) + defaultState[key] = state[key].slice(0); + else + defaultState[key] = state[key]; + } + } + + // Display noData message if there's nothing to show. + if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { + var noDataText = container.selectAll('.nv-noData').data([noData]); + + noDataText.enter().append('text') + .attr('class', 'nvd3 nv-noData') + .attr('dy', '-.7em') + .style('text-anchor', 'middle'); + + noDataText + .attr('x', margin.left + availableWidth / 2) + .attr('y', margin.top + availableHeight / 2) + .text(function(d) { return d }); + + return chart; + } else { + container.selectAll('.nv-noData').remove(); + } + + // Setup Scales + x = multibar.xScale(); + y = multibar.yScale(); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-multiBarWithLegend').data([data]); + var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-multiBarWithLegend').append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-x nv-axis'); + gEnter.append('g').attr('class', 'nv-y nv-axis'); + gEnter.append('g').attr('class', 'nv-barsWrap'); + gEnter.append('g').attr('class', 'nv-legendWrap'); + gEnter.append('g').attr('class', 'nv-controlsWrap'); + + // Legend + if (showLegend) { + legend.width(availableWidth - controlWidth()); + + if (multibar.barColor()) + data.forEach(function(series,i) { + series.color = d3.rgb('#ccc').darker(i * 1.5).toString(); + }); + + g.select('.nv-legendWrap') + .datum(data) + .call(legend); + + if ( margin.top != legend.height()) { + margin.top = legend.height(); + availableHeight = (height || parseInt(container.style('height')) || 400) + - margin.top - margin.bottom; + } + + g.select('.nv-legendWrap') + .attr('transform', 'translate(' + controlWidth() + ',' + (-margin.top) +')'); + } + + // Controls + if (showControls) { + var controlsData = [ + { key: controlLabels.grouped || 'Grouped', disabled: multibar.stacked() }, + { key: controlLabels.stacked || 'Stacked', disabled: !multibar.stacked() } + ]; + + controls.width(controlWidth()).color(['#444', '#444', '#444']); + g.select('.nv-controlsWrap') + .datum(controlsData) + .attr('transform', 'translate(0,' + (-margin.top) +')') + .call(controls); + } + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + if (rightAlignYAxis) { + g.select(".nv-y.nv-axis") + .attr("transform", "translate(" + availableWidth + ",0)"); + } + + // Main Chart Component(s) + multibar + .disabled(data.map(function(series) { return series.disabled })) + .width(availableWidth) + .height(availableHeight) + .color(data.map(function(d,i) { + return d.color || color(d, i); + }).filter(function(d,i) { return !data[i].disabled })); + + + var barsWrap = g.select('.nv-barsWrap') + .datum(data.filter(function(d) { return !d.disabled })); + + barsWrap.call(multibar); + + // Setup Axes + if (showXAxis) { + xAxis + .scale(x) + .ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + .tickSize(-availableHeight, 0); + + g.select('.nv-x.nv-axis') + .attr('transform', 'translate(0,' + y.range()[0] + ')'); + g.select('.nv-x.nv-axis') + .call(xAxis); + + var xTicks = g.select('.nv-x.nv-axis > g').selectAll('g'); + + xTicks + .selectAll('line, text') + .style('opacity', 1) + + if (staggerLabels) { + var getTranslate = function(x,y) { + return "translate(" + x + "," + y + ")"; + }; + + var staggerUp = 5, staggerDown = 17; //pixels to stagger by + // Issue #140 + xTicks + .selectAll("text") + .attr('transform', function(d,i,j) { + return getTranslate(0, (j % 2 == 0 ? staggerUp : staggerDown)); + }); + + var totalInBetweenTicks = d3.selectAll(".nv-x.nv-axis .nv-wrap g g text")[0].length; + g.selectAll(".nv-x.nv-axis .nv-axisMaxMin text") + .attr("transform", function(d,i) { + return getTranslate(0, (i === 0 || totalInBetweenTicks % 2 !== 0) ? staggerDown : staggerUp); + }); + } + + if (reduceXTicks) + xTicks + .filter(function(d,i) { + return i % Math.ceil(data[0].values.length / (availableWidth / 100)) !== 0; + }) + .selectAll('text, line') + .style('opacity', 0); + + if(rotateLabels) + xTicks + .selectAll('.tick text') + .attr('transform', 'rotate(' + rotateLabels + ' 0,0)') + .style('text-anchor', rotateLabels > 0 ? 'start' : 'end'); + + g.select('.nv-x.nv-axis').selectAll('g.nv-axisMaxMin text') + .style('opacity', 1); + } + + if (showYAxis) { + yAxis + .scale(y) + .ticks( nv.utils.calcTicksY(availableHeight/36, data) ) + .tickSize( -availableWidth, 0); + + g.select('.nv-y.nv-axis') + .call(yAxis); + } + + //============================================================ + // Event Handling/Dispatching (in chart's scope) + //------------------------------------------------------------ + + legend.dispatch.on('stateChange', function(newState) { + for (var key in newState) + state[key] = newState[key]; + dispatch.stateChange(state); + chart.update(); + }); + + controls.dispatch.on('legendClick', function(d,i) { + if (!d.disabled) return; + controlsData = controlsData.map(function(s) { + s.disabled = true; + return s; + }); + d.disabled = false; + + switch (d.key) { + case 'Grouped': + multibar.stacked(false); + break; + case 'Stacked': + multibar.stacked(true); + break; + } + + state.stacked = multibar.stacked(); + dispatch.stateChange(state); + + chart.update(); + }); + + dispatch.on('tooltipShow', function(e) { + if (tooltips) showTooltip(e, that.parentNode) + }); + + // Update chart from a state object passed to event handler + dispatch.on('changeState', function(e) { + + if (typeof e.disabled !== 'undefined') { + data.forEach(function(series,i) { + series.disabled = e.disabled[i]; + }); + + state.disabled = e.disabled; + } + + if (typeof e.stacked !== 'undefined') { + multibar.stacked(e.stacked); + state.stacked = e.stacked; + stacked = e.stacked; + } + + chart.update(); + }); + }); + + renderWatch.renderEnd('multibarchart immediate'); + return chart; + } + + //============================================================ + // Event Handling/Dispatching (out of chart's scope) + //------------------------------------------------------------ + + multibar.dispatch.on('elementMouseover.tooltip', function(e) { + e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; + dispatch.tooltipShow(e); + }); + + multibar.dispatch.on('elementMouseout.tooltip', function(e) { + dispatch.tooltipHide(e); + }); + dispatch.on('tooltipHide', function() { + if (tooltips) nv.tooltip.cleanup(); + }); + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + // expose chart's sub-components + chart.dispatch = dispatch; + chart.multibar = multibar; + chart.legend = legend; + chart.xAxis = xAxis; + chart.yAxis = yAxis; + chart.state = state; + + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, + showControls: {get: function(){return showControls;}, set: function(_){showControls=_;}}, + controlLabels: {get: function(){return controlLabels;}, set: function(_){controlLabels=_;}}, + showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}}, + showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}}, + tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, + tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, + defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, + noData: {get: function(){return noData;}, set: function(_){noData=_;}}, + reduceXTicks: {get: function(){return reduceXTicks;}, set: function(_){reduceXTicks=_;}}, + rotateLabels: {get: function(){return rotateLabels;}, set: function(_){rotateLabels=_;}}, + staggerLabels: {get: function(){return staggerLabels;}, set: function(_){staggerLabels=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration = _; + multibar.duration(duration); + xAxis.duration(duration); + yAxis.duration(duration); + renderWatch.reset(duration); + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + legend.color(color); + }}, + rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){ + rightAlignYAxis = _; + yAxis.orient( rightAlignYAxis ? 'right' : 'left'); + }} + }); + + nv.utils.inheritOptions(chart, multibar); + nv.utils.initOptions(chart); + + return chart; +}; + +nv.models.multiBarHorizontal = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 0, right: 0, bottom: 0, left: 0} + , width = 960 + , height = 500 + , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one + , x = d3.scale.ordinal() + , y = d3.scale.linear() + , getX = function(d) { return d.x } + , getY = function(d) { return d.y } + , getYerr = function(d) { return d.yErr } + , forceY = [0] // 0 is forced by default.. this makes sense for the majority of bar graphs... user can always do chart.forceY([]) to remove + , color = nv.utils.defaultColor() + , barColor = null // adding the ability to set the color for each rather than the whole group + , disabled // used in conjunction with barColor to communicate from multiBarHorizontalChart what series are disabled + , stacked = false + , showValues = false + , showBarLabels = false + , valuePadding = 60 + , valueFormat = d3.format(',.2f') + , delay = 1200 + , xDomain + , yDomain + , xRange + , yRange + , duration = 250 + , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout','renderEnd') + ; + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var x0, y0; //used to store previous scales + var renderWatch = nv.utils.renderWatch(dispatch, duration); + + function chart(selection) { + renderWatch.reset(); + selection.each(function(data) { + var availableWidth = width - margin.left - margin.right, + availableHeight = height - margin.top - margin.bottom, + container = d3.select(this); + nv.utils.initSVG(container); + + if (stacked) + data = d3.layout.stack() + .offset('zero') + .values(function(d){ return d.values }) + .y(getY) + (data); + + //add series index to each data point for reference + data.forEach(function(series, i) { + series.values.forEach(function(point) { + point.series = i; + }); + }); + + // HACK for negative value stacking + if (stacked) + data[0].values.map(function(d,i) { + var posBase = 0, negBase = 0; + data.map(function(d) { + var f = d.values[i] + f.size = Math.abs(f.y); + if (f.y<0) { + f.y1 = negBase - f.size; + negBase = negBase - f.size; + } else + { + f.y1 = posBase; + posBase = posBase + f.size; + } + }); + }); + + // Setup Scales + // remap and flatten the data for use in calculating the scales' domains + var seriesData = (xDomain && yDomain) ? [] : // if we know xDomain and yDomain, no need to calculate + data.map(function(d) { + return d.values.map(function(d,i) { + return { x: getX(d,i), y: getY(d,i), y0: d.y0, y1: d.y1 } + }) + }); + + x.domain(xDomain || d3.merge(seriesData).map(function(d) { return d.x })) + .rangeBands(xRange || [0, availableHeight], .1); + + y.domain(yDomain || d3.extent(d3.merge(seriesData).map(function(d) { return stacked ? (d.y > 0 ? d.y1 + d.y : d.y1 ) : d.y }).concat(forceY))) + + if (showValues && !stacked) + y.range(yRange || [(y.domain()[0] < 0 ? valuePadding : 0), availableWidth - (y.domain()[1] > 0 ? valuePadding : 0) ]); + else + y.range(yRange || [0, availableWidth]); + + x0 = x0 || x; + y0 = y0 || d3.scale.linear().domain(y.domain()).range([y(0),y(0)]); + + // Setup containers and skeleton of chart + var wrap = d3.select(this).selectAll('g.nv-wrap.nv-multibarHorizontal').data([data]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-multibarHorizontal'); + var defsEnter = wrapEnter.append('defs'); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-groups'); + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + var groups = wrap.select('.nv-groups').selectAll('.nv-group') + .data(function(d) { return d }, function(d,i) { return i }); + groups.enter().append('g') + .style('stroke-opacity', 1e-6) + .style('fill-opacity', 1e-6); + groups.exit().watchTransition(renderWatch, 'multibarhorizontal: exit groups') + .style('stroke-opacity', 1e-6) + .style('fill-opacity', 1e-6) + .remove(); + groups + .attr('class', function(d,i) { return 'nv-group nv-series-' + i }) + .classed('hover', function(d) { return d.hover }) + .style('fill', function(d,i){ return color(d, i) }) + .style('stroke', function(d,i){ return color(d, i) }); + groups.watchTransition(renderWatch, 'multibarhorizontal: groups') + .style('stroke-opacity', 1) + .style('fill-opacity', .75); + + var bars = groups.selectAll('g.nv-bar') + .data(function(d) { return d.values }); + bars.exit().remove(); + + var barsEnter = bars.enter().append('g') + .attr('transform', function(d,i,j) { + return 'translate(' + y0(stacked ? d.y0 : 0) + ',' + (stacked ? 0 : (j * x.rangeBand() / data.length ) + x(getX(d,i))) + ')' + }); + + barsEnter.append('rect') + .attr('width', 0) + .attr('height', x.rangeBand() / (stacked ? 1 : data.length) ) + + bars + .on('mouseover', function(d,i) { //TODO: figure out why j works above, but not here + d3.select(this).classed('hover', true); + dispatch.elementMouseover({ + value: getY(d,i), + point: d, + series: data[d.series], + pos: [ y(getY(d,i) + (stacked ? d.y0 : 0)), x(getX(d,i)) + (x.rangeBand() * (stacked ? data.length / 2 : d.series + .5) / data.length) ], + pointIndex: i, + seriesIndex: d.series, + e: d3.event + }); + }) + .on('mouseout', function(d,i) { + d3.select(this).classed('hover', false); + dispatch.elementMouseout({ + value: getY(d,i), + point: d, + series: data[d.series], + pointIndex: i, + seriesIndex: d.series, + e: d3.event + }); + }) + .on('click', function(d,i) { + dispatch.elementClick({ + value: getY(d,i), + point: d, + series: data[d.series], + pos: [x(getX(d,i)) + (x.rangeBand() * (stacked ? data.length / 2 : d.series + .5) / data.length), y(getY(d,i) + (stacked ? d.y0 : 0))], // TODO: Figure out why the value appears to be shifted + pointIndex: i, + seriesIndex: d.series, + e: d3.event + }); + d3.event.stopPropagation(); + }) + .on('dblclick', function(d,i) { + dispatch.elementDblClick({ + value: getY(d,i), + point: d, + series: data[d.series], + pos: [x(getX(d,i)) + (x.rangeBand() * (stacked ? data.length / 2 : d.series + .5) / data.length), y(getY(d,i) + (stacked ? d.y0 : 0))], // TODO: Figure out why the value appears to be shifted + pointIndex: i, + seriesIndex: d.series, + e: d3.event + }); + d3.event.stopPropagation(); + }); + + if (getYerr(data[0],0)) { + barsEnter.append('polyline'); + + bars.select('polyline') + .attr('fill', 'none') + .attr('points', function(d,i) { + var xerr = getYerr(d,i) + , mid = 0.8 * x.rangeBand() / ((stacked ? 1 : data.length) * 2); + xerr = xerr.length ? xerr : [-Math.abs(xerr), Math.abs(xerr)]; + xerr = xerr.map(function(e) { return y(e) - y(0); }); + var a = [[xerr[0],-mid], [xerr[0],mid], [xerr[0],0], [xerr[1],0], [xerr[1],-mid], [xerr[1],mid]]; + return a.map(function (path) { return path.join(',') }).join(' '); + }) + .attr('transform', function(d,i) { + var mid = x.rangeBand() / ((stacked ? 1 : data.length) * 2); + return 'translate(' + (getY(d,i) < 0 ? 0 : y(getY(d,i)) - y(0)) + ', ' + mid + ')' + }); + } + + barsEnter.append('text'); + + if (showValues && !stacked) { + bars.select('text') + .attr('text-anchor', function(d,i) { return getY(d,i) < 0 ? 'end' : 'start' }) + .attr('y', x.rangeBand() / (data.length * 2)) + .attr('dy', '.32em') + .html(function(d,i) { + var t = valueFormat(getY(d,i)) + , yerr = getYerr(d,i); + if (yerr === undefined) + return t; + if (!yerr.length) + return t + '±' + valueFormat(Math.abs(yerr)); + return t + '+' + valueFormat(Math.abs(yerr[1])) + '-' + valueFormat(Math.abs(yerr[0])); + }); + bars.watchTransition(renderWatch, 'multibarhorizontal: bars') + .select('text') + .attr('x', function(d,i) { return getY(d,i) < 0 ? -4 : y(getY(d,i)) - y(0) + 4 }) + } else { + bars.selectAll('text').text(''); + } + + if (showBarLabels && !stacked) { + barsEnter.append('text').classed('nv-bar-label',true); + bars.select('text.nv-bar-label') + .attr('text-anchor', function(d,i) { return getY(d,i) < 0 ? 'start' : 'end' }) + .attr('y', x.rangeBand() / (data.length * 2)) + .attr('dy', '.32em') + .text(function(d,i) { return getX(d,i) }); + bars.watchTransition(renderWatch, 'multibarhorizontal: bars') + .select('text.nv-bar-label') + .attr('x', function(d,i) { return getY(d,i) < 0 ? y(0) - y(getY(d,i)) + 4 : -4 }); + } + else { + bars.selectAll('text.nv-bar-label').text(''); + } + + bars + .attr('class', function(d,i) { return getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive'}) + + if (barColor) { + if (!disabled) disabled = data.map(function() { return true }); + bars + .style('fill', function(d,i,j) { return d3.rgb(barColor(d,i)).darker( disabled.map(function(d,i) { return i }).filter(function(d,i){ return !disabled[i] })[j] ).toString(); }) + .style('stroke', function(d,i,j) { return d3.rgb(barColor(d,i)).darker( disabled.map(function(d,i) { return i }).filter(function(d,i){ return !disabled[i] })[j] ).toString(); }); + } + + if (stacked) + bars.watchTransition(renderWatch, 'multibarhorizontal: bars') + .attr('transform', function(d,i) { + return 'translate(' + y(d.y1) + ',' + x(getX(d,i)) + ')' + }) + .select('rect') + .attr('width', function(d,i) { + return Math.abs(y(getY(d,i) + d.y0) - y(d.y0)) + }) + .attr('height', x.rangeBand() ); + else + bars.watchTransition(renderWatch, 'multibarhorizontal: bars') + .attr('transform', function(d,i) { + //TODO: stacked must be all positive or all negative, not both? + return 'translate(' + + (getY(d,i) < 0 ? y(getY(d,i)) : y(0)) + + ',' + + (d.series * x.rangeBand() / data.length + + + x(getX(d,i)) ) + + ')' + }) + .select('rect') + .attr('height', x.rangeBand() / data.length ) + .attr('width', function(d,i) { + return Math.max(Math.abs(y(getY(d,i)) - y(0)),1) + }); + + //store old scales for use in transitions on update + x0 = x.copy(); + y0 = y.copy(); + + }); + + renderWatch.renderEnd('multibarHorizontal immediate'); + return chart; + } + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + x: {get: function(){return getX;}, set: function(_){getX=_;}}, + y: {get: function(){return getY;}, set: function(_){getY=_;}}, + yErr: {get: function(){return getYerr;}, set: function(_){getYerr=_;}}, + xScale: {get: function(){return x;}, set: function(_){x=_;}}, + yScale: {get: function(){return y;}, set: function(_){y=_;}}, + xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}}, + yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}}, + xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}}, + yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}}, + forceY: {get: function(){return forceY;}, set: function(_){forceY=_;}}, + stacked: {get: function(){return stacked;}, set: function(_){stacked=_;}}, + showValues: {get: function(){return showValues;}, set: function(_){showValues=_;}}, + // this shows the group name, seems pointless? + //showBarLabels: {get: function(){return showBarLabels;}, set: function(_){showBarLabels=_;}}, + disabled: {get: function(){return disabled;}, set: function(_){disabled=_;}}, + id: {get: function(){return id;}, set: function(_){id=_;}}, + valueFormat: {get: function(){return valueFormat;}, set: function(_){valueFormat=_;}}, + valuePadding: {get: function(){return valuePadding;}, set: function(_){valuePadding=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration = _; + renderWatch.reset(duration); + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + }}, + barColor: {get: function(){return color;}, set: function(_){ + barColor = nv.utils.getColor(_); + }} + }); + + nv.utils.initOptions(chart); + + return chart; +}; +nv.models.multiBarHorizontalChart = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var multibar = nv.models.multiBarHorizontal() + , xAxis = nv.models.axis() + , yAxis = nv.models.axis() + , legend = nv.models.legend().height(30) + , controls = nv.models.legend().height(30) + ; + + var margin = {top: 30, right: 20, bottom: 50, left: 60} + , width = null + , height = null + , color = nv.utils.defaultColor() + , showControls = true + , controlLabels = {} + , showLegend = true + , showXAxis = true + , showYAxis = true + , stacked = false + , tooltips = true + , tooltip = function(key, x, y, e, graph) { + return '

' + key + ' - ' + x + '

' + + '

' + y + '

' + } + , x //can be accessed via chart.xScale() + , y //can be accessed via chart.yScale() + , state = nv.utils.state() + , defaultState = null + , noData = 'No Data Available.' + , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState','renderEnd') + , controlWidth = function() { return showControls ? 180 : 0 } + , duration = 250 + ; + + state.stacked = false; // DEPRECATED Maintained for backward compatibility + + multibar + .stacked(stacked) + ; + xAxis + .orient('left') + .tickPadding(5) + .highlightZero(false) + .showMaxMin(false) + .tickFormat(function(d) { return d }) + ; + yAxis + .orient('bottom') + .tickFormat(d3.format(',.1f')) + ; + + controls.updateState(false); + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var showTooltip = function(e, offsetElement) { + var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ), + top = e.pos[1] + ( offsetElement.offsetTop || 0), + x = xAxis.tickFormat()(multibar.x()(e.point, e.pointIndex)), + y = yAxis.tickFormat()(multibar.y()(e.point, e.pointIndex)), + content = tooltip(e.series.key, x, y, e, chart); + + nv.tooltip.show([left, top], content, e.value < 0 ? 'e' : 'w', null, offsetElement); + }; + + var stateGetter = function(data) { + return function(){ + return { + active: data.map(function(d) { return !d.disabled }), + stacked: stacked + }; + } + }; + + var stateSetter = function(data) { + return function(state) { + if (state.stacked !== undefined) + stacked = state.stacked; + if (state.active !== undefined) + data.forEach(function(series,i) { + series.disabled = !state.active[i]; + }); + } + }; + + var renderWatch = nv.utils.renderWatch(dispatch, duration); + + function chart(selection) { + renderWatch.reset(); + renderWatch.models(multibar); + if (showXAxis) renderWatch.models(xAxis); + if (showYAxis) renderWatch.models(yAxis); + + selection.each(function(data) { + var container = d3.select(this), + that = this; + nv.utils.initSVG(container); + var availableWidth = (width || parseInt(container.style('width')) || 960) + - margin.left - margin.right, + availableHeight = (height || parseInt(container.style('height')) || 400) + - margin.top - margin.bottom; + + chart.update = function() { container.transition().duration(duration).call(chart) }; + chart.container = this; + + stacked = multibar.stacked(); + + state + .setter(stateSetter(data), chart.update) + .getter(stateGetter(data)) + .update(); + + // DEPRECATED set state.disableddisabled + state.disabled = data.map(function(d) { return !!d.disabled }); + + if (!defaultState) { + var key; + defaultState = {}; + for (key in state) { + if (state[key] instanceof Array) + defaultState[key] = state[key].slice(0); + else + defaultState[key] = state[key]; + } + } + + // Display No Data message if there's nothing to show. + if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { + var noDataText = container.selectAll('.nv-noData').data([noData]); + + noDataText.enter().append('text') + .attr('class', 'nvd3 nv-noData') + .attr('dy', '-.7em') + .style('text-anchor', 'middle'); + + noDataText + .attr('x', margin.left + availableWidth / 2) + .attr('y', margin.top + availableHeight / 2) + .text(function(d) { return d }); + + return chart; + } else { + container.selectAll('.nv-noData').remove(); + } + + // Setup Scales + x = multibar.xScale(); + y = multibar.yScale(); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-multiBarHorizontalChart').data([data]); + var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-multiBarHorizontalChart').append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-x nv-axis'); + gEnter.append('g').attr('class', 'nv-y nv-axis') + .append('g').attr('class', 'nv-zeroLine') + .append('line'); + gEnter.append('g').attr('class', 'nv-barsWrap'); + gEnter.append('g').attr('class', 'nv-legendWrap'); + gEnter.append('g').attr('class', 'nv-controlsWrap'); + + // Legend + if (showLegend) { + legend.width(availableWidth - controlWidth()); + + if (multibar.barColor()) + data.forEach(function(series,i) { + series.color = d3.rgb('#ccc').darker(i * 1.5).toString(); + }); + + g.select('.nv-legendWrap') + .datum(data) + .call(legend); + + if ( margin.top != legend.height()) { + margin.top = legend.height(); + availableHeight = (height || parseInt(container.style('height')) || 400) + - margin.top - margin.bottom; + } + + g.select('.nv-legendWrap') + .attr('transform', 'translate(' + controlWidth() + ',' + (-margin.top) +')'); + } + + // Controls + if (showControls) { + var controlsData = [ + { key: controlLabels.grouped || 'Grouped', disabled: multibar.stacked() }, + { key: controlLabels.stacked || 'Stacked', disabled: !multibar.stacked() } + ]; + + controls.width(controlWidth()).color(['#444', '#444', '#444']); + g.select('.nv-controlsWrap') + .datum(controlsData) + .attr('transform', 'translate(0,' + (-margin.top) +')') + .call(controls); + } + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + // Main Chart Component(s) + multibar + .disabled(data.map(function(series) { return series.disabled })) + .width(availableWidth) + .height(availableHeight) + .color(data.map(function(d,i) { + return d.color || color(d, i); + }).filter(function(d,i) { return !data[i].disabled })); + + var barsWrap = g.select('.nv-barsWrap') + .datum(data.filter(function(d) { return !d.disabled })); + + barsWrap.transition().call(multibar); + + // Setup Axes + if (showXAxis) { + xAxis + .scale(x) + .ticks( nv.utils.calcTicksY(availableHeight/24, data) ) + .tickSize(-availableWidth, 0); + + g.select('.nv-x.nv-axis').call(xAxis); + + var xTicks = g.select('.nv-x.nv-axis').selectAll('g'); + + xTicks + .selectAll('line, text'); + } + + if (showYAxis) { + yAxis + .scale(y) + .ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + .tickSize( -availableHeight, 0); + + g.select('.nv-y.nv-axis') + .attr('transform', 'translate(0,' + availableHeight + ')'); + g.select('.nv-y.nv-axis').call(yAxis); + } + + // Zero line + g.select(".nv-zeroLine line") + .attr("x1", y(0)) + .attr("x2", y(0)) + .attr("y1", 0) + .attr("y2", -availableHeight) + ; + + //============================================================ + // Event Handling/Dispatching (in chart's scope) + //------------------------------------------------------------ + + legend.dispatch.on('stateChange', function(newState) { + for (var key in newState) + state[key] = newState[key]; + dispatch.stateChange(state); + chart.update(); + }); + + controls.dispatch.on('legendClick', function(d,i) { + if (!d.disabled) return; + controlsData = controlsData.map(function(s) { + s.disabled = true; + return s; + }); + d.disabled = false; + + switch (d.key) { + case 'Grouped': + multibar.stacked(false); + break; + case 'Stacked': + multibar.stacked(true); + break; + } + + state.stacked = multibar.stacked(); + dispatch.stateChange(state); + stacked = multibar.stacked(); + + chart.update(); + }); + + dispatch.on('tooltipShow', function(e) { + if (tooltips) showTooltip(e, that.parentNode); + }); + + // Update chart from a state object passed to event handler + dispatch.on('changeState', function(e) { + + if (typeof e.disabled !== 'undefined') { + data.forEach(function(series,i) { + series.disabled = e.disabled[i]; + }); + + state.disabled = e.disabled; + } + + if (typeof e.stacked !== 'undefined') { + multibar.stacked(e.stacked); + state.stacked = e.stacked; + stacked = e.stacked; + } + + chart.update(); + }); + }); + renderWatch.renderEnd('multibar horizontal chart immediate'); + return chart; + } + + //============================================================ + // Event Handling/Dispatching (out of chart's scope) + //------------------------------------------------------------ + + multibar.dispatch.on('elementMouseover.tooltip', function(e) { + e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; + dispatch.tooltipShow(e); + }); + + multibar.dispatch.on('elementMouseout.tooltip', function(e) { + dispatch.tooltipHide(e); + }); + dispatch.on('tooltipHide', function() { + if (tooltips) nv.tooltip.cleanup(); + }); + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + // expose chart's sub-components + chart.dispatch = dispatch; + chart.multibar = multibar; + chart.legend = legend; + chart.xAxis = xAxis; + chart.yAxis = yAxis; + chart.state = state; + + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, + showControls: {get: function(){return showControls;}, set: function(_){showControls=_;}}, + controlLabels: {get: function(){return controlLabels;}, set: function(_){controlLabels=_;}}, + showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}}, + showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}}, + tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, + tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, + defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, + noData: {get: function(){return noData;}, set: function(_){noData=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration = _; + renderWatch.reset(duration); + multibar.duration(duration); + xAxis.duration(duration); + yAxis.duration(duration); + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + legend.color(color); + }} + }); + + nv.utils.inheritOptions(chart, multibar); + nv.utils.initOptions(chart); + + return chart; +}; +nv.models.multiChart = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 30, right: 20, bottom: 50, left: 60}, + color = nv.utils.defaultColor(), + width = null, + height = null, + showLegend = true, + tooltips = true, + tooltip = function(key, x, y, e, graph) { + return '

' + key + '

' + + '

' + y + ' at ' + x + '

' + }, + x, + y, + noData = 'No Data Available.', + yDomain1, + yDomain2, + getX = function(d) { return d.x }, + getY = function(d) { return d.y}, + interpolate = 'monotone' + ; + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var x = d3.scale.linear(), + yScale1 = d3.scale.linear(), + yScale2 = d3.scale.linear(), + + lines1 = nv.models.line().yScale(yScale1), + lines2 = nv.models.line().yScale(yScale2), + + bars1 = nv.models.multiBar().stacked(false).yScale(yScale1), + bars2 = nv.models.multiBar().stacked(false).yScale(yScale2), + + stack1 = nv.models.stackedArea().yScale(yScale1), + stack2 = nv.models.stackedArea().yScale(yScale2), + + xAxis = nv.models.axis().scale(x).orient('bottom').tickPadding(5), + yAxis1 = nv.models.axis().scale(yScale1).orient('left'), + yAxis2 = nv.models.axis().scale(yScale2).orient('right'), + + legend = nv.models.legend().height(30), + dispatch = d3.dispatch('tooltipShow', 'tooltipHide'); + + var showTooltip = function(e, offsetElement) { + var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ), + top = e.pos[1] + ( offsetElement.offsetTop || 0), + x = xAxis.tickFormat()(lines1.x()(e.point, e.pointIndex)), + y = ((e.series.yAxis == 2) ? yAxis2 : yAxis1).tickFormat()(lines1.y()(e.point, e.pointIndex)), + content = tooltip(e.series.key, x, y, e, chart); + + nv.tooltip.show([left, top], content, undefined, undefined, offsetElement.offsetParent); + }; + + function chart(selection) { + selection.each(function(data) { + var container = d3.select(this), + that = this; + nv.utils.initSVG(container); + + chart.update = function() { container.transition().call(chart); }; + chart.container = this; + + var availableWidth = (width || parseInt(container.style('width')) || 960) + - margin.left - margin.right, + availableHeight = (height || parseInt(container.style('height')) || 400) + - margin.top - margin.bottom; + + var dataLines1 = data.filter(function(d) {return d.type == 'line' && d.yAxis == 1}); + var dataLines2 = data.filter(function(d) {return d.type == 'line' && d.yAxis == 2}); + var dataBars1 = data.filter(function(d) {return d.type == 'bar' && d.yAxis == 1}); + var dataBars2 = data.filter(function(d) {return d.type == 'bar' && d.yAxis == 2}); + var dataStack1 = data.filter(function(d) {return d.type == 'area' && d.yAxis == 1}); + var dataStack2 = data.filter(function(d) {return d.type == 'area' && d.yAxis == 2}); + + // Display noData message if there's nothing to show. + if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { + var noDataText = container.selectAll('.nv-noData').data([noData]); + + noDataText.enter().append('text') + .attr('class', 'nvd3 nv-noData') + .attr('dy', '-.7em') + .style('text-anchor', 'middle'); + + noDataText + .attr('x', margin.left + availableWidth / 2) + .attr('y', margin.top + availableHeight / 2) + .text(function(d) { return d }); + + return chart; + } else { + container.selectAll('.nv-noData').remove(); + } + + var series1 = data.filter(function(d) {return !d.disabled && d.yAxis == 1}) + .map(function(d) { + return d.values.map(function(d,i) { + return { x: d.x, y: d.y } + }) + }); + + var series2 = data.filter(function(d) {return !d.disabled && d.yAxis == 2}) + .map(function(d) { + return d.values.map(function(d,i) { + return { x: d.x, y: d.y } + }) + }); + + x .domain(d3.extent(d3.merge(series1.concat(series2)), function(d) { return d.x } )) + .range([0, availableWidth]); + + var wrap = container.selectAll('g.wrap.multiChart').data([data]); + var gEnter = wrap.enter().append('g').attr('class', 'wrap nvd3 multiChart').append('g'); + + gEnter.append('g').attr('class', 'x axis'); + gEnter.append('g').attr('class', 'y1 axis'); + gEnter.append('g').attr('class', 'y2 axis'); + gEnter.append('g').attr('class', 'lines1Wrap'); + gEnter.append('g').attr('class', 'lines2Wrap'); + gEnter.append('g').attr('class', 'bars1Wrap'); + gEnter.append('g').attr('class', 'bars2Wrap'); + gEnter.append('g').attr('class', 'stack1Wrap'); + gEnter.append('g').attr('class', 'stack2Wrap'); + gEnter.append('g').attr('class', 'legendWrap'); + + var g = wrap.select('g'); + + var color_array = data.map(function(d,i) { + return data[i].color || color(d, i); + }); + + if (showLegend) { + legend.color(color_array); + legend.width( availableWidth / 2 ); + + g.select('.legendWrap') + .datum(data.map(function(series) { + series.originalKey = series.originalKey === undefined ? series.key : series.originalKey; + series.key = series.originalKey + (series.yAxis == 1 ? '' : ' (right axis)'); + return series; + })) + .call(legend); + + if ( margin.top != legend.height()) { + margin.top = legend.height(); + availableHeight = (height || parseInt(container.style('height')) || 400) + - margin.top - margin.bottom; + } + + g.select('.legendWrap') + .attr('transform', 'translate(' + ( availableWidth / 2 ) + ',' + (-margin.top) +')'); + } + + lines1 + .width(availableWidth) + .height(availableHeight) + .interpolate(interpolate) + .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 1 && data[i].type == 'line'})); + lines2 + .width(availableWidth) + .height(availableHeight) + .interpolate(interpolate) + .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 2 && data[i].type == 'line'})); + bars1 + .width(availableWidth) + .height(availableHeight) + .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 1 && data[i].type == 'bar'})); + bars2 + .width(availableWidth) + .height(availableHeight) + .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 2 && data[i].type == 'bar'})); + stack1 + .width(availableWidth) + .height(availableHeight) + .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 1 && data[i].type == 'area'})); + stack2 + .width(availableWidth) + .height(availableHeight) + .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 2 && data[i].type == 'area'})); + + g.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + var lines1Wrap = g.select('.lines1Wrap') + .datum( + dataLines1.filter(function(d){return !d.disabled}) + ); + var bars1Wrap = g.select('.bars1Wrap') + .datum( + dataBars1.filter(function(d){return !d.disabled}) + ); + var stack1Wrap = g.select('.stack1Wrap') + .datum( + dataStack1.filter(function(d){return !d.disabled}) + ); + + var lines2Wrap = g.select('.lines2Wrap') + .datum( + dataLines2.filter(function(d){return !d.disabled}) + ); + var bars2Wrap = g.select('.bars2Wrap') + .datum( + dataBars2.filter(function(d){return !d.disabled}) + ); + var stack2Wrap = g.select('.stack2Wrap') + .datum( + dataStack2.filter(function(d){return !d.disabled}) + ); + + var extraValue1 = dataStack1.length ? dataStack1.map(function(a){return a.values}).reduce(function(a,b){ + return a.map(function(aVal,i){return {x: aVal.x, y: aVal.y + b[i].y}}) + }).concat([{x:0, y:0}]) : [] + var extraValue2 = dataStack2.length ? dataStack2.map(function(a){return a.values}).reduce(function(a,b){ + return a.map(function(aVal,i){return {x: aVal.x, y: aVal.y + b[i].y}}) + }).concat([{x:0, y:0}]) : [] + + yScale1 .domain(yDomain1 || d3.extent(d3.merge(series1).concat(extraValue1), function(d) { return d.y } )) + .range([0, availableHeight]) + + yScale2 .domain(yDomain2 || d3.extent(d3.merge(series2).concat(extraValue2), function(d) { return d.y } )) + .range([0, availableHeight]) + + lines1.yDomain(yScale1.domain()) + bars1.yDomain(yScale1.domain()) + stack1.yDomain(yScale1.domain()) + + lines2.yDomain(yScale2.domain()) + bars2.yDomain(yScale2.domain()) + stack2.yDomain(yScale2.domain()) + + if(dataStack1.length){d3.transition(stack1Wrap).call(stack1);} + if(dataStack2.length){d3.transition(stack2Wrap).call(stack2);} + + if(dataBars1.length){d3.transition(bars1Wrap).call(bars1);} + if(dataBars2.length){d3.transition(bars2Wrap).call(bars2);} + + if(dataLines1.length){d3.transition(lines1Wrap).call(lines1);} + if(dataLines2.length){d3.transition(lines2Wrap).call(lines2);} + + xAxis + .ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + .tickSize(-availableHeight, 0); + + g.select('.x.axis') + .attr('transform', 'translate(0,' + availableHeight + ')'); + d3.transition(g.select('.x.axis')) + .call(xAxis); + + yAxis1 + .ticks( nv.utils.calcTicksY(availableHeight/36, data) ) + .tickSize( -availableWidth, 0); + + + d3.transition(g.select('.y1.axis')) + .call(yAxis1); + + yAxis2 + .ticks( nv.utils.calcTicksY(availableHeight/36, data) ) + .tickSize( -availableWidth, 0); + + d3.transition(g.select('.y2.axis')) + .call(yAxis2); + + g.select('.y1.axis') + .classed('nv-disabled', series1.length ? false : true) + .attr('transform', 'translate(' + x.range()[0] + ',0)'); + + g.select('.y2.axis') + .classed('nv-disabled', series2.length ? false : true) + .attr('transform', 'translate(' + x.range()[1] + ',0)'); + + legend.dispatch.on('stateChange', function(newState) { + chart.update(); + }); + + dispatch.on('tooltipShow', function(e) { + if (tooltips) showTooltip(e, that.parentNode); + }); + + }); + + return chart; + } + + //============================================================ + // Event Handling/Dispatching (out of chart's scope) + //------------------------------------------------------------ + + lines1.dispatch.on('elementMouseover.tooltip', function(e) { + e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; + dispatch.tooltipShow(e); + }); + + lines1.dispatch.on('elementMouseout.tooltip', function(e) { + dispatch.tooltipHide(e); + }); + + lines2.dispatch.on('elementMouseover.tooltip', function(e) { + e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; + dispatch.tooltipShow(e); + }); + + lines2.dispatch.on('elementMouseout.tooltip', function(e) { + dispatch.tooltipHide(e); + }); + + bars1.dispatch.on('elementMouseover.tooltip', function(e) { + e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; + dispatch.tooltipShow(e); + }); + + bars1.dispatch.on('elementMouseout.tooltip', function(e) { + dispatch.tooltipHide(e); + }); + + bars2.dispatch.on('elementMouseover.tooltip', function(e) { + e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; + dispatch.tooltipShow(e); + }); + + bars2.dispatch.on('elementMouseout.tooltip', function(e) { + dispatch.tooltipHide(e); + }); + + stack1.dispatch.on('tooltipShow', function(e) { + //disable tooltips when value ~= 0 + //// TODO: consider removing points from voronoi that have 0 value instead of this hack + if (!Math.round(stack1.y()(e.point) * 100)) { // 100 will not be good for very small numbers... will have to think about making this valu dynamic, based on data range + setTimeout(function() { d3.selectAll('.point.hover').classed('hover', false) }, 0); + return false; + } + + e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top], + dispatch.tooltipShow(e); + }); + + stack1.dispatch.on('tooltipHide', function(e) { + dispatch.tooltipHide(e); + }); + + stack2.dispatch.on('tooltipShow', function(e) { + //disable tooltips when value ~= 0 + //// TODO: consider removing points from voronoi that have 0 value instead of this hack + if (!Math.round(stack2.y()(e.point) * 100)) { // 100 will not be good for very small numbers... will have to think about making this valu dynamic, based on data range + setTimeout(function() { d3.selectAll('.point.hover').classed('hover', false) }, 0); + return false; + } + + e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top], + dispatch.tooltipShow(e); + }); + + stack2.dispatch.on('tooltipHide', function(e) { + dispatch.tooltipHide(e); + }); + + lines1.dispatch.on('elementMouseover.tooltip', function(e) { + e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; + dispatch.tooltipShow(e); + }); + + lines1.dispatch.on('elementMouseout.tooltip', function(e) { + dispatch.tooltipHide(e); + }); + + lines2.dispatch.on('elementMouseover.tooltip', function(e) { + e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; + dispatch.tooltipShow(e); + }); + + lines2.dispatch.on('elementMouseout.tooltip', function(e) { + dispatch.tooltipHide(e); + }); + + dispatch.on('tooltipHide', function() { + if (tooltips) nv.tooltip.cleanup(); + }); + + //============================================================ + // Global getters and setters + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.lines1 = lines1; + chart.lines2 = lines2; + chart.bars1 = bars1; + chart.bars2 = bars2; + chart.stack1 = stack1; + chart.stack2 = stack2; + chart.xAxis = xAxis; + chart.yAxis1 = yAxis1; + chart.yAxis2 = yAxis2; + + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, + yDomain1: {get: function(){return yDomain1;}, set: function(_){yDomain1=_;}}, + yDomain2: {get: function(){return yDomain2;}, set: function(_){yDomain2=_;}}, + tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, + tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, + noData: {get: function(){return noData;}, set: function(_){noData=_;}}, + interpolate: {get: function(){return interpolate;}, set: function(_){interpolate=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + }}, + x: {get: function(){return getX;}, set: function(_){ + getX = _; + lines1.x(_); + bars1.x(_); + }}, + y: {get: function(){return getY;}, set: function(_){ + getY = _; + lines1.y(_); + bars1.y(_); + }} + }); + + nv.utils.initOptions(chart); + + return chart; +}; + + +nv.models.ohlcBar = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 0, right: 0, bottom: 0, left: 0} + , width = null + , height = null + , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one + , x = d3.scale.linear() + , y = d3.scale.linear() + , getX = function(d) { return d.x } + , getY = function(d) { return d.y } + , getOpen = function(d) { return d.open } + , getClose = function(d) { return d.close } + , getHigh = function(d) { return d.high } + , getLow = function(d) { return d.low } + , forceX = [] + , forceY = [] + , padData = false // If true, adds half a data points width to front and back, for lining up a line chart with a bar chart + , clipEdge = true + , color = nv.utils.defaultColor() + , interactive = false + , xDomain + , yDomain + , xRange + , yRange + , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState', 'renderEnd', 'chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout') + ; + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + function chart(selection) { + selection.each(function(data) { + var container = d3.select(this); + var availableWidth = (width || parseInt(container.style('width')) || 960) + - margin.left - margin.right; + var availableHeight = (height || parseInt(container.style('height')) || 400) + - margin.top - margin.bottom; + + nv.utils.initSVG(container); + + // Setup Scales + x.domain(xDomain || d3.extent(data[0].values.map(getX).concat(forceX) )); + + if (padData) + x.range(xRange || [availableWidth * .5 / data[0].values.length, availableWidth * (data[0].values.length - .5) / data[0].values.length ]); + else + x.range(xRange || [0, availableWidth]); + + y.domain(yDomain || [ + d3.min(data[0].values.map(getLow).concat(forceY)), + d3.max(data[0].values.map(getHigh).concat(forceY)) + ] + ).range(yRange || [availableHeight, 0]); + + // If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point + if (x.domain()[0] === x.domain()[1]) + x.domain()[0] ? + x.domain([x.domain()[0] - x.domain()[0] * 0.01, x.domain()[1] + x.domain()[1] * 0.01]) + : x.domain([-1,1]); + + if (y.domain()[0] === y.domain()[1]) + y.domain()[0] ? + y.domain([y.domain()[0] + y.domain()[0] * 0.01, y.domain()[1] - y.domain()[1] * 0.01]) + : y.domain([-1,1]); + + // Setup containers and skeleton of chart + var wrap = d3.select(this).selectAll('g.nv-wrap.nv-ohlcBar').data([data[0].values]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-ohlcBar'); + var defsEnter = wrapEnter.append('defs'); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-ticks'); + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + container + .on('click', function(d,i) { + dispatch.chartClick({ + data: d, + index: i, + pos: d3.event, + id: id + }); + }); + + defsEnter.append('clipPath') + .attr('id', 'nv-chart-clip-path-' + id) + .append('rect'); + + wrap.select('#nv-chart-clip-path-' + id + ' rect') + .attr('width', availableWidth) + .attr('height', availableHeight); + + g .attr('clip-path', clipEdge ? 'url(#nv-chart-clip-path-' + id + ')' : ''); + + var ticks = wrap.select('.nv-ticks').selectAll('.nv-tick') + .data(function(d) { return d }); + ticks.exit().remove(); + + var ticksEnter = ticks.enter().append('path') + .attr('class', function(d,i,j) { return (getOpen(d,i) > getClose(d,i) ? 'nv-tick negative' : 'nv-tick positive') + ' nv-tick-' + j + '-' + i }) + .attr('d', function(d,i) { + var w = (availableWidth / data[0].values.length) * .9; + return 'm0,0l0,' + + (y(getOpen(d,i)) + - y(getHigh(d,i))) + + 'l' + + (-w/2) + + ',0l' + + (w/2) + + ',0l0,' + + (y(getLow(d,i)) - y(getOpen(d,i))) + + 'l0,' + + (y(getClose(d,i)) + - y(getLow(d,i))) + + 'l' + + (w/2) + + ',0l' + + (-w/2) + + ',0z'; + }) + .attr('transform', function(d,i) { return 'translate(' + x(getX(d,i)) + ',' + y(getHigh(d,i)) + ')'; }) + .attr('fill', function(d,i) { return color[0]; }) + .attr('stroke', function(d,i) { return color[0]; }) + .attr('x', 0 ) + .attr('y', function(d,i) { return y(Math.max(0, getY(d,i))) }) + .attr('height', function(d,i) { return Math.abs(y(getY(d,i)) - y(0)) }); + + // the bar colors are controlled by CSS currently + ticks.attr('class', function(d,i,j) { + return (getOpen(d,i) > getClose(d,i) ? 'nv-tick negative' : 'nv-tick positive') + ' nv-tick-' + j + '-' + i; + }); + + d3.transition(ticks) + .attr('transform', function(d,i) { return 'translate(' + x(getX(d,i)) + ',' + y(getHigh(d,i)) + ')'; }) + .attr('d', function(d,i) { + var w = (availableWidth / data[0].values.length) * .9; + return 'm0,0l0,' + + (y(getOpen(d,i)) + - y(getHigh(d,i))) + + 'l' + + (-w/2) + + ',0l' + + (w/2) + + ',0l0,' + + (y(getLow(d,i)) + - y(getOpen(d,i))) + + 'l0,' + + (y(getClose(d,i)) + - y(getLow(d,i))) + + 'l' + + (w/2) + + ',0l' + + (-w/2) + + ',0z'; + }); + }); + + return chart; + } + + + //Create methods to allow outside functions to highlight a specific bar. + chart.highlightPoint = function(pointIndex, isHoverOver) { + chart.clearHighlights(); + d3.select(".nv-ohlcBar .nv-tick-0-" + pointIndex) + .classed("hover", isHoverOver) + ; + }; + + chart.clearHighlights = function() { + d3.select(".nv-ohlcBar .nv-tick.hover") + .classed("hover", false) + ; + }; + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + xScale: {get: function(){return x;}, set: function(_){x=_;}}, + yScale: {get: function(){return y;}, set: function(_){y=_;}}, + xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}}, + yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}}, + xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}}, + yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}}, + forceX: {get: function(){return forceX;}, set: function(_){forceX=_;}}, + forceY: {get: function(){return forceY;}, set: function(_){forceY=_;}}, + padData: {get: function(){return padData;}, set: function(_){padData=_;}}, + clipEdge: {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}}, + id: {get: function(){return id;}, set: function(_){id=_;}}, + interactive: {get: function(){return interactive;}, set: function(_){interactive=_;}}, + + x: {get: function(){return getX;}, set: function(_){getX=_;}}, + y: {get: function(){return getY;}, set: function(_){getY=_;}}, + open: {get: function(){return getOpen();}, set: function(_){getOpen=_;}}, + close: {get: function(){return getClose();}, set: function(_){getClose=_;}}, + high: {get: function(){return getHigh;}, set: function(_){getHigh=_;}}, + low: {get: function(){return getLow;}, set: function(_){getLow=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top != undefined ? _.top : margin.top; + margin.right = _.right != undefined ? _.right : margin.right; + margin.bottom = _.bottom != undefined ? _.bottom : margin.bottom; + margin.left = _.left != undefined ? _.left : margin.left; + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + }} + }); + + nv.utils.initOptions(chart); + return chart; +}; + +// Code adapted from Jason Davies' "Parallel Coordinates" +// http://bl.ocks.org/jasondavies/1341281 + +nv.models.parallelCoordinates = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 30, right: 10, bottom: 10, left: 10} + , width = null + , height = null + , x = d3.scale.ordinal() + , y = {} + , dimensions = [] + , color = nv.utils.defaultColor() + , filters = [] + , active = [] + , dispatch = d3.dispatch('brush') + ; + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + function chart(selection) { + selection.each(function(data) { + var container = d3.select(this); + var availableWidth = (width || parseInt(container.style('width')) || 960) + - margin.left - margin.right; + var availableHeight = (height || parseInt(container.style('height')) || 400) + - margin.top - margin.bottom; + + nv.utils.initSVG(container); + + active = data; //set all active before first brush call + + //This is a placeholder until this chart is made resizeable + chart.update = function() { }; + + // Setup Scales + x.rangePoints([0, availableWidth], 1).domain(dimensions); + + // Extract the list of dimensions and create a scale for each. + dimensions.forEach(function(d) { + y[d] = d3.scale.linear() + .domain(d3.extent(data, function(p) { return +p[d]; })) + .range([availableHeight, 0]); + + y[d].brush = d3.svg.brush().y(y[d]).on('brush', brush); + + return d != 'name'; + }); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-parallelCoordinates').data([data]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-parallelCoordinates'); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-parallelCoordinatesWrap'); + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + var line = d3.svg.line(), + axis = d3.svg.axis().orient('left'), + background, + foreground; + + // Add grey background lines for context. + background = gEnter.append('g') + .attr('class', 'background') + .selectAll('path') + .data(data) + .enter().append('path') + .attr('d', path) + ; + + // Add blue foreground lines for focus. + foreground = gEnter.append('g') + .attr('class', 'foreground') + .selectAll('path') + .data(data) + .enter().append('path') + .attr('d', path) + .attr('stroke', color) + ; + + // Add a group element for each dimension. + var dimension = g.selectAll('.dimension') + .data(dimensions) + .enter().append('g') + .attr('class', 'dimension') + .attr('transform', function(d) { return 'translate(' + x(d) + ',0)'; }); + + // Add an axis and title. + dimension.append('g') + .attr('class', 'axis') + .each(function(d) { d3.select(this).call(axis.scale(y[d])); }) + .append('text') + .attr('text-anchor', 'middle') + .attr('y', -9) + .text(String); + + // Add and store a brush for each axis. + dimension.append('g') + .attr('class', 'brush') + .each(function(d) { d3.select(this).call(y[d].brush); }) + .selectAll('rect') + .attr('x', -8) + .attr('width', 16); + + // Returns the path for a given data point. + function path(d) { + return line(dimensions.map(function(p) { return [x(p), y[p](d[p])]; })); + } + + // Handles a brush event, toggling the display of foreground lines. + function brush() { + var actives = dimensions.filter(function(p) { return !y[p].brush.empty(); }), + extents = actives.map(function(p) { return y[p].brush.extent(); }); + + filters = []; //erase current filters + actives.forEach(function(d,i) { + filters[i] = { + dimension: d, + extent: extents[i] + } + }); + + active = []; //erase current active list + foreground.style('display', function(d) { + var isActive = actives.every(function(p, i) { + return extents[i][0] <= d[p] && d[p] <= extents[i][1]; + }); + if (isActive) active.push(d); + return isActive ? null : 'none'; + }); + + dispatch.brush({ + filters: filters, + active: active + }); + } + }); + + return chart; + } + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + dimensions: {get: function(){return dimensions;}, set: function(_){dimensions=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = typeof _.top != 'undefined' ? _.top : margin.top; + margin.right = typeof _.right != 'undefined' ? _.right : margin.right; + margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom; + margin.left = typeof _.left != 'undefined' ? _.left : margin.left; + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + }} + }); + + nv.utils.initOptions(chart); + return chart; +}; +nv.models.pie = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 0, right: 0, bottom: 0, left: 0} + , width = 500 + , height = 500 + , getX = function(d) { return d.x } + , getY = function(d) { return d.y } + , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one + , color = nv.utils.defaultColor() + , valueFormat = d3.format(',.2f') + , labelFormat = d3.format('%') + , showLabels = true + , pieLabelsOutside = true + , donutLabelsOutside = false + , labelType = "key" + , labelThreshold = .02 //if slice percentage is under this, don't show label + , donut = false + , title = false + , growOnHover = true + , titleOffset = 0 + , labelSunbeamLayout = false + , startAngle = false + , padAngle = false + , endAngle = false + , cornerRadius = 0 + , donutRatio = 0.5 + , duration = 250 + , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'renderEnd') + ; + + + //============================================================ + // chart function + //------------------------------------------------------------ + + var renderWatch = nv.utils.renderWatch(dispatch); + + function chart(selection) { + renderWatch.reset(); + selection.each(function(data) { + var availableWidth = width - margin.left - margin.right + ,availableHeight = height - margin.top - margin.bottom + ,radius = Math.min(availableWidth, availableHeight) / 2 + ,arcRadius = radius-(radius / 5) + ,container = d3.select(this) + ; + nv.utils.initSVG(container); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('.nv-wrap.nv-pie').data(data); + var wrapEnter = wrap.enter().append('g').attr('class','nvd3 nv-wrap nv-pie nv-chart-' + id); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g'); + var g_pie = gEnter.append('g').attr('class', 'nv-pie'); + gEnter.append('g').attr('class', 'nv-pieLabels'); + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + g.select('.nv-pie').attr('transform', 'translate(' + availableWidth / 2 + ',' + availableHeight / 2 + ')'); + g.select('.nv-pieLabels').attr('transform', 'translate(' + availableWidth / 2 + ',' + availableHeight / 2 + ')'); + + // + container.on('click', function(d,i) { + dispatch.chartClick({ + data: d, + index: i, + pos: d3.event, + id: id + }); + }); + + + var arc = d3.svg.arc().outerRadius(arcRadius); + var arcOver = d3.svg.arc().outerRadius(arcRadius + 5); + + if (startAngle) { + arc.startAngle(startAngle); + arcOver.startAngle(startAngle); + } + if (endAngle) { + arc.endAngle(endAngle); + arcOver.endAngle(endAngle); + } + if (donut) { + arc.innerRadius(radius * donutRatio); + arcOver.innerRadius(radius * donutRatio); + } + + // Setup the Pie chart and choose the data element + var pie = d3.layout.pie() + .sort(null) + .value(function(d) { return d.disabled ? 0 : getY(d) }); + + // padAngle added in d3 3.5 + if (pie.padAngle && padAngle) { + pie.padAngle(padAngle); + } + + if (arc.cornerRadius && cornerRadius) { + arc.cornerRadius(cornerRadius); + arcOver.cornerRadius(cornerRadius); + } + + // if title is specified and donut, put it in the middle + if (donut && title) { + var title_g = g_pie.append('g').attr('class', 'nv-pie'); + + title_g.append("text") + .style("text-anchor", "middle") + .attr('class', 'nv-pie-title') + .text(function (d) { + return title; + }) + .attr("dy", "0.35em") // trick to vertically center text + .attr('transform', function(d, i) { + return 'translate(0, '+ titleOffset + ')'; + }); + } + + var slices = wrap.select('.nv-pie').selectAll('.nv-slice').data(pie); + var pieLabels = wrap.select('.nv-pieLabels').selectAll('.nv-label').data(pie); + + slices.exit().remove(); + pieLabels.exit().remove(); + + var ae = slices.enter().append('g') + ae.attr('class', 'nv-slice') + ae.on('mouseover', function(d,i){ + d3.select(this).classed('hover', true); + if (growOnHover) { + d3.select(this).select("path").transition() + .duration(70) + .attr("d", arcOver); + } + dispatch.elementMouseover({ + label: getX(d.data), + value: getY(d.data), + point: d.data, + pointIndex: i, + pos: [d3.event.pageX, d3.event.pageY], + id: id, + color: d3.select(this).style("fill") + }); + }); + ae.on('mouseout', function(d,i){ + d3.select(this).classed('hover', false); + if (growOnHover) { + d3.select(this).select("path").transition() + .duration(50) + .attr("d", arc); + } + dispatch.elementMouseout({ + label: getX(d.data), + value: getY(d.data), + point: d.data, + index: i, + id: id + }); + }); + + slices.attr('fill', function(d,i) { return color(d, i); }) + slices.attr('stroke', function(d,i) { return color(d, i); }); + + var paths = ae.append('path').each(function(d) { + this._current = d; + }); + + paths.on('click', function(d,i) { + dispatch.elementClick({ + label: getX(d.data), + value: getY(d.data), + point: d.data, + index: i, + pos: d3.event, + id: id + }); + d3.event.stopPropagation(); + }); + paths.on('dblclick', function(d,i) { + dispatch.elementDblClick({ + label: getX(d.data), + value: getY(d.data), + point: d.data, + index: i, + pos: d3.event, + id: id + }); + d3.event.stopPropagation(); + }); + slices.select('path') + .transition() + .attr('d', arc) + .attrTween('d', arcTween); + + if (showLabels) { + // This does the normal label + var labelsArc = d3.svg.arc().innerRadius(0); + + if (pieLabelsOutside){ + var labelsArc = arc; + } + + if (donutLabelsOutside) { + labelsArc = d3.svg.arc().outerRadius(arc.outerRadius()); + } + + pieLabels.enter().append("g").classed("nv-label",true).each(function(d,i) { + var group = d3.select(this); + + group.attr('transform', function(d) { + if (labelSunbeamLayout) { + d.outerRadius = arcRadius + 10; // Set Outer Coordinate + d.innerRadius = arcRadius + 15; // Set Inner Coordinate + var rotateAngle = (d.startAngle + d.endAngle) / 2 * (180 / Math.PI); + if ((d.startAngle+d.endAngle)/2 < Math.PI) { + rotateAngle -= 90; + } else { + rotateAngle += 90; + } + return 'translate(' + labelsArc.centroid(d) + ') rotate(' + rotateAngle + ')'; + } else { + d.outerRadius = radius + 10; // Set Outer Coordinate + d.innerRadius = radius + 15; // Set Inner Coordinate + return 'translate(' + labelsArc.centroid(d) + ')' + } + }); + + group.append('rect') + .style('stroke', '#fff') + .style('fill', '#fff') + .attr("rx", 3) + .attr("ry", 3); + + group.append('text') + .style('text-anchor', labelSunbeamLayout ? ((d.startAngle + d.endAngle) / 2 < Math.PI ? 'start' : 'end') : 'middle') //center the text on it's origin or begin/end if orthogonal aligned + .style('fill', '#000') + + }); + + var labelLocationHash = {}; + var avgHeight = 14; + var avgWidth = 140; + var createHashKey = function(coordinates) { + return Math.floor(coordinates[0]/avgWidth) * avgWidth + ',' + Math.floor(coordinates[1]/avgHeight) * avgHeight; + }; + + pieLabels.watchTransition(renderWatch,'pie labels').attr('transform', function(d) { + if (labelSunbeamLayout) { + d.outerRadius = arcRadius + 10; // Set Outer Coordinate + d.innerRadius = arcRadius + 15; // Set Inner Coordinate + var rotateAngle = (d.startAngle + d.endAngle) / 2 * (180 / Math.PI); + if ((d.startAngle+d.endAngle)/2 < Math.PI) { + rotateAngle -= 90; + } else { + rotateAngle += 90; + } + return 'translate(' + labelsArc.centroid(d) + ') rotate(' + rotateAngle + ')'; + } else { + d.outerRadius = radius + 10; // Set Outer Coordinate + d.innerRadius = radius + 15; // Set Inner Coordinate + + /* + Overlapping pie labels are not good. What this attempts to do is, prevent overlapping. + Each label location is hashed, and if a hash collision occurs, we assume an overlap. + Adjust the label's y-position to remove the overlap. + */ + var center = labelsArc.centroid(d); + if(d.value){ + var hashKey = createHashKey(center); + if (labelLocationHash[hashKey]) { + center[1] -= avgHeight; + } + labelLocationHash[createHashKey(center)] = true; + } + return 'translate(' + center + ')' + } + }); + + pieLabels.select(".nv-label text") + .style('text-anchor', labelSunbeamLayout ? ((d.startAngle + d.endAngle) / 2 < Math.PI ? 'start' : 'end') : 'middle') //center the text on it's origin or begin/end if orthogonal aligned + .text(function(d, i) { + var percent = (d.endAngle - d.startAngle) / (2 * Math.PI); + var labelTypes = { + "key" : getX(d.data), + "value": getY(d.data), + "percent": labelFormat(percent) + }; + return (d.value && percent > labelThreshold) ? labelTypes[labelType] : ''; + }) + ; + } + + + // Computes the angle of an arc, converting from radians to degrees. + function angle(d) { + var a = (d.startAngle + d.endAngle) * 90 / Math.PI - 90; + return a > 90 ? a - 180 : a; + } + + function arcTween(a) { + a.endAngle = isNaN(a.endAngle) ? 0 : a.endAngle; + a.startAngle = isNaN(a.startAngle) ? 0 : a.startAngle; + if (!donut) a.innerRadius = 0; + var i = d3.interpolate(this._current, a); + this._current = i(0); + return function(t) { + return arc(i(t)); + }; + } + }); + + renderWatch.renderEnd('pie immediate'); + return chart; + } + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + showLabels: {get: function(){return showLabels;}, set: function(_){showLabels=_;}}, + title: {get: function(){return title;}, set: function(_){title=_;}}, + titleOffset: {get: function(){return titleOffset;}, set: function(_){titleOffset=_;}}, + labelThreshold: {get: function(){return labelThreshold;}, set: function(_){labelThreshold=_;}}, + labelFormat: {get: function(){return labelFormat;}, set: function(_){labelFormat=_;}}, + valueFormat: {get: function(){return valueFormat;}, set: function(_){valueFormat=_;}}, + x: {get: function(){return getX;}, set: function(_){getX=_;}}, + id: {get: function(){return id;}, set: function(_){id=_;}}, + endAngle: {get: function(){return endAngle;}, set: function(_){endAngle=_;}}, + startAngle: {get: function(){return startAngle;}, set: function(_){startAngle=_;}}, + padAngle: {get: function(){return padAngle;}, set: function(_){padAngle=_;}}, + cornerRadius: {get: function(){return cornerRadius;}, set: function(_){cornerRadius=_;}}, + donutRatio: {get: function(){return donutRatio;}, set: function(_){donutRatio=_;}}, + pieLabelsOutside: {get: function(){return pieLabelsOutside;}, set: function(_){pieLabelsOutside=_;}}, + donutLabelsOutside: {get: function(){return donutLabelsOutside;}, set: function(_){donutLabelsOutside=_;}}, + labelSunbeamLayout: {get: function(){return labelSunbeamLayout;}, set: function(_){labelSunbeamLayout=_;}}, + donut: {get: function(){return donut;}, set: function(_){donut=_;}}, + growOnHover: {get: function(){return growOnHover;}, set: function(_){growOnHover=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = typeof _.top != 'undefined' ? _.top : margin.top; + margin.right = typeof _.right != 'undefined' ? _.right : margin.right; + margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom; + margin.left = typeof _.left != 'undefined' ? _.left : margin.left; + }}, + y: {get: function(){return getY;}, set: function(_){ + getY=d3.functor(_); + }}, + color: {get: function(){return color;}, set: function(_){ + color=nv.utils.getColor(_); + }}, + labelType: {get: function(){return labelType;}, set: function(_){ + labelType= _ || 'key'; + }} + }); + + nv.utils.initOptions(chart); + return chart; +}; +nv.models.pieChart = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var pie = nv.models.pie(); + var legend = nv.models.legend(); + + var margin = {top: 30, right: 20, bottom: 20, left: 20} + , width = null + , height = null + , showLegend = true + , color = nv.utils.defaultColor() + , tooltips = true + , tooltip = function(key, y, e, graph) { + return '

' + key + '

' + + '

' + y + '

'; + } + , state = nv.utils.state() + , defaultState = null + , noData = "No Data Available." + , duration = 250 + , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState','renderEnd') + ; + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var showTooltip = function(e, offsetElement) { + var tooltipLabel = pie.x()(e.point); + var left = e.pos[0] + ( (offsetElement && offsetElement.offsetLeft) || 0 ), + top = e.pos[1] + ( (offsetElement && offsetElement.offsetTop) || 0), + y = pie.valueFormat()(pie.y()(e.point)), + content = tooltip(tooltipLabel, y, e, chart) + ; + nv.tooltip.show([left, top], content, e.value < 0 ? 'n' : 's', null, offsetElement); + }; + + var renderWatch = nv.utils.renderWatch(dispatch); + + var stateGetter = function(data) { + return function(){ + return { + active: data.map(function(d) { return !d.disabled }) + }; + } + }; + + var stateSetter = function(data) { + return function(state) { + if (state.active !== undefined) { + data.forEach(function (series, i) { + series.disabled = !state.active[i]; + }); + } + } + }; + + //============================================================ + // Chart function + //------------------------------------------------------------ + + function chart(selection) { + renderWatch.reset(); + renderWatch.models(pie); + + selection.each(function(data) { + var container = d3.select(this); + nv.utils.initSVG(container); + + var that = this; + var availableWidth = (width || parseInt(container.style('width'), 10) || 960) + - margin.left - margin.right, + availableHeight = (height || parseInt(container.style('height'), 10) || 400) + - margin.top - margin.bottom + ; + + chart.update = function() { container.transition().call(chart); }; + chart.container = this; + + state.setter(stateSetter(data), chart.update) + .getter(stateGetter(data)) + .update(); + + //set state.disabled + state.disabled = data.map(function(d) { return !!d.disabled }); + + if (!defaultState) { + var key; + defaultState = {}; + for (key in state) { + if (state[key] instanceof Array) + defaultState[key] = state[key].slice(0); + else + defaultState[key] = state[key]; + } + } + + // Display No Data message if there's nothing to show. + if (!data || !data.length) { + var noDataText = container.selectAll('.nv-noData').data([noData]); + + noDataText.enter().append('text') + .attr('class', 'nvd3 nv-noData') + .attr('dy', '-.7em') + .style('text-anchor', 'middle'); + + noDataText + .attr('x', margin.left + availableWidth / 2) + .attr('y', margin.top + availableHeight / 2) + .text(function(d) { return d }); + + return chart; + } else { + container.selectAll('.nv-noData').remove(); + } + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-pieChart').data([data]); + var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-pieChart').append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-pieWrap'); + gEnter.append('g').attr('class', 'nv-legendWrap'); + + // Legend + if (showLegend) { + legend.width( availableWidth ).key(pie.x()); + + wrap.select('.nv-legendWrap') + .datum(data) + .call(legend); + + if ( margin.top != legend.height()) { + margin.top = legend.height(); + availableHeight = (height || parseInt(container.style('height')) || 400) + - margin.top - margin.bottom; + } + + wrap.select('.nv-legendWrap') + .attr('transform', 'translate(0,' + (-margin.top) +')'); + } + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + // Main Chart Component(s) + pie.width(availableWidth).height(availableHeight); + var pieWrap = g.select('.nv-pieWrap').datum([data]); + d3.transition(pieWrap).call(pie); + + // Event Handling/Dispatching (in chart's scope) + legend.dispatch.on('stateChange', function(newState) { + for (var key in newState) { + state[key] = newState[key]; + } + dispatch.stateChange(state); + chart.update(); + }); + + pie.dispatch.on('elementMouseout.tooltip', function(e) { + dispatch.tooltipHide(e); + }); + + // Update chart from a state object passed to event handler + dispatch.on('changeState', function(e) { + if (typeof e.disabled !== 'undefined') { + data.forEach(function(series,i) { + series.disabled = e.disabled[i]; + }); + state.disabled = e.disabled; + } + chart.update(); + }); + + }); + + renderWatch.renderEnd('pieChart immediate'); + return chart; + } + + //============================================================ + // Event Handling/Dispatching (out of chart's scope) + //------------------------------------------------------------ + + pie.dispatch.on('elementMouseover.tooltip', function(e) { + e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; + dispatch.tooltipShow(e); + }); + + dispatch.on('tooltipShow', function(e) { + if (tooltips) showTooltip(e); + }); + + dispatch.on('tooltipHide', function() { + if (tooltips) nv.tooltip.cleanup(); + }); + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + // expose chart's sub-components + chart.legend = legend; + chart.dispatch = dispatch; + chart.pie = pie; + chart.options = nv.utils.optionsFunc.bind(chart); + + // use Object get/set functionality to map between vars and chart functions + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + noData: {get: function(){return noData;}, set: function(_){noData=_;}}, + tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, + tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, + showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, + defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, + // options that require extra logic in the setter + color: {get: function(){return color;}, set: function(_){ + color = _; + legend.color(color); + pie.color(color); + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration = _; + renderWatch.reset(duration); + }} + }); + nv.utils.inheritOptions(chart, pie); + nv.utils.initOptions(chart); + return chart; +}; + +nv.models.scatter = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 0, right: 0, bottom: 0, left: 0} + , width = null + , height = null + , color = nv.utils.defaultColor() // chooses color + , id = Math.floor(Math.random() * 100000) //Create semi-unique ID incase user doesn't select one + , x = d3.scale.linear() + , y = d3.scale.linear() + , z = d3.scale.linear() //linear because d3.svg.shape.size is treated as area + , getX = function(d) { return d.x } // accessor to get the x value + , getY = function(d) { return d.y } // accessor to get the y value + , getSize = function(d) { return d.size || 1} // accessor to get the point size + , getShape = function(d) { return d.shape || 'circle' } // accessor to get point shape + , forceX = [] // List of numbers to Force into the X scale (ie. 0, or a max / min, etc.) + , forceY = [] // List of numbers to Force into the Y scale + , forceSize = [] // List of numbers to Force into the Size scale + , interactive = true // If true, plots a voronoi overlay for advanced point intersection + , pointActive = function(d) { return !d.notActive } // any points that return false will be filtered out + , padData = false // If true, adds half a data points width to front and back, for lining up a line chart with a bar chart + , padDataOuter = .1 //outerPadding to imitate ordinal scale outer padding + , clipEdge = false // if true, masks points within x and y scale + , clipVoronoi = true // if true, masks each point with a circle... can turn off to slightly increase performance + , clipRadius = function() { return 25 } // function to get the radius for voronoi point clips + , xDomain = null // Override x domain (skips the calculation from data) + , yDomain = null // Override y domain + , xRange = null // Override x range + , yRange = null // Override y range + , sizeDomain = null // Override point size domain + , sizeRange = null + , singlePoint = false + , dispatch = d3.dispatch('elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'renderEnd') + , useVoronoi = true + , duration = 250 + ; + + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var x0, y0, z0 // used to store previous scales + , timeoutID + , needsUpdate = false // Flag for when the points are visually updating, but the interactive layer is behind, to disable tooltips + , renderWatch = nv.utils.renderWatch(dispatch, duration) + ; + + function chart(selection) { + renderWatch.reset(); + selection.each(function(data) { + var container = d3.select(this); + var availableWidth = (width || parseInt(container.style('width')) || 960) + - margin.left - margin.right; + var availableHeight = (height || parseInt(container.style('height')) || 400) + - margin.top - margin.bottom; + + nv.utils.initSVG(container); + + //add series index to each data point for reference + data.forEach(function(series, i) { + series.values.forEach(function(point) { + point.series = i; + }); + }); + + // Setup Scales + // remap and flatten the data for use in calculating the scales' domains + var seriesData = (xDomain && yDomain && sizeDomain) ? [] : // if we know xDomain and yDomain and sizeDomain, no need to calculate.... if Size is constant remember to set sizeDomain to speed up performance + d3.merge( + data.map(function(d) { + return d.values.map(function(d,i) { + return { x: getX(d,i), y: getY(d,i), size: getSize(d,i) } + }) + }) + ); + + x .domain(xDomain || d3.extent(seriesData.map(function(d) { return d.x; }).concat(forceX))) + + if (padData && data[0]) + x.range(xRange || [(availableWidth * padDataOuter + availableWidth) / (2 *data[0].values.length), availableWidth - availableWidth * (1 + padDataOuter) / (2 * data[0].values.length) ]); + //x.range([availableWidth * .5 / data[0].values.length, availableWidth * (data[0].values.length - .5) / data[0].values.length ]); + else + x.range(xRange || [0, availableWidth]); + + y .domain(yDomain || d3.extent(seriesData.map(function(d) { return d.y }).concat(forceY))) + .range(yRange || [availableHeight, 0]); + + z .domain(sizeDomain || d3.extent(seriesData.map(function(d) { return d.size }).concat(forceSize))) + .range(sizeRange || [16, 256]); + + // If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point + if (x.domain()[0] === x.domain()[1] || y.domain()[0] === y.domain()[1]) singlePoint = true; + if (x.domain()[0] === x.domain()[1]) + x.domain()[0] ? + x.domain([x.domain()[0] - x.domain()[0] * 0.01, x.domain()[1] + x.domain()[1] * 0.01]) + : x.domain([-1,1]); + + if (y.domain()[0] === y.domain()[1]) + y.domain()[0] ? + y.domain([y.domain()[0] - y.domain()[0] * 0.01, y.domain()[1] + y.domain()[1] * 0.01]) + : y.domain([-1,1]); + + if ( isNaN(x.domain()[0])) { + x.domain([-1,1]); + } + + if ( isNaN(y.domain()[0])) { + y.domain([-1,1]); + } + + x0 = x0 || x; + y0 = y0 || y; + z0 = z0 || z; + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-scatter').data([data]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-scatter nv-chart-' + id + (singlePoint ? ' nv-single-point' : '')); + var defsEnter = wrapEnter.append('defs'); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-groups'); + gEnter.append('g').attr('class', 'nv-point-paths'); + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + defsEnter.append('clipPath') + .attr('id', 'nv-edge-clip-' + id) + .append('rect'); + + wrap.select('#nv-edge-clip-' + id + ' rect') + .attr('width', availableWidth) + .attr('height', (availableHeight > 0) ? availableHeight : 0); + + g.attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + id + ')' : ''); + + function updateInteractiveLayer() { + + if (!interactive) return false; + + var eventElements; + + var vertices = d3.merge(data.map(function(group, groupIndex) { + return group.values + .map(function(point, pointIndex) { + // *Adding noise to make duplicates very unlikely + // *Injecting series and point index for reference + /* *Adding a 'jitter' to the points, because there's an issue in d3.geom.voronoi. + */ + var pX = getX(point,pointIndex); + var pY = getY(point,pointIndex); + + return [x(pX)+ Math.random() * 1e-7, + y(pY)+ Math.random() * 1e-7, + groupIndex, + pointIndex, point]; //temp hack to add noise untill I think of a better way so there are no duplicates + }) + .filter(function(pointArray, pointIndex) { + return pointActive(pointArray[4], pointIndex); // Issue #237.. move filter to after map, so pointIndex is correct! + }) + }) + ); + + //inject series and point index for reference into voronoi + if (useVoronoi === true) { + + if(vertices.length < 3) { + // Issue #283 - Adding 2 dummy points to the voronoi b/c voronoi requires min 3 points to work + vertices.push([x.range()[0] - 20, y.range()[0] - 20, null, null]); + vertices.push([x.range()[1] + 20, y.range()[1] + 20, null, null]); + vertices.push([x.range()[0] - 20, y.range()[0] + 20, null, null]); + vertices.push([x.range()[1] + 20, y.range()[1] - 20, null, null]); + } + + // keep voronoi sections from going more than 10 outside of graph + // to avoid overlap with other things like legend etc + var bounds = d3.geom.polygon([ + [-10,-10], + [-10,height + 10], + [width + 10,height + 10], + [width + 10,-10] + ]); + + var voronoi = d3.geom.voronoi(vertices).map(function(d, i) { + return { + 'data': bounds.clip(d), + 'series': vertices[i][2], + 'point': vertices[i][3] + } + }); + + // nuke all voronoi paths on reload and recreate them + wrap.select('.nv-point-paths').selectAll('path').remove(); + var pointPaths = wrap.select('.nv-point-paths').selectAll('path').data(voronoi); + pointPaths + .enter().append("svg:path") + .attr("d", function(d) { + if (!d || !d.data || d.data.length === 0) + return 'M 0 0'; + else + return "M" + d.data.join(",") + "Z"; + }) + .attr("id", function(d,i) { + return "nv-path-"+i; }) + .attr("clip-path", function(d,i) { return "url(#nv-clip-"+i+")"; }) + ; + // chain these to above to see the voronoi elements (good for debugging) + //.style("fill", d3.rgb(230, 230, 230)) + //.style('fill-opacity', 0.4) + //.style('stroke-opacity', 1) + //.style("stroke", d3.rgb(200,200,200)); + + if (clipVoronoi) { + // voronoi sections are already set to clip, + // just create the circles with the IDs they expect + var clips = wrap.append("svg:g").attr("id", "nv-point-clips"); + clips.selectAll("clipPath") + .data(vertices) + .enter().append("svg:clipPath") + .attr("id", function(d, i) { return "nv-clip-"+i;}) + .append("svg:circle") + .attr('cx', function(d) { return d[0]; }) + .attr('cy', function(d) { return d[1]; }) + .attr('r', clipRadius); + } + + var mouseEventCallback = function(d,mDispatch) { + if (needsUpdate) return 0; + var series = data[d.series]; + if (typeof series === 'undefined') return; + var point = series.values[d.point]; + + mDispatch({ + point: point, + series: series, + pos: [x(getX(point, d.point)) + margin.left, y(getY(point, d.point)) + margin.top], + seriesIndex: d.series, + pointIndex: d.point + }); + }; + + pointPaths + .on('click', function(d) { + mouseEventCallback(d, dispatch.elementClick); + }) + .on('dblclick', function(d) { + mouseEventCallback(d, dispatch.elementDblClick); + }) + .on('mouseover', function(d) { + mouseEventCallback(d, dispatch.elementMouseover); + }) + .on('mouseout', function(d, i) { + mouseEventCallback(d, dispatch.elementMouseout); + }); + + } else { + /* + // bring data in form needed for click handlers + var dataWithPoints = vertices.map(function(d, i) { + return { + 'data': d, + 'series': vertices[i][2], + 'point': vertices[i][3] + } + }); + */ + + // add event handlers to points instead voronoi paths + wrap.select('.nv-groups').selectAll('.nv-group') + .selectAll('.nv-point') + //.data(dataWithPoints) + //.style('pointer-events', 'auto') // recativate events, disabled by css + .on('click', function(d,i) { + //nv.log('test', d, i); + if (needsUpdate || !data[d.series]) return 0; //check if this is a dummy point + var series = data[d.series], + point = series.values[i]; + + dispatch.elementClick({ + point: point, + series: series, + pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top], + seriesIndex: d.series, + pointIndex: i + }); + }) + .on('mouseover', function(d,i) { + if (needsUpdate || !data[d.series]) return 0; //check if this is a dummy point + var series = data[d.series], + point = series.values[i]; + + dispatch.elementMouseover({ + point: point, + series: series, + pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top], + seriesIndex: d.series, + pointIndex: i + }); + }) + .on('mouseout', function(d,i) { + if (needsUpdate || !data[d.series]) return 0; //check if this is a dummy point + var series = data[d.series], + point = series.values[i]; + + dispatch.elementMouseout({ + point: point, + series: series, + seriesIndex: d.series, + pointIndex: i + }); + }); + } + + needsUpdate = false; + } + + needsUpdate = true; + var groups = wrap.select('.nv-groups').selectAll('.nv-group') + .data(function(d) { return d }, function(d) { return d.key }); + groups.enter().append('g') + .style('stroke-opacity', 1e-6) + .style('fill-opacity', 1e-6); + groups.exit() + .remove(); + groups + .attr('class', function(d,i) { return 'nv-group nv-series-' + i }) + .classed('hover', function(d) { return d.hover }); + groups.watchTransition(renderWatch, 'scatter: groups') + .style('fill', function(d,i) { return color(d, i) }) + .style('stroke', function(d,i) { return color(d, i) }) + .style('stroke-opacity', 1) + .style('fill-opacity', .5); + + // create the points + var points = groups.selectAll('path.nv-point') + .data(function(d) { return d.values }); + points.enter().append('path') + .style('fill', function (d,i) { return d.color }) + .style('stroke', function (d,i) { return d.color }) + .attr('transform', function(d,i) { + return 'translate(' + x0(getX(d,i)) + ',' + y0(getY(d,i)) + ')' + }) + .attr('d', + nv.utils.symbol() + .type(getShape) + .size(function(d,i) { return z(getSize(d,i)) }) + ); + points.exit().remove(); + groups.exit().selectAll('path.nv-point') + .watchTransition(renderWatch, 'scatter exit') + .attr('transform', function(d,i) { + return 'translate(' + x(getX(d,i)) + ',' + y(getY(d,i)) + ')' + }) + .remove(); + points.each(function(d,i) { + d3.select(this) + .classed('nv-point', true) + .classed('nv-point-' + i, true) + .classed('hover',false) + ; + }); + points + .watchTransition(renderWatch, 'scatter points') + .attr('transform', function(d,i) { + //nv.log(d,i,getX(d,i), x(getX(d,i))); + return 'translate(' + x(getX(d,i)) + ',' + y(getY(d,i)) + ')' + }) + .attr('d', + nv.utils.symbol() + .type(getShape) + .size(function(d,i) { return z(getSize(d,i)) }) + ); + + // Delay updating the invisible interactive layer for smoother animation + clearTimeout(timeoutID); // stop repeat calls to updateInteractiveLayer + timeoutID = setTimeout(updateInteractiveLayer, 300); + //updateInteractiveLayer(); + + //store old scales for use in transitions on update + x0 = x.copy(); + y0 = y.copy(); + z0 = z.copy(); + + }); + renderWatch.renderEnd('scatter immediate'); + return chart; + } + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.options = nv.utils.optionsFunc.bind(chart); + + // utility function calls provided by this chart + chart._calls = new function() { + this.clearHighlights = function () { + d3.selectAll(".nv-chart-" + id + " .nv-point.hover").classed("hover", false); + return null; + }; + this.highlightPoint = function (seriesIndex, pointIndex, isHoverOver) { + d3.select(".nv-chart-" + id + " .nv-series-" + seriesIndex + " .nv-point-" + pointIndex) + .classed("hover", isHoverOver); + }; + }; + + // trigger calls from events too + dispatch.on('elementMouseover.point', function(d) { + if (interactive) chart._calls.highlightPoint(d.seriesIndex,d.pointIndex,true); + }); + + dispatch.on('elementMouseout.point', function(d) { + if (interactive) chart._calls.highlightPoint(d.seriesIndex,d.pointIndex,false); + }); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + xScale: {get: function(){return x;}, set: function(_){x=_;}}, + yScale: {get: function(){return y;}, set: function(_){y=_;}}, + pointScale: {get: function(){return z;}, set: function(_){z=_;}}, + xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}}, + yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}}, + pointDomain: {get: function(){return sizeDomain;}, set: function(_){sizeDomain=_;}}, + xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}}, + yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}}, + pointRange: {get: function(){return sizeRange;}, set: function(_){sizeRange=_;}}, + forceX: {get: function(){return forceX;}, set: function(_){forceX=_;}}, + forceY: {get: function(){return forceY;}, set: function(_){forceY=_;}}, + forcePoint: {get: function(){return forceSize;}, set: function(_){forceSize=_;}}, + interactive: {get: function(){return interactive;}, set: function(_){interactive=_;}}, + pointActive: {get: function(){return pointActive;}, set: function(_){pointActive=_;}}, + padDataOuter: {get: function(){return padDataOuter;}, set: function(_){padDataOuter=_;}}, + padData: {get: function(){return padData;}, set: function(_){padData=_;}}, + clipEdge: {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}}, + clipVoronoi: {get: function(){return clipVoronoi;}, set: function(_){clipVoronoi=_;}}, + clipRadius: {get: function(){return clipRadius;}, set: function(_){clipRadius=_;}}, + id: {get: function(){return id;}, set: function(_){id=_;}}, + + + // simple functor options + x: {get: function(){return getX;}, set: function(_){getX = d3.functor(_);}}, + y: {get: function(){return getY;}, set: function(_){getY = d3.functor(_);}}, + pointSize: {get: function(){return getSize;}, set: function(_){getSize = d3.functor(_);}}, + pointShape: {get: function(){return getShape;}, set: function(_){getShape = d3.functor(_);}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration = _; + renderWatch.reset(duration); + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + }}, + useVoronoi: {get: function(){return useVoronoi;}, set: function(_){ + useVoronoi = _; + if (useVoronoi === false) { + clipVoronoi = false; + } + }} + }); + + nv.utils.initOptions(chart); + return chart; +}; + +nv.models.scatterChart = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var scatter = nv.models.scatter() + , xAxis = nv.models.axis() + , yAxis = nv.models.axis() + , legend = nv.models.legend() + , distX = nv.models.distribution() + , distY = nv.models.distribution() + ; + + var margin = {top: 30, right: 20, bottom: 50, left: 75} + , width = null + , height = null + , color = nv.utils.defaultColor() + , x = scatter.xScale() + , y = scatter.yScale() + , showDistX = false + , showDistY = false + , showLegend = true + , showXAxis = true + , showYAxis = true + , rightAlignYAxis = false + , tooltips = true + , tooltipX = function(key, x, y) { return '' + x + '' } + , tooltipY = function(key, x, y) { return '' + y + '' } + , tooltip = function(key, x, y, date) { return '

' + key + '

' + + '

' + date + '

' } + , state = nv.utils.state() + , defaultState = null + , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState', 'renderEnd') + , noData = "No Data Available." + , duration = 250 + ; + + scatter + .xScale(x) + .yScale(y) + ; + xAxis + .orient('bottom') + .tickPadding(10) + ; + yAxis + .orient((rightAlignYAxis) ? 'right' : 'left') + .tickPadding(10) + ; + distX + .axis('x') + ; + distY + .axis('y') + ; + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var x0, y0 + , renderWatch = nv.utils.renderWatch(dispatch, duration); + + var showTooltip = function(e, offsetElement) { + //TODO: make tooltip style an option between single or dual on axes (maybe on all charts with axes? + var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ), + top = e.pos[1] + ( offsetElement.offsetTop || 0), + leftX = e.pos[0] + ( offsetElement.offsetLeft || 0 ), + topX = y.range()[0] + margin.top + ( offsetElement.offsetTop || 0), + leftY = x.range()[0] + margin.left + ( offsetElement.offsetLeft || 0 ), + topY = e.pos[1] + ( offsetElement.offsetTop || 0), + xVal = xAxis.tickFormat()(scatter.x()(e.point, e.pointIndex)), + yVal = yAxis.tickFormat()(scatter.y()(e.point, e.pointIndex)); + + if( tooltipX != null ) + nv.tooltip.show([leftX, topX], tooltipX(e.series.key, xVal, yVal, e, chart), 'n', 1, offsetElement, 'x-nvtooltip'); + if( tooltipY != null ) + nv.tooltip.show([leftY, topY], tooltipY(e.series.key, xVal, yVal, e, chart), 'e', 1, offsetElement, 'y-nvtooltip'); + if( tooltip != null ) + nv.tooltip.show([left, top], tooltip(e.series.key, xVal, yVal, e.point.tooltip, e, chart), e.value < 0 ? 'n' : 's', null, offsetElement); + }; + + var stateGetter = function(data) { + return function(){ + return { + active: data.map(function(d) { return !d.disabled }) + }; + } + }; + + var stateSetter = function(data) { + return function(state) { + if (state.active !== undefined) + data.forEach(function(series,i) { + series.disabled = !state.active[i]; + }); + } + }; + + function chart(selection) { + renderWatch.reset(); + renderWatch.models(scatter); + if (showXAxis) renderWatch.models(xAxis); + if (showYAxis) renderWatch.models(yAxis); + if (showDistX) renderWatch.models(distX); + if (showDistY) renderWatch.models(distY); + + selection.each(function(data) { + var container = d3.select(this), + that = this; + nv.utils.initSVG(container); + + var availableWidth = (width || parseInt(container.style('width')) || 960) + - margin.left - margin.right, + availableHeight = (height || parseInt(container.style('height')) || 400) + - margin.top - margin.bottom; + + chart.update = function() { + if (duration === 0) + container.call(chart); + else + container.transition().duration(duration).call(chart); + }; + chart.container = this; + + state + .setter(stateSetter(data), chart.update) + .getter(stateGetter(data)) + .update(); + + // DEPRECATED set state.disableddisabled + state.disabled = data.map(function(d) { return !!d.disabled }); + + if (!defaultState) { + var key; + defaultState = {}; + for (key in state) { + if (state[key] instanceof Array) + defaultState[key] = state[key].slice(0); + else + defaultState[key] = state[key]; + } + } + + // Display noData message if there's nothing to show. + if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { + var noDataText = container.selectAll('.nv-noData').data([noData]); + + noDataText.enter().append('text') + .attr('class', 'nvd3 nv-noData') + .attr('dy', '-.7em') + .style('text-anchor', 'middle'); + + noDataText + .attr('x', margin.left + availableWidth / 2) + .attr('y', margin.top + availableHeight / 2) + .text(function(d) { return d }); + + renderWatch.renderEnd('scatter immediate'); + + return chart; + } else { + container.selectAll('.nv-noData').remove(); + } + + // Setup Scales + x = scatter.xScale(); + y = scatter.yScale(); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-scatterChart').data([data]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-scatterChart nv-chart-' + scatter.id()); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g'); + + // background for pointer events + gEnter.append('rect').attr('class', 'nvd3 nv-background').style("pointer-events","none"); + + gEnter.append('g').attr('class', 'nv-x nv-axis'); + gEnter.append('g').attr('class', 'nv-y nv-axis'); + gEnter.append('g').attr('class', 'nv-scatterWrap'); + gEnter.append('g').attr('class', 'nv-regressionLinesWrap'); + gEnter.append('g').attr('class', 'nv-distWrap'); + gEnter.append('g').attr('class', 'nv-legendWrap'); + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + if (rightAlignYAxis) { + g.select(".nv-y.nv-axis") + .attr("transform", "translate(" + availableWidth + ",0)"); + } + + // Legend + if (showLegend) { + legend.width( availableWidth / 2 ); + + wrap.select('.nv-legendWrap') + .datum(data) + .call(legend); + + if ( margin.top != legend.height()) { + margin.top = legend.height(); + availableHeight = (height || parseInt(container.style('height')) || 400) + - margin.top - margin.bottom; + } + + wrap.select('.nv-legendWrap') + .attr('transform', 'translate(' + (availableWidth / 2) + ',' + (-margin.top) +')'); + } + + // Main Chart Component(s) + scatter + .width(availableWidth) + .height(availableHeight) + .color(data.map(function(d,i) { + return d.color || color(d, i); + }).filter(function(d,i) { return !data[i].disabled })); + + wrap.select('.nv-scatterWrap') + .datum(data.filter(function(d) { return !d.disabled })) + .call(scatter); + + + wrap.select('.nv-regressionLinesWrap') + .attr('clip-path', 'url(#nv-edge-clip-' + scatter.id() + ')'); + + var regWrap = wrap.select('.nv-regressionLinesWrap').selectAll('.nv-regLines') + .data(function (d) { + return d; + }); + + regWrap.enter().append('g').attr('class', 'nv-regLines'); + + var regLine = regWrap.selectAll('.nv-regLine') + .data(function (d) { + return [d] + }); + + regLine.enter() + .append('line').attr('class', 'nv-regLine') + .style('stroke-opacity', 0); + + // don't add lines unless we have slope and intercept to use + regLine.filter(function(d) { + return d.intercept && d.slope; + }) + .watchTransition(renderWatch, 'scatterPlusLineChart: regline') + .attr('x1', x.range()[0]) + .attr('x2', x.range()[1]) + .attr('y1', function (d, i) { + return y(x.domain()[0] * d.slope + d.intercept) + }) + .attr('y2', function (d, i) { + return y(x.domain()[1] * d.slope + d.intercept) + }) + .style('stroke', function (d, i, j) { + return color(d, j) + }) + .style('stroke-opacity', function (d, i) { + return (d.disabled || typeof d.slope === 'undefined' || typeof d.intercept === 'undefined') ? 0 : 1 + }); + + // Setup Axes + if (showXAxis) { + xAxis + .scale(x) + .ticks( xAxis.ticks() ? xAxis.ticks() : nv.utils.calcTicksX(availableWidth/100, data) ) + .tickSize( -availableHeight , 0); + + g.select('.nv-x.nv-axis') + .attr('transform', 'translate(0,' + y.range()[0] + ')') + .call(xAxis); + } + + if (showYAxis) { + yAxis + .scale(y) + .ticks( yAxis.ticks() ? yAxis.ticks() : nv.utils.calcTicksY(availableHeight/36, data) ) + .tickSize( -availableWidth, 0); + + g.select('.nv-y.nv-axis') + .call(yAxis); + } + + + if (showDistX) { + distX + .getData(scatter.x()) + .scale(x) + .width(availableWidth) + .color(data.map(function(d,i) { + return d.color || color(d, i); + }).filter(function(d,i) { return !data[i].disabled })); + gEnter.select('.nv-distWrap').append('g') + .attr('class', 'nv-distributionX'); + g.select('.nv-distributionX') + .attr('transform', 'translate(0,' + y.range()[0] + ')') + .datum(data.filter(function(d) { return !d.disabled })) + .call(distX); + } + + if (showDistY) { + distY + .getData(scatter.y()) + .scale(y) + .width(availableHeight) + .color(data.map(function(d,i) { + return d.color || color(d, i); + }).filter(function(d,i) { return !data[i].disabled })); + gEnter.select('.nv-distWrap').append('g') + .attr('class', 'nv-distributionY'); + g.select('.nv-distributionY') + .attr('transform', 'translate(' + (rightAlignYAxis ? availableWidth : -distY.size() ) + ',0)') + .datum(data.filter(function(d) { return !d.disabled })) + .call(distY); + } + + //============================================================ + // Event Handling/Dispatching (in chart's scope) + //------------------------------------------------------------ + + legend.dispatch.on('stateChange', function(newState) { + for (var key in newState) + state[key] = newState[key]; + dispatch.stateChange(state); + chart.update(); + }); + + + scatter.dispatch.on('elementMouseover.tooltip', function(e) { + d3.select('.nv-chart-' + scatter.id() + ' .nv-series-' + e.seriesIndex + ' .nv-distx-' + e.pointIndex) + .attr('y1', e.pos[1] - availableHeight); + d3.select('.nv-chart-' + scatter.id() + ' .nv-series-' + e.seriesIndex + ' .nv-disty-' + e.pointIndex) + .attr('x2', e.pos[0] + distX.size()); + + e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; + dispatch.tooltipShow(e); + }); + + dispatch.on('tooltipShow', function(e) { + if (tooltips) showTooltip(e, that.parentNode); + }); + + // Update chart from a state object passed to event handler + dispatch.on('changeState', function(e) { + + if (typeof e.disabled !== 'undefined') { + data.forEach(function(series,i) { + series.disabled = e.disabled[i]; + }); + + state.disabled = e.disabled; + } + + chart.update(); + }); + + //store old scales for use in transitions on update + x0 = x.copy(); + y0 = y.copy(); + + }); + + renderWatch.renderEnd('scatter with line immediate'); + return chart; + } + + //============================================================ + // Event Handling/Dispatching (out of chart's scope) + //------------------------------------------------------------ + + scatter.dispatch.on('elementMouseout.tooltip', function(e) { + dispatch.tooltipHide(e); + + d3.select('.nv-chart-' + scatter.id() + ' .nv-series-' + e.seriesIndex + ' .nv-distx-' + e.pointIndex) + .attr('y1', 0); + d3.select('.nv-chart-' + scatter.id() + ' .nv-series-' + e.seriesIndex + ' .nv-disty-' + e.pointIndex) + .attr('x2', distY.size()); + }); + dispatch.on('tooltipHide', function() { + if (tooltips) nv.tooltip.cleanup(); + }); + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + // expose chart's sub-components + chart.dispatch = dispatch; + chart.scatter = scatter; + chart.legend = legend; + chart.xAxis = xAxis; + chart.yAxis = yAxis; + chart.distX = distX; + chart.distY = distY; + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + showDistX: {get: function(){return showDistX;}, set: function(_){showDistX=_;}}, + showDistY: {get: function(){return showDistY;}, set: function(_){showDistY=_;}}, + showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, + showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}}, + showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}}, + tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, + tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, + tooltipXContent: {get: function(){return tooltipX;}, set: function(_){tooltipX=_;}}, + tooltipYContent: {get: function(){return tooltipY;}, set: function(_){tooltipY=_;}}, + defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, + noData: {get: function(){return noData;}, set: function(_){noData=_;}}, + duration: {get: function(){return duration;}, set: function(_){duration=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){ + rightAlignYAxis = _; + yAxis.orient( (_) ? 'right' : 'left'); + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + legend.color(color); + distX.color(color); + distY.color(color); + }} + }); + + nv.utils.inheritOptions(chart, scatter); + nv.utils.initOptions(chart); + return chart; +}; + +nv.models.sparkline = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 2, right: 0, bottom: 2, left: 0} + , width = 400 + , height = 32 + , animate = true + , x = d3.scale.linear() + , y = d3.scale.linear() + , getX = function(d) { return d.x } + , getY = function(d) { return d.y } + , color = nv.utils.getColor(['#000']) + , xDomain + , yDomain + , xRange + , yRange + ; + + function chart(selection) { + selection.each(function(data) { + var availableWidth = width - margin.left - margin.right, + availableHeight = height - margin.top - margin.bottom, + container = d3.select(this); + nv.utils.initSVG(container); + + // Setup Scales + x .domain(xDomain || d3.extent(data, getX )) + .range(xRange || [0, availableWidth]); + + y .domain(yDomain || d3.extent(data, getY )) + .range(yRange || [availableHeight, 0]); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-sparkline').data([data]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-sparkline'); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g'); + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')') + + var paths = wrap.selectAll('path') + .data(function(d) { return [d] }); + paths.enter().append('path'); + paths.exit().remove(); + paths + .style('stroke', function(d,i) { return d.color || color(d, i) }) + .attr('d', d3.svg.line() + .x(function(d,i) { return x(getX(d,i)) }) + .y(function(d,i) { return y(getY(d,i)) }) + ); + + // TODO: Add CURRENT data point (Need Min, Mac, Current / Most recent) + var points = wrap.selectAll('circle.nv-point') + .data(function(data) { + var yValues = data.map(function(d, i) { return getY(d,i); }); + function pointIndex(index) { + if (index != -1) { + var result = data[index]; + result.pointIndex = index; + return result; + } else { + return null; + } + } + var maxPoint = pointIndex(yValues.lastIndexOf(y.domain()[1])), + minPoint = pointIndex(yValues.indexOf(y.domain()[0])), + currentPoint = pointIndex(yValues.length - 1); + return [minPoint, maxPoint, currentPoint].filter(function (d) {return d != null;}); + }); + points.enter().append('circle'); + points.exit().remove(); + points + .attr('cx', function(d,i) { return x(getX(d,d.pointIndex)) }) + .attr('cy', function(d,i) { return y(getY(d,d.pointIndex)) }) + .attr('r', 2) + .attr('class', function(d,i) { + return getX(d, d.pointIndex) == x.domain()[1] ? 'nv-point nv-currentValue' : + getY(d, d.pointIndex) == y.domain()[0] ? 'nv-point nv-minValue' : 'nv-point nv-maxValue' + }); + }); + + return chart; + } + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}}, + yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}}, + xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}}, + yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}}, + xScale: {get: function(){return x;}, set: function(_){x=_;}}, + yScale: {get: function(){return y;}, set: function(_){y=_;}}, + animate: {get: function(){return animate;}, set: function(_){animate=_;}}, + + //functor options + x: {get: function(){return getX;}, set: function(_){getX=d3.functor(_);}}, + y: {get: function(){return getY;}, set: function(_){getY=d3.functor(_);}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + }} + }); + + nv.utils.initOptions(chart); + return chart; +}; + +nv.models.sparklinePlus = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var sparkline = nv.models.sparkline(); + + var margin = {top: 15, right: 100, bottom: 10, left: 50} + , width = null + , height = null + , x + , y + , index = [] + , paused = false + , xTickFormat = d3.format(',r') + , yTickFormat = d3.format(',.2f') + , showValue = true + , alignValue = true + , rightAlignValue = false + , noData = "No Data Available." + ; + + function chart(selection) { + selection.each(function(data) { + var container = d3.select(this); + nv.utils.initSVG(container); + + var availableWidth = (width || parseInt(container.style('width')) || 960) + - margin.left - margin.right, + availableHeight = (height || parseInt(container.style('height')) || 400) + - margin.top - margin.bottom; + + chart.update = function() { chart(selection) }; + chart.container = this; + + // Display No Data message if there's nothing to show. + if (!data || !data.length) { + var noDataText = container.selectAll('.nv-noData').data([noData]); + + noDataText.enter().append('text') + .attr('class', 'nvd3 nv-noData') + .attr('dy', '-.7em') + .style('text-anchor', 'middle'); + + noDataText + .attr('x', margin.left + availableWidth / 2) + .attr('y', margin.top + availableHeight / 2) + .text(function(d) { return d }); + + return chart; + } else { + container.selectAll('.nv-noData').remove(); + } + + var currentValue = sparkline.y()(data[data.length-1], data.length-1); + + // Setup Scales + x = sparkline.xScale(); + y = sparkline.yScale(); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-sparklineplus').data([data]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-sparklineplus'); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-sparklineWrap'); + gEnter.append('g').attr('class', 'nv-valueWrap'); + gEnter.append('g').attr('class', 'nv-hoverArea'); + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + // Main Chart Component(s) + var sparklineWrap = g.select('.nv-sparklineWrap'); + + sparkline.width(availableWidth).height(availableHeight); + sparklineWrap.call(sparkline); + + var valueWrap = g.select('.nv-valueWrap'); + var value = valueWrap.selectAll('.nv-currentValue') + .data([currentValue]); + + value.enter().append('text').attr('class', 'nv-currentValue') + .attr('dx', rightAlignValue ? -8 : 8) + .attr('dy', '.9em') + .style('text-anchor', rightAlignValue ? 'end' : 'start'); + + value + .attr('x', availableWidth + (rightAlignValue ? margin.right : 0)) + .attr('y', alignValue ? function(d) { return y(d) } : 0) + .style('fill', sparkline.color()(data[data.length-1], data.length-1)) + .text(yTickFormat(currentValue)); + + gEnter.select('.nv-hoverArea').append('rect') + .on('mousemove', sparklineHover) + .on('click', function() { paused = !paused }) + .on('mouseout', function() { index = []; updateValueLine(); }); + + g.select('.nv-hoverArea rect') + .attr('transform', function(d) { return 'translate(' + -margin.left + ',' + -margin.top + ')' }) + .attr('width', availableWidth + margin.left + margin.right) + .attr('height', availableHeight + margin.top); + + //index is currently global (within the chart), may or may not keep it that way + function updateValueLine() { + if (paused) return; + + var hoverValue = g.selectAll('.nv-hoverValue').data(index) + + var hoverEnter = hoverValue.enter() + .append('g').attr('class', 'nv-hoverValue') + .style('stroke-opacity', 0) + .style('fill-opacity', 0); + + hoverValue.exit() + .transition().duration(250) + .style('stroke-opacity', 0) + .style('fill-opacity', 0) + .remove(); + + hoverValue + .attr('transform', function(d) { return 'translate(' + x(sparkline.x()(data[d],d)) + ',0)' }) + .transition().duration(250) + .style('stroke-opacity', 1) + .style('fill-opacity', 1); + + if (!index.length) return; + + hoverEnter.append('line') + .attr('x1', 0) + .attr('y1', -margin.top) + .attr('x2', 0) + .attr('y2', availableHeight); + + hoverEnter.append('text').attr('class', 'nv-xValue') + .attr('x', -6) + .attr('y', -margin.top) + .attr('text-anchor', 'end') + .attr('dy', '.9em') + + g.select('.nv-hoverValue .nv-xValue') + .text(xTickFormat(sparkline.x()(data[index[0]], index[0]))); + + hoverEnter.append('text').attr('class', 'nv-yValue') + .attr('x', 6) + .attr('y', -margin.top) + .attr('text-anchor', 'start') + .attr('dy', '.9em') + + g.select('.nv-hoverValue .nv-yValue') + .text(yTickFormat(sparkline.y()(data[index[0]], index[0]))); + } + + function sparklineHover() { + if (paused) return; + + var pos = d3.mouse(this)[0] - margin.left; + + function getClosestIndex(data, x) { + var distance = Math.abs(sparkline.x()(data[0], 0) - x); + var closestIndex = 0; + for (var i = 0; i < data.length; i++){ + if (Math.abs(sparkline.x()(data[i], i) - x) < distance) { + distance = Math.abs(sparkline.x()(data[i], i) - x); + closestIndex = i; + } + } + return closestIndex; + } + + index = [getClosestIndex(data, Math.round(x.invert(pos)))]; + updateValueLine(); + } + + }); + + return chart; + } + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + // expose chart's sub-components + chart.sparkline = sparkline; + + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + xTickFormat: {get: function(){return xTickFormat;}, set: function(_){xTickFormat=_;}}, + yTickFormat: {get: function(){return yTickFormat;}, set: function(_){yTickFormat=_;}}, + showValue: {get: function(){return showValue;}, set: function(_){showValue=_;}}, + alignValue: {get: function(){return alignValue;}, set: function(_){alignValue=_;}}, + rightAlignValue: {get: function(){return rightAlignValue;}, set: function(_){rightAlignValue=_;}}, + noData: {get: function(){return noData;}, set: function(_){noData=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }} + }); + + nv.utils.inheritOptions(chart, sparkline); + nv.utils.initOptions(chart); + + return chart; +}; + +nv.models.stackedArea = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 0, right: 0, bottom: 0, left: 0} + , width = 960 + , height = 500 + , color = nv.utils.defaultColor() // a function that computes the color + , id = Math.floor(Math.random() * 100000) //Create semi-unique ID incase user doesn't selet one + , getX = function(d) { return d.x } // accessor to get the x value from a data point + , getY = function(d) { return d.y } // accessor to get the y value from a data point + , style = 'stack' + , offset = 'zero' + , order = 'default' + , interpolate = 'linear' // controls the line interpolation + , clipEdge = false // if true, masks lines within x and y scale + , x //can be accessed via chart.xScale() + , y //can be accessed via chart.yScale() + , scatter = nv.models.scatter() + , duration = 250 + , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'areaClick', 'areaMouseover', 'areaMouseout','renderEnd') + ; + + // scatter is interactive by default, but this chart isn't so must disable + scatter.interactive(false); + + scatter + .pointSize(2.2) // default size + .pointDomain([2.2, 2.2]) // all the same size by default + ; + + /************************************ + * offset: + * 'wiggle' (stream) + * 'zero' (stacked) + * 'expand' (normalize to 100%) + * 'silhouette' (simple centered) + * + * order: + * 'inside-out' (stream) + * 'default' (input order) + ************************************/ + + var renderWatch = nv.utils.renderWatch(dispatch, duration); + + function chart(selection) { + renderWatch.reset(); + renderWatch.models(scatter); + selection.each(function(data) { + var availableWidth = width - margin.left - margin.right, + availableHeight = height - margin.top - margin.bottom, + container = d3.select(this); + nv.utils.initSVG(container); + + // Setup Scales + x = scatter.xScale(); + y = scatter.yScale(); + + var dataRaw = data; + // Injecting point index into each point because d3.layout.stack().out does not give index + data.forEach(function(aseries, i) { + aseries.seriesIndex = i; + aseries.values = aseries.values.map(function(d, j) { + d.index = j; + d.seriesIndex = i; + return d; + }); + }); + + var dataFiltered = data.filter(function(series) { + return !series.disabled; + }); + + data = d3.layout.stack() + .order(order) + .offset(offset) + .values(function(d) { return d.values }) //TODO: make values customizeable in EVERY model in this fashion + .x(getX) + .y(getY) + .out(function(d, y0, y) { + var yHeight = (getY(d) === 0) ? 0 : y; + d.display = { + y: yHeight, + y0: y0 + }; + }) + (dataFiltered); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-stackedarea').data([data]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-stackedarea'); + var defsEnter = wrapEnter.append('defs'); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-areaWrap'); + gEnter.append('g').attr('class', 'nv-scatterWrap'); + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + scatter + .width(availableWidth) + .height(availableHeight) + .x(getX) + .y(function(d) { return d.display.y + d.display.y0 }) + .forceY([0]) + .color(data.map(function(d,i) { + return d.color || color(d, d.seriesIndex); + })); + + var scatterWrap = g.select('.nv-scatterWrap') + .datum(data); + + scatterWrap.call(scatter); + + defsEnter.append('clipPath') + .attr('id', 'nv-edge-clip-' + id) + .append('rect'); + + wrap.select('#nv-edge-clip-' + id + ' rect') + .attr('width', availableWidth) + .attr('height', availableHeight); + + g.attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + id + ')' : ''); + + var area = d3.svg.area() + .x(function(d,i) { return x(getX(d,i)) }) + .y0(function(d) { + return y(d.display.y0) + }) + .y1(function(d) { + return y(d.display.y + d.display.y0) + }) + .interpolate(interpolate); + + var zeroArea = d3.svg.area() + .x(function(d,i) { return x(getX(d,i)) }) + .y0(function(d) { return y(d.display.y0) }) + .y1(function(d) { return y(d.display.y0) }); + + var path = g.select('.nv-areaWrap').selectAll('path.nv-area') + .data(function(d) { return d }); + + path.enter().append('path').attr('class', function(d,i) { return 'nv-area nv-area-' + i }) + .attr('d', function(d,i){ + return zeroArea(d.values, d.seriesIndex); + }) + .on('mouseover', function(d,i) { + d3.select(this).classed('hover', true); + dispatch.areaMouseover({ + point: d, + series: d.key, + pos: [d3.event.pageX, d3.event.pageY], + seriesIndex: d.seriesIndex + }); + }) + .on('mouseout', function(d,i) { + d3.select(this).classed('hover', false); + dispatch.areaMouseout({ + point: d, + series: d.key, + pos: [d3.event.pageX, d3.event.pageY], + seriesIndex: d.seriesIndex + }); + }) + .on('click', function(d,i) { + d3.select(this).classed('hover', false); + dispatch.areaClick({ + point: d, + series: d.key, + pos: [d3.event.pageX, d3.event.pageY], + seriesIndex: d.seriesIndex + }); + }); + + path.exit().remove(); + path.style('fill', function(d,i){ + return d.color || color(d, d.seriesIndex) + }) + .style('stroke', function(d,i){ return d.color || color(d, d.seriesIndex) }); + path.watchTransition(renderWatch,'stackedArea path') + .attr('d', function(d,i) { + return area(d.values,i) + }); + + //============================================================ + // Event Handling/Dispatching (in chart's scope) + //------------------------------------------------------------ + + scatter.dispatch.on('elementMouseover.area', function(e) { + g.select('.nv-chart-' + id + ' .nv-area-' + e.seriesIndex).classed('hover', true); + }); + scatter.dispatch.on('elementMouseout.area', function(e) { + g.select('.nv-chart-' + id + ' .nv-area-' + e.seriesIndex).classed('hover', false); + }); + + //Special offset functions + chart.d3_stackedOffset_stackPercent = function(stackData) { + var n = stackData.length, //How many series + m = stackData[0].length, //how many points per series + k = 1 / n, + i, + j, + o, + y0 = []; + + for (j = 0; j < m; ++j) { //Looping through all points + for (i = 0, o = 0; i < dataRaw.length; i++) { //looping through series' + o += getY(dataRaw[i].values[j]); //total value of all points at a certian point in time. + } + + if (o) for (i = 0; i < n; i++) { + stackData[i][j][1] /= o; + } else { + for (i = 0; i < n; i++) { + stackData[i][j][1] = k; + } + } + } + for (j = 0; j < m; ++j) y0[j] = 0; + return y0; + }; + + }); + + renderWatch.renderEnd('stackedArea immediate'); + return chart; + } + + + //============================================================ + // Event Handling/Dispatching (out of chart's scope) + //------------------------------------------------------------ + + scatter.dispatch.on('elementClick.area', function(e) { + dispatch.areaClick(e); + }); + scatter.dispatch.on('elementMouseover.tooltip', function(e) { + e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top], + dispatch.tooltipShow(e); + }); + scatter.dispatch.on('elementMouseout.tooltip', function(e) { + dispatch.tooltipHide(e); + }); + + //============================================================ + // Global getters and setters + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.scatter = scatter; + + chart.interpolate = function(_) { + if (!arguments.length) return interpolate; + interpolate = _; + return chart; + }; + + chart.duration = function(_) { + if (!arguments.length) return duration; + duration = _; + renderWatch.reset(duration); + scatter.duration(duration); + return chart; + }; + + chart.dispatch = dispatch; + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + clipEdge: {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}}, + offset: {get: function(){return offset;}, set: function(_){offset=_;}}, + order: {get: function(){return order;}, set: function(_){order=_;}}, + interpolate: {get: function(){return interpolate;}, set: function(_){interpolate=_;}}, + + // simple functor options + x: {get: function(){return getX;}, set: function(_){getX = d3.functor(_);}}, + y: {get: function(){return getY;}, set: function(_){getY = d3.functor(_);}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + }}, + style: {get: function(){return style;}, set: function(_){ + style = _; + switch (style) { + case 'stack': + chart.offset('zero'); + chart.order('default'); + break; + case 'stream': + chart.offset('wiggle'); + chart.order('inside-out'); + break; + case 'stream-center': + chart.offset('silhouette'); + chart.order('inside-out'); + break; + case 'expand': + chart.offset('expand'); + chart.order('default'); + break; + case 'stack_percent': + chart.offset(chart.d3_stackedOffset_stackPercent); + chart.order('default'); + break; + } + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration = _; + renderWatch.reset(duration); + scatter.duration(duration); + }} + }); + + nv.utils.inheritOptions(chart, scatter); + nv.utils.initOptions(chart); + + return chart; +}; + +nv.models.stackedAreaChart = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var stacked = nv.models.stackedArea() + , xAxis = nv.models.axis() + , yAxis = nv.models.axis() + , legend = nv.models.legend() + , controls = nv.models.legend() + , interactiveLayer = nv.interactiveGuideline() + ; + + var margin = {top: 30, right: 25, bottom: 50, left: 60} + , width = null + , height = null + , color = nv.utils.defaultColor() + , showControls = true + , showLegend = true + , showXAxis = true + , showYAxis = true + , rightAlignYAxis = false + , useInteractiveGuideline = false + , tooltips = true + , tooltip = function(key, x, y, e, graph) { + return '

' + key + '

' + + '

' + y + ' on ' + x + '

' + } + , x //can be accessed via chart.xScale() + , y //can be accessed via chart.yScale() + , yAxisTickFormat = d3.format(',.2f') + , state = nv.utils.state() + , defaultState = null + , noData = 'No Data Available.' + , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState','renderEnd') + , controlWidth = 250 + , cData = ['Stacked','Stream','Expanded'] + , controlLabels = {} + , duration = 250 + ; + + state.style = stacked.style(); + xAxis.orient('bottom').tickPadding(7); + yAxis.orient((rightAlignYAxis) ? 'right' : 'left'); + + controls.updateState(false); + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var renderWatch = nv.utils.renderWatch(dispatch); + var style = stacked.style(); + + var showTooltip = function(e, offsetElement) { + var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ), + top = e.pos[1] + ( offsetElement.offsetTop || 0), + x = xAxis.tickFormat()(stacked.x()(e.point, e.pointIndex)), + y = yAxis.tickFormat()(stacked.y()(e.point, e.pointIndex)), + content = tooltip(e.series.key, x, y, e, chart); + + nv.tooltip.show([left, top], content, e.value < 0 ? 'n' : 's', null, offsetElement); + }; + + var stateGetter = function(data) { + return function(){ + return { + active: data.map(function(d) { return !d.disabled }), + style: stacked.style() + }; + } + }; + + var stateSetter = function(data) { + return function(state) { + if (state.style !== undefined) + style = state.style; + if (state.active !== undefined) + data.forEach(function(series,i) { + series.disabled = !state.active[i]; + }); + } + }; + + function chart(selection) { + renderWatch.reset(); + renderWatch.models(stacked); + if (showXAxis) renderWatch.models(xAxis); + if (showYAxis) renderWatch.models(yAxis); + + selection.each(function(data) { + var container = d3.select(this), + that = this; + nv.utils.initSVG(container); + + var availableWidth = (width || parseInt(container.style('width')) || 960) + - margin.left - margin.right, + availableHeight = (height || parseInt(container.style('height')) || 400) + - margin.top - margin.bottom; + + chart.update = function() { container.transition().duration(duration).call(chart); }; + chart.container = this; + + state + .setter(stateSetter(data), chart.update) + .getter(stateGetter(data)) + .update(); + + // DEPRECATED set state.disabled + state.disabled = data.map(function(d) { return !!d.disabled }); + + if (!defaultState) { + var key; + defaultState = {}; + for (key in state) { + if (state[key] instanceof Array) + defaultState[key] = state[key].slice(0); + else + defaultState[key] = state[key]; + } + } + + // Display No Data message if there's nothing to show. + if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { + var noDataText = container.selectAll('.nv-noData').data([noData]); + + noDataText.enter().append('text') + .attr('class', 'nvd3 nv-noData') + .attr('dy', '-.7em') + .style('text-anchor', 'middle'); + + noDataText + .attr('x', margin.left + availableWidth / 2) + .attr('y', margin.top + availableHeight / 2) + .text(function(d) { return d }); + + return chart; + } else { + container.selectAll('.nv-noData').remove(); + } + + // Setup Scales + x = stacked.xScale(); + y = stacked.yScale(); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-stackedAreaChart').data([data]); + var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-stackedAreaChart').append('g'); + var g = wrap.select('g'); + + gEnter.append("rect").style("opacity",0); + gEnter.append('g').attr('class', 'nv-x nv-axis'); + gEnter.append('g').attr('class', 'nv-y nv-axis'); + gEnter.append('g').attr('class', 'nv-stackedWrap'); + gEnter.append('g').attr('class', 'nv-legendWrap'); + gEnter.append('g').attr('class', 'nv-controlsWrap'); + gEnter.append('g').attr('class', 'nv-interactive'); + + g.select("rect").attr("width",availableWidth).attr("height",availableHeight); + + // Legend + if (showLegend) { + var legendWidth = (showControls) ? availableWidth - controlWidth : availableWidth; + + legend.width(legendWidth); + g.select('.nv-legendWrap').datum(data).call(legend); + + if ( margin.top != legend.height()) { + margin.top = legend.height(); + availableHeight = (height || parseInt(container.style('height')) || 400) + - margin.top - margin.bottom; + } + + g.select('.nv-legendWrap') + .attr('transform', 'translate(' + (availableWidth-legendWidth) + ',' + (-margin.top) +')'); + } + + // Controls + if (showControls) { + var controlsData = [ + { + key: controlLabels.stacked || 'Stacked', + metaKey: 'Stacked', + disabled: stacked.style() != 'stack', + style: 'stack' + }, + { + key: controlLabels.stream || 'Stream', + metaKey: 'Stream', + disabled: stacked.style() != 'stream', + style: 'stream' + }, + { + key: controlLabels.expanded || 'Expanded', + metaKey: 'Expanded', + disabled: stacked.style() != 'expand', + style: 'expand' + }, + { + key: controlLabels.stack_percent || 'Stack %', + metaKey: 'Stack_Percent', + disabled: stacked.style() != 'stack_percent', + style: 'stack_percent' + } + ]; + + controlWidth = (cData.length/3) * 260; + controlsData = controlsData.filter(function(d) { + return cData.indexOf(d.metaKey) !== -1; + }); + + controls + .width( controlWidth ) + .color(['#444', '#444', '#444']); + + g.select('.nv-controlsWrap') + .datum(controlsData) + .call(controls); + + if ( margin.top != Math.max(controls.height(), legend.height()) ) { + margin.top = Math.max(controls.height(), legend.height()); + availableHeight = (height || parseInt(container.style('height')) || 400) + - margin.top - margin.bottom; + } + + g.select('.nv-controlsWrap') + .attr('transform', 'translate(0,' + (-margin.top) +')'); + } + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + if (rightAlignYAxis) { + g.select(".nv-y.nv-axis") + .attr("transform", "translate(" + availableWidth + ",0)"); + } + + //Set up interactive layer + if (useInteractiveGuideline) { + interactiveLayer + .width(availableWidth) + .height(availableHeight) + .margin({left: margin.left, top: margin.top}) + .svgContainer(container) + .xScale(x); + wrap.select(".nv-interactive").call(interactiveLayer); + } + + stacked + .width(availableWidth) + .height(availableHeight); + + var stackedWrap = g.select('.nv-stackedWrap') + .datum(data); + + stackedWrap.transition().call(stacked); + + // Setup Axes + if (showXAxis) { + xAxis.scale(x) + .ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + .tickSize( -availableHeight, 0); + + g.select('.nv-x.nv-axis') + .attr('transform', 'translate(0,' + availableHeight + ')'); + + g.select('.nv-x.nv-axis') + .transition().duration(0) + .call(xAxis); + } + + if (showYAxis) { + yAxis.scale(y) + .ticks(stacked.offset() == 'wiggle' ? 0 : nv.utils.calcTicksY(availableHeight/36, data) ) + .tickSize(-availableWidth, 0) + .setTickFormat( (stacked.style() == 'expand' || stacked.style() == 'stack_percent') + ? d3.format('%') : yAxisTickFormat); + + g.select('.nv-y.nv-axis') + .transition().duration(0) + .call(yAxis); + } + + //============================================================ + // Event Handling/Dispatching (in chart's scope) + //------------------------------------------------------------ + + stacked.dispatch.on('areaClick.toggle', function(e) { + if (data.filter(function(d) { return !d.disabled }).length === 1) + data.forEach(function(d) { + d.disabled = false; + }); + else + data.forEach(function(d,i) { + d.disabled = (i != e.seriesIndex); + }); + + state.disabled = data.map(function(d) { return !!d.disabled }); + dispatch.stateChange(state); + + chart.update(); + }); + + legend.dispatch.on('stateChange', function(newState) { + for (var key in newState) + state[key] = newState[key]; + dispatch.stateChange(state); + chart.update(); + }); + + controls.dispatch.on('legendClick', function(d,i) { + if (!d.disabled) return; + + controlsData = controlsData.map(function(s) { + s.disabled = true; + return s; + }); + d.disabled = false; + + stacked.style(d.style); + + + state.style = stacked.style(); + dispatch.stateChange(state); + + chart.update(); + }); + + interactiveLayer.dispatch.on('elementMousemove', function(e) { + stacked.clearHighlights(); + var singlePoint, pointIndex, pointXLocation, allData = []; + data + .filter(function(series, i) { + series.seriesIndex = i; + return !series.disabled; + }) + .forEach(function(series,i) { + pointIndex = nv.interactiveBisect(series.values, e.pointXValue, chart.x()); + stacked.highlightPoint(i, pointIndex, true); + var point = series.values[pointIndex]; + if (typeof point === 'undefined') return; + if (typeof singlePoint === 'undefined') singlePoint = point; + if (typeof pointXLocation === 'undefined') pointXLocation = chart.xScale()(chart.x()(point,pointIndex)); + + //If we are in 'expand' mode, use the stacked percent value instead of raw value. + var tooltipValue = (stacked.style() == 'expand') ? point.display.y : chart.y()(point,pointIndex); + allData.push({ + key: series.key, + value: tooltipValue, + color: color(series,series.seriesIndex), + stackedValue: point.display + }); + }); + + allData.reverse(); + + //Highlight the tooltip entry based on which stack the mouse is closest to. + if (allData.length > 2) { + var yValue = chart.yScale().invert(e.mouseY); + var yDistMax = Infinity, indexToHighlight = null; + allData.forEach(function(series,i) { + + //To handle situation where the stacked area chart is negative, we need to use absolute values + //when checking if the mouse Y value is within the stack area. + yValue = Math.abs(yValue); + var stackedY0 = Math.abs(series.stackedValue.y0); + var stackedY = Math.abs(series.stackedValue.y); + if ( yValue >= stackedY0 && yValue <= (stackedY + stackedY0)) + { + indexToHighlight = i; + return; + } + }); + if (indexToHighlight != null) + allData[indexToHighlight].highlight = true; + } + + var xValue = xAxis.tickFormat()(chart.x()(singlePoint,pointIndex)); + + //If we are in 'expand' mode, force the format to be a percentage. + var valueFormatter = (stacked.style() == 'expand') ? + function(d,i) {return d3.format(".1%")(d);} : + function(d,i) {return yAxis.tickFormat()(d); }; + interactiveLayer.tooltip + .position({left: pointXLocation + margin.left, top: e.mouseY + margin.top}) + .chartContainer(that.parentNode) + .enabled(tooltips) + .valueFormatter(valueFormatter) + .data( + { + value: xValue, + series: allData + } + )(); + + interactiveLayer.renderGuideLine(pointXLocation); + + }); + + interactiveLayer.dispatch.on("elementMouseout",function(e) { + dispatch.tooltipHide(); + stacked.clearHighlights(); + }); + + + dispatch.on('tooltipShow', function(e) { + if (tooltips) showTooltip(e, that.parentNode); + }); + + // Update chart from a state object passed to event handler + dispatch.on('changeState', function(e) { + + if (typeof e.disabled !== 'undefined' && data.length === e.disabled.length) { + data.forEach(function(series,i) { + series.disabled = e.disabled[i]; + }); + + state.disabled = e.disabled; + } + + if (typeof e.style !== 'undefined') { + stacked.style(e.style); + style = e.style; + } + + chart.update(); + }); + + }); + + renderWatch.renderEnd('stacked Area chart immediate'); + return chart; + } + + //============================================================ + // Event Handling/Dispatching (out of chart's scope) + //------------------------------------------------------------ + + stacked.dispatch.on('tooltipShow', function(e) { + e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; + dispatch.tooltipShow(e); + }); + + stacked.dispatch.on('tooltipHide', function(e) { + dispatch.tooltipHide(e); + }); + + dispatch.on('tooltipHide', function() { + if (tooltips) nv.tooltip.cleanup(); + }); + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + // expose chart's sub-components + chart.dispatch = dispatch; + chart.stacked = stacked; + chart.legend = legend; + chart.controls = controls; + chart.xAxis = xAxis; + chart.yAxis = yAxis; + chart.interactiveLayer = interactiveLayer; + + yAxis.setTickFormat = yAxis.tickFormat; + + chart.dispatch = dispatch; + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, + showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}}, + showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}}, + tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, + tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, + defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, + noData: {get: function(){return noData;}, set: function(_){noData=_;}}, + showControls: {get: function(){return showControls;}, set: function(_){showControls=_;}}, + controlLabels: {get: function(){return controlLabels;}, set: function(_){controlLabels=_;}}, + yAxisTickFormat: {get: function(){return yAxisTickFormat;}, set: function(_){yAxisTickFormat=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration = _; + renderWatch.reset(duration); + stacked.duration(duration); + xAxis.duration(duration); + yAxis.duration(duration); + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + legend.color(color); + stacked.color(color); + }}, + rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){ + rightAlignYAxis = _; + yAxis.orient( rightAlignYAxis ? 'right' : 'left'); + }}, + useInteractiveGuideline: {get: function(){return useInteractiveGuideline;}, set: function(_){ + useInteractiveGuideline = !!_; + if (_) { + chart.interactive(false); + chart.useVoronoi(false); + } + }} + }); + + nv.utils.inheritOptions(chart, stacked); + nv.utils.initOptions(chart); + + return chart; +}; + +nv.version = "1.7.1"; +})(); \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/sonar_graph.js b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/sonar_graph.js new file mode 100755 index 00000000..de79082e --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/sonar_graph.js @@ -0,0 +1,60 @@ +var sonarChart; + +nv.addGraph(function () { + + sonarChart = nv.models.lineChart() + .interpolate("linear") + .options({ + transitionDuration: 300, + useInteractiveGuideline: true + }) + ; + + sonarChart.xScale(d3.time.scale()); + + // chart sub-models (ie. xAxis, yAxis, etc) when accessed directly, return themselves, not the parent chart, so need to chain separately + sonarChart.xAxis + .axisLabel("Date/Time") + .ticks(d3.time.seconds) + .tickFormat(function (d) { + return d3.time.format('%m/%d/%Y %I:%M:%S %p')(new Date(d)) + }) + .staggerLabels(true) + ; + + sonarChart.yAxis + .axisLabel('Sonar') + ; + + d3.select('.chart4 svg') + .datum(getSonarChartData()) + .call(sonarChart); + + nv.utils.windowResize(sonarChart.update); + + return sonarChart; +}); + +function getSonarChartData() { + + return [ + { + area: true, + values: [], + key: "Sonar", + color: "#34500e" + } + ]; + +} + +function updateSonarGraph(sonarData) { + + var chartData = getSonarChartData(); + chartData[0]['values'] = sonarData; + + d3.select('.chart4 svg') + .datum(chartData) + .transition().duration(500) + .call(sonarChart); +} \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/stream_layers.js b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/stream_layers.js new file mode 100755 index 00000000..43d7cfe0 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/stream_layers.js @@ -0,0 +1,35 @@ + +/* Inspired by Lee Byron's test data generator. */ +function stream_layers(n, m, o) { + if (arguments.length < 3) o = 0; + function bump(a) { + var x = 1 / (.1 + Math.random()), + y = 2 * Math.random() - .5, + z = 10 / (.1 + Math.random()); + for (var i = 0; i < m; i++) { + var w = (i / m - y) * z; + a[i] += x * Math.exp(-w * w); + } + } + return d3.range(n).map(function() { + var a = [], i; + for (i = 0; i < m; i++) a[i] = o + o * Math.random(); + for (i = 0; i < 5; i++) bump(a); + return a.map(stream_index); + }); +} + +/* Another layer generator using gamma distributions. */ +function stream_waves(n, m) { + return d3.range(n).map(function(i) { + return d3.range(m).map(function(j) { + var x = 20 * j / m - i / 3; + return 2 * x * Math.exp(-.5 * x); + }).map(stream_index); + }); +} + +function stream_index(d, i) { + return {x: i, y: Math.max(0, d)}; +} + diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/temperature_graph.js b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/temperature_graph.js new file mode 100755 index 00000000..4c463b39 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/mydevice/public/js/temperature_graph.js @@ -0,0 +1,60 @@ +var temperatureChart; + +nv.addGraph(function () { + + temperatureChart = nv.models.lineChart() + .interpolate("linear") + .options({ + transitionDuration: 300, + useInteractiveGuideline: true + }) + ; + + temperatureChart.xScale(d3.time.scale()); + + // chart sub-models (ie. xAxis, yAxis, etc) when accessed directly, return themselves, not the parent chart, so need to chain separately + temperatureChart.xAxis + .axisLabel("Date/Time") + .ticks(d3.time.seconds) + .tickFormat(function (d) { + return d3.time.format('%m/%d/%Y %I:%M:%S %p')(new Date(d)) + }) + .staggerLabels(true) + ; + + temperatureChart.yAxis + .axisLabel('Temperature (C)') + ; + + d3.select('.chart1 svg') + .datum(getTemperatureChartData()) + .call(temperatureChart); + + nv.utils.windowResize(temperatureChart.update); + + return temperatureChart; +}); + +function getTemperatureChartData() { + + return [ + { + area: true, + values: [], + key: "Temperature", + color: "#34500e" + } + ]; + +} + +function updateTemperatureGraph(temperatureData) { + + var chartData = getTemperatureChartData(); + chartData[0]['values'] = temperatureData; + + d3.select('.chart1 svg') + .datum(chartData) + .transition().duration(500) + .call(temperatureChart); +} \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/css/bootstrap.min.css b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/css/bootstrap.min.css new file mode 100755 index 00000000..d29dc3b4 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/css/bootstrap.min.css @@ -0,0 +1,6671 @@ +/*! + * Bootstrap v3.3.4 (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +/*! normalize.css v3.0.2 | MIT License | git.io/normalize */ + +html { + font-family: sans-serif; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100% +} +body { + margin: 0 +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block +} +audio, +canvas, +progress, +video { + display: inline-block; + vertical-align: baseline +} +audio:not([controls]) { + display: none; + height: 0 +} +[hidden], +template { + display: none +} +a { + background-color: transparent +} +a:active, +a:hover { + outline: 0 +} +abbr[title] { + border-bottom: 1px dotted +} +b, +strong { + font-weight: 700 +} +dfn { + font-style: italic +} +h1 { + margin: .67em 0; + font-size: 2em +} +mark { + color: #000; + background: #ff0 +} +small { + font-size: 80% +} +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline +} +sup { + top: -.5em +} +sub { + bottom: -.25em +} +img { + border: 0 +} +svg:not(:root) { + overflow: hidden +} +figure { + margin: 1em 40px +} +hr { + height: 0; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box +} +pre { + overflow: auto +} +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em +} +button, +input, +optgroup, +select, +textarea { + margin: 0; + font: inherit; + color: inherit +} +button { + overflow: visible +} +button, +select { + text-transform: none +} +button, +html input[type=button], +input[type=reset], +input[type=submit] { + -webkit-appearance: button; + cursor: pointer +} +button[disabled], +html input[disabled] { + cursor: default +} +button::-moz-focus-inner, +input::-moz-focus-inner { + padding: 0; + border: 0 +} +input { + line-height: normal +} +input[type=checkbox], +input[type=radio] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + padding: 0 +} +input[type=number]::-webkit-inner-spin-button, +input[type=number]::-webkit-outer-spin-button { + height: auto +} +input[type=search] { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + -webkit-appearance: textfield +} +input[type=search]::-webkit-search-cancel-button, +input[type=search]::-webkit-search-decoration { + -webkit-appearance: none +} +fieldset { + padding: .35em .625em .75em; + margin: 0 2px; + border: 1px solid silver +} +legend { + padding: 0; + border: 0 +} +textarea { + overflow: auto +} +optgroup { + font-weight: 700 +} +table { + border-spacing: 0; + border-collapse: collapse +} +td, +th { + padding: 0 +} +/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ + +@media print { + *, + :after, + :before { + color: #000!important; + text-shadow: none!important; + background: 0 0!important; + -webkit-box-shadow: none!important; + box-shadow: none!important + } + a, + a:visited { + text-decoration: underline + } + a[href]:after { + content: " (" attr(href) ")" + } + abbr[title]:after { + content: " (" attr(title) ")" + } + a[href^="javascript:"]:after, + a[href^="#"]:after { + content: "" + } + blockquote, + pre { + border: 1px solid #999; + page-break-inside: avoid + } + thead { + display: table-header-group + } + img, + tr { + page-break-inside: avoid + } + img { + max-width: 100%!important + } + h2, + h3, + p { + orphans: 3; + widows: 3 + } + h2, + h3 { + page-break-after: avoid + } + select { + background: #fff!important + } + .navbar { + display: none + } + .btn>.caret, + .dropup>.btn>.caret { + border-top-color: #000!important + } + .label { + border: 1px solid #000 + } + .table { + border-collapse: collapse!important + } + .table td, + .table th { + background-color: #fff!important + } + .table-bordered td, + .table-bordered th { + border: 1px solid #ddd!important + } +} +@font-face { + font-family: 'Glyphicons Halflings'; + src: url(../fonts/glyphicons-halflings-regular.eot); + src: url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'), url(../fonts/glyphicons-halflings-regular.woff) format('woff'), url(../fonts/glyphicons-halflings-regular.woff) format('woff'), url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'), url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg') +} +.glyphicon { + position: relative; + top: 1px; + display: inline-block; + font-family: 'Glyphicons Halflings'; + font-style: normal; + font-weight: 400; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale +} +.glyphicon-asterisk:before { + content: "\2a" +} +.glyphicon-plus:before { + content: "\2b" +} +.glyphicon-eur:before, +.glyphicon-euro:before { + content: "\20ac" +} +.glyphicon-minus:before { + content: "\2212" +} +.glyphicon-cloud:before { + content: "\2601" +} +.glyphicon-envelope:before { + content: "\2709" +} +.glyphicon-pencil:before { + content: "\270f" +} +.glyphicon-glass:before { + content: "\e001" +} +.glyphicon-music:before { + content: "\e002" +} +.glyphicon-search:before { + content: "\e003" +} +.glyphicon-heart:before { + content: "\e005" +} +.glyphicon-star:before { + content: "\e006" +} +.glyphicon-star-empty:before { + content: "\e007" +} +.glyphicon-user:before { + content: "\e008" +} +.glyphicon-film:before { + content: "\e009" +} +.glyphicon-th-large:before { + content: "\e010" +} +.glyphicon-th:before { + content: "\e011" +} +.glyphicon-th-list:before { + content: "\e012" +} +.glyphicon-ok:before { + content: "\e013" +} +.glyphicon-remove:before { + content: "\e014" +} +.glyphicon-zoom-in:before { + content: "\e015" +} +.glyphicon-zoom-out:before { + content: "\e016" +} +.glyphicon-off:before { + content: "\e017" +} +.glyphicon-signal:before { + content: "\e018" +} +.glyphicon-cog:before { + content: "\e019" +} +.glyphicon-trash:before { + content: "\e020" +} +.glyphicon-home:before { + content: "\e021" +} +.glyphicon-file:before { + content: "\e022" +} +.glyphicon-time:before { + content: "\e023" +} +.glyphicon-road:before { + content: "\e024" +} +.glyphicon-download-alt:before { + content: "\e025" +} +.glyphicon-download:before { + content: "\e026" +} +.glyphicon-upload:before { + content: "\e027" +} +.glyphicon-inbox:before { + content: "\e028" +} +.glyphicon-play-circle:before { + content: "\e029" +} +.glyphicon-repeat:before { + content: "\e030" +} +.glyphicon-refresh:before { + content: "\e031" +} +.glyphicon-list-alt:before { + content: "\e032" +} +.glyphicon-lock:before { + content: "\e033" +} +.glyphicon-flag:before { + content: "\e034" +} +.glyphicon-headphones:before { + content: "\e035" +} +.glyphicon-volume-off:before { + content: "\e036" +} +.glyphicon-volume-down:before { + content: "\e037" +} +.glyphicon-volume-up:before { + content: "\e038" +} +.glyphicon-qrcode:before { + content: "\e039" +} +.glyphicon-barcode:before { + content: "\e040" +} +.glyphicon-tag:before { + content: "\e041" +} +.glyphicon-tags:before { + content: "\e042" +} +.glyphicon-book:before { + content: "\e043" +} +.glyphicon-bookmark:before { + content: "\e044" +} +.glyphicon-print:before { + content: "\e045" +} +.glyphicon-camera:before { + content: "\e046" +} +.glyphicon-font:before { + content: "\e047" +} +.glyphicon-bold:before { + content: "\e048" +} +.glyphicon-italic:before { + content: "\e049" +} +.glyphicon-text-height:before { + content: "\e050" +} +.glyphicon-text-width:before { + content: "\e051" +} +.glyphicon-align-left:before { + content: "\e052" +} +.glyphicon-align-center:before { + content: "\e053" +} +.glyphicon-align-right:before { + content: "\e054" +} +.glyphicon-align-justify:before { + content: "\e055" +} +.glyphicon-list:before { + content: "\e056" +} +.glyphicon-indent-left:before { + content: "\e057" +} +.glyphicon-indent-right:before { + content: "\e058" +} +.glyphicon-facetime-video:before { + content: "\e059" +} +.glyphicon-picture:before { + content: "\e060" +} +.glyphicon-map-marker:before { + content: "\e062" +} +.glyphicon-adjust:before { + content: "\e063" +} +.glyphicon-tint:before { + content: "\e064" +} +.glyphicon-edit:before { + content: "\e065" +} +.glyphicon-share:before { + content: "\e066" +} +.glyphicon-check:before { + content: "\e067" +} +.glyphicon-move:before { + content: "\e068" +} +.glyphicon-step-backward:before { + content: "\e069" +} +.glyphicon-fast-backward:before { + content: "\e070" +} +.glyphicon-backward:before { + content: "\e071" +} +.glyphicon-play:before { + content: "\e072" +} +.glyphicon-pause:before { + content: "\e073" +} +.glyphicon-stop:before { + content: "\e074" +} +.glyphicon-forward:before { + content: "\e075" +} +.glyphicon-fast-forward:before { + content: "\e076" +} +.glyphicon-step-forward:before { + content: "\e077" +} +.glyphicon-eject:before { + content: "\e078" +} +.glyphicon-chevron-left:before { + content: "\e079" +} +.glyphicon-chevron-right:before { + content: "\e080" +} +.glyphicon-plus-sign:before { + content: "\e081" +} +.glyphicon-minus-sign:before { + content: "\e082" +} +.glyphicon-remove-sign:before { + content: "\e083" +} +.glyphicon-ok-sign:before { + content: "\e084" +} +.glyphicon-question-sign:before { + content: "\e085" +} +.glyphicon-info-sign:before { + content: "\e086" +} +.glyphicon-screenshot:before { + content: "\e087" +} +.glyphicon-remove-circle:before { + content: "\e088" +} +.glyphicon-ok-circle:before { + content: "\e089" +} +.glyphicon-ban-circle:before { + content: "\e090" +} +.glyphicon-arrow-left:before { + content: "\e091" +} +.glyphicon-arrow-right:before { + content: "\e092" +} +.glyphicon-arrow-up:before { + content: "\e093" +} +.glyphicon-arrow-down:before { + content: "\e094" +} +.glyphicon-share-alt:before { + content: "\e095" +} +.glyphicon-resize-full:before { + content: "\e096" +} +.glyphicon-resize-small:before { + content: "\e097" +} +.glyphicon-exclamation-sign:before { + content: "\e101" +} +.glyphicon-gift:before { + content: "\e102" +} +.glyphicon-leaf:before { + content: "\e103" +} +.glyphicon-fire:before { + content: "\e104" +} +.glyphicon-eye-open:before { + content: "\e105" +} +.glyphicon-eye-close:before { + content: "\e106" +} +.glyphicon-warning-sign:before { + content: "\e107" +} +.glyphicon-plane:before { + content: "\e108" +} +.glyphicon-calendar:before { + content: "\e109" +} +.glyphicon-random:before { + content: "\e110" +} +.glyphicon-comment:before { + content: "\e111" +} +.glyphicon-magnet:before { + content: "\e112" +} +.glyphicon-chevron-up:before { + content: "\e113" +} +.glyphicon-chevron-down:before { + content: "\e114" +} +.glyphicon-retweet:before { + content: "\e115" +} +.glyphicon-shopping-cart:before { + content: "\e116" +} +.glyphicon-folder-close:before { + content: "\e117" +} +.glyphicon-folder-open:before { + content: "\e118" +} +.glyphicon-resize-vertical:before { + content: "\e119" +} +.glyphicon-resize-horizontal:before { + content: "\e120" +} +.glyphicon-hdd:before { + content: "\e121" +} +.glyphicon-bullhorn:before { + content: "\e122" +} +.glyphicon-bell:before { + content: "\e123" +} +.glyphicon-certificate:before { + content: "\e124" +} +.glyphicon-thumbs-up:before { + content: "\e125" +} +.glyphicon-thumbs-down:before { + content: "\e126" +} +.glyphicon-hand-right:before { + content: "\e127" +} +.glyphicon-hand-left:before { + content: "\e128" +} +.glyphicon-hand-up:before { + content: "\e129" +} +.glyphicon-hand-down:before { + content: "\e130" +} +.glyphicon-circle-arrow-right:before { + content: "\e131" +} +.glyphicon-circle-arrow-left:before { + content: "\e132" +} +.glyphicon-circle-arrow-up:before { + content: "\e133" +} +.glyphicon-circle-arrow-down:before { + content: "\e134" +} +.glyphicon-globe:before { + content: "\e135" +} +.glyphicon-wrench:before { + content: "\e136" +} +.glyphicon-tasks:before { + content: "\e137" +} +.glyphicon-filter:before { + content: "\e138" +} +.glyphicon-briefcase:before { + content: "\e139" +} +.glyphicon-fullscreen:before { + content: "\e140" +} +.glyphicon-dashboard:before { + content: "\e141" +} +.glyphicon-paperclip:before { + content: "\e142" +} +.glyphicon-heart-empty:before { + content: "\e143" +} +.glyphicon-link:before { + content: "\e144" +} +.glyphicon-phone:before { + content: "\e145" +} +.glyphicon-pushpin:before { + content: "\e146" +} +.glyphicon-usd:before { + content: "\e148" +} +.glyphicon-gbp:before { + content: "\e149" +} +.glyphicon-sort:before { + content: "\e150" +} +.glyphicon-sort-by-alphabet:before { + content: "\e151" +} +.glyphicon-sort-by-alphabet-alt:before { + content: "\e152" +} +.glyphicon-sort-by-order:before { + content: "\e153" +} +.glyphicon-sort-by-order-alt:before { + content: "\e154" +} +.glyphicon-sort-by-attributes:before { + content: "\e155" +} +.glyphicon-sort-by-attributes-alt:before { + content: "\e156" +} +.glyphicon-unchecked:before { + content: "\e157" +} +.glyphicon-expand:before { + content: "\e158" +} +.glyphicon-collapse-down:before { + content: "\e159" +} +.glyphicon-collapse-up:before { + content: "\e160" +} +.glyphicon-log-in:before { + content: "\e161" +} +.glyphicon-flash:before { + content: "\e162" +} +.glyphicon-log-out:before { + content: "\e163" +} +.glyphicon-new-window:before { + content: "\e164" +} +.glyphicon-record:before { + content: "\e165" +} +.glyphicon-save:before { + content: "\e166" +} +.glyphicon-open:before { + content: "\e167" +} +.glyphicon-saved:before { + content: "\e168" +} +.glyphicon-import:before { + content: "\e169" +} +.glyphicon-export:before { + content: "\e170" +} +.glyphicon-send:before { + content: "\e171" +} +.glyphicon-floppy-disk:before { + content: "\e172" +} +.glyphicon-floppy-saved:before { + content: "\e173" +} +.glyphicon-floppy-remove:before { + content: "\e174" +} +.glyphicon-floppy-save:before { + content: "\e175" +} +.glyphicon-floppy-open:before { + content: "\e176" +} +.glyphicon-credit-card:before { + content: "\e177" +} +.glyphicon-transfer:before { + content: "\e178" +} +.glyphicon-cutlery:before { + content: "\e179" +} +.glyphicon-header:before { + content: "\e180" +} +.glyphicon-compressed:before { + content: "\e181" +} +.glyphicon-earphone:before { + content: "\e182" +} +.glyphicon-phone-alt:before { + content: "\e183" +} +.glyphicon-tower:before { + content: "\e184" +} +.glyphicon-stats:before { + content: "\e185" +} +.glyphicon-sd-video:before { + content: "\e186" +} +.glyphicon-hd-video:before { + content: "\e187" +} +.glyphicon-subtitles:before { + content: "\e188" +} +.glyphicon-sound-stereo:before { + content: "\e189" +} +.glyphicon-sound-dolby:before { + content: "\e190" +} +.glyphicon-sound-5-1:before { + content: "\e191" +} +.glyphicon-sound-6-1:before { + content: "\e192" +} +.glyphicon-sound-7-1:before { + content: "\e193" +} +.glyphicon-copyright-mark:before { + content: "\e194" +} +.glyphicon-registration-mark:before { + content: "\e195" +} +.glyphicon-cloud-download:before { + content: "\e197" +} +.glyphicon-cloud-upload:before { + content: "\e198" +} +.glyphicon-tree-conifer:before { + content: "\e199" +} +.glyphicon-tree-deciduous:before { + content: "\e200" +} +.glyphicon-cd:before { + content: "\e201" +} +.glyphicon-save-file:before { + content: "\e202" +} +.glyphicon-open-file:before { + content: "\e203" +} +.glyphicon-level-up:before { + content: "\e204" +} +.glyphicon-copy:before { + content: "\e205" +} +.glyphicon-paste:before { + content: "\e206" +} +.glyphicon-alert:before { + content: "\e209" +} +.glyphicon-equalizer:before { + content: "\e210" +} +.glyphicon-king:before { + content: "\e211" +} +.glyphicon-queen:before { + content: "\e212" +} +.glyphicon-pawn:before { + content: "\e213" +} +.glyphicon-bishop:before { + content: "\e214" +} +.glyphicon-knight:before { + content: "\e215" +} +.glyphicon-baby-formula:before { + content: "\e216" +} +.glyphicon-tent:before { + content: "\26fa" +} +.glyphicon-blackboard:before { + content: "\e218" +} +.glyphicon-bed:before { + content: "\e219" +} +.glyphicon-apple:before { + content: "\f8ff" +} +.glyphicon-erase:before { + content: "\e221" +} +.glyphicon-hourglass:before { + content: "\231b" +} +.glyphicon-lamp:before { + content: "\e223" +} +.glyphicon-duplicate:before { + content: "\e224" +} +.glyphicon-piggy-bank:before { + content: "\e225" +} +.glyphicon-scissors:before { + content: "\e226" +} +.glyphicon-bitcoin:before { + content: "\e227" +} +.glyphicon-btc:before { + content: "\e227" +} +.glyphicon-xbt:before { + content: "\e227" +} +.glyphicon-yen:before { + content: "\00a5" +} +.glyphicon-jpy:before { + content: "\00a5" +} +.glyphicon-ruble:before { + content: "\20bd" +} +.glyphicon-rub:before { + content: "\20bd" +} +.glyphicon-scale:before { + content: "\e230" +} +.glyphicon-ice-lolly:before { + content: "\e231" +} +.glyphicon-ice-lolly-tasted:before { + content: "\e232" +} +.glyphicon-education:before { + content: "\e233" +} +.glyphicon-option-horizontal:before { + content: "\e234" +} +.glyphicon-option-vertical:before { + content: "\e235" +} +.glyphicon-menu-hamburger:before { + content: "\e236" +} +.glyphicon-modal-window:before { + content: "\e237" +} +.glyphicon-oil:before { + content: "\e238" +} +.glyphicon-grain:before { + content: "\e239" +} +.glyphicon-sunglasses:before { + content: "\e240" +} +.glyphicon-text-size:before { + content: "\e241" +} +.glyphicon-text-color:before { + content: "\e242" +} +.glyphicon-text-background:before { + content: "\e243" +} +.glyphicon-object-align-top:before { + content: "\e244" +} +.glyphicon-object-align-bottom:before { + content: "\e245" +} +.glyphicon-object-align-horizontal:before { + content: "\e246" +} +.glyphicon-object-align-left:before { + content: "\e247" +} +.glyphicon-object-align-vertical:before { + content: "\e248" +} +.glyphicon-object-align-right:before { + content: "\e249" +} +.glyphicon-triangle-right:before { + content: "\e250" +} +.glyphicon-triangle-left:before { + content: "\e251" +} +.glyphicon-triangle-bottom:before { + content: "\e252" +} +.glyphicon-triangle-top:before { + content: "\e253" +} +.glyphicon-console:before { + content: "\e254" +} +.glyphicon-superscript:before { + content: "\e255" +} +.glyphicon-subscript:before { + content: "\e256" +} +.glyphicon-menu-left:before { + content: "\e257" +} +.glyphicon-menu-right:before { + content: "\e258" +} +.glyphicon-menu-down:before { + content: "\e259" +} +.glyphicon-menu-up:before { + content: "\e260" +} +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box +} +:after, +:before { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box +} +html { + font-size: 10px; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0) +} +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.42857143; + color: #333; + background-color: #fff +} +button, +input, +select, +textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit +} +a { + color: #337ab7; + text-decoration: none +} +a:focus, +a:hover { + color: #23527c; + text-decoration: underline +} +a:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px +} +figure { + margin: 0 +} +img { + vertical-align: middle +} +.carousel-inner>.item>a>img, +.carousel-inner>.item>img, +.img-responsive, +.thumbnail a>img, +.thumbnail>img { + display: block; + max-width: 100%; + height: auto +} +.img-rounded { + border-radius: 6px +} +.img-thumbnail { + display: inline-block; + max-width: 100%; + height: auto; + padding: 4px; + line-height: 1.42857143; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 4px; + -webkit-transition: all .2s ease-in-out; + -o-transition: all .2s ease-in-out; + transition: all .2s ease-in-out +} +.img-circle { + border-radius: 50% +} +hr { + margin-top: 20px; + margin-bottom: 20px; + border: 0; + border-top: 1px solid #eee +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0 +} +.sr-only-focusable:active, +.sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto +} +[role=button] { + cursor: pointer +} +.h1, +.h2, +.h3, +.h4, +.h5, +.h6, +h1, +h2, +h3, +h4, +h5, +h6 { + font-family: inherit; + font-weight: 500; + line-height: 1.1; + color: inherit +} +.h1 .small, +.h1 small, +.h2 .small, +.h2 small, +.h3 .small, +.h3 small, +.h4 .small, +.h4 small, +.h5 .small, +.h5 small, +.h6 .small, +.h6 small, +h1 .small, +h1 small, +h2 .small, +h2 small, +h3 .small, +h3 small, +h4 .small, +h4 small, +h5 .small, +h5 small, +h6 .small, +h6 small { + font-weight: 400; + line-height: 1; + color: #777 +} +.h1, +.h2, +.h3, +h1, +h2, +h3 { + margin-top: 20px; + margin-bottom: 10px +} +.h1 .small, +.h1 small, +.h2 .small, +.h2 small, +.h3 .small, +.h3 small, +h1 .small, +h1 small, +h2 .small, +h2 small, +h3 .small, +h3 small { + font-size: 65% +} +.h4, +.h5, +.h6, +h4, +h5, +h6 { + margin-top: 10px; + margin-bottom: 10px +} +.h4 .small, +.h4 small, +.h5 .small, +.h5 small, +.h6 .small, +.h6 small, +h4 .small, +h4 small, +h5 .small, +h5 small, +h6 .small, +h6 small { + font-size: 75% +} +.h1, +h1 { + font-size: 36px +} +.h2, +h2 { + font-size: 30px +} +.h3, +h3 { + font-size: 24px +} +.h4, +h4 { + font-size: 18px +} +.h5, +h5 { + font-size: 14px +} +.h6, +h6 { + font-size: 12px +} +p { + margin: 0 0 10px +} +.lead { + margin-bottom: 20px; + font-size: 16px; + font-weight: 300; + line-height: 1.4 +} +@media (min-width: 768px) { + .lead { + font-size: 21px + } +} +.small, +small { + font-size: 85% +} +.mark, +mark { + padding: .2em; + background-color: #fcf8e3 +} +.text-left { + text-align: left +} +.text-right { + text-align: right +} +.text-center { + text-align: center +} +.text-justify { + text-align: justify +} +.text-nowrap { + white-space: nowrap +} +.text-lowercase { + text-transform: lowercase +} +.text-uppercase { + text-transform: uppercase +} +.text-capitalize { + text-transform: capitalize +} +.text-muted { + color: #777 +} +.text-primary { + color: #337ab7 +} +a.text-primary:hover { + color: #286090 +} +.text-success { + color: #3c763d +} +a.text-success:hover { + color: #2b542c +} +.text-info { + color: #31708f +} +a.text-info:hover { + color: #245269 +} +.text-warning { + color: #8a6d3b +} +a.text-warning:hover { + color: #66512c +} +.text-danger { + color: #a94442 +} +a.text-danger:hover { + color: #843534 +} +.bg-primary { + color: #fff; + background-color: #337ab7 +} +a.bg-primary:hover { + background-color: #286090 +} +.bg-success { + background-color: #dff0d8 +} +a.bg-success:hover { + background-color: #c1e2b3 +} +.bg-info { + background-color: #d9edf7 +} +a.bg-info:hover { + background-color: #afd9ee +} +.bg-warning { + background-color: #fcf8e3 +} +a.bg-warning:hover { + background-color: #f7ecb5 +} +.bg-danger { + background-color: #f2dede +} +a.bg-danger:hover { + background-color: #e4b9b9 +} +.page-header { + padding-bottom: 9px; + margin: 40px 0 20px; + border-bottom: 1px solid #eee +} +ol, +ul { + margin-top: 0; + margin-bottom: 10px +} +ol ol, +ol ul, +ul ol, +ul ul { + margin-bottom: 0 +} +.list-unstyled { + padding-left: 0; + list-style: none +} +.list-inline { + padding-left: 0; + margin-left: -5px; + list-style: none +} +.list-inline>li { + display: inline-block; + padding-right: 5px; + padding-left: 5px +} +dl { + margin-top: 0; + margin-bottom: 20px +} +dd, +dt { + line-height: 1.42857143 +} +dt { + font-weight: 700 +} +dd { + margin-left: 0 +} +@media (min-width: 768px) { + .dl-horizontal dt { + float: left; + width: 160px; + overflow: hidden; + clear: left; + text-align: right; + text-overflow: ellipsis; + white-space: nowrap + } + .dl-horizontal dd { + margin-left: 180px + } +} +abbr[data-original-title], +abbr[title] { + cursor: help; + border-bottom: 1px dotted #777 +} +.initialism { + font-size: 90%; + text-transform: uppercase +} +blockquote { + padding: 10px 20px; + margin: 0 0 20px; + font-size: 17.5px; + border-left: 5px solid #eee +} +blockquote ol:last-child, +blockquote p:last-child, +blockquote ul:last-child { + margin-bottom: 0 +} +blockquote .small, +blockquote footer, +blockquote small { + display: block; + font-size: 80%; + line-height: 1.42857143; + color: #777 +} +blockquote .small:before, +blockquote footer:before, +blockquote small:before { + content: '\2014 \00A0' +} +.blockquote-reverse, +blockquote.pull-right { + padding-right: 15px; + padding-left: 0; + text-align: right; + border-right: 5px solid #eee; + border-left: 0 +} +.blockquote-reverse .small:before, +.blockquote-reverse footer:before, +.blockquote-reverse small:before, +blockquote.pull-right .small:before, +blockquote.pull-right footer:before, +blockquote.pull-right small:before { + content: '' +} +.blockquote-reverse .small:after, +.blockquote-reverse footer:after, +.blockquote-reverse small:after, +blockquote.pull-right .small:after, +blockquote.pull-right footer:after, +blockquote.pull-right small:after { + content: '\00A0 \2014' +} +address { + margin-bottom: 20px; + font-style: normal; + line-height: 1.42857143 +} +code, +kbd, +pre, +samp { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace +} +code { + padding: 2px 4px; + font-size: 90%; + color: #c7254e; + background-color: #f9f2f4; + border-radius: 4px +} +kbd { + padding: 2px 4px; + font-size: 90%; + color: #fff; + background-color: #333; + border-radius: 3px; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25) +} +kbd kbd { + padding: 0; + font-size: 100%; + font-weight: 700; + -webkit-box-shadow: none; + box-shadow: none +} +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 1.42857143; + color: #333; + word-break: break-all; + word-wrap: break-word; + background-color: #f5f5f5; + border: 1px solid #ccc; + border-radius: 4px +} +pre code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0 +} +.pre-scrollable { + max-height: 340px; + overflow-y: scroll +} +.container { + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto +} +@media (min-width: 768px) { + .container { + width: 750px + } +} +@media (min-width: 992px) { + .container { + width: 970px + } +} +@media (min-width: 1200px) { + .container { + width: 1230px + } +} +.container-fluid { + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto +} +.row { + margin-right: -15px; + margin-left: -15px +} +.col-lg-1, +.col-lg-10, +.col-lg-11, +.col-lg-12, +.col-lg-2, +.col-lg-3, +.col-lg-4, +.col-lg-5, +.col-lg-6, +.col-lg-7, +.col-lg-8, +.col-lg-9, +.col-md-1, +.col-md-10, +.col-md-11, +.col-md-12, +.col-md-2, +.col-md-3, +.col-md-4, +.col-md-5, +.col-md-6, +.col-md-7, +.col-md-8, +.col-md-9, +.col-sm-1, +.col-sm-10, +.col-sm-11, +.col-sm-12, +.col-sm-2, +.col-sm-3, +.col-sm-4, +.col-sm-5, +.col-sm-6, +.col-sm-7, +.col-sm-8, +.col-sm-9, +.col-xs-1, +.col-xs-10, +.col-xs-11, +.col-xs-12, +.col-xs-2, +.col-xs-3, +.col-xs-4, +.col-xs-5, +.col-xs-6, +.col-xs-7, +.col-xs-8, +.col-xs-9 { + position: relative; + min-height: 1px; + padding-right: 15px; + padding-left: 15px +} +.col-xs-1, +.col-xs-10, +.col-xs-11, +.col-xs-12, +.col-xs-2, +.col-xs-3, +.col-xs-4, +.col-xs-5, +.col-xs-6, +.col-xs-7, +.col-xs-8, +.col-xs-9 { + float: left +} +.col-xs-12 { + width: 100% +} +.col-xs-11 { + width: 91.66666667% +} +.col-xs-10 { + width: 83.33333333% +} +.col-xs-9 { + width: 75% +} +.col-xs-8 { + width: 66.66666667% +} +.col-xs-7 { + width: 58.33333333% +} +.col-xs-6 { + width: 50% +} +.col-xs-5 { + width: 41.66666667% +} +.col-xs-4 { + width: 33.33333333% +} +.col-xs-3 { + width: 25% +} +.col-xs-2 { + width: 16.66666667% +} +.col-xs-1 { + width: 8.33333333% +} +.col-xs-pull-12 { + right: 100% +} +.col-xs-pull-11 { + right: 91.66666667% +} +.col-xs-pull-10 { + right: 83.33333333% +} +.col-xs-pull-9 { + right: 75% +} +.col-xs-pull-8 { + right: 66.66666667% +} +.col-xs-pull-7 { + right: 58.33333333% +} +.col-xs-pull-6 { + right: 50% +} +.col-xs-pull-5 { + right: 41.66666667% +} +.col-xs-pull-4 { + right: 33.33333333% +} +.col-xs-pull-3 { + right: 25% +} +.col-xs-pull-2 { + right: 16.66666667% +} +.col-xs-pull-1 { + right: 8.33333333% +} +.col-xs-pull-0 { + right: auto +} +.col-xs-push-12 { + left: 100% +} +.col-xs-push-11 { + left: 91.66666667% +} +.col-xs-push-10 { + left: 83.33333333% +} +.col-xs-push-9 { + left: 75% +} +.col-xs-push-8 { + left: 66.66666667% +} +.col-xs-push-7 { + left: 58.33333333% +} +.col-xs-push-6 { + left: 50% +} +.col-xs-push-5 { + left: 41.66666667% +} +.col-xs-push-4 { + left: 33.33333333% +} +.col-xs-push-3 { + left: 25% +} +.col-xs-push-2 { + left: 16.66666667% +} +.col-xs-push-1 { + left: 8.33333333% +} +.col-xs-push-0 { + left: auto +} +.col-xs-offset-12 { + margin-left: 100% +} +.col-xs-offset-11 { + margin-left: 91.66666667% +} +.col-xs-offset-10 { + margin-left: 83.33333333% +} +.col-xs-offset-9 { + margin-left: 75% +} +.col-xs-offset-8 { + margin-left: 66.66666667% +} +.col-xs-offset-7 { + margin-left: 58.33333333% +} +.col-xs-offset-6 { + margin-left: 50% +} +.col-xs-offset-5 { + margin-left: 41.66666667% +} +.col-xs-offset-4 { + margin-left: 33.33333333% +} +.col-xs-offset-3 { + margin-left: 25% +} +.col-xs-offset-2 { + margin-left: 16.66666667% +} +.col-xs-offset-1 { + margin-left: 8.33333333% +} +.col-xs-offset-0 { + margin-left: 0 +} +@media (min-width: 768px) { + .col-sm-1, + .col-sm-10, + .col-sm-11, + .col-sm-12, + .col-sm-2, + .col-sm-3, + .col-sm-4, + .col-sm-5, + .col-sm-6, + .col-sm-7, + .col-sm-8, + .col-sm-9 { + float: left + } + .col-sm-12 { + width: 100% + } + .col-sm-11 { + width: 91.66666667% + } + .col-sm-10 { + width: 83.33333333% + } + .col-sm-9 { + width: 75% + } + .col-sm-8 { + width: 66.66666667% + } + .col-sm-7 { + width: 58.33333333% + } + .col-sm-6 { + width: 50% + } + .col-sm-5 { + width: 41.66666667% + } + .col-sm-4 { + width: 33.33333333% + } + .col-sm-3 { + width: 25% + } + .col-sm-2 { + width: 16.66666667% + } + .col-sm-1 { + width: 8.33333333% + } + .col-sm-pull-12 { + right: 100% + } + .col-sm-pull-11 { + right: 91.66666667% + } + .col-sm-pull-10 { + right: 83.33333333% + } + .col-sm-pull-9 { + right: 75% + } + .col-sm-pull-8 { + right: 66.66666667% + } + .col-sm-pull-7 { + right: 58.33333333% + } + .col-sm-pull-6 { + right: 50% + } + .col-sm-pull-5 { + right: 41.66666667% + } + .col-sm-pull-4 { + right: 33.33333333% + } + .col-sm-pull-3 { + right: 25% + } + .col-sm-pull-2 { + right: 16.66666667% + } + .col-sm-pull-1 { + right: 8.33333333% + } + .col-sm-pull-0 { + right: auto + } + .col-sm-push-12 { + left: 100% + } + .col-sm-push-11 { + left: 91.66666667% + } + .col-sm-push-10 { + left: 83.33333333% + } + .col-sm-push-9 { + left: 75% + } + .col-sm-push-8 { + left: 66.66666667% + } + .col-sm-push-7 { + left: 58.33333333% + } + .col-sm-push-6 { + left: 50% + } + .col-sm-push-5 { + left: 41.66666667% + } + .col-sm-push-4 { + left: 33.33333333% + } + .col-sm-push-3 { + left: 25% + } + .col-sm-push-2 { + left: 16.66666667% + } + .col-sm-push-1 { + left: 8.33333333% + } + .col-sm-push-0 { + left: auto + } + .col-sm-offset-12 { + margin-left: 100% + } + .col-sm-offset-11 { + margin-left: 91.66666667% + } + .col-sm-offset-10 { + margin-left: 83.33333333% + } + .col-sm-offset-9 { + margin-left: 75% + } + .col-sm-offset-8 { + margin-left: 66.66666667% + } + .col-sm-offset-7 { + margin-left: 58.33333333% + } + .col-sm-offset-6 { + margin-left: 50% + } + .col-sm-offset-5 { + margin-left: 41.66666667% + } + .col-sm-offset-4 { + margin-left: 33.33333333% + } + .col-sm-offset-3 { + margin-left: 25% + } + .col-sm-offset-2 { + margin-left: 16.66666667% + } + .col-sm-offset-1 { + margin-left: 8.33333333% + } + .col-sm-offset-0 { + margin-left: 0 + } +} +@media (min-width: 992px) { + .col-md-1, + .col-md-10, + .col-md-11, + .col-md-12, + .col-md-2, + .col-md-3, + .col-md-4, + .col-md-5, + .col-md-6, + .col-md-7, + .col-md-8, + .col-md-9 { + float: left + } + .col-md-12 { + width: 100% + } + .col-md-11 { + width: 91.66666667% + } + .col-md-10 { + width: 83.33333333% + } + .col-md-9 { + width: 75% + } + .col-md-8 { + width: 66.66666667% + } + .col-md-7 { + width: 58.33333333% + } + .col-md-6 { + width: 50% + } + .col-md-5 { + width: 41.66666667% + } + .col-md-4 { + width: 33.33333333% + } + .col-md-3 { + width: 25% + } + .col-md-2 { + width: 16.66666667% + } + .col-md-1 { + width: 8.33333333% + } + .col-md-pull-12 { + right: 100% + } + .col-md-pull-11 { + right: 91.66666667% + } + .col-md-pull-10 { + right: 83.33333333% + } + .col-md-pull-9 { + right: 75% + } + .col-md-pull-8 { + right: 66.66666667% + } + .col-md-pull-7 { + right: 58.33333333% + } + .col-md-pull-6 { + right: 50% + } + .col-md-pull-5 { + right: 41.66666667% + } + .col-md-pull-4 { + right: 33.33333333% + } + .col-md-pull-3 { + right: 25% + } + .col-md-pull-2 { + right: 16.66666667% + } + .col-md-pull-1 { + right: 8.33333333% + } + .col-md-pull-0 { + right: auto + } + .col-md-push-12 { + left: 100% + } + .col-md-push-11 { + left: 91.66666667% + } + .col-md-push-10 { + left: 83.33333333% + } + .col-md-push-9 { + left: 75% + } + .col-md-push-8 { + left: 66.66666667% + } + .col-md-push-7 { + left: 58.33333333% + } + .col-md-push-6 { + left: 50% + } + .col-md-push-5 { + left: 41.66666667% + } + .col-md-push-4 { + left: 33.33333333% + } + .col-md-push-3 { + left: 25% + } + .col-md-push-2 { + left: 16.66666667% + } + .col-md-push-1 { + left: 8.33333333% + } + .col-md-push-0 { + left: auto + } + .col-md-offset-12 { + margin-left: 100% + } + .col-md-offset-11 { + margin-left: 91.66666667% + } + .col-md-offset-10 { + margin-left: 83.33333333% + } + .col-md-offset-9 { + margin-left: 75% + } + .col-md-offset-8 { + margin-left: 66.66666667% + } + .col-md-offset-7 { + margin-left: 58.33333333% + } + .col-md-offset-6 { + margin-left: 50% + } + .col-md-offset-5 { + margin-left: 41.66666667% + } + .col-md-offset-4 { + margin-left: 33.33333333% + } + .col-md-offset-3 { + margin-left: 25% + } + .col-md-offset-2 { + margin-left: 16.66666667% + } + .col-md-offset-1 { + margin-left: 8.33333333% + } + .col-md-offset-0 { + margin-left: 0 + } +} +@media (min-width: 1200px) { + .col-lg-1, + .col-lg-10, + .col-lg-11, + .col-lg-12, + .col-lg-2, + .col-lg-3, + .col-lg-4, + .col-lg-5, + .col-lg-6, + .col-lg-7, + .col-lg-8, + .col-lg-9 { + float: left + } + .col-lg-12 { + width: 100% + } + .col-lg-11 { + width: 91.66666667% + } + .col-lg-10 { + width: 83.33333333% + } + .col-lg-9 { + width: 75% + } + .col-lg-8 { + width: 66.66666667% + } + .col-lg-7 { + width: 58.33333333% + } + .col-lg-6 { + width: 50% + } + .col-lg-5 { + width: 41.66666667% + } + .col-lg-4 { + width: 33.33333333% + } + .col-lg-3 { + width: 25% + } + .col-lg-2 { + width: 16.66666667% + } + .col-lg-1 { + width: 8.33333333% + } + .col-lg-pull-12 { + right: 100% + } + .col-lg-pull-11 { + right: 91.66666667% + } + .col-lg-pull-10 { + right: 83.33333333% + } + .col-lg-pull-9 { + right: 75% + } + .col-lg-pull-8 { + right: 66.66666667% + } + .col-lg-pull-7 { + right: 58.33333333% + } + .col-lg-pull-6 { + right: 50% + } + .col-lg-pull-5 { + right: 41.66666667% + } + .col-lg-pull-4 { + right: 33.33333333% + } + .col-lg-pull-3 { + right: 25% + } + .col-lg-pull-2 { + right: 16.66666667% + } + .col-lg-pull-1 { + right: 8.33333333% + } + .col-lg-pull-0 { + right: auto + } + .col-lg-push-12 { + left: 100% + } + .col-lg-push-11 { + left: 91.66666667% + } + .col-lg-push-10 { + left: 83.33333333% + } + .col-lg-push-9 { + left: 75% + } + .col-lg-push-8 { + left: 66.66666667% + } + .col-lg-push-7 { + left: 58.33333333% + } + .col-lg-push-6 { + left: 50% + } + .col-lg-push-5 { + left: 41.66666667% + } + .col-lg-push-4 { + left: 33.33333333% + } + .col-lg-push-3 { + left: 25% + } + .col-lg-push-2 { + left: 16.66666667% + } + .col-lg-push-1 { + left: 8.33333333% + } + .col-lg-push-0 { + left: auto + } + .col-lg-offset-12 { + margin-left: 100% + } + .col-lg-offset-11 { + margin-left: 91.66666667% + } + .col-lg-offset-10 { + margin-left: 83.33333333% + } + .col-lg-offset-9 { + margin-left: 75% + } + .col-lg-offset-8 { + margin-left: 66.66666667% + } + .col-lg-offset-7 { + margin-left: 58.33333333% + } + .col-lg-offset-6 { + margin-left: 50% + } + .col-lg-offset-5 { + margin-left: 41.66666667% + } + .col-lg-offset-4 { + margin-left: 33.33333333% + } + .col-lg-offset-3 { + margin-left: 25% + } + .col-lg-offset-2 { + margin-left: 16.66666667% + } + .col-lg-offset-1 { + margin-left: 8.33333333% + } + .col-lg-offset-0 { + margin-left: 0 + } +} +table { + background-color: transparent +} +caption { + padding-top: 8px; + padding-bottom: 8px; + color: #777; + text-align: left +} +th { + text-align: left +} +.table { + width: 100%; + max-width: 100%; + margin-bottom: 20px +} +.table>tbody>tr>td, +.table>tbody>tr>th, +.table>tfoot>tr>td, +.table>tfoot>tr>th, +.table>thead>tr>td, +.table>thead>tr>th { + padding: 8px; + line-height: 1.42857143; + vertical-align: top; + border-top: 1px solid #ddd +} +.table>thead>tr>th { + vertical-align: bottom; + border-bottom: 2px solid #ddd +} +.table>caption+thead>tr:first-child>td, +.table>caption+thead>tr:first-child>th, +.table>colgroup+thead>tr:first-child>td, +.table>colgroup+thead>tr:first-child>th, +.table>thead:first-child>tr:first-child>td, +.table>thead:first-child>tr:first-child>th { + border-top: 0 +} +.table>tbody+tbody { + border-top: 2px solid #ddd +} +.table .table { + background-color: #fff +} +.table-condensed>tbody>tr>td, +.table-condensed>tbody>tr>th, +.table-condensed>tfoot>tr>td, +.table-condensed>tfoot>tr>th, +.table-condensed>thead>tr>td, +.table-condensed>thead>tr>th { + padding: 5px +} +.table-bordered { + border: 1px solid #ddd +} +.table-bordered>tbody>tr>td, +.table-bordered>tbody>tr>th, +.table-bordered>tfoot>tr>td, +.table-bordered>tfoot>tr>th, +.table-bordered>thead>tr>td, +.table-bordered>thead>tr>th { + border: 1px solid #ddd +} +.table-bordered>thead>tr>td, +.table-bordered>thead>tr>th { + border-bottom-width: 2px +} +.table-striped>tbody>tr:nth-of-type(odd) { + background-color: #f9f9f9 +} +.table-hover>tbody>tr:hover { + background-color: #f5f5f5 +} +table col[class*=col-] { + position: static; + display: table-column; + float: none +} +table td[class*=col-], +table th[class*=col-] { + position: static; + display: table-cell; + float: none +} +.table>tbody>tr.active>td, +.table>tbody>tr.active>th, +.table>tbody>tr>td.active, +.table>tbody>tr>th.active, +.table>tfoot>tr.active>td, +.table>tfoot>tr.active>th, +.table>tfoot>tr>td.active, +.table>tfoot>tr>th.active, +.table>thead>tr.active>td, +.table>thead>tr.active>th, +.table>thead>tr>td.active, +.table>thead>tr>th.active { + background-color: #f5f5f5 +} +.table-hover>tbody>tr.active:hover>td, +.table-hover>tbody>tr.active:hover>th, +.table-hover>tbody>tr:hover>.active, +.table-hover>tbody>tr>td.active:hover, +.table-hover>tbody>tr>th.active:hover { + background-color: #e8e8e8 +} +.table>tbody>tr.success>td, +.table>tbody>tr.success>th, +.table>tbody>tr>td.success, +.table>tbody>tr>th.success, +.table>tfoot>tr.success>td, +.table>tfoot>tr.success>th, +.table>tfoot>tr>td.success, +.table>tfoot>tr>th.success, +.table>thead>tr.success>td, +.table>thead>tr.success>th, +.table>thead>tr>td.success, +.table>thead>tr>th.success { + background-color: #dff0d8 +} +.table-hover>tbody>tr.success:hover>td, +.table-hover>tbody>tr.success:hover>th, +.table-hover>tbody>tr:hover>.success, +.table-hover>tbody>tr>td.success:hover, +.table-hover>tbody>tr>th.success:hover { + background-color: #d0e9c6 +} +.table>tbody>tr.info>td, +.table>tbody>tr.info>th, +.table>tbody>tr>td.info, +.table>tbody>tr>th.info, +.table>tfoot>tr.info>td, +.table>tfoot>tr.info>th, +.table>tfoot>tr>td.info, +.table>tfoot>tr>th.info, +.table>thead>tr.info>td, +.table>thead>tr.info>th, +.table>thead>tr>td.info, +.table>thead>tr>th.info { + background-color: #d9edf7 +} +.table-hover>tbody>tr.info:hover>td, +.table-hover>tbody>tr.info:hover>th, +.table-hover>tbody>tr:hover>.info, +.table-hover>tbody>tr>td.info:hover, +.table-hover>tbody>tr>th.info:hover { + background-color: #c4e3f3 +} +.table>tbody>tr.warning>td, +.table>tbody>tr.warning>th, +.table>tbody>tr>td.warning, +.table>tbody>tr>th.warning, +.table>tfoot>tr.warning>td, +.table>tfoot>tr.warning>th, +.table>tfoot>tr>td.warning, +.table>tfoot>tr>th.warning, +.table>thead>tr.warning>td, +.table>thead>tr.warning>th, +.table>thead>tr>td.warning, +.table>thead>tr>th.warning { + background-color: #fcf8e3 +} +.table-hover>tbody>tr.warning:hover>td, +.table-hover>tbody>tr.warning:hover>th, +.table-hover>tbody>tr:hover>.warning, +.table-hover>tbody>tr>td.warning:hover, +.table-hover>tbody>tr>th.warning:hover { + background-color: #faf2cc +} +.table>tbody>tr.danger>td, +.table>tbody>tr.danger>th, +.table>tbody>tr>td.danger, +.table>tbody>tr>th.danger, +.table>tfoot>tr.danger>td, +.table>tfoot>tr.danger>th, +.table>tfoot>tr>td.danger, +.table>tfoot>tr>th.danger, +.table>thead>tr.danger>td, +.table>thead>tr.danger>th, +.table>thead>tr>td.danger, +.table>thead>tr>th.danger { + background-color: #f2dede +} +.table-hover>tbody>tr.danger:hover>td, +.table-hover>tbody>tr.danger:hover>th, +.table-hover>tbody>tr:hover>.danger, +.table-hover>tbody>tr>td.danger:hover, +.table-hover>tbody>tr>th.danger:hover { + background-color: #ebcccc +} +.table-responsive { + min-height: .01%; + overflow-x: auto +} +@media screen and (max-width: 767px) { + .table-responsive { + width: 100%; + margin-bottom: 15px; + overflow-y: hidden; + -ms-overflow-style: -ms-autohiding-scrollbar; + border: 1px solid #ddd + } + .table-responsive>.table { + margin-bottom: 0 + } + .table-responsive>.table>tbody>tr>td, + .table-responsive>.table>tbody>tr>th, + .table-responsive>.table>tfoot>tr>td, + .table-responsive>.table>tfoot>tr>th, + .table-responsive>.table>thead>tr>td, + .table-responsive>.table>thead>tr>th { + white-space: nowrap + } + .table-responsive>.table-bordered { + border: 0 + } + .table-responsive>.table-bordered>tbody>tr>td:first-child, + .table-responsive>.table-bordered>tbody>tr>th:first-child, + .table-responsive>.table-bordered>tfoot>tr>td:first-child, + .table-responsive>.table-bordered>tfoot>tr>th:first-child, + .table-responsive>.table-bordered>thead>tr>td:first-child, + .table-responsive>.table-bordered>thead>tr>th:first-child { + border-left: 0 + } + .table-responsive>.table-bordered>tbody>tr>td:last-child, + .table-responsive>.table-bordered>tbody>tr>th:last-child, + .table-responsive>.table-bordered>tfoot>tr>td:last-child, + .table-responsive>.table-bordered>tfoot>tr>th:last-child, + .table-responsive>.table-bordered>thead>tr>td:last-child, + .table-responsive>.table-bordered>thead>tr>th:last-child { + border-right: 0 + } + .table-responsive>.table-bordered>tbody>tr:last-child>td, + .table-responsive>.table-bordered>tbody>tr:last-child>th, + .table-responsive>.table-bordered>tfoot>tr:last-child>td, + .table-responsive>.table-bordered>tfoot>tr:last-child>th { + border-bottom: 0 + } +} +fieldset { + min-width: 0; + padding: 0; + margin: 0; + border: 0 +} +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: inherit; + color: #333; + border: 0; + border-bottom: 1px solid #e5e5e5 +} +label { + display: inline-block; + max-width: 100%; + margin-bottom: 5px; + font-weight: 700 +} +input[type=search] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box +} +input[type=checkbox], +input[type=radio] { + margin: 4px 0 0; + margin-top: 1px \9; + line-height: normal +} +input[type=file] { + display: block +} +input[type=range] { + display: block; + width: 100% +} +select[multiple], +select[size] { + height: auto +} +input[type=file]:focus, +input[type=checkbox]:focus, +input[type=radio]:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px +} +output { + display: block; + padding-top: 7px; + font-size: 14px; + line-height: 1.42857143; + color: #555 +} +.form-control { + display: block; + width: 100%; + height: 34px; + padding: 6px 12px; + font-size: 14px; + line-height: 1.42857143; + color: #555; + background-color: #fff; + background-image: none; + border: 1px solid #ccc; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; + -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s +} +.form-control:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6) +} +.form-control::-moz-placeholder { + color: #999; + opacity: 1 +} +.form-control:-ms-input-placeholder { + color: #999 +} +.form-control::-webkit-input-placeholder { + color: #999 +} +.form-control[disabled], +.form-control[readonly], +fieldset[disabled] .form-control { + background-color: #eee; + opacity: 1 +} +.form-control[disabled], +fieldset[disabled] .form-control { + cursor: not-allowed +} +textarea.form-control { + height: auto +} +input[type=search] { + -webkit-appearance: none +} +@media screen and (-webkit-min-device-pixel-ratio: 0) { + input[type=date], + input[type=time], + input[type=datetime-local], + input[type=month] { + line-height: 34px + } + .input-group-sm input[type=date], + .input-group-sm input[type=time], + .input-group-sm input[type=datetime-local], + .input-group-sm input[type=month], + input[type=date].input-sm, + input[type=time].input-sm, + input[type=datetime-local].input-sm, + input[type=month].input-sm { + line-height: 30px + } + .input-group-lg input[type=date], + .input-group-lg input[type=time], + .input-group-lg input[type=datetime-local], + .input-group-lg input[type=month], + input[type=date].input-lg, + input[type=time].input-lg, + input[type=datetime-local].input-lg, + input[type=month].input-lg { + line-height: 46px + } +} +.form-group { + margin-bottom: 15px +} +.checkbox, +.radio { + position: relative; + display: block; + margin-top: 10px; + margin-bottom: 10px +} +.checkbox label, +.radio label { + min-height: 20px; + padding-left: 20px; + margin-bottom: 0; + font-weight: 400; + cursor: pointer +} +.checkbox input[type=checkbox], +.checkbox-inline input[type=checkbox], +.radio input[type=radio], +.radio-inline input[type=radio] { + position: absolute; + margin-top: 4px \9; + margin-left: -20px +} +.checkbox+.checkbox, +.radio+.radio { + margin-top: -5px +} +.checkbox-inline, +.radio-inline { + position: relative; + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + font-weight: 400; + vertical-align: middle; + cursor: pointer +} +.checkbox-inline+.checkbox-inline, +.radio-inline+.radio-inline { + margin-top: 0; + margin-left: 10px +} +fieldset[disabled] input[type=checkbox], +fieldset[disabled] input[type=radio], +input[type=checkbox].disabled, +input[type=checkbox][disabled], +input[type=radio].disabled, +input[type=radio][disabled] { + cursor: not-allowed +} +.checkbox-inline.disabled, +.radio-inline.disabled, +fieldset[disabled] .checkbox-inline, +fieldset[disabled] .radio-inline { + cursor: not-allowed +} +.checkbox.disabled label, +.radio.disabled label, +fieldset[disabled] .checkbox label, +fieldset[disabled] .radio label { + cursor: not-allowed +} +.form-control-static { + min-height: 34px; + padding-top: 7px; + padding-bottom: 7px; + margin-bottom: 0 +} +.form-control-static.input-lg, +.form-control-static.input-sm { + padding-right: 0; + padding-left: 0 +} +.input-sm { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px +} +select.input-sm { + height: 30px; + line-height: 30px +} +select[multiple].input-sm, +textarea.input-sm { + height: auto +} +.form-group-sm .form-control { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px +} +select.form-group-sm .form-control { + height: 30px; + line-height: 30px +} +select[multiple].form-group-sm .form-control, +textarea.form-group-sm .form-control { + height: auto +} +.form-group-sm .form-control-static { + height: 30px; + min-height: 32px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5 +} +.input-lg { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px +} +select.input-lg { + height: 46px; + line-height: 46px +} +select[multiple].input-lg, +textarea.input-lg { + height: auto +} +.form-group-lg .form-control { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px +} +select.form-group-lg .form-control { + height: 46px; + line-height: 46px +} +select[multiple].form-group-lg .form-control, +textarea.form-group-lg .form-control { + height: auto +} +.form-group-lg .form-control-static { + height: 46px; + min-height: 38px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333 +} +.has-feedback { + position: relative +} +.has-feedback .form-control { + padding-right: 42.5px +} +.form-control-feedback { + position: absolute; + top: 0; + right: 0; + z-index: 2; + display: block; + width: 34px; + height: 34px; + line-height: 34px; + text-align: center; + pointer-events: none +} +.input-lg+.form-control-feedback { + width: 46px; + height: 46px; + line-height: 46px +} +.input-sm+.form-control-feedback { + width: 30px; + height: 30px; + line-height: 30px +} +.has-success .checkbox, +.has-success .checkbox-inline, +.has-success .control-label, +.has-success .help-block, +.has-success .radio, +.has-success .radio-inline, +.has-success.checkbox label, +.has-success.checkbox-inline label, +.has-success.radio label, +.has-success.radio-inline label { + color: #3c763d +} +.has-success .form-control { + border-color: #3c763d; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075) +} +.has-success .form-control:focus { + border-color: #2b542c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168 +} +.has-success .input-group-addon { + color: #3c763d; + background-color: #dff0d8; + border-color: #3c763d +} +.has-success .form-control-feedback { + color: #3c763d +} +.has-warning .checkbox, +.has-warning .checkbox-inline, +.has-warning .control-label, +.has-warning .help-block, +.has-warning .radio, +.has-warning .radio-inline, +.has-warning.checkbox label, +.has-warning.checkbox-inline label, +.has-warning.radio label, +.has-warning.radio-inline label { + color: #8a6d3b +} +.has-warning .form-control { + border-color: #8a6d3b; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075) +} +.has-warning .form-control:focus { + border-color: #66512c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b +} +.has-warning .input-group-addon { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #8a6d3b +} +.has-warning .form-control-feedback { + color: #8a6d3b +} +.has-error .checkbox, +.has-error .checkbox-inline, +.has-error .control-label, +.has-error .help-block, +.has-error .radio, +.has-error .radio-inline, +.has-error.checkbox label, +.has-error.checkbox-inline label, +.has-error.radio label, +.has-error.radio-inline label { + color: #a94442 +} +.has-error .form-control { + border-color: #a94442; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075) +} +.has-error .form-control:focus { + border-color: #843534; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483 +} +.has-error .input-group-addon { + color: #a94442; + background-color: #f2dede; + border-color: #a94442 +} +.has-error .form-control-feedback { + color: #a94442 +} +.has-feedback label~.form-control-feedback { + top: 25px +} +.has-feedback label.sr-only~.form-control-feedback { + top: 0 +} +.help-block { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #737373 +} +@media (min-width: 768px) { + .form-inline .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle + } + .form-inline .form-control { + display: inline-block; + width: auto; + vertical-align: middle + } + .form-inline .form-control-static { + display: inline-block + } + .form-inline .input-group { + display: inline-table; + vertical-align: middle + } + .form-inline .input-group .form-control, + .form-inline .input-group .input-group-addon, + .form-inline .input-group .input-group-btn { + width: auto + } + .form-inline .input-group>.form-control { + width: 100% + } + .form-inline .control-label { + margin-bottom: 0; + vertical-align: middle + } + .form-inline .checkbox, + .form-inline .radio { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle + } + .form-inline .checkbox label, + .form-inline .radio label { + padding-left: 0 + } + .form-inline .checkbox input[type=checkbox], + .form-inline .radio input[type=radio] { + position: relative; + margin-left: 0 + } + .form-inline .has-feedback .form-control-feedback { + top: 0 + } +} +.form-horizontal .checkbox, +.form-horizontal .checkbox-inline, +.form-horizontal .radio, +.form-horizontal .radio-inline { + padding-top: 7px; + margin-top: 0; + margin-bottom: 0 +} +.form-horizontal .checkbox, +.form-horizontal .radio { + min-height: 27px +} +.form-horizontal .form-group { + margin-right: -15px; + margin-left: -15px +} +@media (min-width: 768px) { + .form-horizontal .control-label { + padding-top: 7px; + margin-bottom: 0; + text-align: right + } +} +.form-horizontal .has-feedback .form-control-feedback { + right: 15px +} +@media (min-width: 768px) { + .form-horizontal .form-group-lg .control-label { + padding-top: 14.33px + } +} +@media (min-width: 768px) { + .form-horizontal .form-group-sm .control-label { + padding-top: 6px + } +} +.btn { + display: inline-block; + padding: 6px 12px; + margin-bottom: 0; + font-size: 14px; + font-weight: 400; + line-height: 1.42857143; + text-align: center; + white-space: nowrap; + vertical-align: middle; + -ms-touch-action: manipulation; + touch-action: manipulation; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + background-image: none; + border: 1px solid transparent; + border-radius: 4px +} +.btn.active.focus, +.btn.active:focus, +.btn.focus, +.btn:active.focus, +.btn:active:focus, +.btn:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px +} +.btn.focus, +.btn:focus, +.btn:hover { + color: #333; + text-decoration: none +} +.btn.active, +.btn:active { + background-image: none; + outline: 0; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125) +} +.btn.disabled, +.btn[disabled], +fieldset[disabled] .btn { + pointer-events: none; + cursor: not-allowed; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; + opacity: .65 +} +.btn-default { + color: #333; + background-color: #fff; + border-color: #ccc +} +.btn-default.active, +.btn-default.focus, +.btn-default:active, +.btn-default:focus, +.btn-default:hover, +.open>.dropdown-toggle.btn-default { + color: #333; + background-color: #e6e6e6; + border-color: #adadad +} +.btn-default.active, +.btn-default:active, +.open>.dropdown-toggle.btn-default { + background-image: none +} +.btn-default.disabled, +.btn-default.disabled.active, +.btn-default.disabled.focus, +.btn-default.disabled:active, +.btn-default.disabled:focus, +.btn-default.disabled:hover, +.btn-default[disabled], +.btn-default[disabled].active, +.btn-default[disabled].focus, +.btn-default[disabled]:active, +.btn-default[disabled]:focus, +.btn-default[disabled]:hover, +fieldset[disabled] .btn-default, +fieldset[disabled] .btn-default.active, +fieldset[disabled] .btn-default.focus, +fieldset[disabled] .btn-default:active, +fieldset[disabled] .btn-default:focus, +fieldset[disabled] .btn-default:hover { + background-color: #fff; + border-color: #ccc +} +.btn-default .badge { + color: #fff; + background-color: #333 +} +.btn-primary { + color: #fff; + background-color: #337ab7; + border-color: #2e6da4 +} +.btn-primary.active, +.btn-primary.focus, +.btn-primary:active, +.btn-primary:focus, +.btn-primary:hover, +.open>.dropdown-toggle.btn-primary { + color: #fff; + background-color: #286090; + border-color: #204d74 +} +.btn-primary.active, +.btn-primary:active, +.open>.dropdown-toggle.btn-primary { + background-image: none +} +.btn-primary.disabled, +.btn-primary.disabled.active, +.btn-primary.disabled.focus, +.btn-primary.disabled:active, +.btn-primary.disabled:focus, +.btn-primary.disabled:hover, +.btn-primary[disabled], +.btn-primary[disabled].active, +.btn-primary[disabled].focus, +.btn-primary[disabled]:active, +.btn-primary[disabled]:focus, +.btn-primary[disabled]:hover, +fieldset[disabled] .btn-primary, +fieldset[disabled] .btn-primary.active, +fieldset[disabled] .btn-primary.focus, +fieldset[disabled] .btn-primary:active, +fieldset[disabled] .btn-primary:focus, +fieldset[disabled] .btn-primary:hover { + background-color: #337ab7; + border-color: #2e6da4 +} +.btn-primary .badge { + color: #337ab7; + background-color: #fff +} +.btn-success { + color: #fff; + background-color: #5cb85c; + border-color: #4cae4c +} +.btn-success.active, +.btn-success.focus, +.btn-success:active, +.btn-success:focus, +.btn-success:hover, +.open>.dropdown-toggle.btn-success { + color: #fff; + background-color: #449d44; + border-color: #398439 +} +.btn-success.active, +.btn-success:active, +.open>.dropdown-toggle.btn-success { + background-image: none +} +.btn-success.disabled, +.btn-success.disabled.active, +.btn-success.disabled.focus, +.btn-success.disabled:active, +.btn-success.disabled:focus, +.btn-success.disabled:hover, +.btn-success[disabled], +.btn-success[disabled].active, +.btn-success[disabled].focus, +.btn-success[disabled]:active, +.btn-success[disabled]:focus, +.btn-success[disabled]:hover, +fieldset[disabled] .btn-success, +fieldset[disabled] .btn-success.active, +fieldset[disabled] .btn-success.focus, +fieldset[disabled] .btn-success:active, +fieldset[disabled] .btn-success:focus, +fieldset[disabled] .btn-success:hover { + background-color: #5cb85c; + border-color: #4cae4c +} +.btn-success .badge { + color: #5cb85c; + background-color: #fff +} +.btn-info { + color: #fff; + background-color: #5bc0de; + border-color: #46b8da +} +.btn-info.active, +.btn-info.focus, +.btn-info:active, +.btn-info:focus, +.btn-info:hover, +.open>.dropdown-toggle.btn-info { + color: #fff; + background-color: #31b0d5; + border-color: #269abc +} +.btn-info.active, +.btn-info:active, +.open>.dropdown-toggle.btn-info { + background-image: none +} +.btn-info.disabled, +.btn-info.disabled.active, +.btn-info.disabled.focus, +.btn-info.disabled:active, +.btn-info.disabled:focus, +.btn-info.disabled:hover, +.btn-info[disabled], +.btn-info[disabled].active, +.btn-info[disabled].focus, +.btn-info[disabled]:active, +.btn-info[disabled]:focus, +.btn-info[disabled]:hover, +fieldset[disabled] .btn-info, +fieldset[disabled] .btn-info.active, +fieldset[disabled] .btn-info.focus, +fieldset[disabled] .btn-info:active, +fieldset[disabled] .btn-info:focus, +fieldset[disabled] .btn-info:hover { + background-color: #5bc0de; + border-color: #46b8da +} +.btn-info .badge { + color: #5bc0de; + background-color: #fff +} +.btn-warning { + color: #fff; + background-color: #f0ad4e; + border-color: #eea236 +} +.btn-warning.active, +.btn-warning.focus, +.btn-warning:active, +.btn-warning:focus, +.btn-warning:hover, +.open>.dropdown-toggle.btn-warning { + color: #fff; + background-color: #ec971f; + border-color: #d58512 +} +.btn-warning.active, +.btn-warning:active, +.open>.dropdown-toggle.btn-warning { + background-image: none +} +.btn-warning.disabled, +.btn-warning.disabled.active, +.btn-warning.disabled.focus, +.btn-warning.disabled:active, +.btn-warning.disabled:focus, +.btn-warning.disabled:hover, +.btn-warning[disabled], +.btn-warning[disabled].active, +.btn-warning[disabled].focus, +.btn-warning[disabled]:active, +.btn-warning[disabled]:focus, +.btn-warning[disabled]:hover, +fieldset[disabled] .btn-warning, +fieldset[disabled] .btn-warning.active, +fieldset[disabled] .btn-warning.focus, +fieldset[disabled] .btn-warning:active, +fieldset[disabled] .btn-warning:focus, +fieldset[disabled] .btn-warning:hover { + background-color: #f0ad4e; + border-color: #eea236 +} +.btn-warning .badge { + color: #f0ad4e; + background-color: #fff +} +.btn-danger { + color: #fff; + background-color: #d9534f; + border-color: #d43f3a +} +.btn-danger.active, +.btn-danger.focus, +.btn-danger:active, +.btn-danger:focus, +.btn-danger:hover, +.open>.dropdown-toggle.btn-danger { + color: #fff; + background-color: #c9302c; + border-color: #ac2925 +} +.btn-danger.active, +.btn-danger:active, +.open>.dropdown-toggle.btn-danger { + background-image: none +} +.btn-danger.disabled, +.btn-danger.disabled.active, +.btn-danger.disabled.focus, +.btn-danger.disabled:active, +.btn-danger.disabled:focus, +.btn-danger.disabled:hover, +.btn-danger[disabled], +.btn-danger[disabled].active, +.btn-danger[disabled].focus, +.btn-danger[disabled]:active, +.btn-danger[disabled]:focus, +.btn-danger[disabled]:hover, +fieldset[disabled] .btn-danger, +fieldset[disabled] .btn-danger.active, +fieldset[disabled] .btn-danger.focus, +fieldset[disabled] .btn-danger:active, +fieldset[disabled] .btn-danger:focus, +fieldset[disabled] .btn-danger:hover { + background-color: #d9534f; + border-color: #d43f3a +} +.btn-danger .badge { + color: #d9534f; + background-color: #fff +} +.btn-link { + font-weight: 400; + color: #337ab7; + border-radius: 0 +} +.btn-link, +.btn-link.active, +.btn-link:active, +.btn-link[disabled], +fieldset[disabled] .btn-link { + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none +} +.btn-link, +.btn-link:active, +.btn-link:focus, +.btn-link:hover { + border-color: transparent +} +.btn-link:focus, +.btn-link:hover { + color: #23527c; + text-decoration: underline; + background-color: transparent +} +.btn-link[disabled]:focus, +.btn-link[disabled]:hover, +fieldset[disabled] .btn-link:focus, +fieldset[disabled] .btn-link:hover { + color: #777; + text-decoration: none +} +.btn-group-lg>.btn, +.btn-lg { + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px +} +.btn-group-sm>.btn, +.btn-sm { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px +} +.btn-group-xs>.btn, +.btn-xs { + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px +} +.btn-block { + display: block; + width: 100% +} +.btn-block+.btn-block { + margin-top: 5px +} +input[type=button].btn-block, +input[type=reset].btn-block, +input[type=submit].btn-block { + width: 100% +} +.fade { + opacity: 0; + -webkit-transition: opacity .15s linear; + -o-transition: opacity .15s linear; + transition: opacity .15s linear +} +.fade.in { + opacity: 1 +} +.collapse { + display: none +} +.collapse.in { + display: block +} +tr.collapse.in { + display: table-row +} +tbody.collapse.in { + display: table-row-group +} +.collapsing { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition-timing-function: ease; + -o-transition-timing-function: ease; + transition-timing-function: ease; + -webkit-transition-duration: .35s; + -o-transition-duration: .35s; + transition-duration: .35s; + -webkit-transition-property: height, visibility; + -o-transition-property: height, visibility; + transition-property: height, visibility +} +.caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: 4px dashed; + border-right: 4px solid transparent; + border-left: 4px solid transparent +} +.dropdown, +.dropup { + position: relative +} +.dropdown-toggle:focus { + outline: 0 +} +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + font-size: 14px; + text-align: left; + list-style: none; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, .15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); + box-shadow: 0 6px 12px rgba(0, 0, 0, .175) +} +.dropdown-menu.pull-right { + right: 0; + left: auto +} +.dropdown-menu .divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5 +} +.dropdown-menu>li>a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: 400; + line-height: 1.42857143; + color: #333; + white-space: nowrap +} +.dropdown-menu>li>a:focus, +.dropdown-menu>li>a:hover { + color: #262626; + text-decoration: none; + background-color: #f5f5f5 +} +.dropdown-menu>.active>a, +.dropdown-menu>.active>a:focus, +.dropdown-menu>.active>a:hover { + color: #fff; + text-decoration: none; + background-color: #337ab7; + outline: 0 +} +.dropdown-menu>.disabled>a, +.dropdown-menu>.disabled>a:focus, +.dropdown-menu>.disabled>a:hover { + color: #777 +} +.dropdown-menu>.disabled>a:focus, +.dropdown-menu>.disabled>a:hover { + text-decoration: none; + cursor: not-allowed; + background-color: transparent; + background-image: none; + filter: progid: DXImageTransform.Microsoft.gradient(enabled=false) +} +.open>.dropdown-menu { + display: block +} +.open>a { + outline: 0 +} +.dropdown-menu-right { + right: 0; + left: auto +} +.dropdown-menu-left { + right: auto; + left: 0 +} +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.42857143; + color: #777; + white-space: nowrap +} +.dropdown-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 990 +} +.pull-right>.dropdown-menu { + right: 0; + left: auto +} +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + content: ""; + border-top: 0; + border-bottom: 4px solid +} +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 2px +} +@media (min-width: 768px) { + .navbar-right .dropdown-menu { + right: 0; + left: auto + } + .navbar-right .dropdown-menu-left { + right: auto; + left: 0 + } +} +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-block; + vertical-align: middle +} +.btn-group-vertical>.btn, +.btn-group>.btn { + position: relative; + float: left +} +.btn-group-vertical>.btn.active, +.btn-group-vertical>.btn:active, +.btn-group-vertical>.btn:focus, +.btn-group-vertical>.btn:hover, +.btn-group>.btn.active, +.btn-group>.btn:active, +.btn-group>.btn:focus, +.btn-group>.btn:hover { + z-index: 2 +} +.btn-group .btn+.btn, +.btn-group .btn+.btn-group, +.btn-group .btn-group+.btn, +.btn-group .btn-group+.btn-group { + margin-left: -1px +} +.btn-toolbar { + margin-left: -5px +} +.btn-toolbar .btn-group, +.btn-toolbar .input-group { + float: left +} +.btn-toolbar>.btn, +.btn-toolbar>.btn-group, +.btn-toolbar>.input-group { + margin-left: 5px +} +.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { + border-radius: 0 +} +.btn-group>.btn:first-child { + margin-left: 0 +} +.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle) { + border-top-right-radius: 0; + border-bottom-right-radius: 0 +} +.btn-group>.btn:last-child:not(:first-child), +.btn-group>.dropdown-toggle:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0 +} +.btn-group>.btn-group { + float: left +} +.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn { + border-radius: 0 +} +.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child, +.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle { + border-top-right-radius: 0; + border-bottom-right-radius: 0 +} +.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child { + border-top-left-radius: 0; + border-bottom-left-radius: 0 +} +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0 +} +.btn-group>.btn+.dropdown-toggle { + padding-right: 8px; + padding-left: 8px +} +.btn-group>.btn-lg+.dropdown-toggle { + padding-right: 12px; + padding-left: 12px +} +.btn-group.open .dropdown-toggle { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125) +} +.btn-group.open .dropdown-toggle.btn-link { + -webkit-box-shadow: none; + box-shadow: none +} +.btn .caret { + margin-left: 0 +} +.btn-lg .caret { + border-width: 5px 5px 0; + border-bottom-width: 0 +} +.dropup .btn-lg .caret { + border-width: 0 5px 5px +} +.btn-group-vertical>.btn, +.btn-group-vertical>.btn-group, +.btn-group-vertical>.btn-group>.btn { + display: block; + float: none; + width: 100%; + max-width: 100% +} +.btn-group-vertical>.btn-group>.btn { + float: none +} +.btn-group-vertical>.btn+.btn, +.btn-group-vertical>.btn+.btn-group, +.btn-group-vertical>.btn-group+.btn, +.btn-group-vertical>.btn-group+.btn-group { + margin-top: -1px; + margin-left: 0 +} +.btn-group-vertical>.btn:not(:first-child):not(:last-child) { + border-radius: 0 +} +.btn-group-vertical>.btn:first-child:not(:last-child) { + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0 +} +.btn-group-vertical>.btn:last-child:not(:first-child) { + border-top-left-radius: 0; + border-top-right-radius: 0; + border-bottom-left-radius: 4px +} +.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn { + border-radius: 0 +} +.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child, +.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0 +} +.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child { + border-top-left-radius: 0; + border-top-right-radius: 0 +} +.btn-group-justified { + display: table; + width: 100%; + table-layout: fixed; + border-collapse: separate +} +.btn-group-justified>.btn, +.btn-group-justified>.btn-group { + display: table-cell; + float: none; + width: 1% +} +.btn-group-justified>.btn-group .btn { + width: 100% +} +.btn-group-justified>.btn-group .dropdown-menu { + left: auto +} +[data-toggle=buttons]>.btn input[type=checkbox], +[data-toggle=buttons]>.btn input[type=radio], +[data-toggle=buttons]>.btn-group>.btn input[type=checkbox], +[data-toggle=buttons]>.btn-group>.btn input[type=radio] { + position: absolute; + clip: rect(0, 0, 0, 0); + pointer-events: none +} +.input-group { + position: relative; + display: table; + border-collapse: separate +} +.input-group[class*=col-] { + float: none; + padding-right: 0; + padding-left: 0 +} +.input-group .form-control { + position: relative; + z-index: 2; + float: left; + width: 100%; + margin-bottom: 0 +} +.input-group-lg>.form-control, +.input-group-lg>.input-group-addon, +.input-group-lg>.input-group-btn>.btn { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px +} +select.input-group-lg>.form-control, +select.input-group-lg>.input-group-addon, +select.input-group-lg>.input-group-btn>.btn { + height: 46px; + line-height: 46px +} +select[multiple].input-group-lg>.form-control, +select[multiple].input-group-lg>.input-group-addon, +select[multiple].input-group-lg>.input-group-btn>.btn, +textarea.input-group-lg>.form-control, +textarea.input-group-lg>.input-group-addon, +textarea.input-group-lg>.input-group-btn>.btn { + height: auto +} +.input-group-sm>.form-control, +.input-group-sm>.input-group-addon, +.input-group-sm>.input-group-btn>.btn { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px +} +select.input-group-sm>.form-control, +select.input-group-sm>.input-group-addon, +select.input-group-sm>.input-group-btn>.btn { + height: 30px; + line-height: 30px +} +select[multiple].input-group-sm>.form-control, +select[multiple].input-group-sm>.input-group-addon, +select[multiple].input-group-sm>.input-group-btn>.btn, +textarea.input-group-sm>.form-control, +textarea.input-group-sm>.input-group-addon, +textarea.input-group-sm>.input-group-btn>.btn { + height: auto +} +.input-group .form-control, +.input-group-addon, +.input-group-btn { + display: table-cell +} +.input-group .form-control:not(:first-child):not(:last-child), +.input-group-addon:not(:first-child):not(:last-child), +.input-group-btn:not(:first-child):not(:last-child) { + border-radius: 0 +} +.input-group-addon, +.input-group-btn { + width: 1%; + white-space: nowrap; + vertical-align: middle +} +.input-group-addon { + padding: 6px 12px; + font-size: 14px; + font-weight: 400; + line-height: 1; + color: #555; + text-align: center; + background-color: #eee; + border: 1px solid #ccc; + border-radius: 4px +} +.input-group-addon.input-sm { + padding: 5px 10px; + font-size: 12px; + border-radius: 3px +} +.input-group-addon.input-lg { + padding: 10px 16px; + font-size: 18px; + border-radius: 6px +} +.input-group-addon input[type=checkbox], +.input-group-addon input[type=radio] { + margin-top: 0 +} +.input-group .form-control:first-child, +.input-group-addon:first-child, +.input-group-btn:first-child>.btn, +.input-group-btn:first-child>.btn-group>.btn, +.input-group-btn:first-child>.dropdown-toggle, +.input-group-btn:last-child>.btn-group:not(:last-child)>.btn, +.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle) { + border-top-right-radius: 0; + border-bottom-right-radius: 0 +} +.input-group-addon:first-child { + border-right: 0 +} +.input-group .form-control:last-child, +.input-group-addon:last-child, +.input-group-btn:first-child>.btn-group:not(:first-child)>.btn, +.input-group-btn:first-child>.btn:not(:first-child), +.input-group-btn:last-child>.btn, +.input-group-btn:last-child>.btn-group>.btn, +.input-group-btn:last-child>.dropdown-toggle { + border-top-left-radius: 0; + border-bottom-left-radius: 0 +} +.input-group-addon:last-child { + border-left: 0 +} +.input-group-btn { + position: relative; + font-size: 0; + white-space: nowrap +} +.input-group-btn>.btn { + position: relative +} +.input-group-btn>.btn+.btn { + margin-left: -1px +} +.input-group-btn>.btn:active, +.input-group-btn>.btn:focus, +.input-group-btn>.btn:hover { + z-index: 2 +} +.input-group-btn:first-child>.btn, +.input-group-btn:first-child>.btn-group { + margin-right: -1px +} +.input-group-btn:last-child>.btn, +.input-group-btn:last-child>.btn-group { + margin-left: -1px +} +.nav { + padding-left: 0; + margin-bottom: 0; + list-style: none +} +.nav>li { + position: relative; + display: block +} +.nav>li>a { + position: relative; + display: block; + padding: 10px 15px +} +.nav>li>a:focus, +.nav>li>a:hover { + text-decoration: none; + background-color: #eee +} +.nav>li.disabled>a { + color: #777 +} +.nav>li.disabled>a:focus, +.nav>li.disabled>a:hover { + color: #777; + text-decoration: none; + cursor: not-allowed; + background-color: transparent +} +.nav .open>a, +.nav .open>a:focus, +.nav .open>a:hover { + background-color: #eee; + border-color: #337ab7 +} +.nav .nav-divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5 +} +.nav>li>a>img { + max-width: none +} +.nav-tabs { + border-bottom: 1px solid #ddd +} +.nav-tabs>li { + float: left; + margin-bottom: -1px +} +.nav-tabs>li>a { + margin-right: 2px; + line-height: 1.42857143; + border: 1px solid transparent; + border-radius: 4px 4px 0 0 +} +.nav-tabs>li>a:hover { + border-color: #eee #eee #ddd +} +.nav-tabs>li.active>a, +.nav-tabs>li.active>a:focus, +.nav-tabs>li.active>a:hover { + color: #555; + cursor: default; + background-color: #fff; + border: 1px solid #ddd; + border-bottom-color: transparent +} +.nav-tabs.nav-justified { + width: 100%; + border-bottom: 0 +} +.nav-tabs.nav-justified>li { + float: none +} +.nav-tabs.nav-justified>li>a { + margin-bottom: 5px; + text-align: center +} +.nav-tabs.nav-justified>.dropdown .dropdown-menu { + top: auto; + left: auto +} +@media (min-width: 768px) { + .nav-tabs.nav-justified>li { + display: table-cell; + width: 1% + } + .nav-tabs.nav-justified>li>a { + margin-bottom: 0 + } +} +.nav-tabs.nav-justified>li>a { + margin-right: 0; + border-radius: 4px +} +.nav-tabs.nav-justified>.active>a, +.nav-tabs.nav-justified>.active>a:focus, +.nav-tabs.nav-justified>.active>a:hover { + border: 1px solid #ddd +} +@media (min-width: 768px) { + .nav-tabs.nav-justified>li>a { + border-bottom: 1px solid #ddd; + border-radius: 4px 4px 0 0 + } + .nav-tabs.nav-justified>.active>a, + .nav-tabs.nav-justified>.active>a:focus, + .nav-tabs.nav-justified>.active>a:hover { + border-bottom-color: #fff + } +} +.nav-pills>li { + float: left +} +.nav-pills>li>a { + border-radius: 4px +} +.nav-pills>li+li { + margin-left: 2px +} +.nav-pills>li.active>a, +.nav-pills>li.active>a:focus, +.nav-pills>li.active>a:hover { + color: #fff; + background-color: #337ab7 +} +.nav-stacked>li { + float: none +} +.nav-stacked>li+li { + margin-top: 2px; + margin-left: 0 +} +.nav-justified { + width: 100% +} +.nav-justified>li { + float: none +} +.nav-justified>li>a { + margin-bottom: 5px; + text-align: center +} +.nav-justified>.dropdown .dropdown-menu { + top: auto; + left: auto +} +@media (min-width: 768px) { + .nav-justified>li { + display: table-cell; + width: 1% + } + .nav-justified>li>a { + margin-bottom: 0 + } +} +.nav-tabs-justified { + border-bottom: 0 +} +.nav-tabs-justified>li>a { + margin-right: 0; + border-radius: 4px +} +.nav-tabs-justified>.active>a, +.nav-tabs-justified>.active>a:focus, +.nav-tabs-justified>.active>a:hover { + border: 1px solid #ddd +} +@media (min-width: 768px) { + .nav-tabs-justified>li>a { + border-bottom: 1px solid #ddd; + border-radius: 4px 4px 0 0 + } + .nav-tabs-justified>.active>a, + .nav-tabs-justified>.active>a:focus, + .nav-tabs-justified>.active>a:hover { + border-bottom-color: #fff + } +} +.tab-content>.tab-pane { + display: none +} +.tab-content>.active { + display: block +} +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-left-radius: 0; + border-top-right-radius: 0 +} +.navbar { + position: relative; + min-height: 50px; + margin-bottom: 20px; + border: 1px solid transparent +} +@media (min-width: 768px) { + .navbar { + border-radius: 4px + } +} +@media (min-width: 768px) { + .navbar-header { + float: left + } +} +.navbar-collapse { + padding-right: 15px; + padding-left: 15px; + overflow-x: visible; + -webkit-overflow-scrolling: touch; + border-top: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1) +} +.navbar-collapse.in { + overflow-y: auto +} +@media (min-width: 768px) { + .navbar-collapse { + width: auto; + border-top: 0; + -webkit-box-shadow: none; + box-shadow: none + } + .navbar-collapse.collapse { + display: block!important; + height: auto!important; + padding-bottom: 0; + overflow: visible!important + } + .navbar-collapse.in { + overflow-y: visible + } + .navbar-fixed-bottom .navbar-collapse, + .navbar-fixed-top .navbar-collapse, + .navbar-static-top .navbar-collapse { + padding-right: 0; + padding-left: 0 + } +} +.navbar-fixed-bottom .navbar-collapse, +.navbar-fixed-top .navbar-collapse { + max-height: 340px +} +@media (max-device-width: 480px)and (orientation: landscape) { + .navbar-fixed-bottom .navbar-collapse, + .navbar-fixed-top .navbar-collapse { + max-height: 200px + } +} +.container-fluid>.navbar-collapse, +.container-fluid>.navbar-header, +.container>.navbar-collapse, +.container>.navbar-header { + margin-right: -15px; + margin-left: -15px +} +@media (min-width: 768px) { + .container-fluid>.navbar-collapse, + .container-fluid>.navbar-header, + .container>.navbar-collapse, + .container>.navbar-header { + margin-right: 0; + margin-left: 0 + } +} +.navbar-static-top { + z-index: 1000; + border-width: 0 0 1px +} +@media (min-width: 768px) { + .navbar-static-top { + border-radius: 0 + } +} +.navbar-fixed-bottom, +.navbar-fixed-top { + position: fixed; + right: 0; + left: 0; + z-index: 1030 +} +@media (min-width: 768px) { + .navbar-fixed-bottom, + .navbar-fixed-top { + border-radius: 0 + } +} +.navbar-fixed-top { + top: 0; + border-width: 0 0 1px +} +.navbar-fixed-bottom { + bottom: 0; + margin-bottom: 0; + border-width: 1px 0 0 +} +.navbar-brand { + float: left; + height: 50px; + padding: 15px 15px; + font-size: 18px; + line-height: 20px +} +.navbar-brand:focus, +.navbar-brand:hover { + text-decoration: none +} +.navbar-brand>img { + display: block +} +@media (min-width: 768px) { + .navbar>.container .navbar-brand, + .navbar>.container-fluid .navbar-brand { + margin-left: -15px + } +} +.navbar-toggle { + position: relative; + float: right; + padding: 9px 10px; + margin-top: 8px; + margin-right: 15px; + margin-bottom: 8px; + background-color: transparent; + background-image: none; + border: 1px solid transparent; + border-radius: 4px +} +.navbar-toggle:focus { + outline: 0 +} +.navbar-toggle .icon-bar { + display: block; + width: 22px; + height: 2px; + border-radius: 1px +} +.navbar-toggle .icon-bar+.icon-bar { + margin-top: 4px +} +@media (min-width: 768px) { + .navbar-toggle { + display: none + } +} +.navbar-nav { + margin: 7.5px -15px +} +.navbar-nav>li>a { + padding-top: 10px; + padding-bottom: 10px; + line-height: 20px +} +@media (max-width: 767px) { + .navbar-nav .open .dropdown-menu { + position: static; + float: none; + width: auto; + margin-top: 0; + background-color: transparent; + border: 0; + -webkit-box-shadow: none; + box-shadow: none + } + .navbar-nav .open .dropdown-menu .dropdown-header, + .navbar-nav .open .dropdown-menu>li>a { + padding: 5px 15px 5px 25px + } + .navbar-nav .open .dropdown-menu>li>a { + line-height: 20px + } + .navbar-nav .open .dropdown-menu>li>a:focus, + .navbar-nav .open .dropdown-menu>li>a:hover { + background-image: none + } +} +@media (min-width: 768px) { + .navbar-nav { + float: left; + margin: 0 + } + .navbar-nav>li { + float: left + } + .navbar-nav>li>a { + padding-top: 15px; + padding-bottom: 15px + } +} +.navbar-form { + padding: 10px 15px; + margin-top: 8px; + margin-right: -15px; + margin-bottom: 8px; + margin-left: -15px; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1) +} +@media (min-width: 768px) { + .navbar-form .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle + } + .navbar-form .form-control { + display: inline-block; + width: auto; + vertical-align: middle + } + .navbar-form .form-control-static { + display: inline-block + } + .navbar-form .input-group { + display: inline-table; + vertical-align: middle + } + .navbar-form .input-group .form-control, + .navbar-form .input-group .input-group-addon, + .navbar-form .input-group .input-group-btn { + width: auto + } + .navbar-form .input-group>.form-control { + width: 100% + } + .navbar-form .control-label { + margin-bottom: 0; + vertical-align: middle + } + .navbar-form .checkbox, + .navbar-form .radio { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle + } + .navbar-form .checkbox label, + .navbar-form .radio label { + padding-left: 0 + } + .navbar-form .checkbox input[type=checkbox], + .navbar-form .radio input[type=radio] { + position: relative; + margin-left: 0 + } + .navbar-form .has-feedback .form-control-feedback { + top: 0 + } +} +@media (max-width: 767px) { + .navbar-form .form-group { + margin-bottom: 5px + } + .navbar-form .form-group:last-child { + margin-bottom: 0 + } +} +@media (min-width: 768px) { + .navbar-form { + width: auto; + padding-top: 0; + padding-bottom: 0; + margin-right: 0; + margin-left: 0; + border: 0; + -webkit-box-shadow: none; + box-shadow: none + } +} +.navbar-nav>li>.dropdown-menu { + margin-top: 0; + border-top-left-radius: 0; + border-top-right-radius: 0 +} +.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu { + margin-bottom: 0; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0 +} +.navbar-btn { + margin-top: 8px; + margin-bottom: 8px +} +.navbar-btn.btn-sm { + margin-top: 10px; + margin-bottom: 10px +} +.navbar-btn.btn-xs { + margin-top: 14px; + margin-bottom: 14px +} +.navbar-text { + margin-top: 15px; + margin-bottom: 15px +} +@media (min-width: 768px) { + .navbar-text { + float: left; + margin-right: 15px; + margin-left: 15px + } +} +@media (min-width: 768px) { + .navbar-left { + float: left!important + } + .navbar-right { + float: right!important; + margin-right: -15px + } + .navbar-right~.navbar-right { + margin-right: 0 + } +} +.navbar-default { + background-color: #f8f8f8; + border-color: #e7e7e7 +} +.navbar-default .navbar-brand { + color: #777 +} +.navbar-default .navbar-brand:focus, +.navbar-default .navbar-brand:hover { + color: #5e5e5e; + background-color: transparent +} +.navbar-default .navbar-text { + color: #777 +} +.navbar-default .navbar-nav>li>a { + color: #777 +} +.navbar-default .navbar-nav>li>a:focus, +.navbar-default .navbar-nav>li>a:hover { + color: #333; + background-color: transparent +} +.navbar-default .navbar-nav>.active>a, +.navbar-default .navbar-nav>.active>a:focus, +.navbar-default .navbar-nav>.active>a:hover { + color: #555; + background-color: #e7e7e7 +} +.navbar-default .navbar-nav>.disabled>a, +.navbar-default .navbar-nav>.disabled>a:focus, +.navbar-default .navbar-nav>.disabled>a:hover { + color: #ccc; + background-color: transparent +} +.navbar-default .navbar-toggle { + border-color: #ddd +} +.navbar-default .navbar-toggle:focus, +.navbar-default .navbar-toggle:hover { + background-color: #ddd +} +.navbar-default .navbar-toggle .icon-bar { + background-color: #888 +} +.navbar-default .navbar-collapse, +.navbar-default .navbar-form { + border-color: #e7e7e7 +} +.navbar-default .navbar-nav>.open>a, +.navbar-default .navbar-nav>.open>a:focus, +.navbar-default .navbar-nav>.open>a:hover { + color: #555; + background-color: #e7e7e7 +} +@media (max-width: 767px) { + .navbar-default .navbar-nav .open .dropdown-menu>li>a { + color: #777 + } + .navbar-default .navbar-nav .open .dropdown-menu>li>a:focus, + .navbar-default .navbar-nav .open .dropdown-menu>li>a:hover { + color: #333; + background-color: transparent + } + .navbar-default .navbar-nav .open .dropdown-menu>.active>a, + .navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus, + .navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover { + color: #555; + background-color: #e7e7e7 + } + .navbar-default .navbar-nav .open .dropdown-menu>.disabled>a, + .navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus, + .navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover { + color: #ccc; + background-color: transparent + } +} +.navbar-default .navbar-link { + color: #777 +} +.navbar-default .navbar-link:hover { + color: #333 +} +.navbar-default .btn-link { + color: #777 +} +.navbar-default .btn-link:focus, +.navbar-default .btn-link:hover { + color: #333 +} +.navbar-default .btn-link[disabled]:focus, +.navbar-default .btn-link[disabled]:hover, +fieldset[disabled] .navbar-default .btn-link:focus, +fieldset[disabled] .navbar-default .btn-link:hover { + color: #ccc +} +.navbar-inverse { + background-color: #222; + border-color: #080808 +} +.navbar-inverse .navbar-brand { + color: #9d9d9d +} +.navbar-inverse .navbar-brand:focus, +.navbar-inverse .navbar-brand:hover { + color: #fff; + background-color: transparent +} +.navbar-inverse .navbar-text { + color: #9d9d9d +} +.navbar-inverse .navbar-nav>li>a { + color: #9d9d9d +} +.navbar-inverse .navbar-nav>li>a:focus, +.navbar-inverse .navbar-nav>li>a:hover { + color: #fff; + background-color: transparent +} +.navbar-inverse .navbar-nav>.active>a, +.navbar-inverse .navbar-nav>.active>a:focus, +.navbar-inverse .navbar-nav>.active>a:hover { + color: #fff; + background-color: #080808 +} +.navbar-inverse .navbar-nav>.disabled>a, +.navbar-inverse .navbar-nav>.disabled>a:focus, +.navbar-inverse .navbar-nav>.disabled>a:hover { + color: #444; + background-color: transparent +} +.navbar-inverse .navbar-toggle { + border-color: #333 +} +.navbar-inverse .navbar-toggle:focus, +.navbar-inverse .navbar-toggle:hover { + background-color: #333 +} +.navbar-inverse .navbar-toggle .icon-bar { + background-color: #fff +} +.navbar-inverse .navbar-collapse, +.navbar-inverse .navbar-form { + border-color: #101010 +} +.navbar-inverse .navbar-nav>.open>a, +.navbar-inverse .navbar-nav>.open>a:focus, +.navbar-inverse .navbar-nav>.open>a:hover { + color: #fff; + background-color: #080808 +} +@media (max-width: 767px) { + .navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header { + border-color: #080808 + } + .navbar-inverse .navbar-nav .open .dropdown-menu .divider { + background-color: #080808 + } + .navbar-inverse .navbar-nav .open .dropdown-menu>li>a { + color: #9d9d9d + } + .navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus, + .navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover { + color: #fff; + background-color: transparent + } + .navbar-inverse .navbar-nav .open .dropdown-menu>.active>a, + .navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus, + .navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover { + color: #fff; + background-color: #080808 + } + .navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a, + .navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus, + .navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover { + color: #444; + background-color: transparent + } +} +.navbar-inverse .navbar-link { + color: #9d9d9d +} +.navbar-inverse .navbar-link:hover { + color: #fff +} +.navbar-inverse .btn-link { + color: #9d9d9d +} +.navbar-inverse .btn-link:focus, +.navbar-inverse .btn-link:hover { + color: #fff +} +.navbar-inverse .btn-link[disabled]:focus, +.navbar-inverse .btn-link[disabled]:hover, +fieldset[disabled] .navbar-inverse .btn-link:focus, +fieldset[disabled] .navbar-inverse .btn-link:hover { + color: #444 +} +.breadcrumb { + padding: 8px 15px; + margin-bottom: 20px; + list-style: none; + background-color: #f5f5f5; + border-radius: 4px +} +.breadcrumb>li { + display: inline-block +} +.breadcrumb>li+li:before { + padding: 0 5px; + color: #ccc; + content: "/\00a0" +} +.breadcrumb>.active { + color: #777 +} +.pagination { + display: inline-block; + padding-left: 0; + margin: 20px 0; + border-radius: 4px +} +.pagination>li { + display: inline +} +.pagination>li>a, +.pagination>li>span { + position: relative; + float: left; + padding: 6px 12px; + margin-left: -1px; + line-height: 1.42857143; + color: #337ab7; + text-decoration: none; + background-color: #fff; + border: 1px solid #ddd +} +.pagination>li:first-child>a, +.pagination>li:first-child>span { + margin-left: 0; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px +} +.pagination>li:last-child>a, +.pagination>li:last-child>span { + border-top-right-radius: 4px; + border-bottom-right-radius: 4px +} +.pagination>li>a:focus, +.pagination>li>a:hover, +.pagination>li>span:focus, +.pagination>li>span:hover { + color: #23527c; + background-color: #eee; + border-color: #ddd +} +.pagination>.active>a, +.pagination>.active>a:focus, +.pagination>.active>a:hover, +.pagination>.active>span, +.pagination>.active>span:focus, +.pagination>.active>span:hover { + z-index: 2; + color: #fff; + cursor: default; + background-color: #337ab7; + border-color: #337ab7 +} +.pagination>.disabled>a, +.pagination>.disabled>a:focus, +.pagination>.disabled>a:hover, +.pagination>.disabled>span, +.pagination>.disabled>span:focus, +.pagination>.disabled>span:hover { + color: #777; + cursor: not-allowed; + background-color: #fff; + border-color: #ddd +} +.pagination-lg>li>a, +.pagination-lg>li>span { + padding: 10px 16px; + font-size: 18px +} +.pagination-lg>li:first-child>a, +.pagination-lg>li:first-child>span { + border-top-left-radius: 6px; + border-bottom-left-radius: 6px +} +.pagination-lg>li:last-child>a, +.pagination-lg>li:last-child>span { + border-top-right-radius: 6px; + border-bottom-right-radius: 6px +} +.pagination-sm>li>a, +.pagination-sm>li>span { + padding: 5px 10px; + font-size: 12px +} +.pagination-sm>li:first-child>a, +.pagination-sm>li:first-child>span { + border-top-left-radius: 3px; + border-bottom-left-radius: 3px +} +.pagination-sm>li:last-child>a, +.pagination-sm>li:last-child>span { + border-top-right-radius: 3px; + border-bottom-right-radius: 3px +} +.pager { + padding-left: 0; + margin: 20px 0; + text-align: center; + list-style: none +} +.pager li { + display: inline +} +.pager li>a, +.pager li>span { + display: inline-block; + padding: 5px 14px; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 15px +} +.pager li>a:focus, +.pager li>a:hover { + text-decoration: none; + background-color: #eee +} +.pager .next>a, +.pager .next>span { + float: right +} +.pager .previous>a, +.pager .previous>span { + float: left +} +.pager .disabled>a, +.pager .disabled>a:focus, +.pager .disabled>a:hover, +.pager .disabled>span { + color: #777; + cursor: not-allowed; + background-color: #fff +} +.label { + display: inline; + padding: .2em .6em .3em; + font-size: 75%; + font-weight: 700; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: .25em +} +a.label:focus, +a.label:hover { + color: #fff; + text-decoration: none; + cursor: pointer +} +.label:empty { + display: none +} +.btn .label { + position: relative; + top: -1px +} +.label-default { + background-color: #777 +} +.label-default[href]:focus, +.label-default[href]:hover { + background-color: #5e5e5e +} +.label-primary { + background-color: #337ab7 +} +.label-primary[href]:focus, +.label-primary[href]:hover { + background-color: #286090 +} +.label-success { + background-color: #5cb85c +} +.label-success[href]:focus, +.label-success[href]:hover { + background-color: #449d44 +} +.label-info { + background-color: #5bc0de +} +.label-info[href]:focus, +.label-info[href]:hover { + background-color: #31b0d5 +} +.label-warning { + background-color: #f0ad4e +} +.label-warning[href]:focus, +.label-warning[href]:hover { + background-color: #ec971f +} +.label-danger { + background-color: #d9534f +} +.label-danger[href]:focus, +.label-danger[href]:hover { + background-color: #c9302c +} +.badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: 700; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + background-color: #777; + border-radius: 10px +} +.badge:empty { + display: none +} +.btn .badge { + position: relative; + top: -1px +} +.btn-group-xs>.btn .badge, +.btn-xs .badge { + top: 0; + padding: 1px 5px +} +a.badge:focus, +a.badge:hover { + color: #fff; + text-decoration: none; + cursor: pointer +} +.list-group-item.active>.badge, +.nav-pills>.active>a>.badge { + color: #337ab7; + background-color: #fff +} +.list-group-item>.badge { + float: right +} +.list-group-item>.badge+.badge { + margin-right: 5px +} +.nav-pills>li>a>.badge { + margin-left: 3px +} +.jumbotron { + padding: 30px 15px; + margin-bottom: 30px; + color: inherit; + background-color: #eee +} +.jumbotron .h1, +.jumbotron h1 { + color: inherit +} +.jumbotron p { + margin-bottom: 15px; + font-size: 21px; + font-weight: 200 +} +.jumbotron>hr { + border-top-color: #d5d5d5 +} +.container .jumbotron, +.container-fluid .jumbotron { + border-radius: 6px +} +.jumbotron .container { + max-width: 100% +} +@media screen and (min-width: 768px) { + .jumbotron { + padding: 48px 0 + } + .container .jumbotron, + .container-fluid .jumbotron { + padding-right: 60px; + padding-left: 60px + } + .jumbotron .h1, + .jumbotron h1 { + font-size: 63px + } +} +.thumbnail { + display: block; + padding: 4px; + margin-bottom: 20px; + line-height: 1.42857143; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 4px; + -webkit-transition: border .2s ease-in-out; + -o-transition: border .2s ease-in-out; + transition: border .2s ease-in-out +} +.thumbnail a>img, +.thumbnail>img { + margin-right: auto; + margin-left: auto +} +a.thumbnail.active, +a.thumbnail:focus, +a.thumbnail:hover { + border-color: #337ab7 +} +.thumbnail .caption { + padding: 9px; + color: #333 +} +.alert { + padding: 15px; + margin-bottom: 20px; + border: 1px solid transparent; + border-radius: 4px +} +.alert h4 { + margin-top: 0; + color: inherit +} +.alert .alert-link { + font-weight: 700 +} +.alert>p, +.alert>ul { + margin-bottom: 0 +} +.alert>p+p { + margin-top: 5px +} +.alert-dismissable, +.alert-dismissible { + padding-right: 35px +} +.alert-dismissable .close, +.alert-dismissible .close { + position: relative; + top: -2px; + right: -21px; + color: inherit +} +.alert-success { + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6 +} +.alert-success hr { + border-top-color: #c9e2b3 +} +.alert-success .alert-link { + color: #2b542c +} +.alert-info { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1 +} +.alert-info hr { + border-top-color: #a6e1ec +} +.alert-info .alert-link { + color: #245269 +} +.alert-warning { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc +} +.alert-warning hr { + border-top-color: #f7e1b5 +} +.alert-warning .alert-link { + color: #66512c +} +.alert-danger { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1 +} +.alert-danger hr { + border-top-color: #e4b9c0 +} +.alert-danger .alert-link { + color: #843534 +} +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0 + } + to { + background-position: 0 0 + } +} +@-o-keyframes progress-bar-stripes { + from { + background-position: 40px 0 + } + to { + background-position: 0 0 + } +} +@keyframes progress-bar-stripes { + from { + background-position: 40px 0 + } + to { + background-position: 0 0 + } +} +.progress { + height: 20px; + margin-bottom: 20px; + overflow: hidden; + background-color: #f5f5f5; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1) +} +.progress-bar { + float: left; + width: 0; + height: 100%; + font-size: 12px; + line-height: 20px; + color: #fff; + text-align: center; + background-color: #337ab7; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); + -webkit-transition: width .6s ease; + -o-transition: width .6s ease; + transition: width .6s ease +} +.progress-bar-striped, +.progress-striped .progress-bar { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + -webkit-background-size: 40px 40px; + background-size: 40px 40px +} +.progress-bar.active, +.progress.active .progress-bar { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite +} +.progress-bar-success { + background-color: #5cb85c +} +.progress-striped .progress-bar-success { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent) +} +.progress-bar-info { + background-color: #5bc0de +} +.progress-striped .progress-bar-info { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent) +} +.progress-bar-warning { + background-color: #f0ad4e +} +.progress-striped .progress-bar-warning { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent) +} +.progress-bar-danger { + background-color: #d9534f +} +.progress-striped .progress-bar-danger { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent) +} +.media { + margin-top: 15px +} +.media:first-child { + margin-top: 0 +} +.media, +.media-body { + overflow: hidden; + zoom: 1 +} +.media-body { + width: 10000px +} +.media-object { + display: block +} +.media-right, +.media>.pull-right { + padding-left: 10px +} +.media-left, +.media>.pull-left { + padding-right: 10px +} +.media-body, +.media-left, +.media-right { + display: table-cell; + vertical-align: top +} +.media-middle { + vertical-align: middle +} +.media-bottom { + vertical-align: bottom +} +.media-heading { + margin-top: 0; + margin-bottom: 5px +} +.media-list { + padding-left: 0; + list-style: none +} +.list-group { + padding-left: 0; + margin-bottom: 20px +} +.list-group-item { + position: relative; + display: block; + padding: 10px 15px; + margin-bottom: -1px; + background-color: #fff; + border: 1px solid #ddd +} +.list-group-item:first-child { + border-top-left-radius: 4px; + border-top-right-radius: 4px +} +.list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px +} +a.list-group-item { + color: #555 +} +a.list-group-item .list-group-item-heading { + color: #333 +} +a.list-group-item:focus, +a.list-group-item:hover { + color: #555; + text-decoration: none; + background-color: #f5f5f5 +} +.list-group-item.disabled, +.list-group-item.disabled:focus, +.list-group-item.disabled:hover { + color: #777; + cursor: not-allowed; + background-color: #eee +} +.list-group-item.disabled .list-group-item-heading, +.list-group-item.disabled:focus .list-group-item-heading, +.list-group-item.disabled:hover .list-group-item-heading { + color: inherit +} +.list-group-item.disabled .list-group-item-text, +.list-group-item.disabled:focus .list-group-item-text, +.list-group-item.disabled:hover .list-group-item-text { + color: #777 +} +.list-group-item.active, +.list-group-item.active:focus, +.list-group-item.active:hover { + z-index: 2; + color: #fff; + background-color: #337ab7; + border-color: #337ab7 +} +.list-group-item.active .list-group-item-heading, +.list-group-item.active .list-group-item-heading>.small, +.list-group-item.active .list-group-item-heading>small, +.list-group-item.active:focus .list-group-item-heading, +.list-group-item.active:focus .list-group-item-heading>.small, +.list-group-item.active:focus .list-group-item-heading>small, +.list-group-item.active:hover .list-group-item-heading, +.list-group-item.active:hover .list-group-item-heading>.small, +.list-group-item.active:hover .list-group-item-heading>small { + color: inherit +} +.list-group-item.active .list-group-item-text, +.list-group-item.active:focus .list-group-item-text, +.list-group-item.active:hover .list-group-item-text { + color: #c7ddef +} +.list-group-item-success { + color: #3c763d; + background-color: #dff0d8 +} +a.list-group-item-success { + color: #3c763d +} +a.list-group-item-success .list-group-item-heading { + color: inherit +} +a.list-group-item-success:focus, +a.list-group-item-success:hover { + color: #3c763d; + background-color: #d0e9c6 +} +a.list-group-item-success.active, +a.list-group-item-success.active:focus, +a.list-group-item-success.active:hover { + color: #fff; + background-color: #3c763d; + border-color: #3c763d +} +.list-group-item-info { + color: #31708f; + background-color: #d9edf7 +} +a.list-group-item-info { + color: #31708f +} +a.list-group-item-info .list-group-item-heading { + color: inherit +} +a.list-group-item-info:focus, +a.list-group-item-info:hover { + color: #31708f; + background-color: #c4e3f3 +} +a.list-group-item-info.active, +a.list-group-item-info.active:focus, +a.list-group-item-info.active:hover { + color: #fff; + background-color: #31708f; + border-color: #31708f +} +.list-group-item-warning { + color: #8a6d3b; + background-color: #fcf8e3 +} +a.list-group-item-warning { + color: #8a6d3b +} +a.list-group-item-warning .list-group-item-heading { + color: inherit +} +a.list-group-item-warning:focus, +a.list-group-item-warning:hover { + color: #8a6d3b; + background-color: #faf2cc +} +a.list-group-item-warning.active, +a.list-group-item-warning.active:focus, +a.list-group-item-warning.active:hover { + color: #fff; + background-color: #8a6d3b; + border-color: #8a6d3b +} +.list-group-item-danger { + color: #a94442; + background-color: #f2dede +} +a.list-group-item-danger { + color: #a94442 +} +a.list-group-item-danger .list-group-item-heading { + color: inherit +} +a.list-group-item-danger:focus, +a.list-group-item-danger:hover { + color: #a94442; + background-color: #ebcccc +} +a.list-group-item-danger.active, +a.list-group-item-danger.active:focus, +a.list-group-item-danger.active:hover { + color: #fff; + background-color: #a94442; + border-color: #a94442 +} +.list-group-item-heading { + margin-top: 0; + margin-bottom: 5px +} +.list-group-item-text { + margin-bottom: 0; + line-height: 1.3 +} +.panel { + margin-bottom: 20px; + background-color: #fff; + border: 1px solid transparent; + border-radius: 4px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); + box-shadow: 0 1px 1px rgba(0, 0, 0, .05) +} +.panel-body { + padding: 15px +} +.panel-heading { + padding: 10px 15px; + border-bottom: 1px solid transparent; + border-top-left-radius: 3px; + border-top-right-radius: 3px +} +.panel-heading>.dropdown .dropdown-toggle { + color: inherit +} +.panel-title { + margin-top: 0; + margin-bottom: 0; + font-size: 16px; + color: inherit +} +.panel-title>.small, +.panel-title>.small>a, +.panel-title>a, +.panel-title>small, +.panel-title>small>a { + color: inherit +} +.panel-footer { + padding: 10px 15px; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px +} +.panel>.list-group, +.panel>.panel-collapse>.list-group { + margin-bottom: 0 +} +.panel>.list-group .list-group-item, +.panel>.panel-collapse>.list-group .list-group-item { + border-width: 1px 0; + border-radius: 0 +} +.panel>.list-group:first-child .list-group-item:first-child, +.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child { + border-top: 0; + border-top-left-radius: 3px; + border-top-right-radius: 3px +} +.panel>.list-group:last-child .list-group-item:last-child, +.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child { + border-bottom: 0; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px +} +.panel-heading+.list-group .list-group-item:first-child { + border-top-width: 0 +} +.list-group+.panel-footer { + border-top-width: 0 +} +.panel>.panel-collapse>.table, +.panel>.table, +.panel>.table-responsive>.table { + margin-bottom: 0 +} +.panel>.panel-collapse>.table caption, +.panel>.table caption, +.panel>.table-responsive>.table caption { + padding-right: 15px; + padding-left: 15px +} +.panel>.table-responsive:first-child>.table:first-child, +.panel>.table:first-child { + border-top-left-radius: 3px; + border-top-right-radius: 3px +} +.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child, +.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child, +.panel>.table:first-child>tbody:first-child>tr:first-child, +.panel>.table:first-child>thead:first-child>tr:first-child { + border-top-left-radius: 3px; + border-top-right-radius: 3px +} +.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child, +.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child, +.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child, +.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child, +.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child, +.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child, +.panel>.table:first-child>thead:first-child>tr:first-child td:first-child, +.panel>.table:first-child>thead:first-child>tr:first-child th:first-child { + border-top-left-radius: 3px +} +.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child, +.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child, +.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child, +.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child, +.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child, +.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child, +.panel>.table:first-child>thead:first-child>tr:first-child td:last-child, +.panel>.table:first-child>thead:first-child>tr:first-child th:last-child { + border-top-right-radius: 3px +} +.panel>.table-responsive:last-child>.table:last-child, +.panel>.table:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px +} +.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child, +.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child, +.panel>.table:last-child>tbody:last-child>tr:last-child, +.panel>.table:last-child>tfoot:last-child>tr:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px +} +.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child, +.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child, +.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child, +.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child, +.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child, +.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child, +.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child, +.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child { + border-bottom-left-radius: 3px +} +.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child, +.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child, +.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child, +.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child, +.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child, +.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child, +.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child, +.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child { + border-bottom-right-radius: 3px +} +.panel>.panel-body+.table, +.panel>.panel-body+.table-responsive, +.panel>.table+.panel-body, +.panel>.table-responsive+.panel-body { + border-top: 1px solid #ddd +} +.panel>.table>tbody:first-child>tr:first-child td, +.panel>.table>tbody:first-child>tr:first-child th { + border-top: 0 +} +.panel>.table-bordered, +.panel>.table-responsive>.table-bordered { + border: 0 +} +.panel>.table-bordered>tbody>tr>td:first-child, +.panel>.table-bordered>tbody>tr>th:first-child, +.panel>.table-bordered>tfoot>tr>td:first-child, +.panel>.table-bordered>tfoot>tr>th:first-child, +.panel>.table-bordered>thead>tr>td:first-child, +.panel>.table-bordered>thead>tr>th:first-child, +.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child, +.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child, +.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child, +.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child, +.panel>.table-responsive>.table-bordered>thead>tr>td:first-child, +.panel>.table-responsive>.table-bordered>thead>tr>th:first-child { + border-left: 0 +} +.panel>.table-bordered>tbody>tr>td:last-child, +.panel>.table-bordered>tbody>tr>th:last-child, +.panel>.table-bordered>tfoot>tr>td:last-child, +.panel>.table-bordered>tfoot>tr>th:last-child, +.panel>.table-bordered>thead>tr>td:last-child, +.panel>.table-bordered>thead>tr>th:last-child, +.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child, +.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child, +.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child, +.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child, +.panel>.table-responsive>.table-bordered>thead>tr>td:last-child, +.panel>.table-responsive>.table-bordered>thead>tr>th:last-child { + border-right: 0 +} +.panel>.table-bordered>tbody>tr:first-child>td, +.panel>.table-bordered>tbody>tr:first-child>th, +.panel>.table-bordered>thead>tr:first-child>td, +.panel>.table-bordered>thead>tr:first-child>th, +.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td, +.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th, +.panel>.table-responsive>.table-bordered>thead>tr:first-child>td, +.panel>.table-responsive>.table-bordered>thead>tr:first-child>th { + border-bottom: 0 +} +.panel>.table-bordered>tbody>tr:last-child>td, +.panel>.table-bordered>tbody>tr:last-child>th, +.panel>.table-bordered>tfoot>tr:last-child>td, +.panel>.table-bordered>tfoot>tr:last-child>th, +.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td, +.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th, +.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td, +.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th { + border-bottom: 0 +} +.panel>.table-responsive { + margin-bottom: 0; + border: 0 +} +.panel-group { + margin-bottom: 20px +} +.panel-group .panel { + margin-bottom: 0; + border-radius: 4px +} +.panel-group .panel+.panel { + margin-top: 5px +} +.panel-group .panel-heading { + border-bottom: 0 +} +.panel-group .panel-heading+.panel-collapse>.list-group, +.panel-group .panel-heading+.panel-collapse>.panel-body { + border-top: 1px solid #ddd +} +.panel-group .panel-footer { + border-top: 0 +} +.panel-group .panel-footer+.panel-collapse .panel-body { + border-bottom: 1px solid #ddd +} +.panel-default { + border-color: #ddd +} +.panel-default>.panel-heading { + color: #333; + background-color: #f5f5f5; + border-color: #ddd +} +.panel-default>.panel-heading+.panel-collapse>.panel-body { + border-top-color: #ddd +} +.panel-default>.panel-heading .badge { + color: #f5f5f5; + background-color: #333 +} +.panel-default>.panel-footer+.panel-collapse>.panel-body { + border-bottom-color: #ddd +} +.panel-primary { + border-color: #337ab7 +} +.panel-primary>.panel-heading { + color: #fff; + background-color: #337ab7; + border-color: #337ab7 +} +.panel-primary>.panel-heading+.panel-collapse>.panel-body { + border-top-color: #337ab7 +} +.panel-primary>.panel-heading .badge { + color: #337ab7; + background-color: #fff +} +.panel-primary>.panel-footer+.panel-collapse>.panel-body { + border-bottom-color: #337ab7 +} +.panel-success { + border-color: #d6e9c6 +} +.panel-success>.panel-heading { + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6 +} +.panel-success>.panel-heading+.panel-collapse>.panel-body { + border-top-color: #d6e9c6 +} +.panel-success>.panel-heading .badge { + color: #dff0d8; + background-color: #3c763d +} +.panel-success>.panel-footer+.panel-collapse>.panel-body { + border-bottom-color: #d6e9c6 +} +.panel-info { + border-color: #bce8f1 +} +.panel-info>.panel-heading { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1 +} +.panel-info>.panel-heading+.panel-collapse>.panel-body { + border-top-color: #bce8f1 +} +.panel-info>.panel-heading .badge { + color: #d9edf7; + background-color: #31708f +} +.panel-info>.panel-footer+.panel-collapse>.panel-body { + border-bottom-color: #bce8f1 +} +.panel-warning { + border-color: #faebcc +} +.panel-warning>.panel-heading { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc +} +.panel-warning>.panel-heading+.panel-collapse>.panel-body { + border-top-color: #faebcc +} +.panel-warning>.panel-heading .badge { + color: #fcf8e3; + background-color: #8a6d3b +} +.panel-warning>.panel-footer+.panel-collapse>.panel-body { + border-bottom-color: #faebcc +} +.panel-danger { + border-color: #ebccd1 +} +.panel-danger>.panel-heading { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1 +} +.panel-danger>.panel-heading+.panel-collapse>.panel-body { + border-top-color: #ebccd1 +} +.panel-danger>.panel-heading .badge { + color: #f2dede; + background-color: #a94442 +} +.panel-danger>.panel-footer+.panel-collapse>.panel-body { + border-bottom-color: #ebccd1 +} +.embed-responsive { + position: relative; + display: block; + height: 0; + padding: 0; + overflow: hidden +} +.embed-responsive .embed-responsive-item, +.embed-responsive embed, +.embed-responsive iframe, +.embed-responsive object, +.embed-responsive video { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 100%; + height: 100%; + border: 0 +} +.embed-responsive-16by9 { + padding-bottom: 56.25% +} +.embed-responsive-4by3 { + padding-bottom: 75% +} +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #e3e3e3; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05) +} +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, .15) +} +.well-lg { + padding: 24px; + border-radius: 6px +} +.well-sm { + padding: 9px; + border-radius: 3px +} +.close { + float: right; + font-size: 21px; + font-weight: 700; + line-height: 1; + color: #000; + text-shadow: 0 1px 0 #fff; + filter: alpha(opacity=20); + opacity: .2 +} +.close:focus, +.close:hover { + color: #000; + text-decoration: none; + cursor: pointer; + filter: alpha(opacity=50); + opacity: .5 +} +button.close { + -webkit-appearance: none; + padding: 0; + cursor: pointer; + background: 0 0; + border: 0 +} +.modal-open { + overflow: hidden +} +.modal { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1050; + display: none; + overflow: hidden; + -webkit-overflow-scrolling: touch; + outline: 0 +} +.modal.fade .modal-dialog { + -webkit-transition: -webkit-transform .3s ease-out; + -o-transition: -o-transform .3s ease-out; + transition: transform .3s ease-out; + -webkit-transform: translate(0, -25%); + -ms-transform: translate(0, -25%); + -o-transform: translate(0, -25%); + transform: translate(0, -25%) +} +.modal.in .modal-dialog { + -webkit-transform: translate(0, 0); + -ms-transform: translate(0, 0); + -o-transform: translate(0, 0); + transform: translate(0, 0) +} +.modal-open .modal { + overflow-x: hidden; + overflow-y: auto +} +.modal-dialog { + position: relative; + width: auto; + margin: 10px +} +.modal-content { + position: relative; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: 6px; + outline: 0; + -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5); + box-shadow: 0 3px 9px rgba(0, 0, 0, .5) +} +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000 +} +.modal-backdrop.fade { + filter: alpha(opacity=0); + opacity: 0 +} +.modal-backdrop.in { + filter: alpha(opacity=50); + opacity: .5 +} +.modal-header { + min-height: 16.43px; + padding: 15px; + border-bottom: 1px solid #e5e5e5 +} +.modal-header .close { + margin-top: -2px +} +.modal-title { + margin: 0; + line-height: 1.42857143 +} +.modal-body { + position: relative; + padding: 15px +} +.modal-footer { + padding: 15px; + text-align: right; + border-top: 1px solid #e5e5e5 +} +.modal-footer .btn+.btn { + margin-bottom: 0; + margin-left: 5px +} +.modal-footer .btn-group .btn+.btn { + margin-left: -1px +} +.modal-footer .btn-block+.btn-block { + margin-left: 0 +} +.modal-scrollbar-measure { + position: absolute; + top: -9999px; + width: 50px; + height: 50px; + overflow: scroll +} +@media (min-width: 768px) { + .modal-dialog { + width: 600px; + margin: 30px auto + } + .modal-content { + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + box-shadow: 0 5px 15px rgba(0, 0, 0, .5) + } + .modal-sm { + width: 300px + } +} +@media (min-width: 992px) { + .modal-lg { + width: 900px + } +} +.tooltip { + position: absolute; + z-index: 1070; + display: block; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 12px; + font-weight: 400; + line-height: 1.4; + filter: alpha(opacity=0); + opacity: 0 +} +.tooltip.in { + filter: alpha(opacity=90); + opacity: .9 +} +.tooltip.top { + padding: 5px 0; + margin-top: -3px +} +.tooltip.right { + padding: 0 5px; + margin-left: 3px +} +.tooltip.bottom { + padding: 5px 0; + margin-top: 3px +} +.tooltip.left { + padding: 0 5px; + margin-left: -3px +} +.tooltip-inner { + max-width: 200px; + padding: 3px 8px; + color: #fff; + text-align: center; + text-decoration: none; + background-color: #000; + border-radius: 4px +} +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid +} +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-width: 5px 5px 0; + border-top-color: #000 +} +.tooltip.top-left .tooltip-arrow { + right: 5px; + bottom: 0; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000 +} +.tooltip.top-right .tooltip-arrow { + bottom: 0; + left: 5px; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000 +} +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-width: 5px 5px 5px 0; + border-right-color: #000 +} +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-width: 5px 0 5px 5px; + border-left-color: #000 +} +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000 +} +.tooltip.bottom-left .tooltip-arrow { + top: 0; + right: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000 +} +.tooltip.bottom-right .tooltip-arrow { + top: 0; + left: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000 +} +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1060; + display: none; + max-width: 276px; + padding: 1px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + font-weight: 400; + line-height: 1.42857143; + text-align: left; + white-space: normal; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2); + box-shadow: 0 5px 10px rgba(0, 0, 0, .2) +} +.popover.top { + margin-top: -10px +} +.popover.right { + margin-left: 10px +} +.popover.bottom { + margin-top: 10px +} +.popover.left { + margin-left: -10px +} +.popover-title { + padding: 8px 14px; + margin: 0; + font-size: 14px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + border-radius: 5px 5px 0 0 +} +.popover-content { + padding: 9px 14px +} +.popover>.arrow, +.popover>.arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid +} +.popover>.arrow { + border-width: 11px +} +.popover>.arrow:after { + content: ""; + border-width: 10px +} +.popover.top>.arrow { + bottom: -11px; + left: 50%; + margin-left: -11px; + border-top-color: #999; + border-top-color: rgba(0, 0, 0, .25); + border-bottom-width: 0 +} +.popover.top>.arrow:after { + bottom: 1px; + margin-left: -10px; + content: " "; + border-top-color: #fff; + border-bottom-width: 0 +} +.popover.right>.arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-right-color: #999; + border-right-color: rgba(0, 0, 0, .25); + border-left-width: 0 +} +.popover.right>.arrow:after { + bottom: -10px; + left: 1px; + content: " "; + border-right-color: #fff; + border-left-width: 0 +} +.popover.bottom>.arrow { + top: -11px; + left: 50%; + margin-left: -11px; + border-top-width: 0; + border-bottom-color: #999; + border-bottom-color: rgba(0, 0, 0, .25) +} +.popover.bottom>.arrow:after { + top: 1px; + margin-left: -10px; + content: " "; + border-top-width: 0; + border-bottom-color: #fff +} +.popover.left>.arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-right-width: 0; + border-left-color: #999; + border-left-color: rgba(0, 0, 0, .25) +} +.popover.left>.arrow:after { + right: 1px; + bottom: -10px; + content: " "; + border-right-width: 0; + border-left-color: #fff +} +.carousel { + position: relative +} +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden +} +.carousel-inner>.item { + position: relative; + display: none; + -webkit-transition: .6s ease-in-out left; + -o-transition: .6s ease-in-out left; + transition: .6s ease-in-out left +} +.carousel-inner>.item>a>img, +.carousel-inner>.item>img { + line-height: 1 +} +@media all and (transform-3d), +(-webkit-transform-3d) { + .carousel-inner>.item { + -webkit-transition: -webkit-transform .6s ease-in-out; + -o-transition: -o-transform .6s ease-in-out; + transition: transform .6s ease-in-out; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-perspective: 1000; + perspective: 1000 + } + .carousel-inner>.item.active.right, + .carousel-inner>.item.next { + left: 0; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0) + } + .carousel-inner>.item.active.left, + .carousel-inner>.item.prev { + left: 0; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0) + } + .carousel-inner>.item.active, + .carousel-inner>.item.next.left, + .carousel-inner>.item.prev.right { + left: 0; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0) + } +} +.carousel-inner>.active, +.carousel-inner>.next, +.carousel-inner>.prev { + display: block +} +.carousel-inner>.active { + left: 0 +} +.carousel-inner>.next, +.carousel-inner>.prev { + position: absolute; + top: 0; + width: 100% +} +.carousel-inner>.next { + left: 100% +} +.carousel-inner>.prev { + left: -100% +} +.carousel-inner>.next.left, +.carousel-inner>.prev.right { + left: 0 +} +.carousel-inner>.active.left { + left: -100% +} +.carousel-inner>.active.right { + left: 100% +} +.carousel-control { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 15%; + font-size: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, .6); + filter: alpha(opacity=50); + opacity: .5 +} +.carousel-control.left { + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .5) 0, rgba(0, 0, 0, .0001) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, .5) 0, rgba(0, 0, 0, .0001) 100%); + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .5)), to(rgba(0, 0, 0, .0001))); + background-image: linear-gradient(to right, rgba(0, 0, 0, .5) 0, rgba(0, 0, 0, .0001) 100%); + filter: progid: DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); + background-repeat: repeat-x +} +.carousel-control.right { + right: 0; + left: auto; + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .0001) 0, rgba(0, 0, 0, .5) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, .0001) 0, rgba(0, 0, 0, .5) 100%); + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .0001)), to(rgba(0, 0, 0, .5))); + background-image: linear-gradient(to right, rgba(0, 0, 0, .0001) 0, rgba(0, 0, 0, .5) 100%); + filter: progid: DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); + background-repeat: repeat-x +} +.carousel-control:focus, +.carousel-control:hover { + color: #fff; + text-decoration: none; + filter: alpha(opacity=90); + outline: 0; + opacity: .9 +} +.carousel-control .glyphicon-chevron-left, +.carousel-control .glyphicon-chevron-right, +.carousel-control .icon-next, +.carousel-control .icon-prev { + position: absolute; + top: 50%; + z-index: 5; + display: inline-block +} +.carousel-control .glyphicon-chevron-left, +.carousel-control .icon-prev { + left: 50%; + margin-left: -10px +} +.carousel-control .glyphicon-chevron-right, +.carousel-control .icon-next { + right: 50%; + margin-right: -10px +} +.carousel-control .icon-next, +.carousel-control .icon-prev { + width: 20px; + height: 20px; + margin-top: -10px; + font-family: serif; + line-height: 1 +} +.carousel-control .icon-prev:before { + content: '\2039' +} +.carousel-control .icon-next:before { + content: '\203a' +} +.carousel-indicators { + position: absolute; + bottom: 10px; + left: 50%; + z-index: 15; + width: 60%; + padding-left: 0; + margin-left: -30%; + text-align: center; + list-style: none +} +.carousel-indicators li { + display: inline-block; + width: 10px; + height: 10px; + margin: 1px; + text-indent: -999px; + cursor: pointer; + background-color: #000 \9; + background-color: rgba(0, 0, 0, 0); + border: 1px solid #fff; + border-radius: 10px +} +.carousel-indicators .active { + width: 12px; + height: 12px; + margin: 0; + background-color: #fff +} +.carousel-caption { + position: absolute; + right: 15%; + bottom: 20px; + left: 15%; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, .6) +} +.carousel-caption .btn { + text-shadow: none +} +@media screen and (min-width: 768px) { + .carousel-control .glyphicon-chevron-left, + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-next, + .carousel-control .icon-prev { + width: 30px; + height: 30px; + margin-top: -15px; + font-size: 30px + } + .carousel-control .glyphicon-chevron-left, + .carousel-control .icon-prev { + margin-left: -15px + } + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-next { + margin-right: -15px + } + .carousel-caption { + right: 20%; + left: 20%; + padding-bottom: 30px + } + .carousel-indicators { + bottom: 20px + } +} +.btn-group-vertical>.btn-group:after, +.btn-group-vertical>.btn-group:before, +.btn-toolbar:after, +.btn-toolbar:before, +.clearfix:after, +.clearfix:before, +.container-fluid:after, +.container-fluid:before, +.container:after, +.container:before, +.dl-horizontal dd:after, +.dl-horizontal dd:before, +.form-horizontal .form-group:after, +.form-horizontal .form-group:before, +.modal-footer:after, +.modal-footer:before, +.nav:after, +.nav:before, +.navbar-collapse:after, +.navbar-collapse:before, +.navbar-header:after, +.navbar-header:before, +.navbar:after, +.navbar:before, +.pager:after, +.pager:before, +.panel-body:after, +.panel-body:before, +.row:after, +.row:before { + display: table; + content: " " +} +.btn-group-vertical>.btn-group:after, +.btn-toolbar:after, +.clearfix:after, +.container-fluid:after, +.container:after, +.dl-horizontal dd:after, +.form-horizontal .form-group:after, +.modal-footer:after, +.nav:after, +.navbar-collapse:after, +.navbar-header:after, +.navbar:after, +.pager:after, +.panel-body:after, +.row:after { + clear: both +} +.center-block { + display: block; + margin-right: auto; + margin-left: auto +} +.pull-right { + float: right!important +} +.pull-left { + float: left!important +} +.hide { + display: none!important +} +.show { + display: block!important +} +.invisible { + visibility: hidden +} +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0 +} +.hidden { + display: none!important +} +.affix { + position: fixed +} +@-ms-viewport { + width: device-width +} +.visible-lg, +.visible-md, +.visible-sm, +.visible-xs { + display: none!important +} +.visible-lg-block, +.visible-lg-inline, +.visible-lg-inline-block, +.visible-md-block, +.visible-md-inline, +.visible-md-inline-block, +.visible-sm-block, +.visible-sm-inline, +.visible-sm-inline-block, +.visible-xs-block, +.visible-xs-inline, +.visible-xs-inline-block { + display: none!important +} +@media (max-width: 767px) { + .visible-xs { + display: block!important + } + table.visible-xs { + display: table + } + tr.visible-xs { + display: table-row!important + } + td.visible-xs, + th.visible-xs { + display: table-cell!important + } +} +@media (max-width: 767px) { + .visible-xs-block { + display: block!important + } +} +@media (max-width: 767px) { + .visible-xs-inline { + display: inline!important + } +} +@media (max-width: 767px) { + .visible-xs-inline-block { + display: inline-block!important + } +} +@media (min-width: 768px)and (max-width: 991px) { + .visible-sm { + display: block!important + } + table.visible-sm { + display: table + } + tr.visible-sm { + display: table-row!important + } + td.visible-sm, + th.visible-sm { + display: table-cell!important + } +} +@media (min-width: 768px)and (max-width: 991px) { + .visible-sm-block { + display: block!important + } +} +@media (min-width: 768px)and (max-width: 991px) { + .visible-sm-inline { + display: inline!important + } +} +@media (min-width: 768px)and (max-width: 991px) { + .visible-sm-inline-block { + display: inline-block!important + } +} +@media (min-width: 992px)and (max-width: 1199px) { + .visible-md { + display: block!important + } + table.visible-md { + display: table + } + tr.visible-md { + display: table-row!important + } + td.visible-md, + th.visible-md { + display: table-cell!important + } +} +@media (min-width: 992px)and (max-width: 1199px) { + .visible-md-block { + display: block!important + } +} +@media (min-width: 992px)and (max-width: 1199px) { + .visible-md-inline { + display: inline!important + } +} +@media (min-width: 992px)and (max-width: 1199px) { + .visible-md-inline-block { + display: inline-block!important + } +} +@media (min-width: 1200px) { + .visible-lg { + display: block!important + } + table.visible-lg { + display: table + } + tr.visible-lg { + display: table-row!important + } + td.visible-lg, + th.visible-lg { + display: table-cell!important + } +} +@media (min-width: 1200px) { + .visible-lg-block { + display: block!important + } +} +@media (min-width: 1200px) { + .visible-lg-inline { + display: inline!important + } +} +@media (min-width: 1200px) { + .visible-lg-inline-block { + display: inline-block!important + } +} +@media (max-width: 767px) { + .hidden-xs { + display: none!important + } +} +@media (min-width: 768px)and (max-width: 991px) { + .hidden-sm { + display: none!important + } +} +@media (min-width: 992px)and (max-width: 1199px) { + .hidden-md { + display: none!important + } +} +@media (min-width: 1200px) { + .hidden-lg { + display: none!important + } +} +.visible-print { + display: none!important +} +@media print { + .visible-print { + display: block!important + } + table.visible-print { + display: table + } + tr.visible-print { + display: table-row!important + } + td.visible-print, + th.visible-print { + display: table-cell!important + } +} +.visible-print-block { + display: none!important +} +@media print { + .visible-print-block { + display: block!important + } +} +.visible-print-inline { + display: none!important +} +@media print { + .visible-print-inline { + display: inline!important + } +} +.visible-print-inline-block { + display: none!important +} +@media print { + .visible-print-inline-block { + display: inline-block!important + } +} +@media print { + .hidden-print { + display: none!important + } +} \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/css/custom-theme.css b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/css/custom-theme.css new file mode 100755 index 00000000..a4256032 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/css/custom-theme.css @@ -0,0 +1,74 @@ +.navbar-default { + background-color: #2a2a2a; + border-color:#2a2a2a ; +} +.navbar-nav{color: #a5a5a5; font-weight:300; padding-top: 5px; padding-left:0px;} +.form-control {background-color: #121212; border: 0px;} +.btn-default {background-color: #121212; border: 1px solid #121212;} +.container { padding:0px;} +.container-fluid{padding-left:0px;} +.navbar-default .navbar-nav > li > a {color: #a5a5a5; font-size: 14px; font-weight: 500;} +.navbar-form .input-group > .form-control { height: 39px; margin-top: 0; } +.input-group-btn:last-child > .btn, .input-group-btn:last-child > .btn-group { height: 39px;} +.container-bg{background-image: url("../images/content-bg.png"); background-repeat: no-repeat; background-position: top left; min-height: 550px; overflow: hidden; padding: 0 15px;} +.navbar-default .navbar-nav > li > a :focus,.navbar-default .navbar-nav>li>a:hover{color:#ccc;background-color:transparent;} +.btn-default.active, +.btn-default.focus, +.btn-default:active, +.btn-default:focus, +.btn-default:hover, +.open>.dropdown-toggle.btn-default { + color: #ccc; + background-color: #121212; + border-color: #121212; +} +input { + background-color: #333; + border: 1px solid #2a2a2a; + border-radius: 3px; + height: 45px; + margin: 5px 0; + width: 100%; + padding-left: 10px; +} +input[type="checkbox"], input[type="radio"] { + line-height: normal; + margin-top: -3px; + width: 30px; +} +.navbar-default .navbar-nav>li>a:focus, +.navbar-default .navbar-nav>li>a:hover { + color: #747474; + outline: 0; +} +.navbar { + margin-bottom: 5px; +} +.navbar-brand { + padding: 15px 10px; +} +.navbar-default .navbar-nav > .open > a, .navbar-default .navbar-nav > .open > a:focus, .navbar-default .navbar-nav > .open > a:hover { + color: #fff; + background-color:#202020 ; +} +.dropdown-menu { + background-clip: padding-box; + background-color: #202020; + border: 0px solid rgba(0, 0, 0, 0.15); + border-radius: 0; + box-shadow: none; + display: none; + float: left; + font-size: 14px; + left: 0; + color: #a5a5a5; +} +.dropdown-menu > li > a { + color: #a5a5a5; +} +.dropdown-menu>li>a:focus, +.dropdown-menu>li>a:hover { + color: #fff; + text-decoration: none; + background-color: #313131; +} \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/css/fontwso2-extend.css b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/css/fontwso2-extend.css new file mode 100755 index 00000000..032768d9 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/css/fontwso2-extend.css @@ -0,0 +1,177 @@ +.fw, [class^="fw-"], [class*=" fw-"] { + display: inline-block; + font: normal normal normal 14px/1 fontwso2; + font-size: inherit; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + vertical-align: middle; + + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-rendering: auto; + transform: translate(0, 0); +} + +/* icon options */ +.fw-lg { + font-size: 1.33333333em; + line-height: 0.75em; + vertical-align: -15%; +} +.fw-1-5x { + font-size: 1.5em; +} +.fw-2x { + font-size: 2em; +} +.fw-3x { + font-size: 3em; +} +.fw-4x { + font-size: 4em; +} +.fw-5x { + font-size: 5em; +} +.fw-fixedwidth { + width: 1.28571429em; + text-align: center; +} +.fw-ul { + padding-left: 0; + margin-left: 2.14285714em; + list-style-type: none; +} +.fw-ul > li { + position: relative; +} +.fw-li { + position: absolute; + left: -2.14285714em; + width: 2.14285714em; + top: 0.14285714em; + text-align: center; +} +.fw-li.fw-lg { + left: -1.85714286em; +} +.fw-border { + padding: .2em .25em .15em; + border: solid 0.08em #eeeeee; + border-radius: .1em; +} +.pull-right { + float: right; +} +.pull-left { + float: left; +} +.fw.pull-left { + margin-right: .3em; +} +.fw.pull-right { + margin-left: .3em; +} +.fw-spin { + -webkit-animation: wso2icon-spin 2s infinite linear; + animation: wso2icon-spin 2s infinite linear; +} +.fw-pulse { + -webkit-animation: wso2icon-spin 1s infinite steps(8); + animation: wso2icon-spin 1s infinite steps(8); +} +@-webkit-keyframes wso2icon-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} +@keyframes wso2icon-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} +.fw-rotate-90 { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1); + -webkit-transform: rotate(90deg); + -ms-transform: rotate(90deg); + transform: rotate(90deg); +} +.fw-rotate-180 { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2); + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + transform: rotate(180deg); +} +.fw-rotate-270 { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3); + -webkit-transform: rotate(270deg); + -ms-transform: rotate(270deg); + transform: rotate(270deg); +} +.fw-flip-horizontal { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1); + -webkit-transform: scale(-1, 1); + -ms-transform: scale(-1, 1); + transform: scale(-1, 1); +} +.fw-flip-vertical { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1); + -webkit-transform: scale(1, -1); + -ms-transform: scale(1, -1); + transform: scale(1, -1); +} +:root .fw-rotate-90, +:root .fw-rotate-180, +:root .fw-rotate-270, +:root .fw-flip-horizontal, +:root .fw-flip-vertical { + filter: none; +} +.fw-stack, .fw-stack-md { + position: relative; + display: inline-block; + width: 2em; + height: 2em; + line-height: 1.8em; + vertical-align: middle; + text-align: center; +} +.fw-stack-md { + width: 1em; +} +.fw-stack-1x, +.fw-stack-2x, +.fw-stack-1-5x { + position: absolute; + left: 0; + width: 100%; + text-align: center; +} +.fw-stack-1x { + line-height: inherit; + font-size: 0.9em; + } +.fw-stack-1-5x { + line-height: inherit; + font-size: 1.2em; +} +.fw-stack-2x { + font-size: 1.8em; +} +.fw-inverse { + color: #ffffff; +} \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/css/fontwso2.css b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/css/fontwso2.css new file mode 100755 index 00000000..463b22ec --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/css/fontwso2.css @@ -0,0 +1,481 @@ +@font-face { + font-family: 'fontwso2'; + src:url('../fonts/fontwso2.eot?3uii6i'); + src:url('../fonts/fontwso2.eot?#iefix3uii6i') format('embedded-opentype'), + url('../fonts/fontwso2.woff?3uii6i') format('woff'), + url('../fonts/fontwso2.ttf?3uii6i') format('truetype'), + url('../fonts/fontwso2.svg?3uii6i#fontwso2') format('svg'); + font-weight: normal; + font-style: normal; +} + +.fw { + font-family: 'fontwso2'; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.fw-lifecycle:before { + content: "\e617"; +} + +.fw-globe:before { + content: "\e666"; +} + +.fw-filter:before { + content: "\e65b"; +} + +.fw-store:before { + content: "\e61b"; +} + +.fw-apple:before { + content: "\e613"; +} + +.fw-android:before { + content: "\e653"; +} + +.fw-windows:before { + content: "\e654"; +} + +.fw-monitor:before { + content: "\e658"; +} + +.fw-laptop:before { + content: "\e659"; +} + +.fw-computer:before { + content: "\e655"; +} + +.fw-mobile:before { + content: "\e656"; +} + +.fw-dots:before { + content: "\e615"; +} + +.fw-tiles:before { + content: "\e60e"; +} + +.fw-menu:before { + content: "\e60f"; +} + +.fw-list:before { + content: "\e610"; +} + +.fw-grid:before { + content: "\e611"; +} + +.fw-list2:before { + content: "\e667"; +} + +.fw-user:before { + content: "\e601"; +} + +.fw-add-user:before { + content: "\e668"; +} + +.fw-key:before { + content: "\e665"; +} + +.fw-star:before { + content: "\e65c"; +} + +.fw-star-2:before { + content: "\e612"; +} + +.fw-view:before { + content: "\e652"; +} + +.fw-edit:before { + content: "\e65d"; +} + +.fw-register2:before { + content: "\e669"; +} + +.fw-register:before { + content: "\e65f"; +} + +.fw-search:before { + content: "\e657"; +} + +.fw-send:before { + content: "\e66a"; +} + +.fw-delete:before { + content: "\e614"; +} + +.fw-settings:before { + content: "\e65e"; +} + +.fw-share:before { + content: "\e65a"; +} + +.fw-message:before { + content: "\e616"; +} + +.fw-bell:before { + content: "\e66b"; +} + +.fw-lock:before { + content: "\e618"; +} + +.fw-battery:before { + content: "\e619"; +} + +.fw-camera:before { + content: "\e61a"; +} + +.fw-wifi:before { + content: "\e606"; +} + +.fw-usb-drive:before { + content: "\e602"; +} + +.fw-hdd:before { + content: "\e61c"; +} + +.fw-map-location:before { + content: "\e61d"; +} + +.fw-invitation:before { + content: "\e664"; +} + +.fw-dial-up:before { + content: "\e61f"; +} + +.fw-incoming-call:before { + content: "\e620"; +} + +.fw-clock:before { + content: "\e621"; +} + +.fw-clean:before { + content: "\e622"; +} + +.fw-sort:before { + content: "\e623"; +} + +.fw-list-sort:before { + content: "\e624"; +} + +.fw-sequence:before { + content: "\e625"; +} + +.fw-rules:before { + content: "\e626"; +} + +.fw-padlock:before { + content: "\e66c"; +} + +.fw-uri:before { + content: "\e603"; +} + +.fw-pdf:before { + content: "\e627"; +} + +.fw-ms-document:before { + content: "\e629"; +} + +.fw-swagger:before { + content: "\e62a"; +} + +.fw-jquery:before { + content: "\e62b"; +} + +.fw-java:before { + content: "\e62c"; +} + +.fw-javaee:before { + content: "\e62d"; +} + +.fw-javascript:before { + content: "\e62e"; +} + +.fw-jaggery:before { + content: "\e62f"; +} + +.fw-uncheck:before { + content: "\e630"; +} + +.fw-check:before { + content: "\e631"; +} + +.fw-up-arrow-2:before { + content: "\e660"; +} + +.fw-down-arrow-2:before { + content: "\e661"; +} + +.fw-left-arrow-2:before { + content: "\e662"; +} + +.fw-right-arrow-2:before { + content: "\e663"; +} + +.fw-up-arrow:before { + content: "\e632"; +} + +.fw-down-arrow:before { + content: "\e63e"; +} + +.fw-left-arrow:before { + content: "\e633"; +} + +.fw-right-arrow:before { + content: "\e634"; +} + +.fw-cancel:before { + content: "\e635"; +} + +.fw-add:before { + content: "\e636"; +} + +.fw-minus:before { + content: "\e628"; +} + +.fw-refresh:before { + content: "\e637"; +} + +.fw-ring:before { + content: "\e600"; +} + +.fw-circle:before { + content: "\e638"; +} + +.fw-ok:before { + content: "\e639"; +} + +.fw-error:before { + content: "\e63a"; +} + +.fw-block:before { + content: "\e63b"; +} + +.fw-warning:before { + content: "\e605"; +} + +.fw-deploy:before { + content: "\e66d"; +} + +.fw-devices:before { + content: "\e63c"; +} + +.fw-dss:before { + content: "\e63d"; +} + +.fw-database:before { + content: "\e66e"; +} + +.fw-computer2:before { + content: "\e66f"; +} + +.fw-endpoint:before { + content: "\e63f"; +} + +.fw-bpmn:before { + content: "\e640"; +} + +.fw-bpel:before { + content: "\e641"; +} + +.fw-gadget:before { + content: "\e642"; +} + +.fw-application:before { + content: "\e643"; +} + +.fw-cloud:before { + content: "\e644"; +} + +.fw-service:before { + content: "\e645"; +} + +.fw-rest-service:before { + content: "\e646"; +} + +.fw-rest-api:before { + content: "\e647"; +} + +.fw-api:before { + content: "\e648"; +} + +.fw-service-provider:before { + content: "\e649"; +} + +.fw-website:before { + content: "\e604"; +} + +.fw-proxy:before { + content: "\e64a"; +} + +.fw-policy:before { + content: "\e64b"; +} + +.fw-security-policy:before { + content: "\e64c"; +} + +.fw-throttling-policy:before { + content: "\e64d"; +} + +.fw-blank-document:before { + content: "\e64e"; +} + +.fw-ebook:before { + content: "\e670"; +} + +.fw-document:before { + content: "\e671"; +} + +.fw-text:before { + content: "\e64f"; +} + +.fw-html:before { + content: "\e650"; +} + +.fw-wadl:before { + content: "\e608"; +} + +.fw-wsdl:before { + content: "\e609"; +} + +.fw-xacml:before { + content: "\e60a"; +} + +.fw-xsd:before { + content: "\e60b"; +} + +.fw-xq:before { + content: "\e60c"; +} + +.fw-xslt:before { + content: "\e60d"; +} + +.fw-xml:before { + content: "\e61e"; +} + +.fw-soap:before { + content: "\e651"; +} + +.fw-wso2:before { + content: "\e607"; +} + diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/css/main.css b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/css/main.css new file mode 100755 index 00000000..2c7dd473 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/css/main.css @@ -0,0 +1,484 @@ +/* _____________________________________________________________________________ + + FONT + _____________________________________________________________________________ */ +/* Regular */ +@font-face { + font-family: 'Open Sans'; + + src: url('../fonts/OpenSans-Regular-webfont.eot'); + src: url('../fonts/OpenSans-Regular-webfont.eot?#iefix') format('embedded-opentype'), + url('../fonts/OpenSans-Regular-webfont.woff') format('woff'), + url('../fonts/OpenSans-Regular-webfont.ttf') format('truetype'), + url('../fonts/OpenSans-Regular-webfont.svg#OpenSansRegular') format('svg'); + font-weight: normal; + font-weight: 400; + font-style: normal; + +} + +/* Italic */ +@font-face { + font-family: 'Open Sans'; + src: url('../fonts/OpenSans-Italic-webfont.eot'); + src: url('../fonts/OpenSans-Italic-webfont.eot?#iefix') format('embedded-opentype'), + url('../fonts/OpenSans-Italic-webfont.woff') format('woff'), + url('../fonts/OpenSans-Italic-webfont.ttf') format('truetype'), + url('../fonts/OpenSans-Italic-webfont.svg#OpenSansItalic') format('svg'); + font-weight: normal; + font-weight: 400; + font-style: italic; + +} + +/* Light */ +@font-face { + font-family: 'Open Sans'; + src: url('../fonts/OpenSans-Light-webfont.eot'); + src: url('../fonts/OpenSans-Light-webfont.eot?#iefix') format('embedded-opentype'), + url('../fonts/OpenSans-Light-webfont.woff') format('woff'), + url('../fonts/OpenSans-Light-webfont.ttf') format('truetype'), + url('../fonts/OpenSans-Light-webfont.svg#OpenSansLight') format('svg'); + font-weight: 200; + font-style: normal; + +} + +/* Light Italic */ +@font-face { + font-family: 'Open Sans'; + src: url('../fonts/OpenSans-LightItalic-webfont.eot'); + src: url('../fonts/OpenSans-LightItalic-webfont.eot?#iefix') format('embedded-opentype'), + url('../fonts/OpenSans-LightItalic-webfont.woff') format('woff'), + url('../fonts/OpenSans-LightItalic-webfont.ttf') format('truetype'), + url('../fonts/OpenSans-LightItalic-webfont.svg#OpenSansLightItalic') format('svg'); + font-weight: 200; + font-style: italic; + +} + +/* Semibold */ +@font-face { + font-family: 'Open Sans'; + src: url('../fonts/OpenSans-Semibold-webfont.eot'); + src: url('../fonts/OpenSans-Semibold-webfont.eot?#iefix') format('embedded-opentype'), + url('../fonts/OpenSans-Semibold-webfont.woff') format('woff'), + url('../fonts/OpenSans-Semibold-webfont.ttf') format('truetype'), + url('../fonts/OpenSans-Semibold-webfont.svg#OpenSansSemibold') format('svg'); + font-weight: 500; + font-style: normal; + +} + +/* Semibold Italic */ +@font-face { + font-family: 'Open Sans'; + src: url('../fonts/OpenSans-SemiboldItalic-webfont.eot'); + src: url('../fonts/OpenSans-SemiboldItalic-webfont.eot?#iefix') format('embedded-opentype'), + url('../fonts/OpenSans-SemiboldItalic-webfont.woff') format('woff'), + url('../fonts/OpenSans-SemiboldItalic-webfont.ttf') format('truetype'), + url('../fonts/OpenSans-SemiboldItalic-webfont.svg#OpenSansSemiboldItalic') format('svg'); + font-weight: 500; + font-style: italic; + +} + +/* Bold */ +@font-face { + font-family: 'Open Sans'; + src: url('../fonts/OpenSans-Bold-webfont.eot'); + src: url('../fonts/OpenSans-Bold-webfont.eot?#iefix') format('embedded-opentype'), + url('../fonts/OpenSans-Bold-webfont.woff') format('woff'), + url('../fonts/OpenSans-Bold-webfont.ttf') format('truetype'), + url('../fonts/OpenSans-Bold-webfont.svg#OpenSansBold') format('svg'); + font-weight: bold; + font-weight: 700; + font-style: normal; + +} + +/* Bold Italic */ +@font-face { + font-family: 'Open Sans'; + src: url('../fonts/OpenSans-BoldItalic-webfont.eot'); + src: url('../fonts/OpenSans-BoldItalic-webfont.eot?#iefix') format('embedded-opentype'), + url('../fonts/OpenSans-BoldItalic-webfont.woff') format('woff'), + url('../fonts/OpenSans-BoldItalic-webfont.ttf') format('truetype'), + url('../fonts/OpenSans-BoldItalic-webfont.svg#OpenSansBoldItalic') format('svg'); + font-weight: bold; + font-weight: 700; + font-style: italic; + +} + +/* Extra Bold */ +@font-face { + font-family: 'Open Sans'; + src: url('../fonts/OpenSans-ExtraBold-webfont.eot'); + src: url('../fonts/OpenSans-ExtraBold-webfont.eot?#iefix') format('embedded-opentype'), + url('../fonts/OpenSans-ExtraBold-webfont.woff') format('woff'), + url('../fonts/OpenSans-ExtraBold-webfont.ttf') format('truetype'), + url('../fonts/OpenSans-ExtraBold-webfont.svg#OpenSansExtrabold') format('svg'); + font-weight: 900; + font-style: normal; + +} + +/* Extra Bold Italic */ +@font-face { + font-family: 'Open Sans'; + src: url('../fonts/OpenSans-ExtraBoldItalic-webfont.eot'); + src: url('../fonts/OpenSans-ExtraBoldItalic-webfont.eot?#iefix') format('embedded-opentype'), + url('../fonts/OpenSans-ExtraBoldItalic-webfont.woff') format('woff'), + url('../fonts/OpenSans-ExtraBoldItalic-webfont.ttf') format('truetype'), + url('../fonts/OpenSans-ExtraBoldItalic-webfont.svg#OpenSansExtraboldItalic') format('svg'); + font-weight: 900; + font-style: italic; + +} +/* _____________________________________________________________________________ + + RESET + _____________________________________________________________________________ */ +html, body, div, span, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +abbr, address, cite, code, +del, dfn, em, img, ins, kbd, q, samp, +small, strong, sub, sup, var, +b, i, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, figcaption, figure, +footer, header, hgroup, menu, nav, section, summary, +time, mark, audio, video { + margin:0; + padding:0; + border:0; + outline:0; + font-size:100%; + vertical-align:baseline; + background:transparent; +} +body { + font-family: 'Open Sans'; + line-height:1; + color:#141414; + line-height:1; + background: url("../images/content-bg-1.png")repeat scroll 0 0 #f0f2f4; + margin: 15px; +} + + +article,aside,details,figcaption,figure, +footer,header,hgroup,menu,nav,section { + display:block; +} +nav ul { + list-style:none; +} +blockquote, q { + quotes:none; +} +blockquote:before, blockquote:after, +q:before, q:after { + content:''; + content:none; +} +a { + margin:0; + padding:0; + font-size:100%; + vertical-align:baseline; + background:transparent; +} +/* change colours to suit your needs */ +ins { + background-color:#ff9; + color:#000; + text-decoration:none; +} +/* change colours to suit your needs */ +mark { + background-color:#ff9; + color:#000; + font-style:italic; + font-weight:bold; +} +del { + text-decoration: line-through; +} +abbr[title], dfn[title] { + border-bottom:1px dotted; + cursor:help; +} +table { + border-collapse:collapse; + border-spacing:0; +} +/* change border colour to suit your needs */ +hr { + display:block; + height:1px; + border:0; + border-top:1px solid #7f7f7f; + margin:1em 0; + padding:0; + opacity: 0.2; +} +input, select { + vertical-align:middle; +} + +/* _____________________________________________________________________________ + + TYPOGRAPHY + _____________________________________________________________________________ */ + + +p{font-size:17px; line-height:24px; color:#c7c7c7;} +h1{ font-size:39px;font-weight:100; line-height:Auto; font-style: normal;} +h2{font-size:24px; line-height:Auto; font-weight: 400; } +h3{font-size:15px; line-height:Auto; font-weight: 400; } +h4{font-size:20px; line-height:Auto; font-weight: 400; } +h5{ font-size:30px;font-weight:100; line-height:Auto; font-style: normal; color: #929292;} +.font-small{font-size:12px;} +.font-large{font-size:25px;} +.font-medium{font-size:16px;} +.medium-weight{font-weight: 100;} + +.uppercase{text-transform:uppercase;} +.capitalize{text-transform:capitalize;} +.lowercase{text-transform:lowercase;} + + +.light-blue{color:#3a9ecf;} +.black{color:#000;} +.grey{color:#333;} +.light-grey{color:#7c7c7c;} +.white{color:#FFF;} +.blue{color: #00979c;} .blue:hover{color: #03c5cb;} + +.bold{font-weight:bold;} +.no-underline{text-decoration:none;} +.italic{font-style: italic;} + +.center{text-align:center;} +.right{text-align:right;} +.left{text-align:left;} +.justify{text-align:justify;} + +.middle{vertical-align: middle;} + +.top{vertical-align: top;} +.middle{vertical-align: middle;} +.bottom{vertical-align: bottom;} +.rounded{-webkit-border-radius: 0px; + -moz-border-radius: 0px; + border-radius: 0px;} +.opacity{opacity: 0.8;} + + +.circle { + background: none repeat scroll 0 0 #191919; + border-radius: 50px; + height: 50px; + padding: 10px; + width: 50px; + color: #fff; +} + + +/* _____________________________________________________________________________ + + BACKGROUND + _____________________________________________________________________________ */ +.grey-bg{ background-color:#f6f4f4;} +.light-grey-bg{ background-color:#f5f5f5 ; } +.white-bg{background-color:#fff;} +.off-white{background-color:#3a9ecf;} +.dark-grey{background-color: #2a2a2a;} +.blue-bg{background-color: #00979c;} + +/* _____________________________________________________________________________ + + Main + _____________________________________________________________________________ */ + +body { margin: 0; } +header{background-color: #2a2a2a;} + + +.product-wrapper{ float: left; width:100%; margin-top: -2px; min-height: 310px; -webkit-box-shadow: 5px 5px 5px 0px rgba(0,0,0,0.14); + -moz-box-shadow: 5px 5px 5px 0px rgba(0,0,0,0.14); + box-shadow: 5px 5px 5px 0px rgba(0,0,0,0.14);} +.icon-wrapper{min-height: 110px; padding-top: 12px; text-align: center; } +.text-wrapper{margin:15px; font-size:14px; border-top: 1px solid #404040; padding-top: 20px; color:#c6c5c5; line-height: 18px; text-align: center } +.sign-panel {background-color: #191919; width: 100%; height: auto; min-height: 150px; display: none; padding:15px; color: #a5a5a5; cursor:pointer;} +#flip-login{ font-weight: 500; font-size: 14px; padding: 20px; cursor:pointer; margin-top:-2px; } +.chart1,.chart2,.chart3 {width: 100%; height: 350px;} +/* ____________________________________________________________________________ + + COLUMNS + _____________________________________________________________________________ */ + +.col-row{width:100%; height: 100px;} +.col-x-large{width:100%; } +.col-large{width:75%; } +.col-medium{width:50%; } +.col-small{width:24%; } +.col-x-small{width:223px; } + +.opacity{opacity: 0.2;} +/* ____________________________________________________________________________ + + padding-margin + _____________________________________________________________________________ */ +.padding-left {padding-left:10px;} +.padding-right {padding-right:10px;} +.padding-top {padding-top:10px;} +.padding-bottom {padding-bottom:10px;} +.padding{padding:10px;} +.padding-none{ padding:0px;} +.padding-left-none{ padding-left:0px;} + + +.padding-left-double {padding-left:20px;} +.padding-right-double {padding-right:20px;} +.padding-top-double {padding-top:20px;} +.padding-bottom-double {padding-bottom:20px;} +.padding-double{padding:20px;} +.padding-top-large{padding-top:60px;} +.padding-bottom-large{padding-bottom:60px;} + +.margin-left {margin-left:10px;} +.margin-right {margin-right:10px;} +.margin-top {margin-top:10px;} +.margin-bottom {margin-bottom:10px;} +.margin{margin:10px;} +.margin-top-minus{margin-top:-123px;} + +.margin-left-double {margin-left:20px;} +.margin-right-double {margin-right:20px;} +.margin-top-double {margin-top:20px;} +.margin-bottom-double {margin-bottom:20px;} +.margin-double{margin:20px;} +.margin-left-none{margin-left: 0px;} +.margin-right-none{margin-right: 0px;} + +.float-left{float:left;} +.float-right{float:right;} +.clear{ clear:both;} + +.inline-block{display: inline-block;} +.relative{ position:relative;} +.border{border: 2px solid #dddddd;} +.border-bottom{border-bottom: 1px solid #efefef;} +.border-radius{border-radius: 5px;} +.border-top{border-top: 1px solid #ddd;} + +/* ____________________________________________________________________________ + + button + _____________________________________________________________________________ */ +.blue-btn { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0px; + color: #ffffff; + font-size: 15px; + font-weight: 500; + background: #00979c; + padding: 10px 20px 10px 20px; + text-decoration: none; + border: 0px; cursor:pointer; +} + +.blue-btn:hover { + background: #00787a; + text-decoration: none; +} +.blue-action-btn { + -webkit-border-radius: 0px; + -moz-border-radius: 0px; + border-radius: 0px; + color: #ffffff; + font-size: 15px; + font-weight: 500; + background: #00979c; + padding: 10px 30px; + height: 45px; + text-decoration: none; + border: 0px; cursor:pointer; +} + +.blue-action-btn:hover { + background: #00787a; + text-decoration: none; +} +.black-btn { + -webkit-border-radius: 0px; + -moz-border-radius: 0px; + border-radius: 0px; + color: #ccc; + font-size: 15px; + font-weight: 500; + background: #333333; + padding: 10px 30px; + height: 45px; + text-decoration: none; + border: 0px; cursor:pointer; +} + +.black-btn:hover { + background: #2a2a2a; + text-decoration: none; ; +} +.grey-btn { + background: none repeat scroll 0 0 #00979c; + border: 0 none; + border-top-left-radius: 0; + border-top-right-radius: 0; + color: #ffffff; + cursor: pointer; + font-size: 18px; + font-weight: 300; + padding: 10px 35px; + text-decoration: none; +} +.grey-btn:hover { + background: none repeat scroll 0 0 #006a6d; + border: 0 none; + border-top-left-radius: 0; + border-top-right-radius: 0; + color: #ffffff; + cursor: pointer; + font-size: 18px; + font-weight: 300; + padding: 10px 35px; + text-decoration: none; +} +.grey-btn a{color: #fff; text-decoration: none;} +.btn-black{color: #ffffff; margin-right: 5px; padding: 10px; text-decoration: none; overflow: hidden; background:#5c5c5c; text-align: center; float: left; cursor: pointer; } +.btn-black:hover{opacity: 0.8; } + +.menu-button-wrapper-temp{float: left; font-size: 13px; width: 125px;} +.menu-button-wrapper{float: left; font-size: 13px; width: 100px;} +.tick { opacity: 0 !important; } +.nv-discreteBarWithAxes>g>.nv-x>g>g>g{opacity: 1 !important;} +#date-range1{ + background: #fff none repeat scroll 0 0; + border: 1px solid #ccc; + width: 300px; +} + +#device_id{ + background: #fff none repeat scroll 0 0; + border: 1px solid #ccc; +} + +.hour-range,.minute-range{background: #fff none repeat scroll 0 0; border: 1px solid #ccc;} + +.btn-black-action{color: #ffffff; padding: 5px 20px; text-decoration: none; overflow: hidden; background:#5c5c5c; text-align: center; margin: 0 10px; float: left; cursor: pointer; border: none; outline:none;} +.btn-black-action:hover{background-color: #0076a3; } +.date-picker-wrapper {box-shadow:none;} \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Bold-webfont.eot b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Bold-webfont.eot new file mode 100755 index 00000000..5d4a1c47 Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Bold-webfont.eot differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Bold-webfont.svg b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Bold-webfont.svg new file mode 100755 index 00000000..7cda1026 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Bold-webfont.svg @@ -0,0 +1,251 @@ + + + + +This is a custom SVG webfont generated by Font Squirrel. +Copyright : Digitized data copyright 20102011 Google Corporation +Foundry : Ascender Corporation +Foundry URL : httpwwwascendercorpcom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Bold-webfont.ttf b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Bold-webfont.ttf new file mode 100755 index 00000000..7ab5d85b Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Bold-webfont.ttf differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Bold-webfont.woff b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Bold-webfont.woff new file mode 100755 index 00000000..869a9ed8 Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Bold-webfont.woff differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-BoldItalic-webfont.eot b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-BoldItalic-webfont.eot new file mode 100755 index 00000000..ad651807 Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-BoldItalic-webfont.eot differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-BoldItalic-webfont.svg b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-BoldItalic-webfont.svg new file mode 100755 index 00000000..91491201 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-BoldItalic-webfont.svg @@ -0,0 +1,251 @@ + + + + +This is a custom SVG webfont generated by Font Squirrel. +Copyright : Digitized data copyright 20102011 Google Corporation +Foundry : Ascender Corporation +Foundry URL : httpwwwascendercorpcom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-BoldItalic-webfont.ttf b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-BoldItalic-webfont.ttf new file mode 100755 index 00000000..6a30fa9d Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-BoldItalic-webfont.ttf differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-BoldItalic-webfont.woff b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-BoldItalic-webfont.woff new file mode 100755 index 00000000..46778a21 Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-BoldItalic-webfont.woff differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-ExtraBold-webfont.eot b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-ExtraBold-webfont.eot new file mode 100755 index 00000000..2f7ae28d Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-ExtraBold-webfont.eot differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-ExtraBold-webfont.svg b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-ExtraBold-webfont.svg new file mode 100755 index 00000000..009e1d7b --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-ExtraBold-webfont.svg @@ -0,0 +1,251 @@ + + + + +This is a custom SVG webfont generated by Font Squirrel. +Copyright : Digitized data copyright 2011 Google Corporation +Foundry : Ascender Corporation +Foundry URL : httpwwwascendercorpcom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-ExtraBold-webfont.ttf b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-ExtraBold-webfont.ttf new file mode 100755 index 00000000..dacc5bbb Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-ExtraBold-webfont.ttf differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-ExtraBold-webfont.woff b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-ExtraBold-webfont.woff new file mode 100755 index 00000000..de4f8e77 Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-ExtraBold-webfont.woff differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-ExtraBoldItalic-webfont.eot b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-ExtraBoldItalic-webfont.eot new file mode 100755 index 00000000..e4f4ab0d Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-ExtraBoldItalic-webfont.eot differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-ExtraBoldItalic-webfont.svg b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-ExtraBoldItalic-webfont.svg new file mode 100755 index 00000000..a0612586 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-ExtraBoldItalic-webfont.svg @@ -0,0 +1,251 @@ + + + + +This is a custom SVG webfont generated by Font Squirrel. +Copyright : Digitized data copyright 20102011 Google Corporation +Foundry : Ascender Corporation +Foundry URL : httpwwwascendercorpcom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-ExtraBoldItalic-webfont.ttf b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-ExtraBoldItalic-webfont.ttf new file mode 100755 index 00000000..7e636eb4 Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-ExtraBoldItalic-webfont.ttf differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-ExtraBoldItalic-webfont.woff b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-ExtraBoldItalic-webfont.woff new file mode 100755 index 00000000..f81b2161 Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-ExtraBoldItalic-webfont.woff differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Italic-webfont.eot b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Italic-webfont.eot new file mode 100755 index 00000000..c3159521 Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Italic-webfont.eot differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Italic-webfont.svg b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Italic-webfont.svg new file mode 100755 index 00000000..be508574 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Italic-webfont.svg @@ -0,0 +1,251 @@ + + + + +This is a custom SVG webfont generated by Font Squirrel. +Copyright : Digitized data copyright 20102011 Google Corporation +Foundry : Ascender Corporation +Foundry URL : httpwwwascendercorpcom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Italic-webfont.ttf b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Italic-webfont.ttf new file mode 100755 index 00000000..cb3fda65 Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Italic-webfont.ttf differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Italic-webfont.woff b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Italic-webfont.woff new file mode 100755 index 00000000..03eaf586 Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Italic-webfont.woff differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Light-webfont.eot b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Light-webfont.eot new file mode 100755 index 00000000..f17617e0 Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Light-webfont.eot differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Light-webfont.svg b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Light-webfont.svg new file mode 100755 index 00000000..deadc3ef --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Light-webfont.svg @@ -0,0 +1,252 @@ + + + + +This is a custom SVG webfont generated by Font Squirrel. +Copyright : Digitized data copyright 20102011 Google Corporation +Foundry : Ascender Corporation +Foundry URL : httpwwwascendercorpcom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Light-webfont.ttf b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Light-webfont.ttf new file mode 100755 index 00000000..b83078a6 Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Light-webfont.ttf differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Light-webfont.woff b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Light-webfont.woff new file mode 100755 index 00000000..ff882b6a Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Light-webfont.woff differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-LightItalic-webfont.eot b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-LightItalic-webfont.eot new file mode 100755 index 00000000..95c6c619 Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-LightItalic-webfont.eot differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-LightItalic-webfont.svg b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-LightItalic-webfont.svg new file mode 100755 index 00000000..1ac169c0 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-LightItalic-webfont.svg @@ -0,0 +1,252 @@ + + + + +This is a custom SVG webfont generated by Font Squirrel. +Copyright : Digitized data copyright 20102011 Google Corporation +Foundry : Ascender Corporation +Foundry URL : httpwwwascendercorpcom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-LightItalic-webfont.ttf b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-LightItalic-webfont.ttf new file mode 100755 index 00000000..3162ff8e Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-LightItalic-webfont.ttf differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-LightItalic-webfont.woff b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-LightItalic-webfont.woff new file mode 100755 index 00000000..f6e97d5a Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-LightItalic-webfont.woff differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Regular-webfont.eot b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Regular-webfont.eot new file mode 100755 index 00000000..545b7c15 Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Regular-webfont.eot differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Regular-webfont.svg b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Regular-webfont.svg new file mode 100755 index 00000000..46a8f4c6 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Regular-webfont.svg @@ -0,0 +1,252 @@ + + + + +This is a custom SVG webfont generated by Font Squirrel. +Copyright : Digitized data copyright 20102011 Google Corporation +Foundry : Ascender Corporation +Foundry URL : httpwwwascendercorpcom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Regular-webfont.ttf b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Regular-webfont.ttf new file mode 100755 index 00000000..a5b2378e Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Regular-webfont.ttf differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Regular-webfont.woff b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Regular-webfont.woff new file mode 100755 index 00000000..11698afc Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Regular-webfont.woff differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Semibold-webfont.eot b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Semibold-webfont.eot new file mode 100755 index 00000000..acc32c42 Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Semibold-webfont.eot differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Semibold-webfont.svg b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Semibold-webfont.svg new file mode 100755 index 00000000..ef8b7a2b --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Semibold-webfont.svg @@ -0,0 +1,251 @@ + + + + +This is a custom SVG webfont generated by Font Squirrel. +Copyright : Digitized data copyright 2011 Google Corporation +Foundry : Ascender Corporation +Foundry URL : httpwwwascendercorpcom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Semibold-webfont.ttf b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Semibold-webfont.ttf new file mode 100755 index 00000000..a5b9691c Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Semibold-webfont.ttf differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Semibold-webfont.woff b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Semibold-webfont.woff new file mode 100755 index 00000000..17fb5dc3 Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-Semibold-webfont.woff differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-SemiboldItalic-webfont.eot b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-SemiboldItalic-webfont.eot new file mode 100755 index 00000000..0048da00 Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-SemiboldItalic-webfont.eot differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-SemiboldItalic-webfont.svg b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-SemiboldItalic-webfont.svg new file mode 100755 index 00000000..46cfd5c8 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-SemiboldItalic-webfont.svg @@ -0,0 +1,251 @@ + + + + +This is a custom SVG webfont generated by Font Squirrel. +Copyright : Digitized data copyright 20102011 Google Corporation +Foundry : Ascender Corporation +Foundry URL : httpwwwascendercorpcom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-SemiboldItalic-webfont.ttf b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-SemiboldItalic-webfont.ttf new file mode 100755 index 00000000..61d58bfa Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-SemiboldItalic-webfont.ttf differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-SemiboldItalic-webfont.woff b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-SemiboldItalic-webfont.woff new file mode 100755 index 00000000..611b3902 Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/OpenSans-SemiboldItalic-webfont.woff differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/fontwso2.eot b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/fontwso2.eot new file mode 100755 index 00000000..5bc87bdb Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/fontwso2.eot differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/fontwso2.svg b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/fontwso2.svg new file mode 100755 index 00000000..40683e9e --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/fontwso2.svg @@ -0,0 +1,124 @@ + + + +Generated by IcoMoon + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/fontwso2.ttf b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/fontwso2.ttf new file mode 100755 index 00000000..787e513d Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/fontwso2.ttf differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/fontwso2.woff b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/fontwso2.woff new file mode 100755 index 00000000..669b1a42 Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/fontwso2.woff differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/glyphicons-halflings-regular.eot b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/glyphicons-halflings-regular.eot new file mode 100755 index 00000000..4a4ca865 Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/glyphicons-halflings-regular.eot differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/glyphicons-halflings-regular.svg b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/glyphicons-halflings-regular.svg new file mode 100755 index 00000000..25691af8 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/glyphicons-halflings-regular.svg @@ -0,0 +1,229 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/glyphicons-halflings-regular.ttf b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/glyphicons-halflings-regular.ttf new file mode 100755 index 00000000..67fa00bf Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/glyphicons-halflings-regular.ttf differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/glyphicons-halflings-regular.woff b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/glyphicons-halflings-regular.woff new file mode 100755 index 00000000..8c54182a Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/fonts/glyphicons-halflings-regular.woff differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/images/content-bg-1.png b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/images/content-bg-1.png new file mode 100755 index 00000000..288797ce Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/images/content-bg-1.png differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/images/content-bg.png b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/images/content-bg.png new file mode 100755 index 00000000..cf4e63e7 Binary files /dev/null and b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/images/content-bg.png differ diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/js/bootstrap.min.js b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/js/bootstrap.min.js new file mode 100755 index 00000000..c8f82e59 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/js/bootstrap.min.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v3.3.4 (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.4",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a(f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.4",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active"));a&&this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),c.preventDefault()}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.4",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));return a>this.$items.length-1||0>a?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide("next")},c.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.4",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){b&&3===b.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=c(d),f={relatedTarget:this};e.hasClass("open")&&(e.trigger(b=a.Event("hide.bs.dropdown",f)),b.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger("hidden.bs.dropdown",f)))}))}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.4",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(this.options.viewport.selector||this.options.viewport),this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c&&c.$tip&&c.$tip.is(":visible")?void(c.hoverState="in"):(c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.options.container?a(this.options.container):this.$element.parent(),p=this.getPosition(o);h="bottom"==h&&k.bottom+m>p.bottom?"top":"top"==h&&k.top-mp.width?"left":"left"==h&&k.left-lg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.width&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){return this.$tip=this.$tip||a(this.options.template)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type)})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;(e||!/destroy|hide/.test(b))&&(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.4",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.4",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b=e[a]&&(void 0===e[a+1]||b .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.4",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return c>e?"top":!1;if("bottom"==this.affixed)return null!=c?e+this.unpin<=f.top?!1:"bottom":a-d>=e+g?!1:"bottom";var h=null==this.affixed,i=h?e:f.top,j=h?g:b;return null!=c&&c>=e?"top":null!=d&&i+j>=a-d?"bottom":!1},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=a(document.body).height();"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/js/html5shiv.min.js b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/js/html5shiv.min.js new file mode 100755 index 00000000..8aff8f65 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/js/html5shiv.min.js @@ -0,0 +1,7 @@ +/** + * Created by Sharon on 5/14/2015. + */ +/** + * @preserve HTML5 Shiv 3.7.2 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed + */ +!function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.2",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b)}(this,document); \ No newline at end of file diff --git a/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/js/jquery-1.11.2.min.js b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/js/jquery-1.11.2.min.js new file mode 100755 index 00000000..18bdbed7 --- /dev/null +++ b/modules/distribution/src/repository/jaggeryapps/sensebot/units/theme/public/js/jquery-1.11.2.min.js @@ -0,0 +1,5 @@ +/*! jQuery v2.1.3 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */ +!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l=a.document,m="2.1.3",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){return!n.isArray(a)&&a-parseFloat(a)+1>=0},isPlainObject:function(a){return"object"!==n.type(a)||a.nodeType||n.isWindow(a)?!1:a.constructor&&!j.call(a.constructor.prototype,"isPrototypeOf")?!1:!0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=l.createElement("script"),b.text=a,l.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:k}),n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=hb(),z=hb(),A=hb(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},eb=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fb){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function gb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+rb(o[l]);w=ab.test(a)&&pb(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function hb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ib(a){return a[u]=!0,a}function jb(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function kb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function lb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function nb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function ob(a){return ib(function(b){return b=+b,ib(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pb(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=gb.support={},f=gb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=gb.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",eb,!1):e.attachEvent&&e.attachEvent("onunload",eb)),p=!f(g),c.attributes=jb(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=jb(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=jb(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(jb(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),jb(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&jb(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return lb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?lb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},gb.matches=function(a,b){return gb(a,null,null,b)},gb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return gb(b,n,null,[a]).length>0},gb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},gb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},gb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},gb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=gb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=gb.selectors={cacheLength:50,createPseudo:ib,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||gb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&gb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=gb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||gb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ib(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ib(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ib(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ib(function(a){return function(b){return gb(a,b).length>0}}),contains:ib(function(a){return a=a.replace(cb,db),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ib(function(a){return W.test(a||"")||gb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:ob(function(){return[0]}),last:ob(function(a,b){return[b-1]}),eq:ob(function(a,b,c){return[0>c?c+b:c]}),even:ob(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:ob(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:ob(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:ob(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function sb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function tb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ub(a,b,c){for(var d=0,e=b.length;e>d;d++)gb(a,b[d],c);return c}function vb(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wb(a,b,c,d,e,f){return d&&!d[u]&&(d=wb(d)),e&&!e[u]&&(e=wb(e,f)),ib(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ub(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:vb(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=vb(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=vb(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sb(function(a){return a===b},h,!0),l=sb(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sb(tb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wb(i>1&&tb(m),i>1&&rb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xb(a.slice(i,e)),f>e&&xb(a=a.slice(e)),f>e&&rb(a))}m.push(c)}return tb(m)}function yb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=vb(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&gb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ib(f):f}return h=gb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,yb(e,d)),f.selector=a}return f},i=gb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&pb(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&rb(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&pb(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=jb(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),jb(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||kb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&jb(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||kb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),jb(function(a){return null==a.getAttribute("disabled")})||kb(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),gb}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return g.call(b,a)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=n.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:l,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}return d=l.getElementById(c[2]),d&&d.parentNode&&(this.length=1,this[0]=d),this.context=l,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};A.prototype=n.fn,y=n(l);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?"string"==typeof a?g.call(n(a),this[0]):g.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,"parentNode")},parentsUntil:function(a,b,c){return n.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return n.dir(a,"nextSibling")},prevAll:function(a){return n.dir(a,"previousSibling")},nextUntil:function(a,b,c){return n.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return n.dir(a,"previousSibling",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(C[a]||n.unique(e),B.test(a)&&e.reverse()),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return n.each(a.match(E)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(b=a.memory&&l,c=!0,g=e||0,e=0,f=h.length,d=!0;h&&f>g;g++)if(h[g].apply(l[0],l[1])===!1&&a.stopOnFalse){b=!1;break}d=!1,h&&(i?i.length&&j(i.shift()):b?h=[]:k.disable())},k={add:function(){if(h){var c=h.length;!function g(b){n.each(b,function(b,c){var d=n.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&g(c)})}(arguments),d?f=h.length:b&&(e=c,j(b))}return this},remove:function(){return h&&n.each(arguments,function(a,b){var c;while((c=n.inArray(b,h,c))>-1)h.splice(c,1),d&&(f>=c&&f--,g>=c&&g--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],f=0,this},disable:function(){return h=i=b=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,b||k.disable(),this},locked:function(){return!i},fireWith:function(a,b){return!h||c&&!i||(b=b||[],b=[a,b.slice?b.slice():b],d?i.push(b):j(b)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!c}};return k},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(H.resolveWith(l,[n]),n.fn.triggerHandler&&(n(l).triggerHandler("ready"),n(l).off("ready"))))}});function I(){l.removeEventListener("DOMContentLoaded",I,!1),a.removeEventListener("load",I,!1),n.ready()}n.ready.promise=function(b){return H||(H=n.Deferred(),"complete"===l.readyState?setTimeout(n.ready):(l.addEventListener("DOMContentLoaded",I,!1),a.addEventListener("load",I,!1))),H.promise(b)},n.ready.promise();var J=n.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)n.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f};n.acceptData=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function K(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=n.expando+K.uid++}K.uid=1,K.accepts=n.acceptData,K.prototype={key:function(a){if(!K.accepts(a))return 0;var b={},c=a[this.expando];if(!c){c=K.uid++;try{b[this.expando]={value:c},Object.defineProperties(a,b)}catch(d){b[this.expando]=c,n.extend(a,b)}}return this.cache[c]||(this.cache[c]={}),c},set:function(a,b,c){var d,e=this.key(a),f=this.cache[e];if("string"==typeof b)f[b]=c;else if(n.isEmptyObject(f))n.extend(this.cache[e],b);else for(d in b)f[d]=b[d];return f},get:function(a,b){var c=this.cache[this.key(a)];return void 0===b?c:c[b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=this.key(a),g=this.cache[f];if(void 0===b)this.cache[f]={};else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in g?d=[b,e]:(d=e,d=d in g?[d]:d.match(E)||[])),c=d.length;while(c--)delete g[d[c]]}},hasData:function(a){return!n.isEmptyObject(this.cache[a[this.expando]]||{})},discard:function(a){a[this.expando]&&delete this.cache[a[this.expando]]}};var L=new K,M=new K,N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(O,"-$1").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}M.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return M.hasData(a)||L.hasData(a)},data:function(a,b,c){return M.access(a,b,c) +},removeData:function(a,b){M.remove(a,b)},_data:function(a,b,c){return L.access(a,b,c)},_removeData:function(a,b){L.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=M.get(f),1===f.nodeType&&!L.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));L.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){M.set(this,a)}):J(this,function(b){var c,d=n.camelCase(a);if(f&&void 0===b){if(c=M.get(f,a),void 0!==c)return c;if(c=M.get(f,d),void 0!==c)return c;if(c=P(f,d,void 0),void 0!==c)return c}else this.each(function(){var c=M.get(this,d);M.set(this,d,b),-1!==a.indexOf("-")&&void 0!==c&&M.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){M.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=L.get(a,b),c&&(!d||n.isArray(c)?d=L.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return L.get(a,c)||L.access(a,c,{empty:n.Callbacks("once memory").add(function(){L.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthx",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U="undefined";k.focusinBubbles="onfocusin"in a;var V=/^key/,W=/^(?:mouse|pointer|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return l.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof n!==U&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(E)||[""],j=b.length;while(j--)h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&(delete r.handle,L.remove(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,m,o,p=[d||l],q=j.call(b,"type")?b.type:b,r=j.call(b,"namespace")?b.namespace.split("."):[];if(g=h=d=d||l,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+n.event.triggered)&&(q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),k=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},e||!o.trigger||o.trigger.apply(d,c)!==!1)){if(!e&&!o.noBubble&&!n.isWindow(d)){for(i=o.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||l)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:o.bindType||q,m=(L.get(g,"events")||{})[b.type]&&L.get(g,"handle"),m&&m.apply(g,c),m=k&&g[k],m&&m.apply&&n.acceptData(g)&&(b.result=m.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!n.acceptData(d)||k&&n.isFunction(d[q])&&!n.isWindow(d)&&(h=d[k],h&&(d[k]=null),n.event.triggered=q,d[q](),n.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(L.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!==this;i=i.parentNode||this)if(i.disabled!==!0||"click"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>=0:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]*)\/>/gi,bb=/<([\w:]+)/,cb=/<|&#?\w+;/,db=/<(?:script|style|link)/i,eb=/checked\s*(?:[^=]|=\s*.checked.)/i,fb=/^$|\/(?:java|ecma)script/i,gb=/^true\/(.*)/,hb=/^\s*\s*$/g,ib={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ib.optgroup=ib.option,ib.tbody=ib.tfoot=ib.colgroup=ib.caption=ib.thead,ib.th=ib.td;function jb(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function kb(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function lb(a){var b=gb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function mb(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],"globalEval",!b||L.get(b[c],"globalEval"))}function nb(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=n.extend({},h),M.set(b,i))}}function ob(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||"*"):a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function pb(a,b){var c=b.nodeName.toLowerCase();"input"===c&&T.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}n.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=ob(h),f=ob(a),d=0,e=f.length;e>d;d++)pb(f[d],g[d]);if(b)if(c)for(f=f||ob(a),g=g||ob(h),d=0,e=f.length;e>d;d++)nb(f[d],g[d]);else nb(a,h);return g=ob(h,"script"),g.length>0&&mb(g,!i&&ob(a,"script")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,o=a.length;o>m;m++)if(e=a[m],e||0===e)if("object"===n.type(e))n.merge(l,e.nodeType?[e]:e);else if(cb.test(e)){f=f||k.appendChild(b.createElement("div")),g=(bb.exec(e)||["",""])[1].toLowerCase(),h=ib[g]||ib._default,f.innerHTML=h[1]+e.replace(ab,"<$1>")+h[2],j=h[0];while(j--)f=f.lastChild;n.merge(l,f.childNodes),f=k.firstChild,f.textContent=""}else l.push(b.createTextNode(e));k.textContent="",m=0;while(e=l[m++])if((!d||-1===n.inArray(e,d))&&(i=n.contains(e.ownerDocument,e),f=ob(k.appendChild(e),"script"),i&&mb(f),c)){j=0;while(e=f[j++])fb.test(e.type||"")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f=n.event.special,g=0;void 0!==(c=a[g]);g++){if(n.acceptData(c)&&(e=c[L.expando],e&&(b=L.cache[e]))){if(b.events)for(d in b.events)f[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);L.cache[e]&&delete L.cache[e]}delete M.cache[c[M.expando]]}}}),n.fn.extend({text:function(a){return J(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(ob(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&mb(ob(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(ob(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return J(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!db.test(a)&&!ib[(bb.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(ab,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ob(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(ob(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,m=this,o=l-1,p=a[0],q=n.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&eb.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(c=n.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=n.map(ob(c,"script"),kb),g=f.length;l>j;j++)h=c,j!==o&&(h=n.clone(h,!0,!0),g&&n.merge(f,ob(h,"script"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,n.map(f,lb),j=0;g>j;j++)h=f[j],fb.test(h.type||"")&&!L.access(h,"globalEval")&&n.contains(i,h)&&(h.src?n._evalUrl&&n._evalUrl(h.src):n.globalEval(h.textContent.replace(hb,"")))}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),n(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qb,rb={};function sb(b,c){var d,e=n(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:n.css(e[0],"display");return e.detach(),f}function tb(a){var b=l,c=rb[a];return c||(c=sb(a,b),"none"!==c&&c||(qb=(qb||n("