Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,7 @@
capIsNewExceptions: [
'QueryInterface', 'ConvertToUnicode', 'ConvertFromUnicode'
]
}],
'one-var': 0,
indent: 0
}]
}
}
},
Expand Down
29 changes: 29 additions & 0 deletions test/manual/expand_test_patch.js
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,35 @@
assert(JSON.stringify(arr.cutIn(1, ...['b', 'd'])), '["a","b","d","c"]');
}

assert(Function.execute(), null);
assert(Function.execute(function () {}), void 0);
assert(Function.execute(function () { return this; }, Array), Array);
assert(Function.execute(a => a, null, 0), 0);
assert(Function.execute(function () { return this instanceof Boolean; }, false));
assert(Function.execute('toString', false), 'false');
assert(Function.execute(function (target) { return this.isArray(target); }, Array, [[]]), true);
assert(Function.execute(function (target) { return this.isArray(target); }, Array, []), false);
assert(Function.execute(function (num1, num2) { return num1 + num2; }, null, [1, 2]), 3);
assert(Function.execute(Object.keys, Object, {hoge : 0})[0], 'hoge');
assert(Function.execute('keys', Object, {hoge : 0})[0], 'hoge');
assert(Function.execute(void 0, Object, {hoge : 0}), null);
assert(Function.execute(void 0, Object), null);
assert(Function.execute('hoge', {hoge : arg => arg}, 0), 0);
assert(Function.execute('hoge', {}, 0), null);
assert(Function.execute('hoge', null, 0), null);
assert(Function.execute('hoge'), null);

assert((function () {}).async(), void 0);
assert((function () {}).async(void 0), void 0);
assert((function () {}).async(null), void 0);
assert((function () {}).async({}), void 0);
assert((function () {}).async(null, 'hoge'), void 0);
assert((function () {}).async({}, 'hoge'), void 0);
assert((function () {}).async(null, ['hoge', 'fuga']), void 0);
assert((function () {}).async({}, ['hoge', 'fuga']), void 0);
assert((function () {}).async({}, [['hoge', 'fuga']]), void 0);
assert((function () { return this instanceof Boolean; }).async(false), void 0);

assert(JSON.parseable(void 0), false);
assert(JSON.parseable(''), false);
assert(JSON.parseable(NaN), false);
Expand Down
25 changes: 20 additions & 5 deletions xpi/chrome/content/changeAccount/changeAccount.css
Original file line number Diff line number Diff line change
@@ -1,14 +1,29 @@
.services > radio,
.accounts > listitem,
dialog {
padding-top: 10px;
padding-right: 10px;
padding-bottom: 10px;
padding-left: 10px;
}

.main,
.left-box,
.right-box,
.accounts {
-moz-box-flex: 1;
}

.services,
.account,
.login-button:not([disabled]) {
cursor: pointer;
}

