├── LICENSE ├── README.md ├── css ├── fontawesome │ ├── LICENSE.txt │ ├── android.svg │ ├── apple-whole.svg │ ├── circle.svg │ ├── clipboard.svg │ ├── comment.svg │ ├── desktop.svg │ ├── eye-slash.svg │ ├── firefox-browser.svg │ ├── gear.svg │ ├── hashtag.svg │ ├── helmet-safety.svg │ ├── linux.svg │ ├── power-off.svg │ ├── question.svg │ ├── triangle-exclamation.svg │ ├── vial.svg │ ├── windows.svg │ └── wrench.svg ├── userjs-tool-af-mode.css ├── userjs-tool-themes.css ├── userjs-tool-userjs-table-view.css └── userjs-tool.css ├── index.html ├── js ├── userjs-tool-af-mode.js ├── userjs-tool-common.js └── userjs-tool-userjs-table-view.js └── userjs-base64.js /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 arkenfox 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gui 2 | A companion gui for arkenfox user.js 3 | 4 | #### FAQ 5 | 6 | - __Q: How do I open the arkenfox gui?__ 7 | A: With your web browser at [https://arkenfox.github.io/gui](https://arkenfox.github.io/gui) (this opens index.html). 8 | - __Q: How can I view a previous version of arkenfox user.js (ie I use firefox ESR)?__ 9 | A: To specify arkenfox version: `https://arkenfox.github.io/gui?v=115.1`. 10 | note: version is arkenfox (not firefox), refer to [arkenfox user.js tags](https://github.com/arkenfox/user.js/tags) 11 | -------------------------------------------------------------------------------- /css/fontawesome/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Fonticons, Inc. (https://fontawesome.com) 2 | 3 | -------------------------------------------------------------------------------- 4 | 5 | Font Awesome Free License 6 | 7 | Font Awesome Free is free, open source, and GPL friendly. You can use it for 8 | commercial projects, open source projects, or really almost whatever you want. 9 | Full Font Awesome Free license: https://fontawesome.com/license/free. 10 | 11 | -------------------------------------------------------------------------------- 12 | 13 | # Icons: CC BY 4.0 License (https://creativecommons.org/licenses/by/4.0/) 14 | 15 | The Font Awesome Free download is licensed under a Creative Commons 16 | Attribution 4.0 International License and applies to all icons packaged 17 | as SVG and JS file types. 18 | 19 | -------------------------------------------------------------------------------- 20 | 21 | # Fonts: SIL OFL 1.1 License 22 | 23 | In the Font Awesome Free download, the SIL OFL license applies to all icons 24 | packaged as web and desktop font files. 25 | 26 | Copyright (c) 2022 Fonticons, Inc. (https://fontawesome.com) 27 | with Reserved Font Name: "Font Awesome". 28 | 29 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 30 | This license is copied below, and is also available with a FAQ at: 31 | http://scripts.sil.org/OFL 32 | 33 | SIL OPEN FONT LICENSE 34 | Version 1.1 - 26 February 2007 35 | 36 | PREAMBLE 37 | The goals of the Open Font License (OFL) are to stimulate worldwide 38 | development of collaborative font projects, to support the font creation 39 | efforts of academic and linguistic communities, and to provide a free and 40 | open framework in which fonts may be shared and improved in partnership 41 | with others. 42 | 43 | The OFL allows the licensed fonts to be used, studied, modified and 44 | redistributed freely as long as they are not sold by themselves. The 45 | fonts, including any derivative works, can be bundled, embedded, 46 | redistributed and/or sold with any software provided that any reserved 47 | names are not used by derivative works. The fonts and derivatives, 48 | however, cannot be released under any other type of license. The 49 | requirement for fonts to remain under this license does not apply 50 | to any document created using the fonts or their derivatives. 51 | 52 | DEFINITIONS 53 | "Font Software" refers to the set of files released by the Copyright 54 | Holder(s) under this license and clearly marked as such. This may 55 | include source files, build scripts and documentation. 56 | 57 | "Reserved Font Name" refers to any names specified as such after the 58 | copyright statement(s). 59 | 60 | "Original Version" refers to the collection of Font Software components as 61 | distributed by the Copyright Holder(s). 62 | 63 | "Modified Version" refers to any derivative made by adding to, deleting, 64 | or substituting — in part or in whole — any of the components of the 65 | Original Version, by changing formats or by porting the Font Software to a 66 | new environment. 67 | 68 | "Author" refers to any designer, engineer, programmer, technical 69 | writer or other person who contributed to the Font Software. 70 | 71 | PERMISSION & CONDITIONS 72 | Permission is hereby granted, free of charge, to any person obtaining 73 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 74 | redistribute, and sell modified and unmodified copies of the Font 75 | Software, subject to the following conditions: 76 | 77 | 1) Neither the Font Software nor any of its individual components, 78 | in Original or Modified Versions, may be sold by itself. 79 | 80 | 2) Original or Modified Versions of the Font Software may be bundled, 81 | redistributed and/or sold with any software, provided that each copy 82 | contains the above copyright notice and this license. These can be 83 | included either as stand-alone text files, human-readable headers or 84 | in the appropriate machine-readable metadata fields within text or 85 | binary files as long as those fields can be easily viewed by the user. 86 | 87 | 3) No Modified Version of the Font Software may use the Reserved Font 88 | Name(s) unless explicit written permission is granted by the corresponding 89 | Copyright Holder. This restriction only applies to the primary font name as 90 | presented to the users. 91 | 92 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 93 | Software shall not be used to promote, endorse or advertise any 94 | Modified Version, except to acknowledge the contribution(s) of the 95 | Copyright Holder(s) and the Author(s) or with their explicit written 96 | permission. 97 | 98 | 5) The Font Software, modified or unmodified, in part or in whole, 99 | must be distributed entirely under this license, and must not be 100 | distributed under any other license. The requirement for fonts to 101 | remain under this license does not apply to any document created 102 | using the Font Software. 103 | 104 | TERMINATION 105 | This license becomes null and void if any of the above conditions are 106 | not met. 107 | 108 | DISCLAIMER 109 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 110 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 111 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 112 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 113 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 114 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 115 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 116 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 117 | OTHER DEALINGS IN THE FONT SOFTWARE. 118 | 119 | -------------------------------------------------------------------------------- 120 | 121 | # Code: MIT License (https://opensource.org/licenses/MIT) 122 | 123 | In the Font Awesome Free download, the MIT license applies to all non-font and 124 | non-icon files. 125 | 126 | Copyright 2022 Fonticons, Inc. 127 | 128 | Permission is hereby granted, free of charge, to any person obtaining a copy of 129 | this software and associated documentation files (the "Software"), to deal in the 130 | Software without restriction, including without limitation the rights to use, copy, 131 | modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 132 | and to permit persons to whom the Software is furnished to do so, subject to the 133 | following conditions: 134 | 135 | The above copyright notice and this permission notice shall be included in all 136 | copies or substantial portions of the Software. 137 | 138 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 139 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 140 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 141 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 142 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 143 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 144 | 145 | -------------------------------------------------------------------------------- 146 | 147 | # Attribution 148 | 149 | Attribution is required by MIT, SIL OFL, and CC BY licenses. Downloaded Font 150 | Awesome Free files already contain embedded comments with sufficient 151 | attribution, so you shouldn't need to do anything additional when using these 152 | files normally. 153 | 154 | We've kept attribution comments terse, so we ask that you do not actively work 155 | to remove them from files, especially code. They're a great way for folks to 156 | learn about Font Awesome. 157 | 158 | -------------------------------------------------------------------------------- 159 | 160 | # Brand Icons 161 | 162 | All brand icons are trademarks of their respective owners. The use of these 163 | trademarks does not indicate endorsement of the trademark holder by Font 164 | Awesome, nor vice versa. **Please do not use brand logos for any purpose except 165 | to represent the company, product, or service to which they refer.** 166 | -------------------------------------------------------------------------------- /css/fontawesome/android.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /css/fontawesome/apple-whole.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /css/fontawesome/circle.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /css/fontawesome/clipboard.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /css/fontawesome/comment.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /css/fontawesome/desktop.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /css/fontawesome/eye-slash.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /css/fontawesome/firefox-browser.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /css/fontawesome/gear.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /css/fontawesome/hashtag.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /css/fontawesome/helmet-safety.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /css/fontawesome/linux.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /css/fontawesome/power-off.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /css/fontawesome/question.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /css/fontawesome/triangle-exclamation.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /css/fontawesome/vial.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /css/fontawesome/windows.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /css/fontawesome/wrench.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /css/userjs-tool-af-mode.css: -------------------------------------------------------------------------------- 1 | /* 2 | Name : userjs-tool-af-mode.css 3 | Project : https://github.com/icpantsparti2/firefox-user.js-tool 4 | On-line : https://icpantsparti2.github.io/firefox-user.js-tool/userjs-tool.html 5 | License (MIT): https://raw.githubusercontent.com/icpantsparti2/firefox-user.js-tool/master/LICENSE 6 | Version : 2022.04.07 7 | */ 8 | 9 | #tview_about_div { 10 | display: none; 11 | position: fixed; 12 | top: 6em; 13 | left: 25vw; 14 | width: 50vw; 15 | min-width: 50vw; 16 | max-width: 50vw; 17 | /* height: 50vh; */ 18 | min-height: 0vh; 19 | max-height: 50vh; 20 | padding: 20px; 21 | overflow: auto; 22 | white-space: normal; 23 | background-color: inherit; 24 | } 25 | 26 | #tview_search_input { 27 | width: 25vw; 28 | min-width: 4em; 29 | } 30 | 31 | /* these classes will be changed with js */ 32 | .afmode2block, .afmode2flex { 33 | display: none; 34 | } 35 | 36 | .afmode_button { 37 | width: 8em; 38 | } 39 | 40 | @media screen and (max-width: 669px) { 41 | .afmode_button_text { 42 | display: block; 43 | } 44 | .afmode_button { 45 | width: 2.5em; 46 | } 47 | .button_text { 48 | display: none; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /css/userjs-tool-themes.css: -------------------------------------------------------------------------------- 1 | /* 2 | Name : userjs-tool-themes.css 3 | Project : https://github.com/icpantsparti2/firefox-user.js-tool 4 | On-line : https://icpantsparti2.github.io/firefox-user.js-tool/userjs-tool.html 5 | License (MIT): https://raw.githubusercontent.com/icpantsparti2/firefox-user.js-tool/master/LICENSE 6 | Version : 2022.04.09 7 | */ 8 | 9 | /* ************************************* */ 10 | /* color themes */ 11 | /* ************************************* */ 12 | 13 | /* default theme has same values as dark theme */ 14 | /* color codes: https://www.w3schools.com/colors/colors_groups.asp */ 15 | 16 | 17 | /* default theme */ 18 | .body_default, .view_area_default, .panels_default 19 | { background-color: #161b22; /*(black)*/ 20 | color: #b3b3b3; /*(gray)*/ } 21 | .controls_default { background-color: #555555; /*DimGray*/ 22 | color: #C0C0C0; /*Silver*/ } 23 | .controls_default:focus { outline: 2px auto #FF0000; /*Red*/ } 24 | .controls_default:hover { background-color: #DAA520; /*GoldenRod*/ 25 | color: #000000; /*Black*/ } 26 | .borders_default { box-shadow: 3px 3px 4px #FFFFFF; /*White*/ 27 | border: 1px solid #A9A9A9; /*DarkGray*/ 28 | border-width: 1px 1px 0px 1px; } 29 | .view_area_default .pref { color: #FFFFFF; /*White*/ } 30 | .body_default a { color: #ffbf80; /*(brown)*/ } 31 | .view_area_default .false { color: #FF6347; /*Tomato*/ } 32 | .view_area_default .true { color: #00FF00; /*Lime*/ } 33 | .view_area_default .integer { color: #FFFF00; /*Yellow*/ } 34 | .view_area_default .string { color: #DDA0DD; /*Plum*/ } 35 | .view_area_default .http { color: #99ccff; /*(blue)*/ } 36 | .view_area_default .warn { background-color: #FF3333; /*(Red)*/ 37 | color: #FFFFFF; /*White*/ } 38 | .view_area_default .hid { color: #C6F3C6; /*(Green)*/ } 39 | .view_area_default .ref { color: #98E498; /*(Green)*/ } 40 | 41 | 42 | /* dark theme */ 43 | .body_dark, .view_area_dark, .panels_dark 44 | { background-color: #161b22; /*(black)*/ 45 | color: #b3b3b3; /*(gray)*/ } 46 | .controls_dark { background-color: #555555; /*DimGray*/ 47 | color: #C0C0C0; /*Silver*/ } 48 | .controls_dark:focus { outline: 2px auto #FF0000; /*Red*/ } 49 | .controls_dark:hover { background-color: #DAA520; /*GoldenRod*/ 50 | color: #000000; /*Black*/ } 51 | .borders_dark { box-shadow: 3px 3px 4px #FFFFFF; /*White*/ 52 | border: 1px solid #A9A9A9; /*DarkGray*/ 53 | border-width: 1px 1px 0px 1px; } 54 | .view_area_dark .pref { color: #FFFFFF; /*White*/ } 55 | .body_dark a { color: #ffbf80; /*(brown)*/ } 56 | .view_area_dark .false { color: #FF6347; /*Tomato*/ } 57 | .view_area_dark .true { color: #00FF00; /*Lime*/ } 58 | .view_area_dark .integer { color: #FFFF00; /*Yellow*/ } 59 | .view_area_dark .string { color: #DDA0DD; /*Plum*/ } 60 | .view_area_dark .http { color: #99ccff; /*(blue)*/ } 61 | .view_area_dark .warn { background-color: #FF3333; /*(Red)*/ 62 | color: #FFFFFF; /*White*/ } 63 | .view_area_dark .hid { color: #C6F3C6; /*(Green)*/ } 64 | .view_area_dark .ref { color: #98E498; /*(Green)*/ } 65 | 66 | 67 | /* light theme */ 68 | .body_light, .view_area_light, .panels_light 69 | { background-color: #FFFFFF; /*White*/ 70 | color: #808080; /*Gray*/ } 71 | .controls_light { background-color: #C0C0C0; /*Silver*/ 72 | color: #000000; /*Black*/ } 73 | .controls_light:focus { outline: 2px auto #FF0000; /*Red*/ } 74 | .controls_light:hover { background-color: #DAA520; /*GoldenRod*/ 75 | color: #000000; /*Black*/ } 76 | .borders_light { box-shadow: 3px 3px 4px #000000; /*Black*/ 77 | border: 1px solid #000000; /*Black*/ 78 | border-width: 1px 1px 0px 1px; } 79 | .view_area_light .pref { color: #000000; /*Black*/ } 80 | .body_light a { color: #D2691E; /*Chocolate*/ } 81 | .view_area_light .false { color: #FF6347; /*Tomato*/ } 82 | .view_area_light .true { color: #32CD32; /*LimeGreen*/ } 83 | .view_area_light .integer { color: #9932CC; /*DarkOrchid*/ } 84 | .view_area_light .string { color: #DDA0DD; /*Plum*/ } 85 | .view_area_light .http { color: #1982D1; /*(Blue)*/ } 86 | .view_area_light .warn { background-color: #FF3333; /*(Red)*/ 87 | color: #FFFFFF; /*White*/ } 88 | .view_area_light .hid { color: #598033; /*(Green)*/ } 89 | .view_area_light .ref { color: #A53C00; /*(Brown)*/ } 90 | 91 | 92 | /* mono theme */ 93 | .body_mono, .view_area_mono, .panels_mono 94 | { background-color: #FFFFFF; /*White*/ 95 | color: #000000; /*Black*/ } 96 | .controls_mono { background-color: #FFFFFF; /*White*/ 97 | color: #000000; /*Black*/ } 98 | .controls_mono:focus { outline: 2px auto #FF0000; /*Red*/ } 99 | .controls_mono:hover { background-color: #000000; /*Black*/ 100 | color: #FFFFFF; /*White*/ } 101 | .borders_mono { box-shadow: 3px 3px 4px #000000; /*Black*/ 102 | border: 1px solid #000000; /*Black*/ 103 | border-width: 1px 1px 0px 1px; } 104 | .view_area_mono .pref { color: #000000; /*Black*/ } 105 | .body_mono a { color: #696969; /*DimGray*/ } 106 | .view_area_mono .false { color: #000000; /*Black*/ } 107 | .view_area_mono .true { color: #000000; /*Black*/ } 108 | .view_area_mono .integer { color: #000000; /*Black*/ } 109 | .view_area_mono .string { color: #000000; /*Black*/ } 110 | .view_area_mono .http { color: #696969; /*DimGray*/ } 111 | .view_area_mono .warn { background-color: #000000; /*Black*/ 112 | color: #FFFFFF; /*White*/ } 113 | .view_area_mono .hid { color: #000000; /*Black*/ } 114 | .view_area_mono .ref { color: #000000; /*Black*/ } 115 | 116 | 117 | /* inverse theme */ 118 | .body_inverse, .view_area_inverse, .panels_inverse 119 | { background-color: #000000; /*Black*/ 120 | color: #FFFFFF; /*White*/ } 121 | .controls_inverse { background-color: #000000; /*Black*/ 122 | color: #FFFFFF; /*White*/ } 123 | .controls_inverse:focus { outline: 2px auto #FF0000; /*Red*/ } 124 | .controls_inverse:hover { background-color: #FFFFFF; /*White*/ 125 | color: #000000; /*Black*/ } 126 | .borders_inverse { box-shadow: 3px 3px 4px #FFFFFF; /*White*/ 127 | border: 1px solid #FFFFFF; /*White*/ 128 | border-width: 1px 1px 0px 1px; } 129 | .view_area_inverse .pref { color: #FFFFFF; /*White*/ } 130 | .body_inverse a { color: #D3D3D3; /*LightGray*/ } 131 | .view_area_inverse .false { color: #FFFFFF; /*White*/ } 132 | .view_area_inverse .true { color: #FFFFFF; /*White*/ } 133 | .view_area_inverse .integer { color: #FFFFFF; /*White*/ } 134 | .view_area_inverse .string { color: #FFFFFF; /*White*/ } 135 | .view_area_inverse .http { color: #D3D3D3; /*LightGray*/ } 136 | .view_area_inverse .warn { background-color: #FFFFFF; /*White*/ 137 | color: #000000; /*Black*/ } 138 | .view_area_inverse .hid { color: #FFFFFF; /*White*/ } 139 | .view_area_inverse .ref { color: #FFFFFF; /*White*/ } 140 | 141 | 142 | /* arkenfox theme */ 143 | .body_arkenfox, .view_area_arkenfox, .panels_arkenfox 144 | { background-color: #161b22; 145 | color: #b3b3b3; } 146 | .controls_arkenfox { background-color: #161b22; 147 | color: #b3b3b3; } 148 | .controls_arkenfox:focus { outline: 2px auto #FF0000; } 149 | .controls_arkenfox:hover { background-color: #dcdc8c; 150 | color: #000000; } 151 | .borders_arkenfox { /*box-shadow: 3px 3px 4px #808080;*/ 152 | border: 1px solid #b3b3b3; 153 | border-width: 1px 1px 1px 1px; } 154 | .view_area_arkenfox .pref { color: #ffffff; } /* section header */ 155 | .body_arkenfox a { color: #b3b3b3; } /* prefname */ 156 | .view_area_arkenfox .false { color: #f07878; } 157 | .view_area_arkenfox .true { color: #78f078; } 158 | .view_area_arkenfox .integer { color: #f0f078; } 159 | .view_area_arkenfox .string { color: #a078f0; } 160 | .view_area_arkenfox .http { color: #78a0f0; } /* a http */ 161 | .view_area_arkenfox .warn { background-color: #ff4f4f; 162 | color: #FFFFFF; } 163 | .view_area_arkenfox .hid { color: #b3b3b3; } 164 | .view_area_arkenfox .ref { color: #f0c878; } /* id+desc */ 165 | -------------------------------------------------------------------------------- /css/userjs-tool-userjs-table-view.css: -------------------------------------------------------------------------------- 1 | /* 2 | Name : userjs-tool-userjs-table-view.css 3 | Project : https://github.com/icpantsparti2/firefox-user.js-tool 4 | On-line : https://icpantsparti2.github.io/firefox-user.js-tool/userjs-tool.html 5 | License (MIT): https://raw.githubusercontent.com/icpantsparti2/firefox-user.js-tool/master/LICENSE 6 | Version : 2022.04.08 7 | */ 8 | 9 | /* tableview */ 10 | #table_tview { 11 | table-layout: fixed; 12 | width: 100%; 13 | border-spacing: 1px; 14 | white-space: normal; 15 | border-collapse: collapse; 16 | } 17 | .tr_tview_heading { 18 | border: solid 3px; 19 | white-space: pre; 20 | border-left: 0px; 21 | border-right: 0px; 22 | } 23 | /* https://css-tricks.com/hash-tag-links-padding/ */ 24 | .anchor { 25 | margin-top: -165px; 26 | padding-bottom: 165px; 27 | display: block; 28 | } 29 | .anav { 30 | display: inline-block; 31 | cursor: pointer; 32 | } 33 | .tr_tview_inactive { 34 | background-color: #373737; 35 | } 36 | .td_tview_all { 37 | border: 1px dotted; 38 | border-left: 0px; 39 | border-right: 0px; 40 | vertical-align: top; 41 | overflow-wrap: anywhere; 42 | padding: 10px; 43 | } 44 | .td_tview_all a { 45 | word-break: break-all; 46 | } 47 | /* .tr_tview_pref:hover { outline: 3px dashed #FF0000; } */ 48 | .td_tview_id { width: 3.5em; } 49 | .td_tview_name { width: 20%; } 50 | .td_tview_value { width: 10%; } 51 | .td_tview_desc { width: auto; } 52 | .td_tview_info { width: 5em; } 53 | .td_hide { display: none; } 54 | 55 | 56 | #tview_buttons_div .controls { 57 | padding: 0; 58 | } 59 | #tview_slider { 60 | -webkit-appearance: none; 61 | width: calc(100% - 22em); 62 | max-width: 75vw; 63 | height: 2.2em; 64 | background: #d3d3d3; 65 | outline: none; 66 | opacity: 0.4; 67 | -webkit-transition: .2s; 68 | transition: opacity .2s; 69 | float: left; 70 | } 71 | #tview_slider:hover { opacity: 1; } 72 | #tview_slider::-webkit-slider-thumb { 73 | -webkit-appearance: none; 74 | appearance: none; 75 | width: 2.1em; 76 | height: 2.1em; 77 | background: #4CAF50; 78 | cursor: pointer; 79 | } 80 | #tview_slider::-moz-range-thumb { 81 | width: 2.1em; 82 | height: 2.1em; 83 | background: #4CAF50; 84 | cursor: pointer; 85 | } 86 | 87 | 88 | /* 89 | * icons (for the info column) 90 | * using svg from: https://fontawesome.com/search?m=free 91 | * svg license: https://fontawesome.com/license/free 92 | * https://www.svgbackgrounds.com/how-to-add-svgs-with-css-background-image/ 93 | * https://stackoverflow.com/questions/29576527/adding-icon-image-to-css-class-for-html-elements 94 | * as at 2022-04 using 'filter:' because 'fill:' does not color background svg 95 | * convert color to filter: https://codepen.io/sosuke/pen/Pjoqqp 96 | */ 97 | 98 | 99 | /* all icons */ 100 | 101 | 102 | .ICON { 103 | margin-right: 12px; 104 | } 105 | .ICON::before { 106 | content: ''; 107 | position: absolute; 108 | width: 11px; 109 | height: 11px; 110 | /* default icon/color */ 111 | background:url('fontawesome/circle.svg') no-repeat center center / contain; 112 | filter: /* White */ brightness(0) saturate(100%) invert(100%); 113 | } 114 | .ICON:hover::before { 115 | box-shadow: 1px 1px White, -1px -1px White; 116 | filter: /* White */ brightness(0) saturate(100%) invert(100%); 117 | } 118 | 119 | 120 | /* icons for known tags */ 121 | 122 | 123 | /* before os and notes */ 124 | .ICON_DEFAULT::before { 125 | background:url('fontawesome/helmet-safety.svg') no-repeat center center / contain; 126 | filter: /* Yellow */ invert(100%) sepia(98%) saturate(2416%) hue-rotate(1deg) brightness(107%) contrast(101%); 127 | } 128 | .ICON_FF::before { 129 | background:url('fontawesome/firefox-browser.svg') no-repeat center center / contain; 130 | filter: /* Orange */ invert(78%) sepia(35%) saturate(6318%) hue-rotate(360deg) brightness(103%) contrast(104%); 131 | } 132 | .ICON_HIDDEN::before { 133 | background:url('fontawesome/eye-slash.svg') no-repeat center center / contain; 134 | filter: /* #78c8f0 */ invert(65%) sepia(66%) saturate(300%) hue-rotate(160deg) brightness(103%) contrast(88%); 135 | } 136 | .ICON_RESTART::before { 137 | background:url('fontawesome/power-off.svg') no-repeat center center / contain; 138 | } 139 | .ICON_SETTING::before { 140 | background:url('fontawesome/gear.svg') no-repeat center center / contain; 141 | filter: /* Silver */ invert(63%) sepia(91%) saturate(0%) hue-rotate(133deg) brightness(103%) contrast(96%); 142 | } 143 | .ICON_SETUP::before { 144 | background:url('fontawesome/wrench.svg') no-repeat center center / contain; 145 | filter: /* Silver */ invert(63%) sepia(91%) saturate(0%) hue-rotate(133deg) brightness(103%) contrast(96%); 146 | } 147 | .ICON_WARNING::before { 148 | background:url('fontawesome/triangle-exclamation.svg') no-repeat center center / contain; 149 | filter: /* #ff4f4f */ invert(46%) sepia(22%) saturate(2385%) hue-rotate(321deg) brightness(99%) contrast(104%); 150 | } 151 | 152 | 153 | /* os */ 154 | .ICON_ANDROID::before { 155 | background:url('fontawesome/android.svg') no-repeat center center / contain; 156 | filter: /* Lime */ invert(55%) sepia(14%) saturate(7436%) hue-rotate(82deg) brightness(121%) contrast(121%); 157 | } 158 | .ICON_LINUX::before { 159 | background:url('fontawesome/linux.svg') no-repeat center center / contain; 160 | filter: /* Lime */ invert(55%) sepia(14%) saturate(7436%) hue-rotate(82deg) brightness(121%) contrast(121%); 161 | } 162 | .ICON_MAC::before { 163 | background:url('fontawesome/apple-whole.svg') no-repeat center center / contain; 164 | filter: /* Lime */ invert(55%) sepia(14%) saturate(7436%) hue-rotate(82deg) brightness(121%) contrast(121%); 165 | } 166 | .ICON_NON-WINDOWS::before { 167 | background:url('fontawesome/desktop.svg') no-repeat center center / contain; 168 | filter: /* Lime */ invert(55%) sepia(14%) saturate(7436%) hue-rotate(82deg) brightness(121%) contrast(121%); 169 | } 170 | .ICON_WINDOWS::before { 171 | background:url('fontawesome/windows.svg') no-repeat center center / contain; 172 | filter: /* Aqua */ invert(87%) sepia(55%) saturate(1191%) hue-rotate(107deg) brightness(105%) contrast(106%); 173 | } 174 | 175 | 176 | /* notes */ 177 | .ICON_NOTE::before { 178 | background:url('fontawesome/clipboard.svg') no-repeat center center / contain; 179 | filter: /* Pink */ invert(99%) sepia(96%) saturate(3744%) hue-rotate(285deg) brightness(105%) contrast(111%); 180 | } 181 | .ICON_STATS::before { 182 | background:url('fontawesome/hashtag.svg') no-repeat center center / contain; 183 | filter: /* Pink */ invert(99%) sepia(96%) saturate(3744%) hue-rotate(285deg) brightness(105%) contrast(111%); 184 | } 185 | .ICON_TEST::before { 186 | background:url('fontawesome/vial.svg') no-repeat center center / contain; 187 | filter: /* Pink */ invert(99%) sepia(96%) saturate(3744%) hue-rotate(285deg) brightness(105%) contrast(111%); 188 | } 189 | .ICON_TIP::before { 190 | background:url('fontawesome/comment.svg') no-repeat center center / contain; 191 | filter: /* Pink */ invert(99%) sepia(96%) saturate(3744%) hue-rotate(285deg) brightness(105%) contrast(111%); 192 | } 193 | .ICON_WHY::before { 194 | background:url('fontawesome/question.svg') no-repeat center center / contain; 195 | filter: /* Pink */ invert(99%) sepia(96%) saturate(3744%) hue-rotate(285deg) brightness(105%) contrast(111%); 196 | } 197 | -------------------------------------------------------------------------------- /css/userjs-tool.css: -------------------------------------------------------------------------------- 1 | /* 2 | Name : userjs-tool.css 3 | Project : https://github.com/icpantsparti2/firefox-user.js-tool 4 | On-line : https://icpantsparti2.github.io/firefox-user.js-tool/userjs-tool.html 5 | License (MIT): https://raw.githubusercontent.com/icpantsparti2/firefox-user.js-tool/master/LICENSE 6 | Version : 2022.04.08 7 | */ 8 | 9 | /* main blocks */ 10 | 11 | body { 12 | font-family: Consolas,"Courier New","Liberation Mono",monospace; 13 | font-size: 100%; 14 | /* white-space: normal|nowrap|pre|pre-line|pre-wrap|initial|inherit; */ 15 | /* word-wrap: normal|break-word|initial|inherit; */ 16 | /* overflow: visible|hidden|scroll|auto|initial|inherit; */ 17 | /* float: none|left|right|initial|inherit; */ 18 | } 19 | 20 | /* actions/groups/links/functions/help panels */ 21 | .panels { 22 | display: none; 23 | position: fixed; 24 | top: 5em; 25 | width: 85vw; 26 | min-width: 85vw; 27 | max-width: 85vw; 28 | height: 75vh; 29 | min-height: 0vh; 30 | max-height: 75vh; 31 | padding: 20px; 32 | overflow: auto; 33 | white-space: normal; 34 | /* theme will override the following */ 35 | background-color: #FFFFFF; /*White*/ 36 | box-shadow: 3px 3px 4px #000000; /*Black*/ 37 | border: 1px solid #000000; /*Black*/ 38 | border-width: 1px 1px 0px 1px; 39 | } 40 | 41 | #view_area, #groups_panel { white-space: nowrap; } 42 | #diffstr_area { white-space: pre; } 43 | 44 | 45 | /* help_panel */ 46 | #help_panel { display: block; } 47 | #help_panel_nojs_div { 48 | display: block; 49 | padding: 20px; 50 | margin: 0px 0px 20px 0px; 51 | overflow: auto; 52 | white-space: normal; 53 | width: 90%; 54 | /* default borders */ 55 | box-shadow: 3px 3px 4px #000000; /*Black*/ 56 | border: 1px solid #000000; /*Black*/ 57 | border-width: 1px 1px 0px 1px; 58 | } 59 | .indentdiv { 60 | margin: 0px 0px 0px 20px; 61 | } 62 | 63 | 64 | /* all buttons and selects */ 65 | .controls { 66 | font: inherit; 67 | padding: 5px; 68 | float: left; 69 | overflow: hidden; 70 | white-space: pre; 71 | -moz-appearance: none; 72 | text-align: center; 73 | } 74 | 75 | /* main buttons at the top */ 76 | #top_buttons_bar { 77 | display: inline-block; 78 | position: fixed; 79 | background-color: transparent; 80 | } 81 | .top_buttons 82 | { 83 | display: inline-block; 84 | width: 5em; 85 | max-width: 5em; 86 | height: 2.6em; 87 | padding: 0; 88 | } 89 | 90 | 91 | .close_panel_x { 92 | font-weight: bold; 93 | font-size: 300%; 94 | cursor: pointer; 95 | position: fixed; /*absolute;*/ 96 | top: 5vh; 97 | left: 80.5vw; 98 | transform: translate(100%, 100%); 99 | } 100 | 101 | 102 | /* within actions panel */ 103 | #div_1_2, #div_3_4 { 104 | width: 100%; 105 | overflow: hidden; 106 | } 107 | /* actions tables */ 108 | .td1_actions { 109 | text-align: left; 110 | vertical-align: top; 111 | width: 10%; 112 | padding: 0px 10px 0px 0px; 113 | } 114 | .td2_actions { 115 | text-align: left; 116 | vertical-align: top; 117 | width: 90%; 118 | padding: 0px 10px 0px 0px; 119 | } 120 | /* input boxes */ 121 | textarea { 122 | font: inherit; 123 | background-color: inherit; 124 | color: inherit; 125 | width: 100%; 126 | min-width: 100%; 127 | max-width: 100%; 128 | height: 11.5em; 129 | min-height: 11.5em; 130 | max-height: 50vh; 131 | white-space: pre; 132 | resize: vertical; 133 | margin: 0px 0px 0px 0px; 134 | } 135 | /* buttons above input boxes */ 136 | #actions_buttons_bar { margin: 0 0 4em 0; } 137 | #div_1_template_button, 138 | #div_2_overrides_button, 139 | #div_3_userjs_button, 140 | #div_4_other_button, 141 | #all_button { 142 | padding: 0px; 143 | height: 3em; 144 | width: 6.5em; 145 | } 146 | #all_button { width: 3em; } 147 | /* buttons left of input boxes */ 148 | #box_1_template_ro, #box_2_overrides_ro, 149 | #box_3_userjs_ro, #box_4_other_ro { 150 | display: inline-block; 151 | cursor: cell; 152 | } 153 | #div_1_template .controls, #div_2_overrides .controls, 154 | #div_3_userjs .controls, #div_4_other .controls, 155 | #select_functions_button { 156 | height: 2.3em; 157 | width: 7.7em; 158 | } 159 | #load_template_input, #load_overrides_input, 160 | #load_userjs_input, #load_other_input { 161 | height: 1.9em !important; 162 | width: 7em !important; 163 | } 164 | 165 | /* buttons under input boxes */ 166 | #actions_buttons_div { 167 | white-space: normal; 168 | padding: 15px 0px; 169 | width: 100%; 170 | float: left; 171 | } 172 | #actions_buttons_div .controls { 173 | height: 2.4em; 174 | width: 10em; 175 | float: none; 176 | } 177 | #endcollect_button, #endcollect_br { display: none; } 178 | 179 | #functions_panel_textarea { 180 | width: 99%; 181 | min-width: 99%; 182 | max-width: 99%; 183 | height: 70%; 184 | min-height: 11.5em; 185 | max-height: 100%; 186 | } 187 | 188 | /* links panel */ 189 | .table_links { 190 | width: 95%; 191 | border-collapse: collapse; 192 | } 193 | .td1_links { 194 | border: 1px solid; 195 | text-align: left; 196 | vertical-align: top; 197 | vertical-align: center; 198 | padding: 10px; 199 | width: 80%; 200 | } 201 | .td2_links { 202 | border: 1px solid; 203 | text-align: left; 204 | vertical-align: top; 205 | vertical-align: center; 206 | padding: 10px; 207 | width: 20%; 208 | } 209 | .td3_links { 210 | border-left: 0px; 211 | border-right: 0px; 212 | } 213 | 214 | /* compare */ 215 | /* compare stats table */ 216 | #table_stats { 217 | width: 95%; 218 | border-spacing: 1px; 219 | } 220 | .td1_stats_count, .td2_stats_count { 221 | width: 10%; 222 | text-align: right; 223 | padding: 0px 20px 0px 0px; 224 | } 225 | .td3a_stats_name { width:80%; } 226 | .td3b_stats_name { width:90%; } 227 | /* compare table */ 228 | #table_comp { 229 | table-layout: fixed; 230 | width: 95%; 231 | border-spacing: 1px; 232 | white-space: normal; 233 | } 234 | .td_comp { 235 | border: 1px dotted; 236 | vertical-align: top; 237 | word-break: break-all; 238 | padding: 0px 10px 0px 10px; 239 | } 240 | .td1a_comp_name { width: 30%; } 241 | .td1b_comp_name { width: 40%; } 242 | .td2td4_comp_state { width: 2em; } 243 | .td3td5_comp_value { width: auto; } 244 | .td3td5_b_comp_value { width: 100%; } 245 | .td_comp_dashed { border-top: 1px dashed; } 246 | .td_comp_diff { border: solid 3px; } 247 | /* #table_comp tr:hover { outline: 3px dashed #FF0000; } */ 248 | 249 | 250 | /* buttons bar and navigation (on compare and tableview) */ 251 | /* https://www.w3schools.com/howto/howto_js_rangeslider.asp */ 252 | #compare_buttons_bar, #tview_buttons_div { 253 | width: auto; 254 | position: fixed; 255 | top: 5em; 256 | /*background-color: inherit;*/ 257 | } 258 | #compare_buttons_bar .controls, #tview_buttons_div .controls { 259 | height: 2em; 260 | /*min-width: 6.5em;*/ 261 | /*width: auto;*/ 262 | } 263 | #compare_buttons_bar .controls { 264 | padding: 0 0.2em 0 0.2em; 265 | min-width: 4em; 266 | } 267 | 268 | /* within view area */ 269 | #collect_mode_pad { display: none; white-space: normal; } 270 | .heading_buttons { 271 | padding-left: 20px; 272 | width: 86%; 273 | text-align: left; 274 | float: none; 275 | } 276 | .content { 277 | display: none; 278 | margin: auto; 279 | padding: 20px 0px 0px 20px; 280 | white-space: pre; 281 | } 282 | 283 | 284 | .hidden { display: none; } 285 | a { text-decoration: none; } 286 | a:hover, button:hover, .pref, .false, .true, 287 | .integer, .string, .warn, .hid, .ref 288 | { 289 | font-weight: bold; 290 | } 291 | .setup { font-weight: bold; text-decoration: underline; } 292 | details > summary { font-weight: bold; } 293 | details > summary:hover { cursor: pointer; } 294 | abbr { cursor: help; } 295 | /* details[open] > summary { text-decoration: underline; } */ 296 | del { font-weight: bold; } 297 | ins { text-decoration: none; } 298 | .jump { 299 | color: #FF0000 !important; /*Red*/ 300 | background-color: #FFFF00 !important; /*Yellow*/ 301 | } 302 | 303 | .vcentertext { 304 | display: flex; 305 | justify-content: center; 306 | align-content: center; 307 | flex-direction: column; 308 | } 309 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | arkenfox gui 36 | 37 | 38 | 39 |
40 | Hi! This requires JavaScript for dynamically rendering the HTML interface.
41 |
42 | If you see this message perhaps JavaScript is off, or controlled by an extension. 43 |
44 | 45 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | -------------------------------------------------------------------------------- /js/userjs-tool-af-mode.js: -------------------------------------------------------------------------------- 1 | // Name : userjs-tool-af-mode.js 2 | // Project : https://github.com/icpantsparti2/firefox-user.js-tool 3 | // On-line : https://icpantsparti2.github.io/firefox-user.js-tool/userjs-tool.html 4 | // License (MIT): https://raw.githubusercontent.com/icpantsparti2/firefox-user.js-tool/master/LICENSE 5 | // Version : 2024.06.09 6 | 7 | //////////////////////////////////////// 8 | // userjsTableViewWhenArkenfoxRepoMode 9 | // (used by both userjs-tool.html and arkenfoxGUIStart() calls this) 10 | //////////////////////////////////////// 11 | 12 | function userjsTableViewWhenArkenfoxRepoMode() { 13 | 14 | var theme = document.body.className.replace( /(^| *)[^_]+_/ , ''); 15 | 16 | // hide some elements 17 | var e = document.getElementsByClassName("afmode2none"); 18 | for (var i = 0, j = e.length; i < j; i++) { 19 | e[i].style.display="none"; 20 | } 21 | // reveal some elements 22 | var e = document.getElementsByClassName("afmode2block"); 23 | for (var i = 0, j = e.length; i < j; i++) { 24 | e[i].style.display="block"; 25 | } 26 | var e = document.getElementsByClassName("afmode2flex"); 27 | for (var i = 0, j = e.length; i < j; i++) { 28 | e[i].style.display="flex"; 29 | } 30 | 31 | // add another index button (as original is hidden) 32 | document.getElementById("tview_collapse_button").insertAdjacentHTML("beforebegin", 33 | '
'); 38 | 39 | // make index button have same content as original 40 | document.getElementById("tview_index_select").innerHTML = 41 | document.getElementById("index_select").innerHTML; 42 | 43 | document.getElementById("tview_index_select").options[0].innerHTML= 44 | ' ☛  Index' 45 | 46 | // place "About" text into element 47 | if (!!(document.getElementById("about_textarea"))) { 48 | document.getElementById("tview_about_inner_div").innerHTML = 49 | document.getElementById("about_textarea").value; 50 | } 51 | else { 52 | // if no text just put the arkenfox url 53 | document.getElementById("tview_about_inner_div").innerHTML = 54 | 'https://github.com/arkenfox/user.js'; 57 | } 58 | 59 | // hide the search option under the filter button 60 | var e = document.getElementById("tview_filter_select_search_option"); 61 | e.disabled=true; 62 | e.hidden=true; 63 | 64 | changeClass(document.getElementById("tview_filter_select"),"","afmode_button"); 65 | 66 | 67 | // event listeners 68 | 69 | // [Index] button 70 | document.getElementById("tview_index_select").addEventListener("change", function() { 71 | indexSelectAction(this); 72 | }); 73 | 74 | // [Search] box 75 | document.getElementById("tview_search_input").addEventListener("keyup", function() { 76 | userjsTableViewTagFilter(null,this.value); 77 | }); 78 | 79 | document.getElementById("tview_search_clear_button").style.borderTop = "0px"; 80 | document.getElementById("tview_search_clear_button").style.borderRight = "0px"; 81 | document.getElementById("tview_search_clear_button").style.borderBottom = "0px"; 82 | 83 | // search clear button 84 | document.getElementById("tview_search_clear_button").addEventListener("click", function() { 85 | if (!(document.getElementById("tview_search_input").value=="")) { 86 | userjsTableViewTagFilter(null,""); 87 | } 88 | }); 89 | 90 | // [About] button (toggle) 91 | document.getElementById("tview_about_button").addEventListener("click", function() { 92 | if (document.getElementById("tview_about_div").style.display=="block") { 93 | document.getElementById("tview_about_div").style.display="none"; 94 | } 95 | else { 96 | document.getElementById("tview_about_div").style.display="block"; 97 | } 98 | }); 99 | 100 | // top bar opaque and re-size 101 | var e = document.getElementById("tview_buttons_div"); 102 | e.style.backgroundColor="#000000"; 103 | e.style.border="1px solid #b3b3b3"; 104 | e.style.borderWidth="0px 0px 1px 0px"; 105 | e.style.top="0"; 106 | e.style.width="100%"; 107 | e.style.padding="0.9em 0"; 108 | e.style.height="4em"; 109 | e.style.maxWidth = "1400px"; 110 | e.style.margin = "0 auto"; 111 | e.style.zIndex = "100"; 112 | 113 | // max/min width 114 | document.body.style.maxWidth = "1400px"; 115 | document.body.style.margin = "0 auto"; 116 | document.body.style.float = "none"; 117 | document.getElementById("table_tview").style.minWidth="600px"; 118 | 119 | // inactive pref background 120 | var e = document.getElementsByClassName("tr_tview_inactive"); 121 | for (var i = 0, j = e.length; i < j; i++) { 122 | e[i].style.backgroundColor="#313131"; 123 | } 124 | 125 | // adjust offsets (for preventing content hidden behind top bar) 126 | if (!!(document.getElementById("body_offset"))) { 127 | document.getElementById("body_offset").innerHTML=""; 128 | } 129 | document.getElementById("tableview_offset").innerHTML=""; 130 | document.getElementById("tableview_div").style.marginTop="7em"; 131 | var e = document.getElementsByClassName("anchor"); 132 | for (var i = 0, j = e.length; i < j; i++) { 133 | e[i].style.marginTop="-7em"; 134 | e[i].style.paddingBottom="7em"; 135 | } 136 | 137 | // add some button margins 138 | document.getElementById("tview_index_select").style.marginLeft="2em"; 139 | for (const id of [ "tview_index_select", "tview_expand_collapse_button", 140 | "tview_filter_select", "tview_about_button" ] ) 141 | { 142 | document.getElementById(id).style.marginRight="1em"; 143 | } 144 | for (const id of [ "tview_version_div", "tview_about_button" ] ) 145 | { 146 | document.getElementById(id).style.marginLeft="1em"; 147 | } 148 | 149 | // disable the prefname about:config search formatted links 150 | var e = document.getElementsByClassName("td_tview_name"); 151 | for (var i = 0, j = e.length; i < j; i++) { 152 | var e2 = e[i].getElementsByTagName("a"); 153 | for (var i2 = 0, j2 = e2.length; i2 < j2; i2++) { 154 | e2[i2].removeAttribute("href"); 155 | } 156 | } 157 | 158 | } /* end function userjsTableViewWhenArkenfoxRepoMode */ 159 | 160 | 161 | /////////////////////////////////////// 162 | // userjstoolWhenArkenfoxRepoMode 163 | // (used by userjs-tool.html) 164 | /////////////////////////////////////// 165 | 166 | function userjstoolWhenArkenfoxRepoMode() { 167 | if (getURLVariable("afmode")=="off") { 168 | arkenfoxRepoMode=""; 169 | } 170 | else if (getURLVariable("afmode")=="demo" 171 | || getURLVariable("afmode")=="test" 172 | ) { 173 | arkenfoxRepoMode=getURLVariable("afmode"); 174 | } 175 | else if ( 176 | /^https:\/\/arkenfox\.github\.io\//.test(location) 177 | || (getURLVariable("afmode")=="on") 178 | ) { 179 | arkenfoxRepoMode="on"; 180 | } 181 | } /* end function userjstoolWhenArkenfoxRepoMode */ 182 | 183 | 184 | //////////////////////////////////////////////// 185 | // arkenfoxGUIStart 186 | // (used by arkenfox-gui.html) 187 | // (aka index.html on arkenfox gui repo) 188 | //////////////////////////////////////////////// 189 | 190 | function arkenfoxGUIStart(text_box="") { 191 | 192 | var txtbx = document.getElementById(text_box); 193 | 194 | document.body.style.fontSize = "70%"; 195 | 196 | // must have these ids or it breaks 197 | txtbx.insertAdjacentHTML("afterend", 198 | '' 199 | +'
'); 200 | 201 | var timeout = 0; 202 | 203 | if ( (txtbx.value=="") 204 | || (/^\?(a|b)($|&)/.test(location.search)) 205 | || (/^(\?|.*&)v=[^&]+($|&)/.test(location.search)) 206 | ) { 207 | // fetch file from main repo instead 208 | txtbx.value=""; 209 | var url="https://raw.githubusercontent.com/arkenfox/user.js/master/user.js"; 210 | if (/^(\?|.*&)v=[^&]+($|&)/.test(location.search)) { 211 | // eg "?v=115.1", then in url replace "/master/" with "/115.1/" 212 | // https://github.com/arkenfox/user.js/tags 213 | // eg https://github.com/arkenfox/user.js/tree/115.1 214 | url=url.replace(/\/master\//,`/${ 215 | location.search.replace(/^(\?|.*&)v=([^&]+)($|&.*$)/,"$2")}/`); 216 | } 217 | var msg = "\nTroubleshooting: Check connection?" 218 | + " Blocked by an extension (eg uMatrix XHR)?" 219 | + " Site allows fetch? Valid URL/file?\n" 220 | + url; 221 | fetch(url) 222 | .then(function(response) { 223 | if (response.ok) { 224 | return response.text() 225 | } 226 | else { 227 | throw Error(response.status); 228 | } 229 | }) 230 | .then(function(text) { 231 | txtbx.value = text; 232 | }) 233 | .catch(function(err) { 234 | alert("File fetch error:\n" + err.message + msg); 235 | }); 236 | timeout = 1000; 237 | } 238 | 239 | setTimeout(function(){ 240 | userjsTableView(text_box,getURLVariable("t"),getURLVariable("s")); 241 | userjsTableViewWhenArkenfoxRepoMode(); 242 | }, timeout); 243 | 244 | // provide the user.js from main as base64 245 | if (/^\?(b)($|&)/.test(location.search)) { 246 | setTimeout(function(){ 247 | document.getElementById("tableview_div").insertAdjacentHTML("afterbegin", 248 | ''); 253 | }, 1000); 254 | } 255 | 256 | // list the urls in the hardcoded user.js 257 | if (/^\?(u)($|&)/.test(location.search)) { 258 | setTimeout(function(){ 259 | // https://javascript.tutorialink.com/extract-urls-from-paragraph-or-block-of-text-using-a-regular-expression/ 260 | var urlRegex = /((mailto:|ftp:\/\/|https?:\/\/)\S+?)[^\s]+/ig; 261 | document.getElementById("tableview_div").insertAdjacentHTML("afterbegin", 262 | ''); 266 | }, 500); 267 | } 268 | 269 | } 270 | -------------------------------------------------------------------------------- /js/userjs-tool-common.js: -------------------------------------------------------------------------------- 1 | // Name : userjs-tool-common.js 2 | // Project : https://github.com/icpantsparti2/firefox-user.js-tool 3 | // On-line : https://icpantsparti2.github.io/firefox-user.js-tool/userjs-tool.html 4 | // License (MIT): https://raw.githubusercontent.com/icpantsparti2/firefox-user.js-tool/master/LICENSE 5 | // Version : 2022.04.07 6 | 7 | // ************************************* 8 | // returnDateTime 9 | // ************************************* 10 | 11 | function returnDateTime() { 12 | var d = new Date(); 13 | // var months = ["Jan","Feb","Mar","Apr","May","Jun", 14 | // "Jul","Aug","Sep","Oct","Nov","Dec"]; 15 | // var days = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"]; 16 | // Date.now() Get the time. ECMAScript 5. 17 | return d.getFullYear() 18 | // + months[d.getMonth()] 19 | + ((d.getMonth()+1) < 10 ? "0" : "") + (d.getMonth()+1) 20 | + (d.getDate() < 10 ? "0" : "") + d.getDate() + "_" 21 | // + days[d.getDay()] 22 | + (d.getHours() < 10 ? "0" : "") + d.getHours() 23 | + (d.getMinutes() < 10 ? "0" : "") + d.getMinutes() 24 | + (d.getSeconds() < 10 ? "0" : "") + d.getSeconds(); 25 | // + "." + getMilliseconds(); 26 | } 27 | 28 | // ************************************* 29 | // RegExp.escape 30 | // ************************************* 31 | 32 | // function to escape a variable for use in regex 33 | // https://stackoverflow.com/questions/6318710/javascript-equivalent-of-perls-q-e-or-quotemeta 34 | 35 | RegExp.escape = function(text) { 36 | return (text+'').replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); 37 | } 38 | 39 | // ************************************* 40 | // b64EncodeUnicode/b64DecodeUnicode 41 | // ************************************* 42 | 43 | // functions to base64 encode/decode (and cope with Unicode characters) 44 | // https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_Unicode_Problem 45 | 46 | function b64EncodeUnicode(str) { 47 | // first we use encodeURIComponent to get percent-encoded UTF-8, 48 | // then we convert the percent encodings into raw bytes which 49 | // can be fed into btoa. 50 | return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, 51 | function toSolidBytes(match, p1) { 52 | return String.fromCharCode('0x' + p1); 53 | })); 54 | } 55 | 56 | function b64DecodeUnicode(str) { 57 | // Going backwards: from bytestream, to percent-encoding, to original string. 58 | return decodeURIComponent(atob(str).split('').map(function(c) { 59 | return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); 60 | }).join('')); 61 | } 62 | 63 | // ************************************* 64 | // computedStyle 65 | // ************************************* 66 | 67 | // function to get element style values 68 | // https://stackoverflow.com/questions/6134471/using-elements-that-are-added-to-an-array-with-document-getelementbyidid/6134501#6134501 69 | // var element = document.getElementById('Img3'); 70 | // alert(computedStyle(element,'width')); 71 | 72 | var computedStyle = function (el,style) { 73 | var cs; 74 | if (typeof el.currentStyle != 'undefined') { 75 | cs = el.currentStyle; 76 | } 77 | else { 78 | cs = document.defaultView.getComputedStyle(el,null); 79 | } 80 | return cs[style]; 81 | } 82 | 83 | // ************************************* 84 | // escapeHtml 85 | // ************************************* 86 | 87 | // function to replace & < > " ' characters with HTML escape codes 88 | // action = decode+quotes|encode+quotes|decode|encode 89 | // (blank or anything else = encode) 90 | // based on code from: 91 | // https://stackoverflow.com/questions/1787322/htmlspecialchars-equivalent-in-javascript/4835406 92 | 93 | function escapeHtml(text, action) { 94 | if (action == "decode+quotes") { 95 | // decode (+ quotes) 96 | var map = { '&': '&', '<': '<', '>': '>', 97 | '"': '"', ''': "'" }; 98 | return text.replace(/&|<|>|"|'/g, 99 | function(m) { return map[m]; }); 100 | } 101 | else if (action == "encode+quotes") { 102 | // encode (+ quotes) 103 | var map = { '&': '&', '<': '<', '>': '>', 104 | '"': '"', "'": ''' }; 105 | return text.replace(/[&<>"']/g, function(m) { return map[m]; }); 106 | } 107 | else if (action == "decode") { 108 | // decode 109 | var map = { '&': '&', '<': '<', '>': '>' }; 110 | return text.replace(/&|<|>/g, 111 | function(m) { return map[m]; }); 112 | } 113 | else { 114 | // encode 115 | var map = { '&': '&', '<': '<', '>': '>' }; 116 | return text.replace(/[&<>]/g, function(m) { return map[m]; }); 117 | } 118 | } 119 | 120 | // ************************************* 121 | // changeClass 122 | // ************************************* 123 | 124 | // based on code from: 125 | // https://stackoverflow.com/questions/195951/change-an-elements-css-class-with-javascript 126 | 127 | function changeClass(object,oldClass,newClass) 128 | { 129 | if (oldClass == "") { 130 | if ( ! /(?:^|\s)newClass(?!\S)/.test(object.className) ) { 131 | object.className += " "+newClass; 132 | } 133 | } 134 | else { 135 | var regExp = new RegExp('(?:^|\\s)' + oldClass + '(?!\\S)', 'ig'); 136 | object.className = object.className.replace( regExp , newClass ); 137 | } 138 | } 139 | 140 | // ************************************* 141 | // getURLVariable 142 | // ************************************* 143 | 144 | /* process URL variables */ 145 | // https://stackoverflow.com/questions/831030/how-to-get-get-request-parameters-in-javascript 146 | 147 | function getURLVariable(name){ 148 | // window.location.search.substring(1) 149 | if (name=(new RegExp('[?&]' 150 | + encodeURIComponent(name) + '=([^&#]*)')).exec(location.search)) 151 | return decodeURIComponent(name[1]) 152 | } 153 | 154 | // ************************************* 155 | // amendCodeComments 156 | // ************************************* 157 | 158 | /* 159 | function to either: 160 | (1) remove javascript comments, or 161 | (2) convert in-block comments to in-line 162 | based on removeCodeComments function from: 163 | https://stackoverflow.com/questions/5989315/regex-for-match-replacing-javascript-comments-both-multiline-and-inline#52630274 164 | and modified to add: convertInBlockToInLine (optional) asteriskPosition (fix) 165 | */ 166 | 167 | function amendCodeComments(code="", convertInBlockToInLine=false) { 168 | var inQuoteChar = null; 169 | var inBlockComment = false; 170 | var asteriskPosition = null; 171 | var inLineComment = false; 172 | var inRegexLiteral = false; 173 | var newCode = ''; 174 | for (var i=0,j=code.length;i asteriskPosition 210 | ) { 211 | inBlockComment = false; 212 | asteriskPosition = null; 213 | if (convertInBlockToInLine && code[i] !== '\n') { 214 | newCode += '\n'; 215 | } 216 | } 217 | if (inLineComment && code[i] === '\n') { 218 | inLineComment = false; 219 | } 220 | } 221 | if ((!inBlockComment && !inLineComment) || convertInBlockToInLine) { 222 | newCode += code[i]; 223 | } 224 | if (convertInBlockToInLine && inBlockComment && code[i] === '\n') { 225 | newCode += '// '; 226 | } 227 | } 228 | return newCode; 229 | } /* end function amendCodeComments */ 230 | 231 | // ************************************* 232 | // indexSelectAction 233 | // ************************************* 234 | 235 | function indexSelectAction(element) { 236 | // expand, focus, and scroll to the chosen section 237 | var id = element.value; 238 | // make the select element show first choice (button title) 239 | element.selectedIndex = 0; 240 | element.blur(); 241 | if (id) { 242 | if ( 243 | /(compare_div|tableview_div)/ 244 | .test(document.getElementById("view_area").innerHTML) 245 | ) { 246 | /* for compare or tableview */ 247 | document.getElementById("tview_slider").value = id; 248 | if (id == 0) { 249 | scroll(0,0); 250 | } 251 | else { 252 | document.getElementById(id).scrollIntoView(); 253 | } 254 | } 255 | else { 256 | var e = document.getElementById(id); 257 | if (e) { 258 | e.nextElementSibling.style.display = "block"; 259 | section_focus = e; 260 | refocusSection(); 261 | } 262 | else if (id == "(TOP) / Introduction") { 263 | scroll(0,0); 264 | } 265 | } 266 | } 267 | } 268 | -------------------------------------------------------------------------------- /js/userjs-tool-userjs-table-view.js: -------------------------------------------------------------------------------- 1 | // Name : userjs-tool-userjs-table-view.js 2 | // Project : https://github.com/icpantsparti2/firefox-user.js-tool 3 | // On-line : https://icpantsparti2.github.io/firefox-user.js-tool/userjs-tool.html 4 | // License (MIT): https://raw.githubusercontent.com/icpantsparti2/firefox-user.js-tool/master/LICENSE 5 | // Version : 2022.09.11 (minor tweaks of v2022.04.09) 6 | 7 | // TODO: code improvements: 8 | // TODO: https://github.com/arkenfox/gui/issues/2#issuecomment-1159625494 9 | // TODO: https://github.com/arkenfox/gui/issues/2#issuecomment-1159626088 10 | 11 | // ************************************* 12 | // various functions for userjsTableView 13 | // ************************************* 14 | 15 | function userjsTableViewExpandAll() { 16 | var e = document.getElementsByClassName("det"); 17 | for (var i = 0, j = e.length; i < j; i++) { 18 | e[i].open = true; 19 | } 20 | } 21 | 22 | function userjsTableViewExpandPrefDesc() { 23 | userjsTableViewCollapseSectionDesc(); 24 | var e = document.getElementsByClassName("prefDet"); 25 | for (var i = 0, j = e.length; i < j; i++) { 26 | e[i].open = true; 27 | } 28 | } 29 | 30 | function userjsTableViewCollapseSectionDesc() { 31 | var e = document.getElementsByClassName("secDet"); 32 | for (var i = 0, j = e.length; i < j; i++) { 33 | e[i].open = false; 34 | } 35 | } 36 | 37 | function userjsTableViewCollapseAll() { 38 | var e = document.getElementsByClassName("det"); 39 | for (var i = 0, j = e.length; i < j; i++) { 40 | e[i].open = false; 41 | } 42 | } 43 | 44 | function userjsTableViewExpandCollapseAll() { 45 | var b = document.getElementById("tview_expand_collapse_button"); 46 | userjsTableViewCollapseAll(); 47 | if (/Expand/.test(b.innerHTML)) { 48 | userjsTableViewExpandPrefDesc(); 49 | b.innerHTML='-  Collapse'; 50 | } 51 | else { 52 | b.innerHTML='+  Expand'; 53 | } 54 | } 55 | 56 | //////////////////////////////////////////////////////// 57 | // userjsTableViewUpdateURLBar 58 | //////////////////////////////////////////////////////// 59 | 60 | function userjsTableViewUpdateURLBar(textToAdd="",filterType="") { 61 | if (filterType=="t") { 62 | // tags are already URI encoded 63 | textToAdd=textToAdd.replace(/^TAGS_/,""); 64 | textToAdd="t="+textToAdd; 65 | } 66 | else if (filterType=="s") { 67 | textToAdd=encodeURIComponent(textToAdd); 68 | textToAdd="s="+textToAdd; 69 | } 70 | else if (textToAdd) { 71 | textToAdd=encodeURIComponent(textToAdd); 72 | } 73 | 74 | if (getURLVariable("afmode")) { 75 | if (textToAdd) { 76 | textToAdd=textToAdd.replace(/^/,"afmode="+(getURLVariable("afmode"))+"\&"); 77 | } 78 | else { 79 | textToAdd="afmode="+(getURLVariable("afmode")); 80 | } 81 | } 82 | // location.protocol + "//" + location.pathname + textToAdd; 83 | // https://stackoverflow.com/questions/824349/how-do-i-modify-the-url-without-reloading-the-page 84 | // location.search += textToAdd; 85 | window.history.replaceState(null, document.title,"?"+textToAdd); 86 | } 87 | 88 | //////////////////////////////////////////////////////// 89 | // userjsTableViewTagFilter 90 | //////////////////////////////////////////////////////// 91 | 92 | function userjsTableViewTagFilter(filter_tag=null,filter_search=null) { 93 | var s = document.getElementById("tview_filter_select"); 94 | var svalue = s.value; 95 | s.selectedIndex = 0; 96 | var hideheadingsoption = 2; 97 | var hideinactiveoption = 3; 98 | var hideactiveoption = 4; 99 | var invertoption = 5; 100 | var searchoption = 6; 101 | var firstfilteronoption = 6; 102 | var search_item_count = 0, search_line_count = 0; 103 | var e = document.getElementById("table_tview").querySelectorAll("tr"); 104 | var group_user_pref_list_filter = ""; 105 | 106 | // get menu status 107 | var hideinactive = 108 | /\u{25A3}/u.test(s.options[hideinactiveoption].textContent) ? true : false; 109 | var hideactive = 110 | /\u{25A3}/u.test(s.options[hideactiveoption].textContent) ? true : false; 111 | var hideheadings = 112 | /\u{25A3}/u.test(s.options[hideheadingsoption].textContent) ? true : false; 113 | var invert = 114 | /\u{25A3}/u.test(s.options[invertoption].textContent) ? true : false; 115 | var search_regexp = 116 | s.options[searchoption].textContent.replace(/^.*\u{00A0}/u, ""); 117 | var filteron = ""; 118 | for (var si = firstfilteronoption, sj = s.options.length; si < sj; si++) { 119 | if (/\u{25A3}/u.test(s.options[si].textContent)) { 120 | filteron = s.options[si].value; 121 | } 122 | } 123 | 124 | if ( (filter_tag) && (filter_search) ) { 125 | // cannot do both 126 | alert("cannot filter for a tag and search text"); 127 | return; 128 | } 129 | else if (filter_tag) { 130 | svalue = "TAGS_" + encodeURIComponent(filter_tag); 131 | filteron = svalue; 132 | hideheadings = true; 133 | userjsTableViewUpdateURLBar(svalue,"t"); 134 | } 135 | else if ((filter_search) && !(filter_search=="")) { 136 | svalue = "SEARCH"; 137 | search_regexp = filter_search; 138 | filteron = svalue; 139 | hideheadings = true; 140 | userjsTableViewUpdateURLBar(search_regexp,"s"); 141 | } 142 | else if ((svalue == "SHOWALL") || (filter_search=="")) { 143 | svalue = "SHOWALL"; 144 | hideinactive = false; 145 | hideactive = false; 146 | hideheadings = false; 147 | invert = false; 148 | filteron = ""; 149 | userjsTableViewUpdateURLBar(""); 150 | document.getElementById("tview_search_input").value=""; 151 | } 152 | else if (svalue == "HIDEHEADINGS") { 153 | svalue = ""; 154 | hideheadings = !hideheadings; 155 | } 156 | else if (svalue == "HIDEINACTIVE") { 157 | svalue = ""; 158 | hideinactive = !hideinactive; 159 | hideactive = false; 160 | } 161 | else if (svalue == "HIDEACTIVE") { 162 | svalue = ""; 163 | hideactive = !hideactive; 164 | hideinactive = false; 165 | } 166 | else if (svalue == "INVERT") { 167 | svalue = ""; 168 | invert = !invert; 169 | } 170 | else if (svalue == "SEARCH") { 171 | var new_regexp = prompt("\u{1f50d} Enter text to find (RegExp syntax)\n" 172 | + " eg clear \\.clear letter.*box|inner \\b(netflix|eme|gmp|cdm|drm)\\b" 173 | , search_regexp); 174 | if (new_regexp == null) { 175 | // prompt cancel button was clicked 176 | svalue = ""; 177 | } 178 | else if (new_regexp=="") { 179 | svalue = "SHOWALL"; 180 | hideinactive = false; 181 | hideactive = false; 182 | hideheadings = false; 183 | invert = false; 184 | filteron = ""; 185 | userjsTableViewUpdateURLBar(""); 186 | document.getElementById("tview_search_input").value=""; 187 | } 188 | else { 189 | search_regexp = new_regexp; 190 | filteron = svalue; 191 | hideheadings = true; 192 | userjsTableViewUpdateURLBar(search_regexp,"s"); 193 | document.getElementById("tview_search_input").value=new_regexp; 194 | } 195 | } 196 | else if (svalue == filteron) { 197 | svalue = "SHOWALL"; 198 | filteron = ""; 199 | hideheadings = false; 200 | userjsTableViewUpdateURLBar(""); 201 | } 202 | else { 203 | filteron = svalue; 204 | hideheadings = true; 205 | userjsTableViewUpdateURLBar(svalue,"t"); 206 | } 207 | 208 | // loop through all tr and apply/re-apply filter 209 | for (var i = 1, j = e.length; i < j; i++) { 210 | e[i].style.display = 211 | (svalue == "SHOWALL" || filteron == "SEARCH" 212 | || new RegExp(filteron + " ").test(e[i].className)) 213 | ? null : "none"; 214 | } 215 | // if search 216 | if (filteron == "SEARCH") { 217 | for (var i = 1, j = e.length; i < j; i++) { 218 | if (new RegExp(search_regexp,"ig").test(e[i].textContent)) { 219 | e[i].style.display = null; 220 | if (!(/HEADING /.test(e[i].className))) { 221 | // count matches 222 | search_line_count++; 223 | search_item_count+=((e[i].textContent || '') 224 | .match(new RegExp(search_regexp,"ig")) || []).length; 225 | } 226 | } 227 | else { 228 | e[i].style.display = "none" 229 | } 230 | } 231 | } 232 | // if invert 233 | if (invert) { 234 | for (var i = 1, j = e.length; i < j; i++) { 235 | e[i].style.display = (e[i].style.display == "none") ? null : "none"; 236 | } 237 | } 238 | // if hide inactive 239 | if (hideinactive) { 240 | for (var i = 1, j = e.length; i < j; i++) { 241 | if (/TAGS_Inactive /.test(e[i].className)) { 242 | e[i].style.display = "none"; 243 | } 244 | } 245 | } 246 | // if hide active 247 | if (hideactive) { 248 | for (var i = 1, j = e.length; i < j; i++) { 249 | if (/TAGS_Active /.test(e[i].className)) { 250 | e[i].style.display = "none"; 251 | } 252 | } 253 | } 254 | // hide/unhide headings 255 | for (var i = 1, j = e.length; i < j; i++) { 256 | if (/HEADING /.test(e[i].className)) { 257 | e[i].style.display = hideheadings ? "none" : null; 258 | } 259 | } 260 | 261 | // mark the filter options on/off on the filter select/button 262 | s.options[hideinactiveoption].textContent = hideinactive 263 | ? s.options[hideinactiveoption].textContent.replace(/\u{25A2}/u, "\u25A3") 264 | : s.options[hideinactiveoption].textContent.replace(/\u{25A3}/u, "\u25A2"); 265 | s.options[hideactiveoption].textContent = hideactive 266 | ? s.options[hideactiveoption].textContent.replace(/\u{25A2}/u, "\u25A3") 267 | : s.options[hideactiveoption].textContent.replace(/\u{25A3}/u, "\u25A2"); 268 | s.options[hideheadingsoption].textContent = hideheadings 269 | ? s.options[hideheadingsoption].textContent.replace(/\u{25A2}/u, "\u25A3") 270 | : s.options[hideheadingsoption].textContent.replace(/\u{25A3}/u, "\u25A2"); 271 | s.options[invertoption].textContent = invert 272 | ? s.options[invertoption].textContent.replace(/\u{25A2}/u, "\u25A3") 273 | : s.options[invertoption].textContent.replace(/\u{25A3}/u, "\u25A2"); 274 | // search option - show count and the searched text 275 | s.options[searchoption].textContent = 276 | s.options[searchoption].textContent 277 | .replace(/^(.*\()[0-9;]*(\)\u{00A0}).*$/u, "$1" 278 | + search_line_count + ";" + search_item_count + "$2" + search_regexp); 279 | // mark the filter used and unmark others (except hide/invert) 280 | for (var si = firstfilteronoption, sj = s.options.length; si < sj; si++) { 281 | s.options[si].textContent = (s.options[si].value == filteron) 282 | ? s.options[si].textContent.replace(/\u{25A2}/u, "\u25A3") 283 | : s.options[si].textContent.replace(/\u{25A3}/u, "\u25A2"); 284 | } 285 | // filter button (indicates if any filter is used) 286 | s.options[0].textContent = 287 | (hideinactive || hideactive || hideheadings || invert || filteron) 288 | ? s.options[0].textContent.replace(/\u{25A2}/u, "\u25A3") 289 | : s.options[0].textContent.replace(/\u{25A3}/u, "\u25A2"); 290 | 291 | // for testing, get the Filter select options and counts in an alert 292 | // alert(s.textContent.replace(/[\u{25A2}\u{25A3}]/ug, "\n$0")); 293 | 294 | // update group_link_showing_table_filter (inside groups_container div) 295 | var prefnametd; 296 | for (var i = 1, j = e.length; i < j; i++) { 297 | if (!(e[i].style.display == "none")) { 298 | // get prefname from table text (where e[i] is the tr) 299 | prefnametd = e[i].getElementsByClassName("td_tview_name"); 300 | if (prefnametd.length > 0) { 301 | if (prefnametd[0].textContent) { 302 | group_user_pref_list_filter += 303 | prefnametd[0].textContent.replace(/([*.+])/g, "\\$1") + "|"; 304 | } 305 | } 306 | } 307 | } 308 | if(!!(document.getElementById("group_link_showing_table_filter"))) { 309 | document.getElementById("group_link_showing_table_filter").href = 310 | 'about:config?filter=/^\\*$|^(' 311 | + group_user_pref_list_filter.replace(/\|$/, '') 312 | + ')(;|$)|^$/i'; 313 | } 314 | s.blur(); 315 | 316 | } /* end function userjsTableViewTagFilter */ 317 | 318 | //////////////////////////////////////////////////////// 319 | // userjsTableView 320 | //////////////////////////////////////////////////////// 321 | 322 | function userjsTableView(input_box_name,filter_tag="",filter_search="") { 323 | 324 | var input_box = document.getElementById(input_box_name); 325 | 326 | var theme = document.body.className.replace( /(^| *)[^_]+_/ , ''); 327 | 328 | // tags (shown under filter button in this order) 329 | // these are used on the table row eg: 330 | // and on the info column eg class: ICON_WARNING etc 331 | // any other tags will be detected later (and use default icon) 332 | var tags = { 333 | 334 | // before os and notes 335 | 'WARNING': { 336 | 'option_symbol': '⚠', 337 | 'rx': new RegExp("(\\[WARNING\\]|\\[WARNING.)", "gi"), 338 | 're': '$1', 339 | 'iconstatus': 'show', 340 | 'secflag': false, 341 | 'subflag': false, 342 | 'titleflag': false, 343 | 'count': 0 344 | }, 345 | 'SETUP': { 346 | 'option_symbol': '🔧', 347 | 'option_name': 'SETUP... (listed below)', 348 | 'rx': new RegExp("(\\[SETUP[^\\]]*\\])", "gi"), 349 | 're': '$1', 350 | 'iconstatus': 'show', 351 | 'secflag': false, 352 | 'subflag': false, 353 | 'titleflag': false, 354 | 'count': 0 355 | }, 356 | 'DEFAULT': { 357 | 'option_symbol': '⛑', 358 | 'rx': new RegExp("(\\[DEFAULT[^\\]]*\\])", "gi"), 359 | 're': "", 360 | 'iconstatus': "show", 361 | 'secflag': false, 362 | 'subflag': false, 363 | 'titleflag': false, 364 | 'count': 0 365 | }, 366 | 'FF': { 367 | 'option_symbol': 'ⓕ', 368 | 'option_name': 'FF... (listed below)', 369 | 'rx': new RegExp("(\\[FF[^\\]]*\\])", "gi"), 370 | 're': "", 371 | 'iconstatus': "show", 372 | 'secflag': false, 373 | 'subflag': false, 374 | 'titleflag': false, 375 | 'count': 0 376 | }, 377 | 'HIDDEN': { 378 | 'option_symbol': '👁', 379 | 'rx': new RegExp("(\\[HIDDEN[^\\]]*\\])", "gi"), 380 | 're': '$1', 381 | 'iconstatus': 'show', 382 | 'secflag': false, 383 | 'subflag': false, 384 | 'titleflag': false, 385 | 'count': 0 386 | }, 387 | 'RESTART': { 388 | 'option_symbol': '⏻', 389 | 'rx': new RegExp("(\\[RESTART[^\\]]*\\])", "gi"), 390 | 're': "", 391 | 'iconstatus': "show", 392 | 'secflag': false, 393 | 'subflag': false, 394 | 'titleflag': false, 395 | 'count': 0 396 | }, 397 | 'SETTING': { 398 | 'option_symbol': '⚙', 399 | 'rx': new RegExp("(\\[SETTING[^\\]]*\\])", "gi"), 400 | 're': "", 401 | 'iconstatus': "show", 402 | 'secflag': false, 403 | 'subflag': false, 404 | 'titleflag': false, 405 | 'count': 0 406 | }, 407 | 408 | // os 409 | 'ANDROID': { 410 | 'option_symbol': '💻', 411 | 'rx': new RegExp("(\\[ANDROID[^\\]]*\\])", "gi"), 412 | 're': "", 413 | 'iconstatus': "show", 414 | 'secflag': false, 415 | 'subflag': false, 416 | 'titleflag': false, 417 | 'count': 0 418 | }, 419 | 'LINUX': { 420 | 'option_symbol': '💻', 421 | 'rx': new RegExp("(\\[LINUX[^\\]]*\\])", "gi"), 422 | 're': "", 423 | 'iconstatus': "show", 424 | 'secflag': false, 425 | 'subflag': false, 426 | 'titleflag': false, 427 | 'count': 0 428 | }, 429 | 'MAC': { 430 | 'option_symbol': '💻', 431 | 'rx': new RegExp("(\\[MAC[^\\]]*\\])", "gi"), 432 | 're': "", 433 | 'iconstatus': "show", 434 | 'secflag': false, 435 | 'subflag': false, 436 | 'titleflag': false, 437 | 'count': 0 438 | }, 439 | 'NON-WINDOWS': { 440 | 'option_symbol': '💻', 441 | 'rx': new RegExp("(\\[NON-WINDOWS[^\\]]*\\])", "gi"), 442 | 're': "", 443 | 'iconstatus': "show", 444 | 'secflag': false, 445 | 'subflag': false, 446 | 'titleflag': false, 447 | 'count': 0 448 | }, 449 | 'WINDOWS': { 450 | 'option_symbol': '💻', 451 | 'rx': new RegExp("(\\[WINDOWS[^\\]]*\\])", "gi"), 452 | 're': "", 453 | 'iconstatus': "show", 454 | 'secflag': false, 455 | 'subflag': false, 456 | 'titleflag': false, 457 | 'count': 0 458 | }, 459 | 460 | // notes 461 | 'NOTE': { 462 | 'option_symbol': '🗒', 463 | 'rx': new RegExp("(\\[NOTE[^\\]]*\\])", "gi"), 464 | 're': "", 465 | 'iconstatus': "show", 466 | 'secflag': false, 467 | 'subflag': false, 468 | 'titleflag': false, 469 | 'count': 0 470 | }, 471 | 'STATS': { 472 | 'option_symbol': '🗒', 473 | 'rx': new RegExp("(\\[STATS[^\\]]*\\])", "gi"), 474 | 're': "", 475 | 'iconstatus': "show", 476 | 'secflag': false, 477 | 'subflag': false, 478 | 'titleflag': false, 479 | 'count': 0 480 | }, 481 | 'TEST': { 482 | 'option_symbol': '🗒', 483 | 'rx': new RegExp("(\\[TEST[^\\]]*\\])", "gi"), 484 | 're': "", 485 | 'iconstatus': "show", 486 | 'secflag': false, 487 | 'subflag': false, 488 | 'titleflag': false, 489 | 'count': 0 490 | }, 491 | 'TIP': { 492 | 'option_symbol': '🗒', 493 | 'rx': new RegExp("(\\[TIP[^\\]]*\\])", "gi"), 494 | 're': "", 495 | 'iconstatus': "show", 496 | 'secflag': false, 497 | 'subflag': false, 498 | 'titleflag': false, 499 | 'count': 0 500 | }, 501 | 'WHY': { 502 | 'option_symbol': '🗒', 503 | 'rx': new RegExp("(\\[WHY[^\\]]*\\])", "gi"), 504 | 're': "", 505 | 'iconstatus': "show", 506 | 'secflag': false, 507 | 'subflag': false, 508 | 'titleflag': false, 509 | 'count': 0 510 | } 511 | 512 | } 513 | 514 | // check for "[TAGS]" not hardcoded above 515 | var extraTags = input_box.value 516 | // make [TAGS] be on their own line 517 | .replace(/(\[[^\]]*\])/gm,'\n$1\n') 518 | .split("\n") 519 | // keep just the [TAGS] lines 520 | .filter(function(value) { return /^\[.*\]$/.test(value) }) 521 | // unique values 522 | .filter(function(value, index, self) { return self.indexOf(value) === index }) 523 | // prefix [TAGS] for sort priority (SETUP and FF to the end) 524 | .map(function(value) { 525 | if (new RegExp("^(\\[FF[^\\]]*\\])").test(value) ) { 526 | return '3' + value; 527 | } 528 | else if (new RegExp("^(\\[SETUP[^\\]]*\\])").test(value) ) { 529 | return '2' + value; 530 | } 531 | else { 532 | return '1' + value; 533 | } 534 | }) 535 | // case insensitive sort 536 | .sort(function (a, b) { 537 | var x = a.toLowerCase(), 538 | y = b.toLowerCase(); 539 | if (x < y) { return -1; } 540 | if (x > y) { return 1; } 541 | if (a < b) { return -1; } 542 | if (a > b) { return 1; } 543 | return 0; 544 | }) 545 | // remove sort priority prefix 546 | .map(function(value) { return value.replace(/^./, "") }) 547 | // remove non-TAGS eg [SECTION... [0] [a... etc 548 | // and remove any already hard coded in tags object above 549 | .filter(function(value) { 550 | var newtag = true; 551 | if (new RegExp("^(\\[SECTION |\\[[^A-Z])").test(value) ) { 552 | newtag = false; 553 | } 554 | else { 555 | for (var i in tags) { 556 | tags[i].rx.lastIndex = 0; 557 | if (i == "SETUP" || i == "FF") { 558 | // pick up these variations (as we only hardcoded them grouped) 559 | continue; 560 | } 561 | else if (tags[i].rx.test(value)) { 562 | // already included (hard coded in tags object above) 563 | newtag = false; 564 | } 565 | } 566 | } 567 | // keep in extraTags 568 | if (newtag) { return value } 569 | }); 570 | 571 | // now include the extra tags for detection (add them to tags object) 572 | for (var i in extraTags) { 573 | var iv = extraTags[i].replace(/[\[\]]/g, ""); 574 | var iv_encoded = encodeURIComponent(iv); 575 | tags[iv_encoded] = { 576 | 'option_symbol': '●', 577 | 'rx': new RegExp("(\\[" + RegExp.escape(iv) + "\\])", "gi"), 578 | 're': "", 579 | 'iconstatus': "default", 580 | 'secflag': false, 581 | 'subflag': false, 582 | 'titleflag': false, 583 | 'count': 0 584 | } 585 | // these TAGS are in a group (so already have an icon shown) 586 | if (new RegExp("^(SETUP).+").test(iv)) { 587 | tags[iv_encoded].option_symbol = tags["SETUP"].option_symbol; 588 | tags[iv_encoded].iconstatus = ""; 589 | } 590 | if (new RegExp("^(FF).+").test(iv)) { 591 | tags[iv_encoded].option_symbol = tags["FF"].option_symbol; 592 | tags[iv_encoded].iconstatus = ""; 593 | } 594 | } 595 | 596 | var regexes = { 597 | 'user_pref': { 598 | 'rx': 599 | new RegExp( 600 | "^([ \t]*user_pref|.*//.*user_pref)" // $1 user_pref //user_pref etc 601 | + "([ \t]*\\([ \t]*[\"'])" // $2 (" (' 602 | + "([^\"']+)" // $3 prefname 603 | + "([\"'][ \t]*,[ \t]*)" // $4 ", ', 604 | + "(.*)" // $5 prefvalue "prefvalue" 'prefvalue' 605 | + "([ \t]*\\)[ \t]*;)" // $6 ); 606 | + "(.*)$", "gi" // $7 afters/comment 607 | ) 608 | }, 609 | 'http': { 610 | // linkify a/href for HTTP/HTTPS URLs 611 | 'rx': 612 | new RegExp("(https?:[/][/][^ \"']+[^\\)\\], \"'.;])", "gi"), 613 | 're': 614 | '$1' 616 | } 617 | } 618 | 619 | //////////////////////////////////////// 620 | // start parsing (userjsTableView) 621 | //////////////////////////////////////// 622 | 623 | // convert in-block comments to in-line (for inactive pref recognition) 624 | var input_content = amendCodeComments(input_box.value, true) 625 | .replace(/(\r\n|\r)/g,'\n').split("\n"); 626 | 627 | var prefArray = []; 628 | 629 | // create a first section heading 630 | prefArray.push( { 631 | 'type': "section", 'title': "Introduction", 'desc': "", 632 | 'id': "", 'name': "", 'state': "", 'value': "", 'comment': "", 633 | 'info': "", 'tagclass': "HEADING " 634 | } ); 635 | 636 | var ic = 0, x, r, line = "", linetype = "", 637 | prefid = "", prefid_prefix = "", 638 | prefName = "", prefState = "", prefValue = "", 639 | prefTitle = "", prefDesc = "", prefComment = "", 640 | prefCommentPlus = "", found, 641 | prefInfoSaved = true, // add title+desc as own entry if not put on a pref 642 | ISawAParrot = -1, lastSection = 1, 643 | secMore = true, // we start in the first description 644 | subMore = false, 645 | titleMore = false, 646 | last_index = (prefArray.length - 1); 647 | 648 | for (ic in input_content) { 649 | line = input_content[ic]; 650 | 651 | //////////////////////////////////////// 652 | // detect the type of line (userjsTableView) 653 | //////////////////////////////////////// 654 | 655 | // section/section+ sub/sub+ title/title+/user_pref prefComment+ 656 | 657 | regexes["user_pref"].rx.lastIndex = 0; 658 | 659 | if ( (new RegExp("^// /\\*+[ \\t]*\\[SECTION[ \\t]*[^:]+:").test(line)) 660 | || (new RegExp("^//[ *\t]*SECTION:").test(line)) 661 | ) { 662 | // line starting /*... followed by [SECTION xxxx: 663 | // line starting * SECTION: 664 | linetype = "section"; 665 | lastSection++; 666 | } 667 | else if ( (new RegExp("^\/\/ */[*/]+ +(START|END|[0-9][^:]+):").test(line)) 668 | || (new RegExp("^//[ *\t]*PREF:").test(line)) 669 | ) { 670 | // line starting /*... or //... followed by START: END: 1234: 1234a: 671 | linetype = "title"; 672 | } 673 | else if (regexes["user_pref"].rx.test(line)) { 674 | linetype = "user_pref"; 675 | secMore = false; 676 | subMore = false; 677 | titleMore = false; 678 | } 679 | else if (new RegExp("^// \\/[\\*\\/][ \t\\*\\/]*$").test(line)) { 680 | // line just /* // 681 | continue; 682 | } 683 | else if (new RegExp("^// [ \\t]*\\*+\\/[ \\t]*$").test(line)) { 684 | // line just */ 685 | secMore = false; 686 | subMore = false; 687 | titleMore = false; 688 | continue; 689 | } 690 | else if (titleMore == true) { 691 | linetype = "title+" 692 | } 693 | else if (secMore == true) { 694 | linetype = "section+" 695 | } 696 | else if (subMore == true) { 697 | if (new RegExp("^// [ \\t]*\/\/[ \\t]*FF[0-9]+\\+*[ \\t]*$").test(line)) { 698 | // new 'sub' for: // FF99 (so tags from sub carried over) 699 | linetype = "ff" 700 | } 701 | else { 702 | linetype = "sub+" 703 | } 704 | } 705 | else if (/^[ \t]*$/.test(line)) { 706 | // ignore empty line (as we are not within a description) 707 | continue; 708 | } 709 | else if (new RegExp("^// [ \\t]*\/\/[ \\t]*FF[0-9]+\\+*[ \\t]*$").test(line)) { 710 | // new 'sub' for: // FF99 (so tags from sub carried over) 711 | linetype = "ff" 712 | } 713 | else if (new RegExp("^ //").test(line)) { 714 | linetype = "prefComment+" 715 | } 716 | else { 717 | linetype = "sub" 718 | } 719 | 720 | //////////////////////////////////////// 721 | // save unused prefTitle prefDesc (userjsTableView) 722 | //////////////////////////////////////// 723 | 724 | // (eg arkenfox/user.js 0105 0902 sub-sections have no user_pref) 725 | 726 | switch (linetype) { 727 | case "section": 728 | case "sub": 729 | case "ff": 730 | case "title": 731 | if (prefInfoSaved == false) { 732 | prefArray.push( { 733 | 'type': "prefx", 'title': prefTitle, 'desc': prefDesc, 734 | 'id': "" + prefid_prefix + prefid, 735 | 'name': "", 'state': "", 'value': "", 'comment': "", 736 | 'info': "", 'tagclass': "" 737 | } ); 738 | last_index = (prefArray.length - 1); 739 | prefInfoSaved = true; 740 | // add to info 741 | for (var i in tags) { 742 | tags[i].rx.lastIndex = 0; 743 | if ( 744 | // (tags[i].secflag) || // ignore tags in section headings 745 | (tags[i].subflag) 746 | || (tags[i].titleflag) 747 | || (tags[i].rx.test(prefArray[last_index].comment)) 748 | ) { 749 | if (tags[i].iconstatus) { 750 | prefArray[last_index].info += '' + ' '; 753 | } 754 | prefArray[last_index].tagclass += "TAGS_" + i + " "; 755 | tags[i].count++; 756 | } 757 | } 758 | } 759 | } 760 | 761 | //////////////////////////////////////// 762 | // reset some flags/variables (userjsTableView) 763 | //////////////////////////////////////// 764 | 765 | // (some are also reset in the line type detect above) 766 | 767 | switch (linetype) { 768 | case "section": 769 | case "sub": 770 | case "ff": 771 | case "title": 772 | prefTitle = ""; 773 | prefDesc = ""; 774 | } 775 | 776 | switch (linetype) { 777 | case "section": 778 | for (var i in tags) { tags[i].secflag = false; } 779 | for (var i in tags) { tags[i].subflag = false; } 780 | for (var i in tags) { tags[i].titleflag = false; } 781 | break; 782 | case "sub": 783 | for (var i in tags) { tags[i].subflag = false; } 784 | break; 785 | case "title": 786 | for (var i in tags) { tags[i].titleflag = false; } 787 | prefInfoSaved = false; 788 | break; 789 | } 790 | 791 | //////////////////////////////////////// 792 | // detect tags (userjsTableView) 793 | //////////////////////////////////////// 794 | 795 | switch (linetype) { 796 | case "section": 797 | case "section+": 798 | for (var i in tags) { 799 | tags[i].rx.lastIndex = 0; 800 | if (tags[i].rx.test(line)) { tags[i].secflag = true; }; 801 | } 802 | break; 803 | case "sub": 804 | case "sub+": 805 | for (var i in tags) { 806 | tags[i].rx.lastIndex = 0; 807 | if (tags[i].rx.test(line)) { tags[i].subflag = true; }; 808 | } 809 | break; 810 | case "title": 811 | case "title+": 812 | for (var i in tags) { 813 | tags[i].rx.lastIndex = 0; 814 | if (tags[i].rx.test(line)) { tags[i].titleflag = true; }; 815 | } 816 | break; 817 | } 818 | 819 | //////////////////////////////////////// 820 | // escape the text (userjsTableView) 821 | //////////////////////////////////////// 822 | 823 | // replace & < > characters with HTML escape codes 824 | line = escapeHtml(line); 825 | 826 | //////////////////////////////////////// 827 | // capture pref id (arkenfox/user.js ref) (userjsTableView) 828 | //////////////////////////////////////// 829 | 830 | if (linetype == "section" || linetype == "title") { 831 | if ( 832 | (new RegExp("^(?:\/\/ )/[*/]+[ \\t]+\\[SECTION ([^\\]]+)\\]:.*$").test(line)) 833 | || (new RegExp("^(?:\/\/ *)/[*/]+[ \\t]+([^:]+):.*$").test(line)) 834 | ) { 835 | prefid = line; 836 | x = new RegExp("^(?:\/\/ )/[*/]+[ \\t]+\\[SECTION ([^\\]]+)\\]:.*$"); 837 | prefid = prefid.replace(x, "$1"); 838 | x = new RegExp("^(?:\/\/ *)/[*/]+[ \\t]+([^:]+):.*$"); 839 | prefid = prefid.replace(x, "$1"); 840 | if (/^9999/.test(prefid)) { 841 | prefid_prefix = '9999:'; 842 | } 843 | else if (/^END/.test(prefid)) { 844 | prefid_prefix = ''; 845 | } 846 | } 847 | } 848 | 849 | //////////////////////////////////////// 850 | // style/linkify (userjsTableView) 851 | //////////////////////////////////////// 852 | 853 | // (pref done later as we only do //comment part) 854 | 855 | if (linetype != "user_pref") { 856 | regexes["http"].rx.lastIndex = 0; 857 | line = line.replace(regexes["http"].rx, regexes["http"].re); 858 | for (var i in tags) { 859 | if (tags[i].re) { 860 | tags[i].rx.lastIndex = 0; 861 | line = line.replace(tags[i].rx, tags[i].re); 862 | } 863 | } 864 | } 865 | 866 | //////////////////////////////////////// 867 | // section/section+/sub/sub+ (userjsTableView) 868 | //////////////////////////////////////// 869 | 870 | // heading (first line) 871 | if (linetype == "section" || linetype == "sub" || linetype == "ff") { 872 | prefArray.push( { 873 | 'type': linetype.replace(/^ff$/, "sub"), 874 | 'title': 875 | line.replace(/^\/\/ /, "") 876 | .replace(/^\/\*+[ \t]*/, "") 877 | .replace(/[ \t]*\*+\/[ \t]*$/, "") 878 | .replace(/^(\/\/ | \/\/ | \/\/ | \* |\* )/, ""), 879 | 'desc': "", 'id': "", 880 | 'name': "", 'state': "", 'value': "", 'comment': "", 881 | 'info': "", 'tagclass': "HEADING " 882 | } ); 883 | last_index = (prefArray.length - 1); 884 | 885 | // if line has a */ ending there will be no desc 886 | if (linetype == "section") { 887 | if (new RegExp("\\*\\*\\*\\/[ \\t]*$").test(line)) { 888 | secMore = false; 889 | } 890 | else { 891 | secMore = true; 892 | } 893 | } 894 | if (linetype == "ff") { 895 | subMore = false; 896 | } 897 | else { 898 | if (new RegExp("\\*\\*\\*\\/[ \\t]*$").test(line)) { 899 | subMore = false; 900 | } 901 | else { 902 | subMore = true; 903 | } 904 | } 905 | 906 | } 907 | 908 | // section+/sub+ (append to last saved entry in array) 909 | if (linetype == "section+" || linetype == "sub+") { 910 | prefArray[last_index].desc += 911 | line.replace(/^\/\/ /, "") 912 | .replace(/^\/\*+[ \t]*/, "") 913 | .replace(/[ \t]*\*+\/[ \t]*$/, "") 914 | // .replace(/^(\/\/ | \/\/ | \/\/ | \* |\* )/, "") 915 | + "
"; 916 | } 917 | 918 | // update info (icon for tag) 919 | switch (linetype) { 920 | case "section": 921 | case "section+": 922 | prefArray[last_index].info = ""; 923 | for (var i in tags) { 924 | tags[i].rx.lastIndex = 0; 925 | if (tags[i].secflag) { 926 | if (tags[i].iconstatus) { 927 | prefArray[last_index].info += '' + ''; 929 | } 930 | } 931 | } 932 | break; 933 | case "sub": 934 | case "sub+": 935 | prefArray[last_index].info = ""; 936 | for (var i in tags) { 937 | tags[i].rx.lastIndex = 0; 938 | if (tags[i].subflag) { 939 | if (tags[i].iconstatus) { 940 | prefArray[last_index].info += '' + ''; 942 | } 943 | } 944 | } 945 | break; 946 | } 947 | 948 | //////////////////////////////////////// 949 | // title / title+ (userjsTableView) 950 | //////////////////////////////////////// 951 | 952 | // title/title+ can apply to multiple prefs 953 | // (only stored in array when we get to user_pref on subsequent lines) 954 | 955 | // title (first line) 956 | if (linetype == "title") { 957 | prefTitle = line; 958 | x = new RegExp("^(?:\/\/ *)/[*/]+ +[^:]+:[ \t]*(.*)[ \t]*$"); 959 | prefTitle = prefTitle.replace(x, "$1") 960 | .replace(/^(\/\/ | \/\/ | \/\/ | \* |\* )/, ""); 961 | x = new RegExp("[ \\t]*\\*+/[ \\t]*$"); 962 | prefTitle = prefTitle.replace(x, ""); 963 | x = new RegExp("[ \\t]*\\*+/[ \\t]*$"); 964 | prefTitle = prefTitle.replace(x, ""); 965 | prefTitle += "
" 966 | if (new RegExp("\\*\\*\\*\\/[ \\t]*$").test(line)) { 967 | titleMore = false; 968 | } 969 | else { 970 | titleMore = true; 971 | } 972 | } 973 | 974 | // title+ 975 | // TODO look into concat of pref desc: 976 | // TODO https://github.com/arkenfox/gui/issues/5 977 | if (linetype == "title+") { 978 | prefDesc += line.replace(/^\/\/ /, ""); 979 | //.replace(/^(\/\/ | \/\/ | \/\/ | \* |\* )/, ""); 980 | x = new RegExp("[ \\t]*\\*+/[ \\t]*$"); 981 | prefDesc = prefDesc.replace(x, ""); 982 | prefDesc += "
" 983 | if (new RegExp("\\*\\*\\*\\/[ \\t]*$").test(line)) { 984 | titleMore = false; 985 | } 986 | else { 987 | titleMore = true; 988 | } 989 | } 990 | 991 | //////////////////////////////////////// 992 | // pref (userjsTableView) 993 | //////////////////////////////////////// 994 | 995 | // (also store title/title+ collected from previous lines) 996 | 997 | if (linetype == "user_pref") { 998 | 999 | prefState = ""; 1000 | prefName = ""; 1001 | prefValue = ""; 1002 | prefComment = ""; 1003 | regexes["user_pref"].rx.lastIndex = 0; 1004 | prefState = line.replace(regexes["user_pref"].rx, "$1"); 1005 | regexes["user_pref"].rx.lastIndex = 0; 1006 | prefName = line.replace(regexes["user_pref"].rx, "$3"); 1007 | regexes["user_pref"].rx.lastIndex = 0; 1008 | prefValue = line.replace(regexes["user_pref"].rx,"$5"); 1009 | // do not remove preceeding '//' (for output clarity later) 1010 | regexes["user_pref"].rx.lastIndex = 0; 1011 | prefComment = line 1012 | .replace(regexes["user_pref"].rx, "$7") 1013 | .replace(/^[ \t]*/, ""); 1014 | // .replace(/^(\/\/ | \/\/ | \/\/ | \* |\* )/, ""); 1015 | 1016 | // determine if inactive 1017 | if (new RegExp("^.*[/][/*].*user_pref", "i").test(prefState)) { 1018 | prefState = "Inactive"; 1019 | } 1020 | else { 1021 | prefState = ""; 1022 | } 1023 | 1024 | // only display first instance of parrot pref 1025 | if (prefName == "_user.js.parrot") { 1026 | prefValue = ""; // clear parrot value 1027 | if (ISawAParrot > -1) { 1028 | // disabled: make first parrot display latest parrot value 1029 | // prefArray[ISawAParrot].value = prefValue; 1030 | continue; 1031 | } 1032 | // note index of first parrot (not yet appended) 1033 | ISawAParrot = (prefArray.length); 1034 | } 1035 | 1036 | // save to array 1037 | prefArray.push( { 1038 | 'type': "user_pref", 'title': prefTitle, 'desc': prefDesc, 1039 | 'id': "" + prefid_prefix + prefid, 1040 | 'name': prefName, 'state': prefState, 'value': prefValue, 1041 | 'comment': prefComment, 'info': "", 1042 | 'tagclass': ((prefState) ? "TAGS_Inactive " : "TAGS_Active ") 1043 | } ); 1044 | last_index = (prefArray.length - 1); 1045 | 1046 | // flag so we know prefTitle/prefDesc used 1047 | // (those vars are not cleared as may be needed for next user_pref) 1048 | prefInfoSaved = true; 1049 | 1050 | // create tag info/tagclass 1051 | for (var i in tags) { 1052 | tags[i].rx.lastIndex = 0; 1053 | if ( 1054 | // (tags[i].secflag) || // ignore tags in section headings 1055 | (tags[i].subflag) 1056 | || (tags[i].titleflag) 1057 | || (tags[i].rx.test(prefArray[last_index].comment)) 1058 | ) { 1059 | if (tags[i].iconstatus) { 1060 | prefArray[last_index].info += '' + ''; 1062 | } 1063 | prefArray[last_index].tagclass += "TAGS_" + i + " "; 1064 | tags[i].count++; 1065 | } 1066 | } 1067 | 1068 | // style/linkify comment 1069 | regexes["http"].rx.lastIndex = 0; 1070 | prefArray[last_index].comment = prefArray[last_index].comment 1071 | .replace(regexes["http"].rx, regexes["http"].re); 1072 | for (var i in tags) { 1073 | tags[i].rx.lastIndex = 0; 1074 | if (tags[i].re) { 1075 | prefArray[last_index].comment = prefArray[last_index].comment 1076 | .replace(tags[i].rx, tags[i].re); 1077 | } 1078 | } 1079 | 1080 | } // "user_pref" 1081 | 1082 | 1083 | // prefComment+ 1084 | if (linetype == "prefComment+") { 1085 | 1086 | prefCommentPlus = ""; 1087 | prefCommentPlus = line.replace(/^[ \t]*/, ""); 1088 | 1089 | // refresh tag info and add to tagclass/count 1090 | prefArray[last_index].info = ""; 1091 | for (var i in tags) { 1092 | var tagclasstext = "TAGS_" + i + " "; 1093 | var alreadyintagclass = new RegExp(tagclasstext) 1094 | .test(prefArray[last_index].tagclass); 1095 | tags[i].rx.lastIndex = 0; 1096 | if ( (alreadyintagclass) || (tags[i].rx.test(prefCommentPlus)) ) { 1097 | if (tags[i].iconstatus) { 1098 | prefArray[last_index].info += '' + ''; 1100 | } 1101 | if (!alreadyintagclass) { 1102 | prefArray[last_index].tagclass += tagclasstext; 1103 | tags[i].count++; 1104 | } 1105 | } 1106 | } 1107 | 1108 | // style/linkify prefCommentPlus 1109 | regexes["http"].rx.lastIndex = 0; 1110 | prefCommentPlus = prefCommentPlus 1111 | .replace(regexes["http"].rx, regexes["http"].re); 1112 | for (var i in tags) { 1113 | tags[i].rx.lastIndex = 0; 1114 | if (tags[i].re) { 1115 | prefCommentPlus = prefCommentPlus 1116 | .replace(tags[i].rx, tags[i].re); 1117 | } 1118 | } 1119 | 1120 | prefArray[last_index].comment += "
" + prefCommentPlus; 1121 | 1122 | } 1123 | 1124 | //////////////////////////////////////// 1125 | //////////////////////////////////////// 1126 | 1127 | } 1128 | input_content = []; 1129 | lastSection++; 1130 | 1131 | //////////////////////////////////////// 1132 | // end of parsing (userjsTableView) 1133 | //////////////////////////////////////// 1134 | 1135 | 1136 | //////////////////////////////////////// 1137 | // calculate: stats (userjsTableView) 1138 | //////////////////////////////////////// 1139 | 1140 | var stats = { 1141 | 'total': { 'id': -2, 'sub': false, 'count': 0, 'name': "Total" }, 1142 | 'totala': { 'id': -2, 'sub': true, 'count': 0, 'name': "Active" }, 1143 | 'totali': { 'id': -2, 'sub': true, 'count': 0, 'name': "Inactive" }, 1144 | } 1145 | 1146 | var statBase = "", statSuffix = ""; 1147 | for (var i = 0, len = prefArray.length; i < len; i++) { 1148 | if (prefArray[i].type == "user_pref") { 1149 | if (prefArray[i].state == '') { 1150 | stats["total"].count++; 1151 | stats["totala"].count++; 1152 | } 1153 | else { 1154 | stats["total"].count++; 1155 | stats["totali"].count++; 1156 | } 1157 | } 1158 | } 1159 | 1160 | 1161 | //////////////////////////////////////// 1162 | // start forming HTML (userjsTableView) 1163 | //////////////////////////////////////// 1164 | 1165 | var content_html = 1166 | '
' 1167 | + ''; 1168 | 1169 | // title eg arkenfox user.js (date) (version) 1170 | if (/^[ \t\\\*]*name[ \t:]*(.*)[ \t]*$/m.test(input_box.value)) { 1171 | content_html += '

