Итератор перебирает подряд набор значений и по очереди выдает элементы iterator.next(), как array.shift()
Генератор по очереди принимает элементы generator.next(1), как array.push(1)
Промис по очереди выполняет цепочку зависимых друг от друга асинхронных событий
Обозреватель добавляет к объекту к объекту функцию события и вызывает её, когда это событие генерируется в коде.
Обозреваемое добавляет к последовательности элементов или асинхронных событий итератор, который по порядку перебирает элементы и обозреватель, который вызывает для перебираемых элементов функции события.
Декоратор обертывает одну функцию в другую функцию decorate(base, wrapper).
Фабрика конструирует объекты по заданным параметрам.
Фасад скрывает сложную функциональность, выдавая вместо неё простую функцию.
Прокси оборачивает функцию в декоратор.
Observer Pattern
// Observer
function Observer () {
this.events = {};
}
Observer.prototype = {
addEvent: function (name, func) {if (this.events[name]) {this.events[name].push(func);} else {this.events[name] = [func];}}
, removeEvent: function (name) {if (this.events[name]) {delete this.events[name];}}
, dispatchEvent: function (name, args) {if (this.events[name]) {this.events[name].forEach(function (func) {func.apply(null, args);});}}
};
// Observer Test
var observer = new Observer();
observer.addEvent('one', function (a) {console.log('1: ' + a);});
observer.addEvent('one', function (b) {console.log('2: ' + b);});
observer.addEvent('two', function (c) {console.log('3: ' + c);});
observer.dispatchEvent('one', ['one']);
observer.dispatchEvent('two', ['two']);
observer.removeEvent('one');
observer.dispatchEvent('one', ['one']);
Iterator Pattern
// Iterator
function Iterator (items) {
var i = 0;
return {
next: function () {
var done = (i >= items.length)
, value = !done ? items[i++] : undefined;
return {value: value, done: done};
}
};
}
// Iterator Test
var iterator = new Iterator([1, 2, 3]);
console.log(iterator.next()); // {value: 1, done: false}
console.log(iterator.next()); // {value: 2, done: false}
console.log(iterator.next()); // {value: 3, done: false}
console.log(iterator.next()); // {value: undefined, done: true}
Generator Pattern
// Generator
function Generator (items) {
var i = 0;
return {
next: function (value) {
items = items.slice();
var done = (i >= items.length)
if (!done) {items[i] = value; i++;}
return {value: items, done: done};
}
};
}
// Generator Test
var generator = new Generator(new Array(3));
console.log(generator.next(1)); // {value: [1, undefined, undefined], done: false}
console.log(generator.next(2)); // {value: [1, 2, undefined], done: false}
console.log(generator.next(3)); // {value: [1, 2, 3], done: false}
console.log(generator.next(4)); // {value: [1, 2, 3], done: true}
Promise Pattern
// Promise
function Promise () {
this.promises = [];
}
Promise.prototype = {
then: function (success, error) {
if (Object.prototype.toString.call(success) !== '[object Function]') {success = function () {};}
if (Object.prototype.toString.call(error) !== '[object Function]') {error = function () {};}
this.promises.push({success: success, error: error});
return this;
}
, success: function () {
if (this.promises.length) {
var args = Array.prototype.slice.call(arguments);
args.unshift(this);
this.promises.shift().success.apply(null, args);
}
}
, error: function () {
if (this.promises.length) {
this.promises.shift().error.apply(null, arguments);
}
}
};
// Promise Test
function timeout1 (seconds, error) {
var promise = new Promise();
setTimeout(function () {
if (seconds > 2) {
promise.error(seconds);
} else {
console.log('Success 1: ' + seconds);
promise.success(seconds);
}
}, seconds * 1000);
return promise;
}
function timeout2 (promise, seconds) {
setTimeout(function () {
if (seconds > 2) {
promise.error(seconds);
} else {
console.log('Success 2: ' + seconds);
promise.success(seconds);
}
}, seconds * 1000);
return promise;
}
function timeout3 (promise, seconds) {
setTimeout(function () {
if (seconds > 1) {
promise.error(seconds);
} else {
console.log('Success 3: ' + seconds);
promise.success(seconds);
}
}, seconds * 1000);
return promise;
}
function done (promise, seconds) {
console.log('Done: ' + seconds);
}
function timeout1error (seconds) {console.log('Error 1 seconds: ' + seconds);}
function timeout2error (seconds) {console.log('Error 2 seconds: ' + seconds);}
function timeout3error (seconds) {console.log('Error 3 seconds: ' + seconds);}
timeout1(2).then(timeout2, timeout1error).then(timeout3, timeout2error).then(done, timeout3error);
Observable Pattern = Interator + Promise for async + Observer
Перебираем с помощью итератора все элементы массива или цепочки промисов и для каждого из них тригерим подставленные функции события (успешно, неуспешно, завершено).
// Observable
var Observable = {
from: function (items) {
var iterator = new Iterator(items);
return {subscribe: function (next, error, complete) {
var item = iterator.next();
while (!item.done) {
next(item.value);
item = iterator.next();
}
complete();
}};
}
};
// Observable Test
Observable.from(['Adria', 'Jen', 'Sergi']).subscribe(
function onNext (value) {console.log('Next: ' + value);}
, function onError (error) {console.log('Error: ' + error);}
, function onCompleted () {console.log('Completed');}
);
пятница, 1 апреля 2016 г.
вторник, 29 марта 2016 г.
Error handling in JavaScript
Modern Chrome and Opera fully support the HTML 5 draft spec for ErrorEvent and window.onerror. In both of these browsers you can either use window.onerror, or bind to the 'error' event properly:
// Only Chrome & Opera pass the error object.
window.onerror = function (message, file, line, col, error) {
console.log(message, "from", error.stack);
// You can send data to your server
// sendError(data);
};
// Only Chrome & Opera have an error attribute on the event.
window.addEventListener("error", function (e) {
console.log(e.error.message, "from", e.error.stack);
// You can send data to your server
// sendError(data);
})
Unfortunately Firefox, Safari and IE are still around and we have to support them too. As the stacktrace is not available in window.onerror we have to do a little bit more work.
It turns out that the only thing we can do to get stacktraces from errors is to wrap all of our code in a try{ }catch(e){ } block and then look at e.stack. We can make the process somewhat easier with a function called wrap that takes a function and returns a new function with good error handling.
function wrap(func) {
// Ensure we only wrap the function once.
if (!func._wrapped) {
func._wrapped = function () {
try{
func.apply(this, arguments);
} catch(e) {
console.log(e.message, "from", e.stack);
// You can send data to your server
// sendError(data);
throw e;
}
}
}
return func._wrapped;
};
This works. Any function that you wrap manually will have good error handling, but it turns out that we can actually do it for you automatically in most cases.
By changing the global definition of addEventListener so that it automatically wraps the callback we can automatically insert try{ }catch(e){ } around most code. This lets existing code continue to work, but adds high-quality exception tracking.
var addEventListener = window.EventTarget.prototype.addEventListener;
window.EventTarget.prototype.addEventListener = function (event, callback, bubble) {
addEventListener.call(this, event, wrap(callback), bubble);
}
We also need to make sure that removeEventListener keeps working. At the moment it won't because the argument to addEventListener is changed. Again we only need to fix this on the prototype object:
var removeEventListener = window.EventTarget.prototype.removeEventListener;
window.EventTarget.prototype.removeEventListener = function (event, callback, bubble) {
removeEventListener.call(this, event, callback._wrapped || callback, bubble);
}
Transmit error data to your backend
You can send error data using image tag as follows
function sendError(data) {
var img = newImage(),
src = 'http://yourserver.com/jserror&data=' + encodeURIComponent(JSON.stringify(data));
img.crossOrigin = 'anonymous';
img.onload = function success() {
console.log('success', data);
};
img.onerror = img.onabort = function failure() {
console.error('failure', data);
};
img.src = src;
}
// Only Chrome & Opera pass the error object.
window.onerror = function (message, file, line, col, error) {
console.log(message, "from", error.stack);
// You can send data to your server
// sendError(data);
};
// Only Chrome & Opera have an error attribute on the event.
window.addEventListener("error", function (e) {
console.log(e.error.message, "from", e.error.stack);
// You can send data to your server
// sendError(data);
})
Unfortunately Firefox, Safari and IE are still around and we have to support them too. As the stacktrace is not available in window.onerror we have to do a little bit more work.
It turns out that the only thing we can do to get stacktraces from errors is to wrap all of our code in a try{ }catch(e){ } block and then look at e.stack. We can make the process somewhat easier with a function called wrap that takes a function and returns a new function with good error handling.
function wrap(func) {
// Ensure we only wrap the function once.
if (!func._wrapped) {
func._wrapped = function () {
try{
func.apply(this, arguments);
} catch(e) {
console.log(e.message, "from", e.stack);
// You can send data to your server
// sendError(data);
throw e;
}
}
}
return func._wrapped;
};
This works. Any function that you wrap manually will have good error handling, but it turns out that we can actually do it for you automatically in most cases.
By changing the global definition of addEventListener so that it automatically wraps the callback we can automatically insert try{ }catch(e){ } around most code. This lets existing code continue to work, but adds high-quality exception tracking.
var addEventListener = window.EventTarget.prototype.addEventListener;
window.EventTarget.prototype.addEventListener = function (event, callback, bubble) {
addEventListener.call(this, event, wrap(callback), bubble);
}
We also need to make sure that removeEventListener keeps working. At the moment it won't because the argument to addEventListener is changed. Again we only need to fix this on the prototype object:
var removeEventListener = window.EventTarget.prototype.removeEventListener;
window.EventTarget.prototype.removeEventListener = function (event, callback, bubble) {
removeEventListener.call(this, event, callback._wrapped || callback, bubble);
}
Transmit error data to your backend
You can send error data using image tag as follows
function sendError(data) {
var img = newImage(),
src = 'http://yourserver.com/jserror&data=' + encodeURIComponent(JSON.stringify(data));
img.crossOrigin = 'anonymous';
img.onload = function success() {
console.log('success', data);
};
img.onerror = img.onabort = function failure() {
console.error('failure', data);
};
img.src = src;
}
среда, 16 марта 2016 г.
Support ECMAScript 5, 6, 7 Shims and Shams
ECMAScript 5 (есть в es5-shim)
Object
- Object.keys
Array
- Array.isArray
- [].indexOf
- [].lastIndexOf
- [].every
- [].some
- [].forEach
- [].map
- [].filter
- [].reduce
- [].reduceRight
String
- "".trim
- "".split - crossbrowser (нет в es5-shim)
Function
- (function(){}).bind
Date
- Date.now
- (new Date()).toISOString
- (new Date()).toJSON
- (new Date()).parse -> return NaN for invalid dates
JSON (нет в es5-shim)
- JSON.parse
- JSON.stringify
ECMAScript 6 (есть в es6-shim)
Object
- Object.assign
- Object.is
Только, если есть поддержка ES5
- Object.getPrototypeOf
- Object.getOwnPropertyDescriptor
- Object.getOwnPropertyNames
- Object.seal
- Object.freeze
- Object.preventExtensions
- Object.isSealed
- Object.isExtensible
- Object.keys
String
- String.raw
- String.fromCodePoint
- "".codePointAt
- "".repeat
- "".startsWith
- "".endsWith
- "".includes
Number
- Number.isFinite
- Number.isInteger
- Number.isSafeInteger
- Number.isNaN
- Number.EPSILON
- Number.MIN_SAFE_INTEGER
- Number.MAX_SAFE_INTEGER
- Number('0o1')
- Number('0b1')
Array
- Array.from
- Array.of
- [].copyWithin
- [].find
- [].fineIndex
- [].fill
- [].keys
- [].values
- [].entries
RegExp
- (//).flags
Math
- Math.clz32
- Math.imul
- Math.sign
- Math.log10
- Math.log2
- Math.log1p
- Math.expm1
- Math.cosh
- Math.sinh
- Math.acosh
- Math.asinh
- Math.atanh
- Math.trunc
- Math.fround
- Math.cbrt
- Math.hypot
Map
Set
Reflect
Promise
ECMAScript 7 (есть в es7-shim)
Object
- Object.values
- Object.entries
- Object.getOwnPropertyDescriptors
Array
- [].includes
String
- "".padStart
- "".padEnd
- "".trimLeft
- "".trimRight
- "".at
Map
- (new Map()).toJSON
Set
- (new Set()).toJSON
Последовательность включения новых функций в проект:
- es5-shim.min.js
- es5-sham.min.js
- json3.min.js
- es6-shim.min.js
- es6-sham.min.js
- es7-shim.min.js
...other-libs.js...
Object
- Object.keys
Array
- Array.isArray
- [].indexOf
- [].lastIndexOf
- [].every
- [].some
- [].forEach
- [].map
- [].filter
- [].reduce
- [].reduceRight
String
- "".trim
- "".split - crossbrowser (нет в es5-shim)
Function
- (function(){}).bind
Date
- Date.now
- (new Date()).toISOString
- (new Date()).toJSON
- (new Date()).parse -> return NaN for invalid dates
JSON (нет в es5-shim)
- JSON.parse
- JSON.stringify
ECMAScript 6 (есть в es6-shim)
Object
- Object.assign
- Object.is
Только, если есть поддержка ES5
- Object.getPrototypeOf
- Object.getOwnPropertyDescriptor
- Object.getOwnPropertyNames
- Object.seal
- Object.freeze
- Object.preventExtensions
- Object.isSealed
- Object.isExtensible
- Object.keys
String
- String.raw
- String.fromCodePoint
- "".codePointAt
- "".repeat
- "".startsWith
- "".endsWith
- "".includes
Number
- Number.isFinite
- Number.isInteger
- Number.isSafeInteger
- Number.isNaN
- Number.EPSILON
- Number.MIN_SAFE_INTEGER
- Number.MAX_SAFE_INTEGER
- Number('0o1')
- Number('0b1')
Array
- Array.from
- Array.of
- [].copyWithin
- [].find
- [].fineIndex
- [].fill
- [].keys
- [].values
- [].entries
RegExp
- (//).flags
Math
- Math.clz32
- Math.imul
- Math.sign
- Math.log10
- Math.log2
- Math.log1p
- Math.expm1
- Math.cosh
- Math.sinh
- Math.acosh
- Math.asinh
- Math.atanh
- Math.trunc
- Math.fround
- Math.cbrt
- Math.hypot
Map
Set
Reflect
Promise
ECMAScript 7 (есть в es7-shim)
Object
- Object.values
- Object.entries
- Object.getOwnPropertyDescriptors
Array
- [].includes
String
- "".padStart
- "".padEnd
- "".trimLeft
- "".trimRight
- "".at
Map
- (new Map()).toJSON
Set
- (new Set()).toJSON
Последовательность включения новых функций в проект:
- es5-shim.min.js
- es5-sham.min.js
- json3.min.js
- es6-shim.min.js
- es6-sham.min.js
- es7-shim.min.js
...other-libs.js...
понедельник, 14 марта 2016 г.
JavaScript Decorator
function decorate (baseFunction, decoratorFunction) {
return function () {decoratorFunction(baseFunction, arguments);};
}
function a (a) {
console.log(a);
return 'OK';
}
function b (baseFunction, baseFunctionArguments) {
console.log('start');
baseFunction.apply(null, baseFunctionArguments);
console.log('b');
console.log('stop');
}
a = decorate(a, b);
a('a');
function trace (baseFunction, baseFunctionArguments) {
var result = baseFunction.apply(null, baseFunctionArguments);
console.log('TRACE: ' + baseFunction.name + ' (' + Array.prototype.slice.call(baseFunctionArguments).join(', ') + ') => ' + result);
return result;
}
var c = decorate(a, trace);
c('a', 'b', 1, 2, {});
return function () {decoratorFunction(baseFunction, arguments);};
}
function a (a) {
console.log(a);
return 'OK';
}
function b (baseFunction, baseFunctionArguments) {
console.log('start');
baseFunction.apply(null, baseFunctionArguments);
console.log('b');
console.log('stop');
}
a = decorate(a, b);
a('a');
function trace (baseFunction, baseFunctionArguments) {
var result = baseFunction.apply(null, baseFunctionArguments);
console.log('TRACE: ' + baseFunction.name + ' (' + Array.prototype.slice.call(baseFunctionArguments).join(', ') + ') => ' + result);
return result;
}
var c = decorate(a, trace);
c('a', 'b', 1, 2, {});
среда, 24 февраля 2016 г.
TypeScript Playground
Файл index.html
<!DOCTYPE html>
<html>
<head>
<style>
body {
font-family: Verdana;
font-size: 62.5%;
}
table {
width: 100%;
}
table tr td {
width: 50%;
vertical-align: top;
border: 1px solid black;
}
textarea {
width: 100%;
height: 500px;
margin: 0;
padding: 5px;
border: none;
resize: none;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
outline: 0;
font-size: 2.5em;
}
div {
height: 500px;
margin: 0;
padding: 5px;
border: none;
font-size: 2.5em;
}
pre {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<table>
<tr>
<td><textarea id="source"></textarea></td>
<td><div><pre id="result"></pre></div></td>
</tr>
</table>
<script type="text/javascript" src="js/typescriptServices.js"></script>
<script type="text/javascript" src="js/transpiler.js"></script>
</body>
</html>
Файл typescriptService.js
https://rawgit.com/Microsoft/TypeScript/master/lib/typescriptServices.js
Файл transpiler.js
;(function(){
document.getElementById('source').addEventListener('keyup', function(){
document.getElementById('result').innerHTML = ts.transpile(document.getElementById('source').value);
}, false);
})();
<!DOCTYPE html>
<html>
<head>
<style>
body {
font-family: Verdana;
font-size: 62.5%;
}
table {
width: 100%;
}
table tr td {
width: 50%;
vertical-align: top;
border: 1px solid black;
}
textarea {
width: 100%;
height: 500px;
margin: 0;
padding: 5px;
border: none;
resize: none;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
outline: 0;
font-size: 2.5em;
}
div {
height: 500px;
margin: 0;
padding: 5px;
border: none;
font-size: 2.5em;
}
pre {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<table>
<tr>
<td><textarea id="source"></textarea></td>
<td><div><pre id="result"></pre></div></td>
</tr>
</table>
<script type="text/javascript" src="js/typescriptServices.js"></script>
<script type="text/javascript" src="js/transpiler.js"></script>
</body>
</html>
Файл typescriptService.js
https://rawgit.com/Microsoft/TypeScript/master/lib/typescriptServices.js
Файл transpiler.js
;(function(){
document.getElementById('source').addEventListener('keyup', function(){
document.getElementById('result').innerHTML = ts.transpile(document.getElementById('source').value);
}, false);
})();
Упрощенный код использования TypeScript в браузере
Файл index.html
<!DOCTYPE html>
<html>
<head>
<script type="text/typescript">
setTimeout(()=>console.log('hello'));
</script>
<script type="text/javascript" src="js/typescriptServices.js"></script>
<script type="text/javascript" src="js/transpiler.js"></script>
</head>
<body>
</body>
</html>
Файл typescriptService.js
https://rawgit.com/Microsoft/TypeScript/master/lib/typescriptServices.js
Файл transpiler.js
;(function(){
var scripts = document.getElementsByTagName('script')
, script;
for (var i = 0, len = scripts.length; i < len; i++) {
if (scripts[i].type === 'text/typescript') {
script = document.createElement('script');
script.type = 'text/javascript';
script.innerHTML = '// Compiled TypeScript:\n\n' + ts.transpile(scripts[i].innerHTML);
document.getElementsByTagName('head')[0].appendChild(script);
}
}
})();
<!DOCTYPE html>
<html>
<head>
<script type="text/typescript">
setTimeout(()=>console.log('hello'));
</script>
<script type="text/javascript" src="js/typescriptServices.js"></script>
<script type="text/javascript" src="js/transpiler.js"></script>
</head>
<body>
</body>
</html>
Файл typescriptService.js
https://rawgit.com/Microsoft/TypeScript/master/lib/typescriptServices.js
Файл transpiler.js
;(function(){
var scripts = document.getElementsByTagName('script')
, script;
for (var i = 0, len = scripts.length; i < len; i++) {
if (scripts[i].type === 'text/typescript') {
script = document.createElement('script');
script.type = 'text/javascript';
script.innerHTML = '// Compiled TypeScript:\n\n' + ts.transpile(scripts[i].innerHTML);
document.getElementsByTagName('head')[0].appendChild(script);
}
}
})();
How to compile TypeScript in the browser
Add the following lines at the bottom of your page:
<script src="https://rawgit.com/Microsoft/TypeScript/master/lib/typescriptServices.js"></script>
<script src="https://rawgit.com/basarat/typescript-script/master/transpiler.js"></script>
And then you can use script tags that load .ts files or even have typescript inline:
<script type="text/typescript" src="script.ts"></script>
<script type="text/typescript">
setTimeout(()=>console.log('hello'));
</script>
Example
index.html source:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
<script type="text/typescript" src="script.ts"></script>
<script type="text/typescript">
setTimeout(()=>console.log('hello'));
</script>
<script src="https://rawgit.com/Microsoft/TypeScript/master/lib/typescriptServices.js"></script>
<script src="https://rawgit.com/basarat/typescript-script/master/transpiler.js"></script>
</head>
<body>
<h1>Hello</h1>
</body>
</html>
transpiler.js source:
// BASED on https://github.com/niutech/typescript-compile but using 1.5 transpile function
(function () {
//Keep track of the number of scripts to be pulled, and fire the compiler
//after the number of loaded reaches the total
var scripts = {
total: 0, //total number of scripts to be loaded
loaded: 0, //current number of loaded scripts
data: [], //file data
name: [] //file name
};
//Function loads each script and pushes its content into scripts.data
var load = function (url) {
var xhr = window.ActiveXObject ? new window.ActiveXObject('Microsoft.XMLHTTP') : new window.XMLHttpRequest();;
xhr.open('GET', url, true);
if ('overrideMimeType' in xhr) xhr.overrideMimeType('text/plain');
xhr.onreadystatechange = function () {
if (xhr.readyState !== 4) return;
if (xhr.status === 0 || xhr.status === 200) {
scripts.loaded++;
scripts.data.push(xhr.responseText);
scripts.name.push(url);
if (scripts.loaded === scripts.total) compile();
return xhr.responseText;
} else {
console.log('Could not load ' + url);
} //end if
}; //end xhr.onreadystatechange()
return xhr.send(null);
};
//Compiles each of the scripts found within scripts.data
var compile = function () {
if (scripts.data.length == 0 || scripts.data.length != scripts.name.length) return; //no reason to compile when there are no scripts
var elem, source = '',
body = document.getElementsByTagName('body')[0];
scripts.total = 0; //clear the 'queue' incase the xhr response was super quick and happened before the initializer finished
var hashCode = function (s) {
var hsh = 0,
chr, i;
if (s.length == 0) {
return hsh;
}
for (i = 0; i < s.length; i++) {
chr = s.charCodeAt(i);
hsh = (hsh << 5) - hsh + chr;
hsh = hsh & hsh; //Convert to 32bit integer
}
return hsh;
};
if (window.sessionStorage && sessionStorage.getItem('typescript' + hashCode(scripts.data.join('')))) {
source = sessionStorage.getItem('typescript' + hashCode(scripts.data.join('')));
} else {
(function () {
var filename;
for (num = 0; num < scripts.data.length; num++) {
filename = scripts.name[num] = scripts.name[num].slice(scripts.name[num].lastIndexOf('/') + 1);
var src = scripts.data[num];
source += ts.transpile(src);
}
})();
}
elem = document.createElement('script');
elem.type = 'text/javascript';
elem.innerHTML = '//Compiled TypeScript\n\n' + source;
body.appendChild(elem);
};
(function () {
//Polyfill for older browsers
if (!window.console) window.console = {
log: function () {}
};
var script = document.getElementsByTagName('script');
var i, src = [];
for (i = 0; i < script.length; i++) {
if (script[i].type == 'text/typescript') {
if (script[i].src) {
scripts.total++
load(script[i].src);
} else {
scripts.data.push(script[i].innerHTML);
scripts.name.push('innerHTML'+scripts.total);
scripts.total++;
scripts.loaded++;
}
}
}
if (scripts.loaded === scripts.total) compile(); //only fires if all scripts are innerHTML, else this is fired on XHR response
})();
})();
<script src="https://rawgit.com/Microsoft/TypeScript/master/lib/typescriptServices.js"></script>
<script src="https://rawgit.com/basarat/typescript-script/master/transpiler.js"></script>
And then you can use script tags that load .ts files or even have typescript inline:
<script type="text/typescript" src="script.ts"></script>
<script type="text/typescript">
setTimeout(()=>console.log('hello'));
</script>
Example
index.html source:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
<script type="text/typescript" src="script.ts"></script>
<script type="text/typescript">
setTimeout(()=>console.log('hello'));
</script>
<script src="https://rawgit.com/Microsoft/TypeScript/master/lib/typescriptServices.js"></script>
<script src="https://rawgit.com/basarat/typescript-script/master/transpiler.js"></script>
</head>
<body>
<h1>Hello</h1>
</body>
</html>
transpiler.js source:
// BASED on https://github.com/niutech/typescript-compile but using 1.5 transpile function
(function () {
//Keep track of the number of scripts to be pulled, and fire the compiler
//after the number of loaded reaches the total
var scripts = {
total: 0, //total number of scripts to be loaded
loaded: 0, //current number of loaded scripts
data: [], //file data
name: [] //file name
};
//Function loads each script and pushes its content into scripts.data
var load = function (url) {
var xhr = window.ActiveXObject ? new window.ActiveXObject('Microsoft.XMLHTTP') : new window.XMLHttpRequest();;
xhr.open('GET', url, true);
if ('overrideMimeType' in xhr) xhr.overrideMimeType('text/plain');
xhr.onreadystatechange = function () {
if (xhr.readyState !== 4) return;
if (xhr.status === 0 || xhr.status === 200) {
scripts.loaded++;
scripts.data.push(xhr.responseText);
scripts.name.push(url);
if (scripts.loaded === scripts.total) compile();
return xhr.responseText;
} else {
console.log('Could not load ' + url);
} //end if
}; //end xhr.onreadystatechange()
return xhr.send(null);
};
//Compiles each of the scripts found within scripts.data
var compile = function () {
if (scripts.data.length == 0 || scripts.data.length != scripts.name.length) return; //no reason to compile when there are no scripts
var elem, source = '',
body = document.getElementsByTagName('body')[0];
scripts.total = 0; //clear the 'queue' incase the xhr response was super quick and happened before the initializer finished
var hashCode = function (s) {
var hsh = 0,
chr, i;
if (s.length == 0) {
return hsh;
}
for (i = 0; i < s.length; i++) {
chr = s.charCodeAt(i);
hsh = (hsh << 5) - hsh + chr;
hsh = hsh & hsh; //Convert to 32bit integer
}
return hsh;
};
if (window.sessionStorage && sessionStorage.getItem('typescript' + hashCode(scripts.data.join('')))) {
source = sessionStorage.getItem('typescript' + hashCode(scripts.data.join('')));
} else {
(function () {
var filename;
for (num = 0; num < scripts.data.length; num++) {
filename = scripts.name[num] = scripts.name[num].slice(scripts.name[num].lastIndexOf('/') + 1);
var src = scripts.data[num];
source += ts.transpile(src);
}
})();
}
elem = document.createElement('script');
elem.type = 'text/javascript';
elem.innerHTML = '//Compiled TypeScript\n\n' + source;
body.appendChild(elem);
};
(function () {
//Polyfill for older browsers
if (!window.console) window.console = {
log: function () {}
};
var script = document.getElementsByTagName('script');
var i, src = [];
for (i = 0; i < script.length; i++) {
if (script[i].type == 'text/typescript') {
if (script[i].src) {
scripts.total++
load(script[i].src);
} else {
scripts.data.push(script[i].innerHTML);
scripts.name.push('innerHTML'+scripts.total);
scripts.total++;
scripts.loaded++;
}
}
}
if (scripts.loaded === scripts.total) compile(); //only fires if all scripts are innerHTML, else this is fired on XHR response
})();
})();
Подписаться на:
Сообщения (Atom)