.'
+ );
+ }
+ }
+ addAttr(el, name, JSON.stringify(value));
+ // #6887 firefox doesn't update muted state if set via attribute
+ // even immediately after element creation
+ if (!el.component &&
+ name === 'muted' &&
+ platformMustUseProp(el.tag, el.attrsMap.type, name)) {
+ addProp(el, name, 'true');
+ }
+ }
+ }
+}
+
+function checkInFor (el) {
+ var parent = el;
+ while (parent) {
+ if (parent.for !== undefined) {
+ return true
+ }
+ parent = parent.parent;
+ }
+ return false
+}
+
+function parseModifiers (name) {
+ var match = name.match(modifierRE);
+ if (match) {
+ var ret = {};
+ match.forEach(function (m) { ret[m.slice(1)] = true; });
+ return ret
+ }
+}
+
+function makeAttrsMap (attrs) {
+ var map = {};
+ for (var i = 0, l = attrs.length; i < l; i++) {
+ if (
+ "development" !== 'production' &&
+ map[attrs[i].name] && !isIE && !isEdge
+ ) {
+ warn$2('duplicate attribute: ' + attrs[i].name);
+ }
+ map[attrs[i].name] = attrs[i].value;
+ }
+ return map
+}
+
+// for script (e.g. type="x/template") or style, do not decode content
+function isTextTag (el) {
+ return el.tag === 'script' || el.tag === 'style'
+}
+
+function isForbiddenTag (el) {
+ return (
+ el.tag === 'style' ||
+ (el.tag === 'script' && (
+ !el.attrsMap.type ||
+ el.attrsMap.type === 'text/javascript'
+ ))
+ )
+}
+
+var ieNSBug = /^xmlns:NS\d+/;
+var ieNSPrefix = /^NS\d+:/;
+
+/* istanbul ignore next */
+function guardIESVGBug (attrs) {
+ var res = [];
+ for (var i = 0; i < attrs.length; i++) {
+ var attr = attrs[i];
+ if (!ieNSBug.test(attr.name)) {
+ attr.name = attr.name.replace(ieNSPrefix, '');
+ res.push(attr);
+ }
+ }
+ return res
+}
+
+function checkForAliasModel (el, value) {
+ var _el = el;
+ while (_el) {
+ if (_el.for && _el.alias === value) {
+ warn$2(
+ "<" + (el.tag) + " v-model=\"" + value + "\">: " +
+ "You are binding v-model directly to a v-for iteration alias. " +
+ "This will not be able to modify the v-for source array because " +
+ "writing to the alias is like modifying a function local variable. " +
+ "Consider using an array of objects and use v-model on an object property instead."
+ );
+ }
+ _el = _el.parent;
+ }
+}
+
+/* */
+
+/**
+ * Expand input[v-model] with dyanmic type bindings into v-if-else chains
+ * Turn this:
+ *
+ * into this:
+ *
+ *
+ *
+ */
+
+function preTransformNode (el, options) {
+ if (el.tag === 'input') {
+ var map = el.attrsMap;
+ if (!map['v-model']) {
+ return
+ }
+
+ var typeBinding;
+ if (map[':type'] || map['v-bind:type']) {
+ typeBinding = getBindingAttr(el, 'type');
+ }
+ if (!map.type && !typeBinding && map['v-bind']) {
+ typeBinding = "(" + (map['v-bind']) + ").type";
+ }
+
+ if (typeBinding) {
+ var ifCondition = getAndRemoveAttr(el, 'v-if', true);
+ var ifConditionExtra = ifCondition ? ("&&(" + ifCondition + ")") : "";
+ var hasElse = getAndRemoveAttr(el, 'v-else', true) != null;
+ var elseIfCondition = getAndRemoveAttr(el, 'v-else-if', true);
+ // 1. checkbox
+ var branch0 = cloneASTElement(el);
+ // process for on the main node
+ processFor(branch0);
+ addRawAttr(branch0, 'type', 'checkbox');
+ processElement(branch0, options);
+ branch0.processed = true; // prevent it from double-processed
+ branch0.if = "(" + typeBinding + ")==='checkbox'" + ifConditionExtra;
+ addIfCondition(branch0, {
+ exp: branch0.if,
+ block: branch0
+ });
+ // 2. add radio else-if condition
+ var branch1 = cloneASTElement(el);
+ getAndRemoveAttr(branch1, 'v-for', true);
+ addRawAttr(branch1, 'type', 'radio');
+ processElement(branch1, options);
+ addIfCondition(branch0, {
+ exp: "(" + typeBinding + ")==='radio'" + ifConditionExtra,
+ block: branch1
+ });
+ // 3. other
+ var branch2 = cloneASTElement(el);
+ getAndRemoveAttr(branch2, 'v-for', true);
+ addRawAttr(branch2, ':type', typeBinding);
+ processElement(branch2, options);
+ addIfCondition(branch0, {
+ exp: ifCondition,
+ block: branch2
+ });
+
+ if (hasElse) {
+ branch0.else = true;
+ } else if (elseIfCondition) {
+ branch0.elseif = elseIfCondition;
+ }
+
+ return branch0
+ }
+ }
+}
+
+function cloneASTElement (el) {
+ return createASTElement(el.tag, el.attrsList.slice(), el.parent)
+}
+
+var model$2 = {
+ preTransformNode: preTransformNode
+}
+
+var modules$1 = [
+ klass$1,
+ style$1,
+ model$2
+]
+
+/* */
+
+function text (el, dir) {
+ if (dir.value) {
+ addProp(el, 'textContent', ("_s(" + (dir.value) + ")"));
+ }
+}
+
+/* */
+
+function html (el, dir) {
+ if (dir.value) {
+ addProp(el, 'innerHTML', ("_s(" + (dir.value) + ")"));
+ }
+}
+
+var directives$1 = {
+ model: model,
+ text: text,
+ html: html
+}
+
+/* */
+
+var baseOptions = {
+ expectHTML: true,
+ modules: modules$1,
+ directives: directives$1,
+ isPreTag: isPreTag,
+ isUnaryTag: isUnaryTag,
+ mustUseProp: mustUseProp,
+ canBeLeftOpenTag: canBeLeftOpenTag,
+ isReservedTag: isReservedTag,
+ getTagNamespace: getTagNamespace,
+ staticKeys: genStaticKeys(modules$1)
+};
+
+/* */
+
+var isStaticKey;
+var isPlatformReservedTag;
+
+var genStaticKeysCached = cached(genStaticKeys$1);
+
+/**
+ * Goal of the optimizer: walk the generated template AST tree
+ * and detect sub-trees that are purely static, i.e. parts of
+ * the DOM that never needs to change.
+ *
+ * Once we detect these sub-trees, we can:
+ *
+ * 1. Hoist them into constants, so that we no longer need to
+ * create fresh nodes for them on each re-render;
+ * 2. Completely skip them in the patching process.
+ */
+function optimize (root, options) {
+ if (!root) { return }
+ isStaticKey = genStaticKeysCached(options.staticKeys || '');
+ isPlatformReservedTag = options.isReservedTag || no;
+ // first pass: mark all non-static nodes.
+ markStatic$1(root);
+ // second pass: mark static roots.
+ markStaticRoots(root, false);
+}
+
+function genStaticKeys$1 (keys) {
+ return makeMap(
+ 'type,tag,attrsList,attrsMap,plain,parent,children,attrs' +
+ (keys ? ',' + keys : '')
+ )
+}
+
+function markStatic$1 (node) {
+ node.static = isStatic(node);
+ if (node.type === 1) {
+ // do not make component slot content static. this avoids
+ // 1. components not able to mutate slot nodes
+ // 2. static slot content fails for hot-reloading
+ if (
+ !isPlatformReservedTag(node.tag) &&
+ node.tag !== 'slot' &&
+ node.attrsMap['inline-template'] == null
+ ) {
+ return
+ }
+ for (var i = 0, l = node.children.length; i < l; i++) {
+ var child = node.children[i];
+ markStatic$1(child);
+ if (!child.static) {
+ node.static = false;
+ }
+ }
+ if (node.ifConditions) {
+ for (var i$1 = 1, l$1 = node.ifConditions.length; i$1 < l$1; i$1++) {
+ var block = node.ifConditions[i$1].block;
+ markStatic$1(block);
+ if (!block.static) {
+ node.static = false;
+ }
+ }
+ }
+ }
+}
+
+function markStaticRoots (node, isInFor) {
+ if (node.type === 1) {
+ if (node.static || node.once) {
+ node.staticInFor = isInFor;
+ }
+ // For a node to qualify as a static root, it should have children that
+ // are not just static text. Otherwise the cost of hoisting out will
+ // outweigh the benefits and it's better off to just always render it fresh.
+ if (node.static && node.children.length && !(
+ node.children.length === 1 &&
+ node.children[0].type === 3
+ )) {
+ node.staticRoot = true;
+ return
+ } else {
+ node.staticRoot = false;
+ }
+ if (node.children) {
+ for (var i = 0, l = node.children.length; i < l; i++) {
+ markStaticRoots(node.children[i], isInFor || !!node.for);
+ }
+ }
+ if (node.ifConditions) {
+ for (var i$1 = 1, l$1 = node.ifConditions.length; i$1 < l$1; i$1++) {
+ markStaticRoots(node.ifConditions[i$1].block, isInFor);
+ }
+ }
+ }
+}
+
+function isStatic (node) {
+ if (node.type === 2) { // expression
+ return false
+ }
+ if (node.type === 3) { // text
+ return true
+ }
+ return !!(node.pre || (
+ !node.hasBindings && // no dynamic bindings
+ !node.if && !node.for && // not v-if or v-for or v-else
+ !isBuiltInTag(node.tag) && // not a built-in
+ isPlatformReservedTag(node.tag) && // not a component
+ !isDirectChildOfTemplateFor(node) &&
+ Object.keys(node).every(isStaticKey)
+ ))
+}
+
+function isDirectChildOfTemplateFor (node) {
+ while (node.parent) {
+ node = node.parent;
+ if (node.tag !== 'template') {
+ return false
+ }
+ if (node.for) {
+ return true
+ }
+ }
+ return false
+}
+
+/* */
+
+var fnExpRE = /^([\w$_]+|\([^)]*?\))\s*=>|^function\s*\(/;
+var simplePathRE = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['[^']*?']|\["[^"]*?"]|\[\d+]|\[[A-Za-z_$][\w$]*])*$/;
+
+// KeyboardEvent.keyCode aliases
+var keyCodes = {
+ esc: 27,
+ tab: 9,
+ enter: 13,
+ space: 32,
+ up: 38,
+ left: 37,
+ right: 39,
+ down: 40,
+ 'delete': [8, 46]
+};
+
+// KeyboardEvent.key aliases
+var keyNames = {
+ esc: 'Escape',
+ tab: 'Tab',
+ enter: 'Enter',
+ space: ' ',
+ // #7806: IE11 uses key names without `Arrow` prefix for arrow keys.
+ up: ['Up', 'ArrowUp'],
+ left: ['Left', 'ArrowLeft'],
+ right: ['Right', 'ArrowRight'],
+ down: ['Down', 'ArrowDown'],
+ 'delete': ['Backspace', 'Delete']
+};
+
+// #4868: modifiers that prevent the execution of the listener
+// need to explicitly return null so that we can determine whether to remove
+// the listener for .once
+var genGuard = function (condition) { return ("if(" + condition + ")return null;"); };
+
+var modifierCode = {
+ stop: '$event.stopPropagation();',
+ prevent: '$event.preventDefault();',
+ self: genGuard("$event.target !== $event.currentTarget"),
+ ctrl: genGuard("!$event.ctrlKey"),
+ shift: genGuard("!$event.shiftKey"),
+ alt: genGuard("!$event.altKey"),
+ meta: genGuard("!$event.metaKey"),
+ left: genGuard("'button' in $event && $event.button !== 0"),
+ middle: genGuard("'button' in $event && $event.button !== 1"),
+ right: genGuard("'button' in $event && $event.button !== 2")
+};
+
+function genHandlers (
+ events,
+ isNative,
+ warn
+) {
+ var res = isNative ? 'nativeOn:{' : 'on:{';
+ for (var name in events) {
+ res += "\"" + name + "\":" + (genHandler(name, events[name])) + ",";
+ }
+ return res.slice(0, -1) + '}'
+}
+
+function genHandler (
+ name,
+ handler
+) {
+ if (!handler) {
+ return 'function(){}'
+ }
+
+ if (Array.isArray(handler)) {
+ return ("[" + (handler.map(function (handler) { return genHandler(name, handler); }).join(',')) + "]")
+ }
+
+ var isMethodPath = simplePathRE.test(handler.value);
+ var isFunctionExpression = fnExpRE.test(handler.value);
+
+ if (!handler.modifiers) {
+ if (isMethodPath || isFunctionExpression) {
+ return handler.value
+ }
+ /* istanbul ignore if */
+ return ("function($event){" + (handler.value) + "}") // inline statement
+ } else {
+ var code = '';
+ var genModifierCode = '';
+ var keys = [];
+ for (var key in handler.modifiers) {
+ if (modifierCode[key]) {
+ genModifierCode += modifierCode[key];
+ // left/right
+ if (keyCodes[key]) {
+ keys.push(key);
+ }
+ } else if (key === 'exact') {
+ var modifiers = (handler.modifiers);
+ genModifierCode += genGuard(
+ ['ctrl', 'shift', 'alt', 'meta']
+ .filter(function (keyModifier) { return !modifiers[keyModifier]; })
+ .map(function (keyModifier) { return ("$event." + keyModifier + "Key"); })
+ .join('||')
+ );
+ } else {
+ keys.push(key);
+ }
+ }
+ if (keys.length) {
+ code += genKeyFilter(keys);
+ }
+ // Make sure modifiers like prevent and stop get executed after key filtering
+ if (genModifierCode) {
+ code += genModifierCode;
+ }
+ var handlerCode = isMethodPath
+ ? ("return " + (handler.value) + "($event)")
+ : isFunctionExpression
+ ? ("return (" + (handler.value) + ")($event)")
+ : handler.value;
+ /* istanbul ignore if */
+ return ("function($event){" + code + handlerCode + "}")
+ }
+}
+
+function genKeyFilter (keys) {
+ return ("if(!('button' in $event)&&" + (keys.map(genFilterCode).join('&&')) + ")return null;")
+}
+
+function genFilterCode (key) {
+ var keyVal = parseInt(key, 10);
+ if (keyVal) {
+ return ("$event.keyCode!==" + keyVal)
+ }
+ var keyCode = keyCodes[key];
+ var keyName = keyNames[key];
+ return (
+ "_k($event.keyCode," +
+ (JSON.stringify(key)) + "," +
+ (JSON.stringify(keyCode)) + "," +
+ "$event.key," +
+ "" + (JSON.stringify(keyName)) +
+ ")"
+ )
+}
+
+/* */
+
+function on (el, dir) {
+ if ("development" !== 'production' && dir.modifiers) {
+ warn("v-on without argument does not support modifiers.");
+ }
+ el.wrapListeners = function (code) { return ("_g(" + code + "," + (dir.value) + ")"); };
+}
+
+/* */
+
+function bind$1 (el, dir) {
+ el.wrapData = function (code) {
+ return ("_b(" + code + ",'" + (el.tag) + "'," + (dir.value) + "," + (dir.modifiers && dir.modifiers.prop ? 'true' : 'false') + (dir.modifiers && dir.modifiers.sync ? ',true' : '') + ")")
+ };
+}
+
+/* */
+
+var baseDirectives = {
+ on: on,
+ bind: bind$1,
+ cloak: noop
+}
+
+/* */
+
+var CodegenState = function CodegenState (options) {
+ this.options = options;
+ this.warn = options.warn || baseWarn;
+ this.transforms = pluckModuleFunction(options.modules, 'transformCode');
+ this.dataGenFns = pluckModuleFunction(options.modules, 'genData');
+ this.directives = extend(extend({}, baseDirectives), options.directives);
+ var isReservedTag = options.isReservedTag || no;
+ this.maybeComponent = function (el) { return !isReservedTag(el.tag); };
+ this.onceId = 0;
+ this.staticRenderFns = [];
+};
+
+
+
+function generate (
+ ast,
+ options
+) {
+ var state = new CodegenState(options);
+ var code = ast ? genElement(ast, state) : '_c("div")';
+ return {
+ render: ("with(this){return " + code + "}"),
+ staticRenderFns: state.staticRenderFns
+ }
+}
+
+function genElement (el, state) {
+ if (el.staticRoot && !el.staticProcessed) {
+ return genStatic(el, state)
+ } else if (el.once && !el.onceProcessed) {
+ return genOnce(el, state)
+ } else if (el.for && !el.forProcessed) {
+ return genFor(el, state)
+ } else if (el.if && !el.ifProcessed) {
+ return genIf(el, state)
+ } else if (el.tag === 'template' && !el.slotTarget) {
+ return genChildren(el, state) || 'void 0'
+ } else if (el.tag === 'slot') {
+ return genSlot(el, state)
+ } else {
+ // component or element
+ var code;
+ if (el.component) {
+ code = genComponent(el.component, el, state);
+ } else {
+ var data = el.plain ? undefined : genData$2(el, state);
+
+ var children = el.inlineTemplate ? null : genChildren(el, state, true);
+ code = "_c('" + (el.tag) + "'" + (data ? ("," + data) : '') + (children ? ("," + children) : '') + ")";
+ }
+ // module transforms
+ for (var i = 0; i < state.transforms.length; i++) {
+ code = state.transforms[i](el, code);
+ }
+ return code
+ }
+}
+
+// hoist static sub-trees out
+function genStatic (el, state) {
+ el.staticProcessed = true;
+ state.staticRenderFns.push(("with(this){return " + (genElement(el, state)) + "}"));
+ return ("_m(" + (state.staticRenderFns.length - 1) + (el.staticInFor ? ',true' : '') + ")")
+}
+
+// v-once
+function genOnce (el, state) {
+ el.onceProcessed = true;
+ if (el.if && !el.ifProcessed) {
+ return genIf(el, state)
+ } else if (el.staticInFor) {
+ var key = '';
+ var parent = el.parent;
+ while (parent) {
+ if (parent.for) {
+ key = parent.key;
+ break
+ }
+ parent = parent.parent;
+ }
+ if (!key) {
+ "development" !== 'production' && state.warn(
+ "v-once can only be used inside v-for that is keyed. "
+ );
+ return genElement(el, state)
+ }
+ return ("_o(" + (genElement(el, state)) + "," + (state.onceId++) + "," + key + ")")
+ } else {
+ return genStatic(el, state)
+ }
+}
+
+function genIf (
+ el,
+ state,
+ altGen,
+ altEmpty
+) {
+ el.ifProcessed = true; // avoid recursion
+ return genIfConditions(el.ifConditions.slice(), state, altGen, altEmpty)
+}
+
+function genIfConditions (
+ conditions,
+ state,
+ altGen,
+ altEmpty
+) {
+ if (!conditions.length) {
+ return altEmpty || '_e()'
+ }
+
+ var condition = conditions.shift();
+ if (condition.exp) {
+ return ("(" + (condition.exp) + ")?" + (genTernaryExp(condition.block)) + ":" + (genIfConditions(conditions, state, altGen, altEmpty)))
+ } else {
+ return ("" + (genTernaryExp(condition.block)))
+ }
+
+ // v-if with v-once should generate code like (a)?_m(0):_m(1)
+ function genTernaryExp (el) {
+ return altGen
+ ? altGen(el, state)
+ : el.once
+ ? genOnce(el, state)
+ : genElement(el, state)
+ }
+}
+
+function genFor (
+ el,
+ state,
+ altGen,
+ altHelper
+) {
+ var exp = el.for;
+ var alias = el.alias;
+ var iterator1 = el.iterator1 ? ("," + (el.iterator1)) : '';
+ var iterator2 = el.iterator2 ? ("," + (el.iterator2)) : '';
+
+ if ("development" !== 'production' &&
+ state.maybeComponent(el) &&
+ el.tag !== 'slot' &&
+ el.tag !== 'template' &&
+ !el.key
+ ) {
+ state.warn(
+ "<" + (el.tag) + " v-for=\"" + alias + " in " + exp + "\">: component lists rendered with " +
+ "v-for should have explicit keys. " +
+ "See https://vuejs.org/guide/list.html#key for more info.",
+ true /* tip */
+ );
+ }
+
+ el.forProcessed = true; // avoid recursion
+ return (altHelper || '_l') + "((" + exp + ")," +
+ "function(" + alias + iterator1 + iterator2 + "){" +
+ "return " + ((altGen || genElement)(el, state)) +
+ '})'
+}
+
+function genData$2 (el, state) {
+ var data = '{';
+
+ // directives first.
+ // directives may mutate the el's other properties before they are generated.
+ var dirs = genDirectives(el, state);
+ if (dirs) { data += dirs + ','; }
+
+ // key
+ if (el.key) {
+ data += "key:" + (el.key) + ",";
+ }
+ // ref
+ if (el.ref) {
+ data += "ref:" + (el.ref) + ",";
+ }
+ if (el.refInFor) {
+ data += "refInFor:true,";
+ }
+ // pre
+ if (el.pre) {
+ data += "pre:true,";
+ }
+ // record original tag name for components using "is" attribute
+ if (el.component) {
+ data += "tag:\"" + (el.tag) + "\",";
+ }
+ // module data generation functions
+ for (var i = 0; i < state.dataGenFns.length; i++) {
+ data += state.dataGenFns[i](el);
+ }
+ // attributes
+ if (el.attrs) {
+ data += "attrs:{" + (genProps(el.attrs)) + "},";
+ }
+ // DOM props
+ if (el.props) {
+ data += "domProps:{" + (genProps(el.props)) + "},";
+ }
+ // event handlers
+ if (el.events) {
+ data += (genHandlers(el.events, false, state.warn)) + ",";
+ }
+ if (el.nativeEvents) {
+ data += (genHandlers(el.nativeEvents, true, state.warn)) + ",";
+ }
+ // slot target
+ // only for non-scoped slots
+ if (el.slotTarget && !el.slotScope) {
+ data += "slot:" + (el.slotTarget) + ",";
+ }
+ // scoped slots
+ if (el.scopedSlots) {
+ data += (genScopedSlots(el.scopedSlots, state)) + ",";
+ }
+ // component v-model
+ if (el.model) {
+ data += "model:{value:" + (el.model.value) + ",callback:" + (el.model.callback) + ",expression:" + (el.model.expression) + "},";
+ }
+ // inline-template
+ if (el.inlineTemplate) {
+ var inlineTemplate = genInlineTemplate(el, state);
+ if (inlineTemplate) {
+ data += inlineTemplate + ",";
+ }
+ }
+ data = data.replace(/,$/, '') + '}';
+ // v-bind data wrap
+ if (el.wrapData) {
+ data = el.wrapData(data);
+ }
+ // v-on data wrap
+ if (el.wrapListeners) {
+ data = el.wrapListeners(data);
+ }
+ return data
+}
+
+function genDirectives (el, state) {
+ var dirs = el.directives;
+ if (!dirs) { return }
+ var res = 'directives:[';
+ var hasRuntime = false;
+ var i, l, dir, needRuntime;
+ for (i = 0, l = dirs.length; i < l; i++) {
+ dir = dirs[i];
+ needRuntime = true;
+ var gen = state.directives[dir.name];
+ if (gen) {
+ // compile-time directive that manipulates AST.
+ // returns true if it also needs a runtime counterpart.
+ needRuntime = !!gen(el, dir, state.warn);
+ }
+ if (needRuntime) {
+ hasRuntime = true;
+ res += "{name:\"" + (dir.name) + "\",rawName:\"" + (dir.rawName) + "\"" + (dir.value ? (",value:(" + (dir.value) + "),expression:" + (JSON.stringify(dir.value))) : '') + (dir.arg ? (",arg:\"" + (dir.arg) + "\"") : '') + (dir.modifiers ? (",modifiers:" + (JSON.stringify(dir.modifiers))) : '') + "},";
+ }
+ }
+ if (hasRuntime) {
+ return res.slice(0, -1) + ']'
+ }
+}
+
+function genInlineTemplate (el, state) {
+ var ast = el.children[0];
+ if ("development" !== 'production' && (
+ el.children.length !== 1 || ast.type !== 1
+ )) {
+ state.warn('Inline-template components must have exactly one child element.');
+ }
+ if (ast.type === 1) {
+ var inlineRenderFns = generate(ast, state.options);
+ return ("inlineTemplate:{render:function(){" + (inlineRenderFns.render) + "},staticRenderFns:[" + (inlineRenderFns.staticRenderFns.map(function (code) { return ("function(){" + code + "}"); }).join(',')) + "]}")
+ }
+}
+
+function genScopedSlots (
+ slots,
+ state
+) {
+ return ("scopedSlots:_u([" + (Object.keys(slots).map(function (key) {
+ return genScopedSlot(key, slots[key], state)
+ }).join(',')) + "])")
+}
+
+function genScopedSlot (
+ key,
+ el,
+ state
+) {
+ if (el.for && !el.forProcessed) {
+ return genForScopedSlot(key, el, state)
+ }
+ var fn = "function(" + (String(el.slotScope)) + "){" +
+ "return " + (el.tag === 'template'
+ ? el.if
+ ? ((el.if) + "?" + (genChildren(el, state) || 'undefined') + ":undefined")
+ : genChildren(el, state) || 'undefined'
+ : genElement(el, state)) + "}";
+ return ("{key:" + key + ",fn:" + fn + "}")
+}
+
+function genForScopedSlot (
+ key,
+ el,
+ state
+) {
+ var exp = el.for;
+ var alias = el.alias;
+ var iterator1 = el.iterator1 ? ("," + (el.iterator1)) : '';
+ var iterator2 = el.iterator2 ? ("," + (el.iterator2)) : '';
+ el.forProcessed = true; // avoid recursion
+ return "_l((" + exp + ")," +
+ "function(" + alias + iterator1 + iterator2 + "){" +
+ "return " + (genScopedSlot(key, el, state)) +
+ '})'
+}
+
+function genChildren (
+ el,
+ state,
+ checkSkip,
+ altGenElement,
+ altGenNode
+) {
+ var children = el.children;
+ if (children.length) {
+ var el$1 = children[0];
+ // optimize single v-for
+ if (children.length === 1 &&
+ el$1.for &&
+ el$1.tag !== 'template' &&
+ el$1.tag !== 'slot'
+ ) {
+ return (altGenElement || genElement)(el$1, state)
+ }
+ var normalizationType = checkSkip
+ ? getNormalizationType(children, state.maybeComponent)
+ : 0;
+ var gen = altGenNode || genNode;
+ return ("[" + (children.map(function (c) { return gen(c, state); }).join(',')) + "]" + (normalizationType ? ("," + normalizationType) : ''))
+ }
+}
+
+// determine the normalization needed for the children array.
+// 0: no normalization needed
+// 1: simple normalization needed (possible 1-level deep nested array)
+// 2: full normalization needed
+function getNormalizationType (
+ children,
+ maybeComponent
+) {
+ var res = 0;
+ for (var i = 0; i < children.length; i++) {
+ var el = children[i];
+ if (el.type !== 1) {
+ continue
+ }
+ if (needsNormalization(el) ||
+ (el.ifConditions && el.ifConditions.some(function (c) { return needsNormalization(c.block); }))) {
+ res = 2;
+ break
+ }
+ if (maybeComponent(el) ||
+ (el.ifConditions && el.ifConditions.some(function (c) { return maybeComponent(c.block); }))) {
+ res = 1;
+ }
+ }
+ return res
+}
+
+function needsNormalization (el) {
+ return el.for !== undefined || el.tag === 'template' || el.tag === 'slot'
+}
+
+function genNode (node, state) {
+ if (node.type === 1) {
+ return genElement(node, state)
+ } if (node.type === 3 && node.isComment) {
+ return genComment(node)
+ } else {
+ return genText(node)
+ }
+}
+
+function genText (text) {
+ return ("_v(" + (text.type === 2
+ ? text.expression // no need for () because already wrapped in _s()
+ : transformSpecialNewlines(JSON.stringify(text.text))) + ")")
+}
+
+function genComment (comment) {
+ return ("_e(" + (JSON.stringify(comment.text)) + ")")
+}
+
+function genSlot (el, state) {
+ var slotName = el.slotName || '"default"';
+ var children = genChildren(el, state);
+ var res = "_t(" + slotName + (children ? ("," + children) : '');
+ var attrs = el.attrs && ("{" + (el.attrs.map(function (a) { return ((camelize(a.name)) + ":" + (a.value)); }).join(',')) + "}");
+ var bind$$1 = el.attrsMap['v-bind'];
+ if ((attrs || bind$$1) && !children) {
+ res += ",null";
+ }
+ if (attrs) {
+ res += "," + attrs;
+ }
+ if (bind$$1) {
+ res += (attrs ? '' : ',null') + "," + bind$$1;
+ }
+ return res + ')'
+}
+
+// componentName is el.component, take it as argument to shun flow's pessimistic refinement
+function genComponent (
+ componentName,
+ el,
+ state
+) {
+ var children = el.inlineTemplate ? null : genChildren(el, state, true);
+ return ("_c(" + componentName + "," + (genData$2(el, state)) + (children ? ("," + children) : '') + ")")
+}
+
+function genProps (props) {
+ var res = '';
+ for (var i = 0; i < props.length; i++) {
+ var prop = props[i];
+ /* istanbul ignore if */
+ {
+ res += "\"" + (prop.name) + "\":" + (transformSpecialNewlines(prop.value)) + ",";
+ }
+ }
+ return res.slice(0, -1)
+}
+
+// #3895, #4268
+function transformSpecialNewlines (text) {
+ return text
+ .replace(/\u2028/g, '\\u2028')
+ .replace(/\u2029/g, '\\u2029')
+}
+
+/* */
+
+// these keywords should not appear inside expressions, but operators like
+// typeof, instanceof and in are allowed
+var prohibitedKeywordRE = new RegExp('\\b' + (
+ 'do,if,for,let,new,try,var,case,else,with,await,break,catch,class,const,' +
+ 'super,throw,while,yield,delete,export,import,return,switch,default,' +
+ 'extends,finally,continue,debugger,function,arguments'
+).split(',').join('\\b|\\b') + '\\b');
+
+// these unary operators should not be used as property/method names
+var unaryOperatorsRE = new RegExp('\\b' + (
+ 'delete,typeof,void'
+).split(',').join('\\s*\\([^\\)]*\\)|\\b') + '\\s*\\([^\\)]*\\)');
+
+// strip strings in expressions
+var stripStringRE = /'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`(?:[^`\\]|\\.)*\$\{|\}(?:[^`\\]|\\.)*`|`(?:[^`\\]|\\.)*`/g;
+
+// detect problematic expressions in a template
+function detectErrors (ast) {
+ var errors = [];
+ if (ast) {
+ checkNode(ast, errors);
+ }
+ return errors
+}
+
+function checkNode (node, errors) {
+ if (node.type === 1) {
+ for (var name in node.attrsMap) {
+ if (dirRE.test(name)) {
+ var value = node.attrsMap[name];
+ if (value) {
+ if (name === 'v-for') {
+ checkFor(node, ("v-for=\"" + value + "\""), errors);
+ } else if (onRE.test(name)) {
+ checkEvent(value, (name + "=\"" + value + "\""), errors);
+ } else {
+ checkExpression(value, (name + "=\"" + value + "\""), errors);
+ }
+ }
+ }
+ }
+ if (node.children) {
+ for (var i = 0; i < node.children.length; i++) {
+ checkNode(node.children[i], errors);
+ }
+ }
+ } else if (node.type === 2) {
+ checkExpression(node.expression, node.text, errors);
+ }
+}
+
+function checkEvent (exp, text, errors) {
+ var stipped = exp.replace(stripStringRE, '');
+ var keywordMatch = stipped.match(unaryOperatorsRE);
+ if (keywordMatch && stipped.charAt(keywordMatch.index - 1) !== '$') {
+ errors.push(
+ "avoid using JavaScript unary operator as property name: " +
+ "\"" + (keywordMatch[0]) + "\" in expression " + (text.trim())
+ );
+ }
+ checkExpression(exp, text, errors);
+}
+
+function checkFor (node, text, errors) {
+ checkExpression(node.for || '', text, errors);
+ checkIdentifier(node.alias, 'v-for alias', text, errors);
+ checkIdentifier(node.iterator1, 'v-for iterator', text, errors);
+ checkIdentifier(node.iterator2, 'v-for iterator', text, errors);
+}
+
+function checkIdentifier (
+ ident,
+ type,
+ text,
+ errors
+) {
+ if (typeof ident === 'string') {
+ try {
+ new Function(("var " + ident + "=_"));
+ } catch (e) {
+ errors.push(("invalid " + type + " \"" + ident + "\" in expression: " + (text.trim())));
+ }
+ }
+}
+
+function checkExpression (exp, text, errors) {
+ try {
+ new Function(("return " + exp));
+ } catch (e) {
+ var keywordMatch = exp.replace(stripStringRE, '').match(prohibitedKeywordRE);
+ if (keywordMatch) {
+ errors.push(
+ "avoid using JavaScript keyword as property name: " +
+ "\"" + (keywordMatch[0]) + "\"\n Raw expression: " + (text.trim())
+ );
+ } else {
+ errors.push(
+ "invalid expression: " + (e.message) + " in\n\n" +
+ " " + exp + "\n\n" +
+ " Raw expression: " + (text.trim()) + "\n"
+ );
+ }
+ }
+}
+
+/* */
+
+function createFunction (code, errors) {
+ try {
+ return new Function(code)
+ } catch (err) {
+ errors.push({ err: err, code: code });
+ return noop
+ }
+}
+
+function createCompileToFunctionFn (compile) {
+ var cache = Object.create(null);
+
+ return function compileToFunctions (
+ template,
+ options,
+ vm
+ ) {
+ options = extend({}, options);
+ var warn$$1 = options.warn || warn;
+ delete options.warn;
+
+ /* istanbul ignore if */
+ {
+ // detect possible CSP restriction
+ try {
+ new Function('return 1');
+ } catch (e) {
+ if (e.toString().match(/unsafe-eval|CSP/)) {
+ warn$$1(
+ 'It seems you are using the standalone build of Vue.js in an ' +
+ 'environment with Content Security Policy that prohibits unsafe-eval. ' +
+ 'The template compiler cannot work in this environment. Consider ' +
+ 'relaxing the policy to allow unsafe-eval or pre-compiling your ' +
+ 'templates into render functions.'
+ );
+ }
+ }
+ }
+
+ // check cache
+ var key = options.delimiters
+ ? String(options.delimiters) + template
+ : template;
+ if (cache[key]) {
+ return cache[key]
+ }
+
+ // compile
+ var compiled = compile(template, options);
+
+ // check compilation errors/tips
+ {
+ if (compiled.errors && compiled.errors.length) {
+ warn$$1(
+ "Error compiling template:\n\n" + template + "\n\n" +
+ compiled.errors.map(function (e) { return ("- " + e); }).join('\n') + '\n',
+ vm
+ );
+ }
+ if (compiled.tips && compiled.tips.length) {
+ compiled.tips.forEach(function (msg) { return tip(msg, vm); });
+ }
+ }
+
+ // turn code into functions
+ var res = {};
+ var fnGenErrors = [];
+ res.render = createFunction(compiled.render, fnGenErrors);
+ res.staticRenderFns = compiled.staticRenderFns.map(function (code) {
+ return createFunction(code, fnGenErrors)
+ });
+
+ // check function generation errors.
+ // this should only happen if there is a bug in the compiler itself.
+ // mostly for codegen development use
+ /* istanbul ignore if */
+ {
+ if ((!compiled.errors || !compiled.errors.length) && fnGenErrors.length) {
+ warn$$1(
+ "Failed to generate render function:\n\n" +
+ fnGenErrors.map(function (ref) {
+ var err = ref.err;
+ var code = ref.code;
+
+ return ((err.toString()) + " in\n\n" + code + "\n");
+ }).join('\n'),
+ vm
+ );
+ }
+ }
+
+ return (cache[key] = res)
+ }
+}
+
+/* */
+
+function createCompilerCreator (baseCompile) {
+ return function createCompiler (baseOptions) {
+ function compile (
+ template,
+ options
+ ) {
+ var finalOptions = Object.create(baseOptions);
+ var errors = [];
+ var tips = [];
+ finalOptions.warn = function (msg, tip) {
+ (tip ? tips : errors).push(msg);
+ };
+
+ if (options) {
+ // merge custom modules
+ if (options.modules) {
+ finalOptions.modules =
+ (baseOptions.modules || []).concat(options.modules);
+ }
+ // merge custom directives
+ if (options.directives) {
+ finalOptions.directives = extend(
+ Object.create(baseOptions.directives || null),
+ options.directives
+ );
+ }
+ // copy other options
+ for (var key in options) {
+ if (key !== 'modules' && key !== 'directives') {
+ finalOptions[key] = options[key];
+ }
+ }
+ }
+
+ var compiled = baseCompile(template, finalOptions);
+ {
+ errors.push.apply(errors, detectErrors(compiled.ast));
+ }
+ compiled.errors = errors;
+ compiled.tips = tips;
+ return compiled
+ }
+
+ return {
+ compile: compile,
+ compileToFunctions: createCompileToFunctionFn(compile)
+ }
+ }
+}
+
+/* */
+
+// `createCompilerCreator` allows creating compilers that use alternative
+// parser/optimizer/codegen, e.g the SSR optimizing compiler.
+// Here we just export a default compiler using the default parts.
+var createCompiler = createCompilerCreator(function baseCompile (
+ template,
+ options
+) {
+ var ast = parse(template.trim(), options);
+ if (options.optimize !== false) {
+ optimize(ast, options);
+ }
+ var code = generate(ast, options);
+ return {
+ ast: ast,
+ render: code.render,
+ staticRenderFns: code.staticRenderFns
+ }
+});
+
+/* */
+
+var ref$1 = createCompiler(baseOptions);
+var compileToFunctions = ref$1.compileToFunctions;
+
+/* */
+
+// check whether current browser encodes a char inside attribute values
+var div;
+function getShouldDecode (href) {
+ div = div || document.createElement('div');
+ div.innerHTML = href ? "
" : "";
+ return div.innerHTML.indexOf('
') > 0
+}
+
+// #3663: IE encodes newlines inside attribute values while other browsers don't
+var shouldDecodeNewlines = inBrowser ? getShouldDecode(false) : false;
+// #6828: chrome encodes content in a[href]
+var shouldDecodeNewlinesForHref = inBrowser ? getShouldDecode(true) : false;
+
+/* */
+
+var idToTemplate = cached(function (id) {
+ var el = query(id);
+ return el && el.innerHTML
+});
+
+var mount = Vue.prototype.$mount;
+Vue.prototype.$mount = function (
+ el,
+ hydrating
+) {
+ el = el && query(el);
+
+ /* istanbul ignore if */
+ if (el === document.body || el === document.documentElement) {
+ "development" !== 'production' && warn(
+ "Do not mount Vue to or - mount to normal elements instead."
+ );
+ return this
+ }
+
+ var options = this.$options;
+ // resolve template/el and convert to render function
+ if (!options.render) {
+ var template = options.template;
+ if (template) {
+ if (typeof template === 'string') {
+ if (template.charAt(0) === '#') {
+ template = idToTemplate(template);
+ /* istanbul ignore if */
+ if ("development" !== 'production' && !template) {
+ warn(
+ ("Template element not found or is empty: " + (options.template)),
+ this
+ );
+ }
+ }
+ } else if (template.nodeType) {
+ template = template.innerHTML;
+ } else {
+ {
+ warn('invalid template option:' + template, this);
+ }
+ return this
+ }
+ } else if (el) {
+ template = getOuterHTML(el);
+ }
+ if (template) {
+ /* istanbul ignore if */
+ if ("development" !== 'production' && config.performance && mark) {
+ mark('compile');
+ }
+
+ var ref = compileToFunctions(template, {
+ shouldDecodeNewlines: shouldDecodeNewlines,
+ shouldDecodeNewlinesForHref: shouldDecodeNewlinesForHref,
+ delimiters: options.delimiters,
+ comments: options.comments
+ }, this);
+ var render = ref.render;
+ var staticRenderFns = ref.staticRenderFns;
+ options.render = render;
+ options.staticRenderFns = staticRenderFns;
+
+ /* istanbul ignore if */
+ if ("development" !== 'production' && config.performance && mark) {
+ mark('compile end');
+ measure(("vue " + (this._name) + " compile"), 'compile', 'compile end');
+ }
+ }
+ }
+ return mount.call(this, el, hydrating)
+};
+
+/**
+ * Get outerHTML of elements, taking care
+ * of SVG elements in IE as well.
+ */
+function getOuterHTML (el) {
+ if (el.outerHTML) {
+ return el.outerHTML
+ } else {
+ var container = document.createElement('div');
+ container.appendChild(el.cloneNode(true));
+ return container.innerHTML
+ }
+}
+
+Vue.compile = compileToFunctions;
+
+return Vue;
+
+})));
diff --git a/docs/index.html b/docs/index.html
index 0eed75f..b934506 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -88,15 +88,15 @@
-
+
+
-
+
+
diff --git a/docs/index.min.js b/docs/index.min.js
index 4c81e0f..efc3c48 100644
--- a/docs/index.min.js
+++ b/docs/index.min.js
@@ -5581,7 +5581,7 @@ var demoSections = [{
options: [{
name: "Discrete domains",
path: ["discreteDomains"],
- type: 'boolean',
+ type: 'Boolean',
// boolNames: ["Continuous", "Discrete"],
states: { "Discrete": 1, "Continuous": 0 }
}, {
diff --git a/docs/reference/api.md b/docs/reference/api.md
index e69de29..09b22a8 100644
--- a/docs/reference/api.md
+++ b/docs/reference/api.md
@@ -0,0 +1,57 @@
+# API
+
+## Modifying Data
+There are two ways to update data in a chart: either in adding and removing individual points, or updating the existing data with an entirely new set of data points.
+
+### Updating individual data points
+
+#### addDataPoint
+Add a data point to the chart, increasing the length of the dataset.
+
+```js
+addDataPoint(label: String, valueFromEachDataset: Array, index: Number): void
+
+// Usage
+let label = 'Wed';
+let valueFromEachDataset = [30, 17];
+
+chart.addDataPoint(label, valueFromEachDataset); // by default adds at end
+chart.addDataPoint(label, valueFromEachDataset, 6);
+```
+
+#### removeDataPoint
+Remove a data point from the chart, reducing the length of the dataset.
+
+```js
+removeDataPoint(index: Number): void
+
+// Usage
+chart.removeDataPoint(); // by default removes from end
+chart.removeDataPoint(10);
+```
+
+### Updating full data
+
+#### update
+
+Update the entire data, including annotations, by passing the entire new `data` object to `update`.
+
+```js
+update(data: Object): void
+
+// Usage
+chart.update(data);
+```
+
+## Exporting
+
+#### export
+
+Frappe charts are exportable to an SVG format, in which they are natively rendered.
+
+```js
+export(): void
+
+// Usage
+chart.export();
+```
diff --git a/docs/reference/configuration.md b/docs/reference/configuration.md
index 227c7c4..e6960e6 100644
--- a/docs/reference/configuration.md
+++ b/docs/reference/configuration.md
@@ -1,198 +1,186 @@
----
-sidebarDepth: 2
----
-
# Configuration
With all the customizable features of Frappe Charts, this section is dedicated to enabling / disabling existing functionality.
## Container
-The first parameter required by the `DataTable` constructor is the container element. You can pass in a CSS Selector or a DOM Object.
+The first parameter required by the `Chart` constructor is the container element. You can pass in a CSS Selector or a DOM Object.
```javascript
-const datatable = new DataTable('#datatable', options);
+const chart = new Chart('#chart', options);
// or
-const container = document.querySelector('#datatable');
-const datatable = new DataTable(container, options);
+const container = document.querySelector('#chart');
+const chart = new Chart(container, options);
```
## Options
-The second parameter required by the `DataTable` constructor is the options object. The minimum required configuration is to pass `column` and `data` values.
+The second parameter required by the `Chart` constructor is the options object. The minimum required configuration is to pass `data` values, which itself requires an array of `labels` and an array of `datasets`.
```javascript
const options = {
- columns: ['Name', 'Position', 'Salary'],
- data: [
- ['John Doe', 'DevOps Engineer', '$12300'],
- ['Mary Jane', 'UX Design', '$14000'],
- ]
+ data: {
+ labels: ["12am-3am", "3am-6am", "6am-9am", "9am-12pm", "12pm-3pm"],
+
+ datasets: [
+ {
+ name: "Some Data", values: [25, 40, 30, 35, 8]
+ },
+ {
+ name: "Another Set", values: [25, 50, -10, 15, 18]
+ }
+ ]
+ }
}
-const datatable = new DataTable(container, options);
+const chart = new Chart(container, options);
```
-The following options are configurable:
-
-### getEditor
- - Type: `Function`
- - Default: `null`
-
-Customize the editor behaviour.
-
----
-
-### serialNoColumn
- - Type: `Boolean`
- - Default: `true`
+### data
+ - Type: `Object`
+ - Required Properties: `labels`, `datasets`
+ - Optional Properties: `yMarkers`, `yRegions`
-Whether to show serial number as the first column in datatable.
+Contains an array of `labels` and an array of `datasets`, each a value for the 2-dimensional data points.
----
+May also have [annotation]() parameters, for example those for `yMarkers` and `yRegions`. This is because all properties defined inside data are meant to be animatable.
+```javascript
+data: {
+ labels: ["12am-3am", "3am-6am", "6am-9am", "9am-12pm", "12pm-3pm"],
-### checkboxColumn
- - Type: `Boolean`
- - Default: `false`
+ datasets: [
+ { name: "Some Data", values: [25, 40, 30, 35, 8] },
+ { name: "Another Set", values: [25, 50, -10, 15, 18] }
+ ],
-Whether to show checkbox column in the datatable.
+ yMarkers: [{ label: "Marker", value: 70 }],
----
+ yRegions: [{ label: "Region", start: -10, end: 50 }]
+}
+```
-### clusterize
- - Type: `Boolean`
- - Default: `true`
+Other configurable options are listed as follows:
-Whether to use clusterize to render the data.
+### title
+ - Type: `String`
+ - Default: `''`
-> If you don't want to show large number of rows. Then you can turn this off. In that case you don't need to load the `clusterize.js` lib
+Add a title to the Chart.
---
-### layout
+### type
- Type: `String`
- - Default: `fixed`
- - Options: `fixed | fluid | ratio`
+ - Values: `line | bar | axis-mixed | pie | percentage | heatmap`
+ - Default: `line`
-This option controls how width of each `column` is calculated in the DataTable.
+Let the chart know what type to render.
-#### fixed
+#### type: 'axis-mixed'
-The column width is calculated based on the content of the first row of the table. This layout can result in horizontal scroll.
+Mixed axis chart. For this to work, you must pass the `chartType` value for each dataset.
-#### fluid
+```javascript
-The column width is adjusted based on the width of container. So the columns will be resized if the window is resized. This layout won't result in horizontal scroll. You will always see all the columns.
+const data = {
+ labels: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
-#### ratio
+ datasets: [
+ {
+ name: "Some Data",
+ values: [18, 40, 30, 35, 8, 52, 17],
+ chartType: 'bar'
+ },
+ {
+ name: "Yet Another",
+ values: [15, 20, -3, -15, 58, 12, -17],
+ chartType: 'line'
+ }
+ ]
+}
-This layout works similar to the `flex` property in CSS. When column A has `width` set as `1` and column B as `2`, then column B's width will be twice as much as column A.
+const chart = new Chart('#chart', {
+ data: data
+});
+
+```
---
-### noDataMessage
- - Type: `String`
- - Default: `No Data`
+### colors
+ - Type: `Array`
+ - Default: `['light-blue', 'blue', 'violet', 'red', 'orange',
+ 'yellow', 'green', 'light-green', 'purple', 'magenta', 'light-grey', 'dark-grey']`
-The message shown when there are no rows to show in the DataTable.
+Set the colors to be used for each individual unit type, depending on the chart type.
---
-### dynamicRowHeight
- - Type: `Boolean`
- - Default: `false`
+### height
+ - Type: `Number`
+ - Default: `240`
-The height of the row will be set according to the content of the cell with the maximum height in that row.
+Set the height of the chart in pixels.
---
-### cellHeight
- - Type: `Number`
- - Default: `null`
-
-Set the height of each cell explicitly.
+### axisOptions
+ - Type: `Object`
+ - Default: `{}`
-> If this value is set, `dynamicRowHeight` won't have any effect.
+#### xAxisMode and yAxisMode
+ - Type: `String`
+ - Values: `span | tick`
+ - Default: `span`
----
+Foo
-### inlineFilters
+#### xIsSeries
- Type: `Boolean`
- - Default: `false`
+ - Default: `0`
-Whether to enable the inline filter feature. If the value is `true`, then you can activate the filter row by pressing `Ctrl/Cmd + F` after clicking on any cell in the DataTable.
+Foo
---
-### treeView
- - Type: `Boolean`
- - Default: `false`
-
-Whether to render rows in a tree structure. For this to work, you must pass the `indent` value for each row.
+### TooltipOptions
+ - Type: `Object`
+ - Default: `{}`
-Example
-```javascript
+####
+---
-const data = [
- {
- 'Department': 'IT Department',
- 'No of People': '10',
- 'indent': 0,
- },
- {
- 'Department': 'Javascript Team',
- 'No of People': '5',
- 'indent': 1,
- },
- {
- 'Department': 'Vue.js Team',
- 'No of People': '3',
- 'indent': 2,
- },
- {
- 'Department': 'React Team',
- 'No of People': '2',
- 'indent': 2,
- },
- {
- 'Department': 'Design Team',
- 'No of People': '5',
- 'indent': 1,
- },
-]
-
-const datatable = new DataTable('#datatable', {
- columns: ['Department', 'No of People'],
- data: data
-});
+### barOptions
+ - Type: `Object`
+ - Default: `{}`
-```
+This option controls how width of each `column` is calculated in the chart.
----
+#### spaceRatio
+ - Type: `Number`
+ - Min: `0`
+ - Max: `2`
+ - Default: `0.5`
-### checkedRowStatus
+#### stacked
- Type: `Boolean`
- - Default: `true`
-
-Whether to show the number of rows checked in a toast message.
+ - Default: `0`
---
-### pasteFromClipboard
- - _Experimental_
- - Type: `Boolean`
- - Default: `false`
+### lineOptions
+ - Type: `Object`
+ - Default: `{}`
-Whether to allow the user to paste copied content into selected cell(s).
+Foo
---
-### dropdownButton
- - Type: `String`
- - Default: `▼`
-
-String to render as the dropdown button. You can pass a span with an icon class.
+### isNavigable
+ - Type: `Boolean`
+ - Default: `0`
+Foo
Example
```javascript
@@ -202,25 +190,10 @@ Example
```
-### headerDropdown
- - Type: `Array`
-
-When you hover over any column, you see the dropdown button which is used to perform certain actions for that column.
-This options allows you to pass an array of custom buttons with custom actions defined by you.
-
-```javascript
-options = {
- headerDropdown: [
- {
- label: 'Copy column contents',
- action: function (column) {
- // code to copy the column contents
- }
- },
-}
-```
+### valuesOverPoints
+ - Type: `Boolean`
+ - Default: `0`
-### events
- - Type: `Object`
+Foo
- The events options is described in detailed in the [next section](events.md).
+###
diff --git a/docs/style.css b/docs/style.css
index 1129c44..8183556 100644
--- a/docs/style.css
+++ b/docs/style.css
@@ -1,3 +1,15 @@
-/* a {
- color: red;
-} */
\ No newline at end of file
+input[type="range"] {
+ padding: 0;
+}
+
+.input-wrapper {
+ display: flex;
+ margin-right: 15px;
+}
+
+.input-wrapper label {
+ margin-right: 10px;
+ margin-top: 5px;
+ font-size: 0.8em;
+ flex-shrink: 0;
+}
\ No newline at end of file
diff --git a/docs/update_state/modify_data.md b/docs/update_state/modify_data.md
index f30a68e..3c72705 100644
--- a/docs/update_state/modify_data.md
+++ b/docs/update_state/modify_data.md
@@ -1,8 +1,26 @@
+# Modifying Data
+
There are two ways to update data in a chart: either in adding and removing individual points, or updating the existing data with an entirely new set of data points.
-## Updating individual data points
+### Updating individual data points
+
+```js
+let label = 'Wed';
+let valueFromEachDataset = [30];
+let index = 10; // default for adding/removing values: last index
+
+chart.addDataPoint(label, valueFromEachDataset); // by default adds at end
+chart.addDataPoint(label, valueFromEachDataset, index);
+```
+
+```js
+let index = 10;
+chart.removeDataPoint();
+chart.removeDataPoint(index);
+```
+
-## Updating full data
+### Updating full data
+
+Another way is to simply update the entire data, including annotations, by passing the entire new `data` object to `update`.
+
+```js
+chart.update(data);
+```
-
-[update data with varying lengths]
-
diff --git a/docs/update_state/navigation.md b/docs/update_state/navigation.md
new file mode 100644
index 0000000..6911dec
--- /dev/null
+++ b/docs/update_state/navigation.md
@@ -0,0 +1,23 @@
+# Navigation
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/vuestyle.css b/docs/vuestyle.css
index 88733b7..af8b104 100644
--- a/docs/vuestyle.css
+++ b/docs/vuestyle.css
@@ -35,7 +35,7 @@ div#app:empty:before {
}
.progress {
- background-color: var(--theme-color, #42b983);
+ background-color: var(--theme-color, #7b85f2);
height: 2px;
left: 0;
position: fixed;
@@ -48,7 +48,7 @@ div#app:empty:before {
.search .search-keyword,
.search a:hover {
- color: var(--theme-color, #42b983)
+ color: var(--theme-color, #7b85f2)
}
.search .search-keyword {
@@ -138,11 +138,11 @@ li input[type=checkbox] {
.app-nav a.active,
.app-nav a:hover {
- color: var(--theme-color, #42b983)
+ color: var(--theme-color, #7b85f2)
}
.app-nav a.active {
- border-bottom: 2px solid var(--theme-color, #42b983)
+ border-bottom: 2px solid var(--theme-color, #7b85f2)
}
.app-nav li {
@@ -208,7 +208,7 @@ li input[type=checkbox] {
.github-corner svg {
color: #fff;
- fill: var(--theme-color, #42b983);
+ fill: var(--theme-color, #7b85f2);
height: 80px;
width: 80px
}
@@ -339,7 +339,7 @@ main.hidden {
}
.sidebar-toggle span {
- background-color: var(--theme-color, #42b983);
+ background-color: var(--theme-color, #7b85f2);
display: block;
margin-bottom: 4px;
width: 16px;
@@ -630,10 +630,10 @@ section.cover ul {
}
section.cover .cover-main>p:last-child a {
- border: 1px solid var(--theme-color, #42b983);
+ border: 1px solid var(--theme-color, #7b85f2);
border-radius: 2rem;
box-sizing: border-box;
- color: var(--theme-color, #42b983);
+ color: var(--theme-color, #7b85f2);
display: inline-block;
font-size: 1.05rem;
letter-spacing: .1rem;
@@ -644,7 +644,7 @@ section.cover .cover-main>p:last-child a {
}
section.cover .cover-main>p:last-child a:last-child {
- background-color: var(--theme-color, #42b983);
+ background-color: var(--theme-color, #7b85f2);
color: #fff
}
@@ -658,12 +658,12 @@ section.cover .cover-main>p:last-child a:hover {
}
section.cover blockquote>p>a {
- border-bottom: 2px solid var(--theme-color, #42b983);
+ border-bottom: 2px solid var(--theme-color, #7b85f2);
transition: color .3s
}
section.cover blockquote>p>a:hover {
- color: var(--theme-color, #42b983)
+ color: var(--theme-color, #7b85f2)
}
.sidebar,
@@ -699,7 +699,7 @@ body {
.sidebar ul li.active>a {
border-right: 2px solid;
- color: var(--theme-color, #42b983);
+ color: var(--theme-color, #7b85f2);
font-weight: 600
}
@@ -719,7 +719,7 @@ body {
}
.markdown-section a {
- color: var(--theme-color, #42b983);
+ color: var(--theme-color, #7b85f2);
font-weight: 600
}
@@ -769,7 +769,7 @@ body {
}
.markdown-section blockquote {
- border-left: 4px solid var(--theme-color, #42b983);
+ border-left: 4px solid var(--theme-color, #7b85f2);
color: #858585;
margin: 2em 0;
padding-left: 20px
@@ -843,7 +843,7 @@ body {
}
.token.string {
- color: var(--theme-color, #42b983)
+ color: var(--theme-color, #7b85f2)
}
.token.selector {
@@ -865,7 +865,7 @@ body {
.token.control,
.token.directive,
.token.unit {
- color: var(--theme-color, #42b983)
+ color: var(--theme-color, #7b85f2)
}
.token.keyword {
diff --git a/docs/wrappers.md b/docs/wrappers.md
new file mode 100644
index 0000000..4b0e208
--- /dev/null
+++ b/docs/wrappers.md
@@ -0,0 +1,4 @@
+- [@tobiaslins](https://github.com/tobiaslins) contributed tweaks for his quest to make these easy to use with React. Check out his [repo]
+- [@iamkdev's](https://github.com/iamkdev) blog on [usage with Angular](https://medium.com/@iamkdev/frappé-charts-with-angular-c9c5dd075d9f).
+- A [Ruby Gem](https://github.com/pacuna/frappe_charts).
+
diff --git a/src/js/utils/dom.js b/src/js/utils/dom.js
index c65b540..5cd386b 100644
--- a/src/js/utils/dom.js
+++ b/src/js/utils/dom.js
@@ -34,6 +34,11 @@ $.create = (tag, o) => {
val(element.value);
});
+ } else if (i === "onChange" ) {
+ element.addEventListener('change', function(e) {
+ val(element.value);
+ });
+
} else if (i === "styles") {
if(typeof val === "object") {
Object.keys(val).map(prop => {