Created
September 21, 2017 16:33
-
-
Save aveao/f0ded1a548167f4e8565ec6d8a5c4d05 to your computer and use it in GitHub Desktop.
Ave's SEChat Mods (partially incompatible with rchern/StackExchangeScripts, remove your current version and install https://gist.github.com/aveao/c825253c63cffe84a1469416e0ada594 to get both working)
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 Ave's SEChat Mods | |
// @namespace https://ave.zone/ | |
// @match *://chat.meta.stackexchange.com/rooms/* | |
// @match *://chat.stackoverflow.com/rooms/* | |
// @match *://chat.stackexchange.com/rooms/* | |
// @version 0.1 | |
// @description A stack-chat mod | |
// @author Avery O (ave.zone) | |
// @grant none | |
// ==/UserScript== | |
function inject() { | |
for (var i = 0; i < arguments.length; ++i) { | |
if (typeof(arguments[i]) == 'function') { | |
var script = document.createElement('script'); | |
script.type = 'text/javascript'; | |
script.textContent = 'if (window.jQuery) (' + arguments[i].toString() + ')(window.jQuery)'; | |
document.body.appendChild(script); | |
} | |
} | |
} | |
inject(livequery, function($) { | |
function addStyleString(str) { | |
var node = document.createElement('style'); | |
node.innerHTML = str; | |
document.body.appendChild(node); | |
} | |
addStyleString('img.emoji {height: 16px;width: 16px;}'); | |
addStyleString('img.wumboji {height: 36px;width: 36px;}'); | |
function isOnlyEmoji(str) { | |
str = str.trim() | |
// https://github.com/fredley/Porkchat/commit/bfc65e5f9a19ddc514b9890c5bc7bd481035f20b#diff-31b1e62e3100b9ffcf06be8265d704edR603 | |
var r = /(?:[\u2700-\u27bf]|(?:\ud83c[\udde6-\uddff]){2}|[\ud800-\udbff][\udc00-\udfff]|[\u0023-\u0039]\ufe0f?\u20e3|\u3299|\u3297|\u303d|\u3030|\u24c2|\ud83c[\udd70-\udd71]|\ud83c[\udd7e-\udd7f]|\ud83c\udd8e|\ud83c[\udd91-\udd9a]|\ud83c[\udde6-\uddff]|[\ud83c[\ude01-\ude02]|\ud83c\ude1a|\ud83c\ude2f|[\ud83c[\ude32-\ude3a]|[\ud83c[\ude50-\ude51]|\u203c|\u2049|[\u25aa-\u25ab]|\u25b6|\u25c0|[\u25fb-\u25fe]|\u00a9|\u00ae|\u2122|\u2139|\ud83c\udc04|[\u2600-\u26FF]|\u2b05|\u2b06|\u2b07|\u2b1b|\u2b1c|\u2b50|\u2b55|\u231a|\u231b|\u2328|\u23cf|[\u23e9-\u23f3]|[\u23f8-\u23fa]|\ud83c\udccf|\u2934|\u2935|[\u2190-\u21ff])/g | |
return str.trim().replace(r, '').length === 0 | |
} | |
function replaceAll(str, find, replace) { | |
return str.replace(new RegExp(find, 'g'), replace); | |
} | |
/*jslint indent: 2, browser: true, bitwise: true, plusplus: true */ | |
/*! Copyright Twitter Inc. and other contributors. Licensed under MIT */ | |
var twemoji=function(){"use strict";var twemoji={base:"https://twemoji.maxcdn.com/2/",ext:".png",size:"72x72",className:"emoji",convert:{fromCodePoint:fromCodePoint,toCodePoint:toCodePoint},onerror:function onerror(){if(this.parentNode){this.parentNode.replaceChild(createText(this.alt,false),this)}},parse:parse,replace:replace,test:test},escaper={"&":"&","<":"<",">":">","'":"'",'"':"""},re=/\ud83d[\udc68-\udc69](?:\ud83c[\udffb-\udfff])?\u200d(?:\u2695\ufe0f|\u2696\ufe0f|\u2708\ufe0f|\ud83c[\udf3e\udf73\udf93\udfa4\udfa8\udfeb\udfed]|\ud83d[\udcbb\udcbc\udd27\udd2c\ude80\ude92])|(?:\ud83c[\udfcb\udfcc]|\ud83d\udd75|\u26f9)(?:\ufe0f|\ud83c[\udffb-\udfff])\u200d[\u2640\u2642]\ufe0f|(?:\ud83c[\udfc3\udfc4\udfca]|\ud83d[\udc6e\udc71\udc73\udc77\udc81\udc82\udc86\udc87\ude45-\ude47\ude4b\ude4d\ude4e\udea3\udeb4-\udeb6]|\ud83e[\udd26\udd37-\udd39\udd3d\udd3e\uddd6-\udddd])(?:\ud83c[\udffb-\udfff])?\u200d[\u2640\u2642]\ufe0f|\ud83d\udc68\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68|\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc69\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d[\udc68\udc69]|\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc68\u200d\u2764\ufe0f\u200d\ud83d\udc68|\ud83d\udc68\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d[\udc66\udc67]|\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d[\udc66\udc67]|\ud83d\udc69\u200d\u2764\ufe0f\u200d\ud83d[\udc68\udc69]|\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d[\udc66\udc67]|\ud83c\udff3\ufe0f\u200d\ud83c\udf08|\ud83c\udff4\u200d\u2620\ufe0f|\ud83d\udc41\u200d\ud83d\udde8|\ud83d\udc68\u200d\ud83d[\udc66\udc67]|\ud83d\udc69\u200d\ud83d[\udc66\udc67]|\ud83d\udc6f\u200d\u2640\ufe0f|\ud83d\udc6f\u200d\u2642\ufe0f|\ud83e\udd3c\u200d\u2640\ufe0f|\ud83e\udd3c\u200d\u2642\ufe0f|\ud83e\uddde\u200d\u2640\ufe0f|\ud83e\uddde\u200d\u2642\ufe0f|\ud83e\udddf\u200d\u2640\ufe0f|\ud83e\udddf\u200d\u2642\ufe0f|(?:[\u0023\u002a\u0030-\u0039])\ufe0f?\u20e3|(?:(?:\ud83c[\udfcb\udfcc]|\ud83d[\udd74\udd75\udd90]|[\u261d\u26f7\u26f9\u270c\u270d])(?:\ufe0f|(?!\ufe0e))|\ud83c[\udf85\udfc2-\udfc4\udfc7\udfca]|\ud83d[\udc42\udc43\udc46-\udc50\udc66-\udc69\udc6e\udc70-\udc78\udc7c\udc81-\udc83\udc85-\udc87\udcaa\udd7a\udd95\udd96\ude45-\ude47\ude4b-\ude4f\udea3\udeb4-\udeb6\udec0\udecc]|\ud83e[\udd18-\udd1c\udd1e\udd1f\udd26\udd30-\udd39\udd3d\udd3e\uddd1-\udddd]|[\u270a\u270b])(?:\ud83c[\udffb-\udfff]|)|\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc65\udb40\udc6e\udb40\udc67\udb40\udc7f|\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc73\udb40\udc63\udb40\udc74\udb40\udc7f|\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc77\udb40\udc6c\udb40\udc73\udb40\udc7f|\ud83c\udde6\ud83c[\udde8-\uddec\uddee\uddf1\uddf2\uddf4\uddf6-\uddfa\uddfc\uddfd\uddff]|\ud83c\udde7\ud83c[\udde6\udde7\udde9-\uddef\uddf1-\uddf4\uddf6-\uddf9\uddfb\uddfc\uddfe\uddff]|\ud83c\udde8\ud83c[\udde6\udde8\udde9\uddeb-\uddee\uddf0-\uddf5\uddf7\uddfa-\uddff]|\ud83c\udde9\ud83c[\uddea\uddec\uddef\uddf0\uddf2\uddf4\uddff]|\ud83c\uddea\ud83c[\udde6\udde8\uddea\uddec\udded\uddf7-\uddfa]|\ud83c\uddeb\ud83c[\uddee-\uddf0\uddf2\uddf4\uddf7]|\ud83c\uddec\ud83c[\udde6\udde7\udde9-\uddee\uddf1-\uddf3\uddf5-\uddfa\uddfc\uddfe]|\ud83c\udded\ud83c[\uddf0\uddf2\uddf3\uddf7\uddf9\uddfa]|\ud83c\uddee\ud83c[\udde8-\uddea\uddf1-\uddf4\uddf6-\uddf9]|\ud83c\uddef\ud83c[\uddea\uddf2\uddf4\uddf5]|\ud83c\uddf0\ud83c[\uddea\uddec-\uddee\uddf2\uddf3\uddf5\uddf7\uddfc\uddfe\uddff]|\ud83c\uddf1\ud83c[\udde6-\udde8\uddee\uddf0\uddf7-\uddfb\uddfe]|\ud83c\uddf2\ud83c[\udde6\udde8-\udded\uddf0-\uddff]|\ud83c\uddf3\ud83c[\udde6\udde8\uddea-\uddec\uddee\uddf1\uddf4\uddf5\uddf7\uddfa\uddff]|\ud83c\uddf4\ud83c\uddf2|\ud83c\uddf5\ud83c[\udde6\uddea-\udded\uddf0-\uddf3\uddf7-\uddf9\uddfc\uddfe]|\ud83c\uddf6\ud83c\udde6|\ud83c\uddf7\ud83c[\uddea\uddf4\uddf8\uddfa\uddfc]|\ud83c\uddf8\ud83c[\udde6-\uddea\uddec-\uddf4\uddf7-\uddf9\uddfb\uddfd-\uddff]|\ud83c\uddf9\ud83c[\udde6\udde8\udde9\uddeb-\udded\uddef-\uddf4\uddf7\uddf9\uddfb\uddfc\uddff]|\ud83c\uddfa\ud83c[\udde6\uddec\uddf2\uddf3\uddf8\uddfe\uddff]|\ud83c\uddfb\ud83c[\udde6\udde8\uddea\uddec\uddee\uddf3\uddfa]|\ud83c\uddfc\ud83c[\uddeb\uddf8]|\ud83c\uddfd\ud83c\uddf0|\ud83c\uddfe\ud83c[\uddea\uddf9]|\ud83c\uddff\ud83c[\udde6\uddf2\uddfc]|\ud800\udc00|\ud83c[\udccf\udd8e\udd91-\udd9a\udde6-\uddff\ude01\ude32-\ude36\ude38-\ude3a\ude50\ude51\udf00-\udf20\udf2d-\udf35\udf37-\udf7c\udf7e-\udf84\udf86-\udf93\udfa0-\udfc1\udfc5\udfc6\udfc8\udfc9\udfcf-\udfd3\udfe0-\udff0\udff4\udff8-\udfff]|\ud83d[\udc00-\udc3e\udc40\udc44\udc45\udc51-\udc65\udc6a-\udc6d\udc6f\udc79-\udc7b\udc7d-\udc80\udc84\udc88-\udca9\udcab-\udcfc\udcff-\udd3d\udd4b-\udd4e\udd50-\udd67\udda4\uddfb-\ude44\ude48-\ude4a\ude80-\udea2\udea4-\udeb3\udeb7-\udebf\udec1-\udec5\uded0-\uded2\udeeb\udeec\udef4-\udef8]|\ud83e[\udd10-\udd17\udd1d\udd20-\udd25\udd27-\udd2f\udd3a\udd3c\udd40-\udd45\udd47-\udd4c\udd50-\udd6b\udd80-\udd97\uddc0\uddd0\uddde-\udde6]|[\u23e9-\u23ec\u23f0\u23f3\u2640\u2642\u2695\u26ce\u2705\u2728\u274c\u274e\u2753-\u2755\u2795-\u2797\u27b0\u27bf\ue50a]|(?:\ud83c[\udc04\udd70\udd71\udd7e\udd7f\ude02\ude1a\ude2f\ude37\udf21\udf24-\udf2c\udf36\udf7d\udf96\udf97\udf99-\udf9b\udf9e\udf9f\udfcd\udfce\udfd4-\udfdf\udff3\udff5\udff7]|\ud83d[\udc3f\udc41\udcfd\udd49\udd4a\udd6f\udd70\udd73\udd76-\udd79\udd87\udd8a-\udd8d\udda5\udda8\uddb1\uddb2\uddbc\uddc2-\uddc4\uddd1-\uddd3\udddc-\uddde\udde1\udde3\udde8\uddef\uddf3\uddfa\udecb\udecd-\udecf\udee0-\udee5\udee9\udef0\udef3]|[\u00a9\u00ae\u203c\u2049\u2122\u2139\u2194-\u2199\u21a9\u21aa\u231a\u231b\u2328\u23cf\u23ed-\u23ef\u23f1\u23f2\u23f8-\u23fa\u24c2\u25aa\u25ab\u25b6\u25c0\u25fb-\u25fe\u2600-\u2604\u260e\u2611\u2614\u2615\u2618\u2620\u2622\u2623\u2626\u262a\u262e\u262f\u2638-\u263a\u2648-\u2653\u2660\u2663\u2665\u2666\u2668\u267b\u267f\u2692-\u2694\u2696\u2697\u2699\u269b\u269c\u26a0\u26a1\u26aa\u26ab\u26b0\u26b1\u26bd\u26be\u26c4\u26c5\u26c8\u26cf\u26d1\u26d3\u26d4\u26e9\u26ea\u26f0-\u26f5\u26f8\u26fa\u26fd\u2702\u2708\u2709\u270f\u2712\u2714\u2716\u271d\u2721\u2733\u2734\u2744\u2747\u2757\u2763\u2764\u27a1\u2934\u2935\u2b05-\u2b07\u2b1b\u2b1c\u2b50\u2b55\u3030\u303d\u3297\u3299])(?:\ufe0f|(?!\ufe0e))/g,UFE0Fg=/\uFE0F/g,U200D=String.fromCharCode(8205),rescaper=/[&<>'"]/g,shouldntBeParsed=/^(?:iframe|noframes|noscript|script|select|style|textarea)$/,fromCharCode=String.fromCharCode;return twemoji;function createText(text,clean){return document.createTextNode(clean?text.replace(UFE0Fg,""):text)}function escapeHTML(s){return s.replace(rescaper,replacer)}function defaultImageSrcGenerator(icon,options){return"".concat(options.base,options.size,"/",icon,options.ext)}function grabAllTextNodes(node,allText){var childNodes=node.childNodes,length=childNodes.length,subnode,nodeType;while(length--){subnode=childNodes[length];nodeType=subnode.nodeType;if(nodeType===3){allText.push(subnode)}else if(nodeType===1&&!("ownerSVGElement"in subnode)&&!shouldntBeParsed.test(subnode.nodeName.toLowerCase())){grabAllTextNodes(subnode,allText)}}return allText}function grabTheRightIcon(rawText){return toCodePoint(rawText.indexOf(U200D)<0?rawText.replace(UFE0Fg,""):rawText)}function parseNode(node,options){var allText=grabAllTextNodes(node,[]),length=allText.length,attrib,attrname,modified,fragment,subnode,text,match,i,index,img,rawText,iconId,src;while(length--){modified=false;fragment=document.createDocumentFragment();subnode=allText[length];text=subnode.nodeValue;i=0;while(match=re.exec(text)){index=match.index;if(index!==i){fragment.appendChild(createText(text.slice(i,index),true))}rawText=match[0];iconId=grabTheRightIcon(rawText);i=index+rawText.length;src=options.callback(iconId,options);if(src){img=new Image;img.onerror=options.onerror;img.setAttribute("draggable","false");attrib=options.attributes(rawText,iconId);for(attrname in attrib){if(attrib.hasOwnProperty(attrname)&&attrname.indexOf("on")!==0&&!img.hasAttribute(attrname)){img.setAttribute(attrname,attrib[attrname])}}img.className=options.className;img.alt=rawText;img.src=src;modified=true;fragment.appendChild(img)}if(!img)fragment.appendChild(createText(rawText,false));img=null}if(modified){if(i<text.length){fragment.appendChild(createText(text.slice(i),true))}subnode.parentNode.replaceChild(fragment,subnode)}}return node}function parseString(str,options){return replace(str,function(rawText){var ret=rawText,iconId=grabTheRightIcon(rawText),src=options.callback(iconId,options),attrib,attrname;if(src){ret="<img ".concat('class="',options.className,'" ','draggable="false" ','alt="',rawText,'"',' src="',src,'"');attrib=options.attributes(rawText,iconId);for(attrname in attrib){if(attrib.hasOwnProperty(attrname)&&attrname.indexOf("on")!==0&&ret.indexOf(" "+attrname+"=")===-1){ret=ret.concat(" ",attrname,'="',escapeHTML(attrib[attrname]),'"')}}ret=ret.concat("/>")}return ret})}function replacer(m){return escaper[m]}function returnNull(){return null}function toSizeSquaredAsset(value){return typeof value==="number"?value+"x"+value:value}function fromCodePoint(codepoint){var code=typeof codepoint==="string"?parseInt(codepoint,16):codepoint;if(code<65536){return fromCharCode(code)}code-=65536;return fromCharCode(55296+(code>>10),56320+(code&1023))}function parse(what,how){if(!how||typeof how==="function"){how={callback:how}}return(typeof what==="string"?parseString:parseNode)(what,{callback:how.callback||defaultImageSrcGenerator,attributes:typeof how.attributes==="function"?how.attributes:returnNull,base:typeof how.base==="string"?how.base:twemoji.base,ext:how.ext||twemoji.ext,size:how.folder||toSizeSquaredAsset(how.size||twemoji.size),className:how.className||twemoji.className,onerror:how.onerror||twemoji.onerror})}function replace(text,callback){return String(text).replace(re,callback)}function test(text){re.lastIndex=0;var result=re.test(text);re.lastIndex=0;return result}function toCodePoint(unicodeSurrogates,sep){var r=[],c=0,p=0,i=0;while(i<unicodeSurrogates.length){c=unicodeSurrogates.charCodeAt(i++);if(p){r.push((65536+(p-55296<<10)+(c-56320)).toString(16));p=0}else if(55296<=c&&c<=56319){p=c}else{r.push(c.toString(16))}}return r.join(sep||"-")}}(); | |
$("#chat .message:not(.pending):not(.posted)").livequery(function () { | |
var id = this.id.replace("message-", ""), self = $(this); | |
if (!self.siblings('#id-' + id).length) { | |
var timestamp = new Date(self.data('info').time * 1000); | |
timestamp = "" + timestamp.getHours() + ":" + (timestamp.getMinutes() < 10 ? "0" + timestamp.getMinutes() : timestamp.getMinutes()) + ":" + (timestamp.getSeconds() < 10 ? "0" + timestamp.getSeconds() : timestamp.getSeconds()); | |
self.prev(".timestamp").remove(); | |
self.prepend($('<div />') | |
.text(id + ' ' + timestamp) | |
.addClass('timestamp') | |
.css('line-height', '1.4em') | |
.attr('id', 'id-' + id)); | |
} | |
}); | |
$('#chat .message .full').livequery(function() { | |
var self = this; | |
var chatmessage_full = $(this).html(); | |
console.log("Full message: " + chatmessage_full); | |
var emojified_chatmessage_full = twemoji.parse(chatmessage_full); | |
if (chatmessage_full != emojified_chatmessage_full) { | |
console.log("Emojified Full:" + emojified_chatmessage_full); | |
$(this).html(emojified_chatmessage_full); | |
} | |
}); | |
$('#chat .message').livequery(function() { | |
var self = this; | |
var chatmessage = $(this).find('.content').html(); | |
if (chatmessage.includes("<div class=\"partial\">")) { | |
var chatmessage_partial = $(this).find('.content').find('.partial').html(); | |
console.log("Partial:" + chatmessage_partial); | |
var emojified_chatmessage_partial = twemoji.parse(chatmessage_partial); | |
if (chatmessage_partial != emojified_chatmessage_partial) { | |
console.log("Emojified Partial:" + emojified_chatmessage_partial); | |
$(this).find('.content').find('.partial').html(emojified_chatmessage_partial); | |
} | |
} else { | |
console.log(chatmessage); | |
var emojified_chatmessage = twemoji.parse(chatmessage); | |
if (chatmessage != emojified_chatmessage) { | |
console.log("Emojified:" + emojified_chatmessage); | |
if (isOnlyEmoji(chatmessage)) | |
{ | |
console.log("Apparently it's emoji only so wumboji-ing"); | |
emojified_chatmessage = replaceAll(emojified_chatmessage, "class=\"emoji\"", "class=\"wumboji\""); | |
} | |
$(this).find('.content').html(emojified_chatmessage); | |
} | |
} | |
if ($(this).find('.meta').find('.newreply').length == 0) { | |
$('<span class="newreply" />') | |
.prependTo($(this).find('.meta')) | |
.attr('title', "link my next chat message as a reply to this") | |
.click(function() { | |
var n = $("#input").focus().val().replace(/^:([0-9]+)\s+/, ""); | |
$("#input").focus().val(":" + self.id.substring(8) + " " + n) | |
}); | |
} | |
}); | |
}); | |
function livequery($) { | |
/*! Copyright (c) 2010 Brandon Aaron (http://brandonaaron.net) | |
* Dual licensed under the MIT (MIT_LICENSE.txt) | |
* and GPL Version 2 (GPL_LICENSE.txt) licenses. | |
* | |
* Version: 1.1.1 | |
* Requires jQuery 1.3+ | |
* Docs: http://docs.jquery.com/Plugins/livequery | |
*/ | |
$.extend($.fn, { | |
livequery: function(type, fn, fn2) { | |
var self = this, | |
q; | |
// Handle different call patterns | |
if ($.isFunction(type)) { | |
fn2 = fn; | |
fn = type; | |
type = undefined; | |
} | |
// See if Live Query already exists | |
$.each($.livequery.queries, function(i, query) { | |
if (self.selector == query.selector && self.context == query.context && | |
type == query.type && (!fn || fn.$lqguid == query.fn.$lqguid) && (!fn2 || fn2.$lqguid == query.fn2.$lqguid)) | |
// Found the query, exit the each loop | |
return (q = query) && false; | |
}); | |
// Create new Live Query if it wasn't found | |
q = q || new $.livequery(this.selector, this.context, type, fn, fn2); | |
// Make sure it is running | |
q.stopped = false; | |
// Run it immediately for the first time | |
q.run(); | |
// Contnue the chain | |
return this; | |
}, | |
expire: function(type, fn, fn2) { | |
var self = this; | |
// Handle different call patterns | |
if ($.isFunction(type)) { | |
fn2 = fn; | |
fn = type; | |
type = undefined; | |
} | |
// Find the Live Query based on arguments and stop it | |
$.each($.livequery.queries, function(i, query) { | |
if (self.selector == query.selector && self.context == query.context && | |
(!type || type == query.type) && (!fn || fn.$lqguid == query.fn.$lqguid) && (!fn2 || fn2.$lqguid == query.fn2.$lqguid) && !this.stopped) | |
$.livequery.stop(query.id); | |
}); | |
// Continue the chain | |
return this; | |
} | |
}); | |
$.livequery = function(selector, context, type, fn, fn2) { | |
this.selector = selector; | |
this.context = context; | |
this.type = type; | |
this.fn = fn; | |
this.fn2 = fn2; | |
this.elements = []; | |
this.stopped = false; | |
// The id is the index of the Live Query in $.livequery.queries | |
this.id = $.livequery.queries.push(this) - 1; | |
// Mark the functions for matching later on | |
fn.$lqguid = fn.$lqguid || $.livequery.guid++; | |
if (fn2) fn2.$lqguid = fn2.$lqguid || $.livequery.guid++; | |
// Return the Live Query | |
return this; | |
}; | |
$.livequery.prototype = { | |
stop: function() { | |
var query = this; | |
if (this.type) | |
// Unbind all bound events | |
this.elements.unbind(this.type, this.fn); | |
else if (this.fn2) | |
// Call the second function for all matched elements | |
this.elements.each(function(i, el) { | |
query.fn2.apply(el); | |
}); | |
// Clear out matched elements | |
this.elements = []; | |
// Stop the Live Query from running until restarted | |
this.stopped = true; | |
}, | |
run: function() { | |
// Short-circuit if stopped | |
if (this.stopped) return; | |
var query = this; | |
var oEls = this.elements, | |
els = $(this.selector, this.context), | |
nEls = els.not(oEls); | |
// Set elements to the latest set of matched elements | |
this.elements = els; | |
if (this.type) { | |
// Bind events to newly matched elements | |
nEls.bind(this.type, this.fn); | |
// Unbind events to elements no longer matched | |
if (oEls.length > 0) | |
$.each(oEls, function(i, el) { | |
if ($.inArray(el, els) < 0) | |
$.event.remove(el, query.type, query.fn); | |
}); | |
} else { | |
// Call the first function for newly matched elements | |
nEls.each(function() { | |
query.fn.apply(this); | |
}); | |
// Call the second function for elements no longer matched | |
if (this.fn2 && oEls.length > 0) | |
$.each(oEls, function(i, el) { | |
if ($.inArray(el, els) < 0) | |
query.fn2.apply(el); | |
}); | |
} | |
} | |
}; | |
$.extend($.livequery, { | |
guid: 0, | |
queries: [], | |
queue: [], | |
running: false, | |
timeout: null, | |
checkQueue: function() { | |
if ($.livequery.running && $.livequery.queue.length) { | |
var length = $.livequery.queue.length; | |
// Run each Live Query currently in the queue | |
while (length--) | |
$.livequery.queries[$.livequery.queue.shift()].run(); | |
} | |
}, | |
pause: function() { | |
// Don't run anymore Live Queries until restarted | |
$.livequery.running = false; | |
}, | |
play: function() { | |
// Restart Live Queries | |
$.livequery.running = true; | |
// Request a run of the Live Queries | |
$.livequery.run(); | |
}, | |
registerPlugin: function() { | |
$.each(arguments, function(i, n) { | |
// Short-circuit if the method doesn't exist | |
if (!$.fn[n]) return; | |
// Save a reference to the original method | |
var old = $.fn[n]; | |
// Create a new method | |
$.fn[n] = function() { | |
var jQuery = $; | |
// Call the original method | |
var r = old.apply(this, arguments); | |
// Request a run of the Live Queries | |
jQuery.livequery.run(); | |
// Return the original methods result | |
return r; | |
}; | |
}); | |
}, | |
run: function(id) { | |
if (id != undefined) { | |
// Put the particular Live Query in the queue if it doesn't already exist | |
if ($.inArray(id, $.livequery.queue) < 0) | |
$.livequery.queue.push(id); | |
} else | |
// Put each Live Query in the queue if it doesn't already exist | |
$.each($.livequery.queries, function(id) { | |
if ($.inArray(id, $.livequery.queue) < 0) | |
$.livequery.queue.push(id); | |
}); | |
// Clear timeout if it already exists | |
if ($.livequery.timeout) clearTimeout($.livequery.timeout); | |
// Create a timeout to check the queue and actually run the Live Queries | |
$.livequery.timeout = setTimeout($.livequery.checkQueue, 20); | |
}, | |
stop: function(id) { | |
if (id != undefined) | |
// Stop are particular Live Query | |
$.livequery.queries[id].stop(); | |
else | |
// Stop all Live Queries | |
$.each($.livequery.queries, function(id) { | |
$.livequery.queries[id].stop(); | |
}); | |
} | |
}); | |
// Register core DOM manipulation methods | |
$.livequery.registerPlugin('append', 'prepend', 'after', 'before', 'wrap', 'attr', 'removeAttr', 'addClass', 'removeClass', 'toggleClass', 'empty', 'remove', 'html'); | |
// Run Live Queries when the Document is ready | |
$(function() { | |
$.livequery.play(); | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment