Do some local style modifications and profile.

1. Do some temporary style modifications to help make the code more readable
   for profiling (with help from ESLint).
2. Profile the code, and optimize accordingly.
This commit is contained in:
impinball 2015-07-09 16:14:08 -04:00
parent 83a30a4d3c
commit 9ae592ee4d
12 changed files with 4426 additions and 2695 deletions

5
.eslintignore Normal file
View file

@ -0,0 +1,5 @@
node_modules
**/*.min.js
docs/layout/lib/**/*.js
tests/e2e/libs/**
mithril.closure-compiler-externs.js

27
.eslintrc Normal file
View file

@ -0,0 +1,27 @@
{
"env": {
"browser": true
},
"rules": {
"no-cond-assign": [2, "except-parens"],
"no-shadow": 0,
"semi-spacing": 0,
"quotes": [2, "double", "avoid-escape"],
"curly": [2, "multi-line"],
"semi": [2, "never"],
"eqeqeq": [2, "allow-null"],
"no-throw-literal": 2,
"wrap-iife": 2,
"strict": [2, "function"],
"brace-style": [2, "1tbs", { "allowSingleLine": true }],
"linebreak-style": [1, "windows"],
"one-var": [2, {
"initialized": "never"
}],
"new-cap": 0,
"no-use-before-define": [2, "nofunc"],
"max-len": [2, 80, 4],
"dot-notation": 2,
"indent": [2, "tab"]
}
}

View file

@ -1,14 +1,15 @@
/* eslint-env node */
module.exports = function(grunt) { module.exports = function(grunt) {
_ = require('lodash'); "use strict"
var version = "0.2.0"; var _ = require("lodash")
var version = "0.4.0"
var inputFolder = "./docs"; var inputFolder = "./docs"
var tempFolder = "./temp"; var tempFolder = "./temp"
var archiveFolder = "./archive"; var archiveFolder = "./archive"
var outputFolder = "../mithril"; var outputFolder = "../mithril"
var guideLayout = "guide";
var guide = [ var guide = [
"auto-redrawing", "auto-redrawing",
"benchmarks", "benchmarks",
@ -24,8 +25,7 @@ module.exports = function(grunt) {
"routing", "routing",
"tools", "tools",
"web-services" "web-services"
]; ]
var apiLayout = "api";
var api = [ var api = [
"change-log", "change-log",
"roadmap", "roadmap",
@ -45,55 +45,68 @@ module.exports = function(grunt) {
"mithril.trust", "mithril.trust",
"mithril.withAttr", "mithril.withAttr",
"mithril.xhr" "mithril.xhr"
]; ]
var md2htmlTasks = {}
var md2htmlTasks = {};
var makeTasks = function(layout, pages) { var makeTasks = function(layout, pages) {
pages.map(function(name) { pages.map(function(name) {
var src = inputFolder + "/" + name + ".md"; var src = inputFolder + "/" + name + ".md"
var title = (grunt.file.exists(src)) ? grunt.file.read(src).split(/\n/)[0].substring(3) + ' - ' : ''; var title
if (grunt.file.exist(src)) {
title = grunt.file.read(src)
.split(/\n/)[0]
.substring(3) + " - "
} else {
title = ""
}
md2htmlTasks[name] = { md2htmlTasks[name] = {
options: {layout: inputFolder + "/layout/" + layout + ".html", templateData: { "topic": title }}, options: {
layout: inputFolder + "/layout/" + layout + ".html",
templateData: { "topic": title }
},
files: [{src: [src], dest: tempFolder + "/" + name + ".html"}] files: [{src: [src], dest: tempFolder + "/" + name + ".html"}]
} }
}) })
}; }
makeTasks("guide", guide); makeTasks("guide", guide)
makeTasks("api", api); makeTasks("api", api)
var sauceBrowsers =[ var sauceBrowsers = [
{ browserName: 'firefox', version: '19', platform: 'XP' }, { browserName: "firefox", version: "19", platform: "XP" },
{ browserName: "internet explorer", platform: "XP", version: "6"}, { browserName: "internet explorer", platform: "XP", version: "6"},
{ browserName: "safari", platform: "OS X 10.9", version: "7"}, { browserName: "safari", platform: "OS X 10.9", version: "7"},
{ browserName: "iPad", platform: "OS X 10.9", version: "7.1"}, { browserName: "iPad", platform: "OS X 10.9", version: "7.1"},
{ browserName: "opera", platform: "Linux", version: "12"}, { browserName: "opera", platform: "Linux", version: "12"},
{ browserName: "chrome", platform: "XP", version: "26"}, { browserName: "chrome", platform: "XP", version: "26"},
{ browserName: "chrome", platform: "Windows 8", version: "26"} { browserName: "chrome", platform: "Windows 8", version: "26"}
]; ]
var sauceOnTestComplete = function(result, callback) { var sauceOnTestComplete = function(result, callback) {
var request = require('request'); var request = require("request")
var user = process.env.SAUCE_USERNAME; var user = process.env.SAUCE_USERNAME
var pass = process.env.SAUCE_ACCESS_KEY; var pass = process.env.SAUCE_ACCESS_KEY
request.put({ request.put({
url: ['https://saucelabs.com/rest/v1', user, 'jobs', result.job_id].join('/'), url: [
"https://saucelabs.com/rest/v1",
user,
"jobs",
result.job_id
].join("/"),
auth: { user: user, pass: pass }, auth: { user: user, pass: pass },
json: { passed: result.passed } json: { passed: result.passed }
}, function (error, response, body) { }, function (error, response) {
if (error) { if (error) {
callback(error); callback(error)
} else if (response.statusCode !== 200) { } else if (response.statusCode !== 200) {
callback(new Error('Unexpected response status: ' callback(new Error("Unexpected response status: "
+ response.statusCode + "\n ")); + response.statusCode + "\n "))
} else { } else {
callback(null, result.passed); callback(null, result.passed)
} }
}); })
}; }
var sauceBaseOptions = { var sauceBaseOptions = {
username: process.env.SAUCE_USERNAME, username: process.env.SAUCE_USERNAME,
@ -102,74 +115,164 @@ module.exports = function(grunt) {
browsers: sauceBrowsers, browsers: sauceBrowsers,
sauceConfig: { sauceConfig: {
"record-video": false, "record-video": false,
"record-screenshots": false, "record-screenshots": false
}, },
build: process.env.TRAVIS_JOB_ID, build: process.env.TRAVIS_JOB_ID,
onTestComplete: sauceOnTestComplete, onTestComplete: sauceOnTestComplete,
tunnelTimeout: 5, tunnelTimeout: 5
}; }
var sauceCustomOptions = { var sauceCustomOptions = {
testname: "Mithril Custom Tests "+ new Date().toJSON(), testname: "Mithril Custom Tests " + new Date().toJSON(),
urls: ["http://127.0.0.1:8000/tests/index.html"], urls: ["http://127.0.0.1:8000/tests/index.html"]
}; }
_.assign(sauceCustomOptions, sauceBaseOptions); _.assign(sauceCustomOptions, sauceBaseOptions)
var sauceQunitOptions = { var sauceQunitOptions = {
testname: "qUnit Tests "+ new Date().toJSON(), testname: "qUnit Tests " + new Date().toJSON(),
urls: ["http://127.0.0.1:8000/tests/e2e/test.html"], urls: ["http://127.0.0.1:8000/tests/e2e/test.html"]
}; }
_.assign(sauceQunitOptions, sauceBaseOptions); _.assign(sauceQunitOptions, sauceBaseOptions)
var currentVersionArchiveFolder = archiveFolder + "/v" + version; var currentVersionArchiveFolder = archiveFolder + "/v" + version
grunt.initConfig({ grunt.initConfig({
md2html: md2htmlTasks, md2html: md2htmlTasks,
uglify: { uglify: {
options: {banner: "/*\nMithril v" + version + "\nhttp://github.com/lhorie/mithril.js\n(c) Leo Horie\nLicense: MIT\n*/", sourceMap: true}, options: {
banner: [[
"/*",
"Mithril v" + version,
"http://github.com/lhorie/mithril.js",
"(c) Leo Horie",
"License: MIT",
"*/"
].join("\n")],
sourceMap: true
},
mithril: {src: "mithril.js", dest: "mithril.min.js"} mithril: {src: "mithril.js", dest: "mithril.min.js"}
}, },
concat: { concat: {
test: {src: ["mithril.js", "./tests/test.js", "./tests/mock.js", "./tests/mithril-tests.js"], dest: currentVersionArchiveFolder + "/mithril-tests.js"} test: {
src: [
"mithril.js",
"./tests/test.js",
"./tests/mock.js",
"./tests/mithril-tests.js"
],
dest: currentVersionArchiveFolder + "/mithril-tests.js"
}
}, },
zip: { zip: {
distribution: { distribution: {
cwd: currentVersionArchiveFolder + "/", cwd: currentVersionArchiveFolder + "/",
src: [currentVersionArchiveFolder + "/mithril.min.js", currentVersionArchiveFolder + "/mithril.min.js.map", currentVersionArchiveFolder + "/mithril.js"], src: [
currentVersionArchiveFolder + "/mithril.min.js",
currentVersionArchiveFolder + "/mithril.min.js.map",
currentVersionArchiveFolder + "/mithril.js"
],
dest: currentVersionArchiveFolder + "/mithril.min.zip" dest: currentVersionArchiveFolder + "/mithril.min.zip"
} }
}, },
replace: { replace: {
options: {force: true, patterns: [{match: /\.md/g, replacement: ".html"}, {match: /\$version/g, replacement: version}]}, options: {
links: {expand: true, flatten: true, src: [tempFolder + "/**/*.html"], dest: currentVersionArchiveFolder + "/"}, force: true,
index: {src: inputFolder + "/layout/index.html", dest: currentVersionArchiveFolder + "/index.html"}, patterns: [
commonjs: {expand: true, flatten: true, src: [inputFolder + "/layout/*.json"], dest: currentVersionArchiveFolder}, {match: /\.md/g, replacement: ".html"},
cdnjs: {src: "deploy/cdnjs-package.json", dest: "../cdnjs/ajax/libs/mithril/package.json"} {match: /\$version/g, replacement: version}
]
},
links: {
expand: true,
flatten: true,
src: [tempFolder + "/**/*.html"],
dest: currentVersionArchiveFolder + "/"
},
index: {
src: inputFolder + "/layout/index.html",
dest: currentVersionArchiveFolder + "/index.html"
},
commonjs: {
expand: true,
flatten: true,
src: [inputFolder + "/layout/*.json"],
dest: currentVersionArchiveFolder
},
cdnjs: {
src: "deploy/cdnjs-package.json",
dest: "../cdnjs/ajax/libs/mithril/package.json"
}
}, },
copy: { copy: {
style: {src: inputFolder + "/layout/style.css", dest: currentVersionArchiveFolder + "/style.css"}, style: {
pages: {src: inputFolder + "/layout/pages.json", dest: currentVersionArchiveFolder + "/pages.json"}, src: inputFolder + "/layout/style.css",
lib: {expand: true, cwd: inputFolder + "/layout/lib/", src: "./**", dest: currentVersionArchiveFolder + "/lib/"}, dest: currentVersionArchiveFolder + "/style.css"
tools: {expand: true, cwd: inputFolder + "/layout/tools/", src: "./**", dest: currentVersionArchiveFolder + "/tools/"}, },
comparisons: {expand: true, cwd: inputFolder + "/layout/comparisons/", src: "./**", dest: currentVersionArchiveFolder + "/comparisons/"}, pages: {
unminified: {src: "mithril.js", dest: currentVersionArchiveFolder + "/mithril.js"}, src: inputFolder + "/layout/pages.json",
minified: {src: "mithril.min.js", dest: currentVersionArchiveFolder + "/mithril.min.js"}, dest: currentVersionArchiveFolder + "/pages.json"
readme: {src: "README.md", dest: currentVersionArchiveFolder + "/README.md"}, },
map: {src: "mithril.min.js.map", dest: currentVersionArchiveFolder + "/mithril.min.js.map"}, lib: {
typescript: {src: "mithril.d.ts", dest: currentVersionArchiveFolder + "/mithril.d.ts"}, expand: true,
publish: {expand: true, cwd: currentVersionArchiveFolder, src: "./**", dest: outputFolder}, cwd: inputFolder + "/layout/lib/",
archive: {expand: true, cwd: currentVersionArchiveFolder, src: "./**", dest: outputFolder + "/archive/v" + version}, src: "./**",
dest: currentVersionArchiveFolder + "/lib/"
},
tools: {
expand: true,
cwd: inputFolder + "/layout/tools/",
src: "./**",
dest: currentVersionArchiveFolder + "/tools/"
},
comparisons: {
expand: true,
cwd: inputFolder + "/layout/comparisons/",
src: "./**",
dest: currentVersionArchiveFolder + "/comparisons/"
},
unminified: {
src: "mithril.js",
dest: currentVersionArchiveFolder + "/mithril.js"
},
minified: {
src: "mithril.min.js",
dest: currentVersionArchiveFolder + "/mithril.min.js"
},
readme: {
src: "README.md",
dest: currentVersionArchiveFolder + "/README.md"
},
map: {
src: "mithril.min.js.map",
dest: currentVersionArchiveFolder + "/mithril.min.js.map"
},
typescript: {
src: "mithril.d.ts",
dest: currentVersionArchiveFolder + "/mithril.d.ts"
},
publish: {
expand: true,
cwd: currentVersionArchiveFolder,
src: "./**",
dest: outputFolder
},
archive: {
expand: true,
cwd: currentVersionArchiveFolder,
src: "./**",
dest: outputFolder + "/archive/v" + version
}
}, },
execute: { execute: {
tests: {src: [currentVersionArchiveFolder + "/mithril-tests.js"]} tests: {src: [currentVersionArchiveFolder + "/mithril-tests.js"]}
}, },
qunit: { qunit: {
all: ['tests/e2e/**/*.html'] all: ["tests/e2e/**/*.html"]
}, },
"saucelabs-custom": { "saucelabs-custom": {
all:{ all: {
options: sauceCustomOptions options: sauceCustomOptions
} }
}, },
"saucelabs-qunit": { "saucelabs-qunit": {
all:{ all: {
options: sauceQunitOptions options: sauceQunitOptions
} }
}, },
@ -179,7 +282,7 @@ module.exports = function(grunt) {
server: { server: {
options: { options: {
port: 8888, port: 8888,
base: '.' base: "."
} }
} }
}, },
@ -191,34 +294,45 @@ module.exports = function(grunt) {
default: { default: {
files: [{ files: [{
expand: true, expand: true,
src: ['mithril.js'], src: ["mithril.js"],
cwd: '.', cwd: ".",
dest: '.' dest: "."
}] }]
} }
},
eslint: {
target: [
"**/*.js",
"!node_modules/**",
"!**/*.min.js",
"!docs/layout/lib/**/*.js"
]
} }
}); })
grunt.loadNpmTasks("grunt-contrib-clean"); grunt.loadNpmTasks("grunt-contrib-clean")
grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks("grunt-contrib-concat")
grunt.loadNpmTasks("grunt-contrib-copy"); grunt.loadNpmTasks("grunt-contrib-copy")
grunt.loadNpmTasks("grunt-contrib-uglify"); grunt.loadNpmTasks("grunt-contrib-uglify")
grunt.loadNpmTasks('grunt-execute'); grunt.loadNpmTasks("grunt-execute")
grunt.loadNpmTasks("grunt-md2html"); grunt.loadNpmTasks("grunt-md2html")
grunt.loadNpmTasks("grunt-replace"); grunt.loadNpmTasks("grunt-replace")
grunt.loadNpmTasks('grunt-zip'); grunt.loadNpmTasks("grunt-zip")
grunt.loadNpmTasks('grunt-contrib-qunit'); grunt.loadNpmTasks("grunt-contrib-qunit")
grunt.loadNpmTasks('grunt-contrib-connect'); grunt.loadNpmTasks("grunt-contrib-connect")
grunt.loadNpmTasks('grunt-saucelabs'); grunt.loadNpmTasks("grunt-saucelabs")
grunt.loadNpmTasks('grunt-jsfmt'); grunt.loadNpmTasks("grunt-jsfmt")
grunt.loadNpmTasks("grunt-eslint")
grunt.registerTask("build", ["test", "uglify", "zip", "md2html", "replace", "copy", "clean"]); grunt.registerTask("build", [
grunt.registerTask("testall", ["test", "teste2e"]); "test", "uglify", "zip", "md2html", "replace", "copy", "clean"])
grunt.registerTask("test", ["concat", "execute"]); grunt.registerTask("testall", ["test", "teste2e"])
grunt.registerTask('teste2e', ['connect', 'qunit']); grunt.registerTask("test", ["eslint", "concat", "execute"])
grunt.registerTask("default", ["build"]); grunt.registerTask("teste2e", ["connect", "qunit"])
grunt.registerTask("default", ["build"])
grunt.registerTask("sauce-qunit", ["connect", "saucelabs-qunit"]); grunt.registerTask("sauce-qunit", ["connect", "saucelabs-qunit"])
grunt.registerTask("sauce-custom", ["connect", "saucelabs-custom"]); grunt.registerTask("sauce-custom", ["connect", "saucelabs-custom"])
grunt.registerTask("sauce-all", ["connect", "saucelabs-qunit", "saucelabs-custom"]); grunt.registerTask("sauce-all", [
}; "connect", "saucelabs-qunit", "saucelabs-custom"])
}

View file

@ -1,3 +1,5 @@
**Note: This is a WIP partial rewrite of Mithril.**
[![JS.ORG](https://img.shields.io/badge/js.org-mithril-ffb400.svg?style=flat-square)](http://js.org) [![JS.ORG](https://img.shields.io/badge/js.org-mithril-ffb400.svg?style=flat-square)](http://js.org)
[![Join the chat at https://gitter.im/lhorie/mithril.js](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/lhorie/mithril.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Join the chat at https://gitter.im/lhorie/mithril.js](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/lhorie/mithril.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Build Status](https://travis-ci.org/lhorie/mithril.js.svg?branch=master)](https://travis-ci.org/lhorie/mithril.js) [![Build Status](https://travis-ci.org/lhorie/mithril.js.svg?branch=master)](https://travis-ci.org/lhorie/mithril.js)

View file

@ -1,90 +1,128 @@
var templateConverter = {}; /* globals m */
var templateConverter = {}
templateConverter.DOMFragment = function(markup) { templateConverter.DOMFragment = function(markup) {
if (markup.indexOf("<!doctype") > -1) return [new DOMParser().parseFromString(markup, "text/html").childNodes[1]] "use strict"
var container = document.createElement("div"); if (markup.indexOf("<!doctype") > -1) {
container.insertAdjacentHTML("beforeend", markup); return [
return container.childNodes; new DOMParser().parseFromString(markup, "text/html").childNodes[1]
]
}
var container = document.createElement("div")
container.insertAdjacentHTML("beforeend", markup)
return container.childNodes
} }
templateConverter.VirtualFragment = function recurse(domFragment) { templateConverter.VirtualFragment = function recurse(domFragment) {
var virtualFragment = []; "use strict"
for (var i = 0, el; el = domFragment[i]; i++) { var virtualFragment = []
if (el.nodeType == 3) { for (var i = 0; i < domFragment.length; i++) {
virtualFragment.push(el.nodeValue); var el = domFragment[i]
} if (el.nodeType === 3) {
else if (el.nodeType == 1) { virtualFragment.push(el.nodeValue)
var attrs = {}; } else if (el.nodeType === 1) {
for (var j = 0, attr; attr = el.attributes[j]; j++) { var attrs = {}
attrs[attr.name] = attr.value; for (var j = 0; el.attributes.length; j++) {
var attr = el.attributes[j]
attrs[attr.name] = attr.value
} }
virtualFragment.push({tag: el.nodeName.toLowerCase(), attrs: attrs, children: recurse(el.childNodes)}); virtualFragment.push({
tag: el.nodeName.toLowerCase(),
attrs: attrs,
children: recurse(el.childNodes)
})
} }
} }
return virtualFragment; return virtualFragment
} }
templateConverter.Template = function recurse() { templateConverter.Template = function recurse() {
if (Object.prototype.toString.call(arguments[0]) == "[object String]") { "use strict"
return new recurse(new templateConverter.VirtualFragment(new templateConverter.DOMFragment(arguments[0]))); if (Object.prototype.toString.call(arguments[0]) === "[object String]") {
return new recurse(new templateConverter.VirtualFragment(
new templateConverter.DOMFragment(arguments[0])))
} }
var virtualFragment = arguments[0], level = arguments[1] var virtualFragment = arguments[0]
if (!level) level = 1; var level = arguments[1]
if (!level) level = 1
var tab = "\n" + new Array(level + 1).join("\t");
var virtuals = []; var tab = "\n" + new Array(level + 1).join("\t")
for (var i = 0, el; el = virtualFragment[i]; i++) { var virtuals = []
if (typeof el == "string") { for (var i = 0; i < virtualFragment.length; i++) {
if (el.match(/\t| {2,}/g) && el.trim().length == 0) virtuals.indented = true; var el = virtualFragment[i]
else virtuals.push('"' + el.replace(/"/g, '\\"').replace(/\r/g, "\\r").replace(/\n/g, "\\n") + '"'); if (typeof el === "string") {
} if (el.match(/\t| {2,}/g) && el.trim().length === 0) {
else { virtuals.indented = true
var virtual = ""; } else {
if (el.tag != "div") virtual += el.tag; virtuals.push('"' + el
if (el.attrs["class"]) { .replace(/"/g, '\\"')
virtual += "." + el.attrs["class"].replace(/\t+/g, " ").split(" ").join("."); .replace(/\r/g, "\\r")
delete el.attrs["class"]; .replace(/\n/g, "\\n") + '"')
}
} else {
var virtual = ""
if (el.tag !== "div") virtual += el.tag
if (el.attrs.class) {
virtual += "." + el.attrs.class
.replace(/\t+/g, " ")
.split(" ")
.join(".")
delete el.attrs.class
} }
var attrNames = Object.keys(el.attrs).sort() var attrNames = Object.keys(el.attrs).sort()
for (var j = 0, attrName; attrName = attrNames[j]; j++) { for (var j = 0; j < attrNames.length; j++) {
if (attrName != "style") virtual += "[" + attrName + "='" + el.attrs[attrName].replace(/'/g, "\\'") + "']"; var attrName = attrNames[j]
if (attrName !== "style") {
virtual += "[" + attrName + "='" +
el.attrs[attrName].replace(/'/g, "\\'") + "']"
}
} }
if (virtual == "") virtual = "div" if (virtual === "") virtual = "div"
virtual = '"' + virtual + '"'; virtual = '"' + virtual + '"'
var style = ""
if (el.attrs.style) { if (el.attrs.style) {
virtual += ", {style: " + ("{\"" + el.attrs.style.replace(/:/g, "\": \"").replace(/;/g, "\", \"") + "}").replace(/, "}|"}/, "}") + "}" virtual += ", {style: " + ("{\"" + el.attrs.style
.replace(/:/g, "\": \"")
.replace(/;/g, "\", \"") + "}")
.replace(/, "}|"}/, "}") + "}"
} }
if (el.children.length > 0) { if (el.children.length > 0) {
virtual += ", " + recurse(el.children, level + 1); virtual += ", " + recurse(el.children, level + 1)
} }
virtual = "m(" + virtual + ")"; virtual = "m(" + virtual + ")"
virtuals.push(virtual); virtuals.push(virtual)
} }
} }
if (!virtuals.indented) tab = ""; if (!virtuals.indented) tab = ""
var isInline = virtuals.length == 1 && virtuals[0].charAt(0) == '"'; var isInline = virtuals.length === 1 && virtuals[0].charAt(0) === '"'
var template = isInline ? virtuals.join(", ") : "[" + tab + virtuals.join("," + tab) + tab.slice(0, -1) + "]"; var template = isInline ?
return new String(template); virtuals.join(", ") :
"[" + tab + virtuals.join("," + tab) + tab.slice(0, -1) + "]"
return new String(template) // eslint-disable-line no-new-wrappers
} }
templateConverter.controller = function() { templateConverter.controller = function() {
this.source = m.prop(""); "use strict"
this.output = m.prop(""); this.source = m.prop("")
this.output = m.prop("")
this.convert = function() { this.convert = function() {
return this.output(new templateConverter.Template(this.source())); return this.output(new templateConverter.Template(this.source()))
}; }
}
};
templateConverter.view = function(ctrl) { templateConverter.view = function(ctrl) {
"use strict"
return m("div", [ return m("div", [
m("textarea", {autofocus: true, style: {width:"100%", height: "40%"}, onchange: m.withAttr("value", ctrl.source)}, ctrl.source()), m("textarea", {
autofocus: true,
style: {width: "100%", height: "40%"},
onchange: m.withAttr("value", ctrl.source)
}, ctrl.source()),
m("button", {onclick: ctrl.convert.bind(ctrl)}, "Convert"), m("button", {onclick: ctrl.convert.bind(ctrl)}, "Convert"),
m("textarea", {style: {width:"100%", height: "40%"}}, ctrl.output()) m("textarea", {style: {width: "100%", height: "40%"}}, ctrl.output())
]); ])
}; }

2626
mithril.js

File diff suppressed because it is too large Load diff

View file

@ -1,46 +1,55 @@
{ {
"name": "mithril", "name": "mithril",
"description": "Mithril.js beta build - use this to help us test the releases before they are released", "description": "Mithril.js beta build - use this to help us test the releases before they are released",
"version": "0.1.34-beta.0", "version": "0.1.34-beta.0",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git@github.com:lhorie/mithril.js.git" "url": "git@github.com:lhorie/mithril.js.git"
}, },
"scripts": { "scripts": {
"test": "grunt test" "test": "grunt test"
}, },
"main": "mithril.js", "main": "mithril.js",
"devDependencies": { "devDependencies": {
"grunt": "*", "colors": "~0.6.2",
"grunt-cli": "*", "grunt": "*",
"grunt-contrib-copy": "*", "grunt-cli": "*",
"grunt-contrib-uglify": "*", "grunt-contrib-clean": "*",
"grunt-contrib-clean": "*", "grunt-contrib-concat": "*",
"grunt-contrib-concat": "*", "grunt-contrib-connect": "~0.7.1",
"grunt-execute": "*", "grunt-contrib-copy": "*",
"grunt-md2html": "*", "grunt-contrib-jshint": "~0.10.0",
"grunt-replace": "*", "grunt-contrib-qunit": "*",
"grunt-contrib-qunit": "*", "grunt-contrib-uglify": "*",
"grunt-zip": "*", "grunt-contrib-watch": "~0.6.1",
"grunt-jsfmt": "git://github.com/ysimonson/grunt-jsfmt", "grunt-eslint": "^16.0.0",
"grunt-execute": "*",
"grunt-contrib-connect": "~0.7.1", "grunt-jscs": "^1.1.0",
"grunt-contrib-jshint": "~0.10.0", "grunt-jsfmt": "git://github.com/ysimonson/grunt-jsfmt",
"grunt-contrib-watch": "~0.6.1", "grunt-md2html": "*",
"grunt-jscs": "^1.1.0", "grunt-replace": "*",
"grunt-sauce-tunnel": "^0.2.1", "grunt-sauce-tunnel": "^0.2.1",
"load-grunt-config": "^0.9.2", "grunt-saucelabs": "*",
"merge": "^1.1.3", "grunt-zip": "*",
"publish": "~0.3.2", "load-grunt-config": "^0.9.2",
"grunt-saucelabs": "*", "lodash": "~2.4.1",
"request": "~2.35.0", "merge": "^1.1.3",
"q": "~1.0.0", "publish": "~0.3.2",
"saucelabs": "~0.1.1", "q": "~1.0.0",
"sauce-tunnel": "~2.0.6", "request": "~2.35.0",
"colors": "~0.6.2", "sauce-tunnel": "~2.0.6",
"lodash": "~2.4.1" "saucelabs": "~0.1.1"
}, },
"main": "mithril.js", "licenses": [
"licenses": [{"type": "MIT", "url": "http://opensource.org/licenses/MIT"}], {
"files": ["mithril.min.js", "mithril.min.js.map", "mithril.js", "README.*"] "type": "MIT",
"url": "http://opensource.org/licenses/MIT"
}
],
"files": [
"mithril.min.js",
"mithril.min.js.map",
"mithril.js",
"README.*"
]
} }

23
tests/e2e/.eslintrc Normal file
View file

@ -0,0 +1,23 @@
{
"extend": "../../.eslintrc",
"globals": {
"asyncTest": false,
"deepEqual": false,
"equal": false,
"expect": false,
"module": false,
"notDeepEqual": false,
"notEqual": false,
"notPropEqual": false,
"notStrictEqual": false,
"ok": false,
"propEqual": false,
"QUnit": false,
"raises": false,
"start": false,
"stop": false,
"strictEqual": false,
"test": false,
"throws": false
}
}

View file

@ -1,8 +1,13 @@
//saucelabs reporting; see https://github.com/axemclion/grunt-saucelabs#test-result-details-with-qunit /* eslint-disable camelcase */
/* global m, Syn */
// saucelabs reporting; see
// https://github.com/axemclion/grunt-saucelabs#test-result-details-with-qunit
var log = [] var log = []
var testName
QUnit.done(function (test_results) { QUnit.done(function (test_results) {
"use strict"
var tests = [] var tests = []
for (var i = 0, len = log.length; i < len; i++) { for (var i = 0, len = log.length; i < len; i++) {
var details = log[i] var details = log[i]
@ -19,6 +24,7 @@ QUnit.done(function (test_results) {
window.global_test_results = test_results window.global_test_results = test_results
}) })
QUnit.testStart(function (testDetails) { QUnit.testStart(function (testDetails) {
"use strict"
QUnit.log(function (details) { QUnit.log(function (details) {
if (!details.result) { if (!details.result) {
details.name = testDetails.name details.name = testDetails.name
@ -27,9 +33,11 @@ QUnit.testStart(function (testDetails) {
}) })
}) })
//qunit doesn't support Function.prototype.bind... // qunit doesn't support Function.prototype.bind...
if (!Function.prototype.bind) { if (!Function.prototype.bind) {
/* eslint-disable */
Function.prototype.bind = function (oThis) { Function.prototype.bind = function (oThis) {
"use strict"
if (typeof this !== "function") { if (typeof this !== "function") {
// closest thing possible to the ECMAScript 5 // closest thing possible to the ECMAScript 5
// internal IsCallable function // internal IsCallable function
@ -51,165 +59,181 @@ if (!Function.prototype.bind) {
return fBound return fBound
} }
/* eslint-enable */
} }
//tests //tests
var dummyEl = document.getElementById('dummy') var dummyEl = document.getElementById("dummy")
test('Mithril accessible as window.m', function() { test("Mithril accessible as window.m", function() {
"use strict"
expect(1) expect(1)
ok(window.m) ok(window.m)
}) })
test('m.trust w/ html entities', function() { test("m.trust w/ html entities", function() {
"use strict"
expect(1) expect(1)
var view1 = m('div', "a", m.trust("&amp;"), "b") var view1 = m("div", "a", m.trust("&amp;"), "b")
m.render(dummyEl, view1) m.render(dummyEl, view1)
equal(dummyEl.innerHTML, '<div>a&amp;b</div>', 'view1 rendered correctly') equal(dummyEl.innerHTML, "<div>a&amp;b</div>", "view1 rendered correctly")
}) })
test('m.trust w/ html entities 2', function() { test("m.trust w/ html entities 2", function() {
"use strict"
expect(1) expect(1)
var view1 = m('div', "a", m.trust("&amp;"), "b", m.trust("&amp;"), "c") var view1 = m("div", "a", m.trust("&amp;"), "b", m.trust("&amp;"), "c")
m.render(dummyEl, view1) m.render(dummyEl, view1)
equal(dummyEl.innerHTML, '<div>a&amp;b&amp;c</div>', 'view1 rendered correctly') equal(dummyEl.innerHTML, "<div>a&amp;b&amp;c</div>",
"view1 rendered correctly")
}) })
test('array item removal', function() { test("array item removal", function() {
"use strict"
expect(2) expect(2)
var view1 = m('div', {}, [ var view1 = m("div", {}, [
m('div', {}, '0'), m("div", {}, "0"),
m('div', {}, '1'), m("div", {}, "1"),
m('div', {}, '2') m("div", {}, "2")
]) ])
var view2= m('div', {}, [ var view2 = m("div", {}, [
m('div', {}, '0') m("div", {}, "0")
]) ])
m.render(dummyEl, view1) m.render(dummyEl, view1)
equal(dummyEl.innerHTML, '<div><div>0</div><div>1</div><div>2</div></div>', 'view1 rendered correctly') equal(dummyEl.innerHTML, "<div><div>0</div><div>1</div><div>2</div></div>",
"view1 rendered correctly")
m.render(dummyEl, view2) m.render(dummyEl, view2)
equal(dummyEl.innerHTML, '<div><div>0</div></div>', 'view2 should be rendered correctly') equal(dummyEl.innerHTML, "<div><div>0</div></div>",
"view2 should be rendered correctly")
}) })
test('issue99 regression', function() { test("issue99 regression", function() {
"use strict"
// see https://github.com/lhorie/mithril.js/issues/99 // see https://github.com/lhorie/mithril.js/issues/99
expect(2) expect(2)
var view1 = m('div', {}, [ var view1 = m("div", {}, [
m('div', {}, '0'), m("div", {}, "0"),
m('div', {}, '1'), m("div", {}, "1"),
m('div', {}, '2') m("div", {}, "2")
]) ])
var view2= m('div', {}, [ var view2 = m("div", {}, [
m('span', {}, '0') m("span", {}, "0")
]) ])
m.render(dummyEl, view1) m.render(dummyEl, view1)
equal(dummyEl.innerHTML, '<div><div>0</div><div>1</div><div>2</div></div>', 'view1 rendered correctly') equal(dummyEl.innerHTML, "<div><div>0</div><div>1</div><div>2</div></div>",
"view1 rendered correctly")
m.render(dummyEl, view2) m.render(dummyEl, view2)
equal(dummyEl.innerHTML, '<div><span>0</span></div>', 'view2 should be rendered correctly') equal(dummyEl.innerHTML, "<div><span>0</span></div>",
"view2 should be rendered correctly")
}) })
test('config handler context', function() { test("config handler context", function() {
"use strict"
expect(3) expect(3)
var view = m('div', {config: function(evt, isInitialized, context) { var view = m("div", {config: function(evt, isInitialized, context) {
equal(context instanceof Object, true) equal(context instanceof Object, true)
context.data = 1 context.data = 1
}}) }})
m.render(dummyEl, view) m.render(dummyEl, view)
var view = m('div', {config: function(evt, isInitialized, context) { view = m("div", {config: function(evt, isInitialized, context) {
equal(context instanceof Object, true) equal(context instanceof Object, true)
equal(context.data, 1) equal(context.data, 1)
}}) }})
m.render(dummyEl, view) m.render(dummyEl, view)
}) })
test('node identity remove firstChild', function() { test("node identity remove firstChild", function() {
"use strict"
expect(2) expect(2)
var view1 = m('div', {}, [ var view1 = m("div", {}, [
m('div', {key:1}, 'E1'), m("div", {key: 1}, "E1"),
m('div', {key:2}, 'E2') m("div", {key: 2}, "E2")
]) ])
m.render(dummyEl, view1) m.render(dummyEl, view1)
var node2 = dummyEl.firstChild.lastChild var node2 = dummyEl.firstChild.lastChild
equal(node2.innerHTML, 'E2') equal(node2.innerHTML, "E2")
var view2 = m('div', {}, [ var view2 = m("div", {}, [
m('div', {key:2}, 'E2') m("div", {key: 2}, "E2")
]) ])
m.render(dummyEl, view2) m.render(dummyEl, view2)
equal(dummyEl.firstChild.firstChild, node2) equal(dummyEl.firstChild.firstChild, node2)
}) })
test('node identity change order', function() { test("node identity change order", function() {
"use strict"
expect(2) expect(2)
var view1 = m('div', {}, [ var view1 = m("div", {}, [
m('div', {key:1}, 'E1'), m("div", {key: 1}, "E1"),
m('div', {key:2}, 'E2'), m("div", {key: 2}, "E2"),
m('div', {key:3}, 'E3') m("div", {key: 3}, "E3")
]) ])
m.render(dummyEl, view1) m.render(dummyEl, view1)
var e2 = dummyEl.firstChild.firstChild.nextSibling var e2 = dummyEl.firstChild.firstChild.nextSibling
equal(e2.innerHTML, 'E2') equal(e2.innerHTML, "E2")
var view2 = m('div', {}, [ var view2 = m("div", {}, [
m('div', {key:2}, 'E2'), m("div", {key: 2}, "E2"),
m('div', {key:1}, 'E1'), m("div", {key: 1}, "E1"),
m('div', {key:3}, 'E3') m("div", {key: 3}, "E3")
]) ])
m.render(dummyEl, view2) m.render(dummyEl, view2)
equal(dummyEl.firstChild.firstChild, e2) equal(dummyEl.firstChild.firstChild, e2)
}) })
test('node identity remove in the middle', function() { test("node identity remove in the middle", function() {
"use strict"
expect(2) expect(2)
var view1 = m('div', {}, [ var view1 = m("div", {}, [
m('div', {key:1}, 'E1'), m("div", {key: 1}, "E1"),
m('div', {key:2}, 'E2'), m("div", {key: 2}, "E2"),
m('div', {key:3}, 'E3') m("div", {key: 3}, "E3")
]) ])
m.render(dummyEl, view1) m.render(dummyEl, view1)
var e3 = dummyEl.firstChild.lastChild var e3 = dummyEl.firstChild.lastChild
equal(e3.innerHTML, 'E3') equal(e3.innerHTML, "E3")
var view2 = m('div', {}, [ var view2 = m("div", {}, [
m('div', {key:1}, 'E1'), m("div", {key: 1}, "E1"),
m('div', {key:3}, 'E3') m("div", {key: 3}, "E3")
]) ])
m.render(dummyEl, view2) m.render(dummyEl, view2)
equal(dummyEl.firstChild.firstChild.nextSibling, e3) equal(dummyEl.firstChild.firstChild.nextSibling, e3)
}) })
test('node identity remove last', function() { test("node identity remove last", function() {
"use strict"
expect(4) expect(4)
var view1 = m('div', {}, [ var view1 = m("div", {}, [
m('div', {key:1}, 'E1'), m("div", {key: 1}, "E1"),
m('div', {key:2}, 'E2'), m("div", {key: 2}, "E2"),
m('div', {key:3}, 'E3') m("div", {key: 3}, "E3")
]) ])
m.render(dummyEl, view1) m.render(dummyEl, view1)
var e1 = dummyEl.firstChild.firstChild var e1 = dummyEl.firstChild.firstChild
equal(e1.innerHTML, 'E1') equal(e1.innerHTML, "E1")
var e2 = dummyEl.firstChild.firstChild.nextSibling var e2 = dummyEl.firstChild.firstChild.nextSibling
equal(e2.innerHTML, 'E2') equal(e2.innerHTML, "E2")
var view2 = m('div', {}, [ var view2 = m("div", {}, [
m('div', {key:1}, 'E1'), m("div", {key: 1}, "E1"),
m('div', {key:2}, 'E2') m("div", {key: 2}, "E2")
]) ])
m.render(dummyEl, view2) m.render(dummyEl, view2)
@ -217,168 +241,176 @@ test('node identity remove last', function() {
equal(dummyEl.firstChild.firstChild.nextSibling, e2) equal(dummyEl.firstChild.firstChild.nextSibling, e2)
}) })
test('node identity shuffle and remove', function() { test("node identity shuffle and remove", function() {
"use strict"
expect(8) expect(8)
var view1 = m('div', {}, [ var view1 = m("div", {}, [
m('div', {key:1}, 'E1'), m("div", {key: 1}, "E1"),
m('div', {key:2}, 'E2'), m("div", {key: 2}, "E2"),
m('div', {key:3}, 'E3'), m("div", {key: 3}, "E3"),
m('div', {key:4}, 'E4'), m("div", {key: 4}, "E4"),
m('div', {key:5}, 'E5') m("div", {key: 5}, "E5")
]) ])
m.render(dummyEl, view1) m.render(dummyEl, view1)
var e1 = dummyEl.firstChild.firstChild var e1 = dummyEl.firstChild.firstChild
equal(e1.innerHTML, 'E1') equal(e1.innerHTML, "E1")
var e2 = e1.nextSibling var e2 = e1.nextSibling
equal(e2.innerHTML, 'E2') equal(e2.innerHTML, "E2")
var e3 = e2.nextSibling var e3 = e2.nextSibling
equal(e3.innerHTML, 'E3') equal(e3.innerHTML, "E3")
var e4 = e3.nextSibling var e4 = e3.nextSibling
equal(e4.innerHTML, 'E4') equal(e4.innerHTML, "E4")
var e5 = e4.nextSibling var e5 = e4.nextSibling
equal(e5.innerHTML, 'E5') equal(e5.innerHTML, "E5")
var view2 = m('div', {}, [ var view2 = m("div", {}, [
m('div', {key:4}, 'E4'), m("div", {key: 4}, "E4"),
m('div', {key:10}, 'E10'), m("div", {key: 10}, "E10"),
m('div', {key:1}, 'E1'), m("div", {key: 1}, "E1"),
m('div', {key:2}, 'E2') m("div", {key: 2}, "E2")
]) ])
m.render(dummyEl, view2) m.render(dummyEl, view2)
equal(dummyEl.firstChild.firstChild, e4, 'e4 is first element') equal(dummyEl.firstChild.firstChild, e4, "e4 is first element")
equal(dummyEl.firstChild.firstChild.nextSibling.nextSibling, e1, 'e1 is third element') equal(dummyEl.firstChild.firstChild.nextSibling.nextSibling, e1,
equal(dummyEl.firstChild.firstChild.nextSibling.nextSibling.nextSibling, e2, 'e2 is fourth element') "e1 is third element")
equal(dummyEl.firstChild.firstChild.nextSibling.nextSibling.nextSibling, e2,
"e2 is fourth element")
}) })
asyncTest('issue214 regression', function() { asyncTest("issue214 regression", function() {
"use strict"
// see https://github.com/lhorie/mithril.js/issues/214 // see https://github.com/lhorie/mithril.js/issues/214
expect(2) expect(2)
function controller() { function controller() {
this.inputValue = m.prop('') this.inputValue = m.prop("")
} }
function view(ctrl) { function view(ctrl) {
return m('input#testinput', { return m("input#testinput", {
value: ctrl.inputValue(), value: ctrl.inputValue(),
onkeyup: m.withAttr('value', ctrl.inputValue) onkeyup: m.withAttr("value", ctrl.inputValue)
}) })
} }
var ctrl = m.module(dummyEl, { controller: controller, view: view }) var ctrl = m.module(dummyEl, { controller: controller, view: view })
Syn.click({}, 'testinput') Syn.click({}, "testinput")
.type('0').delay(10) .type("0").delay(10)
.type('1').delay(10) .type("1").delay(10)
.type('2').delay(10) .type("2").delay(10)
.type('3').delay(10) .type("3").delay(10)
.type('4').delay(10) .type("4").delay(10)
.type('5').delay(10) .type("5").delay(10)
.type('6').delay(10) .type("6").delay(10)
.type('7').delay(10) .type("7").delay(10)
.type('8').delay(10) .type("8").delay(10)
.type('9').delay(10) .type("9").delay(10)
.type('a').delay(10) .type("a").delay(10)
.type('b').delay(10) .type("b").delay(10)
.type('c').delay(10) .type("c").delay(10)
.type('d').delay(10) .type("d").delay(10)
.type('e').delay(10) .type("e").delay(10)
.type('f').delay(10) .type("f").delay(10)
.type('0').delay(10) .type("0").delay(10)
.type('1').delay(10) .type("1").delay(10)
.type('2').delay(10) .type("2").delay(10)
.type('3').delay(10) .type("3").delay(10)
.type('4').delay(10) .type("4").delay(10)
.type('5').delay(10) .type("5").delay(10)
.type('6').delay(10) .type("6").delay(10)
.type('7').delay(10) .type("7").delay(10)
.type('8').delay(10) .type("8").delay(10)
.type('9').delay(10) .type("9").delay(10)
.type('a').delay(10) .type("a").delay(10)
.type('b').delay(10) .type("b").delay(10)
.type('c').delay(10) .type("c").delay(10)
.type('d').delay(10) .type("d").delay(10)
.type('e').delay(10) .type("e").delay(10)
.type('f').delay(10) .type("f").delay(10)
.type('0').delay(10) .type("0").delay(10)
.type('1').delay(10) .type("1").delay(10)
.type('2').delay(10) .type("2").delay(10)
.type('3').delay(10) .type("3").delay(10)
.type('4').delay(10) .type("4").delay(10)
.type('5').delay(10) .type("5").delay(10)
.type('6').delay(10) .type("6").delay(10)
.type('7').delay(10) .type("7").delay(10)
.type('8').delay(10) .type("8").delay(10)
.type('9').delay(10) .type("9").delay(10)
.type('a').delay(10) .type("a").delay(10)
.type('b').delay(10) .type("b").delay(10)
.type('c').delay(10) .type("c").delay(10)
.type('d').delay(10) .type("d").delay(10)
.type('e').delay(10) .type("e").delay(10)
.type('f').delay(10) .type("f").delay(10)
.type('0').delay(10) .type("0").delay(10)
.type('1').delay(10) .type("1").delay(10)
.type('2').delay(10) .type("2").delay(10)
.type('3').delay(10) .type("3").delay(10)
.type('4').delay(10) .type("4").delay(10)
.type('5').delay(10) .type("5").delay(10)
.type('6').delay(10) .type("6").delay(10)
.type('7').delay(10) .type("7").delay(10)
.type('8').delay(10) .type("8").delay(10)
.type('9').delay(10) .type("9").delay(10)
.type('a').delay(10) .type("a").delay(10)
.type('b').delay(10) .type("b").delay(10)
.type('c').delay(10) .type("c").delay(10)
.type('d').delay(10) .type("d").delay(10)
.type('e').delay(10) .type("e").delay(10)
.type('f', function() { .type("f", function() {
equal(ctrl.inputValue(), '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef') equal(ctrl.inputValue(),
equal(document.getElementById('testinput').value, '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef') "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef")
equal(document.getElementById("testinput").value,
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef")
start() start()
}) })
}) })
asyncTest('issue288 regression', function() { asyncTest("issue288 regression", function() {
"use strict"
// see https://github.com/lhorie/mithril.js/issues/288 // see https://github.com/lhorie/mithril.js/issues/288
expect(2) expect(2)
function controller() { function controller() {
this.inputValue = m.prop('') this.inputValue = m.prop("")
this.submit = function() { this.submit = function() {
if (this.inputValue()) { if (this.inputValue()) {
this.inputValue('') this.inputValue("")
} }
}.bind(this); }.bind(this)
} }
function view(ctrl) { function view(ctrl) {
return m('form', { onsubmit: ctrl.submit }, [ return m("form", { onsubmit: ctrl.submit }, [
m('input#testinput', { m("input#testinput", {
onkeyup: m.withAttr('value', ctrl.inputValue), onkeyup: m.withAttr("value", ctrl.inputValue),
value: ctrl.inputValue() value: ctrl.inputValue()
}), }),
m('button[type=submit]') m("button[type=submit]")
]) ])
} }
var ctrl = m.module(dummyEl, { controller: controller, view: view }) var ctrl = m.module(dummyEl, { controller: controller, view: view })
Syn.click({}, 'testinput') Syn.click({}, "testinput")
.type('a').delay(10) .type("a").delay(10)
.type('b').delay(10) .type("b").delay(10)
.type('c').delay(10) .type("c").delay(10)
.type('d').delay(10) .type("d").delay(10)
.type('[enter]', function() { .type("[enter]", function() {
equal(ctrl.inputValue(), '') equal(ctrl.inputValue(), "")
equal(document.getElementById('testinput').value, '') equal(document.getElementById("testinput").value, "")
start() start()
}) })
}) })
test('issue278 regression', function() { test("issue278 regression", function() {
"use strict"
// see https://github.com/lhorie/mithril.js/issues/278 // see https://github.com/lhorie/mithril.js/issues/278
expect(1) expect(1)
@ -389,22 +421,24 @@ test('issue278 regression', function() {
}, },
view: function(ctrl) { view: function(ctrl) {
return m('select#testselect', { return m("select#testselect", {
size: ctrl.values.length, size: ctrl.values.length,
multiple: 'multiple' multiple: "multiple"
}, [ }, [
ctrl.values.map(function(v){ ctrl.values.map(function(v){
var opts = {value: v} var opts = {value: v}
if (ctrl.value().indexOf(v) !== -1) opts.selected = 'selected' if (ctrl.value().indexOf(v) !== -1) {
return m('option', opts, v) opts.selected = "selected"
}
return m("option", opts, v)
}) })
]) ])
} }
} }
m.render(dummyEl, test.view(new test.controller)) m.render(dummyEl, test.view(new test.controller()))
var select = document.getElementById('testselect') var select = document.getElementById("testselect")
for (var i = 0, selected = 0; i < select.options.length; i++) { for (var i = 0, selected = 0; i < select.options.length; i++) {
if (select.options[i].selected) selected++ if (select.options[i].selected) selected++
@ -413,25 +447,30 @@ test('issue278 regression', function() {
equal(selected, 2) equal(selected, 2)
}) })
test("mixing trusted content", function() { test("mixing trusted content", function() {
"use strict"
m.render(dummyEl, [m.trust("<p>1</p><p>2</p>"), m("i", "foo")]) m.render(dummyEl, [m.trust("<p>1</p><p>2</p>"), m("i", "foo")])
equal(dummyEl.childNodes[2].nodeName, "I") equal(dummyEl.childNodes[2].nodeName, "I")
}) })
test("mixing trusted content w/ text nodes", function() { test("mixing trusted content w/ text nodes", function() {
"use strict"
m.render(dummyEl, [m.trust("<p>1</p>123<p>2</p>"), m("i", "foo")]) m.render(dummyEl, [m.trust("<p>1</p>123<p>2</p>"), m("i", "foo")])
equal(dummyEl.childNodes[3].nodeName, "I") equal(dummyEl.childNodes[3].nodeName, "I")
}) })
test("mixing trusted content w/ td", function() { test("mixing trusted content w/ td", function() {
"use strict"
m.render(dummyEl, [m.trust("<td>1</td><td>2</td>"), m("i", "foo")]) m.render(dummyEl, [m.trust("<td>1</td><td>2</td>"), m("i", "foo")])
equal(dummyEl.childNodes[1].nodeName, "I") equal(dummyEl.childNodes[1].nodeName, "I")
}) })
test("0 should not be treated as empty string", function() { test("0 should not be treated as empty string", function() {
"use strict"
m.render(dummyEl, m("input", {value: ""})) m.render(dummyEl, m("input", {value: ""}))
m.render(dummyEl, m("input", {value: 0})) m.render(dummyEl, m("input", {value: 0}))
equal(dummyEl.childNodes[0].value, "0") equal(dummyEl.childNodes[0].value, "0")
}) })
test("empty value in <option> should show as attribute", function() { test("empty value in <option> should show as attribute", function() {
"use strict"
m.render(dummyEl, m("select", m("option", {value: ""}, "aaa"))) m.render(dummyEl, m("select", m("option", {value: ""}, "aaa")))
equal(dummyEl.childNodes[0].innerHTML, '<option value="">aaa</option>') equal(dummyEl.childNodes[0].innerHTML, '<option value="">aaa</option>')
}) })

File diff suppressed because it is too large Load diff

View file

@ -1,3 +1,4 @@
/* eslint-disable no-extend-native, strict */
if (!Array.prototype.indexOf) { if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function(item) { Array.prototype.indexOf = function(item) {
for (var i = 0; i < this.length; i++) { for (var i = 0; i < this.length; i++) {
@ -31,9 +32,11 @@ if (!Object.keys) {
return keys return keys
} }
} }
/* eslint-enable no-extend-native, strict */
var mock = {} var mock = {}
mock.window = (function() { mock.window = (function() {
"use strict"
var window = {} var window = {}
window.document = {} window.document = {}
window.document.childNodes = [] window.document.childNodes = []
@ -55,11 +58,12 @@ mock.window = (function() {
else this.childNodes.splice(referenceIndex, 0, node) else this.childNodes.splice(referenceIndex, 0, node)
}, },
insertAdjacentHTML: function(position, html) { insertAdjacentHTML: function(position, html) {
//todo: accept markup // todo: accept markup
if (position == "beforebegin") { if (position === "beforebegin") {
this.parentNode.insertBefore(window.document.createTextNode(html), this) this.parentNode.insertBefore(
} window.document.createTextNode(html),
else if (position == "beforeend") { this)
} else if (position === "beforeend") {
this.appendChild(window.document.createTextNode(html)) this.appendChild(window.document.createTextNode(html))
} }
}, },
@ -70,7 +74,7 @@ mock.window = (function() {
this.namespaceURI = namespace this.namespaceURI = namespace
this[name] = value.toString() this[name] = value.toString()
}, },
getAttribute: function(name, value) { getAttribute: function(name) {
return this[name] return this[name]
}, },
addEventListener: function () {}, addEventListener: function () {},
@ -104,23 +108,25 @@ mock.window = (function() {
this.childNodes.splice(index, 1) this.childNodes.splice(index, 1)
child.parentNode = null child.parentNode = null
} }
//getElementsByTagName is only used by JSONP tests, it's not required by Mithril // getElementsByTagName is only used by JSONP tests, it's not required by
// Mithril
window.document.getElementsByTagName = function(name){ window.document.getElementsByTagName = function(name){
name = name.toLowerCase(); name = name.toLowerCase()
var out = []; var out = []
var traverse = function(node){ var traverse = function(node){
if(node.childNodes && node.childNodes.length > 0){ if(node.childNodes && node.childNodes.length > 0){
node.childNodes.map(function(curr){ node.childNodes.map(function(curr){
if(curr.nodeName.toLowerCase() === name) if (curr.nodeName.toLowerCase() === name) {
out.push(curr); out.push(curr)
traverse(curr); }
}); traverse(curr)
})
} }
}; }
traverse(window.document); traverse(window.document)
return out; return out
} }
window.scrollTo = function() {} window.scrollTo = function() {}
window.cancelAnimationFrame = function() {} window.cancelAnimationFrame = function() {}
@ -156,15 +162,17 @@ mock.window = (function() {
request.$instances = [] request.$instances = []
return request return request
}()) }())
window.location = {search: "", pathname: "", hash: ""}, window.location = {search: "", pathname: "", hash: ""}
window.history = {} window.history = {}
window.history.$$length = 0 window.history.$$length = 0
window.history.pushState = function(data, title, url) { window.history.pushState = function(data, title, url) {
window.history.$$length++ window.history.$$length++
window.location.pathname = window.location.search = window.location.hash = url window.location.pathname = window.location.search =
}, window.location.hash = url
}
window.history.replaceState = function(data, title, url) { window.history.replaceState = function(data, title, url) {
window.location.pathname = window.location.search = window.location.hash = url window.location.pathname = window.location.search =
window.location.hash = url
} }
return window return window
}()) }())

View file

@ -1,15 +1,19 @@
/* eslint-disable no-console */
if (!this.console) { if (!this.console) {
var log = function(value) {document.write("<pre>" + value + "</pre>")} var log = function(value) {
"use strict"
document.write("<pre>" + value + "</pre>")
}
this.console = {log: log, error: log} this.console = {log: log, error: log}
} }
function test(condition) { function test(condition) {
"use strict"
test.total++ test.total++
try { try {
if (!condition()) throw new Error("failed") if (!condition()) throw new Error("failed")
} } catch (e) {
catch (e) {
console.error(e) console.error(e)
test.failures.push(condition) test.failures.push(condition)
} }
@ -17,6 +21,7 @@ function test(condition) {
test.total = 0 test.total = 0
test.failures = [] test.failures = []
test.print = function(print) { test.print = function(print) {
"use strict"
for (var i = 0; i < test.failures.length; i++) { for (var i = 0; i < test.failures.length; i++) {
print(test.failures[i].toString()) print(test.failures[i].toString())
} }