Changeset 2628264
- Timestamp:
- 11/11/2021 07:47:43 PM (4 years ago)
- Location:
- child-themes-helper/trunk
- Files:
-
- 10 edited
-
child-themes-helper.php (modified) (3 diffs)
-
classes/class_childThemesHelper.php (modified) (2 diffs)
-
css/style.css (modified) (1 diff)
-
js/class-my-spinner.js (modified) (1 diff)
-
js/edit_file.js (modified) (4 diffs)
-
js/js_common_fn.js (modified) (6 diffs)
-
js/menu.js (modified) (8 diffs)
-
js/pasChildThemes.js (modified) (5 diffs)
-
js/tabs.js (modified) (1 diff)
-
readme.txt (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
child-themes-helper/trunk/child-themes-helper.php
r2544671 r2628264 2 2 /* 3 3 Plugin Name: Child Themes Helper 4 Plugin URI: http ://www.paulswarthout.com/Child-Themes-Helper/4 Plugin URI: https://www.paulswarthout.com/Child-Themes-Helper/ 5 5 Description: Tool to aid the child theme developer. Copies files from the parent theme to the child theme, duplicating the folder structure in the child theme. Directly edit the child theme's files. Create a new child theme from any template theme. 6 Version: 2.2. 26 Version: 2.2.4 7 7 Author: Paul A. Swarthout 8 Author URI: http ://www.PaulSwarthout.com8 Author URI: https://www.PaulSwarthout.com 9 9 License: GPL2 10 10 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 158 158 if (defined("DEMO_CAPABILITY")) { add_action( 'init', 'pas_cth_no_profile_access' ); } 159 159 160 add_action( 'wp_footer', 'pas_cth_flushBuffer' ); // Response Buffering160 add_action( 'wp_footer', __NAMESPACE__ . '\pas_cth_flushBuffer' ); // Response Buffering 161 161 162 162 /* AJAX PHP functions may be found in the 'classes/class_ajax_functions.php' file … … 229 229 } 230 230 231 register_deactivation_hook( __FILE__, 'pas_cth_deactivate' );//Plugin Deactivation231 register_deactivation_hook( __FILE__, __NAMESPACE__ . '\pas_cth_deactivate' );//Plugin Deactivation 232 232 233 233 -
child-themes-helper/trunk/classes/class_childThemesHelper.php
r2544661 r2628264 288 288 The Child Theme Helper plugin was created because I, the developer of {$abbr} would invariably screw it up and my child theme would not work and I would spend hours trying to figure out why. 289 289 <br><br> 290 <h3>The Child Themes Helper plugin has 4 areas of primary functionality.</h3> For more information on each of these, review the information at the top of each tab.290 <h3>The Child Themes Helper plugin has 4 areas of primary functionality.</h3> For more information on each of these, review the information at the top of eachBookWriter.tab. 291 291 <ol> 292 292 <li>Create a new child theme from any of the template themes installed on your website. {$abbr} requires the child theme to exist before you can copy files to it.</li> … … 304 304 This selection <u>does not</u> change which theme is activated. It only specifies to {$abbr} which child/parent theme that it should manipulate. 305 305 <br><br> 306 Once selected, the page will reload and you will be on the Copy/Edit Theme Files tab.306 Once selected, the page will reload and you will be on the Copy/Edit Theme FilesBookWriter.tab. 307 307 308 308 -
child-themes-helper/trunk/css/style.css
r2074973 r2628264 49 49 padding: 20px; 50 50 text-align: left; 51 margin-bottom:50px; 51 52 } 52 53 .pas-grid-item-child { -
child-themes-helper/trunk/js/class-my-spinner.js
r2544671 r2628264 5 5 } 6 6 wait_cursor() { 7 debugger8 7 var spinner; 9 8 var self = this; 10 9 if (this.wait_cursor_count == 0) { 11 10 spinner = this.showSpinner(); 12 spinner.onclick = function () { toc_common.default_cursor(); self.wait_cursor_count = 0; }11 spinner.onclick = function () { self.self.default_cursor(); self.wait_cursor_count = 0; } 13 12 } 14 13 this.wait_cursor_count++; -
child-themes-helper/trunk/js/edit_file.js
r2544661 r2628264 72 72 } 73 73 function pas_cth_js_editFile(event) { 74 pas_cth_spinner.wait_cursor(); 75 74 76 var element = document.getElementById(event.srcElement.dataset.elementid); 75 77 var dataBlock = {}; … … 86 88 "</div>"; 87 89 pas_cth_js_createBox("invalidFileTypeMessage", "", document.getElementsByTagName("body")[0], true).innerHTML += msg; 90 pas_cth_spinner.default_cursor(); 88 91 return; 89 92 } … … 253 256 var fileContents = ""; 254 257 var dataBlock = {}; 258 259 pas_cth_spinner.wait_cursor(); 260 255 261 fileContents = ee.editBox.innerText; // .replace(/</g, "<").replace(/>/g, ">"); 256 262 … … 263 269 pas_cth_js_closeEditFile(); // Closing only clears the div and hides it. Not destroyed. 264 270 var successCallback = function (response) { 271 265 272 if (response.length) { 266 273 pas_cth_js_processResponse(response); 267 274 pas_cth_js_hideWait(); 268 275 } 276 pas_cth_spinner.default_cursor(); 269 277 } 270 278 pas_cth_js_AJAXCall('saveFile', dataBlock, successCallback, pas_cth_js_failureCallback); -
child-themes-helper/trunk/js/js_common_fn.js
r2544661 r2628264 15 15 String.prototype.left = function(n) { return this.substring(0, n); } 16 16 } 17 18 17 function pas_cth_DOMFunctions() { 19 18 var self = this; … … 26 25 e = element; 27 26 } 28 29 27 if (e.parentNode != null) { 30 28 e.parentNode.removeChild(e); … … 46 44 box = document.createElement("DIV"); 47 45 box.id = id; 48 49 46 parent.appendChild(box); 50 47 return box; … … 61 58 if (element == null) { return null; } 62 59 var rect = element.getBoundingClientRect(); 63 64 60 return {left : rect.left, top: rect.top, width : Math.abs(rect.right - rect.left), height : Math.abs(rect.bottom - rect.top), 'element' : element }; 65 61 } … … 73 69 this.searchTree = function (rootElement, tree, pointElement) { 74 70 var found = false; 75 76 71 if (rootElement == pointElement) { 77 72 return true; … … 86 81 87 82 var mousePosition = {x:0, y:0, element:null}; 88 89 83 var pas_cth_library = new pas_cth_DOMFunctions(); 90 84 91 92 85 window.addEventListener("mousemove", function (e) { 93 94 86 mousePosition.x = e.clientX; 95 96 87 mousePosition.y = e.clientY; 97 98 88 }); 99 89 100 90 function pas_cth_js_AJAXCall(action, dataBlock = [], callback = null, error_callback = null) { 101 102 91 var xmlhttp = new XMLHttpRequest(); 103 104 92 var data = new FormData(); 105 106 107 108 93 data.append("action", action); 109 110 111 112 94 if (dataBlock != null) { 113 114 95 Object.keys(dataBlock).forEach(function(key) { 115 116 96 if (key != "action") { 117 data.append(key, dataBlock[key]);118 }97 data.append(key, dataBlock[key]); 98 } 119 99 }); 120 121 } 122 100 } 123 101 xmlhttp.open("POST", ajaxurl, true); 124 125 102 xmlhttp.onreadystatechange = function () { 126 127 103 if (4 == xmlhttp.readyState) { 128 129 104 // The next line strips the admin_ajax.php 1 byte response from the beginning of the response. 130 131 105 // Usually, admin_ajax.php returns a zero. This strips that. 132 133 106 var response = (xmlhttp.responseText.length >= 1 ? xmlhttp.responseText.left(xmlhttp.responseText.length - 1) : ""); 134 135 107 if (xmlhttp.status == 200) { 136 137 108 if (callback != null) { 138 139 109 callback(response); 140 141 110 } 142 143 111 } else { 144 145 112 if (error_callback != null) { 146 147 113 error_callback(xmlhttp.statusText, response); 148 149 114 } else { 150 151 115 alert("AJAX Error:\n\n" + xmlhttp.statusText + "\n\n" + response); 152 153 116 } 154 155 117 } 156 157 } 158 159 } 160 118 } 119 } 161 120 xmlhttp.send(data); 162 163 } 164 121 } 165 122 if (document.getElementById("childGrid") != null && document.getElementById("parentGrid") != null) { 166 167 123 window.addEventListener("resize", function (e) { 168 124 var childGrid = document.getElementById("childGrid") 169 170 125 var parentGrid = document.getElementById("parentGrid") 171 172 173 174 126 // Clears inline styles 175 176 127 if (childGrid != null) { 177 178 128 childGrid.style = ""; 179 180 } 181 129 } 182 130 if (parentGrid != null) { 183 184 131 parentGrid.style = ""; 185 186 } 187 188 } 189 ); 132 } 133 }); 190 134 } 191 135 192 136 var windowFlag = false; 193 194 195 137 196 138 if (window.location.href.indexOf("manage_child_themes") >= 0) { 197 139 window.addEventListener("click", function (e) { 198 199 140 if (windowFlag) { 200 201 141 windowFlag = false; 202 203 142 return; 204 205 } 206 143 } 207 144 if (e.clientX == undefined || e.clientY == undefined) { 208 209 145 return; 210 211 } 212 213 214 146 } 215 147 var pointElement = null; 216 217 148 var actionBox = document.getElementById("pas_cth_actionBox"); 218 219 149 var errorMessageBox = document.getElementsByName("errorMessageBox")[0]; 220 221 222 223 150 pointElement = document.elementFromPoint(e.clientX, e.clientY); 224 225 226 227 151 var tree = pas_cth_library.getElementTree(actionBox); 228 229 152 var found = false; 230 231 153 found = pas_cth_library.searchTree(actionBox, tree, pointElement); 232 233 234 235 154 if (! found) { 236 237 155 tree = pas_cth_library.getElementTree(errorMessageBox); 238 239 156 found = pas_cth_library.searchTree(errorMessageBox, tree, pointElement); 240 241 } 242 243 244 157 } 245 158 if (! found) { 246 247 159 pas_cth_library.kill(actionBox); 248 249 160 pas_cth_library.kill(errorMessageBox); 250 251 } 252 161 } 253 162 }); 254 255 } 256 257 163 } 258 164 259 165 // KillMe kills the error message boxes. 260 261 166 // After the last box has been destroyed, kill the actionBox div too. 262 263 167 function pas_cth_js_killMe(element) { 264 265 168 var elements; 266 267 169 if (element.parentNode != null) { 268 269 170 element.parentNode.removeChild(element); 270 271 } 272 171 } 273 172 element.remove(); 274 275 276 277 173 elements = document.getElementsByName("errorMessageBox"); 278 279 174 if (0 == elements.length) { 280 281 175 var actionBox = document.getElementById("pas_cth_actionBox"); 282 283 176 if (actionBox.parentNode != null) { 284 285 177 actionBox.parentNode.removeChild(actionBox); 286 287 } 288 178 } 289 179 actionBox.remove(); 290 291 } 292 180 } 293 181 } 294 182 295 183 function pas_cth_js_popupMessage(abbr, msg) { 296 297 184 var box = document.getElementById("popupMessageBox") 298 299 185 box.innerHTML = msg; 300 301 186 box.style.position = "fixed"; 302 303 187 box.style.left = mousePosition.x + 100 + "px"; 304 305 188 box.style.top = mousePosition.y - 40 + "px"; 306 307 189 box.style.display = "inline"; 308 309 190 setTimeout(function () { 310 311 191 var p = document.getElementById("popupMessageBox") 312 313 192 p.innerHTML = ""; 314 315 193 p.style.display = "none"; 316 317 194 }, 2000); 318 319 195 } 320 196 321 197 // Process the xmlhttp.responseText that was echo'd during the AJAX call 322 323 198 function pas_cth_js_processResponse(response) { 324 325 199 if ("ABBREVIATION:{" == response.left("ABBREVIATION:{".length).toUpperCase()) { 326 327 200 abbr = response.right(response.length - "ABBREVIATION:{".length); 328 329 201 abbr = abbr.left(abbr.length - 1); 330 331 202 pas_cth_js_popupMessage(abbr, "color saved"); 332 333 203 document.getElementById("popupMessageBox").style.display = "inline"; 334 335 204 } else if ("EDITFILEOUTPUT:{" == response.left("EDITFILEOUTPUT:{".length).toUpperCase()) { 336 337 205 response = response.right(response.length - "EDITFILEOUTPUT:{".length); 338 339 206 response = response.left(response.length - 1); 340 341 207 processEditFile(response); 342 343 208 } else if ("DEBUG:{" == response.left("DEBUG:{".length).toUpperCase()) { 344 345 209 pas_cth_library.kill("pas_cth_actionBox"); 346 347 210 debugResponse = response.right(response.length - "debug:{".length); 348 349 211 debugResponse = debugResponse.left(debugResponse.length - 1); 350 351 212 352 213 box = pas_cth_js_createBox('debugBox', 'debug'); 353 354 214 box.innerHTML = debugResponse; 355 356 215 // Nothing special. We've got output from the PHP function, dump it to the screen. 357 358 216 } else { 359 360 217 if (response.length > 0) { 361 362 218 pas_cth_js_createBox("pas_cth_actionBox", "").innerHTML = response; 363 364 219 windowFlag = true; 365 366 } 367 368 } 369 220 } 221 } 370 222 } 371 223 372 224 function pas_cth_js_showBox() { 373 374 225 return pas_cth_library.createBox("pas_cth_actionBox"); 375 226 } 376 227 377 228 function pas_cth_js_createBox(id, className = "", parent = document.getElementsByTagName("body")[0], clickClose = false) { 378 379 229 var box = pas_cth_library.createBox(id, parent); 380 381 230 if (className.trim.length > 0) { 382 383 231 box.className = className; 384 385 } 386 387 388 232 } 389 233 if (clickClose) { 390 391 234 box.onclick= function () { 392 pas_cth_library.kill(this); } 235 pas_cth_library.kill(this); 236 } 393 237 } else { 394 395 238 var dismissBTN = document.createElement("p") 396 397 239 dismissBTN.setAttribute("id", "dismissBox"); 398 399 240 box.appendChild(dismissBTN); 400 401 241 dismissBTN.innerHTML = "DISMISS"; 402 403 242 dismissBTN.onclick = function () { 404 405 243 pas_cth_library.kill("pas_cth_actionBox"); 406 244 } 407 408 } 409 245 } 410 246 return box; 411 412 247 } 413 248 414 249 function pas_cth_js_addCloseButton(id, parent, text) { 415 416 250 var element = document.createElement("p"); 417 418 251 element.setAttribute("id", id); 419 420 421 252 parent.appendChild(element); 422 423 253 element.innerHTML = text; 424 425 254 element.onclick = function () { 426 427 255 var myParent = this.parentNode; 428 429 256 var myGrandParent = myParent.parentNode; 430 431 432 433 257 if (myGrandParent != null) { 434 435 258 myGrandParent.removeChild(myParent); 436 437 259 myParent.remove(); 438 439 } 440 441 } 442 260 } 261 } 443 262 } 444 263 445 264 function getTopLeftPosition(obj = null) { 446 447 265 if (obj != null) { 448 449 266 return pas_cth_library.getPosition(obj); 450 451 267 } else { 452 453 268 return null; 454 455 } 456 457 } 269 } 270 } -
child-themes-helper/trunk/js/menu.js
r2544661 r2628264 77 77 var position = { 'x' : event.clientX, 'y' : event.clientY }; 78 78 var jsdata = JSON.parse(element.getAttribute("data-jsdata")); 79 var elementID = Date.now(); // clock ticks since midnight at the epoch. Guarantees a unique ID number. 79 /* 80 * Originally used Date.now() for unique IDs. But too many operations are performed per clock tick to make these unique IDs. 81 * Instead, I'm using Math.floor(Math.random() * 1000000.0 ). 82 * Does not guarantee uniqueness, but picking 2 random numbers between 0 and 999,999 makes it highly unlikely 83 * that they would be identical. For this purpose, it's good enough. 84 */ 85 var elementID = Math.floor(Math.random() * 1000000.0); 80 86 var childGrid = document.getElementById("childGrid"); 81 87 var parentGrid = document.getElementById("parentGrid"); 82 88 var themeType = ""; 83 89 90 /* 91 * Are we over a child file, a parent file, or no file? 92 */ 84 93 var obj = new elementInfo(childGrid); 85 94 if (obj.isMouseOver(position)) { … … 94 103 return; 95 104 } 105 106 /* 107 * Grab menu items with the appropriate themeType 108 */ 96 109 var menuElements = []; 97 110 pas_cth_menu.forEach(function (cell) { … … 102 115 element.setAttribute("id", "file_" + elementID); 103 116 117 /* 118 * Look for an existing popup menu. If found, close it. 119 */ 104 120 var box = document.getElementById("popupMenu"); 105 121 if (box != null) { … … 107 123 box.remove(); 108 124 } 125 126 /* 127 * Create new popup menu. 128 */ 109 129 box = document.createElement("DIV"); 110 130 var p = document.createElement("P"); … … 114 134 115 135 116 117 var rect = p.getBoundingClientRect(); 118 var pHeight = rect.height; 119 rect = p.getBoundingClientRect(); 136 /* 137 * Position info the new popup menu. 138 */ 139 // var rect = p.getBoundingClientRect(); 140 // var pHeight = rect.height; 141 // rect = p.getBoundingClientRect(); 120 142 121 143 box.appendChild(p); 122 144 145 /* 146 * Display selected menu items (Edit/Remove for child theme, Copy/View for parent theme) 147 */ 123 148 var anchor = []; 124 125 149 for (var ndx = 0; ndx < menuElements.length; ndx++) { 126 150 p = document.createElement("P"); … … 138 162 box.id = "popupMenu"; 139 163 164 /* 165 * Position new popup menu 166 */ 140 167 var lft = position.x + 25; 141 168 var tp = position.y; … … 144 171 document.getElementsByTagName("body")[0].appendChild(box); 145 172 173 /* 174 * Expand or contract the menu width depending upon its contents 175 */ 146 176 box.style.width = box.scrollWidth; 147 177 148 var pRect = p.getBoundingClientRect();149 var boxRect = box.getBoundingClientRect();178 // var pRect = p.getBoundingClientRect(); 179 // var boxRect = box.getBoundingClientRect(); 150 180 151 181 event.preventDefault(); 152 182 } 183 /* 153 184 function findCorners(objPos) { 154 185 this.adjustCorners = function (adjSize) { … … 166 197 } 167 198 } 199 */ -
child-themes-helper/trunk/js/pasChildThemes.js
r2544661 r2628264 17 17 var jsInput; 18 18 var box; 19 20 pas_cth_spinner.wait_cursor(); 19 21 20 22 … … 40 42 document.getElementById("pas_cth_actionBox").style.display = "inline"; 41 43 windowFlag = true; // Prevents the window.onclick event from closing this prompt. 44 45 pas_cth_spinner.default_cursor(); 46 42 47 return; 43 48 } … … 59 64 break; 60 65 } 66 pas_cth_spinner.default_cursor(); 67 61 68 } 62 69 function pas_cth_js_showWait() { … … 134 141 pas_cth_js_processResponse(response); 135 142 pas_cth_js_hideWait(); 143 pas_cth_spinner.default_cursor(); 136 144 } else { 137 145 location.reload(); … … 142 150 pas_cth_js_showBox().innerHTML = msg; 143 151 pas_cth_js_hideWait(); 152 pas_cth_spinner.default_cursor(); 144 153 } 145 154 /* -
child-themes-helper/trunk/js/tabs.js
r2544661 r2628264 53 53 54 54 body.style.overflow = "hidden"; 55 html.style.overflow = "hidden";56 55 } 57 56 function pas_cth_js_expertMode(element) { -
child-themes-helper/trunk/readme.txt
r2544671 r2628264 4 4 Donate link: https://paypal.me/PaulSwarthout 5 5 Tags: child themes helper, child themes, child theme, child, theme, template theme, parent theme, developers, IIS, Linux, copy files to child theme, create a child theme 6 Requires at least: 4.7.07 Tested up to: 5. 7.28 Stable tag: 2.2. 26 Requires at least: 5.0 7 Tested up to: 5.8.2 8 Stable tag: 2.2.4 9 9 Requires PHP: 5.6.31 10 10 License: GPLv2 or later … … 60 60 61 61 - *Development versions* 62 Versions 2\. 1, 1\.2 are available for download and install.62 Versions 2\.2\.1, 2\.1, 1\.2 are available for download and install. 63 63 64 64 - *Screenshot* … … 93 93 94 94 == Frequently Asked Questions == 95 96 = Sometimes the wait spinner gets stuck and doesn't end. What can I do? 97 98 Yep. I've noticed that. I don't know why that happens. When I stumble on that, and I walk the code, it never happens. In the meantime, there's a really simple solution. Just click on the spinner with your primary mouse button (usually the left) and the wait spinner will disappear. 95 99 96 100 = Do I have to keep the Child Themes Helper installed and/or activated? = … … 124 128 == Changelog == 125 129 130 = 2.2.4 = 131 - Tested the plugin with PHP 8.0.0 and WordPress 5.8.2. 132 133 - Cleaned up code. 134 135 - Fixed a problem with the spinning wait cursors. The code was originally copied from another plugin that I'm developing, but I inadvertantly got some code that doesn't work with this plugin. 136 137 - Introduced namespaces to my code. Slowly removing prefixes from all 'global' functions as they are now localized in the child-themes-helper namespace. 138 139 = 2.2.3 = 140 - Bug fix: Format at the very bottom of the list of files didn't leave room for the popup menu. Extended the page with a bottom margin of 50px. 141 126 142 = 2.2.2 = 127 143 - Oops. Forgot to include the new files before I committed the changes. Everything is included with this one. … … 219 235 == Upgrade Notice == 220 236 237 = 2.2.4 = 238 - Fixed several bugs that were preventing the plugin from loading correctly. 239 - Please submit a trouble ticket when you encounter problems. I was embarrassed that this plugin was broken in the latest version on the WordPress Plugins repository. 240 221 241 = 1.1.3 = 222 242 - Fixed a bug: The path to the child theme's stylesheet in the functions.php was incorrect.
Note: See TracChangeset
for help on using the changeset viewer.