|
// ==UserScript== |
|
// @name Chat Snippets |
|
// @author Robert Lemon |
|
// @version 1.35 |
|
// @namespace |
|
// @description tab complete snippets for chat input |
|
// @include http://chat.stackoverflow.com/rooms/* |
|
// ==/UserScript== |
|
|
|
function exec(fn) { |
|
var script = document.createElement('script'); |
|
script.setAttribute('type', 'application/javascript'); |
|
script.textContent = '(' + fn + ')();'; |
|
document.body.appendChild(script); // run the script |
|
} |
|
function inject(str) { |
|
var style = document.createElement('style'); |
|
style.setAttribute('type','text/css'); |
|
style.textContent = str; |
|
document.head.appendChild(style); |
|
} |
|
inject('.csm_tip_content{font:13px/1.7\'Helvetica Neue\',Helvetica,Arial,sans-serif;background-color:#fff;color:#333;padding:9px 17px}.csm_tip_container{display:none;position:absolute;margin-top:-75px;z-index:1000}.csm_tip_point{position:relative;background:#fff;border:1px solid #dcdcdc}.csm_tip_point:after,.csm_tip_point:before{position:absolute;pointer-events:none;border:solid transparent;top:100%;content:"";height:0;width:0}.csm_tip_point:after{border-top-color:#fff;border-width:8px;left:50%;margin-left:-8px}.csm_tip_point:before{border-top-color:#dcdcdc;border-width:9px;left:50%;margin-left:-9px}'); |
|
exec(function () { |
|
function parseContents(str) { |
|
if (/^\s*(https?:\/\/[^\s<>'"?]+)\.(bmp|png|webp|gif|jpg|jpeg|svg)(\?[^\s<>?]*)?\s*$/.test(str)) { |
|
return '<img src="' + str + '" style="width:98px;"/>'; |
|
} |
|
return str.replace(/\r\n/g, '<br />'); |
|
} |
|
var btn = $('<button class="button" style="margin-left: 2px;">Snippets</button>'), |
|
room = document.forms[0].elements.room.value, |
|
snippets = window.localStorage.getItem('so_chat_snippets'); |
|
if( snippets ) { |
|
snippets = JSON.parse(snippets); |
|
} else { |
|
snippets = {}; |
|
} |
|
btn.on('click', function () { |
|
var modal = $('<div style="overflow: inherit !important;"><h4>Chat Snippet Manager</h4></div>'); |
|
var btnNew = $('<button class="button">new</button>'), |
|
btnImp = $('<button class="button">import</button>'), |
|
btnExp = $('<button class="button">export</button>'), |
|
list = $('<ul></ul>'); |
|
var addItem = function(name, replace) { |
|
var item = $('<li style="height:1.45em;"></li>'); |
|
item.data('replace', replace); |
|
item.hover(function() { |
|
$(this).css('background-color', 'rgba(0,0,0,0.05)'); |
|
var out = '<div class="csm_tip_container"><div class="csm_tip_point"><div class="csm_tip_content">' + parseContents($(this).data('replace')) + '</div></div></div>'; |
|
$(this).append(out); |
|
var w_t = $('.csm_tip_container', this).outerWidth(); |
|
var w_e = $(this).width(); |
|
var m_l = (w_e / 2) - (w_t / 2); |
|
$('.csm_tip_container', this).css('margin-left', m_l + 'px').fadeIn(300); |
|
}, |
|
function() { |
|
$(this).css('background-color', 'Transparent'); |
|
$('.csm_tip_container', this).remove(); |
|
}) |
|
item.text(name); |
|
var del = $('<div class="btn-close" title="Delete">X</div>'); |
|
del.on('click', function() { |
|
$(this).remove(); |
|
var key = item.text(); |
|
item.remove(); |
|
delete snippets[key]; |
|
window.localStorage.setItem('so_chat_snippets', JSON.stringify(snippets)); |
|
}); |
|
item.append(del); |
|
list.append(item); |
|
}; |
|
for( var key in snippets ) { |
|
addItem(key, snippets[key] ); |
|
} |
|
btnNew.on('click', function() { |
|
var name, replace; |
|
name = prompt('enter the snippet trigger word'); |
|
if( name ) replace = prompt('enter the replacement string'); |
|
|
|
if( name && replace && !( name in snippets ) ) { |
|
snippets[name] = replace; |
|
window.localStorage.setItem('so_chat_snippets', JSON.stringify(snippets)); |
|
addItem(name, replace); |
|
} |
|
return false; |
|
}); |
|
btnImp.on('click', function() { |
|
var input = prompt('please enter the JSON input'); |
|
if( input ) { |
|
if( JSON.parse(input) ) { |
|
window.localStorage.setItem('so_chat_snippets', input); |
|
} |
|
} |
|
}); |
|
btnExp.on('click', function() { |
|
var win = window.open(); |
|
win.document.write(JSON.stringify(snippets)); |
|
}); |
|
modal.append(btnNew); |
|
modal.append(btnImp); |
|
modal.append(btnExp); |
|
modal.append('<hr>'); |
|
modal.append(list); |
|
modal.addClass('popup room-popup').css({ |
|
bottom: btn.position().top, |
|
left: btn.position().left |
|
}).on('click', function (e) { |
|
modal.remove(); |
|
return false; |
|
}); |
|
$(document.body).append(modal); |
|
return false; |
|
}); |
|
$('#chat-buttons').append(btn); |
|
|
|
input.addEventListener('keydown', function (e) { |
|
if (e.which === 9) { // TAB |
|
var pos = input.selectionStart, |
|
words = input.value.substr(0, pos).split(' '); |
|
last = words[words.length - 1]; |
|
if (last.length > 0) { |
|
if (last in snippets) { |
|
e.preventDefault(); |
|
input.value = input.value.substr(0, pos - last.length) + snippets[last]; |
|
} |
|
} |
|
} |
|
}); |
|
|
|
}); |