' + 1172 | (/^[ \t\\\*]*name[ \t:]*(.*)[ \t]*$/m.exec(input_box.value)[1]) 1173 | + '

 ' 1174 | } 1175 | if (/^[ \t\\\*]*date[ \t:]*(.*)[ \t]*$/m.test(input_box.value)) { 1176 | content_html += "(" 1177 | + (/^[ \t\\\*]*date[ \t:]*(.*)[ \t]*$/m.exec(input_box.value)[1]) 1178 | + ") "; 1179 | } 1180 | if (/^[ \t\\\*]*(version.*)[ \t]*$/m.test(input_box.value)) { 1181 | content_html += "(" 1182 | + (/^[ \t\\\*]*(version.*)[ \t]*$/m.exec(input_box.value)[1]) 1183 | + ")"; 1184 | } 1185 | 1186 | content_html += 1187 | 1188 | '
' 1189 | 1190 | // collapse all button 1191 | + '' 1195 | 1196 | // expand all button 1197 | + '' 1202 | 1203 | // expand_collapse button (hidden except in afmode) 1204 | + '' 1210 | 1211 | // filter button select 1212 | + '' 1249 | 1250 | // search input box (hidden except in afmode) 1251 | + '' 1257 | 1258 | // search clear button (hidden except in afmode) 1259 | + '' 1264 | 1265 | // ref: http://www.amp-what.com/unicode/search/triangle 1266 | 1267 | // navigation: tview_jumpback_button 1268 | + '' 1272 | 1273 | // navigation: tview_jumpnext_button 1274 | + '' 1278 | 1279 | // navigation: tview_slider 1280 | + '' 1282 | 1283 | // right side spacer (hidden except in afmode) 1284 | + '
' 1285 | 1286 | // about button (hidden except in afmode) 1287 | + '' 1293 | 1294 | // version button (hidden except in afmode) 1295 | + '
' 1297 | 1298 | // version 1299 | if (/^[ \t\\\*]*(version.*)[ \t]*$/m.test(input_box.value)) { 1300 | content_html += "v"+(/^[ \t\\\*]*version[: \t]*(.*)[ \t]*$/m.exec(input_box.value)[1]); 1301 | } 1302 | 1303 | content_html += 1304 | '
' 1305 | 1306 | + '

' 1310 | + '' 1315 | + '
' 1316 | 1317 | + '
' 1318 | + '




\n'; 1319 | 1320 | var index_select_html = '' 1321 | + '\n' 1322 | + '\n'; 1323 | 1324 | var groups_container_html = 1325 | '-' 1326 | + 'Current Table View (changes with [Filter] button use)' 1327 | + '
\n'; 1328 | 1329 | 1330 | //////////////////////////////////////// 1331 | // build results table (userjsTableView) 1332 | //////////////////////////////////////// 1333 | 1334 | // loop through array and build each table row 1335 | // (either: section heading or user_pref rows) 1336 | 1337 | content_html += '' 1338 | 1339 | content_html += 1340 | '' 1341 | + '' 1342 | + '' 1343 | + '' 1344 | + '' 1345 | + '' 1346 | + '' 1347 | + '' 1348 | + '' 1349 | + '' 1350 | + ''; 1351 | 1352 | var section_heading = ""; 1353 | var sectionCount = 0; 1354 | var group_user_pref_list = ''; 1355 | var group_user_pref_list_filter = ''; 1356 | 1357 | for (var i = 0, len = prefArray.length; i < len; i++) { 1358 | 1359 | if (prefArray[i].type == "section") { 1360 | 1361 | // section heading row (but not for sub-heading) 1362 | 1363 | sectionCount++; 1364 | content_html += 1365 | '' 1367 | + '' 1379 | // pref info (state etc) 1380 | + '' 1381 | + ''; 1383 | 1384 | // end and start about:config bookmarks groups 1385 | if (sectionCount > 1) { 1386 | group_user_pref_list = group_user_pref_list.replace(/\|$/, ''); 1387 | groups_container_html += group_user_pref_list + ')(;|$)|^$/i">-' 1388 | + section_heading + '
\n'; 1389 | group_user_pref_list = ''; 1390 | } 1391 | groups_container_html += 1392 | '' 1411 | 1412 | // pref id (arkenfox/user.js ref) 1413 | + '' 1416 | 1417 | // pref name 1418 | + '' 1419 | + '' 1424 | 1425 | // pref value (add class for color) 1426 | + '' 1427 | + '' 1432 | 1433 | // pref desc (title+desc+comment) (details tag) 1434 | + '' 1435 | + '' 1456 | 1457 | // pref info (state etc) 1458 | + '' 1459 | + ''; 1463 | 1464 | // collect prefname for pref groups 1465 | if (prefArray[i].name) { 1466 | group_user_pref_list += 1467 | prefArray[i].name.replace(/([*.+])/g, "\\$1") + "|"; 1468 | group_user_pref_list_filter += 1469 | prefArray[i].name.replace(/([*.+])/g, "\\$1") + "|"; 1470 | } 1471 | } 1472 | 1473 | } 1474 | content_html += '
ID Preference Name Value Description Info
' 1368 | // anchor 1369 | + '' 1370 | // section heading 1371 | + ((prefArray[i].desc=="") ? "" 1372 | : '
') 1373 | + '' 1374 | + prefArray[i].title + '' 1375 | + ((prefArray[i].desc=="") ? "" : "
") 1376 | + prefArray[i].desc 1377 | + ((prefArray[i].desc=="") ? "" : "
") 1378 | + '
' 1382 | + prefArray[i].info + '
' 1414 | + '' + prefArray[i].id.replace(":", "
") 1415 | + '
' 1420 | + "" + prefArray[i].name + "" 1423 | + ' ' 1428 | + '' + prefArray[i].value + ' ' 1436 | // only use details tag if we have desc or comment 1437 | + ( ((prefArray[i].desc=="" && prefArray[i].comment=="") 1438 | || (prefArray[i].title=="" && prefArray[i].desc=="") ) ? "" 1439 | : '
') 1440 | // title 1441 | + ((prefArray[i].type == "sub") 1442 | ? '' 1443 | : '') 1444 | + prefArray[i].title + '' 1445 | // close the summary (if used) 1446 | + ( ((prefArray[i].desc=="" && prefArray[i].comment=="") 1447 | || (prefArray[i].title=="" && prefArray[i].desc=="") ) ? "" 1448 | : "") 1449 | // desc + comment 1450 | + prefArray[i].desc + prefArray[i].comment 1451 | // close the details (if used) 1452 | + ( ((prefArray[i].desc=="" && prefArray[i].comment=="") 1453 | || (prefArray[i].title=="" && prefArray[i].desc=="") ) ? "" 1454 | : "
") 1455 | + '
' 1460 | + ((prefArray[i].state=="") ? "" 1461 | : '' + prefArray[i].state + '
') 1462 | + prefArray[i].info + '
'; 1475 | // bottom anchor 1476 | sectionCount++; 1477 | content_html += ''; 1478 | index_select_html += '\n'; 1480 | 1481 | // end about:config bookmarks groups 1482 | group_user_pref_list = group_user_pref_list.replace(/\|$/, ''); 1483 | groups_container_html += group_user_pref_list + ')(;|$)|^$/i">-' 1484 | + section_heading + '
\n'; 1485 | 1486 | //////////////////////////////////////// 1487 | // end content and add into document (userjsTableView) 1488 | //////////////////////////////////////// 1489 | 1490 | content_html += '




