Skip to content

Instantly share code, notes, and snippets.

@khsk
Last active March 2, 2018 04:35
Show Gist options
  • Save khsk/bca459a16e214c4e26c353618249a7bd to your computer and use it in GitHub Desktop.
Save khsk/bca459a16e214c4e26c353618249a7bd to your computer and use it in GitHub Desktop.
Qiitaのフィードのタグアイコンをホバー時ユーザーアイコンに切り替えついでに名前とかをポップアップするユーザースクリプト ref: https://qiita.com/khsk/items/9f806c0a16e12236ec56
{
"articles_count": 114,
"contribution": 656,
"followed": false,
"id": 62354,
"name": "",
"profile_image_url": "https://qiita-image-store.s3.amazonaws.com/0/62354/profile-images/1473695923",
"url_name": "khsk"
}
// ==UserScript==
// @name Qiita show user Icon to feed
// @namespace khsk
// @description フィードの記事アイコンをホバーしたとき、投稿者のアイコンに変更する
// @include http://qiita.com/
// @include https://qiita.com/
// @include http://qiita.com/items
// @include https://qiita.com/items
// @include http://qiita.com/stock
// @include https://qiita.com/stock
// @include http://qiita.com/mine
// @include https://qiita.com/mine
// @version 1
// @grant none
// ==/UserScript==
console.time('hover icon');
const ORIGINAL_CLASS = 'user-icon';
const CUSTOM_CLASS = 'khsk-user-icon'; // IDより面倒だけど、複数作るのでクラスだよ。うっかりIDに書き換えそうになったので。
const getUserName = elm => {
const link = elm.parentNode.parentNode.parentNode.querySelector('div.item-box-title > h1 > a');
return link.href.match(/https?:\/\/qiita.com\/([^/]+)/)[1];
};
const getUserData = (username) => {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://qiita.com/api/internal/hovercard_users/' + username);
xhr.addEventListener('load', e => {
resolve(xhr.responseText);
});
xhr.addEventListener('error', e => {
reject(xhr.responseText);
});
xhr.send();
});
};
const setPopover = (elm, data) => {
// Qiitaのhovercardはhovercard.jsではないのかもで諦め
// 最後に$(elm).tooltip() or popover()を実行するとタイトルがタグになる。謎。なので最初に設定
// datasetでは効かないものがある
$(elm).popover({
trigger : 'hover',
placement : 'top', // フィードは上から下へ見ると思うので
container : 'body',
html : true,
});
elm.dataset.toggle = 'popover';
elm.dataset.originalTitle = 'Author Info';
// hovercardっぽさのためにアイコン画像は不要か…
//elm.dataset.content = '<img src="' + data.profile_image_url + '">' + '<br>\n' + (data.name || data.url_name) + '<br>\n' + data.contribution + ' Contribution';
elm.dataset.content = (data.name || data.url_name) + '<br>\n' + data.contribution + ' Contribution';
elm.dataset.placement = 'top'; // フィードは上から下へ見ると思うので
// 改行対策にデフォルト値 + nowrap
elm.dataset.viewport = "{ selector: 'body', padding: 0 , white-space: nowrap,}";
};
const createUserIcon = elm => {
return (async () => {
const username = getUserName(elm);
const userdata = JSON.parse(await getUserData(username));
const user = elm.cloneNode();
// 識別子
user.className = user.className + ' ' + CUSTOM_CLASS;
user.src = userdata.profile_image_url;
setPopover(user, userdata);
elm.parentNode.insertBefore(user, elm);
return user;
})();
};
const showUser = elm => {
return (async elm => {
// ByClass()[0]とどっちがいいかなあ
let user = elm.parentNode.querySelector('.' + CUSTOM_CLASS);
if (!user) {
user = await createUserIcon(elm);
}
user.style.display = '';
elm.style.display = 'none';
})(elm);
};
const hideUser = user => {
return (async user => {
// たぶんツールチップ表示が邪魔するので隣接セレクタではなく一般兄弟セレクタ(関節セレクタ)で取得する
const tag = user.parentNode.querySelector('.' + CUSTOM_CLASS + ' ~ img');
tag.style.display = '';
user.style.display = 'none';
})(user);
};
// ここ非jQueryでどうするか不明
$(document).on({
'mouseenter': e => {
console.log('mouseenter');
// targetは目的のimgで、currentTargetがa
// targetのクラス名をチェックしないと、マウスでこすると想定外のelmが渡ることがあるので
if (e.target.className.indexOf(ORIGINAL_CLASS) != -1) {
showUser(e.target).catch(e => {
console.log('mouseenter catch : ' + e);
});
}
},
'mouseleave': e => {
console.info('mouseleave');
// 順調ならe.targetが作ったuser imgになるよ
if (e.target.className.indexOf(ORIGINAL_CLASS) != -1) {
hideUser(e.target).catch(e => {
console.log('mouseleave catch : ' + e);
});
}
}
}, '.action-user-icon.action > a'/* imgにイベントを設定すると、非表示時にmouseleaveが起き無限ループするので、親のaにする */);
console.timeEnd('hover icon');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment