Comparing version 1.9.3 to 2.0.0-alpha1
353
aspect.js
@@ -1,223 +0,148 @@ | ||
define([], function(){ | ||
var nextId = 0; | ||
// module: | ||
// dojo/aspect | ||
function advise(dispatcher, type, advice, receiveArguments) { | ||
var previous = dispatcher[type]; | ||
var advised = { | ||
id: nextId++, | ||
advice: advice, | ||
receiveArguments: receiveArguments | ||
}; | ||
"use strict"; | ||
var undefined, nextId = 0; | ||
function advise(dispatcher, type, advice, receiveArguments){ | ||
var previous = dispatcher[type]; | ||
var around = type == "around"; | ||
var signal; | ||
if(around){ | ||
var advised = advice(function(){ | ||
return previous.advice(this, arguments); | ||
}); | ||
signal = { | ||
remove: function(){ | ||
if(advised){ | ||
advised = dispatcher = advice = null; | ||
} | ||
}, | ||
advice: function(target, args){ | ||
return advised ? | ||
advised.apply(target, args) : // called the advised function | ||
previous.advice(target, args); // cancelled, skip to next one | ||
} | ||
}; | ||
}else{ | ||
// create the remove handler | ||
signal = { | ||
remove: function(){ | ||
if(signal.advice){ | ||
var previous = signal.previous; | ||
var next = signal.next; | ||
if(!next && !previous){ | ||
delete dispatcher[type]; | ||
}else{ | ||
if(previous){ | ||
previous.next = next; | ||
}else{ | ||
dispatcher[type] = next; | ||
} | ||
if(next){ | ||
next.previous = previous; | ||
} | ||
} | ||
if (previous) { | ||
if (type === 'after') { | ||
while (previous.next && (previous = previous.next)) { | ||
} | ||
previous.next = advised; | ||
advised.previous = previous; | ||
} else { | ||
// add to the beginning | ||
dispatcher.before = advised; | ||
advised.next = previous; | ||
previous.previous = advised; | ||
} | ||
} else { | ||
dispatcher[type] = advised; | ||
} | ||
// remove the advice to signal that this signal has been removed | ||
dispatcher = advice = signal.advice = null; | ||
} | ||
}, | ||
id: nextId++, | ||
advice: advice, | ||
receiveArguments: receiveArguments | ||
}; | ||
} | ||
if(previous && !around){ | ||
if(type == "after"){ | ||
// add the listener to the end of the list | ||
// note that we had to change this loop a little bit to workaround a bizarre IE10 JIT bug | ||
while(previous.next && (previous = previous.next)){} | ||
previous.next = signal; | ||
signal.previous = previous; | ||
}else if(type == "before"){ | ||
// add to beginning | ||
dispatcher[type] = signal; | ||
signal.next = previous; | ||
previous.previous = signal; | ||
} | ||
}else{ | ||
// around or first one just replaces | ||
dispatcher[type] = signal; | ||
} | ||
return signal; | ||
} | ||
function aspect(type){ | ||
return function(target, methodName, advice, receiveArguments){ | ||
var existing = target[methodName], dispatcher; | ||
if(!existing || existing.target != target){ | ||
// no dispatcher in place | ||
target[methodName] = dispatcher = function(){ | ||
var executionId = nextId; | ||
// before advice | ||
var args = arguments; | ||
var before = dispatcher.before; | ||
while(before){ | ||
args = before.advice.apply(this, args) || args; | ||
before = before.next; | ||
} | ||
// around advice | ||
if(dispatcher.around){ | ||
var results = dispatcher.around.advice(this, args); | ||
} | ||
// after advice | ||
var after = dispatcher.after; | ||
while(after && after.id < executionId){ | ||
if(after.receiveArguments){ | ||
var newResults = after.advice.apply(this, args); | ||
// change the return value only if a new value was returned | ||
results = newResults === undefined ? results : newResults; | ||
}else{ | ||
results = after.advice.call(this, results, args); | ||
} | ||
after = after.next; | ||
} | ||
return results; | ||
}; | ||
if(existing){ | ||
dispatcher.around = {advice: function(target, args){ | ||
return existing.apply(target, args); | ||
}}; | ||
} | ||
dispatcher.target = target; | ||
} | ||
var results = advise((dispatcher || existing), type, advice, receiveArguments); | ||
advice = null; | ||
return results; | ||
}; | ||
} | ||
advice = previous = null; | ||
// TODOC: after/before/around return object | ||
return { | ||
remove: function () { | ||
this.remove = noop; | ||
var after = aspect("after"); | ||
/*===== | ||
after = function(target, methodName, advice, receiveArguments){ | ||
// summary: | ||
// The "after" export of the aspect module is a function that can be used to attach | ||
// "after" advice to a method. This function will be executed after the original method | ||
// is executed. By default the function will be called with a single argument, the return | ||
// value of the original method, or the the return value of the last executed advice (if a previous one exists). | ||
// The fourth (optional) argument can be set to true to so the function receives the original | ||
// arguments (from when the original method was called) rather than the return value. | ||
// If there are multiple "after" advisors, they are executed in the order they were registered. | ||
// target: Object | ||
// This is the target object | ||
// methodName: String | ||
// This is the name of the method to attach to. | ||
// advice: Function | ||
// This is function to be called after the original method | ||
// receiveArguments: Boolean? | ||
// If this is set to true, the advice function receives the original arguments (from when the original mehtod | ||
// was called) rather than the return value of the original/previous method. | ||
// returns: | ||
// A signal object that can be used to cancel the advice. If remove() is called on this signal object, it will | ||
// stop the advice function from being executed. | ||
}; | ||
=====*/ | ||
var previous = advised.previous; | ||
var next = advised.next; | ||
var before = aspect("before"); | ||
/*===== | ||
before = function(target, methodName, advice){ | ||
// summary: | ||
// The "before" export of the aspect module is a function that can be used to attach | ||
// "before" advice to a method. This function will be executed before the original method | ||
// is executed. This function will be called with the arguments used to call the method. | ||
// This function may optionally return an array as the new arguments to use to call | ||
// the original method (or the previous, next-to-execute before advice, if one exists). | ||
// If the before method doesn't return anything (returns undefined) the original arguments | ||
// will be preserved. | ||
// If there are multiple "before" advisors, they are executed in the reverse order they were registered. | ||
// target: Object | ||
// This is the target object | ||
// methodName: String | ||
// This is the name of the method to attach to. | ||
// advice: Function | ||
// This is function to be called before the original method | ||
}; | ||
=====*/ | ||
if (!previous && !next) { | ||
dispatcher[type] = null; | ||
} else { | ||
if (previous) { | ||
previous.next = next; | ||
} else { | ||
dispatcher[type] = next; | ||
} | ||
var around = aspect("around"); | ||
/*===== | ||
around = function(target, methodName, advice){ | ||
// summary: | ||
// The "around" export of the aspect module is a function that can be used to attach | ||
// "around" advice to a method. The advisor function is immediately executed when | ||
// the around() is called, is passed a single argument that is a function that can be | ||
// called to continue execution of the original method (or the next around advisor). | ||
// The advisor function should return a function, and this function will be called whenever | ||
// the method is called. It will be called with the arguments used to call the method. | ||
// Whatever this function returns will be returned as the result of the method call (unless after advise changes it). | ||
// example: | ||
// If there are multiple "around" advisors, the most recent one is executed first, | ||
// which can then delegate to the next one and so on. For example: | ||
// | around(obj, "foo", function(originalFoo){ | ||
// | return function(){ | ||
// | var start = new Date().getTime(); | ||
// | var results = originalFoo.apply(this, arguments); // call the original | ||
// | var end = new Date().getTime(); | ||
// | console.log("foo execution took " + (end - start) + " ms"); | ||
// | return results; | ||
// | }; | ||
// | }); | ||
// target: Object | ||
// This is the target object | ||
// methodName: String | ||
// This is the name of the method to attach to. | ||
// advice: Function | ||
// This is function to be called around the original method | ||
}; | ||
=====*/ | ||
if (next) { | ||
next.previous = previous; | ||
} | ||
} | ||
return { | ||
// summary: | ||
// provides aspect oriented programming functionality, allowing for | ||
// one to add before, around, or after advice on existing methods. | ||
// example: | ||
// | define(["dojo/aspect"], function(aspect){ | ||
// | var signal = aspect.after(targetObject, "methodName", function(someArgument){ | ||
// | this will be called when targetObject.methodName() is called, after the original function is called | ||
// | }); | ||
// | ||
// example: | ||
// The returned signal object can be used to cancel the advice. | ||
// | signal.remove(); // this will stop the advice from being executed anymore | ||
// | aspect.before(targetObject, "methodName", function(someArgument){ | ||
// | // this will be called when targetObject.methodName() is called, before the original function is called | ||
// | }); | ||
dispatcher = advised = null; | ||
} | ||
}; | ||
} | ||
before: before, | ||
around: around, | ||
after: after | ||
}; | ||
}); | ||
function getDispatcher(target, methodName) { | ||
var existing = target[methodName]; | ||
var dispatcher; | ||
if (!existing || existing.target !== target) { | ||
// no dispatcher | ||
target[methodName] = dispatcher = function () { | ||
var executionId = nextId; | ||
var args = arguments; | ||
var results; | ||
var before = dispatcher.before; | ||
while (before) { | ||
args = before.advice.apply(this, args) || args; | ||
before = before.next; | ||
} | ||
if (dispatcher.around) { | ||
results = dispatcher.around.advice(this, args); | ||
} | ||
var after = dispatcher.after; | ||
while (after && after.id < executionId) { | ||
if (after.receiveArguments) { | ||
var newResults = after.advice.apply(this, args); | ||
results = newResults === undefined ? results : newResults; | ||
} else { | ||
results = after.advice.call(this, results, args); | ||
} | ||
after = after.next; | ||
} | ||
return results; | ||
}; | ||
if (existing) { | ||
dispatcher.around = { | ||
advice: function (target, args) { | ||
return existing.apply(target, args); | ||
} | ||
}; | ||
} | ||
dispatcher.target = target; | ||
} else { | ||
dispatcher = existing; | ||
} | ||
target = null; | ||
return dispatcher; | ||
} | ||
function noop() { | ||
} | ||
function after(target, methodName, advice) { | ||
return advise(getDispatcher(target, methodName), 'after', advice); | ||
} | ||
exports.after = after; | ||
function around(target, methodName, advice) { | ||
var dispatcher = getDispatcher(target, methodName); | ||
var previous = dispatcher.around; | ||
var advised = advice(function () { | ||
return previous.advice(this, arguments); | ||
}); | ||
dispatcher.around = { | ||
advice: function (target, args) { | ||
return advised ? advised.apply(target, args) : previous.advice(target, args); | ||
} | ||
}; | ||
advice = null; | ||
return { | ||
remove: function () { | ||
this.remove = noop; | ||
advised = dispatcher = null; | ||
} | ||
}; | ||
} | ||
exports.around = around; | ||
function before(target, methodName, advice) { | ||
return advise(getDispatcher(target, methodName), 'before', advice); | ||
} | ||
exports.before = before; | ||
function on(target, methodName, advice) { | ||
return advise(getDispatcher(target, methodName), 'after', advice, true); | ||
} | ||
exports.on = on; |
147
cookie.js
@@ -1,98 +0,67 @@ | ||
define(["./_base/kernel", "./regexp"], function(dojo, regexp){ | ||
var string = require('./string'); | ||
// module: | ||
// dojo/cookie | ||
if (!navigator.cookieEnabled) { | ||
return null; | ||
} | ||
/*===== | ||
var __cookieProps = { | ||
// expires: Date|String|Number? | ||
// If a number, the number of days from today at which the cookie | ||
// will expire. If a date, the date past which the cookie will expire. | ||
// If expires is in the past, the cookie will be deleted. | ||
// If expires is omitted or is 0, the cookie will expire when the browser closes. | ||
// path: String? | ||
// The path to use for the cookie. | ||
// domain: String? | ||
// The domain to use for the cookie. | ||
// secure: Boolean? | ||
// Whether to only send the cookie on secure connections | ||
}; | ||
=====*/ | ||
var longAgo = new Date(1970, 0, 1).toUTCString(); | ||
function createCookieOptions(options) { | ||
var optionsString = ''; | ||
dojo.cookie = function(/*String*/name, /*String?*/ value, /*__cookieProps?*/ props){ | ||
// summary: | ||
// Get or set a cookie. | ||
// description: | ||
// If one argument is passed, returns the value of the cookie | ||
// For two or more arguments, acts as a setter. | ||
// name: | ||
// Name of the cookie | ||
// value: | ||
// Value for the cookie | ||
// props: | ||
// Properties for the cookie | ||
// example: | ||
// set a cookie with the JSON-serialized contents of an object which | ||
// will expire 5 days from now: | ||
// | require(["dojo/cookie", "dojo/json"], function(cookie, json){ | ||
// | cookie("configObj", json.stringify(config, {expires: 5 })); | ||
// | }); | ||
// | ||
// example: | ||
// de-serialize a cookie back into a JavaScript object: | ||
// | require(["dojo/cookie", "dojo/json"], function(cookie, json){ | ||
// | config = json.parse(cookie("configObj")); | ||
// | }); | ||
// | ||
// example: | ||
// delete a cookie: | ||
// | require(["dojo/cookie"], function(cookie){ | ||
// | cookie("configObj", null, {expires: -1}); | ||
// | }); | ||
var c = document.cookie, ret; | ||
if(arguments.length == 1){ | ||
var matches = c.match(new RegExp("(?:^|; )" + regexp.escapeString(name) + "=([^;]*)")); | ||
ret = matches ? decodeURIComponent(matches[1]) : undefined; | ||
}else{ | ||
props = props || {}; | ||
// FIXME: expires=0 seems to disappear right away, not on close? (FF3) Change docs? | ||
var exp = props.expires; | ||
if(typeof exp == "number"){ | ||
var d = new Date(); | ||
d.setTime(d.getTime() + exp*24*60*60*1000); | ||
exp = props.expires = d; | ||
} | ||
if(exp && exp.toUTCString){ props.expires = exp.toUTCString(); } | ||
for (var key in options) { | ||
var value = options[key]; | ||
value = encodeURIComponent(value); | ||
var updatedCookie = name + "=" + value, propName; | ||
for(propName in props){ | ||
updatedCookie += "; " + propName; | ||
var propValue = props[propName]; | ||
if(propValue !== true){ updatedCookie += "=" + propValue; } | ||
} | ||
document.cookie = updatedCookie; | ||
} | ||
return ret; // String|undefined | ||
}; | ||
if (key === 'maxAge') { | ||
key = 'max-age'; | ||
} else if (key === 'secure' && !value) { | ||
continue; | ||
} | ||
dojo.cookie.isSupported = function(){ | ||
// summary: | ||
// Use to determine if the current browser supports cookies or not. | ||
// | ||
// Returns true if user allows cookies. | ||
// Returns false if user doesn't allow cookies. | ||
optionsString += '; ' + encodeURIComponent(key); | ||
if(!("cookieEnabled" in navigator)){ | ||
this("__djCookieTest__", "CookiesAllowed"); | ||
navigator.cookieEnabled = this("__djCookieTest__") == "CookiesAllowed"; | ||
if(navigator.cookieEnabled){ | ||
this("__djCookieTest__", "", {expires: -1}); | ||
} | ||
} | ||
return navigator.cookieEnabled; | ||
}; | ||
if (key === 'secure') { | ||
// secure is a boolean flag, so provide no value | ||
} else if (key === 'expires') { | ||
// Expires will not work if its value is URI-encoded | ||
optionsString += '=' + (value.toUTCString ? value.toUTCString() : value); | ||
} else { | ||
optionsString += '=' + encodeURIComponent(value); | ||
} | ||
} | ||
return dojo.cookie; | ||
return optionsString; | ||
} | ||
Object.defineProperty(exports, 'length', { | ||
get: function () { | ||
return document.cookie.length ? string.count(document.cookie, '; ') + 1 : 0; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
function key(index) { | ||
var keyValuePair = document.cookie.split('; ', index + 1)[index]; | ||
return keyValuePair ? decodeURIComponent(/^([^=]+)/.exec(keyValuePair)[0]) : null; | ||
} | ||
exports.key = key; | ||
function getItem(key) { | ||
var match = new RegExp('(?:^|; )' + string.escapeRegExpString(encodeURIComponent(key)) + '=([^;]*)').exec(document.cookie); | ||
return match ? decodeURIComponent(match[1]) : null; | ||
} | ||
exports.getItem = getItem; | ||
function setItem(key, data, options) { | ||
if (typeof options === "undefined") { options = {}; } | ||
document.cookie = encodeURIComponent(key) + '=' + encodeURIComponent(data) + createCookieOptions(options); | ||
} | ||
exports.setItem = setItem; | ||
function removeItem(key, options) { | ||
options = options ? Object.create(options) : {}; | ||
options.expires = longAgo; | ||
document.cookie = encodeURIComponent(key) + '=' + createCookieOptions(options); | ||
} | ||
exports.removeItem = removeItem; |
204
dom.js
@@ -1,197 +0,7 @@ | ||
define(["./sniff", "./_base/window"], | ||
function(has, win){ | ||
// module: | ||
// dojo/dom | ||
// FIXME: need to add unit tests for all the semi-public methods | ||
if(has("ie") <= 7){ | ||
try{ | ||
document.execCommand("BackgroundImageCache", false, true); | ||
}catch(e){ | ||
// sane browsers don't have cache "issues" | ||
} | ||
} | ||
// ============================= | ||
// DOM Functions | ||
// ============================= | ||
// the result object | ||
var dom = { | ||
// summary: | ||
// This module defines the core dojo DOM API. | ||
}; | ||
if(has("ie")){ | ||
dom.byId = function(id, doc){ | ||
if(typeof id != "string"){ | ||
return id; | ||
} | ||
var _d = doc || win.doc, te = id && _d.getElementById(id); | ||
// attributes.id.value is better than just id in case the | ||
// user has a name=id inside a form | ||
if(te && (te.attributes.id.value == id || te.id == id)){ | ||
return te; | ||
}else{ | ||
var eles = _d.all[id]; | ||
if(!eles || eles.nodeName){ | ||
eles = [eles]; | ||
} | ||
// if more than 1, choose first with the correct id | ||
var i = 0; | ||
while((te = eles[i++])){ | ||
if((te.attributes && te.attributes.id && te.attributes.id.value == id) || te.id == id){ | ||
return te; | ||
} | ||
} | ||
} | ||
}; | ||
}else{ | ||
dom.byId = function(id, doc){ | ||
// inline'd type check. | ||
// be sure to return null per documentation, to match IE branch. | ||
return ((typeof id == "string") ? (doc || win.doc).getElementById(id) : id) || null; // DOMNode | ||
}; | ||
} | ||
/*===== | ||
dom.byId = function(id, doc){ | ||
// summary: | ||
// Returns DOM node with matching `id` attribute or falsy value (ex: null or undefined) | ||
// if not found. If `id` is a DomNode, this function is a no-op. | ||
// | ||
// id: String|DOMNode | ||
// A string to match an HTML id attribute or a reference to a DOM Node | ||
// | ||
// doc: Document? | ||
// Document to work in. Defaults to the current value of | ||
// dojo/_base/window.doc. Can be used to retrieve | ||
// node references from other documents. | ||
// | ||
// example: | ||
// Look up a node by ID: | ||
// | require(["dojo/dom"], function(dom){ | ||
// | var n = dom.byId("foo"); | ||
// | }); | ||
// | ||
// example: | ||
// Check if a node exists, and use it. | ||
// | require(["dojo/dom"], function(dom){ | ||
// | var n = dom.byId("bar"); | ||
// | if(n){ doStuff() ... } | ||
// | }); | ||
// | ||
// example: | ||
// Allow string or DomNode references to be passed to a custom function: | ||
// | require(["dojo/dom"], function(dom){ | ||
// | var foo = function(nodeOrId){ | ||
// | nodeOrId = dom.byId(nodeOrId); | ||
// | // ... more stuff | ||
// | } | ||
// | }); | ||
}; | ||
=====*/ | ||
dom.isDescendant = function(/*DOMNode|String*/ node, /*DOMNode|String*/ ancestor){ | ||
// summary: | ||
// Returns true if node is a descendant of ancestor | ||
// node: DOMNode|String | ||
// string id or node reference to test | ||
// ancestor: DOMNode|String | ||
// string id or node reference of potential parent to test against | ||
// | ||
// example: | ||
// Test is node id="bar" is a descendant of node id="foo" | ||
// | require(["dojo/dom"], function(dom){ | ||
// | if(dom.isDescendant("bar", "foo")){ ... } | ||
// | }); | ||
try{ | ||
node = dom.byId(node); | ||
ancestor = dom.byId(ancestor); | ||
while(node){ | ||
if(node == ancestor){ | ||
return true; // Boolean | ||
} | ||
node = node.parentNode; | ||
} | ||
}catch(e){ /* squelch, return false */ } | ||
return false; // Boolean | ||
}; | ||
// TODO: do we need setSelectable in the base? | ||
// Add feature test for user-select CSS property | ||
// (currently known to work in all but IE < 10 and Opera) | ||
has.add("css-user-select", function(global, doc, element){ | ||
// Avoid exception when dom.js is loaded in non-browser environments | ||
if(!element){ return false; } | ||
var style = element.style; | ||
var prefixes = ["Khtml", "O", "ms", "Moz", "Webkit"], | ||
i = prefixes.length, | ||
name = "userSelect", | ||
prefix; | ||
// Iterate prefixes from most to least likely | ||
do{ | ||
if(typeof style[name] !== "undefined"){ | ||
// Supported; return property name | ||
return name; | ||
} | ||
}while(i-- && (name = prefixes[i] + "UserSelect")); | ||
// Not supported if we didn't return before now | ||
return false; | ||
}); | ||
/*===== | ||
dom.setSelectable = function(node, selectable){ | ||
// summary: | ||
// Enable or disable selection on a node | ||
// node: DOMNode|String | ||
// id or reference to node | ||
// selectable: Boolean | ||
// state to put the node in. false indicates unselectable, true | ||
// allows selection. | ||
// example: | ||
// Make the node id="bar" unselectable | ||
// | require(["dojo/dom"], function(dom){ | ||
// | dom.setSelectable("bar"); | ||
// | }); | ||
// example: | ||
// Make the node id="bar" selectable | ||
// | require(["dojo/dom"], function(dom){ | ||
// | dom.setSelectable("bar", true); | ||
// | }); | ||
}; | ||
=====*/ | ||
var cssUserSelect = has("css-user-select"); | ||
dom.setSelectable = cssUserSelect ? function(node, selectable){ | ||
// css-user-select returns a (possibly vendor-prefixed) CSS property name | ||
dom.byId(node).style[cssUserSelect] = selectable ? "" : "none"; | ||
} : function(node, selectable){ | ||
node = dom.byId(node); | ||
// (IE < 10 / Opera) Fall back to setting/removing the | ||
// unselectable attribute on the element and all its children | ||
var nodes = node.getElementsByTagName("*"), | ||
i = nodes.length; | ||
if(selectable){ | ||
node.removeAttribute("unselectable"); | ||
while(i--){ | ||
nodes[i].removeAttribute("unselectable"); | ||
} | ||
}else{ | ||
node.setAttribute("unselectable", "on"); | ||
while(i--){ | ||
nodes[i].setAttribute("unselectable", "on"); | ||
} | ||
} | ||
}; | ||
return dom; | ||
}); | ||
function get(id, doc) { | ||
if (typeof id !== 'string') { | ||
return id; | ||
} | ||
return (doc || document).getElementById(id); | ||
} | ||
exports.get = get; |
148
domReady.js
@@ -1,124 +0,48 @@ | ||
define(['./has'], function(has){ | ||
var global = this, | ||
doc = document, | ||
readyStates = { 'loaded': 1, 'complete': 1 }, | ||
fixReadyState = typeof doc.readyState != "string", | ||
ready = !!readyStates[doc.readyState], | ||
readyQ = [], | ||
recursiveGuard; | ||
var has = require('./has'); | ||
function domReady(callback){ | ||
// summary: | ||
// Plugin to delay require()/define() callback from firing until the DOM has finished loading. | ||
readyQ.push(callback); | ||
if(ready){ processQ(); } | ||
} | ||
domReady.load = function(id, req, load){ | ||
domReady(load); | ||
}; | ||
if (!has('host-browser')) { | ||
throw new Error('dojo/domReady makes no sense to load in a non-browser environment'); | ||
} | ||
// Export queue so that ready() can check if it's empty or not. | ||
domReady._Q = readyQ; | ||
domReady._onQEmpty = function(){ | ||
// summary: | ||
// Private method overridden by dojo/ready, to notify when everything in the | ||
// domReady queue has been processed. Do not use directly. | ||
// Will be removed in 2.0, along with domReady._Q. | ||
}; | ||
var readyStates = Object.create(null); | ||
readyStates.loaded = readyStates.complete = true; | ||
// For FF <= 3.5 | ||
if(fixReadyState){ doc.readyState = "loading"; } | ||
var ready = readyStates[document.readyState], readyQueue = [], processing = false; | ||
function processQ(){ | ||
// Calls all functions in the queue in order, unless processQ() is already running, in which case just return | ||
function processQueue() { | ||
if (processing) { | ||
return; | ||
} | ||
processing = true; | ||
if(recursiveGuard){ return; } | ||
recursiveGuard = true; | ||
for (var i = 0; i < readyQueue.length; i++) { | ||
readyQueue[i](document); | ||
} | ||
while(readyQ.length){ | ||
try{ | ||
(readyQ.shift())(doc); | ||
}catch(err){ | ||
console.log("Error on domReady callback: " + err); | ||
} | ||
} | ||
processing = false; | ||
} | ||
recursiveGuard = false; | ||
if (!ready) { | ||
document.addEventListener('DOMContentLoaded', function () { | ||
if (ready) { | ||
return; | ||
} | ||
// Notification for dojo/ready. Remove for 2.0. | ||
// Note that this could add more tasks to the ready queue. | ||
domReady._onQEmpty(); | ||
} | ||
ready = true; | ||
processQueue(); | ||
}); | ||
} | ||
if(!ready){ | ||
var tests = [], | ||
detectReady = function(evt){ | ||
evt = evt || global.event; | ||
if(ready || (evt.type == "readystatechange" && !readyStates[doc.readyState])){ return; } | ||
// For FF <= 3.5 | ||
if(fixReadyState){ doc.readyState = "complete"; } | ||
var domReady = function (callback) { | ||
readyQueue.push(callback); | ||
if (ready) { | ||
processQueue(); | ||
} | ||
}; | ||
ready = 1; | ||
processQ(); | ||
}, | ||
on = function(node, event){ | ||
node.addEventListener(event, detectReady, false); | ||
readyQ.push(function(){ node.removeEventListener(event, detectReady, false); }); | ||
}; | ||
domReady.load = function (resourceId, require, load) { | ||
domReady(load); | ||
}; | ||
if(!has("dom-addeventlistener")){ | ||
on = function(node, event){ | ||
event = "on" + event; | ||
node.attachEvent(event, detectReady); | ||
readyQ.push(function(){ node.detachEvent(event, detectReady); }); | ||
}; | ||
var div = doc.createElement("div"); | ||
try{ | ||
if(div.doScroll && global.frameElement === null){ | ||
// the doScroll test is only useful if we're in the top-most frame | ||
tests.push(function(){ | ||
// Derived with permission from Diego Perini's IEContentLoaded | ||
// http://javascript.nwbox.com/IEContentLoaded/ | ||
try{ | ||
div.doScroll("left"); | ||
return 1; | ||
}catch(e){} | ||
}); | ||
} | ||
}catch(e){} | ||
} | ||
on(doc, "DOMContentLoaded"); | ||
on(global, "load"); | ||
if("onreadystatechange" in doc){ | ||
on(doc, "readystatechange"); | ||
}else if(!fixReadyState){ | ||
// if the ready state property exists and there's | ||
// no readystatechange event, poll for the state | ||
// to change | ||
tests.push(function(){ | ||
return readyStates[doc.readyState]; | ||
}); | ||
} | ||
if(tests.length){ | ||
var poller = function(){ | ||
if(ready){ return; } | ||
var i = tests.length; | ||
while(i--){ | ||
if(tests[i]()){ | ||
detectReady("poller"); | ||
return; | ||
} | ||
} | ||
setTimeout(poller, 30); | ||
}; | ||
poller(); | ||
} | ||
} | ||
return domReady; | ||
}); | ||
module.exports = domReady; |
@@ -1,36 +0,35 @@ | ||
define(["./aspect", "./on"], function(aspect, on){ | ||
// module: | ||
// dojo/Evented | ||
var on = require('./on'); | ||
var aspect = require('./aspect'); | ||
"use strict"; | ||
var after = aspect.after; | ||
function Evented(){ | ||
// summary: | ||
// A class that can be used as a mixin or base class, | ||
// to add on() and emit() methods to a class | ||
// for listening for events and emitting events: | ||
// example: | ||
// | define(["dojo/Evented", "dojo/_base/declare", "dojo/Stateful" | ||
// | ], function(Evented, declare, Stateful){ | ||
// | var EventedStateful = declare([Evented, Stateful], {...}); | ||
// | var instance = new EventedStateful(); | ||
// | instance.on("open", function(event){ | ||
// | ... do something with event | ||
// | }); | ||
// | | ||
// | instance.emit("open", {name:"some event", ...}); | ||
} | ||
Evented.prototype = { | ||
on: function(type, listener){ | ||
return on.parse(this, type, listener, function(target, type){ | ||
return after(target, 'on' + type, listener, true); | ||
}); | ||
}, | ||
emit: function(type, event){ | ||
var args = [this]; | ||
args.push.apply(args, arguments); | ||
return on.emit.apply(on, args); | ||
} | ||
}; | ||
return Evented; | ||
}); | ||
var Evented = (function () { | ||
function Evented() { | ||
} | ||
Evented.prototype.on = function (type, listener) { | ||
var _this = this; | ||
return on.parse(this, type, listener, this, function (target, type) { | ||
var name = '__on' + type; | ||
if (!_this[name]) { | ||
Object.defineProperty(_this, name, { | ||
configurable: true, | ||
value: undefined, | ||
writable: true | ||
}); | ||
} | ||
return aspect.on(_this, '__on' + type, listener); | ||
}); | ||
}; | ||
Evented.prototype.emit = function (type) { | ||
var args = []; | ||
for (var _i = 0; _i < (arguments.length - 1); _i++) { | ||
args[_i] = arguments[_i + 1]; | ||
} | ||
type = '__on' + type; | ||
if (this[type]) { | ||
return this[type].apply(this, args); | ||
} | ||
}; | ||
return Evented; | ||
})(); | ||
module.exports = Evented; |
219
has.js
@@ -1,175 +0,68 @@ | ||
define(["require", "module"], function(require, module){ | ||
// module: | ||
// dojo/has | ||
// summary: | ||
// Defines the has.js API and several feature tests used by dojo. | ||
// description: | ||
// This module defines the has API as described by the project has.js with the following additional features: | ||
// | ||
// - the has test cache is exposed at has.cache. | ||
// - the method has.add includes a forth parameter that controls whether or not existing tests are replaced | ||
// - the loader's has cache may be optionally copied into this module's has cahce. | ||
// | ||
// This module adopted from https://github.com/phiggins42/has.js; thanks has.js team! | ||
// try to pull the has implementation from the loader; both the dojo loader and bdLoad provide one | ||
// if using a foreign loader, then the has cache may be initialized via the config object for this module | ||
// WARNING: if a foreign loader defines require.has to be something other than the has.js API, then this implementation fail | ||
var has = require.has || function(){}; | ||
if(!has("dojo-has-api")){ | ||
var | ||
isBrowser = | ||
// the most fundamental decision: are we in the browser? | ||
typeof window != "undefined" && | ||
typeof location != "undefined" && | ||
typeof document != "undefined" && | ||
window.location == location && window.document == document, | ||
/* tslint:enable:class-name */ | ||
var has = require.has; | ||
// has API variables | ||
global = this, | ||
doc = isBrowser && document, | ||
element = doc && doc.createElement("DiV"), | ||
cache = (module.config && module.config()) || {}; | ||
if (!has) { | ||
has = (function () { | ||
var hasCache = Object.create(null); | ||
var global = this; | ||
var document = global.document; | ||
var element = document && document.createElement('div'); | ||
has = function(name){ | ||
// summary: | ||
// Return the current value of the named feature. | ||
// | ||
// name: String|Integer | ||
// The name (if a string) or identifier (if an integer) of the feature to test. | ||
// | ||
// description: | ||
// Returns the value of the feature named by name. The feature must have been | ||
// previously added to the cache by has.add. | ||
var has = function (name) { | ||
return typeof hasCache[name] === 'function' ? (hasCache[name] = hasCache[name](global, document, element)) : hasCache[name]; | ||
}; | ||
return typeof cache[name] == "function" ? (cache[name] = cache[name](global, doc, element)) : cache[name]; // Boolean | ||
}; | ||
has.add = function (name, test, now, force) { | ||
(!(name in hasCache) || force) && (hasCache[name] = test); | ||
now && has(name); | ||
}; | ||
has.cache = cache; | ||
return has; | ||
})(); | ||
has.add = function(name, test, now, force){ | ||
// summary: | ||
// Register a new feature test for some named feature. | ||
// name: String|Integer | ||
// The name (if a string) or identifier (if an integer) of the feature to test. | ||
// test: Function | ||
// A test function to register. If a function, queued for testing until actually | ||
// needed. The test function should return a boolean indicating | ||
// the presence of a feature or bug. | ||
// now: Boolean? | ||
// Optional. Omit if `test` is not a function. Provides a way to immediately | ||
// run the test and cache the result. | ||
// force: Boolean? | ||
// Optional. If the test already exists and force is truthy, then the existing | ||
// test will be replaced; otherwise, add does not replace an existing test (that | ||
// is, by default, the first test advice wins). | ||
// example: | ||
// A redundant test, testFn with immediate execution: | ||
// | has.add("javascript", function(){ return true; }, true); | ||
// | ||
// example: | ||
// Again with the redundantness. You can do this in your tests, but we should | ||
// not be doing this in any internal has.js tests | ||
// | has.add("javascript", true); | ||
// | ||
// example: | ||
// Three things are passed to the testFunction. `global`, `document`, and a generic element | ||
// from which to work your test should the need arise. | ||
// | has.add("bug-byid", function(g, d, el){ | ||
// | // g == global, typically window, yadda yadda | ||
// | // d == document object | ||
// | // el == the generic element. a `has` element. | ||
// | return false; // fake test, byid-when-form-has-name-matching-an-id is slightly longer | ||
// | }); | ||
has.add('host-browser', typeof document !== 'undefined' && typeof location !== 'undefined'); | ||
has.add('host-node', typeof process === 'object' && process.versions && process.versions.node); | ||
has.add('debug', true); | ||
} | ||
(typeof cache[name]=="undefined" || force) && (cache[name]= test); | ||
return now && has(name); | ||
}; | ||
has.normalize = function (resourceId, normalize) { | ||
var tokens = resourceId.match(/[\?:]|[^:\?]*/g); | ||
// since we're operating under a loader that doesn't provide a has API, we must explicitly initialize | ||
// has as it would have otherwise been initialized by the dojo loader; use has.add to the builder | ||
// can optimize these away iff desired | ||
has.add("host-browser", isBrowser); | ||
has.add("host-node", (typeof process == "object" && process.versions && process.versions.node && process.versions.v8)); | ||
has.add("host-rhino", (typeof load == "function" && (typeof Packages == "function" || typeof Packages == "object"))); | ||
has.add("dom", isBrowser); | ||
has.add("dojo-dom-ready-api", 1); | ||
has.add("dojo-sniff", 1); | ||
} | ||
var i = 0; | ||
function get(skip) { | ||
var term = tokens[i++]; | ||
if (term === ':') { | ||
// empty string module name, resolves to 0 | ||
return null; | ||
} else { | ||
// postfixed with a ? means it is a feature to branch on, the term is the name of the feature | ||
if (tokens[i++] === '?') { | ||
if (!skip && has(term)) { | ||
// matched the feature, get the first value from the options | ||
return get(); | ||
} else { | ||
// did not match, get the second value, passing over the first | ||
get(true); | ||
return get(skip); | ||
} | ||
} | ||
if(has("host-browser")){ | ||
// Common application level tests | ||
has.add("dom-addeventlistener", !!document.addEventListener); | ||
has.add("touch", "ontouchstart" in document || window.navigator.msMaxTouchPoints > 0); | ||
// I don't know if any of these tests are really correct, just a rough guess | ||
has.add("device-width", screen.availWidth || innerWidth); | ||
// a module | ||
return term; | ||
} | ||
} | ||
// Tests for DOMNode.attributes[] behavior: | ||
// - dom-attributes-explicit - attributes[] only lists explicitly user specified attributes | ||
// - dom-attributes-specified-flag (IE8) - need to check attr.specified flag to skip attributes user didn't specify | ||
// - Otherwise, in IE6-7. attributes[] will list hundreds of values, so need to do outerHTML to get attrs instead. | ||
var form = document.createElement("form"); | ||
has.add("dom-attributes-explicit", form.attributes.length == 0); // W3C | ||
has.add("dom-attributes-specified-flag", form.attributes.length > 0 && form.attributes.length < 40); // IE8 | ||
} | ||
resourceId = get(); | ||
return resourceId && normalize(resourceId); | ||
}; | ||
has.clearElement = function(element){ | ||
// summary: | ||
// Deletes the contents of the element passed to test functions. | ||
element.innerHTML= ""; | ||
return element; | ||
}; | ||
has.load = function (resourceId, require, load) { | ||
if (resourceId) { | ||
require([resourceId], load); | ||
} else { | ||
load(); | ||
} | ||
}; | ||
has.normalize = function(id, toAbsMid){ | ||
// summary: | ||
// Resolves id into a module id based on possibly-nested tenary expression that branches on has feature test value(s). | ||
// | ||
// toAbsMid: Function | ||
// Resolves a relative module id into an absolute module id | ||
var | ||
tokens = id.match(/[\?:]|[^:\?]*/g), i = 0, | ||
get = function(skip){ | ||
var term = tokens[i++]; | ||
if(term == ":"){ | ||
// empty string module name, resolves to 0 | ||
return 0; | ||
}else{ | ||
// postfixed with a ? means it is a feature to branch on, the term is the name of the feature | ||
if(tokens[i++] == "?"){ | ||
if(!skip && has(term)){ | ||
// matched the feature, get the first value from the options | ||
return get(); | ||
}else{ | ||
// did not match, get the second value, passing over the first | ||
get(true); | ||
return get(skip); | ||
} | ||
} | ||
// a module | ||
return term || 0; | ||
} | ||
}; | ||
id = get(); | ||
return id && toAbsMid(id); | ||
}; | ||
has.load = function(id, parentRequire, loaded){ | ||
// summary: | ||
// Conditional loading of AMD modules based on a has feature test value. | ||
// id: String | ||
// Gives the resolved module id to load. | ||
// parentRequire: Function | ||
// The loader require function with respect to the module that contained the plugin resource in it's | ||
// dependency list. | ||
// loaded: Function | ||
// Callback to loader that consumes result of plugin demand. | ||
if(id){ | ||
parentRequire([id], loaded); | ||
}else{ | ||
loaded(); | ||
} | ||
}; | ||
return has; | ||
}); | ||
module.exports = has; |
132
io-query.js
@@ -1,97 +0,47 @@ | ||
define(["./_base/lang"], function(lang){ | ||
/** | ||
* @module dojo/io-query | ||
* | ||
* This module defines query string processing functions. | ||
*/ | ||
/** | ||
* Takes a name/value mapping object and returns a string representing a URL-encoded version of that object. | ||
* example: | ||
* this object: | ||
* | ||
* | { | ||
* | blah: "blah", | ||
* | multi: [ | ||
* | "thud", | ||
* | "thonk" | ||
* | ] | ||
* | }; | ||
* | ||
* yields the following query string: | ||
* | ||
* | "blah=blah&multi=thud&multi=thonk" | ||
*/ | ||
function objectToQuery(map) { | ||
var query = []; | ||
var value; | ||
// module: | ||
// dojo/io-query | ||
for (var key in map) { | ||
value = map[key]; | ||
var backstop = {}; | ||
key = encodeURIComponent(key); | ||
return { | ||
// summary: | ||
// This module defines query string processing functions. | ||
objectToQuery: function objectToQuery(/*Object*/ map){ | ||
// summary: | ||
// takes a name/value mapping object and returns a string representing | ||
// a URL-encoded version of that object. | ||
// example: | ||
// this object: | ||
// | ||
// | { | ||
// | blah: "blah", | ||
// | multi: [ | ||
// | "thud", | ||
// | "thonk" | ||
// | ] | ||
// | }; | ||
// | ||
// yields the following query string: | ||
// | ||
// | "blah=blah&multi=thud&multi=thonk" | ||
// FIXME: need to implement encodeAscii!! | ||
var enc = encodeURIComponent, pairs = []; | ||
for(var name in map){ | ||
var value = map[name]; | ||
if(value != backstop[name]){ | ||
var assign = enc(name) + "="; | ||
if(lang.isArray(value)){ | ||
for(var i = 0, l = value.length; i < l; ++i){ | ||
pairs.push(assign + enc(value[i])); | ||
} | ||
}else{ | ||
pairs.push(assign + enc(value)); | ||
} | ||
if (typeof value === 'boolean') { | ||
// Boolean properties are identified as true by their existence and do not have a corresponding | ||
// value | ||
value && query.push(key); | ||
} else if (Array.isArray(value)) { | ||
for (var i = 0, j = value.length; i < j; ++i) { | ||
query.push(key + '=' + encodeURIComponent(value[i])); | ||
} | ||
} else { | ||
query.push(key + '=' + encodeURIComponent(value)); | ||
} | ||
return pairs.join("&"); // String | ||
}, | ||
} | ||
queryToObject: function queryToObject(/*String*/ str){ | ||
// summary: | ||
// Create an object representing a de-serialized query section of a | ||
// URL. Query keys with multiple values are returned in an array. | ||
// | ||
// example: | ||
// This string: | ||
// | ||
// | "foo=bar&foo=baz&thinger=%20spaces%20=blah&zonk=blarg&" | ||
// | ||
// results in this object structure: | ||
// | ||
// | { | ||
// | foo: [ "bar", "baz" ], | ||
// | thinger: " spaces =blah", | ||
// | zonk: "blarg" | ||
// | } | ||
// | ||
// Note that spaces and other urlencoded entities are correctly | ||
// handled. | ||
// FIXME: should we grab the URL string if we're not passed one? | ||
var dec = decodeURIComponent, qp = str.split("&"), ret = {}, name, val; | ||
for(var i = 0, l = qp.length, item; i < l; ++i){ | ||
item = qp[i]; | ||
if(item.length){ | ||
var s = item.indexOf("="); | ||
if(s < 0){ | ||
name = dec(item); | ||
val = ""; | ||
}else{ | ||
name = dec(item.slice(0, s)); | ||
val = dec(item.slice(s + 1)); | ||
} | ||
if(typeof ret[name] == "string"){ // inline'd type check | ||
ret[name] = [ret[name]]; | ||
} | ||
if(lang.isArray(ret[name])){ | ||
ret[name].push(val); | ||
}else{ | ||
ret[name] = val; | ||
} | ||
} | ||
} | ||
return ret; // Object | ||
} | ||
}; | ||
}); | ||
return query.join('&'); | ||
} | ||
exports.objectToQuery = objectToQuery; |
110
node.js
@@ -1,62 +0,72 @@ | ||
define(["./has"], function(has){ | ||
if(!has("host-node")){ | ||
throw new Error("node plugin failed to load because environment is not Node.js"); | ||
} | ||
define([ 'require' ], function (require) { | ||
var nodeRequire = this.require && this.require.nodeRequire; | ||
var pathUtil; | ||
if(require.nodeRequire){ | ||
pathUtil = require.nodeRequire("path"); | ||
}else{ | ||
throw new Error("node plugin failed to load because it cannot find the original Node.js require"); | ||
if (!nodeRequire) { | ||
throw new Error('Cannot find the Node.js require'); | ||
} | ||
var module = nodeRequire('module'); | ||
/** | ||
* This AMD plugin module allows native Node.js modules to be loaded by AMD modules from within a compliant AMD | ||
* loader. This plugin will not work with AMD loaders that do not expose the Node.js require function at | ||
* `require.nodeRequire` (RequireJS, Dojo). | ||
* | ||
* @example | ||
* require([ 'dojo/node!fs' ], function (fs) { | ||
* var fileData = fs.readFileSync('foo.txt', 'utf-8'); | ||
* }); | ||
*/ | ||
return { | ||
// summary: | ||
// This AMD plugin module allows native Node.js modules to be loaded by AMD modules using the Dojo | ||
// loader. Note that this plugin will not work with AMD loaders other than the Dojo loader. | ||
// example: | ||
// | require(["dojo/node!fs"], function(fs){ | ||
// | var fileData = fs.readFileSync("foo.txt", "utf-8"); | ||
// | }); | ||
load: function (/**string*/ id, /**Function*/ contextRequire, /**Function*/ load) { | ||
/*global define:true */ | ||
load: function(/*string*/ id, /*Function*/ require, /*Function*/ load){ | ||
// summary: | ||
// Standard AMD plugin interface. See https://github.com/amdjs/amdjs-api/wiki/Loader-Plugins | ||
// for information. | ||
if(!require.nodeRequire){ | ||
throw new Error("Cannot find native require function"); | ||
// The `nodeRequire` function comes from the Node.js module of the AMD loader, so module ID resolution is | ||
// relative to the loader's path, not the calling AMD module's path. This means that loading Node.js | ||
// modules that exist in a higher level or sibling path to the loader will cause those modules to fail to | ||
// resolve. | ||
// | ||
// Node.js does not expose a public API for performing module filename resolution relative to an arbitrary | ||
// directory root, so we are forced to dig into the internal functions of the Node.js `module` module to | ||
// use Node.js's own path resolution code instead of having to duplicate its rules ourselves. | ||
// | ||
// Sooner or later, probably around the time that Node.js internal code is reworked to use ES6, these | ||
// methods will no longer be exposed and we will have to find another workaround if they have not exposed | ||
// an API for doing this by then. | ||
if (module._findPath && module._nodeModulePaths) { | ||
var localModulePath = module._findPath(id, module._nodeModulePaths(contextRequire.toUrl('.'))); | ||
if (localModulePath !== false) { | ||
id = localModulePath; | ||
} | ||
} | ||
load((function(id, require){ | ||
var oldDefine = define, | ||
result; | ||
var oldDefine = define; | ||
var result; | ||
// Some modules may attempt to detect an AMD loader via define and define.amd. This can cause issues | ||
// when other CommonJS modules attempt to load them via the standard node require(). If define is | ||
// temporarily moved into another variable, it will prevent modules from detecting AMD in this fashion. | ||
define = undefined; | ||
// Some modules attempt to detect an AMD loader by looking for global AMD `define`. This causes issues | ||
// when other CommonJS modules attempt to load them via the standard Node.js `require`, so hide it | ||
// during the load | ||
define = undefined; | ||
try{ | ||
result = require(id); | ||
}finally{ | ||
define = oldDefine; | ||
} | ||
return result; | ||
})(id, require.nodeRequire)); | ||
try { | ||
result = nodeRequire(id); | ||
} | ||
finally { | ||
define = oldDefine; | ||
} | ||
load(result); | ||
}, | ||
normalize: function (/**string*/ id, /*Function*/ normalize){ | ||
// summary: | ||
// Produces a normalized id to be used by node. Relative ids are resolved relative to the requesting | ||
// module's location in the file system and will return an id with path separators appropriate for the | ||
// local file system. | ||
if(id.charAt(0) === "."){ | ||
// dirname of the reference module - normalized to match the local file system | ||
var referenceModuleDirname = require.toUrl(normalize(".")).replace("/", pathUtil.sep), | ||
segments = id.split("/"); | ||
segments.unshift(referenceModuleDirname); | ||
// this will produce an absolute path normalized to the semantics of the underlying file system. | ||
id = pathUtil.join.apply(pathUtil, segments); | ||
/** | ||
* Produces a normalized CommonJS module ID to be used by Node.js `require`. Relative IDs are resolved relative | ||
* to the requesting module’s location in the filesystem and will return an ID with path separators appropriate | ||
* for the local filesystem. | ||
*/ | ||
normalize: function (/**string*/ id, /*Function*/ normalize) { | ||
if (id.charAt(0) === '.') { | ||
// absolute module IDs need to be generated based on the AMD loader's knowledge of the parent module, | ||
// since Node.js will try to use the directory containing `dojo.js` as the relative root if a | ||
// relative module ID is provided | ||
id = require.toUrl(normalize('./' + id)); | ||
} | ||
@@ -63,0 +73,0 @@ |
596
on.js
@@ -1,533 +0,77 @@ | ||
define(["./has!dom-addeventlistener?:./aspect", "./_base/kernel", "./sniff"], function(aspect, dojo, has){ | ||
"use strict"; | ||
if(has("dom")){ // check to make sure we are in a browser, this module should work anywhere | ||
var major = window.ScriptEngineMajorVersion; | ||
has.add("jscript", major && (major() + ScriptEngineMinorVersion() / 10)); | ||
has.add("event-orientationchange", has("touch") && !has("android")); // TODO: how do we detect this? | ||
has.add("event-stopimmediatepropagation", window.Event && !!window.Event.prototype && !!window.Event.prototype.stopImmediatePropagation); | ||
has.add("event-focusin", function(global, doc, element){ | ||
return 'onfocusin' in element; | ||
}); | ||
} | ||
var on = function(target, type, listener, dontFix){ | ||
// summary: | ||
// A function that provides core event listening functionality. With this function | ||
// you can provide a target, event type, and listener to be notified of | ||
// future matching events that are fired. | ||
// target: Element|Object | ||
// This is the target object or DOM element that to receive events from | ||
// type: String|Function | ||
// This is the name of the event to listen for or an extension event type. | ||
// listener: Function | ||
// This is the function that should be called when the event fires. | ||
// returns: Object | ||
// An object with a remove() method that can be used to stop listening for this | ||
// event. | ||
// description: | ||
// To listen for "click" events on a button node, we can do: | ||
// | define(["dojo/on"], function(listen){ | ||
// | on(button, "click", clickHandler); | ||
// | ... | ||
// Evented JavaScript objects can also have their own events. | ||
// | var obj = new Evented; | ||
// | on(obj, "foo", fooHandler); | ||
// And then we could publish a "foo" event: | ||
// | on.emit(obj, "foo", {key: "value"}); | ||
// We can use extension events as well. For example, you could listen for a tap gesture: | ||
// | define(["dojo/on", "dojo/gesture/tap", function(listen, tap){ | ||
// | on(button, tap, tapHandler); | ||
// | ... | ||
// which would trigger fooHandler. Note that for a simple object this is equivalent to calling: | ||
// | obj.onfoo({key:"value"}); | ||
// If you use on.emit on a DOM node, it will use native event dispatching when possible. | ||
function noop() { | ||
} | ||
if(typeof target.on == "function" && typeof type != "function" && !target.nodeType){ | ||
// delegate to the target's on() method, so it can handle it's own listening if it wants (unless it | ||
// is DOM node and we may be dealing with jQuery or Prototype's incompatible addition to the | ||
// Element prototype | ||
return target.on(type, listener); | ||
} | ||
// delegate to main listener code | ||
return on.parse(target, type, listener, addListener, dontFix, this); | ||
}; | ||
on.pausable = function(target, type, listener, dontFix){ | ||
// summary: | ||
// This function acts the same as on(), but with pausable functionality. The | ||
// returned signal object has pause() and resume() functions. Calling the | ||
// pause() method will cause the listener to not be called for future events. Calling the | ||
// resume() method will cause the listener to again be called for future events. | ||
var paused; | ||
var signal = on(target, type, function(){ | ||
if(!paused){ | ||
return listener.apply(this, arguments); | ||
} | ||
}, dontFix); | ||
signal.pause = function(){ | ||
paused = true; | ||
}; | ||
signal.resume = function(){ | ||
paused = false; | ||
}; | ||
return signal; | ||
}; | ||
on.once = function(target, type, listener, dontFix){ | ||
// summary: | ||
// This function acts the same as on(), but will only call the listener once. The | ||
// listener will be called for the first | ||
// event that takes place and then listener will automatically be removed. | ||
var signal = on(target, type, function(){ | ||
// remove this listener | ||
signal.remove(); | ||
// proceed to call the listener | ||
return listener.apply(this, arguments); | ||
}); | ||
return signal; | ||
}; | ||
on.parse = function(target, type, listener, addListener, dontFix, matchesTarget){ | ||
if(type.call){ | ||
// event handler function | ||
// on(node, touch.press, touchListener); | ||
return type.call(matchesTarget, target, listener); | ||
} | ||
function addListener(target, type, listener, capture) { | ||
if (target.addEventListener) { | ||
target.addEventListener(type, listener, capture); | ||
if(type.indexOf(",") > -1){ | ||
// we allow comma delimited event names, so you can register for multiple events at once | ||
var events = type.split(/\s*,\s*/); | ||
var handles = []; | ||
var i = 0; | ||
var eventName; | ||
while(eventName = events[i++]){ | ||
handles.push(addListener(target, eventName, listener, dontFix, matchesTarget)); | ||
} | ||
handles.remove = function(){ | ||
for(var i = 0; i < handles.length; i++){ | ||
handles[i].remove(); | ||
} | ||
}; | ||
return handles; | ||
} | ||
return addListener(target, type, listener, dontFix, matchesTarget); | ||
}; | ||
var touchEvents = /^touch/; | ||
function addListener(target, type, listener, dontFix, matchesTarget){ | ||
// event delegation: | ||
var selector = type.match(/(.*):(.*)/); | ||
// if we have a selector:event, the last one is interpreted as an event, and we use event delegation | ||
if(selector){ | ||
type = selector[2]; | ||
selector = selector[1]; | ||
// create the extension event for selectors and directly call it | ||
return on.selector(selector, type).call(matchesTarget, target, listener); | ||
} | ||
// test to see if it a touch event right now, so we don't have to do it every time it fires | ||
if(has("touch")){ | ||
if(touchEvents.test(type)){ | ||
// touch event, fix it | ||
listener = fixTouchListener(listener); | ||
} | ||
if(!has("event-orientationchange") && (type == "orientationchange")){ | ||
//"orientationchange" not supported <= Android 2.1, | ||
//but works through "resize" on window | ||
type = "resize"; | ||
target = window; | ||
listener = fixTouchListener(listener); | ||
} | ||
} | ||
if(addStopImmediate){ | ||
// add stopImmediatePropagation if it doesn't exist | ||
listener = addStopImmediate(listener); | ||
} | ||
// normal path, the target is |this| | ||
if(target.addEventListener){ | ||
// the target has addEventListener, which should be used if available (might or might not be a node, non-nodes can implement this method as well) | ||
// check for capture conversions | ||
var capture = type in captures, | ||
adjustedType = capture ? captures[type] : type; | ||
target.addEventListener(adjustedType, listener, capture); | ||
// create and return the signal | ||
return { | ||
remove: function(){ | ||
target.removeEventListener(adjustedType, listener, capture); | ||
} | ||
}; | ||
} | ||
type = "on" + type; | ||
if(fixAttach && target.attachEvent){ | ||
return fixAttach(target, type, listener); | ||
} | ||
throw new Error("Target must be an event emitter"); | ||
} | ||
return { | ||
remove: function () { | ||
this.remove = noop; | ||
target.removeEventListener(type, listener, capture); | ||
target = listener = null; | ||
} | ||
}; | ||
} | ||
on.selector = function(selector, eventType, children){ | ||
// summary: | ||
// Creates a new extension event with event delegation. This is based on | ||
// the provided event type (can be extension event) that | ||
// only calls the listener when the CSS selector matches the target of the event. | ||
// | ||
// The application must require() an appropriate level of dojo/query to handle the selector. | ||
// selector: | ||
// The CSS selector to use for filter events and determine the |this| of the event listener. | ||
// eventType: | ||
// The event to listen for | ||
// children: | ||
// Indicates if children elements of the selector should be allowed. This defaults to | ||
// true | ||
// example: | ||
// | require(["dojo/on", "dojo/mouse", "dojo/query!css2"], function(listen, mouse){ | ||
// | on(node, on.selector(".my-class", mouse.enter), handlerForMyHover); | ||
return function(target, listener){ | ||
// if the selector is function, use it to select the node, otherwise use the matches method | ||
var matchesTarget = typeof selector == "function" ? {matches: selector} : this, | ||
bubble = eventType.bubble; | ||
function select(eventTarget){ | ||
// see if we have a valid matchesTarget or default to dojo/query | ||
matchesTarget = matchesTarget && matchesTarget.matches ? matchesTarget : dojo.query; | ||
// there is a selector, so make sure it matches | ||
while(!matchesTarget.matches(eventTarget, selector, target)){ | ||
if(eventTarget == target || children === false || !(eventTarget = eventTarget.parentNode) || eventTarget.nodeType != 1){ // intentional assignment | ||
return; | ||
} | ||
} | ||
return eventTarget; | ||
} | ||
if(bubble){ | ||
// the event type doesn't naturally bubble, but has a bubbling form, use that, and give it the selector so it can perform the select itself | ||
return on(target, bubble(select), listener); | ||
} | ||
// standard event delegation | ||
return on(target, eventType, function(event){ | ||
// call select to see if we match | ||
var eventTarget = select(event.target); | ||
// if it matches we call the listener | ||
return eventTarget && listener.call(eventTarget, event); | ||
}); | ||
}; | ||
}; | ||
throw new Error('Target must be an event emitter'); | ||
} | ||
function syntheticPreventDefault(){ | ||
this.cancelable = false; | ||
this.defaultPrevented = true; | ||
} | ||
function syntheticStopPropagation(){ | ||
this.bubbles = false; | ||
} | ||
var slice = [].slice, | ||
syntheticDispatch = on.emit = function(target, type, event){ | ||
// summary: | ||
// Fires an event on the target object. | ||
// target: | ||
// The target object to fire the event on. This can be a DOM element or a plain | ||
// JS object. If the target is a DOM element, native event emitting mechanisms | ||
// are used when possible. | ||
// type: | ||
// The event type name. You can emulate standard native events like "click" and | ||
// "mouseover" or create custom events like "open" or "finish". | ||
// event: | ||
// An object that provides the properties for the event. See https://developer.mozilla.org/en/DOM/event.initEvent | ||
// for some of the properties. These properties are copied to the event object. | ||
// Of particular importance are the cancelable and bubbles properties. The | ||
// cancelable property indicates whether or not the event has a default action | ||
// that can be cancelled. The event is cancelled by calling preventDefault() on | ||
// the event object. The bubbles property indicates whether or not the | ||
// event will bubble up the DOM tree. If bubbles is true, the event will be called | ||
// on the target and then each parent successively until the top of the tree | ||
// is reached or stopPropagation() is called. Both bubbles and cancelable | ||
// default to false. | ||
// returns: | ||
// If the event is cancelable and the event is not cancelled, | ||
// emit will return true. If the event is cancelable and the event is cancelled, | ||
// emit will return false. | ||
// details: | ||
// Note that this is designed to emit events for listeners registered through | ||
// dojo/on. It should actually work with any event listener except those | ||
// added through IE's attachEvent (IE8 and below's non-W3C event emitting | ||
// doesn't support custom event types). It should work with all events registered | ||
// through dojo/on. Also note that the emit method does do any default | ||
// action, it only returns a value to indicate if the default action should take | ||
// place. For example, emitting a keypress event would not cause a character | ||
// to appear in a textbox. | ||
// example: | ||
// To fire our own click event | ||
// | require(["dojo/on", "dojo/dom" | ||
// | ], function(on, dom){ | ||
// | on.emit(dom.byId("button"), "click", { | ||
// | cancelable: true, | ||
// | bubbles: true, | ||
// | screenX: 33, | ||
// | screenY: 44 | ||
// | }); | ||
// We can also fire our own custom events: | ||
// | on.emit(dom.byId("slider"), "slide", { | ||
// | cancelable: true, | ||
// | bubbles: true, | ||
// | direction: "left-to-right" | ||
// | }); | ||
// | }); | ||
var args = slice.call(arguments, 2); | ||
var method = "on" + type; | ||
if("parentNode" in target){ | ||
// node (or node-like), create event controller methods | ||
var newEvent = args[0] = {}; | ||
for(var i in event){ | ||
newEvent[i] = event[i]; | ||
} | ||
newEvent.preventDefault = syntheticPreventDefault; | ||
newEvent.stopPropagation = syntheticStopPropagation; | ||
newEvent.target = target; | ||
newEvent.type = type; | ||
event = newEvent; | ||
} | ||
do{ | ||
// call any node which has a handler (note that ideally we would try/catch to simulate normal event propagation but that causes too much pain for debugging) | ||
target[method] && target[method].apply(target, args); | ||
// and then continue up the parent node chain if it is still bubbling (if started as bubbles and stopPropagation hasn't been called) | ||
}while(event && event.bubbles && (target = target.parentNode)); | ||
return event && event.cancelable && event; // if it is still true (was cancelable and was cancelled), return the event to indicate default action should happen | ||
}; | ||
var captures = has("event-focusin") ? {} : {focusin: "focus", focusout: "blur"}; | ||
if(!has("event-stopimmediatepropagation")){ | ||
var stopImmediatePropagation =function(){ | ||
this.immediatelyStopped = true; | ||
this.modified = true; // mark it as modified so the event will be cached in IE | ||
}; | ||
var addStopImmediate = function(listener){ | ||
return function(event){ | ||
if(!event.immediatelyStopped){// check to make sure it hasn't been stopped immediately | ||
event.stopImmediatePropagation = stopImmediatePropagation; | ||
return listener.apply(this, arguments); | ||
} | ||
}; | ||
} | ||
} | ||
if(has("dom-addeventlistener")){ | ||
// emitter that works with native event handling | ||
on.emit = function(target, type, event){ | ||
if(target.dispatchEvent && document.createEvent){ | ||
// use the native event emitting mechanism if it is available on the target object | ||
// create a generic event | ||
// we could create branch into the different types of event constructors, but | ||
// that would be a lot of extra code, with little benefit that I can see, seems | ||
// best to use the generic constructor and copy properties over, making it | ||
// easy to have events look like the ones created with specific initializers | ||
var ownerDocument = target.ownerDocument || document; | ||
var nativeEvent = ownerDocument.createEvent("HTMLEvents"); | ||
nativeEvent.initEvent(type, !!event.bubbles, !!event.cancelable); | ||
// and copy all our properties over | ||
for(var i in event){ | ||
if(!(i in nativeEvent)){ | ||
nativeEvent[i] = event[i]; | ||
} | ||
} | ||
return target.dispatchEvent(nativeEvent) && nativeEvent; | ||
} | ||
return syntheticDispatch.apply(on, arguments); // emit for a non-node | ||
}; | ||
}else{ | ||
// no addEventListener, basically old IE event normalization | ||
on._fixEvent = function(evt, sender){ | ||
// summary: | ||
// normalizes properties on the event object including event | ||
// bubbling methods, keystroke normalization, and x/y positions | ||
// evt: | ||
// native event object | ||
// sender: | ||
// node to treat as "currentTarget" | ||
if(!evt){ | ||
var w = sender && (sender.ownerDocument || sender.document || sender).parentWindow || window; | ||
evt = w.event; | ||
} | ||
if(!evt){return evt;} | ||
try{ | ||
if(lastEvent && evt.type == lastEvent.type && evt.srcElement == lastEvent.target){ | ||
// should be same event, reuse event object (so it can be augmented); | ||
// accessing evt.srcElement rather than evt.target since evt.target not set on IE until fixup below | ||
evt = lastEvent; | ||
} | ||
}catch(e){ | ||
// will occur on IE on lastEvent.type reference if lastEvent points to a previous event that already | ||
// finished bubbling, but the setTimeout() to clear lastEvent hasn't fired yet | ||
} | ||
if(!evt.target){ // check to see if it has been fixed yet | ||
evt.target = evt.srcElement; | ||
evt.currentTarget = (sender || evt.srcElement); | ||
if(evt.type == "mouseover"){ | ||
evt.relatedTarget = evt.fromElement; | ||
} | ||
if(evt.type == "mouseout"){ | ||
evt.relatedTarget = evt.toElement; | ||
} | ||
if(!evt.stopPropagation){ | ||
evt.stopPropagation = stopPropagation; | ||
evt.preventDefault = preventDefault; | ||
} | ||
switch(evt.type){ | ||
case "keypress": | ||
var c = ("charCode" in evt ? evt.charCode : evt.keyCode); | ||
if (c==10){ | ||
// CTRL-ENTER is CTRL-ASCII(10) on IE, but CTRL-ENTER on Mozilla | ||
c=0; | ||
evt.keyCode = 13; | ||
}else if(c==13||c==27){ | ||
c=0; // Mozilla considers ENTER and ESC non-printable | ||
}else if(c==3){ | ||
c=99; // Mozilla maps CTRL-BREAK to CTRL-c | ||
} | ||
// Mozilla sets keyCode to 0 when there is a charCode | ||
// but that stops the event on IE. | ||
evt.charCode = c; | ||
_setKeyChar(evt); | ||
break; | ||
} | ||
} | ||
return evt; | ||
}; | ||
var lastEvent, IESignal = function(handle){ | ||
this.handle = handle; | ||
}; | ||
IESignal.prototype.remove = function(){ | ||
delete _dojoIEListeners_[this.handle]; | ||
}; | ||
var fixListener = function(listener){ | ||
// this is a minimal function for closing on the previous listener with as few as variables as possible | ||
return function(evt){ | ||
evt = on._fixEvent(evt, this); | ||
var result = listener.call(this, evt); | ||
if(evt.modified){ | ||
// cache the last event and reuse it if we can | ||
if(!lastEvent){ | ||
setTimeout(function(){ | ||
lastEvent = null; | ||
}); | ||
} | ||
lastEvent = evt; | ||
} | ||
return result; | ||
}; | ||
}; | ||
var fixAttach = function(target, type, listener){ | ||
listener = fixListener(listener); | ||
if(((target.ownerDocument ? target.ownerDocument.parentWindow : target.parentWindow || target.window || window) != top || | ||
has("jscript") < 5.8) && | ||
!has("config-_allow_leaks")){ | ||
// IE will leak memory on certain handlers in frames (IE8 and earlier) and in unattached DOM nodes for JScript 5.7 and below. | ||
// Here we use global redirection to solve the memory leaks | ||
if(typeof _dojoIEListeners_ == "undefined"){ | ||
_dojoIEListeners_ = []; | ||
} | ||
var emitter = target[type]; | ||
if(!emitter || !emitter.listeners){ | ||
var oldListener = emitter; | ||
emitter = Function('event', 'var callee = arguments.callee; for(var i = 0; i<callee.listeners.length; i++){var listener = _dojoIEListeners_[callee.listeners[i]]; if(listener){listener.call(this,event);}}'); | ||
emitter.listeners = []; | ||
target[type] = emitter; | ||
emitter.global = this; | ||
if(oldListener){ | ||
emitter.listeners.push(_dojoIEListeners_.push(oldListener) - 1); | ||
} | ||
} | ||
var handle; | ||
emitter.listeners.push(handle = (emitter.global._dojoIEListeners_.push(listener) - 1)); | ||
return new IESignal(handle); | ||
} | ||
return aspect.after(target, type, listener, true); | ||
}; | ||
var on = function (target, type, listener, capture) { | ||
if (typeof target.on === 'function' && typeof type !== 'function' && !target.nodeType) { | ||
return target.on(type, listener, capture); | ||
} | ||
var _setKeyChar = function(evt){ | ||
evt.keyChar = evt.charCode ? String.fromCharCode(evt.charCode) : ''; | ||
evt.charOrCode = evt.keyChar || evt.keyCode; | ||
}; | ||
// Called in Event scope | ||
var stopPropagation = function(){ | ||
this.cancelBubble = true; | ||
}; | ||
var preventDefault = on._preventDefault = function(){ | ||
// Setting keyCode to 0 is the only way to prevent certain keypresses (namely | ||
// ctrl-combinations that correspond to menu accelerator keys). | ||
// Otoh, it prevents upstream listeners from getting this information | ||
// Try to split the difference here by clobbering keyCode only for ctrl | ||
// combinations. If you still need to access the key upstream, bubbledKeyCode is | ||
// provided as a workaround. | ||
this.bubbledKeyCode = this.keyCode; | ||
if(this.ctrlKey){ | ||
try{ | ||
// squelch errors when keyCode is read-only | ||
// (e.g. if keyCode is ctrl or shift) | ||
this.keyCode = 0; | ||
}catch(e){ | ||
} | ||
} | ||
this.defaultPrevented = true; | ||
this.returnValue = false; | ||
this.modified = true; // mark it as modified (for defaultPrevented flag) so the event will be cached in IE | ||
}; | ||
} | ||
if(has("touch")){ | ||
var Event = function(){}; | ||
var windowOrientation = window.orientation; | ||
var fixTouchListener = function(listener){ | ||
return function(originalEvent){ | ||
//Event normalization(for ontouchxxx and resize): | ||
//1.incorrect e.pageX|pageY in iOS | ||
//2.there are no "e.rotation", "e.scale" and "onorientationchange" in Android | ||
//3.More TBD e.g. force | screenX | screenX | clientX | clientY | radiusX | radiusY | ||
return on.parse(target, type, listener, this, addListener, capture); | ||
}; | ||
// see if it has already been corrected | ||
var event = originalEvent.corrected; | ||
if(!event){ | ||
var type = originalEvent.type; | ||
try{ | ||
delete originalEvent.type; // on some JS engines (android), deleting properties make them mutable | ||
}catch(e){} | ||
if(originalEvent.type){ | ||
// deleting properties doesn't work (older iOS), have to use delegation | ||
if(has('mozilla')){ | ||
// Firefox doesn't like delegated properties, so we have to copy | ||
var event = {}; | ||
for(var name in originalEvent){ | ||
event[name] = originalEvent[name]; | ||
} | ||
}else{ | ||
// old iOS branch | ||
Event.prototype = originalEvent; | ||
var event = new Event; | ||
} | ||
// have to delegate methods to make them work | ||
event.preventDefault = function(){ | ||
originalEvent.preventDefault(); | ||
}; | ||
event.stopPropagation = function(){ | ||
originalEvent.stopPropagation(); | ||
}; | ||
}else{ | ||
// deletion worked, use property as is | ||
event = originalEvent; | ||
event.type = type; | ||
} | ||
originalEvent.corrected = event; | ||
if(type == 'resize'){ | ||
if(windowOrientation == window.orientation){ | ||
return null;//double tap causes an unexpected 'resize' in Android | ||
} | ||
windowOrientation = window.orientation; | ||
event.type = "orientationchange"; | ||
return listener.call(this, event); | ||
} | ||
// We use the original event and augment, rather than doing an expensive mixin operation | ||
if(!("rotation" in event)){ // test to see if it has rotation | ||
event.rotation = 0; | ||
event.scale = 1; | ||
} | ||
//use event.changedTouches[0].pageX|pageY|screenX|screenY|clientX|clientY|target | ||
var firstChangeTouch = event.changedTouches[0]; | ||
for(var i in firstChangeTouch){ // use for-in, we don't need to have dependency on dojo/_base/lang here | ||
delete event[i]; // delete it first to make it mutable | ||
event[i] = firstChangeTouch[i]; | ||
} | ||
} | ||
return listener.call(this, event); | ||
}; | ||
}; | ||
} | ||
return on; | ||
}); | ||
on.parse = function (target, type, listener, context, addListener, capture) { | ||
// `type` is ExtensionEvent | ||
if (type.call) { | ||
return type.call(context, target, listener, capture); | ||
} | ||
if (type.indexOf(',') > -1) { | ||
var events = type.split(/\s*,\s*/); | ||
var handles = events.map(function (type) { | ||
return addListener(target, type, listener, capture); | ||
}); | ||
return { | ||
remove: function () { | ||
this.remove = noop; | ||
var handle; | ||
while ((handle = handles.pop())) { | ||
handle.remove(); | ||
} | ||
} | ||
}; | ||
} | ||
return addListener(target, type, listener, capture); | ||
}; | ||
on.emit = function (target, type, event) { | ||
// `target` is not a DOM node | ||
if (typeof target.emit === 'function' && !target.nodeType) { | ||
return target.emit(type, event); | ||
} | ||
if (target.dispatchEvent && target.ownerDocument && target.ownerDocument.createEvent) { | ||
var nativeEvent = target.ownerDocument.createEvent('HTMLEvents'); | ||
nativeEvent.initEvent(type, Boolean(event.bubbles), Boolean(event.cancelable)); | ||
for (var key in event) { | ||
if (!(key in nativeEvent)) { | ||
nativeEvent[key] = event[key]; | ||
} | ||
} | ||
return target.dispatchEvent(nativeEvent); | ||
} | ||
throw new Error('Target must be an event emitter'); | ||
}; | ||
module.exports = on; |
{ | ||
"name": "dojo", | ||
"version":"1.9.3", | ||
"directories": { | ||
"lib": "." | ||
}, | ||
"main": "main", | ||
"description": "Dojo core is a powerful, lightweight library that makes common tasks quicker and easier. Animate elements, manipulate the DOM, and query with easy CSS syntax, all without sacrificing performance.", | ||
"licenses": [ | ||
{ | ||
"type": "AFLv2.1", | ||
"url": "http://trac.dojotoolkit.org/browser/dojo/trunk/LICENSE#L43" | ||
}, | ||
{ | ||
"type": "BSD", | ||
"url": "http://trac.dojotoolkit.org/browser/dojo/trunk/LICENSE#L13" | ||
} | ||
], | ||
"bugs": "http://bugs.dojotoolkit.org/", | ||
"keywords": ["JavaScript", "Dojo", "Toolkit"], | ||
"homepage": "http://dojotoolkit.org/", | ||
"dojoBuild": "dojo.profile.js" | ||
"name": "dojo", | ||
"version": "2.0.0-alpha1", | ||
"scripts": { | ||
"prepublish": "support/prepublish.sh" | ||
}, | ||
"devDependencies": { | ||
"typescript": "1.0.1", | ||
"grunt": "0.4.1", | ||
"grunt-contrib-clean": "0.5.0", | ||
"grunt-contrib-watch": "0.5.3", | ||
"intern": "1.7.0", | ||
"grunt-ts": "1.6.4", | ||
"lodash": "2.4.1", | ||
"globule": "0.2.0" | ||
} | ||
} |
130
request.js
@@ -1,81 +0,53 @@ | ||
define([ | ||
'./request/default!'/*=====, | ||
'./_base/declare', | ||
'./promise/Promise' =====*/ | ||
], function(request/*=====, declare, Promise =====*/){ | ||
/*===== | ||
request = function(url, options){ | ||
// summary: | ||
// Send a request using the default transport for the current platform. | ||
// url: String | ||
// The URL to request. | ||
// options: dojo/request.__Options? | ||
// Options for the request. | ||
// returns: dojo/request.__Promise | ||
}; | ||
request.__Promise = declare(Promise, { | ||
// response: dojo/promise/Promise | ||
// A promise resolving to an object representing | ||
// the response from the server. | ||
}); | ||
request.__BaseOptions = declare(null, { | ||
// query: String|Object? | ||
// Query parameters to append to the URL. | ||
// data: String|Object? | ||
// Data to transfer. This is ignored for GET and DELETE | ||
// requests. | ||
// preventCache: Boolean? | ||
// Whether to append a cache-busting parameter to the URL. | ||
// timeout: Integer? | ||
// Milliseconds to wait for the response. If this time | ||
// passes, the then the promise is rejected. | ||
// handleAs: String? | ||
// How to handle the response from the server. Default is | ||
// 'text'. Other values are 'json', 'javascript', and 'xml'. | ||
}); | ||
request.__MethodOptions = declare(null, { | ||
// method: String? | ||
// The HTTP method to use to make the request. Must be | ||
// uppercase. | ||
}); | ||
request.__Options = declare([request.__BaseOptions, request.__MethodOptions]); | ||
request.get = function(url, options){ | ||
// summary: | ||
// Send an HTTP GET request using the default transport for the current platform. | ||
// url: String | ||
// URL to request | ||
// options: dojo/request.__BaseOptions? | ||
// Options for the request. | ||
// returns: dojo/request.__Promise | ||
}; | ||
request.post = function(url, options){ | ||
// summary: | ||
// Send an HTTP POST request using the default transport for the current platform. | ||
// url: String | ||
// URL to request | ||
// options: dojo/request.__BaseOptions? | ||
// Options for the request. | ||
// returns: dojo/request.__Promise | ||
}; | ||
request.put = function(url, options){ | ||
// summary: | ||
// Send an HTTP POST request using the default transport for the current platform. | ||
// url: String | ||
// URL to request | ||
// options: dojo/request.__BaseOptions? | ||
// Options for the request. | ||
// returns: dojo/request.__Promise | ||
}; | ||
request.del = function(url, options){ | ||
// summary: | ||
// Send an HTTP DELETE request using the default transport for the current platform. | ||
// url: String | ||
// URL to request | ||
// options: dojo/request.__BaseOptions? | ||
// Options for the request. | ||
// returns: dojo/request.__Promise | ||
}; | ||
=====*/ | ||
return request; | ||
var has = require('./has'); | ||
var Promise = require('./Promise'); | ||
var Registry = require('./Registry'); | ||
var defaultProvider; | ||
if (has('host-node')) { | ||
defaultProvider = require('./request/node'); | ||
} else if (has('host-browser')) { | ||
defaultProvider = require('./request/xhr'); | ||
} | ||
var request = function (url, options) { | ||
var args = Array.prototype.slice.call(arguments, 0); | ||
var promise = request.providerRegistry.match(arguments).apply(null, arguments).then(function (response) { | ||
args.unshift(response); | ||
return Promise.resolve(request.filterRegistry.match(args).apply(null, args)).then(function (filterResponse) { | ||
response.data = filterResponse.data; | ||
return response; | ||
}); | ||
}); | ||
promise.data = promise.then(function (response) { | ||
return response.data; | ||
}); | ||
return promise; | ||
}; | ||
request.providerRegistry = new Registry(defaultProvider); | ||
request.filterRegistry = new Registry(function (response) { | ||
return response; | ||
}); | ||
// TODO: Put somewhere permanent | ||
request.filterRegistry.register(function (response, url, options) { | ||
return typeof response.data === 'string' && options.responseType === 'json'; | ||
}, function (response, url, options) { | ||
return JSON.parse(response.data); | ||
}); | ||
['delete', 'get', 'post', 'put'].forEach(function (method) { | ||
request[method] = function (url, options) { | ||
options = Object.create(options); | ||
options.method = method.toUpperCase(); | ||
return request(url, options); | ||
}; | ||
}); | ||
module.exports = request; |
@@ -1,195 +0,159 @@ | ||
define([ | ||
'require', | ||
'./util', | ||
'./handlers', | ||
'../errors/RequestTimeoutError', | ||
'../node!http', | ||
'../node!https', | ||
'../node!url', | ||
'../node!stream'/*=====, | ||
'../request', | ||
'../_base/declare' =====*/ | ||
], function(require, util, handlers, RequestTimeoutError, http, https, URL, stream/*=====, request, declare =====*/){ | ||
var Stream = stream.Stream, | ||
undefined; | ||
var http = require('http'); | ||
var https = require('https'); | ||
var kernel = require('../kernel'); | ||
var Promise = require('../Promise'); | ||
var defaultOptions = { | ||
method: 'GET', | ||
query: null, | ||
data: undefined, | ||
headers: {} | ||
}; | ||
function node(url, options){ | ||
var response = util.parseArgs(url, util.deepCreate(defaultOptions, options), options && options.data instanceof Stream); | ||
url = response.url; | ||
options = response.options; | ||
var urlUtil = require('url'); | ||
var def = util.deferred( | ||
response, | ||
function(dfd, response){ | ||
response.clientRequest.abort(); | ||
} | ||
); | ||
function normalizeHeaders(headers) { | ||
var normalizedHeaders = {}; | ||
for (var key in headers) { | ||
normalizedHeaders[key.toLowerCase()] = headers[key]; | ||
} | ||
url = URL.parse(url); | ||
return normalizedHeaders; | ||
} | ||
var reqOptions = response.requestOptions = { | ||
hostname: url.hostname, | ||
port: url.port, | ||
socketPath: options.socketPath, | ||
method: options.method, | ||
headers: options.headers, | ||
agent: options.agent, | ||
pfx: options.pfx, | ||
key: options.key, | ||
passphrase: options.passphrase, | ||
cert: options.cert, | ||
ca: options.ca, | ||
ciphers: options.ciphers, | ||
rejectUnauthorized: options.rejectUnauthorized === false ? false : true | ||
}; | ||
if(url.path){ | ||
reqOptions.path = url.path; | ||
} | ||
if(options.user || options.password){ | ||
reqOptions.auth = (options.user||'') + ':' + (options.password||''); | ||
} | ||
var req = response.clientRequest = (url.protocol === 'https:' ? https : http).request(reqOptions); | ||
function node(url, options) { | ||
var deferred = new Promise.Deferred(function (reason) { | ||
request && request.abort(); | ||
throw reason; | ||
}); | ||
var promise = deferred.promise; | ||
var parsedUrl = urlUtil.parse(options.proxy || url); | ||
if(options.socketOptions){ | ||
if('timeout' in options.socketOptions){ | ||
req.setTimeout(options.socketOptions.timeout); | ||
} | ||
if('noDelay' in options.socketOptions){ | ||
req.setNoDelay(options.socketOptions.noDelay); | ||
} | ||
if('keepAlive' in options.socketOptions){ | ||
var initialDelay = options.socketOptions.keepAlive; | ||
req.setKeepAlive(initialDelay >= 0, initialDelay || 0); | ||
} | ||
} | ||
var requestOptions = { | ||
agent: options.agent, | ||
auth: parsedUrl.auth || options.auth, | ||
ca: options.ca, | ||
cert: options.cert, | ||
ciphers: options.ciphers, | ||
headers: normalizeHeaders(options.headers || {}), | ||
host: parsedUrl.host, | ||
hostname: parsedUrl.hostname, | ||
key: options.key, | ||
localAddress: options.localAddress, | ||
method: options.method, | ||
passphrase: options.passphrase, | ||
path: parsedUrl.path, | ||
pfx: options.pfx, | ||
port: +parsedUrl.port, | ||
rejectUnauthorized: options.rejectUnauthorized, | ||
secureProtocol: options.secureProtocol, | ||
socketPath: options.socketPath | ||
}; | ||
req.on('socket', function(){ | ||
response.hasSocket = true; | ||
def.progress(response); | ||
}); | ||
if (!('user-agent' in requestOptions.headers)) { | ||
requestOptions.headers['user-agent'] = 'dojo/' + kernel.version + ' Node.js/' + process.version.replace(/^v/, ''); | ||
} | ||
req.on('response', function(clientResponse){ | ||
response.clientResponse = clientResponse; | ||
response.status = clientResponse.statusCode; | ||
response.getHeader = function(headerName){ | ||
return clientResponse.headers[headerName.toLowerCase()] || null; | ||
}; | ||
if (options.proxy) { | ||
requestOptions.path = url; | ||
if (parsedUrl.auth) { | ||
requestOptions.headers['proxy-authorization'] = 'Basic ' + new Buffer(parsedUrl.auth).toString('base64'); | ||
} | ||
var body = []; | ||
clientResponse.on('data', function(chunk){ | ||
body.push(chunk); | ||
(function () { | ||
var parsedUrl = urlUtil.parse(url); | ||
requestOptions.headers['host'] = parsedUrl.host; | ||
requestOptions.auth = parsedUrl.auth || options.auth; | ||
})(); | ||
} | ||
// TODO: progress updates via the deferred | ||
}); | ||
clientResponse.on('end', function(){ | ||
if(timeout){ | ||
clearTimeout(timeout); | ||
} | ||
response.text = body.join(''); | ||
try{ | ||
handlers(response); | ||
def.resolve(response); | ||
}catch(error){ | ||
def.reject(error); | ||
} | ||
}); | ||
}); | ||
if (!options.auth && (options.user || options.password)) { | ||
requestOptions.auth = encodeURIComponent(options.user || '') + ':' + encodeURIComponent(options.password || ''); | ||
} | ||
req.on('error', def.reject); | ||
// TODO: Cast to `any` prevents TS2226 error | ||
var request = (parsedUrl.protocol === 'https:' ? https : http).request(requestOptions); | ||
var response = { | ||
data: null, | ||
getHeader: function (name) { | ||
return (this.nativeResponse && this.nativeResponse.headers[name.toLowerCase()]) || null; | ||
}, | ||
requestOptions: options, | ||
statusCode: null, | ||
url: url | ||
}; | ||
if(options.data){ | ||
if(typeof options.data === 'string'){ | ||
req.end(options.data); | ||
}else{ | ||
options.data.pipe(req); | ||
} | ||
}else{ | ||
req.end(); | ||
} | ||
if (options.socketOptions) { | ||
if ('timeout' in options.socketOptions) { | ||
request.setTimeout(options.socketOptions.timeout); | ||
} | ||
if(options.timeout){ | ||
var timeout = setTimeout(function(){ | ||
def.cancel(new RequestTimeoutError(response)); | ||
}, options.timeout); | ||
} | ||
if ('noDelay' in options.socketOptions) { | ||
request.setNoDelay(options.socketOptions.noDelay); | ||
} | ||
return def.promise; | ||
} | ||
if ('keepAlive' in options.socketOptions) { | ||
var initialDelay = options.socketOptions.keepAlive; | ||
request.setSocketKeepAlive(initialDelay >= 0, initialDelay || 0); | ||
} | ||
} | ||
/*===== | ||
node = function(url, options){ | ||
// summary: | ||
// Sends a request using the included http or https interface from node.js | ||
// with the given URL and options. | ||
// url: String | ||
// URL to request | ||
// options: dojo/request/node.__Options? | ||
// Options for the request. | ||
// returns: dojo/request.__Promise | ||
}; | ||
node.__BaseOptions = declare(request.__BaseOptions, { | ||
// data: String|Object|Stream? | ||
// Data to transfer. This is ignored for GET and DELETE | ||
// requests. | ||
// headers: Object? | ||
// Headers to use for the request. | ||
// user: String? | ||
// Username to use during the request. | ||
// password: String? | ||
// Password to use during the request. | ||
}); | ||
node.__MethodOptions = declare(null, { | ||
// method: String? | ||
// The HTTP method to use to make the request. Must be | ||
// uppercase. Default is `"GET"`. | ||
}); | ||
node.__Options = declare([node.__BaseOptions, node.__MethodOptions]); | ||
request.once('response', function (nativeResponse) { | ||
var data; | ||
var loaded = 0; | ||
var total = +nativeResponse.headers['content-length']; | ||
node.get = function(url, options){ | ||
// summary: | ||
// Send an HTTP GET request using XMLHttpRequest with the given URL and options. | ||
// url: String | ||
// URL to request | ||
// options: dojo/request/node.__BaseOptions? | ||
// Options for the request. | ||
// returns: dojo/request.__Promise | ||
}; | ||
node.post = function(url, options){ | ||
// summary: | ||
// Send an HTTP POST request using XMLHttpRequest with the given URL and options. | ||
// url: String | ||
// URL to request | ||
// options: dojo/request/node.__BaseOptions? | ||
// Options for the request. | ||
// returns: dojo/request.__Promise | ||
}; | ||
node.put = function(url, options){ | ||
// summary: | ||
// Send an HTTP PUT request using XMLHttpRequest with the given URL and options. | ||
// url: String | ||
// URL to request | ||
// options: dojo/request/node.__BaseOptions? | ||
// Options for the request. | ||
// returns: dojo/request.__Promise | ||
}; | ||
node.del = function(url, options){ | ||
// summary: | ||
// Send an HTTP DELETE request using XMLHttpRequest with the given URL and options. | ||
// url: String | ||
// URL to request | ||
// options: dojo/request/node.__BaseOptions? | ||
// Options for the request. | ||
// returns: dojo/request.__Promise | ||
}; | ||
=====*/ | ||
if (!options.streamData) { | ||
data = []; | ||
} | ||
util.addCommonMethods(node); | ||
options.streamEncoding && nativeResponse.setEncoding(options.streamEncoding); | ||
return node; | ||
}); | ||
nativeResponse.on('data', function (chunk) { | ||
options.streamData || data.push(chunk); | ||
loaded += typeof chunk === 'string' ? Buffer.byteLength(chunk, options.streamEncoding) : chunk.length; | ||
deferred.progress({ type: 'data', chunk: chunk, loaded: loaded, total: total }); | ||
}); | ||
nativeResponse.once('end', function () { | ||
timeout && timeout.remove(); | ||
if (!options.streamData) { | ||
response.data = options.streamEncoding ? data.join('') : Buffer.concat(data, loaded); | ||
} | ||
deferred.resolve(response); | ||
}); | ||
deferred.progress({ type: 'nativeResponse', response: nativeResponse }); | ||
response.nativeResponse = nativeResponse; | ||
response.statusCode = nativeResponse.statusCode; | ||
}); | ||
request.once('error', deferred.reject); | ||
if (options.data) { | ||
if (options.data.pipe) { | ||
options.data.pipe(request); | ||
} else { | ||
request.end(options.data, options.dataEncoding); | ||
} | ||
} else { | ||
request.end(); | ||
} | ||
if (options.timeout > 0 && options.timeout !== Infinity) { | ||
var timeout = (function () { | ||
var timer = setTimeout(function () { | ||
var error = new Error('Request timed out after ' + options.timeout + 'ms'); | ||
error.name = 'RequestTimeoutError'; | ||
promise.cancel(error); | ||
}, options.timeout); | ||
return { | ||
remove: function () { | ||
this.remove = function () { | ||
}; | ||
clearTimeout(timer); | ||
} | ||
}; | ||
})(); | ||
} | ||
return promise; | ||
} | ||
module.exports = node; |
@@ -1,316 +0,66 @@ | ||
define([ | ||
'../errors/RequestError', | ||
'./watch', | ||
'./handlers', | ||
'./util', | ||
'../has'/*=====, | ||
'../request', | ||
'../_base/declare' =====*/ | ||
], function(RequestError, watch, handlers, util, has/*=====, request, declare =====*/){ | ||
has.add('native-xhr', function(){ | ||
// if true, the environment has a native XHR implementation | ||
return typeof XMLHttpRequest !== 'undefined'; | ||
}); | ||
has.add('dojo-force-activex-xhr', function(){ | ||
return has('activex') && !document.addEventListener && window.location.protocol === 'file:'; | ||
}); | ||
var Promise = require('../Promise'); | ||
has.add('native-xhr2', function(){ | ||
if(!has('native-xhr')){ return; } | ||
var x = new XMLHttpRequest(); | ||
return typeof x['addEventListener'] !== 'undefined' && | ||
(typeof opera === 'undefined' || typeof x['upload'] !== 'undefined'); | ||
}); | ||
function xhr(url, options) { | ||
var deferred = new Promise.Deferred(function (reason) { | ||
request && request.abort(); | ||
throw reason; | ||
}); | ||
has.add('native-formdata', function(){ | ||
// if true, the environment has a native FormData implementation | ||
return typeof FormData === 'function'; | ||
}); | ||
var request = new XMLHttpRequest(); | ||
var response = { | ||
data: null, | ||
getHeader: function (name) { | ||
return request.getResponseHeader(name); | ||
}, | ||
nativeResponse: request, | ||
requestOptions: options, | ||
statusCode: null, | ||
statusText: null, | ||
url: url | ||
}; | ||
function handleResponse(response, error){ | ||
var _xhr = response.xhr; | ||
response.status = response.xhr.status; | ||
response.text = _xhr.responseText; | ||
if ((!options.user || !options.password) && options.auth) { | ||
(function () { | ||
var auth = options.auth.split(':'); | ||
options.user = decodeURIComponent(auth[0]); | ||
options.password = decodeURIComponent(auth[1]); | ||
})(); | ||
} | ||
if(response.options.handleAs === 'xml'){ | ||
response.data = _xhr.responseXML; | ||
} | ||
request.open(options.method, url, !options.blockMainThread, options.user, options.password); | ||
if(!error){ | ||
try{ | ||
handlers(response); | ||
}catch(e){ | ||
error = e; | ||
} | ||
} | ||
request.onerror = function (event) { | ||
deferred.reject(event.error); | ||
}; | ||
if(error){ | ||
this.reject(error); | ||
}else if(util.checkStatus(_xhr.status)){ | ||
this.resolve(response); | ||
}else{ | ||
error = new RequestError('Unable to load ' + response.url + ' status: ' + _xhr.status, response); | ||
request.onload = function () { | ||
if (options.responseType === 'xml') { | ||
response.data = request.responseXML; | ||
} else { | ||
response.data = request.response; | ||
} | ||
this.reject(error); | ||
} | ||
} | ||
response.statusCode = request.status; | ||
response.statusText = request.statusText; | ||
var isValid, isReady, addListeners, cancel; | ||
if(has('native-xhr2')){ | ||
// Any platform with XHR2 will only use the watch mechanism for timeout. | ||
deferred.resolve(response); | ||
}; | ||
isValid = function(response){ | ||
// summary: | ||
// Check to see if the request should be taken out of the watch queue | ||
return !this.isFulfilled(); | ||
}; | ||
cancel = function(dfd, response){ | ||
// summary: | ||
// Canceler for deferred | ||
response.xhr.abort(); | ||
}; | ||
addListeners = function(_xhr, dfd, response){ | ||
// summary: | ||
// Adds event listeners to the XMLHttpRequest object | ||
function onLoad(evt){ | ||
dfd.handleResponse(response); | ||
} | ||
function onError(evt){ | ||
var _xhr = evt.target; | ||
var error = new RequestError('Unable to load ' + response.url + ' status: ' + _xhr.status, response); | ||
dfd.handleResponse(response, error); | ||
} | ||
request.onprogress = function (event) { | ||
deferred.progress(event); | ||
}; | ||
function onProgress(evt){ | ||
if(evt.lengthComputable){ | ||
response.loaded = evt.loaded; | ||
response.total = evt.total; | ||
dfd.progress(response); | ||
} | ||
} | ||
if (options.timeout > 0 && options.timeout !== Infinity) { | ||
request.timeout = options.timeout; | ||
} | ||
_xhr.addEventListener('load', onLoad, false); | ||
_xhr.addEventListener('error', onError, false); | ||
_xhr.addEventListener('progress', onProgress, false); | ||
for (var header in options.headers) { | ||
request.setRequestHeader(header, options.headers[header]); | ||
} | ||
return function(){ | ||
_xhr.removeEventListener('load', onLoad, false); | ||
_xhr.removeEventListener('error', onError, false); | ||
_xhr.removeEventListener('progress', onProgress, false); | ||
_xhr = null; | ||
}; | ||
}; | ||
}else{ | ||
isValid = function(response){ | ||
return response.xhr.readyState; //boolean | ||
}; | ||
isReady = function(response){ | ||
return 4 === response.xhr.readyState; //boolean | ||
}; | ||
cancel = function(dfd, response){ | ||
// summary: | ||
// canceller function for util.deferred call. | ||
var xhr = response.xhr; | ||
var _at = typeof xhr.abort; | ||
if(_at === 'function' || _at === 'object' || _at === 'unknown'){ | ||
xhr.abort(); | ||
} | ||
}; | ||
} | ||
request.send(options.data); | ||
function getHeader(headerName){ | ||
return this.xhr.getResponseHeader(headerName); | ||
} | ||
return deferred.promise; | ||
} | ||
var undefined, | ||
defaultOptions = { | ||
data: null, | ||
query: null, | ||
sync: false, | ||
method: 'GET' | ||
}; | ||
function xhr(url, options, returnDeferred){ | ||
var response = util.parseArgs( | ||
url, | ||
util.deepCreate(defaultOptions, options), | ||
has('native-formdata') && options && options.data && options.data instanceof FormData | ||
); | ||
url = response.url; | ||
options = response.options; | ||
var remover, | ||
last = function(){ | ||
remover && remover(); | ||
}; | ||
//Make the Deferred object for this xhr request. | ||
var dfd = util.deferred( | ||
response, | ||
cancel, | ||
isValid, | ||
isReady, | ||
handleResponse, | ||
last | ||
); | ||
var _xhr = response.xhr = xhr._create(); | ||
if(!_xhr){ | ||
// If XHR factory somehow returns nothings, | ||
// cancel the deferred. | ||
dfd.cancel(new RequestError('XHR was not created')); | ||
return returnDeferred ? dfd : dfd.promise; | ||
} | ||
response.getHeader = getHeader; | ||
if(addListeners){ | ||
remover = addListeners(_xhr, dfd, response); | ||
} | ||
var data = options.data, | ||
async = !options.sync, | ||
method = options.method; | ||
try{ | ||
// IE6 won't let you call apply() on the native function. | ||
_xhr.open(method, url, async, options.user || undefined, options.password || undefined); | ||
if(options.withCredentials){ | ||
_xhr.withCredentials = options.withCredentials; | ||
} | ||
var headers = options.headers, | ||
contentType = 'application/x-www-form-urlencoded'; | ||
if(headers){ | ||
for(var hdr in headers){ | ||
if(hdr.toLowerCase() === 'content-type'){ | ||
contentType = headers[hdr]; | ||
}else if(headers[hdr]){ | ||
//Only add header if it has a value. This allows for instance, skipping | ||
//insertion of X-Requested-With by specifying empty value. | ||
_xhr.setRequestHeader(hdr, headers[hdr]); | ||
} | ||
} | ||
} | ||
if(contentType && contentType !== false){ | ||
_xhr.setRequestHeader('Content-Type', contentType); | ||
} | ||
if(!headers || !('X-Requested-With' in headers)){ | ||
_xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); | ||
} | ||
if(util.notify){ | ||
util.notify.emit('send', response, dfd.promise.cancel); | ||
} | ||
_xhr.send(data); | ||
}catch(e){ | ||
dfd.reject(e); | ||
} | ||
watch(dfd); | ||
_xhr = null; | ||
return returnDeferred ? dfd : dfd.promise; | ||
} | ||
/*===== | ||
xhr = function(url, options){ | ||
// summary: | ||
// Sends a request using XMLHttpRequest with the given URL and options. | ||
// url: String | ||
// URL to request | ||
// options: dojo/request/xhr.__Options? | ||
// Options for the request. | ||
// returns: dojo/request.__Promise | ||
}; | ||
xhr.__BaseOptions = declare(request.__BaseOptions, { | ||
// sync: Boolean? | ||
// Whether to make a synchronous request or not. Default | ||
// is `false` (asynchronous). | ||
// data: String|Object|FormData? | ||
// Data to transfer. This is ignored for GET and DELETE | ||
// requests. | ||
// headers: Object? | ||
// Headers to use for the request. | ||
// user: String? | ||
// Username to use during the request. | ||
// password: String? | ||
// Password to use during the request. | ||
// withCredentials: Boolean? | ||
// For cross-site requests, whether to send credentials | ||
// or not. | ||
}); | ||
xhr.__MethodOptions = declare(null, { | ||
// method: String? | ||
// The HTTP method to use to make the request. Must be | ||
// uppercase. Default is `"GET"`. | ||
}); | ||
xhr.__Options = declare([xhr.__BaseOptions, xhr.__MethodOptions]); | ||
xhr.get = function(url, options){ | ||
// summary: | ||
// Send an HTTP GET request using XMLHttpRequest with the given URL and options. | ||
// url: String | ||
// URL to request | ||
// options: dojo/request/xhr.__BaseOptions? | ||
// Options for the request. | ||
// returns: dojo/request.__Promise | ||
}; | ||
xhr.post = function(url, options){ | ||
// summary: | ||
// Send an HTTP POST request using XMLHttpRequest with the given URL and options. | ||
// url: String | ||
// URL to request | ||
// options: dojo/request/xhr.__BaseOptions? | ||
// Options for the request. | ||
// returns: dojo/request.__Promise | ||
}; | ||
xhr.put = function(url, options){ | ||
// summary: | ||
// Send an HTTP PUT request using XMLHttpRequest with the given URL and options. | ||
// url: String | ||
// URL to request | ||
// options: dojo/request/xhr.__BaseOptions? | ||
// Options for the request. | ||
// returns: dojo/request.__Promise | ||
}; | ||
xhr.del = function(url, options){ | ||
// summary: | ||
// Send an HTTP DELETE request using XMLHttpRequest with the given URL and options. | ||
// url: String | ||
// URL to request | ||
// options: dojo/request/xhr.__BaseOptions? | ||
// Options for the request. | ||
// returns: dojo/request.__Promise | ||
}; | ||
=====*/ | ||
xhr._create = function(){ | ||
// summary: | ||
// does the work of portably generating a new XMLHTTPRequest object. | ||
throw new Error('XMLHTTP not available'); | ||
}; | ||
if(has('native-xhr') && !has('dojo-force-activex-xhr')){ | ||
xhr._create = function(){ | ||
return new XMLHttpRequest(); | ||
}; | ||
}else if(has('activex')){ | ||
try{ | ||
new ActiveXObject('Msxml2.XMLHTTP'); | ||
xhr._create = function(){ | ||
return new ActiveXObject('Msxml2.XMLHTTP'); | ||
}; | ||
}catch(e){ | ||
try{ | ||
new ActiveXObject('Microsoft.XMLHTTP'); | ||
xhr._create = function(){ | ||
return new ActiveXObject('Microsoft.XMLHTTP'); | ||
}; | ||
}catch(e){} | ||
} | ||
} | ||
util.addCommonMethods(xhr); | ||
return xhr; | ||
}); | ||
module.exports = xhr; |
235
string.js
@@ -1,162 +0,99 @@ | ||
define([ | ||
"./_base/kernel", // kernel.global | ||
"./_base/lang" | ||
], function(kernel, lang){ | ||
var lang = require('./lang'); | ||
// module: | ||
// dojo/string | ||
function repeat(string, times) { | ||
if (!string || times <= 0) { | ||
return ''; | ||
} | ||
var string = { | ||
// summary: | ||
// String utilities for Dojo | ||
}; | ||
lang.setObject("dojo.string", string); | ||
var buffer = []; | ||
while (true) { | ||
if (times & 1) { | ||
buffer.push(string); | ||
} | ||
times >>= 1; | ||
if (!times) { | ||
break; | ||
} | ||
string += string; | ||
} | ||
return buffer.join(''); | ||
} | ||
exports.repeat = repeat; | ||
string.rep = function(/*String*/str, /*Integer*/num){ | ||
// summary: | ||
// Efficiently replicate a string `n` times. | ||
// str: | ||
// the string to replicate | ||
// num: | ||
// number of times to replicate the string | ||
var Padding; | ||
(function (Padding) { | ||
Padding[Padding["Left"] = 0] = "Left"; | ||
Padding[Padding["Right"] = 1] = "Right"; | ||
Padding[Padding["Both"] = 2] = "Both"; | ||
})(Padding || (Padding = {})); | ||
; | ||
if(num <= 0 || !str){ return ""; } | ||
function _pad(text, size, character, position) { | ||
if (typeof position === "undefined") { position = 1 /* Right */; } | ||
var length = size - text.length, pad = exports.repeat(character, Math.ceil(length / character.length)); | ||
var buf = []; | ||
for(;;){ | ||
if(num & 1){ | ||
buf.push(str); | ||
} | ||
if(!(num >>= 1)){ break; } | ||
str += str; | ||
} | ||
return buf.join(""); // String | ||
}; | ||
if (position === 0 /* Left */) { | ||
return pad + text; | ||
} else if (position === 1 /* Right */) { | ||
return text + pad; | ||
} else { | ||
var left = Math.ceil(length / 2); | ||
return pad.substr(0, left) + text + pad.substr(0, length - left); | ||
} | ||
} | ||
string.pad = function(/*String*/text, /*Integer*/size, /*String?*/ch, /*Boolean?*/end){ | ||
// summary: | ||
// Pad a string to guarantee that it is at least `size` length by | ||
// filling with the character `ch` at either the start or end of the | ||
// string. Pads at the start, by default. | ||
// text: | ||
// the string to pad | ||
// size: | ||
// length to provide padding | ||
// ch: | ||
// character to pad, defaults to '0' | ||
// end: | ||
// adds padding at the end if true, otherwise pads at start | ||
// example: | ||
// | // Fill the string to length 10 with "+" characters on the right. Yields "Dojo++++++". | ||
// | string.pad("Dojo", 10, "+", true); | ||
function pad(text, size, character) { | ||
if (typeof character === "undefined") { character = ' '; } | ||
return _pad(text, size, character, 2 /* Both */); | ||
} | ||
exports.pad = pad; | ||
if(!ch){ | ||
ch = '0'; | ||
} | ||
var out = String(text), | ||
pad = string.rep(ch, Math.ceil((size - out.length) / ch.length)); | ||
return end ? out + pad : pad + out; // String | ||
}; | ||
function padr(text, size, character) { | ||
if (typeof character === "undefined") { character = ' '; } | ||
return _pad(text, size, character, 1 /* Right */); | ||
} | ||
exports.padr = padr; | ||
function padl(text, size, character) { | ||
if (typeof character === "undefined") { character = ' '; } | ||
return _pad(text, size, character, 0 /* Left */); | ||
} | ||
exports.padl = padl; | ||
string.substitute = function( /*String*/ template, | ||
/*Object|Array*/map, | ||
/*Function?*/ transform, | ||
/*Object?*/ thisObject){ | ||
// summary: | ||
// Performs parameterized substitutions on a string. Throws an | ||
// exception if any parameter is unmatched. | ||
// template: | ||
// a string with expressions in the form `${key}` to be replaced or | ||
// `${key:format}` which specifies a format function. keys are case-sensitive. | ||
// map: | ||
// hash to search for substitutions | ||
// transform: | ||
// a function to process all parameters before substitution takes | ||
// place, e.g. mylib.encodeXML | ||
// thisObject: | ||
// where to look for optional format function; default to the global | ||
// namespace | ||
// example: | ||
// Substitutes two expressions in a string from an Array or Object | ||
// | // returns "File 'foo.html' is not found in directory '/temp'." | ||
// | // by providing substitution data in an Array | ||
// | string.substitute( | ||
// | "File '${0}' is not found in directory '${1}'.", | ||
// | ["foo.html","/temp"] | ||
// | ); | ||
// | | ||
// | // also returns "File 'foo.html' is not found in directory '/temp'." | ||
// | // but provides substitution data in an Object structure. Dotted | ||
// | // notation may be used to traverse the structure. | ||
// | string.substitute( | ||
// | "File '${name}' is not found in directory '${info.dir}'.", | ||
// | { name: "foo.html", info: { dir: "/temp" } } | ||
// | ); | ||
// example: | ||
// Use a transform function to modify the values: | ||
// | // returns "file 'foo.html' is not found in directory '/temp'." | ||
// | string.substitute( | ||
// | "${0} is not found in ${1}.", | ||
// | ["foo.html","/temp"], | ||
// | function(str){ | ||
// | // try to figure out the type | ||
// | var prefix = (str.charAt(0) == "/") ? "directory": "file"; | ||
// | return prefix + " '" + str + "'"; | ||
// | } | ||
// | ); | ||
// example: | ||
// Use a formatter | ||
// | // returns "thinger -- howdy" | ||
// | string.substitute( | ||
// | "${0:postfix}", ["thinger"], null, { | ||
// | postfix: function(value, key){ | ||
// | return value + " -- howdy"; | ||
// | } | ||
// | } | ||
// | ); | ||
var substitutePattern = /\$\{([^\s\:\}]+)(?:\:([^\s\:\}]+))?\}/g; | ||
function defaultTransform(value) { | ||
return value; | ||
} | ||
; | ||
thisObject = thisObject || kernel.global; | ||
transform = transform ? | ||
lang.hitch(thisObject, transform) : function(v){ return v; }; | ||
function substitute(template, map, transform, context) { | ||
context = context || undefined; | ||
transform = transform ? transform.bind(context) : defaultTransform; | ||
return template.replace(/\$\{([^\s\:\}]+)(?:\:([^\s\:\}]+))?\}/g, | ||
function(match, key, format){ | ||
var value = lang.getObject(key, false, map); | ||
if(format){ | ||
value = lang.getObject(format, false, thisObject).call(thisObject, value, key); | ||
} | ||
return transform(value, key).toString(); | ||
}); // String | ||
}; | ||
// TODO: remove <any> after https://typescript.codeplex.com/workitem/1812 is fixed | ||
return template.replace(substitutePattern, function (match, key, format) { | ||
var value = lang.getProperty(map, key); | ||
if (format) { | ||
value = lang.getProperty(context, format).call(context, value, key); | ||
} | ||
return transform(value, key) + ''; | ||
}); | ||
} | ||
exports.substitute = substitute; | ||
string.trim = String.prototype.trim ? | ||
lang.trim : // aliasing to the native function | ||
function(str){ | ||
str = str.replace(/^\s+/, ''); | ||
for(var i = str.length - 1; i >= 0; i--){ | ||
if(/\S/.test(str.charAt(i))){ | ||
str = str.substring(0, i + 1); | ||
break; | ||
} | ||
} | ||
return str; | ||
}; | ||
function count(haystack, needle) { | ||
var hits = 0, lastIndex = haystack.indexOf(needle); | ||
/*===== | ||
string.trim = function(str){ | ||
// summary: | ||
// Trims whitespace from both sides of the string | ||
// str: String | ||
// String to be trimmed | ||
// returns: String | ||
// Returns the trimmed string | ||
// description: | ||
// This version of trim() was taken from [Steven Levithan's blog](http://blog.stevenlevithan.com/archives/faster-trim-javascript). | ||
// The short yet performant version of this function is dojo/_base/lang.trim(), | ||
// which is part of Dojo base. Uses String.prototype.trim instead, if available. | ||
return ""; // String | ||
}; | ||
=====*/ | ||
while (lastIndex > -1) { | ||
++hits; | ||
lastIndex = haystack.indexOf(needle, lastIndex + 1); | ||
} | ||
return string; | ||
}); | ||
return hits; | ||
} | ||
exports.count = count; | ||
var regExpPattern = /[-\[\]{}()*+?.,\\\^$|#\s]/g; | ||
function escapeRegExpString(string) { | ||
return string.replace(regExpPattern, '\\$&'); | ||
} | ||
exports.escapeRegExpString = escapeRegExpString; |
243
text.js
@@ -1,218 +0,37 @@ | ||
define(["./_base/kernel", "require", "./has", "./has!host-browser?./request"], function(dojo, require, has, request){ | ||
// module: | ||
// dojo/text | ||
/// <reference path="./nodejs" /> | ||
var has = require('./has'); | ||
var getText; | ||
if(has("host-browser")){ | ||
getText= function(url, sync, load){ | ||
request(url, {sync:!!sync}).then(load); | ||
}; | ||
}else{ | ||
// Path for node.js and rhino, to load from local file system. | ||
// TODO: use node.js native methods rather than depending on a require.getText() method to exist. | ||
if(require.getText){ | ||
getText= require.getText; | ||
}else{ | ||
console.error("dojo/text plugin failed to load because loader does not support getText"); | ||
} | ||
} | ||
var getText; | ||
var | ||
theCache = {}, | ||
if (has('host-browser')) { | ||
getText = function (url, callback) { | ||
var xhr = new XMLHttpRequest(); | ||
strip= function(text){ | ||
//Strips <?xml ...?> declarations so that external SVG and XML | ||
//documents can be added to a document without worry. Also, if the string | ||
//is an HTML document, only the part inside the body tag is returned. | ||
if(text){ | ||
text= text.replace(/^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im, ""); | ||
var matches= text.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im); | ||
if(matches){ | ||
text= matches[1]; | ||
} | ||
}else{ | ||
text = ""; | ||
} | ||
return text; | ||
}, | ||
xhr.onload = function () { | ||
callback(xhr.responseText); | ||
}; | ||
notFound = {}, | ||
xhr.open('GET', url, true); | ||
xhr.send(null); | ||
}; | ||
} else if (has('host-node')) { | ||
var fs = require('fs'); | ||
getText = function (url, callback) { | ||
fs.readFile(url, { encoding: 'utf8' }, function (error, data) { | ||
if (error) { | ||
throw error; | ||
} | ||
pending = {}; | ||
callback(data); | ||
}); | ||
}; | ||
} else { | ||
getText = function () { | ||
throw new Error('dojo/text not supported on this platform'); | ||
}; | ||
} | ||
dojo.cache = function(/*String||Object*/module, /*String*/url, /*String||Object?*/value){ | ||
// summary: | ||
// A getter and setter for storing the string content associated with the | ||
// module and url arguments. | ||
// description: | ||
// If module is a string that contains slashes, then it is interpretted as a fully | ||
// resolved path (typically a result returned by require.toUrl), and url should not be | ||
// provided. This is the preferred signature. If module is a string that does not | ||
// contain slashes, then url must also be provided and module and url are used to | ||
// call `dojo.moduleUrl()` to generate a module URL. This signature is deprecated. | ||
// If value is specified, the cache value for the moduleUrl will be set to | ||
// that value. Otherwise, dojo.cache will fetch the moduleUrl and store it | ||
// in its internal cache and return that cached value for the URL. To clear | ||
// a cache value pass null for value. Since XMLHttpRequest (XHR) is used to fetch the | ||
// the URL contents, only modules on the same domain of the page can use this capability. | ||
// The build system can inline the cache values though, to allow for xdomain hosting. | ||
// module: String||Object | ||
// If a String with slashes, a fully resolved path; if a String without slashes, the | ||
// module name to use for the base part of the URL, similar to module argument | ||
// to `dojo.moduleUrl`. If an Object, something that has a .toString() method that | ||
// generates a valid path for the cache item. For example, a dojo._Url object. | ||
// url: String | ||
// The rest of the path to append to the path derived from the module argument. If | ||
// module is an object, then this second argument should be the "value" argument instead. | ||
// value: String||Object? | ||
// If a String, the value to use in the cache for the module/url combination. | ||
// If an Object, it can have two properties: value and sanitize. The value property | ||
// should be the value to use in the cache, and sanitize can be set to true or false, | ||
// to indicate if XML declarations should be removed from the value and if the HTML | ||
// inside a body tag in the value should be extracted as the real value. The value argument | ||
// or the value property on the value argument are usually only used by the build system | ||
// as it inlines cache content. | ||
// example: | ||
// To ask dojo.cache to fetch content and store it in the cache (the dojo["cache"] style | ||
// of call is used to avoid an issue with the build system erroneously trying to intern | ||
// this example. To get the build system to intern your dojo.cache calls, use the | ||
// "dojo.cache" style of call): | ||
// | //If template.html contains "<h1>Hello</h1>" that will be | ||
// | //the value for the text variable. | ||
// | //Note: This is pre-AMD, deprecated syntax | ||
// | var text = dojo["cache"]("my.module", "template.html"); | ||
// example: | ||
// To ask dojo.cache to fetch content and store it in the cache, and sanitize the input | ||
// (the dojo["cache"] style of call is used to avoid an issue with the build system | ||
// erroneously trying to intern this example. To get the build system to intern your | ||
// dojo.cache calls, use the "dojo.cache" style of call): | ||
// | //If template.html contains "<html><body><h1>Hello</h1></body></html>", the | ||
// | //text variable will contain just "<h1>Hello</h1>". | ||
// | //Note: This is pre-AMD, deprecated syntax | ||
// | var text = dojo["cache"]("my.module", "template.html", {sanitize: true}); | ||
// example: | ||
// Same example as previous, but demonstrates how an object can be passed in as | ||
// the first argument, then the value argument can then be the second argument. | ||
// | //If template.html contains "<html><body><h1>Hello</h1></body></html>", the | ||
// | //text variable will contain just "<h1>Hello</h1>". | ||
// | //Note: This is pre-AMD, deprecated syntax | ||
// | var text = dojo["cache"](new dojo._Url("my/module/template.html"), {sanitize: true}); | ||
// * (string string [value]) => (module, url, value) | ||
// * (object [value]) => (module, value), url defaults to "" | ||
// | ||
// * if module is an object, then it must be convertable to a string | ||
// * (module, url) module + (url ? ("/" + url) : "") must be a legal argument to require.toUrl | ||
// * value may be a string or an object; if an object then may have the properties "value" and/or "sanitize" | ||
var key; | ||
if(typeof module=="string"){ | ||
if(/\//.test(module)){ | ||
// module is a version 1.7+ resolved path | ||
key = module; | ||
value = url; | ||
}else{ | ||
// module is a version 1.6- argument to dojo.moduleUrl | ||
key = require.toUrl(module.replace(/\./g, "/") + (url ? ("/" + url) : "")); | ||
} | ||
}else{ | ||
key = module + ""; | ||
value = url; | ||
} | ||
var | ||
val = (value != undefined && typeof value != "string") ? value.value : value, | ||
sanitize = value && value.sanitize; | ||
if(typeof val == "string"){ | ||
//We have a string, set cache value | ||
theCache[key] = val; | ||
return sanitize ? strip(val) : val; | ||
}else if(val === null){ | ||
//Remove cached value | ||
delete theCache[key]; | ||
return null; | ||
}else{ | ||
//Allow cache values to be empty strings. If key property does | ||
//not exist, fetch it. | ||
if(!(key in theCache)){ | ||
getText(key, true, function(text){ | ||
theCache[key]= text; | ||
}); | ||
} | ||
return sanitize ? strip(theCache[key]) : theCache[key]; | ||
} | ||
}; | ||
return { | ||
// summary: | ||
// This module implements the dojo/text! plugin and the dojo.cache API. | ||
// description: | ||
// We choose to include our own plugin to leverage functionality already contained in dojo | ||
// and thereby reduce the size of the plugin compared to various foreign loader implementations. | ||
// Also, this allows foreign AMD loaders to be used without their plugins. | ||
// | ||
// CAUTION: this module is designed to optionally function synchronously to support the dojo v1.x synchronous | ||
// loader. This feature is outside the scope of the CommonJS plugins specification. | ||
// the dojo/text caches it's own resources because of dojo.cache | ||
dynamic: true, | ||
normalize: function(id, toAbsMid){ | ||
// id is something like (path may be relative): | ||
// | ||
// "path/to/text.html" | ||
// "path/to/text.html!strip" | ||
var parts= id.split("!"), | ||
url= parts[0]; | ||
return (/^\./.test(url) ? toAbsMid(url) : url) + (parts[1] ? "!" + parts[1] : ""); | ||
}, | ||
load: function(id, require, load){ | ||
// id: String | ||
// Path to the resource. | ||
// require: Function | ||
// Object that include the function toUrl with given id returns a valid URL from which to load the text. | ||
// load: Function | ||
// Callback function which will be called, when the loading finished. | ||
// id is something like (path is always absolute): | ||
// | ||
// "path/to/text.html" | ||
// "path/to/text.html!strip" | ||
var | ||
parts= id.split("!"), | ||
stripFlag= parts.length>1, | ||
absMid= parts[0], | ||
url = require.toUrl(parts[0]), | ||
requireCacheUrl = "url:" + url, | ||
text = notFound, | ||
finish = function(text){ | ||
load(stripFlag ? strip(text) : text); | ||
}; | ||
if(absMid in theCache){ | ||
text = theCache[absMid]; | ||
}else if(require.cache && requireCacheUrl in require.cache){ | ||
text = require.cache[requireCacheUrl]; | ||
}else if(url in theCache){ | ||
text = theCache[url]; | ||
} | ||
if(text===notFound){ | ||
if(pending[url]){ | ||
pending[url].push(finish); | ||
}else{ | ||
var pendingList = pending[url] = [finish]; | ||
getText(url, !require.async, function(text){ | ||
theCache[absMid]= theCache[url]= text; | ||
for(var i = 0; i<pendingList.length;){ | ||
pendingList[i++](text); | ||
} | ||
delete pending[url]; | ||
}); | ||
} | ||
}else{ | ||
finish(text); | ||
} | ||
} | ||
}; | ||
}); | ||
function load(resourceId, require, load) { | ||
getText(resourceId, load); | ||
} | ||
exports.load = load; |
49
topic.js
@@ -1,38 +0,17 @@ | ||
define(["./Evented"], function(Evented){ | ||
var Evented = require('./Evented'); | ||
// module: | ||
// dojo/topic | ||
var hub = new Evented(); | ||
var hub = new Evented; | ||
return { | ||
// summary: | ||
// Pubsub hub. | ||
// example: | ||
// | topic.subscribe("some/topic", function(event){ | ||
// | ... do something with event | ||
// | }); | ||
// | topic.publish("some/topic", {name:"some event", ...}); | ||
function subscribe(topic, listener) { | ||
return hub.on.apply(hub, arguments); | ||
} | ||
exports.subscribe = subscribe; | ||
publish: function(topic, event){ | ||
// summary: | ||
// Publishes a message to a topic on the pub/sub hub. All arguments after | ||
// the first will be passed to the subscribers, so any number of arguments | ||
// can be provided (not just event). | ||
// topic: String | ||
// The name of the topic to publish to | ||
// event: Object | ||
// An event to distribute to the topic listeners | ||
return hub.emit.apply(hub, arguments); | ||
}, | ||
subscribe: function(topic, listener){ | ||
// summary: | ||
// Subscribes to a topic on the pub/sub hub | ||
// topic: String | ||
// The topic to subscribe to | ||
// listener: Function | ||
// A function to call when a message is published to the given topic | ||
return hub.on.apply(hub, arguments); | ||
} | ||
}; | ||
}); | ||
function publish(topic) { | ||
var args = []; | ||
for (var _i = 0; _i < (arguments.length - 1); _i++) { | ||
args[_i] = arguments[_i + 1]; | ||
} | ||
hub.emit.apply(hub, arguments); | ||
} | ||
exports.publish = publish; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 2 instances in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No License Found
License(Experimental) License information could not be found.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Found 1 instance in 1 package
Mixed license
License(Experimental) Package contains multiple licenses.
Found 1 instance in 1 package
9
4
106028
8
31
2839
2
2