Last active
June 13, 2017 01:02
-
-
Save shogo82148/3953476 to your computer and use it in GitHub Desktop.
Togetterの編集作業便利にしたい
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name TogetterHelper | |
// @namespace https://gist.github.com/3883841 | |
// @version 0.2 | |
// @description Togetterの編集作業便利にしたい. | |
// @include http://togetter.com/create | |
// @include http://togetter.com/edit/* | |
// @copyright 2012+, shogo82148 | |
// ==/UserScript== | |
(function() { | |
function $(expression, callback) { | |
var iterator, node; | |
if(callback) { | |
iterator = document.evaluate(expression, document, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null); | |
node = iterator.iterateNext(); | |
while(node) { | |
callback(node); | |
node = iterator.iterateNext(); | |
} | |
} else { | |
return document.evaluate(expression, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; | |
} | |
} | |
function remove(node) { | |
node.parentNode.removeChild(node); | |
return node; | |
} | |
function click(elem) { | |
var e = document.createEvent("MouseEvents"); | |
e.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, | |
false, false, false, 0, null); | |
elem.dispatchEvent(e); | |
} | |
function Item(elem) { | |
this.elem = elem; | |
} | |
Item.prototype.tweet = function() { | |
var tweet = document.evaluate( | |
'.//div[@class="tweet"]', | |
this.elem, null, | |
XPathResult.FIRST_ORDERED_NODE_TYPE, | |
null).singleNodeValue; | |
if(!tweet) return null; | |
return tweet.innerText; | |
}; | |
Item.prototype.id = function() { | |
return this.elem.id; | |
}; | |
Item.prototype.remove = function() { | |
remove(this.elem); | |
}; | |
Item.prototype.selected = function(flag) { | |
var classes = this.elem.className.split(' '); | |
var i, new_classes; | |
if(flag==undefined) { | |
return classes.indexOf('selected_item') > 0; | |
} else { | |
new_classes = []; | |
for(i=0;i<classes.length;i++) { | |
if(classes[i] != 'selected_item') | |
new_classes.push(classes[i]); | |
} | |
if(flag) new_classes.push('selected_item'); | |
this.elem.className = new_classes.join(' '); | |
} | |
}; | |
var ALL_CHOICES = '//*[@id="choices"]/*[contains(@class,"action_item")]'; | |
var ALL_RESULTS = '//*[@id="results"]/*[contains(@class,"action_item")]'; | |
var SELECTED_CHOICES = '//*[@id="choices"]/*[contains(@class,"action_item") and contains(@class,"selected_item")]'; | |
var SELECTED_RESULTS = '//*[@id="results"]/*[contains(@class,"action_item") and contains(@class,"selected_item")]'; | |
function getAllChices() { | |
var items = []; | |
$(ALL_CHOICES, function(elem) { | |
items.push(new Item(elem)); | |
}); | |
return items; | |
} | |
function getAllResults() { | |
var items = []; | |
$(ALL_RESULTS, function(elem) { | |
items.push(new Item(elem)); | |
}); | |
return items; | |
} | |
// リストの選択イベントを上書き | |
(function() { | |
var results = document.getElementById('results'); | |
var choices = document.getElementById('choices'); | |
bind(results, getAllResults); | |
bind(choices, getAllChices); | |
function bind(target, getAll) { | |
var last_click = null; | |
target.addEventListener('click', function(e) { | |
var target = getTargetItem(e); | |
var i, all, range; | |
if(!target) return; | |
if(e.ctrlKey) { | |
return; | |
} else if(e.shiftKey) { | |
//範囲選択 | |
all = getAll(); | |
range = []; | |
for(i=0;i<all.length;i++) { | |
if(all[i].elem==target.elem) range.push(i); | |
if(last_click && all[i].elem==last_click.elem) range.push(i); | |
} | |
if(range.length==1) { | |
target.selected(true); | |
last_click = target; | |
} else { | |
for(i=0;i<all.length;i++) { | |
all[i].selected(range[0] <= i && i <= range[1]); | |
} | |
} | |
} else { | |
//クリックされたものだけ選択を反転 | |
last_click = target; | |
getAll().forEach(function(item) { | |
if(item.elem!=target.elem) item.selected(false); | |
}); | |
} | |
getSelection().removeAllRanges(); | |
}); | |
function getTargetItem(e) { | |
var target = e.target; | |
while(target) { | |
if(target.className.indexOf('action_item')>=0) | |
return new Item(target); | |
target = target.parentNode; | |
} | |
return null; | |
} | |
} | |
})(); | |
//自動読み込みスクリプト | |
(function() { | |
var autoSearch = document.createElement('input'); | |
autoSearch.className = "btn"; | |
autoSearch.type = "button"; | |
autoSearch.value = "自動検索開始"; | |
var searchButton = $('//*[@value="検索"]'); | |
console.log(searchButton); | |
searchButton.parentNode.insertBefore(autoSearch, searchButton.nextSibling); | |
var countDown = document.createElement('span'); | |
autoSearch.parentNode.insertBefore(countDown, autoSearch.nextSibling); | |
var timer, countDownTimer; | |
var ids = {}; | |
autoSearch.addEventListener('click', function() { | |
var count = 0; | |
if(timer) { | |
clearInterval(timer); | |
clearInterval(countDownTimer); | |
timer = null; | |
autoSearch.value = "自動検索開始"; | |
countDown.innerText = ''; | |
} else { | |
var interval = prompt('更新間隔を秒単位で指定してください'); | |
if(interval*1==NaN || interval < 10) { | |
alert('更新間隔には10以上の数字を入れてください!'); | |
return ; | |
} | |
autoSearch.value = "自動検索停止"; | |
$(ALL_CHOICES, function(elem) { | |
ids[elem.id] = true; | |
}); | |
timer = setInterval(doAutoSearch, interval * 1000); | |
countDownTimer = setInterval(doCountDown, 1000); | |
countDown.innerText = interval; | |
doAutoSearch(); | |
} | |
function doAutoSearch() { | |
count = interval; | |
var results = document.getElementById('results'); | |
results.innerHTML = ''; | |
var e = document.createEvent("MouseEvents"); | |
click(searchButton); | |
setTimeout(function move() { | |
var items = []; | |
$(ALL_RESULTS, function(elem) { | |
items.push(elem); | |
}); | |
if(items.length==0) { | |
setTimeout(move, 1000); | |
return ; | |
} | |
var choices = document.getElementById('choices'); | |
items.reverse(); | |
items.forEach(function(elem) { | |
if(ids[elem.id]) return ; | |
choices.appendChild(elem); | |
ids[elem.id] = true; | |
}); | |
results.innerHTML = ''; | |
}, 1000); | |
} | |
function doCountDown() { | |
count--; | |
countDown.innerText = count; | |
} | |
}); | |
})(); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
現在TogetterがAOSSLに移行しているため、作動するURL (@include) について https://... も追加する必要があるようです。
(対象のウェブサイトに追加したところ、スクリプト自体は変更なしに動作しています。)