.right-box {
margin-left: 0.7em;
.services .menulist-icon {
width: 16px;
height: 16px;
}

.accounts > listitem {
.account {
padding-top: 0.5em;
padding-right: 0.2em;
padding-bottom: 0.5em;
Expand Down
98 changes: 61 additions & 37 deletions xpi/chrome/content/changeAccount/changeAccount.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,73 +4,88 @@
'use strict';

let env = Components.classes[
'@tombfix.github.io/tombfix-service;1'
].getService().wrappedJSObject,
{Models} = env,
services = doc.querySelector('.services');

for (let model of Models.values) {
if (
model.login && model.getCurrentUser &&
model.getPasswords && model.getPasswords().length
) {
let modelName = model.name;
'@tombfix.github.io/tombfix-service;1'
].getService().wrappedJSObject;
let {Models} = env;

function getAccountInfoList(model) {
let infoList;

services.appendItem(modelName, modelName).setAttribute('src', model.ICON);
if (model.getPasswords) {
infoList = model.getPasswords();
}

return Array.isArray(infoList) ? infoList : [];
}

if (!services.childElementCount) {
let targets = Models.values.filter(model =>
model.login && model.getCurrentUser && getAccountInfoList(model).length
);

if (!targets.length) {
doc.querySelector('.left-box').hidden = true;

win.addEventListener('load', () => {
// load時は、まだダイアログが表示されていない
setTimeout(() => {
win.alert(env.getMessage('message.changeAccount.infoNotFound'));
}, 0);
env.showMessage.async(env, ['message.changeAccount.infoNotFound', win]);
});

return;
}

let loginButton = doc.querySelector('.login-button'),
accounts = doc.querySelector('.accounts');
let services = doc.querySelector('.services');
let loginButton = doc.querySelector('.login-button');
let accounts = doc.querySelector('.accounts');

function createAccountList(accountInfoList, currentUserList) {
for (let {user, password} of accountInfoList) {
let account = accounts.appendItem(user, password);

account.classList.add('listitem-iconic', 'account');

if (currentUserList.some(currentUser =>
currentUser && currentUser === user
)) {
account.image = 'chrome://tombfix/skin/tick.png';
account.disabled = true;
} else {
account.image = 'chrome://tombfix/skin/empty.png';

if (!accounts.selectedItem) {
accounts.selectedItem = account;
}
}
}
}

services.addEventListener('select', () => {
loginButton.disabled = true;

let model = Models[services.value];

model.getCurrentUser().addBoth(result => {
model.getCurrentUser().addErrback(() => []).addCallback(list => {
if (model.name !== services.value) {
return;
}

env.clearChildren(accounts);

let currentUser = typeof result === 'string' ? result : '';

for (let {user, password} of model.getPasswords()) {
let account = accounts.appendItem(user, password);

account.classList.add('listitem-iconic');

if (currentUser && currentUser === user) {
account.image = 'chrome://tombfix/skin/tick.png';
account.disabled = true;

accounts.selectedItem = account;
} else {
account.image = 'chrome://tombfix/skin/empty.png';
}
}
// 「アカウントの切り替え」を開いて2回目以降にアカウントリストの表示がおかしくなるのを防ぐ
createAccountList.async(null, [
getAccountInfoList(model),
Array.wrap(list)
]);
});
});

accounts.addEventListener('select', () => {
let account = accounts.selectedItem;

if (account) {
loginButton.disabled = account.disabled;
if (!account) {
return;
}

loginButton.disabled = account.disabled;
});

win.addEventListener('dialogaccept', () => {
Expand All @@ -80,6 +95,15 @@
});

win.addEventListener('load', () => {
// load後でないとアイコンが表示されない
for (let model of targets) {
let modelName = model.name;
let menuitem = services.appendItem(modelName, modelName);

menuitem.classList.add('menuitem-iconic');
menuitem.image = model.ICON;
}

services.selectedIndex = 0;
});
}(window, document));
25 changes: 16 additions & 9 deletions xpi/chrome/content/changeAccount/changeAccount.xul
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,26 @@
<?xml-stylesheet type="text/css" href="chrome://global/skin/"?>
<?xml-stylesheet type="text/css" href="changeAccount.css"?>
<!DOCTYPE dialog SYSTEM "chrome://tombfix/locale/tombfix.dtd">
<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="&label.action.changeAccount;"
<dialog
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="&title.changeAccount;"
buttons="accept">
<hbox flex="1">
<radiogroup class="services"></radiogroup>
<vbox class="right-box" flex="1">
<listbox class="accounts" flex="1"></listbox>
<button class="login-button"
label="Login"
<hbox class="main">
<vbox class="left-box">
<menulist class="services"/>
</vbox>
<vbox class="right-box">
<listbox class="accounts"/>
<button
class="login-button"
label="&label.changeAccount.login;"
image="chrome://tombfix/skin/accept.png"
disabled="true"
dlgtype="accept"/>
</vbox>
</hbox>
<script type="application/javascript" src="changeAccount.js"></script>
<script
type="application/javascript"
src="chrome://tombfix/content/library/expand.js"/>
<script type="application/javascript" src="changeAccount.js"/>
</dialog>
26 changes: 26 additions & 0 deletions xpi/chrome/content/library/expand.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,32 @@
}
});

Object.expand(Function, {
execute(target, obj, arr) {
let func = target;
let funcThis = obj == null ? null : obj;
let funcArgs = Array.wrap(arr);

if (typeof func === 'string' && funcThis !== null) {
func = funcThis[func];
}

if (typeof func === 'function') {
return func.call(funcThis, ...funcArgs);
}

return null;
}
});

Object.expand(Function.prototype, {
async(obj, arr) {
setTimeout(() => {
this.call(obj == null ? null : obj, ...Array.wrap(arr));
}, 0);
}
});

Object.expand(JSON, {
parseable(target) {
try {
Expand Down
6 changes: 6 additions & 0 deletions xpi/chrome/content/library/utility.js
Original file line number Diff line number Diff line change
Expand Up @@ -2590,3 +2590,9 @@ function getFlavoredString(target) {
flavors : {html}
}) : '';
}

function showMessage(val, target) {
(target || this).alert((
Array.isArray(val) ? getMessage(...val) : getMessage(val)
) || val);
}
3 changes: 2 additions & 1 deletion xpi/chrome/locale/en-US/tombfix.dtd
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,5 @@
<!ENTITY label.browse "Browse...">

<!-- Change Account -->
<!ENTITY label.action.changeAccount "Change Account">
<!ENTITY title.changeAccount "Change Account">
<!ENTITY label.changeAccount.login "Login">
3 changes: 2 additions & 1 deletion xpi/chrome/locale/ja-JP/tombfix.dtd
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,5 @@
<!ENTITY label.browse "参照...">

<!-- Change Account -->
<!ENTITY label.action.changeAccount "アカウントの切り替え">
<!ENTITY title.changeAccount "アカウントの切り替え">
<!ENTITY label.changeAccount.login "ログイン">