6 posts tagged “greasemonkey”
I updated Vox Editing with WYSIWYG or HTML alternately userscript. Now, this script just insert a button to toolbar of the composing view to run the command which is already defined in Vox JS.
Ref. Editing with WYSIWYG or HTML alternately.
Updated: Added to userscripts.org http://userscripts.org/scripts/show/17963. I'm lazy to update scripts on userscripts.org... I hope that userscripts.org updates from subversion automatically or by one-click. (updated: wrote a script...)
I wrote a greasemonkey script for using hatena notation at composing. Maybe this is no use.
Issues:
- pre kihou (>|| .. ||<) will be broken because Vox indents all elements.
- The original text is saved as hidden p element. This is so ugly implement. But it seems like Vox strips all comments (I first implemented with comment (<!-- -->). So I have no idea without it...
voxeditingwithtexthatena.user.js
Uses text-hatena.js for parsing. Using Markdown syntax may be easy, bacause it has javascript implementation.
Uh, I will not use this.
Vox ではてな記法を使う Greasemonkey スクリプトを書いてみました。全然使えませんが。
- pre 記法は Vox がインデントを行うため崩れます。
- オリジナルのテキストを display: none な p 要素に base64 して突っ込むため美しくないです。もともとコメントとして挿入する実装にしようと思って試したのですが、保存されなかったのでこうなってます。何かいい方法ないかな。
おれはつかわない!
Update:
This script is now committed in CodeRepos: http://coderepos.org/share/browser/lang/javascript/userscripts/voxeditingwithwysiwygorh.user.js
I wrote a greasemonkey script for editting HTML directly on Vox composing view.
I'm sometimes not able to edit with WYSIWYG smartly. In a case like that, I want to edit HTML directly.
// ==UserScript==
// @name Vox Editing with WYSIWYG or HTML alternately
// @namespace http://lowreal.net/
// @include http://www.vox.com/compose*
// ==/UserScript==
(function () {
var iframe = $X('//iframe[contains(@src, "editor-content.html")]')[0];
var textarea = $N('textarea', {
cols:'30',
rows:'10',
style: <>
width : {iframe.offsetWidth + 'px'};
height : {iframe.offsetHeight + 'px'};
display : none;
background : #eee;
z-index : 500;
</>.replace(/\n/g, ''),
}, 'test');
iframe.parentNode.insertBefore(textarea, iframe);
var toggle = $N('div', {
style: <>
width: 3em;
text-align: center;
margin: 0.5em 0 -0.5em 0;
padding: 0 0.5em;
background: #000;
color: #fff;
z-index: 999;
</>.replace(/\n/g, '')
}, 'Toggle');
toggle.addEventListener('click', function (e) {
if (iframe.style.display == 'none') {
iframe.style.display = 'block';
textarea.style.display = 'none';
iframe.contentDocument.body.innerHTML = textarea.value;
} else {
iframe.style.display = 'none';
textarea.style.display = 'block';
textarea.value = iframe.contentDocument.body.innerHTML;
}
}, false);
var area = document.getElementById('compose-entry');
area.parentNode.insertBefore(toggle, area);
/* template functions */
function log () {
var c = unsafeWindow.console;
if (c) c.log.apply(c, arguments);
}
function $N(name, attr, childs) {
var ret = document.createElement(name);
for (k in attr) {
if (!attr.hasOwnProperty(k)) continue;
v = attr[k];
if (k == "class") {
ret.className = v;
} else {
ret.setAttribute(k, v);
}
}
switch (typeof childs) {
case "string": {
ret.appendChild(document.createTextNode(childs));
break;
}
case "object": {
for (var i = 0, len = childs.length; i < len; i++) {
var child = childs[i];
if (typeof child == "string") {
ret.appendChild(document.createTextNode(child));
} else {
ret.appendChild(child);
}
}
break;
}
}
return ret;
}
function $X(exp, context) {
if (!context) context = document;
var resolver = function (prefix) {
var o = document.createNSResolver(context)(prefix);
return o ? o : (document.contentType == "text/html") ? "" : "http://www.w3.org/1999/xhtml";
}
var exp = document.createExpression(exp, resolver);
var result = exp.evaluate(context, XPathResult.ANY_TYPE, null);
switch (result.resultType) {
case XPathResult.STRING_TYPE : return result.stringValue;
case XPathResult.NUMBER_TYPE : return result.numberValue;
case XPathResult.BOOLEAN_TYPE: return result.booleanValue;
case XPathResult.UNORDERED_NODE_ITERATOR_TYPE: {
result = exp.evaluate(context, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
var ret = [];
for (var i = 0, len = result.snapshotLength; i < len ; i++) {
ret.push(result.snapshotItem(i));
}
return ret;
}
}
return null;
}
})();
を作ろうと思ったのだけど、greasemonkey スクリプト内に text-hatena.js をコピペしたところ Compose 画面で Fx が瞬間で落ちるようになってしまったので断念した。いろいろ考えられる理由がありすぎて原因を追うのが面倒くさい。毎回再起動しないといけない。
でもってそれは諦めて、常に iframe 内の innerHTML をいぢれるように textarea を配置してみたのだけど、iframe の上に textarea をおくとキャレットが表示されなくなってしまって使えない (OS X, Fx2.0)。回避法を模索中
それと、pre でソースコード挿入するとき、シンタックスハイライトをしようと思って昔作ったやつをひっぱりだしたけど、UI 実装するのが面倒くさくてまだやっていない。Vox の JS は圧縮されて読みにくいので自己実装したほうがはやいのだけど、それだと UI がちょっと変わってキモイのでどうしようとかいう悩み。
頭使わないで書くというアレが崩れそうなので深入りしないようにしよう。
After reading 【Vox使い方講座】アカウント設定で世界旅行!, you may want to change the language setting more easily.
I wrote a greasemonkey script for changing the setting on one click.
// ==UserScript==
// @name Vox Change Lang on one click
// @namespace http://lowreal.net/
// @include http://*.vox.com/*
// @exclude http://*.vox.com/*editor-content.html
// ==/UserScript==
(function () {
const SHOW_LANGS = [
'en',
'fr',
'ja',
];
var area = $N('div', {
style: [
'position: absolute',
'top: 0',
'right: 0',
'background: #000',
'color: #fff',
'padding: 0.2em 1em',
'font-size: 14px',
].join(';')
});
SHOW_LANGS.forEach(function (l) {
var ll = $N('a', {
href:'javascript:void("fumino")',
style: 'color: #fff',
}, l);
ll.addEventListener('click', function (e) {
set_lang(l);
}, false);
area.appendChild(ll);
area.appendChild(document.createTextNode(' '));
});
document.body.appendChild(area);
function params2data(params) {
var data = [];
for (name in params) {
if (!params.hasOwnProperty(name)) continue;
if (!name) continue;
params[name].forEach(function (i) {
data.push(name+'='+encodeURIComponent(i));
});
}
log(data);
data = data.join('&');
return data;
}
function set_lang(lang) {
log('set lang to ' + lang);
GM_xmlhttpRequest({
method: "GET",
url: 'http://www.vox.com/account/info',
onload: function (req) {
var t = $N('div');
t.innerHTML = req.responseText;
var params = {};
['input', 'select', 'textarea'].forEach(function (i) {
$X('.//form[@id="account-info"]//'+i, t).forEach(function (i) {
var name = i.name;
var value = i.value;
if (!params[name]) params[name] = [];
params[name].push(value);
});
});
params['locale'] = [lang];
delete params['cancel'];
log('%.o', params);
var data = params2data(params);
GM_xmlhttpRequest({
method: "POST",
url: 'http://www.vox.com/account/info',
headers : {
"Content-Type":"application/x-www-form-urlencoded"
},
data: data,
onload: function (req) {
location.reload();
}
});
}
});
}
/* template functions */
function log () {
var c = unsafeWindow.console;
if (c) c.log.apply(c, arguments);
}
function $N(name, attr, childs) {
var ret = document.createElement(name);
for (k in attr) {
if (!attr.hasOwnProperty(k)) continue;
v = attr[k];
if (k == "class") {
ret.className = v;
} else {
ret.setAttribute(k, v);
}
}
switch (typeof childs) {
case "string": {
ret.appendChild(document.createTextNode(childs));
break;
}
case "object": {
for (var i = 0, len = childs.length; i < len; i++) {
var child = childs[i];
if (typeof child == "string") {
ret.appendChild(document.createTextNode(child));
} else {
ret.appendChild(child);
}
}
break;
}
}
return ret;
}
function $X(exp, context) {
if (!context) context = document;
var resolver = function (prefix) {
var o = document.createNSResolver(context)(prefix);
return o ? o : (document.contentType == "text/html") ? "" : "http://www.w3.org/1999/xhtml";
}
var exp = document.createExpression(exp, resolver);
var result = exp.evaluate(context, XPathResult.ANY_TYPE, null);
switch (result.resultType) {
case XPathResult.STRING_TYPE : return result.stringValue;
case XPathResult.NUMBER_TYPE : return result.numberValue;
case XPathResult.BOOLEAN_TYPE: return result.booleanValue;
case XPathResult.UNORDERED_NODE_ITERATOR_TYPE: {
result = exp.evaluate(context, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
var ret = [];
for (var i = 0, len = result.snapshotLength; i < len ; i++) {
ret.push(result.snapshotItem(i));
}
return ret;
}
}
return null;
}
})();
This shows language links on right-top of your window. (after clicked the link, wait for reloading)
// ==UserScript==
// @name Vox Add Toolbar Functions
// @namespace http://lowreal.net/
// @include http://www.vox.com/compose*
// ==/UserScript==
(function () {
var toolbar = document.getElementById('compose-toolbar');
var pre_button = $N('a', {
'class':'toolbar button',
'style':<>
background: url('http://aka-static.vox.com/.shared:v19.9:vox:ja/images/buttons/toolbar/toolbar.gif') no-repeat -220px 0;
width: 22px;
height: 22px;
</>.replace(/\n/, ""),
'title':'preformatted text',
}, 'pre');
toolbar.insertBefore(pre_button, document.getElementById('restore-post'));
var iframe = $X('//iframe[contains(@src, "editor-content.html")]')[0];
iframe.addEventListener('load', function (e) {
var head = iframe.contentDocument.getElementsByTagName('head')[0];
head.appendChild($N('style', {type:'text/css'}, <><![CDATA[
pre {
border: 1px solid #ccc;
padding: 1em;
margin: 0 1em;
}
]]></>.toString()));
}, false);
pre_button.addEventListener('click', function (e) {
iframe.contentDocument.body.appendChild(
$N('pre', {}, 'Insert preformatted text here!')
);
iframe.contentDocument.body.appendChild($N('br'));
}, false);
/* template functions */
function log () {
var c = unsafeWindow.console;
if (c) c.log.apply(c, arguments);
}
function $N(name, attr, childs) {
var ret = document.createElement(name);
for (k in attr) {
if (!attr.hasOwnProperty(k)) continue;
v = attr[k];
if (k == "class") {
ret.className = v;
} else {
ret.setAttribute(k, v);
}
}
switch (typeof childs) {
case "string": {
ret.appendChild(document.createTextNode(childs));
break;
}
case "object": {
for (var i = 0, len = childs.length; i < len; i++) {
var child = childs[i];
if (typeof child == "string") {
ret.appendChild(document.createTextNode(child));
} else {
ret.appendChild(child);
}
}
break;
}
}
return ret;
}
function $X(exp, context) {
if (!context) context = document;
var resolver = function (prefix) {
var o = document.createNSResolver(context)(prefix);
return o ? o : (document.contentType == "text/html") ? "" : "http://www.w3.org/1999/xhtml";
}
var exp = document.createExpression(exp, resolver);
var result = exp.evaluate(context, XPathResult.ANY_TYPE, null);
switch (result.resultType) {
case XPathResult.STRING_TYPE : return result.stringValue;
case XPathResult.NUMBER_TYPE : return result.numberValue;
case XPathResult.BOOLEAN_TYPE: return result.booleanValue;
case XPathResult.UNORDERED_NODE_ITERATOR_TYPE: {
result = exp.evaluate(context, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
var ret = [];
for (var i = 0, len = result.snapshotLength; i < len ; i++) {
ret.push(result.snapshotItem(i));
}
return ret;
}
}
return null;
}
})();
- Using E4X just for here document.
- Using XPath with wraped function named $X
I want to insert the element to cursor point.
Tomorrow, I must wake up early. I lie by now. 意味わからん.
PS
br が入力されてしまう。どうすればいいかなぁ。