Advertisement
djhonga2001

Untitled

Dec 9th, 2016
245
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.38 KB | None | 0 0
  1. //META{"name":"searchPlugin"}*//
  2. class searchPlugin{
  3. constructor(){
  4. this.cancelFlag = false;
  5. this.css = "<style class='searchBarPlugin'>"+
  6. "#searchBarInner{"+
  7. "float:right; position:relative; height: 40px; bottom:40px;color:#FFF; padding: 0 4px; border-radius: 4px;"+
  8. '}'+
  9. '.buttonClose{'+
  10. 'background: transparent url(https://discordapp.com/assets/14f734d6803726c94b970c3ed80c0864.svg); background-size: cover; transition: opacity .1s easeout; opacity: .5; width:12px; height: 12px; padding: 0'+
  11. '}'+
  12. '.buttonClose:hover{opacity:1;}'+
  13. '#searchBar{'+
  14. 'height:0; width:auto;'+
  15. '}'+
  16. '#searchBar .btn{'+
  17. 'cursor: pointer;'+
  18. '}'+
  19. '#searchBarInner>*+*{'+
  20. 'margin-left:5px;'+
  21. '}'+
  22.  
  23. '#searchBarInner>.buttonClose:last-child{'+
  24. 'margin-left:30px;'+
  25. '}'+
  26. '#searchBarStopper{'+
  27. 'width: auto; position: absolute; right: 0; top: -100%;'+
  28. '}'+
  29. '#searchBar input:not(:placeholder-shown)+.search-bar-clear:after,#searchBar input:not(:placeholder-shown)+.search-bar-clear:before{'+
  30. ' background:#373a3f;width:3px;height:14px;margin:6px 0 0 11px;'+
  31. '}'+
  32. '#searchBar input:not(:placeholder-shown)+.search-bar-clear{cursor:pointer;pointer-events:auto;}'+
  33. '</style>';
  34. this.defaultSettings = {"matchCase":false, "mentionsCheck":true, "namesCheck":true, "codeCheck":true, "searchTerm":""}
  35. }
  36. getUpdates(){
  37. $.getJSON("https://megamit.github.io/repository/search/version.json",(data)=>{
  38. let version = this.getVersion().split(".")
  39. let latest = data[0].version.split(".")
  40. if ( latest[0] > version[0] || (latest[0] == version[0] && latest[1] > version[1]) || (latest[0] == version[0] && latest[1] == version[1] && latest[2] > version[2] )){
  41. let notice;
  42. notice = $(`<div class="notice"><div class="notice-dismiss"></div> Version ${latest.join(".")} of Search is available: ${data[0].notes} <a class="btn btn-primary" href="${data[0].src}" target="_blank">Download</a></div>`).on("click",".notice-dismiss",()=>notice.remove()).appendTo(".app")
  43. }
  44. })
  45. }
  46. log(){
  47. var args = Array.prototype.slice.call(arguments);
  48. args.unshift("%c["+this.getName()+"]", 'font-weight: bold;color: green;');
  49. console.log.apply(console,args);
  50. }
  51. stop(){
  52. $('.searchBarPlugin').remove();
  53. }
  54. start(){
  55. this.loadSettings()
  56. window.addEventListener('keydown', (function(e){if(e.ctrlKey&&e.which==70){this.displaySearchbar()} }).bind(this) );
  57. $('head').append(this.css);
  58. this.getUpdates()
  59. }
  60. addStopper(){
  61. this.removeStopper()
  62. $("<div id='searchBarStopper' class='form'><button class='btn btn-primary red' type='button'><span>Stop Search</span></button></div>").insertBefore('#searchBarInner>*:last-child')
  63. .click(() => {
  64. this.stopSearch();
  65. })
  66. }
  67. removeStopper(){ $("#searchBarStopper").remove(); }
  68. containsCode(node){
  69. return ( node.nodeName=="PRE" && node.firstChild.nodeName == "CODE" || node.nodeName == "CODE" ) ;
  70. }
  71. containsMention(node){
  72. return false;
  73. }
  74. search(query_s,settings,startNode,startIndex){
  75. if (this.cancelFlag) return (this.cancelFlag = false)
  76. let { matchCase, mentionsCheck, namesCheck, codeCheck, direction } = settings,
  77. query = matchCase?query_s:query_s.toLowerCase(),
  78. messages = $(".message-group.compact .message-content, .message-group:not(.compact) .markup"+
  79. // the span part is poor solution but i wont lose any sleep over it
  80. (codeCheck?", .message-group.compact .message-content code, .message-group.compact .message-content code span, .message-group:not(.compact) .markup code, .message-group:not(.compact) .markup code span":"")+
  81. (namesCheck?", .message-group.compact strong.user-name, .message-group:not(.compact) strong.user-name":"")+
  82. (mentionsCheck?", .message-group.compact .message-content .highlight, .message-group:not(.compact) .markup .highlight":"")
  83. )
  84. .contents()
  85. .filter(function() {
  86. return this.nodeType === 3
  87. //||( codeCheck && this.containsCode(this) )
  88. ;
  89. }),
  90. foundStart = false,
  91. found = false;
  92. let start, check, next;
  93. if (direction=="down"){
  94. start = 0;
  95. check = (i) => i<messages.length;
  96. next = (i) => i+1 ;
  97. } else {
  98. start = messages.length-1;
  99. check = (i) => i>=0;
  100. next = (i) => i-1;
  101. }
  102. let limit = 1000,
  103. msg;
  104. for (let i = start;check(i);i=next(i)){
  105. msg = messages[i];
  106. let msgtxt = matchCase?msg.nodeValue:msg.nodeValue.toLowerCase();
  107. if (!startNode||foundStart||startNode==msg){
  108. foundStart = true;
  109. if(startIndex==0&&startNode==msg) continue;
  110. let index = startNode==msg?msgtxt.lastIndexOf(query,startIndex-1):msgtxt.lastIndexOf(query)
  111. if (index!=-1){
  112. found=true
  113. $(".messages").scrollTop(msg.parentElement.offsetTop)
  114. let sel = window.getSelection();
  115. let range = document.createRange();
  116. let endpoint = query.length+index
  117. range.setStart(msg,0);
  118. range.setEnd(msg,endpoint);
  119. range.setStart(msg,index);
  120. sel.removeAllRanges();
  121. sel.addRange(range);
  122. //this.log("found",msg,msg.parentElement.offsetTop,"from",startNode,startIndex)
  123. break;
  124. }
  125. }
  126. if (limit-- ==0) return console.error("LIMIT BREAK",i,messages.length)
  127. }
  128. if (this.cancelFlag){
  129. //this.log("stop")
  130. this.cancelFlag = false;
  131. }
  132. if(found||this.cancelFlag){
  133. this.cancelFlag = false; this.removeStopper();
  134. }else{
  135. this.scrollChatToTop()
  136. this.cancelTO = setTimeout(() => {
  137. this.search(query,settings,msg,0)
  138. },50)
  139. }
  140.  
  141.  
  142. }
  143. scrollChatToTop(){
  144. $(".has-more button").click()
  145. $(".messages")[0].scrollTop=0;
  146. }
  147. scrollChatToBottom(){
  148. $(".has-more button").click()
  149. $(".messages")[0].scrollTop=0;
  150. }
  151. displaySearchbar(){
  152. if($("#searchBar").length==0){
  153. var sb = $("<form class='searchPlugin' id='searchBar'></form>").css("display","block")
  154. var sbInner = $("<div id='searchBarInner' class='search-bar'></div>").css("float","right")
  155. sb.append(sbInner)
  156. sbInner.append(
  157. $("<div class='search-bar-inner'></div>").append(
  158. $("<input id='searchBarInput' placeholder='Find...'>").keydown((event) => {
  159. if(event.keyCode == 13){
  160. event.preventDefault()
  161. $("#searchBarUp").click();
  162. }
  163. })
  164. ).append(
  165. $(
  166. '<div class="search-bar-clear"></div>'
  167. ).click(function(){
  168. this.previousSibling.value = "";
  169. this.previousSibling.focus();
  170. })
  171. )
  172. );
  173. const doSearch = (isDown) => {
  174. var q = $("#searchBarInput").val()
  175. if (q.length>0){
  176. var sel = window.getSelection();
  177. if (sel.type == "Range"&&sel.anchorNode.id != "searchBarForm"){
  178. $(".messages").scrollTop(sel.anchorNode.parentElement.offsetTop)
  179. this.addStopper();
  180. this.search($("#searchBarInput").val(),{
  181. matchCase: document.getElementById('searchBarCaseCheck').checked,
  182. mentionsCheck: document.getElementById('searchBarMentionsCheck').checked,
  183. codeCheck: document.getElementById('searchBarCodeCheck').checked,
  184. namesCheck: document.getElementById('searchBarNameCheck').checked,
  185. direction: isDown?"down":"up"
  186. },sel.anchorNode,sel.anchorOffset)
  187.  
  188. }else{
  189. this.addStopper();
  190. this.search($("#searchBarInput").val(),{
  191. matchCase: document.getElementById('searchBarCaseCheck').checked,
  192. mentionsCheck: document.getElementById('searchBarMentionsCheck').checked,
  193. codeCheck: document.getElementById('searchBarCodeCheck').checked,
  194. namesCheck: document.getElementById('searchBarNameCheck').checked,
  195. direction: isDown?"down":"up"
  196. })
  197. }
  198.  
  199. }
  200. }
  201. var up = $("<input id='searchBarUp' class='btn' type='button' value='&#x25B2'>").click(() => {doSearch(false)})
  202. sbInner.append(up);
  203. var down = $("<input id='searchBarDown' class='btn' type='button' value='&#x25BC'>").click(() => {doSearch(true)})
  204. sbInner.append(down);
  205.  
  206. //var caseCheck = $("<input name='caseCheck' id='searchBarCaseCheck' class='btn' type='checkbox'>")
  207. var caseCheck = $('<div class="checkbox"><div class="checkbox-inner"><input id="searchBarCaseCheck" type="checkbox" '+(this.settings.matchCase?"checked":"")+'><span></span></div><span>Match Case</span></div>').click(function(){var x = document.getElementById('searchBarCaseCheck'); x.checked = !x.checked; this.settings.matchCase = x.checked; this.saveSettings();});
  208. var namesCheck = $('<div class="checkbox"><div class="checkbox-inner"><input id="searchBarNameCheck" type="checkbox"'+(this.settings.namesCheck?"checked":"")+'><span></span></div><span>Names</span></div>').click(function(){var x = document.getElementById('searchBarNameCheck'); x.checked = !x.checked; this.settings.namesCheck= x.checked; this.saveSettings();});
  209. var mentionsCheck = $('<div class="checkbox"><div class="checkbox-inner"><input id="searchBarMentionsCheck" type="checkbox"'+(this.settings.mentionsCheck?"checked":"")+'><span></span></div><span>Mentions</span></div>').click(function(){var x = document.getElementById('searchBarMentionsCheck'); x.checked = !x.checked;this.settings.mentionsCheck = x.checked; this.saveSettings();});
  210. var codeCheck = $('<div class="checkbox"><div class="checkbox-inner"><input id="searchBarCodeCheck" type="checkbox"'+(this.settings.codeCheck?"checked":"")+'><span></span></div><span>Code</span></div>').click(function(){var x = document.getElementById('searchBarCodeCheck'); x.checked = !x.checked; this.settings.codeCheck = x.checked; this.saveSettings();});
  211. //var caseLabel = $("<label for='caseCheck' id='searchBarCaseLabel' class='btn' type='checkbox'>Match Case</label>")
  212. sbInner.append(caseCheck)
  213. .append(namesCheck)
  214. .append(mentionsCheck)
  215. .append(codeCheck);
  216. //caseCheck.after(caseLabel);
  217.  
  218. var closeX = $("<button id='searchBarClose' class='btn buttonClose' type='button'></button>").click( () => {
  219. this.stopSearch();
  220. $("#searchBar").remove();
  221. });
  222. sbInner.append(closeX);
  223. $(".messages-wrapper").after(sb)
  224.  
  225. }
  226. $("#searchBarInput").focus();
  227. }
  228. stopSearch(){
  229. //this.log("stopping")
  230. clearTimeout(this.cancelTO)
  231. this.cancelFlag = true;
  232. this.removeStopper();
  233. setTimeout(function(){
  234. this.cancelFlag = false;
  235. },50)
  236. }
  237.  
  238. saveSettings(){
  239. localStorage.setItem(this.getName(),JSON.stringify(this.settings));
  240. }
  241. loadSettings(){
  242. this.settings = $.extend({},this.defaultSettings,JSON.parse(localStorage.getItem(this.getName())))
  243. this.saveSettings();
  244. }
  245.  
  246. getName(){return "searchPlugin"};
  247. getDescription(){return "The return of ctrl+f! until at least discord devs decide to add it"};
  248. getVersion(){return "1.2.1"};
  249. getAuthor(){return "Megamit/Mitchell"};
  250. load(){};
  251. unload(){};
  252.  
  253. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement