Skip to content

Instantly share code, notes, and snippets.

@Milly
Last active September 3, 2015 17:45
Show Gist options
  • Save Milly/186367 to your computer and use it in GitHub Desktop.
Save Milly/186367 to your computer and use it in GitHub Desktop.
pixiv to dynamic greasemonkey script
// ==UserScript==
// @name pixiv ajaxer
// @namespace http://d.hatena.ne.jp/MillyC/
// @include http://www.pixiv.net/*
// @grant GM_addStyle
// @grant GM_xmlhttpRequest
// @author Milly
// @version 1.0.20130315
// ==/UserScript==
var pixivAjaxer = {
defs : [
// add illust bookmark
{
href : /\bbookmark_add\.php\?.*\btype=illust\b/,
listener : function(target) {
GM_xmlhttpRequest({
method : 'GET',
url : target.href,
onload : function(r) {
var html = r.responseText;
var form = pixivAjaxer.parseHtml(html, '//form[@action="bookmark_add.php"]');
if (!form) return;
pixivAjaxer.loadStylesInHtml(html);
var win = pixivAjaxer.openWindow('bookmark_add', 'ブックマークに追加', form, 'tag');
pixivAjaxer.loadScriptsInHtml(html);
pixivAjaxer.dispatchPage('bookmark_add');
pixivAjaxer.dispatchPage('*/bookmark_add');
pixivAjaxer.hookFormSubmit({
form : form,
onsubmit : function() { win.close(); },
onload : function(r) {
var html = r.responseText;
var content = pixivAjaxer.parseHtml(html, '//div[@id="content3"]/div[contains(@style,"border")]');
if (!content) return;
content.style.width = '';
var win = pixivAjaxer.openWindow('bookmark_add', 'ブックマークに追加', content);
}
});
}
});
}
}
],
init : function() {
window.addEventListener('click', pixivAjaxer.captureClick, true);
},
captureClick : function(event) {
if (event.ctrlKey || event.altKey) return;
var link = pixivAjaxer.evaluateFirst('ancestor-or-self::a', event.target);
if (!link) return;
var href = link.getAttribute('href');
if (!href) return;
for each (var def in pixivAjaxer.defs) {
if (href.match(def.href)) {
event.preventDefault();
event.stopPropagation();
def.listener(link);
break;
}
}
},
initStyle : function() {
pixivAjaxer.initStyle = function() {};
GM_addStyle([
'.pixivajaxer-window {',
'position: absolute;',
'background: white;',
'border: 1px solid #88a;',
'padding: 0;',
'z-index: 11000000;',
'}',
'.pixivajaxer-window > h2 {',
'text-align: center;',
'line-height: 1.5em;',
'font-weight: bold;',
'}',
'.pixivajaxer-window > a {',
'position: absolute;',
'top: 0;',
'right: 0;',
'width: 1.5em;',
'height: 1.5em;',
'line-height: 1.5em;',
'border-left: 1px solid #88a;',
'border-bottom: 1px solid #88a;',
'-moz-border-radius-bottomleft: 10px;',
'background-color: #88a;',
'color: #fff;',
'text-align: center;',
'font-weight: bold;',
'cursor: pointer;',
'}',
'.pixivajaxer-window > a:before {',
'content: "\xd7";',
'}',
'.pixivajaxer-window > a:hover {',
'text-decoration: none;',
'}',
'.pixivajaxer-window > p {',
'padding: 8px;',
'}'
].join('\n'));
},
checkEvent : function(event) {
if (event.ctrlKey || event.altKey) return false;
event.preventDefault();
event.stopPropagation();
return true;
},
parseHtml : function(text, xpath) {
var innerBody = (text.match(/<body(?=[\s>])[^>]*>(?:.|\n)*<\/body>/i) || {})[0];
if (innerBody) {
var parent = document.createElement('div');
parent.innerHTML = innerBody.replace(/<(no)?script(?:.|\n)*?<\/\1script>/ig, '');
return pixivAjaxer.evaluateFirst(xpath, parent);
}
return false;
},
evaluateFirst : function (xpath, base) {
return document.evaluate(xpath, base || document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
},
loadScriptsInHtml : function(text) {
var reg = /<script(?=(?:[^>]|\n)*\bsrc="([^"]*)")(?:[^>]|\n)*>(.|\n)*?<\/script>/img;
for (var m; m = reg.exec(text);) {
var src = decodeURI(m[1].replace('&amp;', '&'));
var script = m[2];
if (src) {
pixivAjaxer.loadScript(src);
} else if (false /* disabled */ && script) {
try {
with (unsafeWindow) { eval(script); }
} catch (e) {}
}
}
},
loadStylesInHtml : function(text) {
var reg = /<link(?=(?:[^>]|\n)*\brel="stylesheet")(?=(?:[^>]|\n)*\bhref="([^"]*)")(?:[^>]|\n)*>/img;
for (var m; m = reg.exec(text);) {
var href = decodeURI(m[1].replace('&amp;', '&'));
if (href) {
pixivAjaxer.loadStyle(href);
}
}
},
loadScript : function(src) {
var options = options || {};
var xpath = '//script[@src="' + src + '"]'
if (!pixivAjaxer.evaluateFirst(xpath)) {
var script = document.createElement('script');
script.type = 'text/javascript';
script.charet = 'UTF-8';
script.src = src;
document.getElementsByTagName('head')[0].appendChild(script);
}
},
loadStyle : function(href) {
var xpath = '//link[@href="' + href + '"]'
if (!pixivAjaxer.evaluateFirst(xpath)) {
var link = document.createElement('link');
link.type = 'text/css';
link.rel = 'stylesheet';
link.href = href;
document.getElementsByTagName('head')[0].appendChild(link);
}
},
openWindow : function(id, title, content, focus) {
pixivAjaxer.initStyle();
// title bar
var titleBar = document.createElement('h2');
titleBar.appendChild(document.createTextNode(title));
// close button
var closeButton = document.createElement('a');
closeButton.addEventListener('click', function(e) { e.preventDefault(); win.close(); }, false);
// content area
var contentArea = document.createElement('p');
contentArea.appendChild(content);
// window box
var win = document.createElement('div');
win.setAttribute('id', id);
win.setAttribute('class', 'pixivajaxer-window');
win.addEventListener('keydown', function(e) { if (27 == e.keyCode) { win.close(); } }, true);
win.appendChild(titleBar);
win.appendChild(closeButton);
win.appendChild(contentArea);
// add methods
win.close = function() { document.body.removeChild(win); };
// centering window
var doc = document.documentElement;
win.style.visibility = 'hidden';
document.body.appendChild(win);
win.style.top = Math.round(doc.scrollTop + Math.max(0, (doc.clientHeight - win.offsetHeight) / 2)) + 'px';
win.style.left = Math.round(doc.scrollLeft + Math.max(0, (doc.clientWidth - win.offsetWidth ) / 2)) + 'px';
win.style.visibility = 'visible';
// set focus
var focusElement =
focus && pixivAjaxer.evaluateFirst('.//input[@name="' + focus + '"]', win)
|| pixivAjaxer.evaluateFirst('.//input[not(@type="hidden")]|.//a[@href]', win);
if (focusElement && focusElement.focus)
focusElement.focus();
return win;
},
hookFormSubmit : function(options) {
var form = options.form;
var request = {
method : form.method || 'GET',
url : form.action,
headers : {}
};
// build request
for (var opt in options)
request[opt] = options[opt];
request.method = request.method.toUpperCase();
if ('POST' == request.method)
request.headers['Content-type'] = 'application/x-www-form-urlencoded';
form.addEventListener('submit', function(e) {
e.preventDefault();
e.stopPropagation();
if (request.onsubmit)
request.onsubmit.call(form, e);
// build form data
var data = [];
for (var i = 0; i < form.elements.length; ++i) {
var input = form.elements[i];
if (('radio' == input.type || 'checkbox' == input.type) && !input.checked) continue;
data.push(encodeURI(input.name) + '=' + encodeURI(input.value));
}
request.url = request.url.replace(/\?.*$/, '');
if ('GET' == request.method) {
request.url += '?' + data.join('&');
} else {
request.data = data.join('&');
}
GM_xmlhttpRequest(request);
}, false);
},
dispatchPage : function(name, params) {
var action = unsafeWindow.pixiv.page[name];
if (action) action.call(unsafeWindow, params);
}
};
pixivAjaxer.init();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment