зеркало из https://github.com/mozilla/gecko-dev.git
merge fx-team to mozilla-central
This commit is contained in:
Коммит
c78cc390fa
|
@ -35,13 +35,13 @@ geolocation API in Firefox.
|
||||||
## Using Geolocation in an Add-on ##
|
## Using Geolocation in an Add-on ##
|
||||||
|
|
||||||
Suppose we want to use the
|
Suppose we want to use the
|
||||||
[geolocation API built into Firefox](https://developer.mozilla.org/en/using_geolocation).
|
[geolocation API built into Firefox](https://developer.mozilla.org/en-US/docs/WebAPI/Using_geolocation).
|
||||||
The SDK doesn't provide an API to access geolocation, but we can
|
The SDK doesn't provide an API to access geolocation, but we can
|
||||||
[access the underlying XPCOM API using `require("chrome")`](dev-guide/guides/xul-migration.html#xpcom).
|
[access the underlying XPCOM API using `require("chrome")`](dev-guide/guides/xul-migration.html#xpcom).
|
||||||
|
|
||||||
The following add-on adds a [button to the toolbar](dev-guide/tutorials/adding-toolbar-button.html):
|
The following add-on adds a [button to the toolbar](dev-guide/tutorials/adding-toolbar-button.html):
|
||||||
when the user clicks the button, it loads the
|
when the user clicks the button, it loads the
|
||||||
[XPCOM nsIDOMGeoGeolocation](https://developer.mozilla.org/en/XPCOM_Interface_Reference/NsIDOMGeoGeolocation)
|
[XPCOM nsIDOMGeoGeolocation](https://developer.mozilla.org/en-US/docs/XPCOM_Interface_Reference/NsIDOMGeoGeolocation)
|
||||||
object, and retrieves the user's current position:
|
object, and retrieves the user's current position:
|
||||||
|
|
||||||
var {Cc, Ci} = require("chrome");
|
var {Cc, Ci} = require("chrome");
|
||||||
|
@ -88,7 +88,7 @@ info: longitude: 93.0785269
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
So far, so good. But the geolocation guide on MDN tells us that we must
|
So far, so good. But the geolocation guide on MDN tells us that we must
|
||||||
[ask the user for permission](https://developer.mozilla.org/en/using_geolocation#Prompting_for_permission)
|
[ask the user for permission](https://developer.mozilla.org/en-US/docs/WebAPI/Using_geolocation#Prompting_for_permission)
|
||||||
before using the API.
|
before using the API.
|
||||||
|
|
||||||
So we'll extend the add-on to include an adapted version of the code in
|
So we'll extend the add-on to include an adapted version of the code in
|
||||||
|
@ -384,4 +384,4 @@ to add your name as the author, choose a distribution license, and so on.
|
||||||
To see some of the modules people have already developed, see the page of
|
To see some of the modules people have already developed, see the page of
|
||||||
[community-developed modules](https://github.com/mozilla/addon-sdk/wiki/Community-developed-modules).
|
[community-developed modules](https://github.com/mozilla/addon-sdk/wiki/Community-developed-modules).
|
||||||
To learn how to use third-party modules in your own code, see the
|
To learn how to use third-party modules in your own code, see the
|
||||||
[tutorial on adding menu items](dev-guide/tutorials/adding-menus.html).
|
[tutorial on adding menu items](dev-guide/tutorials/adding-menus.html).
|
||||||
|
|
|
@ -13,15 +13,17 @@ When the method is invoked on an instance of the object, the original
|
||||||
function is called. It is passed the object instance (i.e. `this`) as
|
function is called. It is passed the object instance (i.e. `this`) as
|
||||||
the first parameter, followed by any parameters passed into the method.
|
the first parameter, followed by any parameters passed into the method.
|
||||||
|
|
||||||
let { method } = require("sdk/lang/functional");
|
const { method } = require("sdk/lang/functional");
|
||||||
let myNumber = {
|
|
||||||
|
const times = (target, x) => target.number *= x;
|
||||||
|
const add = (target, x) => target.number += x;
|
||||||
|
|
||||||
|
const myNumber = {
|
||||||
times: method(times),
|
times: method(times),
|
||||||
add: method(add),
|
add: method(add),
|
||||||
number: 0
|
number: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
function times (target, x) { return target.number *= x; }
|
|
||||||
function add (target, x) { return target.number += x; }
|
|
||||||
|
|
||||||
console.log(myNumber.number); // 0
|
console.log(myNumber.number); // 0
|
||||||
myNumber.add(10); // 10
|
myNumber.add(10); // 10
|
||||||
|
@ -44,8 +46,8 @@ wait (i.e. `setTimeout(function () { ... }, 0)`), except that the wrapped functi
|
||||||
may be reused and does not need to be repeated each time. This also enables you
|
may be reused and does not need to be repeated each time. This also enables you
|
||||||
to use these functions as event listeners.
|
to use these functions as event listeners.
|
||||||
|
|
||||||
let { defer } = require("sdk/lang/functional");
|
const { defer } = require("sdk/lang/functional");
|
||||||
let fn = defer(function myEvent (event, value) {
|
const fn = defer((event, value) => {
|
||||||
console.log(event + " : " + value);
|
console.log(event + " : " + value);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -74,16 +76,11 @@ An alias for [defer](modules/sdk/lang/functional.html#defer(fn)).
|
||||||
Invokes `callee`, passing `params` as an argument and `self` as `this`.
|
Invokes `callee`, passing `params` as an argument and `self` as `this`.
|
||||||
Returns the value that is returned by `callee`.
|
Returns the value that is returned by `callee`.
|
||||||
|
|
||||||
let { invoke } = require("sdk/lang/functional");
|
const { invoke } = require("sdk/lang/functional");
|
||||||
|
|
||||||
|
const sum = (...args) => args.reduce((a, b) => a + b);
|
||||||
invoke(sum, [1,2,3,4,5], null); // 15
|
invoke(sum, [1,2,3,4,5], null); // 15
|
||||||
|
|
||||||
function sum () {
|
|
||||||
return Array.slice(arguments).reduce(function (a, b) {
|
|
||||||
return a + b;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@param callee {function}
|
@param callee {function}
|
||||||
Function to invoke.
|
Function to invoke.
|
||||||
@param params {Array}
|
@param params {Array}
|
||||||
|
@ -98,9 +95,9 @@ Returns the value that is returned by `callee`.
|
||||||
@function
|
@function
|
||||||
Takes a function and bind values to one or more arguments, returning a new function of smaller arity.
|
Takes a function and bind values to one or more arguments, returning a new function of smaller arity.
|
||||||
|
|
||||||
let { partial } = require("sdk/lang/functional");
|
const { partial } = require("sdk/lang/functional");
|
||||||
let add = function add (x, y) { return x + y; }
|
const add = (x, y) => x + y;
|
||||||
let addOne = partial(add, 1);
|
const addOne = partial(add, 1);
|
||||||
|
|
||||||
addOne(5); // 6
|
addOne(5); // 6
|
||||||
addOne(10); // 11
|
addOne(10); // 11
|
||||||
|
@ -122,14 +119,16 @@ Returns the [composition](http://en.wikipedia.org/wiki/Function_composition_(com
|
||||||
return value of the function that follows. In math terms, composing the functions
|
return value of the function that follows. In math terms, composing the functions
|
||||||
`f()`, `g()`, and `h()` produces `f(g(h()))`.
|
`f()`, `g()`, and `h()` produces `f(g(h()))`.
|
||||||
|
|
||||||
let { compose } = require("sdk/lang/functional");
|
const { compose } = require("sdk/lang/functional");
|
||||||
|
|
||||||
let welcome = compose(exclaim, greet);
|
const square = x => x * x;
|
||||||
|
const increment = x => x + 1;
|
||||||
|
|
||||||
welcome('moe'); // "hi: moe!";
|
const f1 = compose(increment, square);
|
||||||
|
f1(5); // => 26
|
||||||
|
|
||||||
function greet (name) { return "hi: " + name; }
|
const f2 = compose(square, increment);
|
||||||
function exclaim (statement) { return statement + "!"; }
|
f2(5); // => 36
|
||||||
|
|
||||||
@param fn... {function}
|
@param fn... {function}
|
||||||
Takes a variable number of functions as arguments and composes them from right to left.
|
Takes a variable number of functions as arguments and composes them from right to left.
|
||||||
|
@ -144,16 +143,14 @@ Returns the first function passed as an argument to the second,
|
||||||
allowing you to adjust arguments, run code before and after, and
|
allowing you to adjust arguments, run code before and after, and
|
||||||
conditionally execute the original function.
|
conditionally execute the original function.
|
||||||
|
|
||||||
let { wrap } = require("sdk/lang/functional");
|
const { wrap } = require("sdk/lang/functional");
|
||||||
|
|
||||||
let wrappedHello = wrap(hello, function (fn, name) {
|
const hello = name => "hello: " + name;
|
||||||
return "before, " + fn(name) + "after";
|
const wrappedHello = wrap(hello, (fn, name) =>
|
||||||
});
|
"before, " + fn(name) + "after");
|
||||||
|
|
||||||
wrappedHello("moe"); // "before, hello: moe, after"
|
wrappedHello("moe"); // "before, hello: moe, after"
|
||||||
|
|
||||||
function hello (name) { return "hello: " + name; }
|
|
||||||
|
|
||||||
@param fn {function}
|
@param fn {function}
|
||||||
The function to be passed into the `wrapper` function.
|
The function to be passed into the `wrapper` function.
|
||||||
|
|
||||||
|
@ -170,8 +167,8 @@ conditionally execute the original function.
|
||||||
@function
|
@function
|
||||||
Returns the same value that is used as the argument. In math: f(x) = x.
|
Returns the same value that is used as the argument. In math: f(x) = x.
|
||||||
|
|
||||||
let { identity } = require("sdk/lang/functional");
|
const { identity } = require("sdk/lang/functional");
|
||||||
let x = 5;
|
const x = 5;
|
||||||
identity(x); // 5
|
identity(x); // 5
|
||||||
|
|
||||||
@param value {mixed}
|
@param value {mixed}
|
||||||
|
@ -190,15 +187,15 @@ storing the result, based on the arguments to the original function. The
|
||||||
default `hashFunction` just uses the first argument to the memoized function as
|
default `hashFunction` just uses the first argument to the memoized function as
|
||||||
the key.
|
the key.
|
||||||
|
|
||||||
let { memoize } = require("sdk/lang/functional");
|
const { memoize } = require("sdk/lang/functional");
|
||||||
|
|
||||||
let memoizedFn = memoize(primeFactorization);
|
const memoizedFn = memoize(primeFactorization);
|
||||||
|
|
||||||
memoizedFn(50); // Returns [2, 5, 5], had to compute
|
memoizedFn(50); // Returns [2, 5, 5], had to compute
|
||||||
memoizedFn(100); // Returns [2, 2, 5, 5], had to compute
|
memoizedFn(100); // Returns [2, 2, 5, 5], had to compute
|
||||||
memoizedFn(50); // Returns [2, 5, 5] again, but pulled from cache
|
memoizedFn(50); // Returns [2, 5, 5] again, but pulled from cache
|
||||||
|
|
||||||
function primeFactorization (x) {
|
const primeFactorization = x => {
|
||||||
// Some tricky stuff
|
// Some tricky stuff
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,16 +206,14 @@ the key.
|
||||||
// function will just parse the last name, as our naive
|
// function will just parse the last name, as our naive
|
||||||
// implementation assumes that they will share the same lineage
|
// implementation assumes that they will share the same lineage
|
||||||
|
|
||||||
let getLineage = memoize(function (name) {
|
const getLineage = memoize(name => {
|
||||||
// computes lineage
|
// computes lineage
|
||||||
return data;
|
return data;
|
||||||
}, hasher);
|
}, hasher);
|
||||||
|
|
||||||
// Hashing function takes a string of first and last name
|
// Hashing function takes a string of first and last name
|
||||||
// and returns the last name.
|
// and returns the last name.
|
||||||
function hasher (input) {
|
const hasher = input => input.split(" ")[1];
|
||||||
return input.split(" ")[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
getLineage("homer simpson"); // Computes and returns information for "simpson"
|
getLineage("homer simpson"); // Computes and returns information for "simpson"
|
||||||
getLineage("lisa simpson"); // Returns cached for "simpson"
|
getLineage("lisa simpson"); // Returns cached for "simpson"
|
||||||
|
@ -240,12 +235,11 @@ Much like `setTimeout`, `delay` invokes a function after waiting a set number of
|
||||||
milliseconds. If you pass additional, optional, arguments, they will be forwarded
|
milliseconds. If you pass additional, optional, arguments, they will be forwarded
|
||||||
on to the function when it is invoked.
|
on to the function when it is invoked.
|
||||||
|
|
||||||
let { delay } = require("sdk/lang/functional");
|
const { delay } = require("sdk/lang/functional");
|
||||||
|
|
||||||
|
const printAdd = (a, b) console.log(a + "+" + b + "=" + (a+b));
|
||||||
delay(printAdd, 2000, 5, 10);
|
delay(printAdd, 2000, 5, 10);
|
||||||
|
|
||||||
// Prints "5+10=15" in two seconds (2000ms)
|
// Prints "5+10=15" in two seconds (2000ms)
|
||||||
function printAdd (a, b) { console.log(a + "+" + b + "=" + (a+b)); }
|
|
||||||
|
|
||||||
@param fn {function}
|
@param fn {function}
|
||||||
A function to be delayed.
|
A function to be delayed.
|
||||||
|
@ -264,8 +258,8 @@ Repeated calls to the modified function will have no effect, returning
|
||||||
the value from the original call. Useful for initialization functions, instead
|
the value from the original call. Useful for initialization functions, instead
|
||||||
of having to set a boolean flag and checking it later.
|
of having to set a boolean flag and checking it later.
|
||||||
|
|
||||||
let { once } = require("sdk/lang/functional");
|
const { once } = require("sdk/lang/functional");
|
||||||
let setup = once(function (env) {
|
const setup = once(env => {
|
||||||
// initializing important things
|
// initializing important things
|
||||||
console.log("successfully initialized " + env);
|
console.log("successfully initialized " + env);
|
||||||
return 1; // Assume success and return 1
|
return 1; // Assume success and return 1
|
||||||
|
@ -273,7 +267,7 @@ of having to set a boolean flag and checking it later.
|
||||||
|
|
||||||
setup('dev'); // returns 1
|
setup('dev'); // returns 1
|
||||||
// prints "successfully initialized dev"
|
// prints "successfully initialized dev"
|
||||||
|
|
||||||
// Future attempts to call this function just return the cached
|
// Future attempts to call this function just return the cached
|
||||||
// value that was returned previously
|
// value that was returned previously
|
||||||
setup('production'); // Returns 1
|
setup('production'); // Returns 1
|
||||||
|
@ -286,16 +280,156 @@ of having to set a boolean flag and checking it later.
|
||||||
The wrapped `fn` that can only be executed once.
|
The wrapped `fn` that can only be executed once.
|
||||||
</api>
|
</api>
|
||||||
|
|
||||||
<api name="chain">
|
<api name="cache">
|
||||||
|
@function
|
||||||
|
An alias for [once](modules/sdk/lang/functional.html#once(fn)).
|
||||||
|
</api>
|
||||||
|
|
||||||
|
<api name="complement">
|
||||||
|
@function
|
||||||
|
Takes a `f` function and returns a function that takes the same
|
||||||
|
arguments as `f`, has the same effects, if any, and returns the
|
||||||
|
opposite truth value.
|
||||||
|
|
||||||
|
const { complement } = require("sdk/lang/functional");
|
||||||
|
|
||||||
|
let isOdd = x => Boolean(x % 2);
|
||||||
|
|
||||||
|
isOdd(1) // => true
|
||||||
|
isOdd(2) // => false
|
||||||
|
|
||||||
|
let isEven = complement(isOdd);
|
||||||
|
|
||||||
|
isEven(1) // => false
|
||||||
|
isEven(2) // => true
|
||||||
|
|
||||||
|
@param lambda {function}
|
||||||
|
The function to compose from
|
||||||
|
|
||||||
|
@returns {boolean}
|
||||||
|
`!lambda(...)`
|
||||||
|
</api>
|
||||||
|
|
||||||
|
<api name="constant">
|
||||||
|
@function
|
||||||
|
Constructs function that returns `x` no matter what is it
|
||||||
|
invoked with.
|
||||||
|
|
||||||
|
const { constant } = require("sdk/lang/functional");
|
||||||
|
|
||||||
|
const one = constant(1);
|
||||||
|
|
||||||
|
one(); // => 1
|
||||||
|
one(2); // => 1
|
||||||
|
one.apply({}, 3); // => 1
|
||||||
|
|
||||||
|
@param x {object}
|
||||||
|
Value that will be returned by composed function
|
||||||
|
|
||||||
|
@returns {function}
|
||||||
|
</api>
|
||||||
|
|
||||||
|
|
||||||
|
<api name="apply">
|
||||||
|
@function
|
||||||
|
Apply function that behaves like `apply` in other functional
|
||||||
|
languages:
|
||||||
|
|
||||||
|
const { apply } = require("sdk/lang/functional");
|
||||||
|
|
||||||
|
const dashify = (...args) => args.join("-");
|
||||||
|
|
||||||
|
apply(dashify, 1, [2, 3]); // => "1-2-3"
|
||||||
|
apply(dashify, "a"); // => "a"
|
||||||
|
apply(dashify, ["a", "b"]); // => "a-b"
|
||||||
|
apply(dashify, ["a", "b"], "c"); // => "a,b-c"
|
||||||
|
apply(dashify, [1, 2], [3, 4]); // => "1,2-3-4"
|
||||||
|
|
||||||
|
@param f {function}
|
||||||
|
function to be invoked
|
||||||
|
</api>
|
||||||
|
|
||||||
|
<api name="flip">
|
||||||
|
@function
|
||||||
|
Returns function identical to given `f` but with flipped order
|
||||||
|
of arguments.
|
||||||
|
|
||||||
|
const { flip } = require("sdk/lang/functional");
|
||||||
|
|
||||||
|
const append = (left, right) => left + " " + right;
|
||||||
|
const prepend = flip(append);
|
||||||
|
|
||||||
|
append("hello", "world") // => "hello world"
|
||||||
|
prepend("hello", "world") // => "world hello"
|
||||||
|
|
||||||
|
@param f {function}
|
||||||
|
function whose arguments should to be flipped
|
||||||
|
|
||||||
|
@returns {function}
|
||||||
|
function with flipped arguments
|
||||||
|
</api>
|
||||||
|
|
||||||
|
<api name="when">
|
||||||
|
@function
|
||||||
|
Takes `p` predicate, `consequent` function and an optional
|
||||||
|
`alternate` function and composes function that returns
|
||||||
|
application of arguments over `consequent` if application over
|
||||||
|
`p` is `true` otherwise returns application over `alternate`.
|
||||||
|
If `alternate` is not a function returns `undefined`.
|
||||||
|
|
||||||
|
const { when } = require("sdk/lang/functional");
|
||||||
|
|
||||||
|
function Point(x, y) {
|
||||||
|
this.x = x
|
||||||
|
this.y = y
|
||||||
|
}
|
||||||
|
|
||||||
|
const isPoint = x => x instanceof Point;
|
||||||
|
|
||||||
|
const inc = when(isPoint, ({x, y}) => new Point(x + 1, y + 1));
|
||||||
|
|
||||||
|
inc({}); // => undefined
|
||||||
|
inc(new Point(0, 0)); // => { x: 1, y: 1 }
|
||||||
|
|
||||||
|
const axis = when(isPoint,
|
||||||
|
({ x, y }) => [x, y],
|
||||||
|
_ => [0, 0]);
|
||||||
|
|
||||||
|
axis(new Point(1, 4)); // => [1, 4]
|
||||||
|
axis({ foo: "bar" }); // => [0, 0]
|
||||||
|
|
||||||
|
@param p {function}
|
||||||
|
predicate function whose return value determines to which
|
||||||
|
function be delegated control.
|
||||||
|
|
||||||
|
@param consequent {function}
|
||||||
|
function to which arguments are applied if `predicate` returned
|
||||||
|
`true`.
|
||||||
|
|
||||||
|
@param alternate {function}
|
||||||
|
function to which arguments are applied if `predicate` returned
|
||||||
|
`false`.
|
||||||
|
|
||||||
|
@returns {object|string|number|function}
|
||||||
|
Return value from `consequent` if `p` returned `true` or return
|
||||||
|
value from `alternate` if `p` returned `false`. If `alternate`
|
||||||
|
is not provided and `p` returned `false` then `undefined` is
|
||||||
|
returned.
|
||||||
|
</api>
|
||||||
|
|
||||||
|
|
||||||
|
<api name="chainable">
|
||||||
@function
|
@function
|
||||||
Creates a version of the input function that will return `this`.
|
Creates a version of the input function that will return `this`.
|
||||||
|
|
||||||
let { chain } = require("sdk/lang/functional");
|
const { chainable } = require("sdk/lang/functional");
|
||||||
|
|
||||||
function Person (age) { this.age = age; }
|
function Person (age) { this.age = age; }
|
||||||
Person.prototype.happyBirthday = chain(function () this.age++);
|
Person.prototype.happyBirthday = chainable(function() {
|
||||||
|
return this.age++
|
||||||
|
});
|
||||||
|
|
||||||
let person = new Person(30);
|
const person = new Person(30);
|
||||||
|
|
||||||
person
|
person
|
||||||
.happyBirthday()
|
.happyBirthday()
|
||||||
|
@ -311,7 +445,126 @@ Creates a version of the input function that will return `this`.
|
||||||
The wrapped function that executes `fn` and returns `this`.
|
The wrapped function that executes `fn` and returns `this`.
|
||||||
</api>
|
</api>
|
||||||
|
|
||||||
<api name="cache">
|
<api name="field">
|
||||||
@function
|
@function
|
||||||
An alias for [once](modules/sdk/lang/functional.html#once(fn)).
|
|
||||||
|
Takes field `name` and `target` and returns value of that field.
|
||||||
|
If `target` is `null` or `undefined` it would be returned back
|
||||||
|
instead of attempt to access it's field. Function is implicitly
|
||||||
|
curried, this allows accessor function generation by calling it
|
||||||
|
with only `name` argument.
|
||||||
|
|
||||||
|
const { field } = require("sdk/lang/functional");
|
||||||
|
|
||||||
|
field("x", { x: 1, y: 2}); // => 1
|
||||||
|
field("x")({ x: 1 }); // => 1
|
||||||
|
field("x", { y: 2 }); // => undefiend
|
||||||
|
|
||||||
|
const getX = field("x");
|
||||||
|
getX({ x: 1 }); // => 1
|
||||||
|
getX({ y: 1 }); // => undefined
|
||||||
|
getX(null); // => null
|
||||||
|
|
||||||
|
@param name {string}
|
||||||
|
Name of the field to be returned
|
||||||
|
|
||||||
|
@param target {object}
|
||||||
|
Target to get a field by the given `name` from
|
||||||
|
|
||||||
|
@returns {object|function|string|number|boolean}
|
||||||
|
Field value
|
||||||
|
</api>
|
||||||
|
|
||||||
|
<api name="query">
|
||||||
|
@function
|
||||||
|
|
||||||
|
Takes `.` delimited string representing `path` to a nested field
|
||||||
|
and a `target` to get it from. For convinience function is
|
||||||
|
implicitly curried, there for accessors can be created by invoking
|
||||||
|
it with just a `path` argument.
|
||||||
|
|
||||||
|
const { query } = require("sdk/lang/functional");
|
||||||
|
|
||||||
|
query("x", { x: 1, y: 2}); // => 1
|
||||||
|
query("top.x", { x: 1 }); // => undefiend
|
||||||
|
query("top.x", { top: { x: 2 } }); // => 2
|
||||||
|
|
||||||
|
const topX = query("top.x");
|
||||||
|
topX({ top: { x: 1 } }); // => 1
|
||||||
|
topX({ y: 1 }); // => undefined
|
||||||
|
topX(null); // => null
|
||||||
|
|
||||||
|
@param path {string}
|
||||||
|
`.` delimited path to a field
|
||||||
|
|
||||||
|
@param target {object}
|
||||||
|
Target to get a field by the given `name` from
|
||||||
|
|
||||||
|
@returns {object|function|string|number|boolean}
|
||||||
|
Field value
|
||||||
|
</api>
|
||||||
|
|
||||||
|
<api name="isInstance">
|
||||||
|
@function
|
||||||
|
|
||||||
|
Takes `Type` (constructor function) and a `value` and returns
|
||||||
|
`true` if `value` is instance of the given `Type`. Function is
|
||||||
|
implicitly curried this allows predicate generation by calling
|
||||||
|
function with just first argument.
|
||||||
|
|
||||||
|
const { isInstance } = require("sdk/lang/functional");
|
||||||
|
|
||||||
|
function X() {}
|
||||||
|
function Y() {}
|
||||||
|
let isX = isInstance(X);
|
||||||
|
|
||||||
|
isInstance(X, new X); // true
|
||||||
|
isInstance(X)(new X); // true
|
||||||
|
isInstance(X, new Y); // false
|
||||||
|
isInstance(X)(new Y); // false
|
||||||
|
|
||||||
|
isX(new X); // true
|
||||||
|
isX(new Y); // false
|
||||||
|
|
||||||
|
@param Type {function}
|
||||||
|
Type (constructor function)
|
||||||
|
|
||||||
|
@param instance {object}
|
||||||
|
Instance to test
|
||||||
|
|
||||||
|
@returns {boolean}
|
||||||
|
</api>
|
||||||
|
|
||||||
|
<api name="is">
|
||||||
|
@function
|
||||||
|
|
||||||
|
Functions takes `expected` and `actual` values and returns `true` if
|
||||||
|
`expected === actual`. If invoked with just one argument returns pratially
|
||||||
|
applied function, which can be invoked to provide a second argument, this
|
||||||
|
is handy with `map`, `filter` and other high order functions:
|
||||||
|
|
||||||
|
const { is } = require("sdk/util/oops");
|
||||||
|
[ 1, 0, 1, 0, 1 ].map(is(1)) // => [ true, false, true, false, true ]
|
||||||
|
|
||||||
|
@param expected {object|string|number|boolean}
|
||||||
|
@param actual {object|string|number|boolean}
|
||||||
|
|
||||||
|
@returns {boolean}
|
||||||
|
</api>
|
||||||
|
|
||||||
|
<api name="isnt">
|
||||||
|
@function
|
||||||
|
|
||||||
|
Functions takes `expected` and `actual` values and returns `true` if
|
||||||
|
`expected !== actual`. If invoked with just one argument returns pratially
|
||||||
|
applied function, which can be invoked with a second argument, which is
|
||||||
|
handy with `map`, `filter` and other high order functions:
|
||||||
|
|
||||||
|
const { isnt } = require("sdk/util/oops");
|
||||||
|
[ 1, 0, 1, 0, 1 ].map(isnt(0)) // => [ true, false, true, false, true ]
|
||||||
|
|
||||||
|
@param expected {object|string|number|boolean}
|
||||||
|
@param actual {object|string|number|boolean}
|
||||||
|
|
||||||
|
@returns {boolean}
|
||||||
</api>
|
</api>
|
||||||
|
|
|
@ -9,7 +9,7 @@ module.metadata = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const { on, once, off, setListeners } = require('./core');
|
const { on, once, off, setListeners } = require('./core');
|
||||||
const { method, chain } = require('../lang/functional');
|
const { method, chainable } = require('../lang/functional');
|
||||||
const { Class } = require('../core/heritage');
|
const { Class } = require('../core/heritage');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -43,7 +43,7 @@ const EventTarget = Class({
|
||||||
* console.log('data received: ' + data)
|
* console.log('data received: ' + data)
|
||||||
* })
|
* })
|
||||||
*/
|
*/
|
||||||
on: chain(method(on)),
|
on: chainable(method(on)),
|
||||||
/**
|
/**
|
||||||
* Registers an event `listener` that is called once the next time an event
|
* Registers an event `listener` that is called once the next time an event
|
||||||
* of the specified `type` is emitted.
|
* of the specified `type` is emitted.
|
||||||
|
@ -52,7 +52,7 @@ const EventTarget = Class({
|
||||||
* @param {Function} listener
|
* @param {Function} listener
|
||||||
* The listener function that processes the event.
|
* The listener function that processes the event.
|
||||||
*/
|
*/
|
||||||
once: chain(method(once)),
|
once: chainable(method(once)),
|
||||||
/**
|
/**
|
||||||
* Removes an event `listener` for the given event `type`.
|
* Removes an event `listener` for the given event `type`.
|
||||||
* @param {String} type
|
* @param {String} type
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
// Disclaimer: Most of the functions in this module implement APIs from
|
// Disclaimer: Some of the functions in this module implement APIs from
|
||||||
// Jeremy Ashkenas's http://underscorejs.org/ library and all credits for
|
// Jeremy Ashkenas's http://underscorejs.org/ library and all credits for
|
||||||
// those goes to him.
|
// those goes to him.
|
||||||
|
|
||||||
|
@ -12,19 +12,33 @@ module.metadata = {
|
||||||
"stability": "unstable"
|
"stability": "unstable"
|
||||||
};
|
};
|
||||||
|
|
||||||
const { setImmediate, setTimeout } = require("../timers");
|
|
||||||
const { deprecateFunction } = require("../util/deprecate");
|
const { deprecateFunction } = require("../util/deprecate");
|
||||||
|
const { setImmediate, setTimeout } = require("../timers");
|
||||||
|
|
||||||
|
const arity = f => f.arity || f.length;
|
||||||
|
|
||||||
|
const name = f => f.displayName || f.name;
|
||||||
|
|
||||||
|
const derive = (f, source) => {
|
||||||
|
f.displayName = name(source);
|
||||||
|
f.arity = arity(source);
|
||||||
|
return f;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes `lambda` function and returns a method. When returned method is
|
* Takes variadic numeber of functions and returns composed one.
|
||||||
* invoked it calls wrapped `lambda` and passes `this` as a first argument
|
* Returned function pushes `this` pseudo-variable to the head
|
||||||
* and given argument as rest.
|
* of the passed arguments and invokes all the functions from
|
||||||
|
* left to right passing same arguments to them. Composite function
|
||||||
|
* returns return value of the right most funciton.
|
||||||
*/
|
*/
|
||||||
function method(lambda) {
|
const method = (...lambdas) => {
|
||||||
return function method() {
|
return function method(...args) {
|
||||||
return lambda.apply(null, [this].concat(Array.slice(arguments)));
|
args.unshift(this);
|
||||||
}
|
return lambdas.reduce((_, lambda) => lambda.apply(this, args),
|
||||||
}
|
void(0));
|
||||||
|
};
|
||||||
|
};
|
||||||
exports.method = method;
|
exports.method = method;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -34,24 +48,13 @@ exports.method = method;
|
||||||
* function is reused, instead of creating a new one each time. This also allows
|
* function is reused, instead of creating a new one each time. This also allows
|
||||||
* to use this functions as event listeners.
|
* to use this functions as event listeners.
|
||||||
*/
|
*/
|
||||||
function defer(f) {
|
const defer = f => derive(function(...args) {
|
||||||
return function deferred() setImmediate(invoke, f, arguments, this);
|
setImmediate(invoke, f, args, this);
|
||||||
}
|
}, f);
|
||||||
exports.defer = defer;
|
exports.defer = defer;
|
||||||
// Exporting `remit` alias as `defer` may conflict with promises.
|
// Exporting `remit` alias as `defer` may conflict with promises.
|
||||||
exports.remit = defer;
|
exports.remit = defer;
|
||||||
|
|
||||||
/*
|
|
||||||
* Takes a funtion and returns a wrapped function that returns `this`
|
|
||||||
*/
|
|
||||||
function chain(f) {
|
|
||||||
return function chainable(...args) {
|
|
||||||
f.apply(this, args);
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
exports.chain = chain;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invokes `callee` by passing `params` as an arguments and `self` as `this`
|
* Invokes `callee` by passing `params` as an arguments and `self` as `this`
|
||||||
* pseudo-variable. Returns value that is returned by a callee.
|
* pseudo-variable. Returns value that is returned by a callee.
|
||||||
|
@ -62,7 +65,7 @@ exports.chain = chain;
|
||||||
* @param {Object} self
|
* @param {Object} self
|
||||||
* Object to be passed as a `this` pseudo variable.
|
* Object to be passed as a `this` pseudo variable.
|
||||||
*/
|
*/
|
||||||
function invoke(callee, params, self) callee.apply(self, params);
|
const invoke = (callee, params, self) => callee.apply(self, params);
|
||||||
exports.invoke = invoke;
|
exports.invoke = invoke;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -74,14 +77,16 @@ exports.invoke = invoke;
|
||||||
*
|
*
|
||||||
* @returns The new function with binded values
|
* @returns The new function with binded values
|
||||||
*/
|
*/
|
||||||
function partial(fn) {
|
const partial = (f, ...curried) => {
|
||||||
if (typeof fn !== "function")
|
if (typeof(f) !== "function")
|
||||||
throw new TypeError(String(fn) + " is not a function");
|
throw new TypeError(String(f) + " is not a function");
|
||||||
|
|
||||||
let args = Array.slice(arguments, 1);
|
let fn = derive(function(...args) {
|
||||||
|
return f.apply(this, curried.concat(args));
|
||||||
return function() fn.apply(this, args.concat(Array.slice(arguments)));
|
}, f);
|
||||||
}
|
fn.arity = arity(f) - curried.length;
|
||||||
|
return fn;
|
||||||
|
};
|
||||||
exports.partial = partial;
|
exports.partial = partial;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -98,12 +103,11 @@ exports.partial = partial;
|
||||||
* console.log(sum(2, 2)) // 4
|
* console.log(sum(2, 2)) // 4
|
||||||
* console.log(sum(2)(4)) // 6
|
* console.log(sum(2)(4)) // 6
|
||||||
*/
|
*/
|
||||||
var curry = new function() {
|
const curry = new function() {
|
||||||
function currier(fn, arity, params) {
|
const currier = (fn, arity, params) => {
|
||||||
// Function either continues to curry arguments or executes function
|
// Function either continues to curry arguments or executes function
|
||||||
// if desired arguments have being collected.
|
// if desired arguments have being collected.
|
||||||
return function curried() {
|
const curried = function(...input) {
|
||||||
var input = Array.slice(arguments);
|
|
||||||
// Prepend all curried arguments to the given arguments.
|
// Prepend all curried arguments to the given arguments.
|
||||||
if (params) input.unshift.apply(input, params);
|
if (params) input.unshift.apply(input, params);
|
||||||
// If expected number of arguments has being collected invoke fn,
|
// If expected number of arguments has being collected invoke fn,
|
||||||
|
@ -111,11 +115,12 @@ var curry = new function() {
|
||||||
return (input.length >= arity) ? fn.apply(this, input) :
|
return (input.length >= arity) ? fn.apply(this, input) :
|
||||||
currier(fn, arity, input);
|
currier(fn, arity, input);
|
||||||
};
|
};
|
||||||
}
|
curried.arity = arity - (params ? params.length : 0);
|
||||||
|
|
||||||
return function curry(fn) {
|
return curried;
|
||||||
return currier(fn, fn.length);
|
};
|
||||||
}
|
|
||||||
|
return fn => currier(fn, arity(fn));
|
||||||
};
|
};
|
||||||
exports.curry = curry;
|
exports.curry = curry;
|
||||||
|
|
||||||
|
@ -131,12 +136,12 @@ exports.curry = curry;
|
||||||
*
|
*
|
||||||
* welcome('moe'); // => 'hi: moe!'
|
* welcome('moe'); // => 'hi: moe!'
|
||||||
*/
|
*/
|
||||||
function compose() {
|
function compose(...lambdas) {
|
||||||
let lambdas = Array.slice(arguments);
|
return function composed(...args) {
|
||||||
return function composed() {
|
let index = lambdas.length;
|
||||||
let args = Array.slice(arguments), index = lambdas.length;
|
|
||||||
while (0 <= --index)
|
while (0 <= --index)
|
||||||
args = [ lambdas[index].apply(this, args) ];
|
args = [lambdas[index].apply(this, args)];
|
||||||
|
|
||||||
return args[0];
|
return args[0];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -155,16 +160,15 @@ exports.compose = compose;
|
||||||
*
|
*
|
||||||
* hello(); // => 'before, hello: moe, after'
|
* hello(); // => 'before, hello: moe, after'
|
||||||
*/
|
*/
|
||||||
function wrap(f, wrapper) {
|
const wrap = (f, wrapper) => derive(function wrapped(...args) {
|
||||||
return function wrapped()
|
return wrapper.apply(this, [f].concat(args));
|
||||||
wrapper.apply(this, [ f ].concat(Array.slice(arguments)))
|
}, f);
|
||||||
};
|
|
||||||
exports.wrap = wrap;
|
exports.wrap = wrap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the same value that is used as the argument. In math: f(x) = x
|
* Returns the same value that is used as the argument. In math: f(x) = x
|
||||||
*/
|
*/
|
||||||
function identity(value) value
|
const identity = value => value;
|
||||||
exports.identity = identity;
|
exports.identity = identity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -174,14 +178,25 @@ exports.identity = identity;
|
||||||
* the arguments to the original function. The default hashFunction just uses
|
* the arguments to the original function. The default hashFunction just uses
|
||||||
* the first argument to the memoized function as the key.
|
* the first argument to the memoized function as the key.
|
||||||
*/
|
*/
|
||||||
function memoize(f, hasher) {
|
const memoize = (f, hasher) => {
|
||||||
let memo = Object.create(null);
|
let memo = Object.create(null);
|
||||||
|
let cache = new WeakMap();
|
||||||
hasher = hasher || identity;
|
hasher = hasher || identity;
|
||||||
return function memoizer() {
|
return derive(function memoizer(...args) {
|
||||||
let key = hasher.apply(this, arguments);
|
const key = hasher.apply(this, args);
|
||||||
return key in memo ? memo[key] : (memo[key] = f.apply(this, arguments));
|
const type = typeof(key);
|
||||||
};
|
if (key && (type === "object" || type === "function")) {
|
||||||
}
|
if (!cache.has(key))
|
||||||
|
cache.set(key, f.apply(this, args));
|
||||||
|
return cache.get(key);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!(key in memo))
|
||||||
|
memo[key] = f.apply(this, args);
|
||||||
|
return memo[key];
|
||||||
|
}
|
||||||
|
}, f);
|
||||||
|
};
|
||||||
exports.memoize = memoize;
|
exports.memoize = memoize;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -189,9 +204,8 @@ exports.memoize = memoize;
|
||||||
* the optional arguments, they will be forwarded on to the function when it is
|
* the optional arguments, they will be forwarded on to the function when it is
|
||||||
* invoked.
|
* invoked.
|
||||||
*/
|
*/
|
||||||
function delay(f, ms) {
|
const delay = function delay(f, ms, ...args) {
|
||||||
let args = Array.slice(arguments, 2);
|
setTimeout(() => f.apply(this, args), ms);
|
||||||
setTimeout(function(context) { return f.apply(context, args); }, ms, this);
|
|
||||||
};
|
};
|
||||||
exports.delay = delay;
|
exports.delay = delay;
|
||||||
|
|
||||||
|
@ -201,10 +215,116 @@ exports.delay = delay;
|
||||||
* the original call. Useful for initialization functions, instead of having to
|
* the original call. Useful for initialization functions, instead of having to
|
||||||
* set a boolean flag and then check it later.
|
* set a boolean flag and then check it later.
|
||||||
*/
|
*/
|
||||||
function once(f) {
|
const once = f => {
|
||||||
let ran = false, cache;
|
let ran = false, cache;
|
||||||
return function() ran ? cache : (ran = true, cache = f.apply(this, arguments))
|
return derive(function(...args) {
|
||||||
|
return ran ? cache : (ran = true, cache = f.apply(this, args));
|
||||||
|
}, f);
|
||||||
};
|
};
|
||||||
exports.once = once;
|
exports.once = once;
|
||||||
// export cache as once will may be conflicting with event once a lot.
|
// export cache as once will may be conflicting with event once a lot.
|
||||||
exports.cache = once;
|
exports.cache = once;
|
||||||
|
|
||||||
|
// Takes a `f` function and returns a function that takes the same
|
||||||
|
// arguments as `f`, has the same effects, if any, and returns the
|
||||||
|
// opposite truth value.
|
||||||
|
const complement = f => derive(function(...args) {
|
||||||
|
return args.length < arity(f) ? complement(partial(f, ...args)) :
|
||||||
|
!f.apply(this, args);
|
||||||
|
}, f);
|
||||||
|
exports.complement = complement;
|
||||||
|
|
||||||
|
// Constructs function that returns `x` no matter what is it
|
||||||
|
// invoked with.
|
||||||
|
const constant = x => _ => x;
|
||||||
|
exports.constant = constant;
|
||||||
|
|
||||||
|
// Takes `p` predicate, `consequent` function and an optional
|
||||||
|
// `alternate` function and composes function that returns
|
||||||
|
// application of arguments over `consequent` if application over
|
||||||
|
// `p` is `true` otherwise returns application over `alternate`.
|
||||||
|
// If `alternate` is not a function returns `undefined`.
|
||||||
|
const when = (p, consequent, alternate) => {
|
||||||
|
if (typeof(alternate) !== "function" && alternate !== void(0))
|
||||||
|
throw TypeError("alternate must be a function");
|
||||||
|
if (typeof(consequent) !== "function")
|
||||||
|
throw TypeError("consequent must be a function");
|
||||||
|
|
||||||
|
return function(...args) {
|
||||||
|
return p.apply(this, args) ?
|
||||||
|
consequent.apply(this, args) :
|
||||||
|
alternate && alternate.apply(this, args);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
exports.when = when;
|
||||||
|
|
||||||
|
// Apply function that behaves as `apply` does in lisp:
|
||||||
|
// apply(f, x, [y, z]) => f.apply(f, [x, y, z])
|
||||||
|
// apply(f, x) => f.apply(f, [x])
|
||||||
|
const apply = (f, ...rest) => f.apply(f, rest.concat(rest.pop()));
|
||||||
|
exports.apply = apply;
|
||||||
|
|
||||||
|
// Returns function identical to given `f` but with flipped order
|
||||||
|
// of arguments.
|
||||||
|
const flip = f => derive(function(...args) {
|
||||||
|
return f.apply(this, args.reverse());
|
||||||
|
}, f);
|
||||||
|
exports.flip = flip;
|
||||||
|
|
||||||
|
|
||||||
|
// Takes field `name` and `target` and returns value of that field.
|
||||||
|
// If `target` is `null` or `undefined` it would be returned back
|
||||||
|
// instead of attempt to access it's field. Function is implicitly
|
||||||
|
// curried, this allows accessor function generation by calling it
|
||||||
|
// with only `name` argument.
|
||||||
|
const field = curry((name, target) =>
|
||||||
|
// Note: Permisive `==` is intentional.
|
||||||
|
target == null ? target : target[name]);
|
||||||
|
exports.field = field;
|
||||||
|
|
||||||
|
// Takes `.` delimited string representing `path` to a nested field
|
||||||
|
// and a `target` to get it from. For convinience function is
|
||||||
|
// implicitly curried, there for accessors can be created by invoking
|
||||||
|
// it with just a `path` argument.
|
||||||
|
const query = curry((path, target) => {
|
||||||
|
const names = path.split(".");
|
||||||
|
const count = names.length;
|
||||||
|
let index = 0;
|
||||||
|
let result = target;
|
||||||
|
// Note: Permisive `!=` is intentional.
|
||||||
|
while (result != null && index < count) {
|
||||||
|
result = result[names[index]];
|
||||||
|
index = index + 1;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
exports.query = query;
|
||||||
|
|
||||||
|
// Takes `Type` (constructor function) and a `value` and returns
|
||||||
|
// `true` if `value` is instance of the given `Type`. Function is
|
||||||
|
// implicitly curried this allows predicate generation by calling
|
||||||
|
// function with just first argument.
|
||||||
|
const isInstance = curry((Type, value) => value instanceof Type);
|
||||||
|
exports.isInstance = isInstance;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Takes a funtion and returns a wrapped function that returns `this`
|
||||||
|
*/
|
||||||
|
const chainable = f => derive(function(...args) {
|
||||||
|
f.apply(this, args);
|
||||||
|
return this;
|
||||||
|
}, f);
|
||||||
|
exports.chainable = chainable;
|
||||||
|
exports.chain =
|
||||||
|
deprecateFunction(chainable, "Function `chain` was renamed to `chainable`");
|
||||||
|
|
||||||
|
// Functions takes `expected` and `actual` values and returns `true` if
|
||||||
|
// `expected === actual`. Returns curried function if called with less then
|
||||||
|
// two arguments.
|
||||||
|
//
|
||||||
|
// [ 1, 0, 1, 0, 1 ].map(is(1)) // => [ true, false, true, false, true ]
|
||||||
|
const is = curry((expected, actual) => actual === expected);
|
||||||
|
exports.is = is;
|
||||||
|
|
||||||
|
const isnt = complement(is);
|
||||||
|
exports.isnt = isnt;
|
||||||
|
|
|
@ -1,21 +1,22 @@
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
const { setTimeout } = require('sdk/timers');
|
const { setTimeout } = require('sdk/timers');
|
||||||
const utils = require('sdk/lang/functional');
|
const utils = require('sdk/lang/functional');
|
||||||
const { invoke, defer, partial, compose, memoize, once, delay, wrap, curry, chain } = utils;
|
const { invoke, defer, partial, compose, memoize, once, is, isnt,
|
||||||
|
delay, wrap, curry, chainable, field, query, isInstance } = utils;
|
||||||
const { LoaderWithHookedConsole } = require('sdk/test/loader');
|
const { LoaderWithHookedConsole } = require('sdk/test/loader');
|
||||||
|
|
||||||
exports['test forwardApply'] = function(assert) {
|
exports['test forwardApply'] = function(assert) {
|
||||||
function sum(b, c) this.a + b + c
|
function sum(b, c) { return this.a + b + c; }
|
||||||
assert.equal(invoke(sum, [2, 3], { a: 1 }), 6,
|
assert.equal(invoke(sum, [2, 3], { a: 1 }), 6,
|
||||||
'passed arguments and pseoude-variable are used');
|
'passed arguments and pseoude-variable are used');
|
||||||
|
|
||||||
assert.equal(invoke(sum.bind({ a: 2 }), [2, 3], { a: 1 }), 7,
|
assert.equal(invoke(sum.bind({ a: 2 }), [2, 3], { a: 1 }), 7,
|
||||||
'bounded `this` pseoudo variable is used');
|
'bounded `this` pseoudo variable is used');
|
||||||
}
|
};
|
||||||
|
|
||||||
exports['test deferred function'] = function(assert, done) {
|
exports['test deferred function'] = function(assert, done) {
|
||||||
let nextTurn = false;
|
let nextTurn = false;
|
||||||
|
@ -26,13 +27,13 @@ exports['test deferred function'] = function(assert, done) {
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
|
|
||||||
let fixture = { a: 1, method: defer(sum) }
|
let fixture = { a: 1, method: defer(sum) };
|
||||||
fixture.method(2, 3);
|
fixture.method(2, 3);
|
||||||
nextTurn = true;
|
nextTurn = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
exports['test partial function'] = function(assert) {
|
exports['test partial function'] = function(assert) {
|
||||||
function sum(b, c) this.a + b + c;
|
function sum(b, c) { return this.a + b + c; }
|
||||||
|
|
||||||
let foo = { a : 5 };
|
let foo = { a : 5 };
|
||||||
|
|
||||||
|
@ -68,11 +69,11 @@ exports['test compose'] = function(assert) {
|
||||||
let target = {
|
let target = {
|
||||||
name: 'Joe',
|
name: 'Joe',
|
||||||
greet: compose(function exclaim(sentence) {
|
greet: compose(function exclaim(sentence) {
|
||||||
return sentence + '!'
|
return sentence + '!';
|
||||||
}, function(title) {
|
}, function(title) {
|
||||||
return 'hi : ' + title + ' ' + this.name;
|
return 'hi : ' + title + ' ' + this.name;
|
||||||
})
|
})
|
||||||
}
|
};
|
||||||
|
|
||||||
assert.equal(target.greet('Mr'), 'hi : Mr Joe!',
|
assert.equal(target.greet('Mr'), 'hi : Mr Joe!',
|
||||||
'this can be passed in');
|
'this can be passed in');
|
||||||
|
@ -106,7 +107,7 @@ exports['test wrap'] = function(assert) {
|
||||||
|
|
||||||
assert.equal(target.hi(), 'Hello Matteo', 'works with this');
|
assert.equal(target.hi(), 'Hello Matteo', 'works with this');
|
||||||
|
|
||||||
function noop() { };
|
function noop() { }
|
||||||
let wrapped = wrap(noop, function(f) {
|
let wrapped = wrap(noop, function(f) {
|
||||||
return Array.slice(arguments);
|
return Array.slice(arguments);
|
||||||
});
|
});
|
||||||
|
@ -117,7 +118,7 @@ exports['test wrap'] = function(assert) {
|
||||||
};
|
};
|
||||||
|
|
||||||
exports['test memoize'] = function(assert) {
|
exports['test memoize'] = function(assert) {
|
||||||
function fib(n) n < 2 ? n : fib(n - 1) + fib(n - 2)
|
const fib = n => n < 2 ? n : fib(n - 1) + fib(n - 2);
|
||||||
let fibnitro = memoize(fib);
|
let fibnitro = memoize(fib);
|
||||||
|
|
||||||
assert.equal(fib(10), 55,
|
assert.equal(fib(10), 55,
|
||||||
|
@ -125,7 +126,7 @@ exports['test memoize'] = function(assert) {
|
||||||
assert.equal(fibnitro(10), 55,
|
assert.equal(fibnitro(10), 55,
|
||||||
'a memoized version of fibonacci produces identical results');
|
'a memoized version of fibonacci produces identical results');
|
||||||
|
|
||||||
function o(key, value) { return value; };
|
function o(key, value) { return value; }
|
||||||
let oo = memoize(o), v1 = {}, v2 = {};
|
let oo = memoize(o), v1 = {}, v2 = {};
|
||||||
|
|
||||||
|
|
||||||
|
@ -136,12 +137,12 @@ exports['test memoize'] = function(assert) {
|
||||||
assert.notEqual(oo(1), oo(2), 'values do not override');
|
assert.notEqual(oo(1), oo(2), 'values do not override');
|
||||||
assert.equal(o(3, v2), oo(2, 3), 'returns same value as un-memoized');
|
assert.equal(o(3, v2), oo(2, 3), 'returns same value as un-memoized');
|
||||||
|
|
||||||
let get = memoize(function(attribute) this[attribute])
|
let get = memoize(function(attribute) { return this[attribute]; });
|
||||||
let target = { name: 'Bob', get: get }
|
let target = { name: 'Bob', get: get };
|
||||||
|
|
||||||
assert.equal(target.get('name'), 'Bob', 'has correct `this`');
|
assert.equal(target.get('name'), 'Bob', 'has correct `this`');
|
||||||
assert.equal(target.get.call({ name: 'Jack' }, 'name'), 'Bob',
|
assert.equal(target.get.call({ name: 'Jack' }, 'name'), 'Bob',
|
||||||
'name is memoized')
|
'name is memoized');
|
||||||
assert.equal(get('name'), 'Bob', 'once memoized can be called without this');
|
assert.equal(get('name'), 'Bob', 'once memoized can be called without this');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -155,13 +156,13 @@ exports['test delay'] = function(assert, done) {
|
||||||
};
|
};
|
||||||
|
|
||||||
exports['test delay with this'] = function(assert, done) {
|
exports['test delay with this'] = function(assert, done) {
|
||||||
let context = {}
|
let context = {};
|
||||||
delay.call(context, function(name) {
|
delay.call(context, function(name) {
|
||||||
assert.equal(this, context, 'this was passed in');
|
assert.equal(this, context, 'this was passed in');
|
||||||
assert.equal(name, 'Tom', 'argument was passed in');
|
assert.equal(name, 'Tom', 'argument was passed in');
|
||||||
done();
|
done();
|
||||||
}, 10, 'Tom');
|
}, 10, 'Tom');
|
||||||
}
|
};
|
||||||
|
|
||||||
exports['test once'] = function(assert) {
|
exports['test once'] = function(assert) {
|
||||||
let n = 0;
|
let n = 0;
|
||||||
|
@ -172,7 +173,12 @@ exports['test once'] = function(assert) {
|
||||||
|
|
||||||
assert.equal(n, 1, 'only incremented once');
|
assert.equal(n, 1, 'only incremented once');
|
||||||
|
|
||||||
let target = { state: 0, update: once(function() this.state ++ ) };
|
let target = {
|
||||||
|
state: 0,
|
||||||
|
update: once(function() {
|
||||||
|
return this.state ++;
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
target.update();
|
target.update();
|
||||||
target.update();
|
target.update();
|
||||||
|
@ -182,7 +188,7 @@ exports['test once'] = function(assert) {
|
||||||
|
|
||||||
exports['test once with argument'] = function(assert) {
|
exports['test once with argument'] = function(assert) {
|
||||||
let n = 0;
|
let n = 0;
|
||||||
let increment = once(function(a) n++);
|
let increment = once(a => n++);
|
||||||
|
|
||||||
increment();
|
increment();
|
||||||
increment('foo');
|
increment('foo');
|
||||||
|
@ -195,11 +201,121 @@ exports['test once with argument'] = function(assert) {
|
||||||
assert.equal(n, 1, 'only incremented once');
|
assert.equal(n, 1, 'only incremented once');
|
||||||
};
|
};
|
||||||
|
|
||||||
exports['test chain'] = function (assert) {
|
exports['test complement'] = assert => {
|
||||||
|
let { complement } = require("sdk/lang/functional");
|
||||||
|
|
||||||
|
let isOdd = x => Boolean(x % 2);
|
||||||
|
|
||||||
|
assert.equal(isOdd(1), true);
|
||||||
|
assert.equal(isOdd(2), false);
|
||||||
|
|
||||||
|
let isEven = complement(isOdd);
|
||||||
|
|
||||||
|
assert.equal(isEven(1), false);
|
||||||
|
assert.equal(isEven(2), true);
|
||||||
|
|
||||||
|
let foo = {};
|
||||||
|
let isFoo = function() { return this === foo; };
|
||||||
|
let insntFoo = complement(isFoo);
|
||||||
|
|
||||||
|
assert.equal(insntFoo.call(foo), false);
|
||||||
|
assert.equal(insntFoo.call({}), true);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports['test constant'] = assert => {
|
||||||
|
let { constant } = require("sdk/lang/functional");
|
||||||
|
|
||||||
|
let one = constant(1);
|
||||||
|
|
||||||
|
assert.equal(one(1), 1);
|
||||||
|
assert.equal(one(2), 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports['test apply'] = assert => {
|
||||||
|
let { apply } = require("sdk/lang/functional");
|
||||||
|
|
||||||
|
let dashify = (...args) => args.join("-");
|
||||||
|
|
||||||
|
assert.equal(apply(dashify, 1, [2, 3]), "1-2-3");
|
||||||
|
assert.equal(apply(dashify, "a"), "a");
|
||||||
|
assert.equal(apply(dashify, ["a", "b"]), "a-b");
|
||||||
|
assert.equal(apply(dashify, ["a", "b"], "c"), "a,b-c");
|
||||||
|
assert.equal(apply(dashify, [1, 2], [3, 4]), "1,2-3-4");
|
||||||
|
};
|
||||||
|
|
||||||
|
exports['test flip'] = assert => {
|
||||||
|
let { flip } = require("sdk/lang/functional");
|
||||||
|
|
||||||
|
let append = (left, right) => left + " " + right;
|
||||||
|
let prepend = flip(append);
|
||||||
|
|
||||||
|
assert.equal(append("hello", "world"), "hello world");
|
||||||
|
assert.equal(prepend("hello", "world"), "world hello");
|
||||||
|
|
||||||
|
let wrap = function(left, right) {
|
||||||
|
return left + " " + this + " " + right;
|
||||||
|
};
|
||||||
|
let invertWrap = flip(wrap);
|
||||||
|
|
||||||
|
assert.equal(wrap.call("@", "hello", "world"), "hello @ world");
|
||||||
|
assert.equal(invertWrap.call("@", "hello", "world"), "world @ hello");
|
||||||
|
|
||||||
|
let reverse = flip((...args) => args);
|
||||||
|
|
||||||
|
assert.deepEqual(reverse(1, 2, 3, 4), [4, 3, 2, 1]);
|
||||||
|
assert.deepEqual(reverse(1), [1]);
|
||||||
|
assert.deepEqual(reverse(), []);
|
||||||
|
|
||||||
|
// currying still works
|
||||||
|
let prependr = curry(prepend);
|
||||||
|
|
||||||
|
assert.equal(prependr("hello", "world"), "world hello");
|
||||||
|
assert.equal(prependr("hello")("world"), "world hello");
|
||||||
|
};
|
||||||
|
|
||||||
|
exports["test when"] = assert => {
|
||||||
|
let { when } = require("sdk/lang/functional");
|
||||||
|
|
||||||
|
let areNums = (...xs) => xs.every(x => typeof(x) === "number");
|
||||||
|
|
||||||
|
let sum = when(areNums, (...xs) => xs.reduce((y, x) => x + y, 0));
|
||||||
|
|
||||||
|
assert.equal(sum(1, 2, 3), 6);
|
||||||
|
assert.equal(sum(1, 2, "3"), undefined);
|
||||||
|
|
||||||
|
let multiply = when(areNums,
|
||||||
|
(...xs) => xs.reduce((y, x) => x * y, 1),
|
||||||
|
(...xs) => xs);
|
||||||
|
|
||||||
|
assert.equal(multiply(2), 2);
|
||||||
|
assert.equal(multiply(2, 3), 6);
|
||||||
|
assert.deepEqual(multiply(2, "4"), [2, "4"]);
|
||||||
|
|
||||||
|
function Point(x, y) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
let isPoint = x => x instanceof Point;
|
||||||
|
|
||||||
|
let inc = when(isPoint, ({x, y}) => new Point(x + 1, y + 1));
|
||||||
|
|
||||||
|
assert.equal(inc({}), undefined);
|
||||||
|
assert.deepEqual(inc(new Point(0, 0)), { x: 1, y: 1 });
|
||||||
|
|
||||||
|
let axis = when(isPoint,
|
||||||
|
({ x, y }) => [x, y],
|
||||||
|
_ => [0, 0]);
|
||||||
|
|
||||||
|
assert.deepEqual(axis(new Point(1, 4)), [1, 4]);
|
||||||
|
assert.deepEqual(axis({ foo: "bar" }), [0, 0]);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports["test chainable"] = function(assert) {
|
||||||
let Player = function () { this.volume = 5; };
|
let Player = function () { this.volume = 5; };
|
||||||
Player.prototype = {
|
Player.prototype = {
|
||||||
setBand: chain(function (band) this.band = band),
|
setBand: chainable(function (band) { return (this.band = band); }),
|
||||||
incVolume: chain(function () this.volume++)
|
incVolume: chainable(function () { return this.volume++; })
|
||||||
};
|
};
|
||||||
let player = new Player();
|
let player = new Player();
|
||||||
player
|
player
|
||||||
|
@ -210,4 +326,97 @@ exports['test chain'] = function (assert) {
|
||||||
assert.equal(player.volume, 11, 'accepts no arguments in chain');
|
assert.equal(player.volume, 11, 'accepts no arguments in chain');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports["test field"] = assert => {
|
||||||
|
let Num = field("constructor", 0);
|
||||||
|
assert.equal(Num.name, Number.name);
|
||||||
|
assert.ok(typeof(Num), "function");
|
||||||
|
|
||||||
|
let x = field("x");
|
||||||
|
|
||||||
|
[
|
||||||
|
[field("foo", { foo: 1 }), 1],
|
||||||
|
[field("foo")({ foo: 1 }), 1],
|
||||||
|
[field("bar", {}), undefined],
|
||||||
|
[field("bar")({}), undefined],
|
||||||
|
[field("hey", undefined), undefined],
|
||||||
|
[field("hey")(undefined), undefined],
|
||||||
|
[field("how", null), null],
|
||||||
|
[field("how")(null), null],
|
||||||
|
[x(1), undefined],
|
||||||
|
[x(undefined), undefined],
|
||||||
|
[x(null), null],
|
||||||
|
[x({ x: 1 }), 1],
|
||||||
|
[x({ x: 2 }), 2],
|
||||||
|
].forEach(([actual, expected]) => assert.equal(actual, expected));
|
||||||
|
};
|
||||||
|
|
||||||
|
exports["test query"] = assert => {
|
||||||
|
let Num = query("constructor", 0);
|
||||||
|
assert.equal(Num.name, Number.name);
|
||||||
|
assert.ok(typeof(Num), "function");
|
||||||
|
|
||||||
|
let x = query("x");
|
||||||
|
let xy = query("x.y");
|
||||||
|
|
||||||
|
[
|
||||||
|
[query("foo", { foo: 1 }), 1],
|
||||||
|
[query("foo")({ foo: 1 }), 1],
|
||||||
|
[query("foo.bar", { foo: { bar: 2 } }), 2],
|
||||||
|
[query("foo.bar")({ foo: { bar: 2 } }), 2],
|
||||||
|
[query("foo.bar", { foo: 1 }), undefined],
|
||||||
|
[query("foo.bar")({ foo: 1 }), undefined],
|
||||||
|
[x(1), undefined],
|
||||||
|
[x(undefined), undefined],
|
||||||
|
[x(null), null],
|
||||||
|
[x({ x: 1 }), 1],
|
||||||
|
[x({ x: 2 }), 2],
|
||||||
|
[xy(1), undefined],
|
||||||
|
[xy(undefined), undefined],
|
||||||
|
[xy(null), null],
|
||||||
|
[xy({ x: 1 }), undefined],
|
||||||
|
[xy({ x: 2 }), undefined],
|
||||||
|
[xy({ x: { y: 1 } }), 1],
|
||||||
|
[xy({ x: { y: 2 } }), 2]
|
||||||
|
].forEach(([actual, expected]) => assert.equal(actual, expected));
|
||||||
|
};
|
||||||
|
|
||||||
|
exports["test isInstance"] = assert => {
|
||||||
|
function X() {}
|
||||||
|
function Y() {}
|
||||||
|
let isX = isInstance(X);
|
||||||
|
|
||||||
|
[
|
||||||
|
isInstance(X, new X()),
|
||||||
|
isInstance(X)(new X()),
|
||||||
|
!isInstance(X, new Y()),
|
||||||
|
!isInstance(X)(new Y()),
|
||||||
|
isX(new X()),
|
||||||
|
!isX(new Y())
|
||||||
|
].forEach(x => assert.ok(x));
|
||||||
|
};
|
||||||
|
|
||||||
|
exports["test is"] = assert => {
|
||||||
|
|
||||||
|
assert.deepEqual([ 1, 0, 1, 0, 1 ].map(is(1)),
|
||||||
|
[ true, false, true, false, true ],
|
||||||
|
"is can be partially applied");
|
||||||
|
|
||||||
|
assert.ok(is(1, 1));
|
||||||
|
assert.ok(!is({}, {}));
|
||||||
|
assert.ok(is()(1)()(1), "is is curried");
|
||||||
|
assert.ok(!is()(1)()(2));
|
||||||
|
};
|
||||||
|
|
||||||
|
exports["test isnt"] = assert => {
|
||||||
|
|
||||||
|
assert.deepEqual([ 1, 0, 1, 0, 1 ].map(isnt(0)),
|
||||||
|
[ true, false, true, false, true ],
|
||||||
|
"is can be partially applied");
|
||||||
|
|
||||||
|
assert.ok(!isnt(1, 1));
|
||||||
|
assert.ok(isnt({}, {}));
|
||||||
|
assert.ok(!isnt()(1)()(1));
|
||||||
|
assert.ok(isnt()(1)()(2));
|
||||||
|
};
|
||||||
|
|
||||||
require('test').run(exports);
|
require('test').run(exports);
|
||||||
|
|
|
@ -1093,7 +1093,7 @@ pref("devtools.toolbox.footer.height", 250);
|
||||||
pref("devtools.toolbox.sidebar.width", 500);
|
pref("devtools.toolbox.sidebar.width", 500);
|
||||||
pref("devtools.toolbox.host", "bottom");
|
pref("devtools.toolbox.host", "bottom");
|
||||||
pref("devtools.toolbox.selectedTool", "webconsole");
|
pref("devtools.toolbox.selectedTool", "webconsole");
|
||||||
pref("devtools.toolbox.toolbarSpec", '["paintflashing toggle","tilt toggle","scratchpad","resize toggle"]');
|
pref("devtools.toolbox.toolbarSpec", '["splitconsole", "paintflashing toggle","tilt toggle","scratchpad","resize toggle"]');
|
||||||
pref("devtools.toolbox.sideEnabled", true);
|
pref("devtools.toolbox.sideEnabled", true);
|
||||||
pref("devtools.toolbox.zoomValue", "1");
|
pref("devtools.toolbox.zoomValue", "1");
|
||||||
|
|
||||||
|
|
|
@ -2272,3 +2272,68 @@ gcli.addCommand({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}(this));
|
}(this));
|
||||||
|
|
||||||
|
/* CmdSplitConsole ------------------------------------------------------- */
|
||||||
|
|
||||||
|
(function(module) {
|
||||||
|
/**
|
||||||
|
* 'splitconsole' command (hidden)
|
||||||
|
*/
|
||||||
|
|
||||||
|
gcli.addCommand({
|
||||||
|
name: 'splitconsole',
|
||||||
|
hidden: true,
|
||||||
|
buttonId: "command-button-splitconsole",
|
||||||
|
buttonClass: "command-button",
|
||||||
|
tooltipText: gcli.lookup("splitconsoleTooltip"),
|
||||||
|
state: {
|
||||||
|
isChecked: function(aTarget) {
|
||||||
|
let toolbox = gDevTools.getToolbox(aTarget);
|
||||||
|
return toolbox &&
|
||||||
|
toolbox.splitConsole;
|
||||||
|
},
|
||||||
|
onChange: function(aTarget, aChangeHandler) {
|
||||||
|
eventEmitter.on("changed", aChangeHandler);
|
||||||
|
},
|
||||||
|
offChange: function(aTarget, aChangeHandler) {
|
||||||
|
eventEmitter.off("changed", aChangeHandler);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
exec: function(args, context) {
|
||||||
|
toggleSplitConsole(context);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function toggleSplitConsole(context) {
|
||||||
|
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
|
||||||
|
let target = devtools.TargetFactory.forTab(gBrowser.selectedTab);
|
||||||
|
let toolbox = gDevTools.getToolbox(target);
|
||||||
|
|
||||||
|
if (!toolbox) {
|
||||||
|
gDevTools.showToolbox(target, "inspector").then((toolbox) => {
|
||||||
|
toolbox.toggleSplitConsole();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
toolbox.toggleSplitConsole();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let eventEmitter = new EventEmitter();
|
||||||
|
function fireChange(tab) {
|
||||||
|
eventEmitter.emit("changed", tab);
|
||||||
|
}
|
||||||
|
|
||||||
|
gDevTools.on("toolbox-ready", (e, toolbox) => {
|
||||||
|
if (!toolbox.target) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let fireChangeForTab = fireChange.bind(this, toolbox.target.tab);
|
||||||
|
toolbox.on("split-console", fireChangeForTab);
|
||||||
|
toolbox.on("select", fireChangeForTab);
|
||||||
|
toolbox.once("destroyed", () => {
|
||||||
|
toolbox.off("split-console", fireChangeForTab);
|
||||||
|
toolbox.off("select", fireChangeForTab);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
}(this));
|
||||||
|
|
|
@ -182,6 +182,13 @@ Toolbox.prototype = {
|
||||||
return parseFloat(Services.prefs.getCharPref(ZOOM_PREF));
|
return parseFloat(Services.prefs.getCharPref(ZOOM_PREF));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the toggled state of the split console
|
||||||
|
*/
|
||||||
|
get splitConsole() {
|
||||||
|
return this._splitConsole;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open the toolbox
|
* Open the toolbox
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -63,22 +63,24 @@ function test()
|
||||||
function getCurrentUIState()
|
function getCurrentUIState()
|
||||||
{
|
{
|
||||||
let win = toolbox.doc.defaultView;
|
let win = toolbox.doc.defaultView;
|
||||||
let deck = toolbox.doc.getElementById("toolbox-deck");
|
let deck = toolbox.doc.querySelector("#toolbox-deck");
|
||||||
let webconsolePanel = toolbox.doc.getElementById("toolbox-panel-webconsole");
|
let webconsolePanel = toolbox.doc.querySelector("#toolbox-panel-webconsole");
|
||||||
let splitter = toolbox.doc.getElementById("toolbox-console-splitter");
|
let splitter = toolbox.doc.querySelector("#toolbox-console-splitter");
|
||||||
|
|
||||||
let containerHeight = parseFloat(win.getComputedStyle(deck.parentNode).getPropertyValue("height"));
|
let containerHeight = parseFloat(win.getComputedStyle(deck.parentNode).getPropertyValue("height"));
|
||||||
let deckHeight = parseFloat(win.getComputedStyle(deck).getPropertyValue("height"));
|
let deckHeight = parseFloat(win.getComputedStyle(deck).getPropertyValue("height"));
|
||||||
let webconsoleHeight = parseFloat(win.getComputedStyle(webconsolePanel).getPropertyValue("height"));
|
let webconsoleHeight = parseFloat(win.getComputedStyle(webconsolePanel).getPropertyValue("height"));
|
||||||
let splitterVisibility = !splitter.getAttribute("hidden");
|
let splitterVisibility = !splitter.getAttribute("hidden");
|
||||||
let openedConsolePanel = toolbox.currentToolId === "webconsole";
|
let openedConsolePanel = toolbox.currentToolId === "webconsole";
|
||||||
|
let cmdButton = toolbox.doc.querySelector("#command-button-splitconsole");
|
||||||
|
|
||||||
return {
|
return {
|
||||||
deckHeight: deckHeight,
|
deckHeight: deckHeight,
|
||||||
containerHeight: containerHeight,
|
containerHeight: containerHeight,
|
||||||
webconsoleHeight: webconsoleHeight,
|
webconsoleHeight: webconsoleHeight,
|
||||||
splitterVisibility: splitterVisibility,
|
splitterVisibility: splitterVisibility,
|
||||||
openedConsolePanel: openedConsolePanel
|
openedConsolePanel: openedConsolePanel,
|
||||||
|
buttonSelected: cmdButton.hasAttribute("checked")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,6 +99,7 @@ function test()
|
||||||
ok (currentUIState.deckHeight > 0, "Deck has a height > 0 when console is split");
|
ok (currentUIState.deckHeight > 0, "Deck has a height > 0 when console is split");
|
||||||
ok (currentUIState.webconsoleHeight > 0, "Web console has a height > 0 when console is split");
|
ok (currentUIState.webconsoleHeight > 0, "Web console has a height > 0 when console is split");
|
||||||
ok (!currentUIState.openedConsolePanel, "The console panel is not the current tool");
|
ok (!currentUIState.openedConsolePanel, "The console panel is not the current tool");
|
||||||
|
ok (currentUIState.buttonSelected, "The command button is selected");
|
||||||
|
|
||||||
openPanel("webconsole").then(() => {
|
openPanel("webconsole").then(() => {
|
||||||
|
|
||||||
|
@ -106,6 +109,7 @@ function test()
|
||||||
is (currentUIState.deckHeight, 0, "Deck has a height == 0 when console is opened.");
|
is (currentUIState.deckHeight, 0, "Deck has a height == 0 when console is opened.");
|
||||||
is (currentUIState.webconsoleHeight, currentUIState.containerHeight, "Web console is full height.");
|
is (currentUIState.webconsoleHeight, currentUIState.containerHeight, "Web console is full height.");
|
||||||
ok (currentUIState.openedConsolePanel, "The console panel is the current tool");
|
ok (currentUIState.openedConsolePanel, "The console panel is the current tool");
|
||||||
|
ok (currentUIState.buttonSelected, "The command button is still selected.");
|
||||||
|
|
||||||
// Make sure splitting console does nothing while webconsole is opened
|
// Make sure splitting console does nothing while webconsole is opened
|
||||||
toolbox.toggleSplitConsole();
|
toolbox.toggleSplitConsole();
|
||||||
|
@ -116,6 +120,7 @@ function test()
|
||||||
is (currentUIState.deckHeight, 0, "Deck has a height == 0 when console is opened.");
|
is (currentUIState.deckHeight, 0, "Deck has a height == 0 when console is opened.");
|
||||||
is (currentUIState.webconsoleHeight, currentUIState.containerHeight, "Web console is full height.");
|
is (currentUIState.webconsoleHeight, currentUIState.containerHeight, "Web console is full height.");
|
||||||
ok (currentUIState.openedConsolePanel, "The console panel is the current tool");
|
ok (currentUIState.openedConsolePanel, "The console panel is the current tool");
|
||||||
|
ok (currentUIState.buttonSelected, "The command button is still selected.");
|
||||||
|
|
||||||
// Make sure that split state is saved after opening another panel
|
// Make sure that split state is saved after opening another panel
|
||||||
openPanel("inspector").then(() => {
|
openPanel("inspector").then(() => {
|
||||||
|
@ -124,6 +129,7 @@ function test()
|
||||||
ok (currentUIState.deckHeight > 0, "Deck has a height > 0 when console is split");
|
ok (currentUIState.deckHeight > 0, "Deck has a height > 0 when console is split");
|
||||||
ok (currentUIState.webconsoleHeight > 0, "Web console has a height > 0 when console is split");
|
ok (currentUIState.webconsoleHeight > 0, "Web console has a height > 0 when console is split");
|
||||||
ok (!currentUIState.openedConsolePanel, "The console panel is not the current tool");
|
ok (!currentUIState.openedConsolePanel, "The console panel is not the current tool");
|
||||||
|
ok (currentUIState.buttonSelected, "The command button is still selected.");
|
||||||
|
|
||||||
toolbox.toggleSplitConsole();
|
toolbox.toggleSplitConsole();
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
|
@ -163,6 +169,7 @@ function test()
|
||||||
is (currentUIState.deckHeight, currentUIState.containerHeight, "Deck has a height > 0 by default");
|
is (currentUIState.deckHeight, currentUIState.containerHeight, "Deck has a height > 0 by default");
|
||||||
is (currentUIState.webconsoleHeight, 0, "Web console is collapsed by default");
|
is (currentUIState.webconsoleHeight, 0, "Web console is collapsed by default");
|
||||||
ok (!currentUIState.openedConsolePanel, "The console panel is not the current tool");
|
ok (!currentUIState.openedConsolePanel, "The console panel is not the current tool");
|
||||||
|
ok (!currentUIState.buttonSelected, "The command button is not selected.");
|
||||||
|
|
||||||
toolbox.toggleSplitConsole();
|
toolbox.toggleSplitConsole();
|
||||||
|
|
||||||
|
@ -175,6 +182,7 @@ function test()
|
||||||
currentUIState.containerHeight,
|
currentUIState.containerHeight,
|
||||||
"Everything adds up to container height");
|
"Everything adds up to container height");
|
||||||
ok (!currentUIState.openedConsolePanel, "The console panel is not the current tool");
|
ok (!currentUIState.openedConsolePanel, "The console panel is not the current tool");
|
||||||
|
ok (currentUIState.buttonSelected, "The command button is selected.");
|
||||||
|
|
||||||
toolbox.toggleSplitConsole();
|
toolbox.toggleSplitConsole();
|
||||||
|
|
||||||
|
@ -184,9 +192,9 @@ function test()
|
||||||
is (currentUIState.deckHeight, currentUIState.containerHeight, "Deck has a height > 0 after toggling");
|
is (currentUIState.deckHeight, currentUIState.containerHeight, "Deck has a height > 0 after toggling");
|
||||||
is (currentUIState.webconsoleHeight, 0, "Web console is collapsed after toggling");
|
is (currentUIState.webconsoleHeight, 0, "Web console is collapsed after toggling");
|
||||||
ok (!currentUIState.openedConsolePanel, "The console panel is not the current tool");
|
ok (!currentUIState.openedConsolePanel, "The console panel is not the current tool");
|
||||||
|
ok (!currentUIState.buttonSelected, "The command button is not selected.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function testBottomHost()
|
function testBottomHost()
|
||||||
{
|
{
|
||||||
checkHostType(Toolbox.HostType.BOTTOM);
|
checkHostType(Toolbox.HostType.BOTTOM);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
This is the pdf.js project output, https://github.com/mozilla/pdf.js
|
This is the pdf.js project output, https://github.com/mozilla/pdf.js
|
||||||
|
|
||||||
Current extension version is: 0.8.681
|
Current extension version is: 0.8.759
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
*/
|
*/
|
||||||
/* jshint esnext:true */
|
/* jshint esnext:true */
|
||||||
/* globals Components, Services, XPCOMUtils, NetUtil, PrivateBrowsingUtils,
|
/* globals Components, Services, XPCOMUtils, NetUtil, PrivateBrowsingUtils,
|
||||||
dump, NetworkManager, PdfJsTelemetry */
|
dump, NetworkManager, PdfJsTelemetry, DEFAULT_PREFERENCES */
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
@ -33,12 +33,16 @@ const PDF_CONTENT_TYPE = 'application/pdf';
|
||||||
const PREF_PREFIX = 'pdfjs';
|
const PREF_PREFIX = 'pdfjs';
|
||||||
const PDF_VIEWER_WEB_PAGE = 'resource://pdf.js/web/viewer.html';
|
const PDF_VIEWER_WEB_PAGE = 'resource://pdf.js/web/viewer.html';
|
||||||
const MAX_DATABASE_LENGTH = 4096;
|
const MAX_DATABASE_LENGTH = 4096;
|
||||||
|
const MAX_STRING_PREF_LENGTH = 4096;
|
||||||
|
|
||||||
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
|
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||||
Cu.import('resource://gre/modules/Services.jsm');
|
Cu.import('resource://gre/modules/Services.jsm');
|
||||||
Cu.import('resource://gre/modules/NetUtil.jsm');
|
Cu.import('resource://gre/modules/NetUtil.jsm');
|
||||||
Cu.import('resource://pdf.js/network.js');
|
Cu.import('resource://pdf.js/network.js');
|
||||||
|
|
||||||
|
// Load the default preferences.
|
||||||
|
Cu.import('resource://pdf.js/default_preferences.js');
|
||||||
|
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, 'PrivateBrowsingUtils',
|
XPCOMUtils.defineLazyModuleGetter(this, 'PrivateBrowsingUtils',
|
||||||
'resource://gre/modules/PrivateBrowsingUtils.jsm');
|
'resource://gre/modules/PrivateBrowsingUtils.jsm');
|
||||||
|
|
||||||
|
@ -58,6 +62,10 @@ function getChromeWindow(domWindow) {
|
||||||
return containingBrowser.ownerDocument.defaultView;
|
return containingBrowser.ownerDocument.defaultView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setBoolPref(pref, value) {
|
||||||
|
Services.prefs.setBoolPref(pref, value);
|
||||||
|
}
|
||||||
|
|
||||||
function getBoolPref(pref, def) {
|
function getBoolPref(pref, def) {
|
||||||
try {
|
try {
|
||||||
return Services.prefs.getBoolPref(pref);
|
return Services.prefs.getBoolPref(pref);
|
||||||
|
@ -66,6 +74,10 @@ function getBoolPref(pref, def) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setIntPref(pref, value) {
|
||||||
|
Services.prefs.setIntPref(pref, value);
|
||||||
|
}
|
||||||
|
|
||||||
function getIntPref(pref, def) {
|
function getIntPref(pref, def) {
|
||||||
try {
|
try {
|
||||||
return Services.prefs.getIntPref(pref);
|
return Services.prefs.getIntPref(pref);
|
||||||
|
@ -431,6 +443,62 @@ ChromeActions.prototype = {
|
||||||
}
|
}
|
||||||
getChromeWindow(this.domWindow).gFindBar
|
getChromeWindow(this.domWindow).gFindBar
|
||||||
.updateControlState(result, findPrevious);
|
.updateControlState(result, findPrevious);
|
||||||
|
},
|
||||||
|
setPreferences: function(prefs) {
|
||||||
|
var prefValue, defaultValue, prefName, prefType, defaultType;
|
||||||
|
|
||||||
|
for (var key in DEFAULT_PREFERENCES) {
|
||||||
|
prefValue = prefs[key];
|
||||||
|
defaultValue = DEFAULT_PREFERENCES[key];
|
||||||
|
prefName = (PREF_PREFIX + '.' + key);
|
||||||
|
|
||||||
|
if (prefValue === undefined || prefValue === defaultValue) {
|
||||||
|
Services.prefs.clearUserPref(prefName);
|
||||||
|
} else {
|
||||||
|
prefType = typeof prefValue;
|
||||||
|
defaultType = typeof defaultValue;
|
||||||
|
|
||||||
|
if (prefType !== defaultType) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
switch (defaultType) {
|
||||||
|
case 'boolean':
|
||||||
|
setBoolPref(prefName, prefValue);
|
||||||
|
break;
|
||||||
|
case 'number':
|
||||||
|
setIntPref(prefName, prefValue);
|
||||||
|
break;
|
||||||
|
case 'string':
|
||||||
|
// Protect against adding arbitrarily long strings in about:config.
|
||||||
|
if (prefValue.length <= MAX_STRING_PREF_LENGTH) {
|
||||||
|
setStringPref(prefName, prefValue);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getPreferences: function() {
|
||||||
|
var currentPrefs = {};
|
||||||
|
var defaultValue, prefName;
|
||||||
|
|
||||||
|
for (var key in DEFAULT_PREFERENCES) {
|
||||||
|
defaultValue = DEFAULT_PREFERENCES[key];
|
||||||
|
prefName = (PREF_PREFIX + '.' + key);
|
||||||
|
|
||||||
|
switch (typeof defaultValue) {
|
||||||
|
case 'boolean':
|
||||||
|
currentPrefs[key] = getBoolPref(prefName, defaultValue);
|
||||||
|
break;
|
||||||
|
case 'number':
|
||||||
|
currentPrefs[key] = getIntPref(prefName, defaultValue);
|
||||||
|
break;
|
||||||
|
case 'string':
|
||||||
|
currentPrefs[key] = getStringPref(prefName, defaultValue);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return JSON.stringify(currentPrefs);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -439,9 +507,12 @@ var RangedChromeActions = (function RangedChromeActionsClosure() {
|
||||||
* This is for range requests
|
* This is for range requests
|
||||||
*/
|
*/
|
||||||
function RangedChromeActions(
|
function RangedChromeActions(
|
||||||
domWindow, contentDispositionFilename, originalRequest) {
|
domWindow, contentDispositionFilename, originalRequest,
|
||||||
|
dataListener) {
|
||||||
|
|
||||||
ChromeActions.call(this, domWindow, contentDispositionFilename);
|
ChromeActions.call(this, domWindow, contentDispositionFilename);
|
||||||
|
this.dataListener = dataListener;
|
||||||
|
this.originalRequest = originalRequest;
|
||||||
|
|
||||||
this.pdfUrl = originalRequest.URI.spec;
|
this.pdfUrl = originalRequest.URI.spec;
|
||||||
this.contentLength = originalRequest.contentLength;
|
this.contentLength = originalRequest.contentLength;
|
||||||
|
@ -487,11 +558,15 @@ var RangedChromeActions = (function RangedChromeActionsClosure() {
|
||||||
proto.constructor = RangedChromeActions;
|
proto.constructor = RangedChromeActions;
|
||||||
|
|
||||||
proto.initPassiveLoading = function RangedChromeActions_initPassiveLoading() {
|
proto.initPassiveLoading = function RangedChromeActions_initPassiveLoading() {
|
||||||
|
this.originalRequest.cancel(Cr.NS_BINDING_ABORTED);
|
||||||
|
this.originalRequest = null;
|
||||||
this.domWindow.postMessage({
|
this.domWindow.postMessage({
|
||||||
pdfjsLoadAction: 'supportsRangedLoading',
|
pdfjsLoadAction: 'supportsRangedLoading',
|
||||||
pdfUrl: this.pdfUrl,
|
pdfUrl: this.pdfUrl,
|
||||||
length: this.contentLength
|
length: this.contentLength,
|
||||||
|
data: this.dataListener.getData()
|
||||||
}, '*');
|
}, '*');
|
||||||
|
this.dataListener = null;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
@ -692,8 +767,8 @@ PdfStreamConverter.prototype = {
|
||||||
* 1. asyncConvertData stores the listener
|
* 1. asyncConvertData stores the listener
|
||||||
* 2. onStartRequest creates a new channel, streams the viewer
|
* 2. onStartRequest creates a new channel, streams the viewer
|
||||||
* 3. If range requests are supported:
|
* 3. If range requests are supported:
|
||||||
* 3.1. Suspends and cancels the request so we can issue range
|
* 3.1. Leave the request open until the viewer is ready to switch to
|
||||||
* requests instead.
|
* range requests.
|
||||||
*
|
*
|
||||||
* If range rquests are not supported:
|
* If range rquests are not supported:
|
||||||
* 3.1. Read the stream as it's loaded in onDataAvailable to send
|
* 3.1. Read the stream as it's loaded in onDataAvailable to send
|
||||||
|
@ -779,18 +854,12 @@ PdfStreamConverter.prototype = {
|
||||||
PdfJsTelemetry.onViewerIsUsed();
|
PdfJsTelemetry.onViewerIsUsed();
|
||||||
PdfJsTelemetry.onDocumentSize(aRequest.contentLength);
|
PdfJsTelemetry.onDocumentSize(aRequest.contentLength);
|
||||||
|
|
||||||
if (!rangeRequest) {
|
|
||||||
// Creating storage for PDF data
|
// Creating storage for PDF data
|
||||||
var contentLength = aRequest.contentLength;
|
var contentLength = aRequest.contentLength;
|
||||||
this.dataListener = new PdfDataListener(contentLength);
|
this.dataListener = new PdfDataListener(contentLength);
|
||||||
this.binaryStream = Cc['@mozilla.org/binaryinputstream;1']
|
this.binaryStream = Cc['@mozilla.org/binaryinputstream;1']
|
||||||
.createInstance(Ci.nsIBinaryInputStream);
|
.createInstance(Ci.nsIBinaryInputStream);
|
||||||
} else {
|
|
||||||
// Suspend the request so we're not consuming any of the stream,
|
|
||||||
// but we can't cancel the request yet. Otherwise, the original
|
|
||||||
// listener will think we do not want to go the new PDF url
|
|
||||||
aRequest.suspend();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new channel that is viewer loaded as a resource.
|
// Create a new channel that is viewer loaded as a resource.
|
||||||
var ioService = Services.io;
|
var ioService = Services.io;
|
||||||
|
@ -816,12 +885,8 @@ PdfStreamConverter.prototype = {
|
||||||
var domWindow = getDOMWindow(channel);
|
var domWindow = getDOMWindow(channel);
|
||||||
var actions;
|
var actions;
|
||||||
if (rangeRequest) {
|
if (rangeRequest) {
|
||||||
// We are going to be issuing range requests, so cancel the
|
actions = new RangedChromeActions(
|
||||||
// original request
|
domWindow, contentDispositionFilename, aRequest, dataListener);
|
||||||
aRequest.resume();
|
|
||||||
aRequest.cancel(Cr.NS_BINDING_ABORTED);
|
|
||||||
actions = new RangedChromeActions(domWindow,
|
|
||||||
contentDispositionFilename, aRequest);
|
|
||||||
} else {
|
} else {
|
||||||
actions = new StandardChromeActions(
|
actions = new StandardChromeActions(
|
||||||
domWindow, contentDispositionFilename, dataListener);
|
domWindow, contentDispositionFilename, dataListener);
|
||||||
|
|
|
@ -20,8 +20,8 @@ if (typeof PDFJS === 'undefined') {
|
||||||
(typeof window !== 'undefined' ? window : this).PDFJS = {};
|
(typeof window !== 'undefined' ? window : this).PDFJS = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFJS.version = '0.8.681';
|
PDFJS.version = '0.8.759';
|
||||||
PDFJS.build = '48c672b';
|
PDFJS.build = 'd3b5aa3';
|
||||||
|
|
||||||
(function pdfjsWrapper() {
|
(function pdfjsWrapper() {
|
||||||
// Use strict in our context only - users might not want it
|
// Use strict in our context only - users might not want it
|
||||||
|
@ -43,7 +43,7 @@ PDFJS.build = '48c672b';
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
/* globals Cmd, ColorSpace, Dict, MozBlobBuilder, Name, PDFJS, Ref */
|
/* globals Cmd, ColorSpace, Dict, MozBlobBuilder, Name, PDFJS, Ref, URL */
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
@ -78,6 +78,98 @@ if (!globalScope.PDFJS) {
|
||||||
|
|
||||||
globalScope.PDFJS.pdfBug = false;
|
globalScope.PDFJS.pdfBug = false;
|
||||||
|
|
||||||
|
// All the possible operations for an operator list.
|
||||||
|
var OPS = PDFJS.OPS = {
|
||||||
|
// Intentionally start from 1 so it is easy to spot bad operators that will be
|
||||||
|
// 0's.
|
||||||
|
dependency: 1,
|
||||||
|
setLineWidth: 2,
|
||||||
|
setLineCap: 3,
|
||||||
|
setLineJoin: 4,
|
||||||
|
setMiterLimit: 5,
|
||||||
|
setDash: 6,
|
||||||
|
setRenderingIntent: 7,
|
||||||
|
setFlatness: 8,
|
||||||
|
setGState: 9,
|
||||||
|
save: 10,
|
||||||
|
restore: 11,
|
||||||
|
transform: 12,
|
||||||
|
moveTo: 13,
|
||||||
|
lineTo: 14,
|
||||||
|
curveTo: 15,
|
||||||
|
curveTo2: 16,
|
||||||
|
curveTo3: 17,
|
||||||
|
closePath: 18,
|
||||||
|
rectangle: 19,
|
||||||
|
stroke: 20,
|
||||||
|
closeStroke: 21,
|
||||||
|
fill: 22,
|
||||||
|
eoFill: 23,
|
||||||
|
fillStroke: 24,
|
||||||
|
eoFillStroke: 25,
|
||||||
|
closeFillStroke: 26,
|
||||||
|
closeEOFillStroke: 27,
|
||||||
|
endPath: 28,
|
||||||
|
clip: 29,
|
||||||
|
eoClip: 30,
|
||||||
|
beginText: 31,
|
||||||
|
endText: 32,
|
||||||
|
setCharSpacing: 33,
|
||||||
|
setWordSpacing: 34,
|
||||||
|
setHScale: 35,
|
||||||
|
setLeading: 36,
|
||||||
|
setFont: 37,
|
||||||
|
setTextRenderingMode: 38,
|
||||||
|
setTextRise: 39,
|
||||||
|
moveText: 40,
|
||||||
|
setLeadingMoveText: 41,
|
||||||
|
setTextMatrix: 42,
|
||||||
|
nextLine: 43,
|
||||||
|
showText: 44,
|
||||||
|
showSpacedText: 45,
|
||||||
|
nextLineShowText: 46,
|
||||||
|
nextLineSetSpacingShowText: 47,
|
||||||
|
setCharWidth: 48,
|
||||||
|
setCharWidthAndBounds: 49,
|
||||||
|
setStrokeColorSpace: 50,
|
||||||
|
setFillColorSpace: 51,
|
||||||
|
setStrokeColor: 52,
|
||||||
|
setStrokeColorN: 53,
|
||||||
|
setFillColor: 54,
|
||||||
|
setFillColorN: 55,
|
||||||
|
setStrokeGray: 56,
|
||||||
|
setFillGray: 57,
|
||||||
|
setStrokeRGBColor: 58,
|
||||||
|
setFillRGBColor: 59,
|
||||||
|
setStrokeCMYKColor: 60,
|
||||||
|
setFillCMYKColor: 61,
|
||||||
|
shadingFill: 62,
|
||||||
|
beginInlineImage: 63,
|
||||||
|
beginImageData: 64,
|
||||||
|
endInlineImage: 65,
|
||||||
|
paintXObject: 66,
|
||||||
|
markPoint: 67,
|
||||||
|
markPointProps: 68,
|
||||||
|
beginMarkedContent: 69,
|
||||||
|
beginMarkedContentProps: 70,
|
||||||
|
endMarkedContent: 71,
|
||||||
|
beginCompat: 72,
|
||||||
|
endCompat: 73,
|
||||||
|
paintFormXObjectBegin: 74,
|
||||||
|
paintFormXObjectEnd: 75,
|
||||||
|
beginGroup: 76,
|
||||||
|
endGroup: 77,
|
||||||
|
beginAnnotations: 78,
|
||||||
|
endAnnotations: 79,
|
||||||
|
beginAnnotation: 80,
|
||||||
|
endAnnotation: 81,
|
||||||
|
paintJpegXObject: 82,
|
||||||
|
paintImageMaskXObject: 83,
|
||||||
|
paintImageMaskXObjectGroup: 84,
|
||||||
|
paintImageXObject: 85,
|
||||||
|
paintInlineImageXObject: 86,
|
||||||
|
paintInlineImageXObjectGroup: 87
|
||||||
|
};
|
||||||
|
|
||||||
// Use only for debugging purposes. This should not be used in any code that is
|
// Use only for debugging purposes. This should not be used in any code that is
|
||||||
// in mozilla master.
|
// in mozilla master.
|
||||||
|
@ -292,7 +384,7 @@ var MissingDataException = (function MissingDataExceptionClosure() {
|
||||||
function MissingDataException(begin, end) {
|
function MissingDataException(begin, end) {
|
||||||
this.begin = begin;
|
this.begin = begin;
|
||||||
this.end = end;
|
this.end = end;
|
||||||
this.message = 'Missing data [begin, end)';
|
this.message = 'Missing data [' + begin + ', ' + end + ')';
|
||||||
}
|
}
|
||||||
|
|
||||||
MissingDataException.prototype = new Error();
|
MissingDataException.prototype = new Error();
|
||||||
|
@ -865,7 +957,7 @@ var Promise = PDFJS.Promise = (function PromiseClosure() {
|
||||||
/**
|
/**
|
||||||
* Builds a promise that is resolved when all the passed in promises are
|
* Builds a promise that is resolved when all the passed in promises are
|
||||||
* resolved.
|
* resolved.
|
||||||
* @param {Promise[]} promises Array of promises to wait for.
|
* @param {array} array of data and/or promises to wait for.
|
||||||
* @return {Promise} New dependant promise.
|
* @return {Promise} New dependant promise.
|
||||||
*/
|
*/
|
||||||
Promise.all = function Promise_all(promises) {
|
Promise.all = function Promise_all(promises) {
|
||||||
|
@ -885,7 +977,7 @@ var Promise = PDFJS.Promise = (function PromiseClosure() {
|
||||||
}
|
}
|
||||||
for (var i = 0, ii = promises.length; i < ii; ++i) {
|
for (var i = 0, ii = promises.length; i < ii; ++i) {
|
||||||
var promise = promises[i];
|
var promise = promises[i];
|
||||||
promise.then((function(i) {
|
var resolve = (function(i) {
|
||||||
return function(value) {
|
return function(value) {
|
||||||
if (deferred._status === STATUS_REJECTED) {
|
if (deferred._status === STATUS_REJECTED) {
|
||||||
return;
|
return;
|
||||||
|
@ -895,11 +987,24 @@ var Promise = PDFJS.Promise = (function PromiseClosure() {
|
||||||
if (unresolved === 0)
|
if (unresolved === 0)
|
||||||
deferred.resolve(results);
|
deferred.resolve(results);
|
||||||
};
|
};
|
||||||
})(i), reject);
|
})(i);
|
||||||
|
if (Promise.isPromise(promise)) {
|
||||||
|
promise.then(resolve, reject);
|
||||||
|
} else {
|
||||||
|
resolve(promise);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return deferred;
|
return deferred;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the value is likely a promise (has a 'then' function).
|
||||||
|
* @return {boolean} true if x is thenable
|
||||||
|
*/
|
||||||
|
Promise.isPromise = function Promise_isPromise(value) {
|
||||||
|
return value && typeof value.then === 'function';
|
||||||
|
};
|
||||||
|
|
||||||
Promise.prototype = {
|
Promise.prototype = {
|
||||||
_status: null,
|
_status: null,
|
||||||
_value: null,
|
_value: null,
|
||||||
|
@ -913,7 +1018,7 @@ var Promise = PDFJS.Promise = (function PromiseClosure() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == STATUS_RESOLVED &&
|
if (status == STATUS_RESOLVED &&
|
||||||
value && typeof(value.then) === 'function') {
|
Promise.isPromise(value)) {
|
||||||
value.then(this._updateStatus.bind(this, STATUS_RESOLVED),
|
value.then(this._updateStatus.bind(this, STATUS_RESOLVED),
|
||||||
this._updateStatus.bind(this, STATUS_REJECTED));
|
this._updateStatus.bind(this, STATUS_REJECTED));
|
||||||
return;
|
return;
|
||||||
|
@ -1016,7 +1121,7 @@ var StatTimer = (function StatTimerClosure() {
|
||||||
})();
|
})();
|
||||||
|
|
||||||
PDFJS.createBlob = function createBlob(data, contentType) {
|
PDFJS.createBlob = function createBlob(data, contentType) {
|
||||||
if (typeof Blob === 'function')
|
if (typeof Blob !== 'undefined')
|
||||||
return new Blob([data], { type: contentType });
|
return new Blob([data], { type: contentType });
|
||||||
// Blob builder is deprecated in FF14 and removed in FF18.
|
// Blob builder is deprecated in FF14 and removed in FF18.
|
||||||
var bb = new MozBlobBuilder();
|
var bb = new MozBlobBuilder();
|
||||||
|
@ -1024,10 +1129,38 @@ PDFJS.createBlob = function createBlob(data, contentType) {
|
||||||
return bb.getBlob(contentType);
|
return bb.getBlob(contentType);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
PDFJS.createObjectURL = (function createObjectURLClosure() {
|
||||||
|
if (typeof URL !== 'undefined' && URL.createObjectURL) {
|
||||||
|
return function createObjectURL(data, contentType) {
|
||||||
|
var blob = PDFJS.createBlob(data, contentType);
|
||||||
|
return URL.createObjectURL(blob);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Blob/createObjectURL is not available, falling back to data schema.
|
||||||
|
var digits =
|
||||||
|
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
||||||
|
|
||||||
|
return function createObjectURL(data, contentType) {
|
||||||
|
var buffer = 'data:' + contentType + ';base64,';
|
||||||
|
for (var i = 0, ii = data.length; i < ii; i += 3) {
|
||||||
|
var b1 = data[i] & 0xFF;
|
||||||
|
var b2 = data[i + 1] & 0xFF;
|
||||||
|
var b3 = data[i + 2] & 0xFF;
|
||||||
|
var d1 = b1 >> 2, d2 = ((b1 & 3) << 4) | (b2 >> 4);
|
||||||
|
var d3 = i + 1 < ii ? ((b2 & 0xF) << 2) | (b3 >> 6) : 64;
|
||||||
|
var d4 = i + 2 < ii ? (b3 & 0x3F) : 64;
|
||||||
|
buffer += digits[d1] + digits[d2] + digits[d3] + digits[d4];
|
||||||
|
}
|
||||||
|
return buffer;
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
function MessageHandler(name, comObj) {
|
function MessageHandler(name, comObj) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.comObj = comObj;
|
this.comObj = comObj;
|
||||||
this.callbackIndex = 1;
|
this.callbackIndex = 1;
|
||||||
|
this.postMessageTransfers = true;
|
||||||
var callbacks = this.callbacks = {};
|
var callbacks = this.callbacks = {};
|
||||||
var ah = this.actionHandler = {};
|
var ah = this.actionHandler = {};
|
||||||
|
|
||||||
|
@ -1094,8 +1227,9 @@ MessageHandler.prototype = {
|
||||||
* @param {String} actionName Action to call.
|
* @param {String} actionName Action to call.
|
||||||
* @param {JSON} data JSON data to send.
|
* @param {JSON} data JSON data to send.
|
||||||
* @param {function} [callback] Optional callback that will handle a reply.
|
* @param {function} [callback] Optional callback that will handle a reply.
|
||||||
|
* @param {Array} [transfers] Optional list of transfers/ArrayBuffers
|
||||||
*/
|
*/
|
||||||
send: function messageHandlerSend(actionName, data, callback) {
|
send: function messageHandlerSend(actionName, data, callback, transfers) {
|
||||||
var message = {
|
var message = {
|
||||||
action: actionName,
|
action: actionName,
|
||||||
data: data
|
data: data
|
||||||
|
@ -1105,16 +1239,20 @@ MessageHandler.prototype = {
|
||||||
this.callbacks[callbackId] = callback;
|
this.callbacks[callbackId] = callback;
|
||||||
message.callbackId = callbackId;
|
message.callbackId = callbackId;
|
||||||
}
|
}
|
||||||
this.comObj.postMessage(message);
|
if (transfers && this.postMessageTransfers) {
|
||||||
|
this.comObj.postMessage(message, transfers);
|
||||||
|
} else {
|
||||||
|
this.comObj.postMessage(message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function loadJpegStream(id, imageData, objs) {
|
function loadJpegStream(id, imageUrl, objs) {
|
||||||
var img = new Image();
|
var img = new Image();
|
||||||
img.onload = (function loadJpegStream_onloadClosure() {
|
img.onload = (function loadJpegStream_onloadClosure() {
|
||||||
objs.resolve(id, img);
|
objs.resolve(id, img);
|
||||||
});
|
});
|
||||||
img.src = 'data:image/jpeg;base64,' + window.btoa(imageData);
|
img.src = imageUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3430,9 +3568,9 @@ var Annotation = (function AnnotationClosure() {
|
||||||
|
|
||||||
resourcesPromise.then(function(resources) {
|
resourcesPromise.then(function(resources) {
|
||||||
var opList = new OperatorList();
|
var opList = new OperatorList();
|
||||||
opList.addOp('beginAnnotation', [data.rect, transform, matrix]);
|
opList.addOp(OPS.beginAnnotation, [data.rect, transform, matrix]);
|
||||||
evaluator.getOperatorList(this.appearance, resources, opList);
|
evaluator.getOperatorList(this.appearance, resources, opList);
|
||||||
opList.addOp('endAnnotation', []);
|
opList.addOp(OPS.endAnnotation, []);
|
||||||
promise.resolve(opList);
|
promise.resolve(opList);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
|
@ -3526,12 +3664,12 @@ var Annotation = (function AnnotationClosure() {
|
||||||
annotationPromises.push(annotations[i].getOperatorList(partialEvaluator));
|
annotationPromises.push(annotations[i].getOperatorList(partialEvaluator));
|
||||||
}
|
}
|
||||||
Promise.all(annotationPromises).then(function(datas) {
|
Promise.all(annotationPromises).then(function(datas) {
|
||||||
opList.addOp('beginAnnotations', []);
|
opList.addOp(OPS.beginAnnotations, []);
|
||||||
for (var i = 0, n = datas.length; i < n; ++i) {
|
for (var i = 0, n = datas.length; i < n; ++i) {
|
||||||
var annotOpList = datas[i];
|
var annotOpList = datas[i];
|
||||||
opList.addOpList(annotOpList);
|
opList.addOpList(annotOpList);
|
||||||
}
|
}
|
||||||
opList.addOp('endAnnotations', []);
|
opList.addOp(OPS.endAnnotations, []);
|
||||||
annotationsReadyPromise.resolve();
|
annotationsReadyPromise.resolve();
|
||||||
}, reject);
|
}, reject);
|
||||||
|
|
||||||
|
@ -3707,10 +3845,10 @@ var TextWidgetAnnotation = (function TextWidgetAnnotationClosure() {
|
||||||
data.rgb = [0, 0, 0];
|
data.rgb = [0, 0, 0];
|
||||||
// TODO THIS DOESN'T MAKE ANY SENSE SINCE THE fnArray IS EMPTY!
|
// TODO THIS DOESN'T MAKE ANY SENSE SINCE THE fnArray IS EMPTY!
|
||||||
for (var i = 0, n = fnArray.length; i < n; ++i) {
|
for (var i = 0, n = fnArray.length; i < n; ++i) {
|
||||||
var fnName = appearanceFnArray[i];
|
var fnId = appearanceFnArray[i];
|
||||||
var args = appearanceArgsArray[i];
|
var args = appearanceArgsArray[i];
|
||||||
|
|
||||||
if (fnName === 'setFont') {
|
if (fnId === OPS.setFont) {
|
||||||
data.fontRefName = args[0];
|
data.fontRefName = args[0];
|
||||||
var size = args[1];
|
var size = args[1];
|
||||||
if (size < 0) {
|
if (size < 0) {
|
||||||
|
@ -3720,9 +3858,9 @@ var TextWidgetAnnotation = (function TextWidgetAnnotationClosure() {
|
||||||
data.fontDirection = 1;
|
data.fontDirection = 1;
|
||||||
data.fontSize = size;
|
data.fontSize = size;
|
||||||
}
|
}
|
||||||
} else if (fnName === 'setFillRGBColor') {
|
} else if (fnId === OPS.setFillRGBColor) {
|
||||||
data.rgb = args;
|
data.rgb = args;
|
||||||
} else if (fnName === 'setFillGray') {
|
} else if (fnId === OPS.setFillGray) {
|
||||||
var rgbValue = args[0] * 255;
|
var rgbValue = args[0] * 255;
|
||||||
data.rgb = [rgbValue, rgbValue, rgbValue];
|
data.rgb = [rgbValue, rgbValue, rgbValue];
|
||||||
}
|
}
|
||||||
|
@ -3973,7 +4111,9 @@ PDFJS.disableWorker = PDFJS.disableWorker === undefined ?
|
||||||
false : PDFJS.disableWorker;
|
false : PDFJS.disableWorker;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Path and filename of the worker file. Required when the worker is enabled.
|
* Path and filename of the worker file. Required when the worker is enabled in
|
||||||
|
* development mode. If unspecified in the production build, the worker will be
|
||||||
|
* loaded based on the location of the pdf.js file.
|
||||||
* @var {String}
|
* @var {String}
|
||||||
*/
|
*/
|
||||||
PDFJS.workerSrc = PDFJS.workerSrc === undefined ? null : PDFJS.workerSrc;
|
PDFJS.workerSrc = PDFJS.workerSrc === undefined ? null : PDFJS.workerSrc;
|
||||||
|
@ -4002,6 +4142,12 @@ PDFJS.disableAutoFetch = PDFJS.disableAutoFetch === undefined ?
|
||||||
*/
|
*/
|
||||||
PDFJS.pdfBug = PDFJS.pdfBug === undefined ? false : PDFJS.pdfBug;
|
PDFJS.pdfBug = PDFJS.pdfBug === undefined ? false : PDFJS.pdfBug;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables transfer usage in postMessage for ArrayBuffers.
|
||||||
|
* @var {boolean}
|
||||||
|
*/
|
||||||
|
PDFJS.postMessageTransfers = PDFJS.postMessageTransfers === undefined ?
|
||||||
|
true : PDFJS.postMessageTransfers;
|
||||||
/**
|
/**
|
||||||
* This is the main entry point for loading a PDF and interacting with it.
|
* This is the main entry point for loading a PDF and interacting with it.
|
||||||
* NOTE: If a URL is used to fetch the PDF data a standard XMLHttpRequest(XHR)
|
* NOTE: If a URL is used to fetch the PDF data a standard XMLHttpRequest(XHR)
|
||||||
|
@ -4015,6 +4161,9 @@ PDFJS.pdfBug = PDFJS.pdfBug === undefined ? false : PDFJS.pdfBug;
|
||||||
* - data - A typed array with PDF data.
|
* - data - A typed array with PDF data.
|
||||||
* - httpHeaders - Basic authentication headers.
|
* - httpHeaders - Basic authentication headers.
|
||||||
* - password - For decrypting password-protected PDFs.
|
* - password - For decrypting password-protected PDFs.
|
||||||
|
* - initialData - A typed array with the first portion or all of the pdf data.
|
||||||
|
* Used by the extension since some data is already loaded
|
||||||
|
* before the switch to range requests.
|
||||||
*
|
*
|
||||||
* @param {object} pdfDataRangeTransport is optional. It is used if you want
|
* @param {object} pdfDataRangeTransport is optional. It is used if you want
|
||||||
* to manually serve range requests for data in the PDF. See viewer.js for
|
* to manually serve range requests for data in the PDF. See viewer.js for
|
||||||
|
@ -4104,6 +4253,14 @@ var PDFDocumentProxy = (function PDFDocumentProxyClosure() {
|
||||||
getPage: function PDFDocumentProxy_getPage(number) {
|
getPage: function PDFDocumentProxy_getPage(number) {
|
||||||
return this.transport.getPage(number);
|
return this.transport.getPage(number);
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* @param {object} Must have 'num' and 'gen' properties.
|
||||||
|
* @return {Promise} A promise that is resolved with the page index that is
|
||||||
|
* associated with the reference.
|
||||||
|
*/
|
||||||
|
getPageIndex: function PDFDocumentProxy_getPageIndex(ref) {
|
||||||
|
return this.transport.getPageIndex(ref);
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* @return {Promise} A promise that is resolved with a lookup table for
|
* @return {Promise} A promise that is resolved with a lookup table for
|
||||||
* mapping named destinations to reference numbers.
|
* mapping named destinations to reference numbers.
|
||||||
|
@ -4179,6 +4336,9 @@ var PDFDocumentProxy = (function PDFDocumentProxyClosure() {
|
||||||
dataLoaded: function PDFDocumentProxy_dataLoaded() {
|
dataLoaded: function PDFDocumentProxy_dataLoaded() {
|
||||||
return this.transport.dataLoaded();
|
return this.transport.dataLoaded();
|
||||||
},
|
},
|
||||||
|
cleanup: function PDFDocumentProxy_cleanup() {
|
||||||
|
this.transport.startCleanup();
|
||||||
|
},
|
||||||
destroy: function PDFDocumentProxy_destroy() {
|
destroy: function PDFDocumentProxy_destroy() {
|
||||||
this.transport.destroy();
|
this.transport.destroy();
|
||||||
}
|
}
|
||||||
|
@ -4398,10 +4558,10 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
|
||||||
*/
|
*/
|
||||||
_renderPageChunk: function PDFPageProxy_renderPageChunk(operatorListChunk) {
|
_renderPageChunk: function PDFPageProxy_renderPageChunk(operatorListChunk) {
|
||||||
// Add the new chunk to the current operator list.
|
// Add the new chunk to the current operator list.
|
||||||
Util.concatenateToArray(this.operatorList.fnArray,
|
for (var i = 0, ii = operatorListChunk.length; i < ii; i++) {
|
||||||
operatorListChunk.fnArray);
|
this.operatorList.fnArray.push(operatorListChunk.fnArray[i]);
|
||||||
Util.concatenateToArray(this.operatorList.argsArray,
|
this.operatorList.argsArray.push(operatorListChunk.argsArray[i]);
|
||||||
operatorListChunk.argsArray);
|
}
|
||||||
this.operatorList.lastChunk = operatorListChunk.lastChunk;
|
this.operatorList.lastChunk = operatorListChunk.lastChunk;
|
||||||
|
|
||||||
// Notify all the rendering tasks there are more operators to be consumed.
|
// Notify all the rendering tasks there are more operators to be consumed.
|
||||||
|
@ -4453,9 +4613,13 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
||||||
var messageHandler = new MessageHandler('main', worker);
|
var messageHandler = new MessageHandler('main', worker);
|
||||||
this.messageHandler = messageHandler;
|
this.messageHandler = messageHandler;
|
||||||
|
|
||||||
messageHandler.on('test', function transportTest(supportTypedArray) {
|
messageHandler.on('test', function transportTest(data) {
|
||||||
|
var supportTypedArray = data && data.supportTypedArray;
|
||||||
if (supportTypedArray) {
|
if (supportTypedArray) {
|
||||||
this.worker = worker;
|
this.worker = worker;
|
||||||
|
if (!data.supportTransfers) {
|
||||||
|
PDFJS.postMessageTransfers = false;
|
||||||
|
}
|
||||||
this.setupMessageHandler(messageHandler);
|
this.setupMessageHandler(messageHandler);
|
||||||
workerInitializedPromise.resolve();
|
workerInitializedPromise.resolve();
|
||||||
} else {
|
} else {
|
||||||
|
@ -4467,10 +4631,16 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
||||||
}
|
}
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
var testObj = new Uint8Array(1);
|
var testObj = new Uint8Array([PDFJS.postMessageTransfers ? 255 : 0]);
|
||||||
// Some versions of Opera throw a DATA_CLONE_ERR on
|
// Some versions of Opera throw a DATA_CLONE_ERR on serializing the
|
||||||
// serializing the typed array.
|
// typed array. Also, checking if we can use transfers.
|
||||||
messageHandler.send('test', testObj);
|
try {
|
||||||
|
messageHandler.send('test', testObj, null, [testObj.buffer]);
|
||||||
|
} catch (ex) {
|
||||||
|
info('Cannot use postMessage transfers');
|
||||||
|
testObj[0] = 0;
|
||||||
|
messageHandler.send('test', testObj);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
info('The worker has been disabled.');
|
info('The worker has been disabled.');
|
||||||
|
@ -4704,7 +4874,7 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
messageHandler.on('JpegDecode', function(data, promise) {
|
messageHandler.on('JpegDecode', function(data, promise) {
|
||||||
var imageData = data[0];
|
var imageUrl = data[0];
|
||||||
var components = data[1];
|
var components = data[1];
|
||||||
if (components != 3 && components != 1)
|
if (components != 3 && components != 1)
|
||||||
error('Only 3 component or 1 component can be returned');
|
error('Only 3 component or 1 component can be returned');
|
||||||
|
@ -4734,8 +4904,7 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
||||||
}
|
}
|
||||||
promise.resolve({ data: buf, width: width, height: height});
|
promise.resolve({ data: buf, width: width, height: height});
|
||||||
}).bind(this);
|
}).bind(this);
|
||||||
var src = 'data:image/jpeg;base64,' + window.btoa(imageData);
|
img.src = imageUrl;
|
||||||
img.src = src;
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -4774,6 +4943,16 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
||||||
return promise;
|
return promise;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getPageIndex: function WorkerTransport_getPageIndexByRef(ref) {
|
||||||
|
var promise = new PDFJS.Promise();
|
||||||
|
this.messageHandler.send('GetPageIndex', { ref: ref },
|
||||||
|
function (pageIndex) {
|
||||||
|
promise.resolve(pageIndex);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return promise;
|
||||||
|
},
|
||||||
|
|
||||||
getAnnotations: function WorkerTransport_getAnnotations(pageIndex) {
|
getAnnotations: function WorkerTransport_getAnnotations(pageIndex) {
|
||||||
this.messageHandler.send('GetAnnotationsRequest',
|
this.messageHandler.send('GetAnnotationsRequest',
|
||||||
{ pageIndex: pageIndex });
|
{ pageIndex: pageIndex });
|
||||||
|
@ -4787,6 +4966,21 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
return promise;
|
return promise;
|
||||||
|
},
|
||||||
|
|
||||||
|
startCleanup: function WorkerTransport_startCleanup() {
|
||||||
|
this.messageHandler.send('Cleanup', null,
|
||||||
|
function endCleanup() {
|
||||||
|
for (var i = 0, ii = this.pageCache.length; i < ii; i++) {
|
||||||
|
var page = this.pageCache[i];
|
||||||
|
if (page) {
|
||||||
|
page.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.commonObjs.clear();
|
||||||
|
FontLoader.clear();
|
||||||
|
}.bind(this)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return WorkerTransport;
|
return WorkerTransport;
|
||||||
|
@ -5007,7 +5201,7 @@ var InternalRenderTask = (function InternalRenderTaskClosure() {
|
||||||
this.operatorListIdx,
|
this.operatorListIdx,
|
||||||
this._continue.bind(this),
|
this._continue.bind(this),
|
||||||
this.stepper);
|
this.stepper);
|
||||||
if (this.operatorListIdx === this.operatorList.fnArray.length) {
|
if (this.operatorListIdx === this.operatorList.argsArray.length) {
|
||||||
this.running = false;
|
this.running = false;
|
||||||
if (this.operatorList.lastChunk) {
|
if (this.operatorList.lastChunk) {
|
||||||
this.gfx.endDrawing();
|
this.gfx.endDrawing();
|
||||||
|
@ -5536,37 +5730,6 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||||
var EO_CLIP = {};
|
var EO_CLIP = {};
|
||||||
|
|
||||||
CanvasGraphics.prototype = {
|
CanvasGraphics.prototype = {
|
||||||
slowCommands: {
|
|
||||||
'stroke': true,
|
|
||||||
'closeStroke': true,
|
|
||||||
'fill': true,
|
|
||||||
'eoFill': true,
|
|
||||||
'fillStroke': true,
|
|
||||||
'eoFillStroke': true,
|
|
||||||
'closeFillStroke': true,
|
|
||||||
'closeEOFillStroke': true,
|
|
||||||
'showText': true,
|
|
||||||
'showSpacedText': true,
|
|
||||||
'setStrokeColorSpace': true,
|
|
||||||
'setFillColorSpace': true,
|
|
||||||
'setStrokeColor': true,
|
|
||||||
'setStrokeColorN': true,
|
|
||||||
'setFillColor': true,
|
|
||||||
'setFillColorN': true,
|
|
||||||
'setStrokeGray': true,
|
|
||||||
'setFillGray': true,
|
|
||||||
'setStrokeRGBColor': true,
|
|
||||||
'setFillRGBColor': true,
|
|
||||||
'setStrokeCMYKColor': true,
|
|
||||||
'setFillCMYKColor': true,
|
|
||||||
'paintJpegXObject': true,
|
|
||||||
'paintImageXObject': true,
|
|
||||||
'paintInlineImageXObject': true,
|
|
||||||
'paintInlineImageXObjectGroup': true,
|
|
||||||
'paintImageMaskXObject': true,
|
|
||||||
'paintImageMaskXObjectGroup': true,
|
|
||||||
'shadingFill': true
|
|
||||||
},
|
|
||||||
|
|
||||||
beginDrawing: function CanvasGraphics_beginDrawing(viewport, transparency) {
|
beginDrawing: function CanvasGraphics_beginDrawing(viewport, transparency) {
|
||||||
// For pdfs that use blend modes we have to clear the canvas else certain
|
// For pdfs that use blend modes we have to clear the canvas else certain
|
||||||
|
@ -5618,8 +5781,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||||
|
|
||||||
var commonObjs = this.commonObjs;
|
var commonObjs = this.commonObjs;
|
||||||
var objs = this.objs;
|
var objs = this.objs;
|
||||||
var fnName;
|
var fnId;
|
||||||
var slowCommands = this.slowCommands;
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (stepper && i === stepper.nextBreakPoint) {
|
if (stepper && i === stepper.nextBreakPoint) {
|
||||||
|
@ -5627,10 +5789,10 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
fnName = fnArray[i];
|
fnId = fnArray[i];
|
||||||
|
|
||||||
if (fnName !== 'dependency') {
|
if (fnId !== OPS.dependency) {
|
||||||
this[fnName].apply(this, argsArray[i]);
|
this[fnId].apply(this, argsArray[i]);
|
||||||
} else {
|
} else {
|
||||||
var deps = argsArray[i];
|
var deps = argsArray[i];
|
||||||
for (var n = 0, nn = deps.length; n < nn; n++) {
|
for (var n = 0, nn = deps.length; n < nn; n++) {
|
||||||
|
@ -5657,10 +5819,10 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the execution took longer then a certain amount of time, shedule
|
// If the execution took longer then a certain amount of time, schedule
|
||||||
// to continue exeution after a short delay.
|
// to continue exeution after a short delay.
|
||||||
// However, this is only possible if a 'continueCallback' is passed in.
|
// However, this is only possible if a 'continueCallback' is passed in.
|
||||||
if (continueCallback && slowCommands[fnName] && Date.now() > endTime) {
|
if (continueCallback && Date.now() > endTime) {
|
||||||
setTimeout(continueCallback, 0);
|
setTimeout(continueCallback, 0);
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
@ -6947,6 +7109,10 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
for (var op in OPS) {
|
||||||
|
CanvasGraphics.prototype[OPS[op]] = CanvasGraphics.prototype[op];
|
||||||
|
}
|
||||||
|
|
||||||
return CanvasGraphics;
|
return CanvasGraphics;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
@ -6967,6 +7133,12 @@ var FontLoader = {
|
||||||
var styleSheet = styleElement.sheet;
|
var styleSheet = styleElement.sheet;
|
||||||
styleSheet.insertRule(rule, styleSheet.cssRules.length);
|
styleSheet.insertRule(rule, styleSheet.cssRules.length);
|
||||||
},
|
},
|
||||||
|
clear: function fontLoaderClear() {
|
||||||
|
var styleElement = document.getElementById('PDFJS_FONT_STYLE_TAG');
|
||||||
|
if (styleElement) {
|
||||||
|
styleElement.parentNode.removeChild(styleElement);
|
||||||
|
}
|
||||||
|
},
|
||||||
bind: function fontLoaderBind(fonts, callback) {
|
bind: function fontLoaderBind(fonts, callback) {
|
||||||
assert(!isWorker, 'bind() shall be called from main thread');
|
assert(!isWorker, 'bind() shall be called from main thread');
|
||||||
|
|
||||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,27 @@
|
||||||
|
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||||
|
/* Copyright 2013 Mozilla Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
/* globals */
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var EXPORTED_SYMBOLS = ['DEFAULT_PREFERENCES'];
|
||||||
|
|
||||||
|
var DEFAULT_PREFERENCES = {
|
||||||
|
showPreviousViewOnLoad: true,
|
||||||
|
defaultZoomValue: '',
|
||||||
|
ifAvailableShowOutlineOnLoad: false
|
||||||
|
};
|
|
@ -240,6 +240,8 @@ var Stepper = (function StepperClosure() {
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var opMap = null;
|
||||||
|
|
||||||
var glyphCommands = {
|
var glyphCommands = {
|
||||||
'showText': 0,
|
'showText': 0,
|
||||||
'showSpacedText': 0,
|
'showSpacedText': 0,
|
||||||
|
@ -271,6 +273,12 @@ var Stepper = (function StepperClosure() {
|
||||||
headerRow.appendChild(c('th', 'args'));
|
headerRow.appendChild(c('th', 'args'));
|
||||||
panel.appendChild(content);
|
panel.appendChild(content);
|
||||||
this.table = table;
|
this.table = table;
|
||||||
|
if (!opMap) {
|
||||||
|
opMap = Object.create(null);
|
||||||
|
for (var key in PDFJS.OPS) {
|
||||||
|
opMap[PDFJS.OPS[key]] = key;
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
updateOperatorList: function updateOperatorList(operatorList) {
|
updateOperatorList: function updateOperatorList(operatorList) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
@ -300,7 +308,7 @@ var Stepper = (function StepperClosure() {
|
||||||
breakCell.appendChild(cbox);
|
breakCell.appendChild(cbox);
|
||||||
line.appendChild(breakCell);
|
line.appendChild(breakCell);
|
||||||
line.appendChild(c('td', i.toString()));
|
line.appendChild(c('td', i.toString()));
|
||||||
var fn = operatorList.fnArray[i];
|
var fn = opMap[operatorList.fnArray[i]];
|
||||||
var decArgs = args;
|
var decArgs = args;
|
||||||
if (fn in glyphCommands) {
|
if (fn in glyphCommands) {
|
||||||
var glyphIndex = glyphCommands[fn];
|
var glyphIndex = glyphCommands[fn];
|
||||||
|
|
|
@ -144,7 +144,6 @@ limitations under the License.
|
||||||
</div>
|
</div>
|
||||||
<label id="pageNumberLabel" class="toolbarLabel" for="pageNumber" data-l10n-id="page_label">Page: </label>
|
<label id="pageNumberLabel" class="toolbarLabel" for="pageNumber" data-l10n-id="page_label">Page: </label>
|
||||||
<input type="number" id="pageNumber" class="toolbarField pageNumber" value="1" size="4" min="1" tabindex="8">
|
<input type="number" id="pageNumber" class="toolbarField pageNumber" value="1" size="4" min="1" tabindex="8">
|
||||||
</input>
|
|
||||||
<span id="numPages" class="toolbarLabel"></span>
|
<span id="numPages" class="toolbarLabel"></span>
|
||||||
</div>
|
</div>
|
||||||
<div id="toolbarViewerRight">
|
<div id="toolbarViewerRight">
|
||||||
|
|
|
@ -16,8 +16,8 @@
|
||||||
*/
|
*/
|
||||||
/* globals PDFJS, PDFBug, FirefoxCom, Stats, Cache, PDFFindBar, CustomStyle,
|
/* globals PDFJS, PDFBug, FirefoxCom, Stats, Cache, PDFFindBar, CustomStyle,
|
||||||
PDFFindController, ProgressBar, TextLayerBuilder, DownloadManager,
|
PDFFindController, ProgressBar, TextLayerBuilder, DownloadManager,
|
||||||
getFileName, getOutputScale, scrollIntoView, getPDFFileNameFromURL,
|
getFileName, scrollIntoView, getPDFFileNameFromURL, PDFHistory,
|
||||||
PDFHistory, Settings, PageView, ThumbnailView, noContextMenuHandler,
|
Preferences, Settings, PageView, ThumbnailView, noContextMenuHandler,
|
||||||
SecondaryToolbar, PasswordPrompt, PresentationMode */
|
SecondaryToolbar, PasswordPrompt, PresentationMode */
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
@ -38,6 +38,7 @@ var SCALE_SELECT_CONTAINER_PADDING = 8;
|
||||||
var SCALE_SELECT_PADDING = 22;
|
var SCALE_SELECT_PADDING = 22;
|
||||||
var THUMBNAIL_SCROLL_MARGIN = -19;
|
var THUMBNAIL_SCROLL_MARGIN = -19;
|
||||||
var USE_ONLY_CSS_ZOOM = false;
|
var USE_ONLY_CSS_ZOOM = false;
|
||||||
|
var CLEANUP_TIMEOUT = 30000;
|
||||||
var RenderingStates = {
|
var RenderingStates = {
|
||||||
INITIAL: 0,
|
INITIAL: 0,
|
||||||
RUNNING: 1,
|
RUNNING: 1,
|
||||||
|
@ -154,6 +155,9 @@ function scrollIntoView(element, spot) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
while (parent.clientHeight == parent.scrollHeight) {
|
while (parent.clientHeight == parent.scrollHeight) {
|
||||||
|
if (parent.dataset._scaleY) {
|
||||||
|
offsetY /= parent.dataset._scaleY;
|
||||||
|
}
|
||||||
offsetY += parent.offsetTop;
|
offsetY += parent.offsetTop;
|
||||||
parent = parent.offsetParent;
|
parent = parent.offsetParent;
|
||||||
if (!parent)
|
if (!parent)
|
||||||
|
@ -284,6 +288,92 @@ var Cache = function cacheCache(size) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var EXPORTED_SYMBOLS = ['DEFAULT_PREFERENCES'];
|
||||||
|
|
||||||
|
var DEFAULT_PREFERENCES = {
|
||||||
|
showPreviousViewOnLoad: true,
|
||||||
|
defaultZoomValue: '',
|
||||||
|
ifAvailableShowOutlineOnLoad: false
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var Preferences = (function PreferencesClosure() {
|
||||||
|
function Preferences() {
|
||||||
|
this.prefs = {};
|
||||||
|
this.initializedPromise = this.readFromStorage().then(function(prefObj) {
|
||||||
|
if (prefObj) {
|
||||||
|
this.prefs = prefObj;
|
||||||
|
}
|
||||||
|
}.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
Preferences.prototype = {
|
||||||
|
writeToStorage: function Preferences_writeToStorage(prefObj) {
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
|
||||||
|
readFromStorage: function Preferences_readFromStorage() {
|
||||||
|
var readFromStoragePromise = new PDFJS.Promise();
|
||||||
|
return readFromStoragePromise;
|
||||||
|
},
|
||||||
|
|
||||||
|
reset: function Preferences_reset() {
|
||||||
|
if (this.initializedPromise.isResolved) {
|
||||||
|
this.prefs = {};
|
||||||
|
this.writeToStorage(this.prefs);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
set: function Preferences_set(name, value) {
|
||||||
|
if (!this.initializedPromise.isResolved) {
|
||||||
|
return;
|
||||||
|
} else if (DEFAULT_PREFERENCES[name] === undefined) {
|
||||||
|
console.error('Preferences_set: \'' + name + '\' is undefined.');
|
||||||
|
return;
|
||||||
|
} else if (value === undefined) {
|
||||||
|
console.error('Preferences_set: no value is specified.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var valueType = typeof value;
|
||||||
|
var defaultType = typeof DEFAULT_PREFERENCES[name];
|
||||||
|
|
||||||
|
if (valueType !== defaultType) {
|
||||||
|
if (valueType === 'number' && defaultType === 'string') {
|
||||||
|
value = value.toString();
|
||||||
|
} else {
|
||||||
|
console.error('Preferences_set: \'' + value + '\' is a \"' +
|
||||||
|
valueType + '\", expected a \"' + defaultType + '\".');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.prefs[name] = value;
|
||||||
|
this.writeToStorage(this.prefs);
|
||||||
|
},
|
||||||
|
|
||||||
|
get: function Preferences_get(name) {
|
||||||
|
var defaultPref = DEFAULT_PREFERENCES[name];
|
||||||
|
|
||||||
|
if (defaultPref === undefined) {
|
||||||
|
console.error('Preferences_get: \'' + name + '\' is undefined.');
|
||||||
|
return;
|
||||||
|
} else if (this.initializedPromise.isResolved) {
|
||||||
|
var pref = this.prefs[name];
|
||||||
|
|
||||||
|
if (pref !== undefined) {
|
||||||
|
return pref;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return defaultPref;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return Preferences;
|
||||||
|
})();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var FirefoxCom = (function FirefoxComClosure() {
|
var FirefoxCom = (function FirefoxComClosure() {
|
||||||
|
@ -373,6 +463,17 @@ var DownloadManager = (function DownloadManagerClosure() {
|
||||||
return DownloadManager;
|
return DownloadManager;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
Preferences.prototype.writeToStorage = function(prefObj) {
|
||||||
|
FirefoxCom.requestSync('setPreferences', prefObj);
|
||||||
|
};
|
||||||
|
|
||||||
|
Preferences.prototype.readFromStorage = function() {
|
||||||
|
var readFromStoragePromise = new PDFJS.Promise();
|
||||||
|
var readPrefs = JSON.parse(FirefoxCom.requestSync('getPreferences'));
|
||||||
|
readFromStoragePromise.resolve(readPrefs);
|
||||||
|
return readFromStoragePromise;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
var cache = new Cache(CACHE_SIZE);
|
var cache = new Cache(CACHE_SIZE);
|
||||||
var currentPageNumber = 1;
|
var currentPageNumber = 1;
|
||||||
|
@ -580,11 +681,12 @@ var PDFFindBar = {
|
||||||
},
|
},
|
||||||
|
|
||||||
open: function() {
|
open: function() {
|
||||||
if (this.opened) return;
|
if (!this.opened) {
|
||||||
|
this.opened = true;
|
||||||
|
this.toggleButton.classList.add('toggled');
|
||||||
|
this.bar.classList.remove('hidden');
|
||||||
|
}
|
||||||
|
|
||||||
this.opened = true;
|
|
||||||
this.toggleButton.classList.add('toggled');
|
|
||||||
this.bar.classList.remove('hidden');
|
|
||||||
this.findField.select();
|
this.findField.select();
|
||||||
this.findField.focus();
|
this.findField.focus();
|
||||||
},
|
},
|
||||||
|
@ -797,8 +899,8 @@ var PDFFindController = {
|
||||||
},
|
},
|
||||||
|
|
||||||
nextMatch: function() {
|
nextMatch: function() {
|
||||||
var pages = this.pdfPageSource.pages;
|
|
||||||
var previous = this.state.findPrevious;
|
var previous = this.state.findPrevious;
|
||||||
|
var currentPageIndex = this.pdfPageSource.page - 1;
|
||||||
var numPages = this.pdfPageSource.pages.length;
|
var numPages = this.pdfPageSource.pages.length;
|
||||||
|
|
||||||
this.active = true;
|
this.active = true;
|
||||||
|
@ -807,7 +909,7 @@ var PDFFindController = {
|
||||||
// Need to recalculate the matches, reset everything.
|
// Need to recalculate the matches, reset everything.
|
||||||
this.dirtyMatch = false;
|
this.dirtyMatch = false;
|
||||||
this.selected.pageIdx = this.selected.matchIdx = -1;
|
this.selected.pageIdx = this.selected.matchIdx = -1;
|
||||||
this.offset.pageIdx = previous ? numPages - 1 : 0;
|
this.offset.pageIdx = currentPageIndex;
|
||||||
this.offset.matchIdx = null;
|
this.offset.matchIdx = null;
|
||||||
this.hadMatch = false;
|
this.hadMatch = false;
|
||||||
this.resumeCallback = null;
|
this.resumeCallback = null;
|
||||||
|
@ -998,8 +1100,7 @@ var PDFHistory = {
|
||||||
// is opened in the web viewer.
|
// is opened in the web viewer.
|
||||||
this.reInitialized = true;
|
this.reInitialized = true;
|
||||||
}
|
}
|
||||||
window.history.replaceState({ fingerprint: this.fingerprint }, '',
|
this._pushOrReplaceState({ fingerprint: this.fingerprint }, true);
|
||||||
document.URL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
@ -1064,6 +1165,15 @@ var PDFHistory = {
|
||||||
state.target && state.target.hash) ? true : false;
|
state.target && state.target.hash) ? true : false;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_pushOrReplaceState: function pdfHistory_pushOrReplaceState(stateObj,
|
||||||
|
replace) {
|
||||||
|
if (replace) {
|
||||||
|
window.history.replaceState(stateObj, '');
|
||||||
|
} else {
|
||||||
|
window.history.pushState(stateObj, '');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
get isHashChangeUnlocked() {
|
get isHashChangeUnlocked() {
|
||||||
if (!this.initialized) {
|
if (!this.initialized) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -1224,11 +1334,8 @@ var PDFHistory = {
|
||||||
this._pushToHistory(previousParams, false, replacePrevious);
|
this._pushToHistory(previousParams, false, replacePrevious);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (overwrite || this.uid === 0) {
|
this._pushOrReplaceState(this._stateObj(params),
|
||||||
window.history.replaceState(this._stateObj(params), '', document.URL);
|
(overwrite || this.uid === 0));
|
||||||
} else {
|
|
||||||
window.history.pushState(this._stateObj(params), '', document.URL);
|
|
||||||
}
|
|
||||||
this.currentUid = this.uid++;
|
this.currentUid = this.uid++;
|
||||||
this.current = params;
|
this.current = params;
|
||||||
this.updatePreviousBookmark = true;
|
this.updatePreviousBookmark = true;
|
||||||
|
@ -1689,6 +1796,7 @@ var PDFView = {
|
||||||
lastScroll: 0,
|
lastScroll: 0,
|
||||||
previousPageNumber: 1,
|
previousPageNumber: 1,
|
||||||
isViewerEmbedded: (window.parent !== window),
|
isViewerEmbedded: (window.parent !== window),
|
||||||
|
idleTimeout: null,
|
||||||
|
|
||||||
// called once when the document is loaded
|
// called once when the document is loaded
|
||||||
initialize: function pdfViewInitialize() {
|
initialize: function pdfViewInitialize() {
|
||||||
|
@ -1789,7 +1897,7 @@ var PDFView = {
|
||||||
var number = parseFloat(value);
|
var number = parseFloat(value);
|
||||||
var scale;
|
var scale;
|
||||||
|
|
||||||
if (number) {
|
if (number > 0) {
|
||||||
scale = number;
|
scale = number;
|
||||||
resetAutoSettings = true;
|
resetAutoSettings = true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1816,6 +1924,10 @@ var PDFView = {
|
||||||
case 'auto':
|
case 'auto':
|
||||||
scale = Math.min(MAX_AUTO_SCALE, pageWidthScale);
|
scale = Math.min(MAX_AUTO_SCALE, pageWidthScale);
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
console.error('pdfViewSetScale: \'' + value +
|
||||||
|
'\' is an unknown zoom value.');
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.currentScaleValue = value;
|
this.currentScaleValue = value;
|
||||||
|
@ -2019,7 +2131,8 @@ var PDFView = {
|
||||||
switch (args.pdfjsLoadAction) {
|
switch (args.pdfjsLoadAction) {
|
||||||
case 'supportsRangedLoading':
|
case 'supportsRangedLoading':
|
||||||
PDFView.open(args.pdfUrl, 0, undefined, pdfDataRangeTransport, {
|
PDFView.open(args.pdfUrl, 0, undefined, pdfDataRangeTransport, {
|
||||||
length: args.length
|
length: args.length,
|
||||||
|
initialData: args.data
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 'range':
|
case 'range':
|
||||||
|
@ -2182,9 +2295,9 @@ var PDFView = {
|
||||||
// Update the browsing history.
|
// Update the browsing history.
|
||||||
PDFHistory.push({ dest: dest, hash: destString, page: pageNumber });
|
PDFHistory.push({ dest: dest, hash: destString, page: pageNumber });
|
||||||
} else {
|
} else {
|
||||||
self.pendingRefStrLoaded = new PDFJS.Promise();
|
self.pdfDocument.getPageIndex(destRef).then(function (pageIndex) {
|
||||||
self.pendingRefStr = destRef.num + ' ' + destRef.gen + ' R';
|
var pageNum = pageIndex + 1;
|
||||||
self.pendingRefStrLoaded.then(function() {
|
self.pagesRefMap[destRef.num + ' ' + destRef.gen + ' R'] = pageNum;
|
||||||
goToDestination(destRef);
|
goToDestination(destRef);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -2289,9 +2402,14 @@ var PDFView = {
|
||||||
},
|
},
|
||||||
|
|
||||||
load: function pdfViewLoad(pdfDocument, scale) {
|
load: function pdfViewLoad(pdfDocument, scale) {
|
||||||
|
var self = this;
|
||||||
|
var onePageRendered = new PDFJS.Promise();
|
||||||
function bindOnAfterDraw(pageView, thumbnailView) {
|
function bindOnAfterDraw(pageView, thumbnailView) {
|
||||||
// when page is painted, using the image as thumbnail base
|
// when page is painted, using the image as thumbnail base
|
||||||
pageView.onAfterDraw = function pdfViewLoadOnAfterDraw() {
|
pageView.onAfterDraw = function pdfViewLoadOnAfterDraw() {
|
||||||
|
if (!onePageRendered.isResolved) {
|
||||||
|
onePageRendered.resolve();
|
||||||
|
}
|
||||||
thumbnailView.setImage(pageView.canvas);
|
thumbnailView.setImage(pageView.canvas);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -2329,6 +2447,7 @@ var PDFView = {
|
||||||
mozL10n.get('page_of', {pageCount: pagesCount}, 'of {{pageCount}}');
|
mozL10n.get('page_of', {pageCount: pagesCount}, 'of {{pageCount}}');
|
||||||
document.getElementById('pageNumber').max = pagesCount;
|
document.getElementById('pageNumber').max = pagesCount;
|
||||||
|
|
||||||
|
var prefs = PDFView.prefs = new Preferences();
|
||||||
PDFView.documentFingerprint = id;
|
PDFView.documentFingerprint = id;
|
||||||
var store = PDFView.store = new Settings(id);
|
var store = PDFView.store = new Settings(id);
|
||||||
|
|
||||||
|
@ -2339,7 +2458,6 @@ var PDFView = {
|
||||||
var thumbnails = this.thumbnails = [];
|
var thumbnails = this.thumbnails = [];
|
||||||
|
|
||||||
var pagesPromise = this.pagesPromise = new PDFJS.Promise();
|
var pagesPromise = this.pagesPromise = new PDFJS.Promise();
|
||||||
var self = this;
|
|
||||||
|
|
||||||
var firstPagePromise = pdfDocument.getPage(1);
|
var firstPagePromise = pdfDocument.getPage(1);
|
||||||
|
|
||||||
|
@ -2347,7 +2465,6 @@ var PDFView = {
|
||||||
// viewport for all pages
|
// viewport for all pages
|
||||||
firstPagePromise.then(function(pdfPage) {
|
firstPagePromise.then(function(pdfPage) {
|
||||||
var viewport = pdfPage.getViewport((scale || 1.0) * CSS_UNITS);
|
var viewport = pdfPage.getViewport((scale || 1.0) * CSS_UNITS);
|
||||||
var pagePromises = [];
|
|
||||||
for (var pageNum = 1; pageNum <= pagesCount; ++pageNum) {
|
for (var pageNum = 1; pageNum <= pagesCount; ++pageNum) {
|
||||||
var viewportClone = viewport.clone();
|
var viewportClone = viewport.clone();
|
||||||
var pageView = new PageView(container, pageNum, scale,
|
var pageView = new PageView(container, pageNum, scale,
|
||||||
|
@ -2360,56 +2477,59 @@ var PDFView = {
|
||||||
thumbnails.push(thumbnailView);
|
thumbnails.push(thumbnailView);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fetch all the pages since the viewport is needed before printing
|
||||||
|
// starts to create the correct size canvas. Wait until one page is
|
||||||
|
// rendered so we don't tie up too many resources early on.
|
||||||
|
onePageRendered.then(function () {
|
||||||
|
if (!PDFJS.disableAutoFetch) {
|
||||||
|
var getPagesLeft = pagesCount;
|
||||||
|
for (var pageNum = 1; pageNum <= pagesCount; ++pageNum) {
|
||||||
|
pdfDocument.getPage(pageNum).then(function (pageNum, pdfPage) {
|
||||||
|
var pageView = pages[pageNum - 1];
|
||||||
|
if (!pageView.pdfPage) {
|
||||||
|
pageView.setPdfPage(pdfPage);
|
||||||
|
}
|
||||||
|
var refStr = pdfPage.ref.num + ' ' + pdfPage.ref.gen + ' R';
|
||||||
|
pagesRefMap[refStr] = pageNum;
|
||||||
|
getPagesLeft--;
|
||||||
|
if (!getPagesLeft) {
|
||||||
|
pagesPromise.resolve();
|
||||||
|
}
|
||||||
|
}.bind(null, pageNum));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// XXX: Printing is semi-broken with auto fetch disabled.
|
||||||
|
pagesPromise.resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
var event = document.createEvent('CustomEvent');
|
var event = document.createEvent('CustomEvent');
|
||||||
event.initCustomEvent('documentload', true, true, {});
|
event.initCustomEvent('documentload', true, true, {});
|
||||||
window.dispatchEvent(event);
|
window.dispatchEvent(event);
|
||||||
|
|
||||||
PDFView.loadingBar.setWidth(container);
|
PDFView.loadingBar.setWidth(container);
|
||||||
|
|
||||||
for (var pageNum = 1; pageNum <= pagesCount; ++pageNum) {
|
|
||||||
var pagePromise = pdfDocument.getPage(pageNum);
|
|
||||||
pagePromise.then(function(pdfPage) {
|
|
||||||
var pageNum = pdfPage.pageNumber;
|
|
||||||
var pageView = pages[pageNum - 1];
|
|
||||||
if (!pageView.pdfPage) {
|
|
||||||
// The pdfPage might already be set if we've already entered
|
|
||||||
// pageView.draw()
|
|
||||||
pageView.setPdfPage(pdfPage);
|
|
||||||
}
|
|
||||||
var thumbnailView = thumbnails[pageNum - 1];
|
|
||||||
if (!thumbnailView.pdfPage) {
|
|
||||||
thumbnailView.setPdfPage(pdfPage);
|
|
||||||
}
|
|
||||||
|
|
||||||
var pageRef = pdfPage.ref;
|
|
||||||
var refStr = pageRef.num + ' ' + pageRef.gen + ' R';
|
|
||||||
pagesRefMap[refStr] = pdfPage.pageNumber;
|
|
||||||
|
|
||||||
if (self.pendingRefStr && self.pendingRefStr === refStr) {
|
|
||||||
self.pendingRefStrLoaded.resolve();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
pagePromises.push(pagePromise);
|
|
||||||
}
|
|
||||||
|
|
||||||
PDFFindController.firstPagePromise.resolve();
|
PDFFindController.firstPagePromise.resolve();
|
||||||
|
|
||||||
PDFJS.Promise.all(pagePromises).then(function(pages) {
|
|
||||||
pagesPromise.resolve(pages);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var prefsPromise = prefs.initializedPromise;
|
||||||
var storePromise = store.initializedPromise;
|
var storePromise = store.initializedPromise;
|
||||||
PDFJS.Promise.all([firstPagePromise, storePromise]).then(function() {
|
PDFJS.Promise.all([firstPagePromise, prefsPromise, storePromise]).
|
||||||
|
then(function() {
|
||||||
|
var showPreviousViewOnLoad = prefs.get('showPreviousViewOnLoad');
|
||||||
|
var defaultZoomValue = prefs.get('defaultZoomValue');
|
||||||
|
|
||||||
var storedHash = null;
|
var storedHash = null;
|
||||||
if (store.get('exists', false)) {
|
if (showPreviousViewOnLoad && store.get('exists', false)) {
|
||||||
var pageNum = store.get('page', '1');
|
var pageNum = store.get('page', '1');
|
||||||
var zoom = store.get('zoom', PDFView.currentScale);
|
var zoom = defaultZoomValue || store.get('zoom', PDFView.currentScale);
|
||||||
var left = store.get('scrollLeft', '0');
|
var left = store.get('scrollLeft', '0');
|
||||||
var top = store.get('scrollTop', '0');
|
var top = store.get('scrollTop', '0');
|
||||||
|
|
||||||
storedHash = 'page=' + pageNum + '&zoom=' + zoom + ',' +
|
storedHash = 'page=' + pageNum + '&zoom=' + zoom + ',' +
|
||||||
left + ',' + top;
|
left + ',' + top;
|
||||||
|
} else if (defaultZoomValue) {
|
||||||
|
storedHash = 'page=1&zoom=' + defaultZoomValue;
|
||||||
}
|
}
|
||||||
// Initialize the browsing history.
|
// Initialize the browsing history.
|
||||||
PDFHistory.initialize(self.documentFingerprint);
|
PDFHistory.initialize(self.documentFingerprint);
|
||||||
|
@ -2459,6 +2579,13 @@ var PDFView = {
|
||||||
pdfDocument.getOutline().then(function(outline) {
|
pdfDocument.getOutline().then(function(outline) {
|
||||||
self.outline = new DocumentOutlineView(outline);
|
self.outline = new DocumentOutlineView(outline);
|
||||||
document.getElementById('viewOutline').disabled = !outline;
|
document.getElementById('viewOutline').disabled = !outline;
|
||||||
|
|
||||||
|
if (outline && prefs.get('ifAvailableShowOutlineOnLoad')) {
|
||||||
|
if (!self.sidebarOpen) {
|
||||||
|
document.getElementById('sidebarToggle').click();
|
||||||
|
}
|
||||||
|
self.switchSidebarView('outline');
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2550,6 +2677,11 @@ var PDFView = {
|
||||||
},
|
},
|
||||||
|
|
||||||
renderHighestPriority: function pdfViewRenderHighestPriority() {
|
renderHighestPriority: function pdfViewRenderHighestPriority() {
|
||||||
|
if (PDFView.idleTimeout) {
|
||||||
|
clearTimeout(PDFView.idleTimeout);
|
||||||
|
PDFView.idleTimeout = null;
|
||||||
|
}
|
||||||
|
|
||||||
// Pages have a higher priority than thumbnails, so check them first.
|
// Pages have a higher priority than thumbnails, so check them first.
|
||||||
var visiblePages = this.getVisiblePages();
|
var visiblePages = this.getVisiblePages();
|
||||||
var pageView = this.getHighestPriority(visiblePages, this.pages,
|
var pageView = this.getHighestPriority(visiblePages, this.pages,
|
||||||
|
@ -2564,9 +2696,25 @@ var PDFView = {
|
||||||
var thumbView = this.getHighestPriority(visibleThumbs,
|
var thumbView = this.getHighestPriority(visibleThumbs,
|
||||||
this.thumbnails,
|
this.thumbnails,
|
||||||
this.thumbnailViewScroll.down);
|
this.thumbnailViewScroll.down);
|
||||||
if (thumbView)
|
if (thumbView) {
|
||||||
this.renderView(thumbView, 'thumbnail');
|
this.renderView(thumbView, 'thumbnail');
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PDFView.idleTimeout = setTimeout(function () {
|
||||||
|
PDFView.cleanup();
|
||||||
|
}, CLEANUP_TIMEOUT);
|
||||||
|
},
|
||||||
|
|
||||||
|
cleanup: function pdfViewCleanup() {
|
||||||
|
for (var i = 0, ii = this.pages.length; i < ii; i++) {
|
||||||
|
if (this.pages[i] &&
|
||||||
|
this.pages[i].renderingState !== RenderingStates.FINISHED) {
|
||||||
|
this.pages[i].reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.pdfDocument.cleanup();
|
||||||
},
|
},
|
||||||
|
|
||||||
getHighestPriority: function pdfViewGetHighestPriority(visible, views,
|
getHighestPriority: function pdfViewGetHighestPriority(visible, views,
|
||||||
|
@ -2643,28 +2791,31 @@ var PDFView = {
|
||||||
PDFView.navigateTo(params.nameddest);
|
PDFView.navigateTo(params.nameddest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
var pageNumber, dest;
|
||||||
if ('page' in params) {
|
if ('page' in params) {
|
||||||
var pageNumber = (params.page | 0) || 1;
|
pageNumber = (params.page | 0) || 1;
|
||||||
if ('zoom' in params) {
|
}
|
||||||
var zoomArgs = params.zoom.split(','); // scale,left,top
|
if ('zoom' in params) {
|
||||||
// building destination array
|
var zoomArgs = params.zoom.split(','); // scale,left,top
|
||||||
|
// building destination array
|
||||||
|
|
||||||
// If the zoom value, it has to get divided by 100. If it is a string,
|
// If the zoom value, it has to get divided by 100. If it is a string,
|
||||||
// it should stay as it is.
|
// it should stay as it is.
|
||||||
var zoomArg = zoomArgs[0];
|
var zoomArg = zoomArgs[0];
|
||||||
var zoomArgNumber = parseFloat(zoomArg);
|
var zoomArgNumber = parseFloat(zoomArg);
|
||||||
if (zoomArgNumber)
|
if (zoomArgNumber) {
|
||||||
zoomArg = zoomArgNumber / 100;
|
zoomArg = zoomArgNumber / 100;
|
||||||
|
|
||||||
var dest = [null, {name: 'XYZ'},
|
|
||||||
zoomArgs.length > 1 ? (zoomArgs[1] | 0) : null,
|
|
||||||
zoomArgs.length > 2 ? (zoomArgs[2] | 0) : null,
|
|
||||||
zoomArg];
|
|
||||||
var currentPage = this.pages[pageNumber - 1];
|
|
||||||
currentPage.scrollIntoView(dest);
|
|
||||||
} else {
|
|
||||||
this.page = pageNumber; // simple page
|
|
||||||
}
|
}
|
||||||
|
dest = [null, {name: 'XYZ'},
|
||||||
|
zoomArgs.length > 1 ? (zoomArgs[1] | 0) : null,
|
||||||
|
zoomArgs.length > 2 ? (zoomArgs[2] | 0) : null,
|
||||||
|
zoomArg];
|
||||||
|
}
|
||||||
|
if (dest) {
|
||||||
|
var currentPage = this.pages[(pageNumber || this.page) - 1];
|
||||||
|
currentPage.scrollIntoView(dest);
|
||||||
|
} else if (pageNumber) {
|
||||||
|
this.page = pageNumber; // simple page
|
||||||
}
|
}
|
||||||
if ('pagemode' in params) {
|
if ('pagemode' in params) {
|
||||||
var toggle = document.getElementById('sidebarToggle');
|
var toggle = document.getElementById('sidebarToggle');
|
||||||
|
@ -2935,12 +3086,11 @@ var PageView = function pageView(container, id, scale,
|
||||||
this.rotation = 0;
|
this.rotation = 0;
|
||||||
this.scale = scale || 1.0;
|
this.scale = scale || 1.0;
|
||||||
this.viewport = defaultViewport;
|
this.viewport = defaultViewport;
|
||||||
this.pdfPageRotate = defaultViewport.rotate;
|
this.pdfPageRotate = defaultViewport.rotation;
|
||||||
|
|
||||||
this.renderingState = RenderingStates.INITIAL;
|
this.renderingState = RenderingStates.INITIAL;
|
||||||
this.resume = null;
|
this.resume = null;
|
||||||
|
|
||||||
this.textContent = null;
|
|
||||||
this.textLayer = null;
|
this.textLayer = null;
|
||||||
|
|
||||||
this.zoomLayer = null;
|
this.zoomLayer = null;
|
||||||
|
@ -2962,7 +3112,8 @@ var PageView = function pageView(container, id, scale,
|
||||||
this.setPdfPage = function pageViewSetPdfPage(pdfPage) {
|
this.setPdfPage = function pageViewSetPdfPage(pdfPage) {
|
||||||
this.pdfPage = pdfPage;
|
this.pdfPage = pdfPage;
|
||||||
this.pdfPageRotate = pdfPage.rotate;
|
this.pdfPageRotate = pdfPage.rotate;
|
||||||
this.viewport = pdfPage.getViewport(this.scale * CSS_UNITS);
|
var totalRotation = (this.rotation + this.pdfPageRotate) % 360;
|
||||||
|
this.viewport = pdfPage.getViewport(this.scale * CSS_UNITS, totalRotation);
|
||||||
this.stats = pdfPage.stats;
|
this.stats = pdfPage.stats;
|
||||||
this.reset();
|
this.reset();
|
||||||
};
|
};
|
||||||
|
@ -3279,7 +3430,7 @@ var PageView = function pageView(container, id, scale,
|
||||||
width / CSS_UNITS;
|
width / CSS_UNITS;
|
||||||
heightScale = (PDFView.container.clientHeight - SCROLLBAR_PADDING) /
|
heightScale = (PDFView.container.clientHeight - SCROLLBAR_PADDING) /
|
||||||
height / CSS_UNITS;
|
height / CSS_UNITS;
|
||||||
scale = Math.min(widthScale, heightScale);
|
scale = Math.min(Math.abs(widthScale), Math.abs(heightScale));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
|
@ -3313,10 +3464,9 @@ var PageView = function pageView(container, id, scale,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.getTextContent = function pageviewGetTextContent() {
|
this.getTextContent = function pageviewGetTextContent() {
|
||||||
if (!this.textContent) {
|
return PDFView.getPage(this.id).then(function(pdfPage) {
|
||||||
this.textContent = this.pdfPage.getTextContent();
|
return pdfPage.getTextContent();
|
||||||
}
|
});
|
||||||
return this.textContent;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.draw = function pageviewDraw(callback) {
|
this.draw = function pageviewDraw(callback) {
|
||||||
|
@ -3364,8 +3514,8 @@ var PageView = function pageView(container, id, scale,
|
||||||
outputScale.scaled = true;
|
outputScale.scaled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas.width = Math.floor(viewport.width * outputScale.sx);
|
canvas.width = (Math.floor(viewport.width) * outputScale.sx) | 0;
|
||||||
canvas.height = Math.floor(viewport.height * outputScale.sy);
|
canvas.height = (Math.floor(viewport.height) * outputScale.sy) | 0;
|
||||||
canvas.style.width = Math.floor(viewport.width) + 'px';
|
canvas.style.width = Math.floor(viewport.width) + 'px';
|
||||||
canvas.style.height = Math.floor(viewport.height) + 'px';
|
canvas.style.height = Math.floor(viewport.height) + 'px';
|
||||||
// Add the viewport so it's known what it was originally drawn with.
|
// Add the viewport so it's known what it was originally drawn with.
|
||||||
|
@ -3398,6 +3548,8 @@ var PageView = function pageView(container, id, scale,
|
||||||
(1 / outputScale.sy) + ')';
|
(1 / outputScale.sy) + ')';
|
||||||
CustomStyle.setProp('transform' , textLayerDiv, cssScale);
|
CustomStyle.setProp('transform' , textLayerDiv, cssScale);
|
||||||
CustomStyle.setProp('transformOrigin' , textLayerDiv, '0% 0%');
|
CustomStyle.setProp('transformOrigin' , textLayerDiv, '0% 0%');
|
||||||
|
textLayerDiv.dataset._scaleX = outputScale.sx;
|
||||||
|
textLayerDiv.dataset._scaleY = outputScale.sy;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checking if document fonts are used only once
|
// Checking if document fonts are used only once
|
||||||
|
@ -3813,27 +3965,24 @@ var TextLayerBuilder = function textLayerBuilder(options) {
|
||||||
if ('isWhitespace' in textDiv.dataset) {
|
if ('isWhitespace' in textDiv.dataset) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
textLayerFrag.appendChild(textDiv);
|
|
||||||
|
|
||||||
ctx.font = textDiv.style.fontSize + ' ' + textDiv.style.fontFamily;
|
ctx.font = textDiv.style.fontSize + ' ' + textDiv.style.fontFamily;
|
||||||
var width = ctx.measureText(textDiv.textContent).width;
|
var width = ctx.measureText(textDiv.textContent).width;
|
||||||
|
|
||||||
if (width > 0) {
|
if (width > 0) {
|
||||||
|
textLayerFrag.appendChild(textDiv);
|
||||||
var textScale = textDiv.dataset.canvasWidth / width;
|
var textScale = textDiv.dataset.canvasWidth / width;
|
||||||
var rotation = textDiv.dataset.angle;
|
var rotation = textDiv.dataset.angle;
|
||||||
var transform = 'scale(' + textScale + ', 1)';
|
var transform = 'scale(' + textScale + ', 1)';
|
||||||
transform = 'rotate(' + rotation + 'deg) ' + transform;
|
transform = 'rotate(' + rotation + 'deg) ' + transform;
|
||||||
CustomStyle.setProp('transform' , textDiv, transform);
|
CustomStyle.setProp('transform' , textDiv, transform);
|
||||||
CustomStyle.setProp('transformOrigin' , textDiv, '0% 0%');
|
CustomStyle.setProp('transformOrigin' , textDiv, '0% 0%');
|
||||||
|
|
||||||
textLayerDiv.appendChild(textDiv);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
textLayerDiv.appendChild(textLayerFrag);
|
||||||
this.renderingDone = true;
|
this.renderingDone = true;
|
||||||
this.updateMatches();
|
this.updateMatches();
|
||||||
|
|
||||||
textLayerDiv.appendChild(textLayerFrag);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.setupRenderLayoutTimer = function textLayerSetupRenderLayoutTimer() {
|
this.setupRenderLayoutTimer = function textLayerSetupRenderLayoutTimer() {
|
||||||
|
@ -4587,7 +4736,7 @@ window.addEventListener('keydown', function keydown(evt) {
|
||||||
switch (evt.keyCode) {
|
switch (evt.keyCode) {
|
||||||
case 70: // f
|
case 70: // f
|
||||||
if (!PDFView.supportsIntegratedFind) {
|
if (!PDFView.supportsIntegratedFind) {
|
||||||
PDFFindBar.toggle();
|
PDFFindBar.open();
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -4629,6 +4778,11 @@ window.addEventListener('keydown', function keydown(evt) {
|
||||||
SecondaryToolbar.presentationModeClick();
|
SecondaryToolbar.presentationModeClick();
|
||||||
handled = true;
|
handled = true;
|
||||||
break;
|
break;
|
||||||
|
case 71: // g
|
||||||
|
// focuses input#pageNumber field
|
||||||
|
document.getElementById('pageNumber').select();
|
||||||
|
handled = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ content/PdfJs.jsm
|
||||||
content/PdfJsTelemetry.jsm
|
content/PdfJsTelemetry.jsm
|
||||||
content/build/pdf.js
|
content/build/pdf.js
|
||||||
content/build/pdf.worker.js
|
content/build/pdf.worker.js
|
||||||
|
content/default_preferences.js
|
||||||
content/network.js
|
content/network.js
|
||||||
content/web/debugger.js
|
content/web/debugger.js
|
||||||
content/web/images/annotation-check.svg
|
content/web/images/annotation-check.svg
|
||||||
|
|
|
@ -1187,10 +1187,14 @@ paintflashingManual=Draw repainted areas in different colors
|
||||||
# tooltip of button in devtools toolbox which toggles paint flashing.
|
# tooltip of button in devtools toolbox which toggles paint flashing.
|
||||||
paintflashingTooltip=Highlight painted area
|
paintflashingTooltip=Highlight painted area
|
||||||
|
|
||||||
# LOCALIZATION NOTE (paintflashingOnDesc) A very short string used to describe the
|
# LOCALIZATION NOTE (paintflashingToggleDesc) A very short string used to describe the
|
||||||
# function of the "paintflashing on" command.
|
# function of the "paintflashing toggle" command.
|
||||||
paintflashingToggleDesc=Toggle paint flashing
|
paintflashingToggleDesc=Toggle paint flashing
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (splitconsoleTooltip) A string displayed as the
|
||||||
|
# tooltip of button in devtools toolbox which toggles the split webconsole.
|
||||||
|
splitconsoleTooltip=Toggle split console
|
||||||
|
|
||||||
# LOCALIZATION NOTE (appCacheDesc) A very short string used to describe the
|
# LOCALIZATION NOTE (appCacheDesc) A very short string used to describe the
|
||||||
# function of the "appcache" command
|
# function of the "appcache" command
|
||||||
appCacheDesc=Application cache utilities
|
appCacheDesc=Application cache utilities
|
||||||
|
|
|
@ -115,10 +115,11 @@ var Appbar = {
|
||||||
onMenuButton: function(aEvent) {
|
onMenuButton: function(aEvent) {
|
||||||
let typesArray = [];
|
let typesArray = [];
|
||||||
|
|
||||||
if (!BrowserUI.isStartTabVisible)
|
if (!BrowserUI.isStartTabVisible) {
|
||||||
typesArray.push("find-in-page");
|
typesArray.push("find-in-page");
|
||||||
if (ContextCommands.getPageSource())
|
if (ContextCommands.getPageSource())
|
||||||
typesArray.push("view-page-source");
|
typesArray.push("view-page-source");
|
||||||
|
}
|
||||||
if (ContextCommands.getStoreLink())
|
if (ContextCommands.getStoreLink())
|
||||||
typesArray.push("ms-meta-data");
|
typesArray.push("ms-meta-data");
|
||||||
if (ConsolePanelView.enabled)
|
if (ConsolePanelView.enabled)
|
||||||
|
|
|
@ -265,10 +265,10 @@ Desktop browser's sync prefs.
|
||||||
<hbox id="toolbar-context-page" pack="end">
|
<hbox id="toolbar-context-page" pack="end">
|
||||||
<circularprogressindicator id="download-progress" class="appbar-primary"
|
<circularprogressindicator id="download-progress" class="appbar-primary"
|
||||||
oncommand="MetroDownloadsView.onDownloadButton()"/>
|
oncommand="MetroDownloadsView.onDownloadButton()"/>
|
||||||
<toolbarbutton id="star-button" class="appbar-primary"
|
<toolbarbutton id="star-button" class="appbar-primary hide-on-start"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
oncommand="Appbar.onStarButton()"/>
|
oncommand="Appbar.onStarButton()"/>
|
||||||
<toolbarbutton id="pin-button" class="appbar-primary"
|
<toolbarbutton id="pin-button" class="appbar-primary hide-on-start"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
oncommand="Appbar.onPinButton()"/>
|
oncommand="Appbar.onPinButton()"/>
|
||||||
<toolbarbutton id="menu-button" class="appbar-primary"
|
<toolbarbutton id="menu-button" class="appbar-primary"
|
||||||
|
|
|
@ -118,6 +118,14 @@ var ContextMenuHandler = {
|
||||||
} else {
|
} else {
|
||||||
Util.dumpLn("error: target element does not support nsIDOMNSEditableElement");
|
Util.dumpLn("error: target element does not support nsIDOMNSEditableElement");
|
||||||
}
|
}
|
||||||
|
} else if (this._target.isContentEditable) {
|
||||||
|
try {
|
||||||
|
this._target.ownerDocument.execCommand("paste",
|
||||||
|
false,
|
||||||
|
Ci.nsIClipboard.kGlobalClipboard);
|
||||||
|
} catch (ex) {
|
||||||
|
dump("ContextMenuHandler: exception pasting into contentEditable: " + ex.message + "\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.reset();
|
this.reset();
|
||||||
},
|
},
|
||||||
|
@ -134,6 +142,12 @@ var ContextMenuHandler = {
|
||||||
} else {
|
} else {
|
||||||
Util.dumpLn("error: target element does not support nsIDOMNSEditableElement");
|
Util.dumpLn("error: target element does not support nsIDOMNSEditableElement");
|
||||||
}
|
}
|
||||||
|
} else if (this._target.isContentEditable) {
|
||||||
|
try {
|
||||||
|
this._target.ownerDocument.execCommand("cut", false);
|
||||||
|
} catch (ex) {
|
||||||
|
dump("ContextMenuHandler: exception cutting from contentEditable: " + ex.message + "\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.reset();
|
this.reset();
|
||||||
},
|
},
|
||||||
|
@ -188,12 +202,13 @@ var ContextMenuHandler = {
|
||||||
contentDisposition: "",
|
contentDisposition: "",
|
||||||
string: "",
|
string: "",
|
||||||
};
|
};
|
||||||
|
let uniqueStateTypes = new Set();
|
||||||
|
|
||||||
// Do checks for nodes that never have children.
|
// Do checks for nodes that never have children.
|
||||||
if (popupNode.nodeType == Ci.nsIDOMNode.ELEMENT_NODE) {
|
if (popupNode.nodeType == Ci.nsIDOMNode.ELEMENT_NODE) {
|
||||||
// See if the user clicked on an image.
|
// See if the user clicked on an image.
|
||||||
if (popupNode instanceof Ci.nsIImageLoadingContent && popupNode.currentURI) {
|
if (popupNode instanceof Ci.nsIImageLoadingContent && popupNode.currentURI) {
|
||||||
state.types.push("image");
|
uniqueStateTypes.add("image");
|
||||||
state.label = state.mediaURL = popupNode.currentURI.spec;
|
state.label = state.mediaURL = popupNode.currentURI.spec;
|
||||||
imageUrl = state.mediaURL;
|
imageUrl = state.mediaURL;
|
||||||
this._target = popupNode;
|
this._target = popupNode;
|
||||||
|
@ -218,6 +233,7 @@ var ContextMenuHandler = {
|
||||||
|
|
||||||
let elem = popupNode;
|
let elem = popupNode;
|
||||||
let isText = false;
|
let isText = false;
|
||||||
|
let isEditableText = false;
|
||||||
|
|
||||||
while (elem) {
|
while (elem) {
|
||||||
if (elem.nodeType == Ci.nsIDOMNode.ELEMENT_NODE) {
|
if (elem.nodeType == Ci.nsIDOMNode.ELEMENT_NODE) {
|
||||||
|
@ -230,7 +246,7 @@ var ContextMenuHandler = {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
state.types.push("link");
|
uniqueStateTypes.add("link");
|
||||||
state.label = state.linkURL = this._getLinkURL(elem);
|
state.label = state.linkURL = this._getLinkURL(elem);
|
||||||
linkUrl = state.linkURL;
|
linkUrl = state.linkURL;
|
||||||
state.linkTitle = popupNode.textContent || popupNode.title;
|
state.linkTitle = popupNode.textContent || popupNode.title;
|
||||||
|
@ -238,49 +254,61 @@ var ContextMenuHandler = {
|
||||||
// mark as text so we can pickup on selection below
|
// mark as text so we can pickup on selection below
|
||||||
isText = true;
|
isText = true;
|
||||||
break;
|
break;
|
||||||
} else if (Util.isTextInput(elem)) {
|
}
|
||||||
|
// is the target contentEditable (not just inheriting contentEditable)
|
||||||
|
else if (elem.contentEditable == "true") {
|
||||||
|
this._target = elem;
|
||||||
|
isEditableText = true;
|
||||||
|
isText = true;
|
||||||
|
uniqueStateTypes.add("input-text");
|
||||||
|
|
||||||
|
if (elem.textContent.length) {
|
||||||
|
uniqueStateTypes.add("selectable");
|
||||||
|
} else {
|
||||||
|
uniqueStateTypes.add("input-empty");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// is the target a text input
|
||||||
|
else if (Util.isTextInput(elem)) {
|
||||||
|
this._target = elem;
|
||||||
|
isEditableText = true;
|
||||||
|
uniqueStateTypes.add("input-text");
|
||||||
|
|
||||||
let selectionStart = elem.selectionStart;
|
let selectionStart = elem.selectionStart;
|
||||||
let selectionEnd = elem.selectionEnd;
|
let selectionEnd = elem.selectionEnd;
|
||||||
|
|
||||||
state.types.push("input-text");
|
|
||||||
this._target = elem;
|
|
||||||
|
|
||||||
// Don't include "copy" for password fields.
|
// Don't include "copy" for password fields.
|
||||||
if (!(elem instanceof Ci.nsIDOMHTMLInputElement) || elem.mozIsTextField(true)) {
|
if (!(elem instanceof Ci.nsIDOMHTMLInputElement) || elem.mozIsTextField(true)) {
|
||||||
// If there is a selection add cut and copy
|
// If there is a selection add cut and copy
|
||||||
if (selectionStart != selectionEnd) {
|
if (selectionStart != selectionEnd) {
|
||||||
state.types.push("cut");
|
uniqueStateTypes.add("cut");
|
||||||
state.types.push("copy");
|
uniqueStateTypes.add("copy");
|
||||||
state.string = elem.value.slice(selectionStart, selectionEnd);
|
state.string = elem.value.slice(selectionStart, selectionEnd);
|
||||||
} else if (elem.value && elem.textLength) {
|
} else if (elem.value && elem.textLength) {
|
||||||
// There is text and it is not selected so add selectable items
|
// There is text and it is not selected so add selectable items
|
||||||
state.types.push("selectable");
|
uniqueStateTypes.add("selectable");
|
||||||
state.string = elem.value;
|
state.string = elem.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!elem.textLength) {
|
if (!elem.textLength) {
|
||||||
state.types.push("input-empty");
|
uniqueStateTypes.add("input-empty");
|
||||||
}
|
|
||||||
|
|
||||||
let flavors = ["text/unicode"];
|
|
||||||
let cb = Cc["@mozilla.org/widget/clipboard;1"].getService(Ci.nsIClipboard);
|
|
||||||
let hasData = cb.hasDataMatchingFlavors(flavors,
|
|
||||||
flavors.length,
|
|
||||||
Ci.nsIClipboard.kGlobalClipboard);
|
|
||||||
if (hasData && !elem.readOnly) {
|
|
||||||
state.types.push("paste");
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
} else if (Util.isText(elem)) {
|
}
|
||||||
|
// is the target an element containing text content
|
||||||
|
else if (Util.isText(elem)) {
|
||||||
isText = true;
|
isText = true;
|
||||||
} else if (elem instanceof Ci.nsIDOMHTMLMediaElement ||
|
}
|
||||||
|
// is the target a media element
|
||||||
|
else if (elem instanceof Ci.nsIDOMHTMLMediaElement ||
|
||||||
elem instanceof Ci.nsIDOMHTMLVideoElement) {
|
elem instanceof Ci.nsIDOMHTMLVideoElement) {
|
||||||
state.label = state.mediaURL = (elem.currentSrc || elem.src);
|
state.label = state.mediaURL = (elem.currentSrc || elem.src);
|
||||||
state.types.push((elem.paused || elem.ended) ?
|
uniqueStateTypes.add((elem.paused || elem.ended) ?
|
||||||
"media-paused" : "media-playing");
|
"media-paused" : "media-playing");
|
||||||
if (elem instanceof Ci.nsIDOMHTMLVideoElement) {
|
if (elem instanceof Ci.nsIDOMHTMLVideoElement) {
|
||||||
state.types.push("video");
|
uniqueStateTypes.add("video");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -295,20 +323,37 @@ var ContextMenuHandler = {
|
||||||
let selection = targetWindow.getSelection();
|
let selection = targetWindow.getSelection();
|
||||||
if (selection && this._tapInSelection(selection, aX, aY)) {
|
if (selection && this._tapInSelection(selection, aX, aY)) {
|
||||||
state.string = targetWindow.getSelection().toString();
|
state.string = targetWindow.getSelection().toString();
|
||||||
state.types.push("copy");
|
uniqueStateTypes.add("copy");
|
||||||
state.types.push("selected-text");
|
uniqueStateTypes.add("selected-text");
|
||||||
|
if (isEditableText) {
|
||||||
|
uniqueStateTypes.add("cut");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Add general content text if this isn't anything specific
|
// Add general content text if this isn't anything specific
|
||||||
if (state.types.indexOf("image") == -1 &&
|
if (!(
|
||||||
state.types.indexOf("media") == -1 &&
|
uniqueStateTypes.has("image") ||
|
||||||
state.types.indexOf("video") == -1 &&
|
uniqueStateTypes.has("media") ||
|
||||||
state.types.indexOf("link") == -1 &&
|
uniqueStateTypes.has("video") ||
|
||||||
state.types.indexOf("input-text") == -1) {
|
uniqueStateTypes.has("link") ||
|
||||||
state.types.push("content-text");
|
uniqueStateTypes.has("input-text")
|
||||||
|
)) {
|
||||||
|
uniqueStateTypes.add("content-text");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Is paste applicable here?
|
||||||
|
if (isEditableText) {
|
||||||
|
let flavors = ["text/unicode"];
|
||||||
|
let cb = Cc["@mozilla.org/widget/clipboard;1"].getService(Ci.nsIClipboard);
|
||||||
|
let hasData = cb.hasDataMatchingFlavors(flavors,
|
||||||
|
flavors.length,
|
||||||
|
Ci.nsIClipboard.kGlobalClipboard);
|
||||||
|
// add paste if there's data
|
||||||
|
if (hasData && !elem.readOnly) {
|
||||||
|
uniqueStateTypes.add("paste");
|
||||||
|
}
|
||||||
|
}
|
||||||
// populate position and event source
|
// populate position and event source
|
||||||
state.xPos = offsetX + aX;
|
state.xPos = offsetX + aX;
|
||||||
state.yPos = offsetY + aY;
|
state.yPos = offsetY + aY;
|
||||||
|
@ -316,8 +361,9 @@ var ContextMenuHandler = {
|
||||||
|
|
||||||
for (let i = 0; i < this._types.length; i++)
|
for (let i = 0; i < this._types.length; i++)
|
||||||
if (this._types[i].handler(state, popupNode))
|
if (this._types[i].handler(state, popupNode))
|
||||||
state.types.push(this._types[i].name);
|
uniqueStateTypes.add(this._types[i].name);
|
||||||
|
|
||||||
|
state.types = [type for (type of uniqueStateTypes)];
|
||||||
this._previousState = state;
|
this._previousState = state;
|
||||||
|
|
||||||
sendAsyncMessage("Content:ContextMenu", state);
|
sendAsyncMessage("Content:ContextMenu", state);
|
||||||
|
|
|
@ -109,3 +109,24 @@
|
||||||
<!ENTITY optionsFlyout.key "o">
|
<!ENTITY optionsFlyout.key "o">
|
||||||
<!ENTITY syncFlyout.key "s">
|
<!ENTITY syncFlyout.key "s">
|
||||||
<!ENTITY aboutFlyout.key "a">
|
<!ENTITY aboutFlyout.key "a">
|
||||||
|
|
||||||
|
<!-- FIRT RUN EXPERIENCE -->
|
||||||
|
<!-- LOCALIZATION NOTE (firstRunTabs.label,
|
||||||
|
firstRunTopSites.label,
|
||||||
|
firstRunBookmarks.label,
|
||||||
|
firstRunMenu.label,
|
||||||
|
firstRunHistory.label )
|
||||||
|
These strings appear on the Firefox Start page the first time
|
||||||
|
Firefox for Windows 8 Touch (Metro) is launched. Each one
|
||||||
|
has an arrow pointing toward the feature it references. The code
|
||||||
|
to display these strings is not enabled yet, but will be soon.
|
||||||
|
For now, you can see this mockup for an example of how they are
|
||||||
|
used: https://bug941284.bugzilla.mozilla.org/attachment.cgi?id=8344046
|
||||||
|
-->
|
||||||
|
<!ENTITY firstRunTabs.label "Looking for your tabs? Just pull down or right-click">
|
||||||
|
<!ENTITY firstRunTopSites.label "Go to the sites you visit most">
|
||||||
|
<!ENTITY firstRunBookmarks.label "Find pages you've saved for later">
|
||||||
|
<!ENTITY firstRunMenu.label "Access more features and options">
|
||||||
|
<!ENTITY firstRunHistory.label "See where you've been on the Web">
|
||||||
|
<!ENTITY firstRunWelcome.label "Welcome to &brandShortName;">
|
||||||
|
<!ENTITY firstRunDifferent.label "Different by design">
|
||||||
|
|
|
@ -714,6 +714,7 @@ documenttab[selected] .documenttab-selection {
|
||||||
/* Contextual toolbar controls */
|
/* Contextual toolbar controls */
|
||||||
|
|
||||||
#toolbar-context-autocomplete,
|
#toolbar-context-autocomplete,
|
||||||
|
.hide-on-start,
|
||||||
#toolbar-context-page {
|
#toolbar-context-page {
|
||||||
transition-property: opacity, visibility;
|
transition-property: opacity, visibility;
|
||||||
transition-duration: @forward_transition_length@;
|
transition-duration: @forward_transition_length@;
|
||||||
|
@ -721,7 +722,7 @@ documenttab[selected] .documenttab-selection {
|
||||||
}
|
}
|
||||||
|
|
||||||
#toolbar-contextual:not([autocomplete]) #toolbar-context-autocomplete,
|
#toolbar-contextual:not([autocomplete]) #toolbar-context-autocomplete,
|
||||||
#toolbar-contextual[startpage] #toolbar-context-page,
|
#toolbar-contextual[startpage] .hide-on-start,
|
||||||
#toolbar-contextual[autocomplete] #toolbar-context-page {
|
#toolbar-contextual[autocomplete] #toolbar-context-page {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 695 B |
|
@ -156,6 +156,7 @@ browser.jar:
|
||||||
skin/classic/browser/devtools/command-responsivemode.png (devtools/command-responsivemode.png)
|
skin/classic/browser/devtools/command-responsivemode.png (devtools/command-responsivemode.png)
|
||||||
skin/classic/browser/devtools/command-scratchpad.png (devtools/command-scratchpad.png)
|
skin/classic/browser/devtools/command-scratchpad.png (devtools/command-scratchpad.png)
|
||||||
skin/classic/browser/devtools/command-tilt.png (devtools/command-tilt.png)
|
skin/classic/browser/devtools/command-tilt.png (devtools/command-tilt.png)
|
||||||
|
skin/classic/browser/devtools/command-console.png (devtools/command-console.png)
|
||||||
skin/classic/browser/devtools/alerticon-warning.png (devtools/alerticon-warning.png)
|
skin/classic/browser/devtools/alerticon-warning.png (devtools/alerticon-warning.png)
|
||||||
skin/classic/browser/devtools/ruleview.css (devtools/ruleview.css)
|
skin/classic/browser/devtools/ruleview.css (devtools/ruleview.css)
|
||||||
* skin/classic/browser/devtools/webconsole.css (devtools/webconsole.css)
|
* skin/classic/browser/devtools/webconsole.css (devtools/webconsole.css)
|
||||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 695 B |
|
@ -258,6 +258,7 @@ browser.jar:
|
||||||
skin/classic/browser/devtools/command-responsivemode.png (devtools/command-responsivemode.png)
|
skin/classic/browser/devtools/command-responsivemode.png (devtools/command-responsivemode.png)
|
||||||
skin/classic/browser/devtools/command-scratchpad.png (devtools/command-scratchpad.png)
|
skin/classic/browser/devtools/command-scratchpad.png (devtools/command-scratchpad.png)
|
||||||
skin/classic/browser/devtools/command-tilt.png (devtools/command-tilt.png)
|
skin/classic/browser/devtools/command-tilt.png (devtools/command-tilt.png)
|
||||||
|
skin/classic/browser/devtools/command-console.png (devtools/command-console.png)
|
||||||
skin/classic/browser/devtools/alerticon-warning.png (devtools/alerticon-warning.png)
|
skin/classic/browser/devtools/alerticon-warning.png (devtools/alerticon-warning.png)
|
||||||
skin/classic/browser/devtools/ruleview.css (devtools/ruleview.css)
|
skin/classic/browser/devtools/ruleview.css (devtools/ruleview.css)
|
||||||
skin/classic/browser/devtools/commandline.css (devtools/commandline.css)
|
skin/classic/browser/devtools/commandline.css (devtools/commandline.css)
|
||||||
|
|
|
@ -441,6 +441,23 @@
|
||||||
-moz-image-region: rect(0px, 48px, 16px, 32px);
|
-moz-image-region: rect(0px, 48px, 16px, 32px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#command-button-splitconsole {
|
||||||
|
list-style-image: url("chrome://browser/skin/devtools/command-console.png");
|
||||||
|
-moz-image-region: rect(0px, 16px, 16px, 0px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#command-button-splitconsole:hover {
|
||||||
|
-moz-image-region: rect(0px, 32px, 16px, 16px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#command-button-splitconsole:hover:active {
|
||||||
|
-moz-image-region: rect(0px, 48px, 16px, 32px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#command-button-splitconsole[checked=true] {
|
||||||
|
-moz-image-region: rect(0px, 64px, 16px, 48px);
|
||||||
|
}
|
||||||
|
|
||||||
/* Tabs */
|
/* Tabs */
|
||||||
|
|
||||||
.devtools-tabbar {
|
.devtools-tabbar {
|
||||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 695 B |
|
@ -186,6 +186,7 @@ browser.jar:
|
||||||
skin/classic/browser/devtools/command-responsivemode.png (devtools/command-responsivemode.png)
|
skin/classic/browser/devtools/command-responsivemode.png (devtools/command-responsivemode.png)
|
||||||
skin/classic/browser/devtools/command-scratchpad.png (devtools/command-scratchpad.png)
|
skin/classic/browser/devtools/command-scratchpad.png (devtools/command-scratchpad.png)
|
||||||
skin/classic/browser/devtools/command-tilt.png (devtools/command-tilt.png)
|
skin/classic/browser/devtools/command-tilt.png (devtools/command-tilt.png)
|
||||||
|
skin/classic/browser/devtools/command-console.png (devtools/command-console.png)
|
||||||
skin/classic/browser/devtools/markup-view.css (../shared/devtools/markup-view.css)
|
skin/classic/browser/devtools/markup-view.css (../shared/devtools/markup-view.css)
|
||||||
skin/classic/browser/devtools/editor-error.png (devtools/editor-error.png)
|
skin/classic/browser/devtools/editor-error.png (devtools/editor-error.png)
|
||||||
skin/classic/browser/devtools/editor-breakpoint.png (devtools/editor-breakpoint.png)
|
skin/classic/browser/devtools/editor-breakpoint.png (devtools/editor-breakpoint.png)
|
||||||
|
@ -487,6 +488,7 @@ browser.jar:
|
||||||
skin/classic/aero/browser/devtools/command-responsivemode.png (devtools/command-responsivemode.png)
|
skin/classic/aero/browser/devtools/command-responsivemode.png (devtools/command-responsivemode.png)
|
||||||
skin/classic/aero/browser/devtools/command-scratchpad.png (devtools/command-scratchpad.png)
|
skin/classic/aero/browser/devtools/command-scratchpad.png (devtools/command-scratchpad.png)
|
||||||
skin/classic/aero/browser/devtools/command-tilt.png (devtools/command-tilt.png)
|
skin/classic/aero/browser/devtools/command-tilt.png (devtools/command-tilt.png)
|
||||||
|
skin/classic/aero/browser/devtools/command-console.png (devtools/command-console.png)
|
||||||
skin/classic/aero/browser/devtools/alerticon-warning.png (devtools/alerticon-warning.png)
|
skin/classic/aero/browser/devtools/alerticon-warning.png (devtools/alerticon-warning.png)
|
||||||
skin/classic/aero/browser/devtools/ruleview.css (devtools/ruleview.css)
|
skin/classic/aero/browser/devtools/ruleview.css (devtools/ruleview.css)
|
||||||
skin/classic/aero/browser/devtools/commandline.css (devtools/commandline.css)
|
skin/classic/aero/browser/devtools/commandline.css (devtools/commandline.css)
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
package org.mozilla.gecko;
|
package org.mozilla.gecko.tests;
|
||||||
|
|
||||||
public class TestConstants {
|
public class TestConstants {
|
||||||
public static final String ANDROID_PACKAGE_NAME = "@ANDROID_PACKAGE_NAME@";
|
public static final String ANDROID_PACKAGE_NAME = "@ANDROID_PACKAGE_NAME@";
|
||||||
|
|
|
@ -12,7 +12,6 @@ import org.mozilla.gecko.FennecMochitestAssert;
|
||||||
import org.mozilla.gecko.FennecNativeActions;
|
import org.mozilla.gecko.FennecNativeActions;
|
||||||
import org.mozilla.gecko.FennecNativeDriver;
|
import org.mozilla.gecko.FennecNativeDriver;
|
||||||
import org.mozilla.gecko.FennecTalosAssert;
|
import org.mozilla.gecko.FennecTalosAssert;
|
||||||
import org.mozilla.gecko.TestConstants;
|
|
||||||
import org.mozilla.gecko.tests.components.*;
|
import org.mozilla.gecko.tests.components.*;
|
||||||
import org.mozilla.gecko.tests.helpers.*;
|
import org.mozilla.gecko.tests.helpers.*;
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ public class AboutHomeComponent extends BaseComponent {
|
||||||
(expectedPageIndex >= 0) ? expectedPageIndex : Page.values().length - 1;
|
(expectedPageIndex >= 0) ? expectedPageIndex : Page.values().length - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals("The current HomePager page is " + Page.values()[expectedPageIndex],
|
assertEquals("The current HomePager page is " + expectedPage,
|
||||||
expectedPageIndex, getHomePagerView().getCurrentItem());
|
expectedPageIndex, getHomePagerView().getCurrentItem());
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6631,7 +6631,27 @@ var SearchEngines = {
|
||||||
|
|
||||||
let filter = {
|
let filter = {
|
||||||
matches: function (aElement) {
|
matches: function (aElement) {
|
||||||
return (aElement.form && NativeWindow.contextmenus.textContext.matches(aElement));
|
// Copied from body of isTargetAKeywordField function in nsContextMenu.js
|
||||||
|
if(!(aElement instanceof HTMLInputElement))
|
||||||
|
return false;
|
||||||
|
let form = aElement.form;
|
||||||
|
if (!form || aElement.type == "password")
|
||||||
|
return false;
|
||||||
|
|
||||||
|
let method = form.method.toUpperCase();
|
||||||
|
|
||||||
|
// These are the following types of forms we can create keywords for:
|
||||||
|
//
|
||||||
|
// method encoding type can create keyword
|
||||||
|
// GET * YES
|
||||||
|
// * YES
|
||||||
|
// POST * YES
|
||||||
|
// POST application/x-www-form-urlencoded YES
|
||||||
|
// POST text/plain NO ( a little tricky to do)
|
||||||
|
// POST multipart/form-data NO
|
||||||
|
// POST everything else YES
|
||||||
|
return (method == "GET" || method == "") ||
|
||||||
|
(form.enctype != "text/plain") && (form.enctype != "multipart/form-data");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
SelectionHandler.actions.SEARCH_ADD = {
|
SelectionHandler.actions.SEARCH_ADD = {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче