├── LICENSE ├── README.md ├── devpostparticipants.js ├── docs └── chrome-dev-tools.png └── star.user.js /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Star-Me 2 | Starring is fun! 3 | 4 | The script in this repository connects developers automatically with FOSSASIA projects on GitHub. You need to run the script in your Chrome browser developer console. 5 | 6 | # Steps 7 | 8 | ## 1. Sign In 9 | Make sure that you are signed in your GitHub account, if not do so now! 10 | 11 | ## 2. Copy the Script 12 | Open star.user.js [at this link here](https://github.com/fossasia/star-me/blob/master/star.user.js) and copy the entire script. 13 | 14 | ## 3. Open Developer Tools in Your Browser 15 | 16 | Make sure you are on a tab with an open GitHub page and open developer tools. 17 | 18 | ### For Linux and Windows Users 19 | To open developer tools on Chrome/Chromium please press ctrl+shift+I 20 | 21 | ### For macOS Users using Chrome/Chromium 22 | To open developer tools please press ⌘+⌥+I 23 | 24 | 25 | ### It should look something like this: 26 | 27 |  28 | 29 | ## 4. Open the Console tab in the Developer Tools 30 | Click on the `Console` tab in the developer tools to open it, then click on the text area in the Console tab. 31 | 32 | Ensure you are still on a browser tab that has GitHub open. 33 | 34 | ## 5. Paste the Script 35 | Paste the script by pressing ctrl+V if you are on Windows or if you are on macOS press ⌘+V. 36 | 37 | Then hit return / Enter. 38 | 39 | ## 6. Wait until the script is finished 40 | The script needs to run a few minutes. At the end it will display "Finally Over ;-)" in blue color. Ensure it runs until the end. 41 | 42 | ## 7.Starring is done. Go start contributing 43 | Once starring is finished, you can find starred repositories in your github handle.Choose project of your interest and start contributing. 44 | You will also receive updates regarding repositories. 45 | 46 | -------------------------------------------------------------------------------- /devpostparticipants.js: -------------------------------------------------------------------------------- 1 | var parser = new DOMParser(); 2 | 3 | function getUserData(user) { 4 | return fetch("user").then(a => a.text()).then(function(txt) { 5 | var htmlDoc = parser.parseFromString(txt, "text/html"); 6 | return [].map.call(htmlDoc.getElementById('portfolio-user-links').getElementsByTagName('li'), function(a) { 7 | var h = a.getElementsByTagName('a')[0]; 8 | return { 9 | name: a.children[0].className, 10 | str: a.innerText.trim(), 11 | href: h ? h.href : "" 12 | } 13 | }) 14 | }).catch(console.log) 15 | } 16 | 17 | function getParticipants(nameFromHackathon, i) { 18 | return fetch("https://" + nameFromHackathon + ".devpost.com/participants?page=" + i, { 19 | headers: { 20 | Accept: "text/html, */*; q=0.01", 21 | "X-Csrf-Token": "Mi2DOJ2BcnS1YZYg+kMNAM9gPRePOt8QtwhCvyjZx9JzDuI2QlwF+0AitR1h50gYhaqYLNMAVHQZmZniMhKAKQ==", 22 | "X-Requested-With": "XMLHttpRequest" 23 | } 24 | }).then(a => a.text()).then(txt => parser.parseFromString(txt, "text/html")).then(function(document) { 25 | var participantLinks = [].map.call(document.getElementsByClassName('participant'), function(e) { 26 | return e.getElementsByTagName('a')[0].href 27 | }); 28 | var p; 29 | if (participantLinks.length) { 30 | p = new Promise(function(resolve, reject) { 31 | getParticipants(nameFromHackathon, i + 1).then(function(p) { 32 | resolve(participantLinks.concat(p)) 33 | }) 34 | }) 35 | } 36 | return p ? p : Promise.resolve(participantLinks); 37 | }) 38 | } 39 | -------------------------------------------------------------------------------- /docs/chrome-dev-tools.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossasia/star-me/e44223ec4206b0e40ba5213dfba67945e1627e47/docs/chrome-dev-tools.png -------------------------------------------------------------------------------- /star.user.js: -------------------------------------------------------------------------------- 1 | /* 2 | Create Element: 3 | $Rainb.el('div',{'attribute':"value",style:{"color":"red"}},[ (childnodes) ]) 4 | becomes:
5 | Append Element 6 | $Rainb.add(element,elementToAppend) 7 | Get Element By Id 8 | $Rainb.id(id); 9 | Create TextNode 10 | $Rainb.tn(text); 11 | Create a RainbNode (an element wrapper) 12 | $Rainb.node(elem); 13 | You can modify RainbNode attributes and children and it will not affect DOM until you call .render 14 | Parameter is boolean, true for rendering children, false for not rendering children 15 | $Rainb.node.render(boolean); 16 | */ 17 | //This probably proves I've gotten better at programming. 18 | //DOM helper functions. 19 | var genParser = (function(tys, tree, start) { 20 | var source, index; 21 | var treeRewrite = tree; 22 | //Apparently, you don't tokenize and then parse, you do it on the go, but with more specific techniques which people call grammars, oh well, how was I suppesd to know that anyway. 23 | //reference {type:"type",is:"type"} "hue" 24 | //repetition {type:"repeat",optional:false,from:1,to:Infinity,contains:{},delimiting:null,multipleDelimeters:null} optional to and from are defaulted, delimiters can be used for lists like a,b,c and stuff 25 | //array {type:"tyArray",contains:[]} 26 | //alternate {type:"alternate",contains:[]} 27 | //Expression {type:"expression",contains:{},operators:[{precedence:1,rightAssociative:false,tokens:[]}}],delimeters=[["(",")"]],whiteSpaceIgnore:null} 28 | var mains = { //START PARSE 29 | type: "type", 30 | is: start 31 | } 32 | //yay extendibility 33 | var funcs = { //funcions/types used, hue 34 | expression: function(o) { //parse it like an expression 35 | //this is probably a little bit hard to understand 36 | var r = { 37 | type: "alternate", 38 | contains: [o.contains] 39 | }, //is it a token, an operator, or a parenthesis? 40 | opers = { 41 | type: "alternate", 42 | contains: [] 43 | }, 44 | delims = { 45 | type: "alternate", 46 | contains: [] 47 | }, 48 | i, I, l, L, props, t, n, ret = {}, 49 | _ind = index, 50 | EXPRS = [], 51 | OPERATORS = [], 52 | O, precedence, rightAssociative, arg1, arg2, k; //I use and reuse most variables I can, damn 53 | if (O = o.operators) { 54 | for (i = 0, l = O.length; i < l; i++) { 55 | for (I = 0, L = O[i].tokens.length; I < L; I++) { 56 | t = O[i].tokens[I]; 57 | if (o.whiteSpaceIgnore) { 58 | if (typeof t === "string") { 59 | opers.contains.push(new RegExp("\\s*(?:" + t.replace(/([-+\\?.!$^&*(){}[\]])/g, "\\$1") + ")\\s*")); 60 | } else if (t instanceof RegExp) { 61 | opers.contains.push(new RegExp("\\s*(?:" + t.source + ")\\s*", (t.multiline ? "m" : "") + (t.ignoreCase ? "i" : ""))) 62 | } else { 63 | opers.contains.push({ 64 | type: "tyArray", 65 | contains: [/\s*/, t, /\s*/] 66 | }); /*Ahh I HATE THIS! D:*/ 67 | } 68 | } else { 69 | opers.contains.push(t); 70 | } 71 | } 72 | } 73 | r.contains[1] = opers; //ADD THEM TO THE LIST 74 | } 75 | if (O = o.delimeters) { //this is like a carbon copy of the previous if, should I try to make it a function? Don't repeat yourself 76 | for (i = 0, l = O.length; i < l; i++) { 77 | for (I = 0, L = O[i].length; I < L; I++) { 78 | t = O[i][I]; 79 | if (o.whiteSpaceIgnore) { 80 | if (typeof t === "string") { 81 | delims.contains.push(new RegExp("\s*(?:" + t + ")\s*")); 82 | } else if (t instanceof RegExp) { 83 | delims.contains.push(new RegExp("\s*(?:" + t.source + ")\s*", (t.multiline ? "m" : "") + (t.ignoreCase ? "i" : ""))) 84 | } else { 85 | delims.contains.push({ 86 | type: "tyArray", 87 | contains: [/\s*/, t, /\s*/] 88 | }); /*Ahh I HATE THIS! D:*/ 89 | } 90 | } else { 91 | delims.contains.push(t); 92 | } 93 | } 94 | } 95 | r.contains[2] = delims; 96 | } 97 | /*Shunting Yard Algorithm*/ 98 | while (n = isIndexItem(r, props = {})) { //While there are tokens to be read 99 | //read a token 100 | if (props._matched === r.contains[0]) { //If the token is a number, then add it to the output queue. 101 | EXPRS.push(n); 102 | } else 103 | if (props._matched === opers) { //If the token is an operator, o1, then 104 | if ((I = opers.contains.indexOf(props.props._matched)) !== -1) { 105 | for (i = 0, l = (O = o.operators).length, k = 0; i < l; i++) { // 106 | if ((k += O[i].tokens.length) > I) { 107 | precedence = O[i].precedence; 108 | rightAssociative = O[i].rightAssociative; 109 | break; 110 | } 111 | } 112 | } else { 113 | throw new Error("props.props._matched not found at oper.contains, This is impossible.. or is it?"); 114 | } 115 | while ((L = OPERATORS.length) && (((!rightAssociative) && precedence === OPERATORS[L - 1][1]) || precedence < OPERATORS[L - 1][1])) { //while there is an operator token, o2, at the top of the stack, and 116 | //either o1 is left-associative and its precedence is equal to that of o2, 117 | //or o1 has precedence less than that of o2, 118 | /*POPPINGG!!*/ 119 | //pop o2 off the stack, onto the output queue; 120 | //This popping is also a bit of PRN execution, basically it is shunting yard and prn, or something weird 121 | arg2 = EXPRS.pop(); 122 | arg1 = EXPRS.pop(); 123 | if (!(EXPRS.length || arg1)) { 124 | console.warn("NOT ENOUGH TERMS"); 125 | } 126 | t = OPERATORS.pop(); 127 | for (i = 0, l = (O = o.operators).length, k = 0; i < l; i++) { 128 | if ((k += O[i].tokens.length) > t[2]) { 129 | EXPRS.push({ 130 | operation: O[i].tokens[t[2] - (k - O[i].tokens.length)], 131 | op: t[0], 132 | arguments: [arg1, arg2], 133 | name: "operator" 134 | }); 135 | break; 136 | } 137 | } 138 | } 139 | OPERATORS.push([n, precedence, I]); 140 | } else 141 | if (props._match === delims) {} else { 142 | throw Error("This is impossible! It has matched an unknown value..???"); 143 | } 144 | } 145 | //When there are no more tokens to read 146 | while (L = OPERATORS.length) { //While there are still operator tokens in the stack 147 | //Pop the operator onto the output queue. 148 | arg2 = EXPRS.pop(); 149 | arg1 = EXPRS.pop(); 150 | if (!(EXPRS.length || arg1)) { 151 | console.warn("NOT ENOUGH TERMS"); 152 | } 153 | t = OPERATORS.pop(); 154 | for (i = 0, l = (O = o.operators).length, k = 0; i < l; i++) { 155 | if ((k += O[i].tokens.length) > t[2]) { 156 | EXPRS.push({ 157 | operation: O[i].tokens[t[2] - (k - O[i].tokens.length)], 158 | op: t[0], 159 | arguments: [arg1, arg2], 160 | name: "operator" 161 | }); 162 | break; 163 | } 164 | } 165 | } 166 | if (EXPRS.length < 1) { 167 | return null; 168 | } 169 | if (EXPRS.length !== 1) { 170 | throw new Error("Operators and expressions mismatch!!"); 171 | } 172 | return EXPRS[0]; 173 | }, 174 | type: function(o) { //get type and parse it 175 | var props = {}, 176 | a = isIndexItem(tys[o.is], props), 177 | t, ret; //this is where props originally started, in short words, it is used to pass properties from other functions to here 178 | if (a === null) return null; 179 | //console.log() 180 | ret = { 181 | type: (t = tys[o.is]) && (t.delimiting ? "list" : t.type || ((typeof t === "string" || t instanceof RegExp) ? "String" : undefined)), 182 | name: o.is, 183 | content: a 184 | } 185 | for (var k in props) { 186 | if (props.hasOwnProperty(k) && (!ret[k])) { 187 | ret[k] = props[k]; 188 | } 189 | } 190 | return ret; 191 | }, 192 | repeat: function(o, props) { //repeat 193 | var reto = [], 194 | e, d, _ind = index, 195 | l, p, D = o.delimiting, 196 | i = 0, 197 | p = D && o.multipleDelimeters, //say, if the delimeter is just once, there is no point in putting it each time it appears.. right? so an CSV like "abc,dfe,ege" will appear as ["abc","dfe","ege"] instead of ["abc",',',"dfe",',',"ege"] 198 | props2; 199 | d = o.contains; 200 | props.props = []; 201 | do { 202 | e = isIndexItem(D ? i & 1 ? D : d : d, props2 = {}); 203 | if ((!p) && D && i & 1) { 204 | i++; 205 | if (e !== null) { 206 | continue; 207 | } else { 208 | break; 209 | } 210 | } 211 | i++; 212 | if (e !== null) { 213 | reto.push(e) 214 | props.props.push(props2) 215 | } 216 | } while (e !== null && i !== o.to); 217 | l = reto.length; 218 | if (((!o.optional) && l == 0) || ((!isNaN(p = o.from)) && l < p)) { 219 | index = _ind; 220 | return null; 221 | } 222 | if (D && !p) { 223 | props.delimeter = D 224 | } 225 | return reto; 226 | }, 227 | tyArray: function(o, props) { //tokens are in some order 228 | var reto = [], 229 | e, _ind = index, 230 | opt = o.optional || [], 231 | props2; 232 | props.props = []; 233 | for (var i = 0, l = o.contains.length, d; i < l; i++) { 234 | d = o.contains[i]; 235 | e = isIndexItem(d, props2 = {}); 236 | if (e === null && (opt.indexOf(i) < 0)) { 237 | index = _ind; 238 | return null; 239 | } 240 | if (e !== null) props.props.push(props2); 241 | reto.push(e); 242 | } 243 | return reto; 244 | }, 245 | alternate: function(o, props) { //It alternates 246 | var reto = null, 247 | e, props2 = {}; 248 | for (var i = 0, l = o.contains.length, d; i < l; i++) { 249 | d = o.contains[i]; 250 | e = isIndexItem(d, props2); 251 | if (e !== null) { 252 | reto = e; 253 | props.props = props2; 254 | props._matched = d; 255 | break; 256 | } 257 | } 258 | return reto; 259 | } 260 | } 261 | 262 | function isIndexItem(item, props) { //recursive 263 | //returns item or null 264 | var s, t, r, 265 | f; 266 | if (!item) { 267 | return null 268 | } else 269 | if (item instanceof RegExp) { 270 | r = new RegExp 271 | r.compile("^(?:" + item.source + ")", (item.multiline ? "m" : "") + (item.eturnignoreCase ? "i" : "")) 272 | //r.lastIndex = index; 273 | s = r.exec(source.substr(index)); //RAAAWR damn it 274 | t = s && s[0]; 275 | if (t === null) return null; 276 | index += t.length; 277 | return t; 278 | } else if (typeof item == "string") { //literal match 279 | //console.log("DOES "+item+" and"+source.substr(index,item.length)+" MATCHES??"); 280 | if (item === source.substr(index, item.length)) return (index += item.length), item; 281 | return null; 282 | } else { 283 | t = item.type; 284 | f = funcs[t]; 285 | s = f(item, props); 286 | if (f) return s; 287 | else return null; 288 | } 289 | } 290 | 291 | function Parser(arg) { 292 | source = arg, 293 | index = 0; //index is 0!!! 294 | return treeRewrite.unknown(isIndexItem(mains)); //wasn't that just pretty understandable? 295 | } 296 | return Parser; 297 | }); 298 | var CssSelectorParser = genParser({ //tys, meaning types 299 | "type selector": /\*|(?:[\w_]|\\x?[a-f0-9]{2,6}\s?|\\[\S\s])(?:[^\\\s#.>&+~:,="'[\]\)]|\\x?[a-f0-9]{2,6}\s?|\\[\S\s])*/i, //regex for tagname 300 | attributeValue: { //the vaue of an attibute, it can be 301 | type: "alternate", 302 | contains: [/"(?:[^"\\]|\\[\s\S])*"|'(?:[^'\\]|\\[\s\S])*'/i, { 303 | type: "type", 304 | is: "type selector" 305 | }] 306 | }, 307 | "pseudo-class": { 308 | type: "alternate", 309 | contains: [{ 310 | type: "tyArray", 311 | contains: [":not", { 312 | type: "tyArray", 313 | contains: ["(", { 314 | type: "type", 315 | is: "selectorArray" 316 | }, ")"] 317 | }], 318 | }, { 319 | type: "tyArray", 320 | contains: [/::?(?:[\w_]|\\x?[a-f0-9]{2,6}\s?|\\[\S\s])(?:[^\\\s#.>&+~:,(]|\\x?[a-f0-9]{2,6}\s?|\\[\S\s])*/, { 321 | type: "tyArray", 322 | contains: ["(", /(?:[^)\\]|\\[\S\s])*/, ")"] 323 | }], 324 | optional: [1] 325 | }] 326 | }, //is for this I was thinking of implementing my own regex, this is beyond ridiculous 327 | operator: /\s*(?:\$=|\^=|~=|\|=|\*=|=)\s*/, //you know the thing at [attr=value] 328 | "attribute selector": { 329 | type: "tyArray", 330 | contains: ['[', { 331 | type: "tyArray", 332 | contains: [{ 333 | type: "type", 334 | is: "type selector" 335 | }, { 336 | type: "type", 337 | is: "operator" 338 | }, { 339 | type: "type", 340 | is: "attributeValue" 341 | }], 342 | optional: [1, 2] 343 | }, ']'] 344 | }, 345 | "ID selector": { 346 | type: "tyArray", 347 | contains: ['#', { //an id starts with an # 348 | type: "type", 349 | is: "type selector" 350 | }] 351 | }, 352 | "class selector": { //a classname starts with a dot 353 | type: "tyArray", 354 | contains: ['.', { 355 | type: "type", 356 | is: "type selector" 357 | }] 358 | }, 359 | "simple selector": { //a element selector is composed from tagname, clasname,attributesm, and pseudoclasses 360 | //this is a sequence of simple selectors 361 | type: "repeat", 362 | contains: { 363 | type: "alternate", 364 | contains: [{ 365 | type: "type", 366 | is: "type selector" 367 | }, { 368 | type: "type", 369 | is: "class selector" 370 | }, { 371 | type: "type", 372 | is: "ID selector" 373 | }, { 374 | type: "type", 375 | is: "attribute selector" 376 | }, { 377 | type: "type", 378 | is: "pseudo-class" 379 | }] 380 | } 381 | }, 382 | selector: 383 | /* {OLD LOL 384 | type: "repeat", 385 | delimiting: { 386 | type: "type", 387 | is: "relationship" 388 | }, 389 | contains: { 390 | type: "type", 391 | is: "element" 392 | }*/ 393 | { 394 | type: "expression", 395 | contains: { 396 | type: "type", 397 | is: "simple selector" 398 | }, 399 | whiteSpaceIgnore: true, 400 | rightAssociative: true, 401 | operators: [{ 402 | precedence: 1, 403 | tokens: ['>', '&', '+', '~', /\s/] //these are not actually operators this are combinators 404 | }] 405 | }, 406 | selectorArray: { //this is a selector group 407 | type: "repeat", 408 | delimiting: /\s*,\s*/, //it is separated by a comma, and optionally whitespace 409 | contains: { 410 | type: "type", 411 | is: "selector" 412 | } 413 | } 414 | }, { 415 | unknown: function(a) { 416 | return a.name ? this[a.name](a) : a; 417 | }, 418 | selectorArray: function(a) { 419 | var b = { 420 | name: "selector group", 421 | list: [] 422 | }; 423 | for (var i = 0, l = a.content.length; i < l; i++) b.list.push(this.unknown(a.content[i])) 424 | return b 425 | }, 426 | selector: function(a) { 427 | return this.unknown(a.content) 428 | }, 429 | "simple selector": function(a) { 430 | var b = {}, 431 | att, c; 432 | b.class = []; 433 | b.attributes = []; 434 | b.pseudoClass = []; 435 | for (var i = 0, l = a.content.length, d; i < l; i++) { 436 | d = a.content[i]; 437 | switch (d.name) { 438 | case "type selector": 439 | if (!b.tagName) { 440 | b.tagname = this.unescape(d.content); 441 | } 442 | break; 443 | case "class selector": 444 | b.class.push(this.unescape(d.content[1].content)) 445 | break; 446 | case "ID selector": 447 | if (!b.ID) { 448 | b.ID = this.unescape(d.content[1].content); 449 | } 450 | break; 451 | case "attribute selector": 452 | att = { 453 | attributeName: this.unescape(d.content[1][0].content) 454 | } 455 | if (c = d.content[1][1]) { 456 | att.operator = c.content; 457 | att.attributeValue = this.unescape(d.content[1][2].content) 458 | } 459 | b.attributes.push(att); 460 | break; 461 | case "pseudo-class": 462 | b.pseudoClass.push({ 463 | class: this.unescape(d.content[0]), 464 | value: d.content[1] && this.unknown(d.content[1][1]) 465 | }) 466 | break; 467 | } 468 | } 469 | return b; 470 | }, 471 | operator: function(a) { 472 | var b = this.unknown(a.arguments[1]); 473 | b.parent = this.unknown(a.arguments[0]); 474 | b.parentRelationship = a.op; 475 | return b; 476 | }, 477 | unescape: function(string) { 478 | var unescape = [{ 479 | search: /\\([0-9A-fa-f]{1,6} ?)/g, 480 | replace: { 481 | f: "hexadecimal", 482 | for: 1 483 | } 484 | }, { 485 | search: /\\(.)/g, 486 | replace: { 487 | for: 1 488 | } 489 | }]; 490 | var replacement, string2 = string, 491 | func; 492 | if ((string[0] == '"' || string[0] == "'") && (string[0] === string[string.length - 1])) { 493 | string2 = string.substring(1, string.length - 1) 494 | } 495 | for (var i = 0; i < unescape.length; i++) { 496 | if ((func = unescape[i].replace.f) === undefined) { 497 | replacement = "$" + unescape[i].replace.for 498 | } else { 499 | if (func == "hexadecimal") replacement = function(s) { 500 | return String.fromCharCode(parseInt(arguments[unescape[i].replace.for], 16)) 501 | } 502 | } 503 | string2 = string2.replace(unescape[i].search, replacement) 504 | } 505 | return string2; 506 | } 507 | }, "selectorArray"); 508 | $Rainb = { 509 | d: document.documentElement 510 | } 511 | $Rainb.id = function(id) { 512 | return document.getElementById(id); 513 | }; 514 | $Rainb.ready = function(fc) { 515 | var cb; 516 | if (document.readyState !== 'loading') { 517 | fc(); 518 | return; 519 | } 520 | cb = function() { 521 | $Rainb.off(document, 'DOMContentLoaded', cb); 522 | return fc(); 523 | }; 524 | return $Rainb.on(document, 'DOMContentLoaded', cb); 525 | }; 526 | $Rainb.formData = function(form) { 527 | var fd, key, val; 528 | if (form instanceof HTMLFormElement) { 529 | return new FormData(form); 530 | } 531 | fd = new FormData(); 532 | for (key in form) { 533 | val = form[key]; 534 | if (val) { 535 | if (typeof val === 'object' && 'newName' in val) { 536 | fd.append(key, val, val.newName); 537 | } else { 538 | fd.append(key, val); 539 | } 540 | } 541 | } 542 | return fd; 543 | }; 544 | $Rainb.extend = function(object, properties) { 545 | var key, val; 546 | for (key in properties) { 547 | val = properties[key]; 548 | object[key] = val; 549 | } 550 | }; 551 | $Rainb.deepCompare = function() { 552 | var i, l, leftChain, rightChain; 553 | 554 | function compare2Objects(x, y) { 555 | var p; 556 | // remember that NaN === NaN returns false 557 | // and isNaN(undefined) returns true 558 | if (isNaN(x) && isNaN(y) && typeof x === 'number' && typeof y === 'number') { 559 | return true; 560 | } 561 | // Compare primitives and functions. 562 | // Check if both arguments link to the same object. 563 | // Especially useful on step when comparing prototypes 564 | if (x === y) { 565 | return true; 566 | } 567 | // Works in case when functions are created in constructor. 568 | // Comparing dates is a common scenario. Another built-ins? 569 | // We can even handle functions passed across iframes 570 | if ((typeof x === 'function' && typeof y === 'function') || (x instanceof Date && y instanceof Date) || (x instanceof RegExp && y instanceof RegExp) || (x instanceof String && y instanceof String) || (x instanceof Number && y instanceof Number)) { 571 | return x.toString() === y.toString(); 572 | } 573 | // At last checking prototypes as good a we can 574 | if (!(x instanceof Object && y instanceof Object)) { 575 | return false; 576 | } 577 | if (x.isPrototypeOf(y) || y.isPrototypeOf(x)) { 578 | return false; 579 | } 580 | if (x.constructor !== y.constructor) { 581 | return false; 582 | } 583 | if (x.prototype !== y.prototype) { 584 | return false; 585 | } 586 | // Check for infinitive linking loops 587 | if (leftChain.indexOf(x) > -1 || rightChain.indexOf(y) > -1) { 588 | return false; 589 | } 590 | // Quick checking of one object beeing a subset of another. 591 | // todo: cache the structure of arguments[0] for performance 592 | for (p in y) { 593 | if (y.hasOwnProperty(p) !== x.hasOwnProperty(p)) { 594 | return false; 595 | } else if (typeof y[p] !== typeof x[p]) { 596 | return false; 597 | } 598 | } 599 | for (p in x) { 600 | if (y.hasOwnProperty(p) !== x.hasOwnProperty(p)) { 601 | return false; 602 | } else if (typeof y[p] !== typeof x[p]) { 603 | return false; 604 | } 605 | switch (typeof(x[p])) { 606 | case 'object': 607 | case 'function': 608 | leftChain.push(x); 609 | rightChain.push(y); 610 | if (!compare2Objects(x[p], y[p])) { 611 | return false; 612 | } 613 | leftChain.pop(); 614 | rightChain.pop(); 615 | break; 616 | default: 617 | if (x[p] !== y[p]) { 618 | return false; 619 | } 620 | break; 621 | } 622 | } 623 | return true; 624 | } 625 | if (arguments.length < 1) { 626 | return true; //Die silently? Don't know how to handle such case, please help... 627 | // throw "Need two or more arguments to compare"; 628 | } 629 | for (i = 1, l = arguments.length; i < l; i++) { 630 | leftChain = []; //Todo: this can be cached 631 | rightChain = []; 632 | if (!compare2Objects(arguments[0], arguments[i])) { 633 | return false; 634 | } 635 | } 636 | return true; 637 | } 638 | $Rainb.on = function(el, events, handler) { 639 | var event, _i, _len, _ref; 640 | _ref = events.split(' '); 641 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 642 | event = _ref[_i]; 643 | el.addEventListener(event, handler, false); 644 | } 645 | }; 646 | $Rainb.off = function(el, events, handler) { 647 | var event, _i, _len, _ref; 648 | _ref = events.split(' '); 649 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 650 | event = _ref[_i]; 651 | el.removeEventListener(event, handler, false); 652 | } 653 | }; 654 | $Rainb.el = function(elem, attributes, childnodes, listeners) { 655 | //listener format: {lstng:"click",cb:callback} 656 | var e = (elem instanceof Element) ? elem : document.createElement(elem), 657 | l; 658 | for (var a in attributes) { 659 | if (a == "style") { 660 | for (var d in attributes[a]) { 661 | e.style[d] = attributes[a][d]; 662 | } 663 | continue; 664 | } 665 | if (a == "__properties") { 666 | for (d in attributes[a]) { 667 | e[d] = attributes[a][d]; 668 | } 669 | continue; 670 | } 671 | e.setAttribute(a, attributes[a]) 672 | } 673 | if (childnodes && (l = childnodes.length)) { 674 | for (var i = 0, c; i < l; i++) { 675 | c = childnodes[i]; 676 | if (c.length && typeof c == "string") { 677 | e.appendChild(document.createTextNode(c)); 678 | continue; 679 | } 680 | e.appendChild(c) 681 | } 682 | } 683 | if (listeners && (l = listeners.length)) { 684 | for (var i = 0, c; i < l; i++) { 685 | c = listeners[i]; 686 | $Rainb.on(e, c.lstng, c.cb); 687 | } 688 | } 689 | return e; 690 | } 691 | $Rainb.HTTP = function() { 692 | var lastModified = {}; 693 | return (function(url, extra, callback, headers) { 694 | //headers is an object like this {Connection:"keep-alive"} 695 | extra = extra || {}; 696 | 697 | function createXMLHttpRequest() { 698 | if (typeof XMLHttpRequest != "undefined") { 699 | return new XMLHttpRequest(); 700 | } else if (typeof window.ActiveXObject != "undefined") { 701 | try { 702 | return new ActiveXObject("Msxml2.XMLHTTP.4.0"); 703 | } catch (e) { 704 | try { 705 | return new ActiveXObject("MSXML2.XMLHTTP"); 706 | } catch (e) { 707 | try { 708 | return new ActiveXObject("Microsoft.XMLHTTP"); 709 | } catch (e) { 710 | return null; 711 | } 712 | } 713 | } 714 | } 715 | } 716 | 717 | function looProp(object, callback) { 718 | var a; 719 | for (a in object) { 720 | if (object.hasOwnProperty(a)) callback.call(object, a, object[a]); 721 | } 722 | } 723 | extra.method = extra.method || "GET"; 724 | var xhr = createXMLHttpRequest(), 725 | callbackcall = true; 726 | if (xhr) { 727 | $Rainb.extend(xhr, extra.opts); 728 | $Rainb.extend(xhr.upload, extra.upCallbacks); 729 | xhr.open(extra.method, url, !extra.sync); 730 | if (extra.whenModified) { 731 | if (url in lastModified) { 732 | xhr.setRequestHeader('If-Modified-Since', lastModified[url]); 733 | } 734 | $Rainb.on(r, 'load', function() { 735 | return lastModified[url] = r.getResponseHeader('Last-Modified'); 736 | }); 737 | } 738 | looProp(headers, function(a, b) { 739 | xhr.setRequestHeader(a, b) 740 | }) 741 | xhr.onreadystatechange = function() { 742 | if (xhr.readyState == xhr.DONE && callbackcall) { 743 | callbackcall = false; 744 | callback(xhr) 745 | } 746 | }; 747 | xhr.onloadend = function() { 748 | if (callbackcall) { 749 | callbackcall = false; 750 | callback(xhr) 751 | } 752 | }; 753 | xhr.send(extra.post); 754 | return xhr; 755 | } else { 756 | return null; 757 | } 758 | }); 759 | }() 760 | $Rainb.hasClass = function(el, className) { 761 | return el.classList && el.classList.contains(className); 762 | }; 763 | $Rainb.rm = function(el) { 764 | return el && el.parentNode.removeChild(el); 765 | } 766 | $Rainb.tn = function(s) { 767 | return document.createTextNode(s); 768 | }; 769 | $Rainb.add = function(parent, el) { 770 | return parent.appendChild($Rainb.nodes(el)); 771 | }; 772 | $Rainb.nodes = function(nodes) { 773 | var frag, node, _i, _len; 774 | if (!(nodes instanceof Array)) { 775 | return nodes; 776 | } 777 | frag = d.createDocumentFragment(); 778 | for (_i = 0, _len = nodes.length; _i < _len; _i++) { 779 | node = nodes[_i]; 780 | frag.appendChild(node); 781 | } 782 | return frag; 783 | }; 784 | $Rainb.prepend = function(parent, el) { 785 | return parent.insertBefore($Rainb.nodes(el), parent.firstChild); 786 | }; 787 | $Rainb.bubbleFind = function(element, elementSelector) { 788 | while (element !== null) { 789 | if ($Rainb.isElement(element, elementSelector)) { 790 | return element; 791 | break; 792 | } else { 793 | element = element.parentNode 794 | } 795 | } 796 | } 797 | $Rainb.nodes = function(nodes) { 798 | var frag, node, _i, _len; 799 | if (!(nodes instanceof Array)) { 800 | return nodes; 801 | } 802 | frag = document.createDocumentFragment(); 803 | for (_i = 0, _len = nodes.length; _i < _len; _i++) { 804 | node = nodes[_i]; 805 | frag.appendChild(node); 806 | } 807 | return frag; 808 | }; 809 | $Rainb.after = function(root, el) { 810 | return root.parentNode.insertBefore($Rainb.nodes(el), root.nextSibling); 811 | }; 812 | $Rainb.before = function(root, el) { 813 | return root.parentNode.insertBefore($Rainb.nodes(el), root); 814 | }; 815 | $Rainb.replace = function(root, el) { 816 | return root.parentNode.replaceChild($Rainb.nodes(el), root); 817 | }; 818 | $Rainb.ins = function(txtarea, text, textEnd) { 819 | var scrollPos = txtarea.scrollTop; 820 | var strPos = 0; 821 | textEnd = textEnd || ""; 822 | var br = ((txtarea.selectionStart || txtarea.selectionStart == '0') ? "ff" : (document.selection ? "ie" : false)); 823 | if (br == "ie") { 824 | txtarea.focus(); 825 | var range = document.selection.createRange(); 826 | range.moveStart('character', -txtarea.value.length); 827 | strPos = range.text.length; 828 | } else if (br == "ff") strPos = txtarea.selectionStart; 829 | var front = (txtarea.value).substring(0, strPos); 830 | var selectedText = (txtarea.value).substring(strPos, txtarea.selectionEnd); 831 | var back = (txtarea.value).substring(txtarea.selectionEnd, txtarea.value.length); 832 | txtarea.value = front + text + selectedText + textEnd + back; 833 | strPos = strPos + text.length + selectedText.length + textEnd.length; 834 | if (br == "ie") { 835 | txtarea.focus(); 836 | var range = document.selection.createRange(); 837 | range.moveStart('character', -txtarea.value.length); 838 | range.moveStart('character', strPos); 839 | range.moveEnd('character', 0); 840 | range.select(); 841 | } else if (br == "ff") { 842 | txtarea.selectionStart = strPos; 843 | txtarea.selectionEnd = strPos; 844 | txtarea.focus(); 845 | } 846 | txtarea.scrollTop = scrollPos; 847 | }; 848 | $Rainb.alast = function(arr) { 849 | return arr[arr.length - 1]; 850 | } 851 | $Rainb.till = function() { 852 | var selects = [], 853 | listening = false; 854 | 855 | function nodeInserted(event) { 856 | if (!selects.length) { 857 | $Rainb.off(document, "DOMNodeInserted", nodeInserted); 858 | listening = false; 859 | } else { 860 | for (var i = 0, l = selects.length; i < l; i++) { 861 | if ($Rainb.isElement(selects[i].selector, event.target)) { 862 | selects[i].cb(event.target) 863 | } 864 | } 865 | }; 866 | } 867 | return function(selector, cb, ctx) { 868 | ctx = ctx || window; 869 | var asd; 870 | if (asd = document.querySelector(selector)) { 871 | cb(asd); 872 | } else { 873 | selects.push({ 874 | selector: selector, 875 | cb: cb 876 | }); 877 | if (!listening) { 878 | $Rainb.on(document, "DOMNodeInserted", nodeInserted); 879 | listening = true; 880 | } 881 | } 882 | } 883 | }(); 884 | $Rainb.addStyle = function(css, cb) { 885 | var style = []; 886 | for (var i = 0, l = css.length; i < l; i++) { 887 | style[i] = $Rainb.el('style', null, [css[i]]); 888 | } 889 | $Rainb.till("head", function(a) { 890 | for (var i = 0, l = style.length; i < l; i++) { 891 | $Rainb.add(document.head, style[i]); 892 | } 893 | return cb(style); 894 | }); 895 | return style; 896 | }; 897 | (function() { 898 | //INCOMPLETE 899 | $Rainb.compareElement = function(element, elementDescription) { 900 | if (elementDescription.tagname && (elementDescription.tagname.toUpperCase() !== element.tagName)) return false; 901 | for (var i2 = 0, item, l2 = (item = elementDescription.class).length; i2 < l2; i2++) { 902 | if (!$Rainb.hasClass(element, item[i2])) return false; 903 | } 904 | for (var i2 = 0, item, l2 = (item = elementDescription.pseudoClass).length; i2 < l2; i2++) { 905 | if (item[i2].class == ":not" && isElement(element, item[i2].value)) return false 906 | } 907 | for (var i2 = 0, item, l2 = (item = elementDescription.attributes).length; i2 < l2; i2++) { 908 | var val; 909 | if (val = element.attributes.getNamedItem(item[i2].attributeName)) { 910 | if (!compare(item[i2].operator, item[i2].attributeValue, val.value)) { 911 | return false 912 | } 913 | } else { 914 | return false 915 | } 916 | } 917 | return true; 918 | }; 919 | 920 | function compare(operator, attribute, attributeCompare) { 921 | switch (operator) { 922 | case "*=": 923 | return attributeCompare.indexOf(attribute) !== -1 924 | break; 925 | case "~=": 926 | return new RegExp("(?:^|\\s)" + attribute + "(?:\\s|$)").test(attributeCompare) 927 | break; 928 | case "|=": 929 | return new RegExp("^" + attribute + "-?").test(attributeCompare); 930 | break; 931 | case "$=": 932 | return new RegExp(attribute + "$").test(attributeCompare); 933 | break; 934 | case "^=": 935 | return new RegExp("^" + attribute).test(attributeCompare); 936 | break; 937 | case "=": 938 | return attribute == attributeCompare; 939 | break; 940 | default: 941 | return true; 942 | } 943 | } 944 | 945 | function isElement(element, abstractparsetree) { 946 | for (var i = 0, l = abstractparsetree.list.length; i < l; i++) { 947 | if ($Rainb.compareElement(element, abstractparsetree.list[i])) { 948 | return true; 949 | }; 950 | } 951 | } 952 | //compareElement is incomplete 953 | $Rainb.isElement = function(element, elementSelector) { 954 | if (!elementSelector) return true; 955 | var abstractparsetree = CssSelectorParser(elementSelector); 956 | return isElement(element, abstractparsetree); 957 | }; 958 | })(); 959 | (function() { 960 | var events = {} 961 | $Rainb.unsetEventListener = function(listener, listening, callback, elementSelector) { 962 | var _ref = listening.split(' '); 963 | if (!listener.__$Rainb_Events) { 964 | return false; 965 | } 966 | for (var _i = 0, _len = _ref.length; _i < _len; _i++) { 967 | event = _ref[_i]; 968 | var events; 969 | if ((events = listener.__$Rainb_Events)[event]) { 970 | if (!(callback || elementSelector)) { //if no callback or selector treat as wildcard (all of them) 971 | listener.__$Rainb_Events[event] = []; 972 | $Rainb.off(listener, event, callBack); 973 | continue; 974 | } 975 | for (var i = 0, l = events[event].length; i < l; i++) { 976 | if ((events[event][i].callback == callback || !callback) && (!elementSelector || events[event][i].selector == elementSelector)) { 977 | events[event].splice(i--, 1); 978 | continue; 979 | } 980 | } 981 | } 982 | if (!(events[event] && events[event].length)) { 983 | $Rainb.off(listener, event, callBack); 984 | } 985 | } 986 | } 987 | 988 | function callBack(event, callback) { 989 | var x, element = event.target, 990 | events = event.currentTarget.__$Rainb_Events[event.type].slice(); 991 | while (element !== null) { 992 | for (var i = 0; i < events.length; i++) { 993 | x = events[i]; 994 | if ($Rainb.isElement(element, x.selector)) { 995 | callback.call(element, event); 996 | events.splice(i--, 1); 997 | continue; 998 | } 999 | } 1000 | if (!events.length) break; 1001 | element = element.parentNode 1002 | } 1003 | } 1004 | 1005 | function EventCallback(callback, elementSelector) { 1006 | this.callback = callback; 1007 | this.selector = elementSelector; 1008 | } 1009 | $Rainb.setEventListener = function(listener, listening, callback, elementSelector) { 1010 | var _ref = listening.split(' '); 1011 | for (var eventCallback = new EventCallback(callback, elementSelector), _i = 0, _len = _ref.length; _i < _len; _i++) { 1012 | event = _ref[_i]; 1013 | var events; 1014 | if (!listener.__$Rainb_Events) { 1015 | listener.__$Rainb_Events = {} 1016 | } 1017 | if ((events = listener.__$Rainb_Events)[event]) 1018 | for (var i = 0, l = events[event].length; i < l; i++) { 1019 | if ($Rainb.deepCompare(events[event][i], eventCallback)) { 1020 | return; 1021 | } 1022 | } else { 1023 | events[event] = [] 1024 | } 1025 | events[event].push(eventCallback); 1026 | } 1027 | if (!(listener._$Rainb_Event && listener._$Rainb_Event.length)) $Rainb.on(listener, listening, function(e) { 1028 | callBack(e, callback) 1029 | }); 1030 | } 1031 | })() 1032 | $Rainb.HTTPRequestsRetry = function(requests, success, done, extra, headers, timeout, attemptsleft, failure) { //Same shit when basically the caller function is the same 1033 | var queue = requests; 1034 | 1035 | function DoOne() { 1036 | return $Rainb.HTTPRequestRetry(queue.pop(), function(afg) { 1037 | success(afg); 1038 | if (queue.length) { 1039 | if (timeout) { 1040 | setTimeout(DoOne, timeout); 1041 | } else { 1042 | DoOne(); 1043 | } 1044 | } else { 1045 | if (done) done(); 1046 | } 1047 | }, extra, headers, attemptsleft, failure)(); 1048 | } 1049 | return DoOne; 1050 | } 1051 | $Rainb.HTTPRequestRetry = function(link, success, extra, headers, attemptsleft, failure) { 1052 | attemptsleft = attemptsleft | 0; 1053 | var f, abort = false, 1054 | req; 1055 | 1056 | function callback(xhr) { 1057 | if (xhr.status) { 1058 | success(xhr) 1059 | } else { 1060 | if (abort) return; 1061 | if (failure) failure(xhr); 1062 | if (--attemptsleft) { 1063 | console.log("Didn't work, trying again"); 1064 | f(); 1065 | } 1066 | } 1067 | } 1068 | f = function(arg) { 1069 | if (arg == "abort") { 1070 | abort = true; 1071 | req.abort(); 1072 | attemptsleft = 1; 1073 | return; 1074 | }; 1075 | req = $Rainb.HTTP(link, extra, callback, headers); 1076 | } 1077 | return f; 1078 | }; 1079 | (function() { 1080 | function dragstart(e) { 1081 | var el, isTouching, o, rect, screenHeight, screenWidth, _ref; 1082 | if (e.type === 'mousedown' && e.button !== 0) { 1083 | return; 1084 | } 1085 | e.preventDefault(); 1086 | if (isTouching = e.type === 'touchstart') { 1087 | _ref = e.changedTouches, e = _ref[_ref.length - 1]; 1088 | } 1089 | el = this; 1090 | rect = el.getBoundingClientRect(); 1091 | screenHeight = $Rainb.d.clientHeight; 1092 | screenWidth = $Rainb.d.clientWidth; 1093 | o = { 1094 | id: el.id, 1095 | style: el.style, 1096 | dx: e.clientX - rect.left, 1097 | dy: e.clientY - rect.top, 1098 | height: screenHeight - rect.height, 1099 | width: screenWidth - rect.width, 1100 | screenHeight: screenHeight, 1101 | screenWidth: screenWidth, 1102 | isTouching: isTouching 1103 | }; 1104 | if (isTouching) { 1105 | o.identifier = e.identifier; 1106 | o.move = touchmove.bind(o); 1107 | o.up = touchend.bind(o); 1108 | $Rainb.on(document, 'touchmove', o.move); 1109 | return $Rainb.on(d, 'touchend touchcancel', o.up); 1110 | } else { 1111 | o.move = drag.bind(o); 1112 | o.up = dragend.bind(o); 1113 | $Rainb.on(document, 'mousemove', o.move); 1114 | return $Rainb.on(document, 'mouseup', o.up); 1115 | } 1116 | }; 1117 | touchmove = function(e) { 1118 | var touch, _i, _len, _ref; 1119 | _ref = e.changedTouches; 1120 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 1121 | touch = _ref[_i]; 1122 | if (touch.identifier === this.identifier) { 1123 | drag.call(this, touch); 1124 | return; 1125 | } 1126 | } 1127 | }; 1128 | drag = function(e) { 1129 | var bottom, clientX, clientY, left, right, style, top; 1130 | clientX = e.clientX, clientY = e.clientY; 1131 | left = clientX - this.dx; 1132 | left = left < 10 ? 0 : this.width - left < 10 ? null : left / this.screenWidth * 100 + '%'; 1133 | top = clientY - this.dy; 1134 | top = top < 10 ? 0 : this.height - top < 10 ? null : top / this.screenHeight * 100 + '%'; 1135 | right = left === null ? 0 : null; 1136 | bottom = top === null ? 0 : null; 1137 | style = this.style; 1138 | style.left = left; 1139 | style.right = right; 1140 | style.top = top; 1141 | return style.bottom = bottom; 1142 | }; 1143 | touchend = function(e) { 1144 | var touch, _i, _len, _ref; 1145 | _ref = e.changedTouches; 1146 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 1147 | touch = _ref[_i]; 1148 | if (touch.identifier === this.identifier) { 1149 | dragend.call(this); 1150 | return; 1151 | } 1152 | } 1153 | }; 1154 | dragend = function() { 1155 | if (this.isTouching) { 1156 | $Rainb.off(document, 'touchmove', this.move); 1157 | $Rainb.off(document, 'touchend touchcancel', this.up); 1158 | } else { 1159 | $Rainb.off(document, 'mousemove', this.move); 1160 | $Rainb.off(document, 'mouseup', this.up); 1161 | } 1162 | //return $.set("" + this.id + ".position", this.style.cssText); 1163 | }; 1164 | $Rainb.enableDrag = function() { 1165 | $Rainb.setEventListener(document, "touchstart mousedown", dragstart, ".draggable:not(textarea,button,input,a)") 1166 | } 1167 | })(); 1168 | $Rainb.key = function() { 1169 | this.keys = []; 1170 | } 1171 | $Rainb.key.prototype.add = function(key) { 1172 | if (!this.exists(key)) { 1173 | this.keys.push(key); 1174 | return true 1175 | } 1176 | return false; 1177 | } 1178 | $Rainb.key.prototype.exists = function(key) { 1179 | for (var i = 0, l = this.keys.length; i < l; i++) { 1180 | if (this.keys[i] === key) return true; 1181 | } 1182 | return false; 1183 | } 1184 | $Rainb.key.prototype.remove = function(key) { 1185 | for (var i = 0, l = this.keys.length; i < l; i++) { 1186 | if (this.keys[i] === key) { 1187 | this.keys.splice(i, 1); 1188 | return true; 1189 | } 1190 | } 1191 | return false; 1192 | } 1193 | $Rainb.key.prototype.toggle = function(key) { 1194 | if (this.exists(key)) { 1195 | this.remove(key); 1196 | } else { 1197 | this.add(key); 1198 | } 1199 | } 1200 | $Rainb.key.prototype.isEmpty = function() { 1201 | return this.keys.length === 0; 1202 | }; 1203 | /* 1204 | 1205 | Node rainb. 1206 | */ 1207 | (function() { 1208 | $Rainb.node = function(node) { 1209 | if (!(this instanceof arguments.callee)) return new $Rainb.node(node) 1210 | var attr = {}, 1211 | childNodes = []; 1212 | this.events = []; 1213 | this.classes = new $Rainb.key(); 1214 | this.showChildren = false; 1215 | if (typeof node == "string" || node === undefined) { 1216 | this.nodeName = node; 1217 | this.node = null; 1218 | } else { 1219 | this.nodeName = node.nodeName; 1220 | this.nodeType = node.nodeType; 1221 | if (node.classList) { 1222 | for (var i = 0; i < node.classList.length; i++) { 1223 | this.classes.add(node.classList[i]) 1224 | } 1225 | } 1226 | if (node.attributes) 1227 | for (var i = 0; i < node.attributes.length; i++) { 1228 | attr[node.attributes[i].name] = node.attributes[i].value 1229 | } 1230 | for (i = 0; i < node.childNodes.length; i++) { 1231 | childNodes.push(new $Rainb.node(node.childNodes[i])); 1232 | } 1233 | this.node = node; 1234 | } 1235 | this.childNodes = childNodes; 1236 | this.attr = attr; 1237 | }; 1238 | 1239 | function toNode(node) { //returns a custom rainb node 1240 | if (node instanceof Node) { 1241 | return new $Rainb.node(node); 1242 | } 1243 | return node; 1244 | } 1245 | $Rainb.node.prototype.appendChildren = function() { 1246 | for (var type, i = 0; i < arguments.length; i++) { 1247 | if (!((arguments[i].node instanceof $Rainb.node) || (arguments[i].node instanceof Node)) && arguments[i].node) { 1248 | this.childNodes.push(arguments[i]); 1249 | arguments[i].node = toNode(arguments[i].node); 1250 | } else this.childNodes.push(toNode((type = typeof arguments[i]) === "string" || type === "number" ? $Rainb.tn(arguments[i]) : arguments[i])); 1251 | } 1252 | return this; 1253 | }; 1254 | $Rainb.node.prototype.attribute = function(attr, value) { 1255 | this.attr[attr] = value; 1256 | return this; 1257 | }; 1258 | $Rainb.node.prototype.clss = function(clss) { 1259 | this.classes.keys = clss.split(' '); 1260 | return this; 1261 | } 1262 | $Rainb.node.prototype.style = function(propertyName, value) { 1263 | if (!this.attr.style) { 1264 | this.attribute("style", {}); 1265 | } 1266 | this.attr.style[propertyName] = value; 1267 | return this; 1268 | }; 1269 | $Rainb.node.prototype.item = function(i) { 1270 | return this.childNodes[i]; 1271 | return this; 1272 | }; 1273 | $Rainb.node.prototype.splice = function(start, end /*,newchilds*/ ) { 1274 | for (var i = 2; i < arguments.length; i++) { 1275 | arguments[i] = toNode(arguments[i]); 1276 | } 1277 | this.childNodes.splice.apply(this.childNodes, arguments); 1278 | if (this.showChildren) { 1279 | for (var i = start; i < end && i < this.node.childNodes; i++) { 1280 | $Rainb.rm(this.node.childNodes[start]); 1281 | } 1282 | var args = Array.prototype.slice.call(arguments, 2).map(function(n) { 1283 | return n.render() 1284 | }) 1285 | $Rainb.after(this.node.childNodes[start - 1], args) 1286 | } 1287 | return this; 1288 | }; 1289 | $Rainb.node.prototype.off = function(eventToListen, callback, selector) { 1290 | var event = [eventToListen, callback, selector] 1291 | if (this.node) { 1292 | $Rainb.unsetEventListener(this.node, event[0], event[1], event[2]); 1293 | } 1294 | for (var i = 0; i < this.events.length; i++) { 1295 | if ($Rainb.deepCompare(this.events[i], event)) { 1296 | this.events.splice(i--, 1); 1297 | } 1298 | } 1299 | } 1300 | $Rainb.node.prototype.on = function(eventToListen, callback, selector) { 1301 | this.events.push([eventToListen, callback, selector]); 1302 | return this; 1303 | } 1304 | $Rainb.node.removeAttr = function(attr) {}; 1305 | $Rainb.node.prototype.render = function(children) { 1306 | this.attribute("class", this.classes.keys.join(' ')); 1307 | var ret; 1308 | switch (this.nodeType) { 1309 | case 3: 1310 | case 8: 1311 | return this.node; 1312 | break; 1313 | } 1314 | var child = []; 1315 | if (children) { 1316 | this.showChildren = true; 1317 | for (var i = 0, n; i < this.childNodes.length; i++) { 1318 | n = this.childNodes[i]; 1319 | child.push(typeof n == "string" ? $Rainb.tn(n) : n.render ? n.render(children - 1) : n.node.render(children - 1)); 1320 | } 1321 | } 1322 | this.node = $Rainb.el(this.node || this.nodeName, this.attr, [$Rainb.nodes(child)]); 1323 | this.node.__$Rainb_node = this; //Well, how else do you know what is the Rainb.node when a event points to a targetElement? 1324 | //Yes, I hate this too. I cry everytiem. 1325 | while (this.events.length) { 1326 | var s = this.events.pop(); 1327 | $Rainb.setEventListener(this.node, s[0], s[1], s[2]); 1328 | } 1329 | return this.node; 1330 | } 1331 | })(); 1332 | (function() { 1333 | $Rainb.Uilist = function(node) { 1334 | this.listElement = new $Rainb.node(node); 1335 | } 1336 | })(); 1337 | 1338 | function followUser(user) { 1339 | return new Promise(function(resolve, reject) { 1340 | $Rainb.HTTP("https://github.com/" + user, {}, function(lol) { 1341 | var div = $Rainb.el("div"); 1342 | div.innerHTML = lol.response; 1343 | var form = div.querySelector(".follow>form"); 1344 | if (form) { 1345 | //console.log(form[0]) 1346 | $Rainb.HTTP(form.action, { 1347 | method: form.method, 1348 | post: new FormData(form) 1349 | }, function(asdf) { 1350 | console.log(user + " success follow (I think...)") 1351 | resolve(true); 1352 | }, { 1353 | accept: "application/json" 1354 | }) 1355 | } else { 1356 | console.log("%cHello " + user + "! You cannot follow yourself you noob", "color:blue"); 1357 | resolve(false) 1358 | } 1359 | }) 1360 | }) 1361 | } 1362 | 1363 | function starRepo(repo) { 1364 | var i = 1; 1365 | var x = Promise.resolve([]) 1366 | 1367 | function getNext(x, callback) { 1368 | $Rainb.HTTP("https://api.github.com/" + repo + "/repos?per_page=2000&page=" + x, {}, function(asdf) { 1369 | callback(JSON.parse(asdf.response)) 1370 | }) 1371 | } 1372 | 1373 | function ahh(x) { 1374 | return x.then(function(val) { 1375 | return new Promise(function(resolve, reject) { 1376 | getNext(i++, function(t) { 1377 | if (!t.length) { 1378 | //END 1379 | resolve(val); 1380 | } else { 1381 | //KEEP GOING 1382 | //resolve(val.concat(t)) 1383 | resolve(ahh(Promise.resolve(val.concat(t)))) 1384 | } 1385 | }) 1386 | }) 1387 | }) 1388 | } 1389 | return ahh(x).then(function(ohh) { 1390 | var i = -1; 1391 | return new Promise(function(resolve, reject) { 1392 | function next() { 1393 | if (ohh[++i] && ohh[i].html_url) { 1394 | starForm(ohh[i].html_url, next) 1395 | } else { 1396 | resolve(true) 1397 | } 1398 | } 1399 | next(); next(); 1400 | next(); 1401 | next(); 1402 | next(); 1403 | next(); 1404 | next(); 1405 | next(); 1406 | }) 1407 | }) 1408 | } 1409 | 1410 | function starForm(repo, next) { 1411 | $Rainb.HTTP(repo, {}, function(lol) { 1412 | var div = $Rainb.el("div"); 1413 | div.innerHTML = lol.response; 1414 | var form = Array.prototype.map.call(div.getElementsByClassName("unstarred js-social-form"), function(a) { 1415 | return [a.action, a.method, new FormData(a)] 1416 | }); 1417 | if (form.length) { 1418 | form = form[0] 1419 | //console.log(form[0]) 1420 | $Rainb.HTTP(form[0], { 1421 | method: form[1], 1422 | post: form[2] 1423 | }, function(asdf) { 1424 | console.log(repo + " success starred (I think...)") 1425 | next(); 1426 | }, { 1427 | accept: "application/json" 1428 | }) 1429 | } 1430 | }) 1431 | } 1432 | $Rainb.enableDrag(); 1433 | $Rainb.add(document.body, $Rainb.el('div', { 1434 | class: "draggable", 1435 | style: { 1436 | position: "fixed", 1437 | top: 0, 1438 | backgroundColor: "rebeccapurple", 1439 | padding: "2em 10%" 1440 | } 1441 | }, ["You are now starring these repos, trust me m8", $Rainb.el("button", {}, ["close"])])) 1442 | 1443 | var StarRepos = ["orgs/fossasia", "orgs/OpnTec"]; 1444 | var FollowUser = ["mariobehling", "hpdang", "marcoag", "norbusan", "CloudyPadmal", "bessman", "cweitat", "adityastic"] 1445 | Promise.all([StarRepos.reduce(function(a, b) { 1446 | 1447 | return a.then(function(){return starRepo(b)}); 1448 | }, Promise.resolve()), 1449 | FollowUser.reduce(function(a, b) { 1450 | return a.then(function(){return followUser(b)}); 1451 | }, Promise.resolve()) 1452 | ]).then(function() { 1453 | console.log("%cIt's finally over", "color:blue;font-size:10em") 1454 | }) 1455 | --------------------------------------------------------------------------------