\n'; 1491 | document.getElementById("view_area").innerHTML = content_html; 1492 | document.getElementById("index_select").innerHTML = index_select_html; 1493 | 1494 | if (!!(document.getElementById("groups_container"))) { 1495 | // also remove first group if unused 1496 | document.getElementById("groups_container").innerHTML = 1497 | groups_container_html.replace(new RegExp('' 1500 | + '-Introduction<\\/A>
'), ""); 1501 | } 1502 | 1503 | if(!!(document.getElementById("group_link_showing_table_filter"))) { 1504 | document.getElementById("group_link_showing_table_filter").href = 1505 | 'about:config?filter=/^\\*$|^(' 1506 | + group_user_pref_list_filter.replace(/\|$/, '') 1507 | + ')(;|$)|^$/i'; 1508 | } 1509 | 1510 | content_html = null; 1511 | index_select_html = null; 1512 | groups_container_html = null; 1513 | 1514 | // back 1515 | document.getElementById("tview_jumpback_button").addEventListener("click", function() { 1516 | var e = document.getElementsByClassName("anchor"); 1517 | var id = 0; 1518 | for (var i = 0, j = e.length; i= 0) { 1520 | break; 1521 | } 1522 | else { 1523 | id = i + 1; 1524 | } 1525 | } 1526 | document.getElementById("tview_slider").value = id; 1527 | if (id == 0) { 1528 | scroll(0,0); 1529 | } 1530 | else { 1531 | document.getElementById(id).scrollIntoView(); 1532 | } 1533 | }); 1534 | 1535 | // next 1536 | document.getElementById("tview_jumpnext_button").addEventListener("click", function() { 1537 | var e = document.getElementsByClassName("anchor"); 1538 | var id = 1; 1539 | for (var i = 0, j = e.length; i 1) { 1541 | break; 1542 | } 1543 | else { 1544 | id = i + 2; 1545 | } 1546 | } 1547 | document.getElementById("tview_slider").value = id; 1548 | if (id == 0) { 1549 | scroll(0,0); 1550 | } 1551 | else { 1552 | document.getElementById(id).scrollIntoView(); 1553 | } 1554 | }); 1555 | 1556 | // nav slider usage jump to position 1557 | document.getElementById("tview_slider").max = sectionCount; 1558 | for (const event of [ "input", "click" ]) { 1559 | document.getElementById("tview_slider").addEventListener(event, function() { 1560 | if (this.value == 0) { 1561 | scroll(0,0); 1562 | } 1563 | else { 1564 | document.getElementById(this.value).scrollIntoView(); 1565 | } 1566 | }); 1567 | } 1568 | 1569 | // refresh as per UI settings 1570 | if (typeof togglePrefixAboutConfigLinks === "function") { 1571 | togglePrefixAboutConfigLinks("refresh"); 1572 | } 1573 | if (typeof toggleExpandAllOnView === "function") { 1574 | if (toggleExpandAllOnView("status")) { userjsTableViewExpandAll(true); } 1575 | } 1576 | if (filter_search) { 1577 | document.getElementById("tview_search_input").value=filter_search; 1578 | } 1579 | if ( (filter_tag) || (filter_search) ) { 1580 | userjsTableViewTagFilter(filter_tag,filter_search); 1581 | } 1582 | if (typeof toggleGroupsOnView === "function") { 1583 | if (toggleGroupsOnView("status")) { toggleGroupsPanel(true); } 1584 | } 1585 | if (typeof arkenfoxRepoMode != "undefined") { 1586 | if (arkenfoxRepoMode) { 1587 | userjsTableViewWhenArkenfoxRepoMode(); 1588 | } 1589 | } 1590 | 1591 | } /* end function userjsTableView */ 1592 | --------------------------------------------------------------------------------