Changeset 2074973
- Timestamp:
- 04/25/2019 07:47:17 PM (7 years ago)
- Location:
- child-themes-helper
- Files:
-
- 67 added
- 2 deleted
- 12 edited
-
assets/icon-256x256.png (added)
-
assets/screenshot-1.JPG (modified) (previous)
-
assets/screenshot-2.JPG (modified) (previous)
-
assets/screenshot-3.jpg (added)
-
assets/screenshot-4.jpg (added)
-
assets/screenshot-5.jpg (added)
-
assets/screenshot-6.jpg (added)
-
assets/screenshot-7.jpg (added)
-
assets/screenshot-8.jpg (added)
-
assets/screenshot-9.jpg (added)
-
tags/1.0 (deleted)
-
tags/1.1.3 (deleted)
-
tags/2.1.1 (added)
-
tags/2.1.1/LICENSE (added)
-
tags/2.1.1/README.md (added)
-
tags/2.1.1/assets (added)
-
tags/2.1.1/assets/fonts (added)
-
tags/2.1.1/assets/fonts/Anton-Regular.ttf (added)
-
tags/2.1.1/assets/fonts/BadScript-Regular.ttf (added)
-
tags/2.1.1/assets/fonts/BalooTammudu-Regular.ttf (added)
-
tags/2.1.1/assets/fonts/ConcertOne-Regular.ttf (added)
-
tags/2.1.1/assets/fonts/Courgette-Regular.ttf (added)
-
tags/2.1.1/assets/fonts/DancingScript-Bold.ttf (added)
-
tags/2.1.1/assets/fonts/GloriaHallelujah.ttf (added)
-
tags/2.1.1/assets/fonts/GreatVibes-Regular.ttf (added)
-
tags/2.1.1/assets/fonts/KaushanScript-Regular.ttf (added)
-
tags/2.1.1/assets/fonts/Lobster-Regular.ttf (added)
-
tags/2.1.1/assets/fonts/Monoton-Regular.ttf (added)
-
tags/2.1.1/assets/fonts/OpenSansCondensed-Bold.ttf (added)
-
tags/2.1.1/assets/fonts/OpenSansCondensed-Light.ttf (added)
-
tags/2.1.1/assets/fonts/OpenSansCondensed-LightItalic.ttf (added)
-
tags/2.1.1/assets/fonts/Orbitron-Black.ttf (added)
-
tags/2.1.1/assets/fonts/Orbitron-Bold.ttf (added)
-
tags/2.1.1/assets/fonts/Oswald-Bold.ttf (added)
-
tags/2.1.1/assets/fonts/Pacifico-Regular.ttf (added)
-
tags/2.1.1/assets/fonts/PermanentMarker-Regular.ttf (added)
-
tags/2.1.1/assets/fonts/Rancho-Regular.ttf (added)
-
tags/2.1.1/assets/fonts/Roboto-Black.ttf (added)
-
tags/2.1.1/assets/fonts/Roboto-Italic.ttf (added)
-
tags/2.1.1/assets/fonts/Roboto-Medium.ttf (added)
-
tags/2.1.1/assets/fonts/Roboto-MediumItalic.ttf (added)
-
tags/2.1.1/assets/fonts/Roboto-Regular.ttf (added)
-
tags/2.1.1/assets/fonts/Sacramento-Regular.ttf (added)
-
tags/2.1.1/assets/fonts/samples (added)
-
tags/2.1.1/child-themes-helper.php (added)
-
tags/2.1.1/classes (added)
-
tags/2.1.1/classes/class-themes.php (added)
-
tags/2.1.1/classes/class_activeThemeInfo.php (added)
-
tags/2.1.1/classes/class_ajax_functions.php (added)
-
tags/2.1.1/classes/class_childThemesHelper.php (added)
-
tags/2.1.1/classes/class_colorPicker.php (added)
-
tags/2.1.1/classes/class_common_functions.php (added)
-
tags/2.1.1/classes/class_createScreenShot.php (added)
-
tags/2.1.1/classes/class_fontMeta.php (added)
-
tags/2.1.1/css (added)
-
tags/2.1.1/css/color_picker_grid.css (added)
-
tags/2.1.1/css/hexdump.css (added)
-
tags/2.1.1/css/menu_page.css (added)
-
tags/2.1.1/css/style.css (added)
-
tags/2.1.1/css/tabs.css (added)
-
tags/2.1.1/js (added)
-
tags/2.1.1/js/color_picker.js (added)
-
tags/2.1.1/js/edit_file.js (added)
-
tags/2.1.1/js/hexdump.js (added)
-
tags/2.1.1/js/js_common_fn.js (added)
-
tags/2.1.1/js/menu.js (added)
-
tags/2.1.1/js/pasChildThemes.js (added)
-
tags/2.1.1/js/tabs.js (added)
-
tags/2.1.1/lib (added)
-
tags/2.1.1/lib/plugin_constants.php (added)
-
tags/2.1.1/readme.txt (added)
-
trunk/child-themes-helper.php (modified) (1 diff)
-
trunk/classes/class_childThemesHelper.php (modified) (8 diffs)
-
trunk/css/style.css (modified) (3 diffs)
-
trunk/js/color_picker.js (modified) (3 diffs)
-
trunk/js/edit_file.js (modified) (3 diffs)
-
trunk/js/js_common_fn.js (modified) (6 diffs)
-
trunk/js/menu.js (modified) (1 diff)
-
trunk/js/pasChildThemes.js (modified) (11 diffs)
-
trunk/js/tabs.js (modified) (1 diff)
-
trunk/readme.txt (modified) (9 diffs)
Legend:
- Unmodified
- Added
- Removed
-
child-themes-helper/trunk/child-themes-helper.php
r2073439 r2074973 9 9 Description: Tool to aid 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. 10 10 11 Version: 2. 1.111 Version: 2.2 12 12 13 13 Author: Paul A. Swarthout -
child-themes-helper/trunk/classes/class_childThemesHelper.php
r2072750 r2074973 217 217 Array( $this, 'pas_cth_tabPage' ), 218 218 219 " ",219 "dashicons-admin-appearance", 220 220 221 221 61 // appears just below the Appearances menu. … … 1376 1376 echo "<div class='createChildThemeBox'>"; 1377 1377 1378 $urlPattern = "^[a-zA-Z]{4,5}\:/{2}[a-zA-Z0-9]{1}[a-zA-Z0-9:/\-\.\&\=\?]+$"; 1378 1379 1379 1380 … … 1402 1403 <br> 1403 1404 1404 <input type='text' name='childThemeName' id='childThemeName' value='' required pattern='^[a-zA-Z][a-zA-Z0-9\-\ ]+' data-message='Child Theme Names must begin with a letter' onblur='javascript:pas_cth_validateField(this);'>1405 <input required type='text' name='childThemeName' id='childThemeName' value='' data-pattern='^[a-zA-Z][a-zA-Z0-9\- ]+$' data-message='Child Theme Name: Names must begin with a letter and contain only numbers letters, spaces, and dashes. The name is required.' onblur='javascript:pas_cth_validateField(this);'> 1405 1406 1406 1407 </label> … … 1414 1415 Theme URI<br> 1415 1416 1416 <input type='text' name='themeURI' id='themeURI' value='' pattern='^[a-zA-Z]{4,5}\://[a-zA-Z0-9:/\-\.\&\=\?]+$' data-message='Invalid URI' onblur='javascript:pas_cth_validateField(this);'>1417 <input type='text' name='themeURI' id='themeURI' value='' data-pattern='{$urlPattern}' data-message='Theme URI: The entered URL is not valid.' onblur='javascript:pas_cth_validateField(this);'> 1417 1418 1418 1419 </label><br> … … 1422 1423 Theme Description<br> 1423 1424 1424 <textarea required id='description' name='description' pattern='^[a-zA-Z0-9\.:;?#\%,\(\)/ ]+$' data-message='You may use letters, numbers, and special characters that you would normally use in writing, only. No HTML or other scripts are allowed here.' onblur='javascript:pas_cth_validateField(this);'></textarea>1425 <textarea id='description' name='description' data-pattern='^[a-zA-Z0-9\.:;?#\%,\(\)/ ]+$' data-message='Description: You may use letters, numbers, and special characters that you would normally use in writing, only. No HTML or other scripts are allowed here.' onblur='javascript:pas_cth_validateField(this);'></textarea> 1425 1426 1426 1427 </label><br> … … 1430 1431 Author Name:<br> 1431 1432 1432 <input type='text' id='authorName' name='authorName' value='' pattern='^[a-zA-Z \.]+$' data-message='upper or lower case, spaces, or periods, only.' onblur='javascript:pas_cth_validateField(this);'>1433 <input type='text' id='authorName' name='authorName' value='' data-pattern='^[a-zA-Z \.]+$' data-message='Author Name: You may use upper or lower case letters, spaces, or periods, only.' onblur='javascript:pas_cth_validateField(this);'> 1433 1434 1434 1435 </label><br> … … 1438 1439 Author URI:<br> 1439 1440 1440 <input type='text' id='authorURI' name='authorURI' value='' pattern='^[a-zA-Z]{4,5}\://[a-zA-Z0-9:/\-\.\&\=\?]+$' data-message='Invalid URI' onblur='javascript:pas_cth_validateField(this);'>1441 <input type='text' id='authorURI' name='authorURI' value='' data-pattern='{$urlPattern}' data-message='Author URI: The entered URL is not valid.' onblur='javascript:pas_cth_validateField(this);'> 1441 1442 1442 1443 </label><br> 1443 1444 1444 <input type='hidden' id='version' name='version' value='0. 0.1' readonly>1445 <input type='hidden' id='version' name='version' value='0.1.0' readonly> 1445 1446 1446 1447 <br> … … 1468 1469 class='blueButton' 1469 1470 1470 onclick='javascript: this.form.reset();'1471 onclick='javascript:pas_cth_js_resetChildThemeForm(this.form)' 1471 1472 1472 1473 > -
child-themes-helper/trunk/css/style.css
r2057158 r2074973 313 313 font-style:italic; 314 314 color:black; 315 } 316 .pas_cth_errorCondition { 317 background-color:#FFFF90; 315 318 } 316 319 @media (min-width:830px) { … … 912 915 background-color:rgba(255, 255, 255, .8); 913 916 color:black; 914 z-index: 99999;917 z-index:1000000; 915 918 } 916 919 #ef_readonly_msg { grid-column:1 / span 4; grid-row:1; } … … 987 990 font-size:12pt; 988 991 font-weight:bold; 992 z-index:1000005; 989 993 } 990 994 #sp_saveButton, #sp_closeButton { -
child-themes-helper/trunk/js/color_picker.js
r2057158 r2074973 1 "use strict;" 1 2 // /js/color_picker.js 2 3 … … 463 464 function pas_cth_js_showColorPicker(clr) { 464 465 465 var xmlhttp = new XMLHttpRequest();466 467 var data = new FormData();468 469 466 var currentColor = clr.value; 470 467 … … 472 469 473 470 474 475 data.append('action', 'displayColorPicker'); 476 477 data.append('initialColor', currentColor); 478 479 data.append('callingFieldName', fieldName); 480 481 482 483 xmlhttp.open("POST", ajaxurl,true); 484 485 486 487 xmlhttp.onreadystatechange = function () { 488 489 if (4 == xmlhttp.readyState) { 490 491 // strip the AJAX zero from wp_die() WORDPRESS ONLY 492 493 var response = (xmlhttp.responseText.length >= 1 ? 494 495 xmlhttp.responseText.left(xmlhttp.responseText.length - 1) : 496 497 xmlhttp.responseText); 498 499 500 501 switch (xmlhttp.status) { 502 503 case 200: // Everything is Okay 504 505 /* If responseText is not empty, there might be a request to overwrite 506 507 * or a request to delete that needs to be displayed. 508 509 * else, reload the page. 510 511 * <= 1 accounts for the AJAX return of zero that sometimes shows up 512 513 * despite my best efforts to avoid that. 514 515 */ 516 517 if (response.length <= 0) { 518 519 // refresh the current display 520 521 location.reload(); 522 523 } else { 524 525 pas_cth_js_createColorWindow(response); 526 527 // display any output from the wp_ajax_* function. 528 529 // pas_cth_js_processResponse(response); 530 531 } 532 533 break; 534 535 536 537 case 400: // There was an error 538 539 msg = "400 Error:<br>" + xmlhttp.statusText; 540 541 pas_cth_js_showBox().innerHTML = msg; 542 543 break; 471 var dataBlock = {}; 472 473 474 dataBlock.initialColor = currentColor; 475 dataBlock.callingFieldName = fieldName; 476 477 var successCallback = function (response) { 478 if (response.length) { 479 pas_cth_js_createColorWindow(response); 480 } else { 481 location.reload(); 482 } 483 } 484 485 486 pas_cth_js_AJAXCall('displayColorPicker', dataBlock, successCallback, pas_cth_js_failureCallback); 487 } 488 489 490 491 function pas_cth_js_createColorWindow(response) { 492 493 var colorPickerWindow = document.getElementById("colorPickerWindow"); 494 495 var theBody = document.getElementsByTagName("body")[0]; 496 497 if (colorPickerWindow == null || colorPickerWindow == undefined) { 498 499 colorPickerWindow = document.createElement("div"); 500 501 colorPickerWindow.setAttribute("id", "colorPickerWindow"); 502 503 theBody.appendChild(colorPickerWindow); 504 505 } 506 507 colorPickerWindow.innerHTML = response; 508 509 } 510 511 function exitColorPickerDialog() { 512 513 var colorPickerWindow = document.getElementById("colorPickerWindow"); 514 515 var parent = colorPickerWindow.parentNode; 516 517 if (parent != null) { 518 519 parent.removeChild(colorPickerWindow) 520 521 } 522 523 colorPickerWindow.remove(); 524 525 } 526 527 function makeElement(id, name, type, value) { 528 529 var element = document.createElement("input"); 530 531 element.setAttribute("id", id); 532 533 element.setAttribute("name", name); 534 535 element.setAttribute("type", type); 536 537 element.setAttribute("value", value); 538 539 return element; 540 541 } 542 543 function saveColor(button) { 544 545 var abbr = button.getAttribute("data-abbr"); 546 547 var cp = new colorPickerElements(abbr); 548 549 var dataBlock = {}; 550 cp.initialColor.value = cp.hexval.value; 551 552 553 554 var jsInput; 555 556 557 558 dataBlock.hexColorCode = cp.hexval.value; 559 dataBlock.abbreviation = abbr; 560 561 cp.saveButton.disabled = true; 562 cp.resetButton.disabled = true; 563 564 pas_cth_js_AJAXCall('saveOptions', dataBlock, pas_cth_js_successCallback, pas_cth_js_failureCallback); 565 } 566 567 function resetColor(element) { 568 569 var abbr = element.id.left(element.id.length - "_resetButton".length) 570 571 var cp = new colorPickerElements(abbr); 572 573 cp.hexval.value = cp.initialColor.value; 574 575 var hexcolors = cp.hexColor2Decimal(cp.initialColor.value); 576 577 cp.rval.value = hexcolors.red; 578 579 cp.gval.value = hexcolors.green; 580 581 cp.bval.value = hexcolors.blue; 582 583 584 585 cp.redSlider.value = hexcolors.red; 586 587 cp.greenSlider.value = hexcolors.green; 588 589 cp.blueSlider.value = hexcolors.blue; 590 591 592 593 updateColorPicker(abbr); 594 595 cp.saveButton.disabled = true; 596 597 cp.resetButton.disabled = true; 598 599 600 601 } 602 603 // Get Complementary color 604 605 function invertColor(hex, bw = true) { 606 607 if (hex.indexOf('#') === 0) { 608 609 hex = hex.slice(1); 610 611 } 612 613 var r = parseInt(hex.slice(0, 2), 16), 614 615 g = parseInt(hex.slice(2, 4), 16), 616 617 b = parseInt(hex.slice(4, 6), 16); 618 619 if (bw) { 620 621 // http://stackoverflow.com/a/3943023/112731 622 623 return (r * 0.299 + g * 0.587 + b * 0.114) > 186 624 625 ? '#000000' 626 627 : '#FFFFFF'; 628 629 } 630 631 // invert color components 632 633 r = (255 - r).toString(16).digits(2); 634 635 g = (255 - g).toString(16).digits(2); 636 637 b = (255 - b).toString(16).digits(2); 638 639 // pad each with zeros and return 640 641 return "#" + r + g + b; 642 643 } 644 645 function showDropDown(listBoxID) { 646 647 var listBox = document.getElementById(listBoxID) 648 649 if (listBox.style.display == "") { 650 651 listBox.style.display = "inline-block"; 652 653 } else { 654 655 listBox.style.display = ""; 656 657 } 658 659 } 660 661 function selectThisFont(fontDataElement) { 662 663 var fontData = JSON.parse(fontDataElement.getAttribute("data-font")); 664 665 var row = fontData['data-row']; 666 667 var fontName = row['fontName'] 668 669 var fontBase = row['fontFile-base']; 670 671 var fontFile = fontData['url'] + fontBase + ".ttf"; 672 673 var fontSampleImg = fontData['url'] + fontBase + ".png"; 674 675 676 677 var textBox = document.getElementById(fontData['text-box']); 678 679 var listBox = document.getElementById(fontData['list-box']); 680 681 682 683 var selectedFontNameElement = document.getElementById("selectedFontName") 684 ; 685 var selectedFontSampleElement = document.getElementById("selectedFontSample") 686 ; 687 688 var dataBlock = {}; 689 690 691 selectedFontNameElement.innerHTML = fontName 692 693 694 695 var img = document.getElementById("sampleFontImage") 696 697 if (img != null) { 698 699 if (img.parentNode != null) { 700 701 img.parentNode.removeChild(img); 702 703 } 704 705 img.remove(); 706 707 } 708 709 img = document.createElement("img") 710 711 img.setAttribute("id", "sampleFontImage") 712 713 img.src = fontSampleImg 714 715 img.style.cssText = "visibility:visible;display:inline;"; 716 717 selectedFontSampleElement.appendChild(img) 718 719 720 721 textBox.style.display = "inline"; 722 723 listBox.style.display = "none"; 724 725 726 727 dataBlock.fontName = fontName; 728 dataBlock['fontFile-base'] = fontBase; 729 730 var successCallback = function (response) { 731 if (response.length) { 732 pas_cth_js_processResponse(response); 733 pas_cth_js_hideWait(); 734 } 735 } 736 737 pas_cth_js_AJAXCall('saveDefaultFont', dataBlock, successCallback, pas_cth_js_failureCallback); 738 } 739 740 function test(abbr) { 741 742 var r = document.getElementById(abbr + "_rval_cell") 743 744 r.style.backgroundColor = "#00FF00"; 745 746 747 748 var rslidercell = document.getElementById(abbr + "_redSlider_cell") 749 750 var gslidercell = document.getElementById(abbr + "_greenSlider_cell") 751 752 var bslidercell = document.getElementById(abbr + "_blueSlider_cell") 753 754 } 755 756 757 758 function makeItDarker(element) { 759 760 var abbr = element.id.left(element.id.length - "_darkerBTN".length); 761 762 var cp = new colorPickerElements(abbr); 763 764 765 766 var cv = new colorValues(cp); 767 768 769 770 var minColor = getMinColor(cv.redValue, cv.greenValue, cv.blueValue); 771 772 var adjustValue = 255 * 0.05; // 5% 773 774 775 776 cp.rval.value = (parseInt(cp.rval.value, 10) - adjustValue < 0 ? 0 : parseInt(cp.rval.value, 10) - adjustValue); 777 778 cp.redSlider.value = cp.rval.value; 779 780 781 782 cp.gval.value = (parseInt(cp.gval.value, 10) - adjustValue < 0 ? 0 : parseInt(cp.gval.value, 10) - adjustValue); 783 784 cp.greenSlider.value = cp.gval.value; 785 786 787 788 cp.bval.value = (parseInt(cp.bval.value, 10) - adjustValue < 0 ? 0 : parseInt(cp.bval.value, 10) - adjustValue); 789 790 cp.blueSlider.value = cp.bval.value; 791 792 updateColorPicker(abbr); 793 794 } 795 796 function makeItLighter(element) { 797 798 var abbr = element.id.left(element.id.length - "_lighterBTN".length); 799 800 var cp = new colorPickerElements(abbr); 801 802 803 804 var cv = new colorValues(cp); 805 806 807 808 var maxColor = getMaxColor(cv.redValue, cv.greenValue, cv.blueValue); 809 810 var adjustValue = 255 * 0.05; // 5% 811 812 813 814 cp.rval.value = (parseInt(cp.rval.value, 10) + adjustValue > 255 ? 255 : parseInt(cp.rval.value, 10) + adjustValue); 815 816 cp.redSlider.value = cp.rval.value; 817 818 819 820 cp.gval.value = (parseInt(cp.gval.value, 10) + adjustValue > 255 ? 255 : parseInt(cp.gval.value, 10) + adjustValue); 821 822 cp.greenSlider.value = cp.gval.value; 823 824 825 826 cp.bval.value = (parseInt(cp.bval.value, 10) + adjustValue > 255 ? 255 : parseInt(cp.bval.value, 10) + adjustValue); 827 828 cp.blueSlider.value = cp.bval.value; 829 830 updateColorPicker(abbr); 831 832 } 833 834 function setWebColor(element, color) { 835 836 var abbr = element.getAttribute("data-abbr"); 837 838 var cp = new colorPickerElements(abbr); 839 840 var decvalues = cp.hexColor2Decimal(color); 841 842 843 844 cp.rval.value = decvalues.red; 845 846 cp.gval.value = decvalues.green; 847 848 cp.bval.value = decvalues.blue; 849 850 851 852 cp.redSlider.value = decvalues.red; 853 854 cp.greenSlider.value = decvalues.green; 855 856 cp.blueSlider.value = decvalues.blue; 857 858 cp.hexval.value = color; 859 860 861 862 updateColorPicker(abbr); 863 864 } 865 866 function generateScreenShot(abbr) { 867 868 var saveBTNs = new eList(document.getElementsByClassName("saveButton")).toArray(); 869 870 var unsavedCount = 0; 871 872 873 874 saveBTNs.map(function (cell) { 875 876 if (! cell.disabled ) { 877 878 unsavedCount++; 879 880 } 881 882 }); 883 884 885 886 if (unsavedCount > 0) { 887 888 var box = pas_cth_library.displayError("Please save or reset your changes before attempting to generate a new screenshot for your child theme."); 889 890 var p = document.createElement("P"); 891 892 p.innerHTML = "close [X]"; 893 894 box.appendChild(p); 895 896 return; 897 898 } 899 900 var displayScreenshotFile = function (xmlResponse) { 901 902 var parser = new DOMParser(); 903 904 var xmlDoc = parser.parseFromString(xmlResponse,"text/xml"); 905 906 var records = xmlDoc.getElementsByTagName("record"); 907 908 var site_url = records[0].getElementsByTagName("siteURL")[0].textContent; 909 910 var stylesheet = records[0].getElementsByTagName("stylesheet")[0].textContent; 911 912 var filename = records[0].getElementsByTagName("filename")[0].textContent; 913 914 915 916 var box = pas_cth_library.createBox("screenshotBox") 917 box.onclick = function () { 918 919 if (this.parentNode != null) { 920 921 this.parentNode.removeChild(this); 544 922 545 923 } 546 924 925 this.remove(); 926 547 927 } 548 928 549 } 550 551 xmlhttp.send(data); 552 553 } 554 555 556 557 function pas_cth_js_createColorWindow(response) { 558 559 var colorPickerWindow = document.getElementById("colorPickerWindow"); 560 561 var theBody = document.getElementsByTagName("body")[0]; 562 563 if (colorPickerWindow == null || colorPickerWindow == undefined) { 564 565 colorPickerWindow = document.createElement("div"); 566 567 colorPickerWindow.setAttribute("id", "colorPickerWindow"); 568 569 theBody.appendChild(colorPickerWindow); 570 571 } 572 573 colorPickerWindow.innerHTML = response; 574 575 } 576 577 function exitColorPickerDialog() { 578 579 var colorPickerWindow = document.getElementById("colorPickerWindow"); 580 581 var parent = colorPickerWindow.parentNode; 582 583 if (parent != null) { 584 585 parent.removeChild(colorPickerWindow) 586 587 } 588 589 colorPickerWindow.remove(); 590 591 } 592 593 function makeElement(id, name, type, value) { 594 595 var element = document.createElement("input"); 596 597 element.setAttribute("id", id); 598 599 element.setAttribute("name", name); 600 601 element.setAttribute("type", type); 602 603 element.setAttribute("value", value); 604 605 return element; 606 607 } 608 609 function saveColor(button) { 610 611 var abbr = button.getAttribute("data-abbr"); 612 613 var cp = new colorPickerElements(abbr); 614 615 cp.initialColor.value = cp.hexval.value; 616 617 618 619 var xmlhttp = new XMLHttpRequest(); 620 621 var data = new FormData(); 622 623 var jsInput; 624 625 626 627 data.append("hexColorCode", cp.hexval.value); 628 629 data.append("abbreviation", abbr); 630 631 data.append("action", "saveOptions"); 632 633 634 635 xmlhttp.open("POST", ajaxurl,true); 636 637 638 639 xmlhttp.onreadystatechange = function () { 640 641 if (4 == xmlhttp.readyState) { 642 643 var response = (xmlhttp.responseText.length >= 1 ? 644 645 xmlhttp.responseText.left(xmlhttp.responseText.length - 1) : 646 647 xmlhttp.responseText); 648 649 650 651 switch (xmlhttp.status) { 652 653 case 200: // Everything is okay 654 655 if (response.length <= 0) { 656 657 } else { 658 659 pas_cth_js_processResponse(response); 660 661 } 662 663 break; 664 665 666 667 case 400: 668 669 msg = "400 Error:<br>" + xmlhttp.statusText; 670 671 pas_cth_js_showBox().innerHTML = msg; 672 673 break; 674 675 } 676 677 } 678 679 } 680 681 cp.saveButton.disabled = true; 682 683 cp.resetButton.disabled = true; 684 685 xmlhttp.send(data) 686 687 } 688 689 function resetColor(element) { 690 691 var abbr = element.id.left(element.id.length - "_resetButton".length) 692 693 var cp = new colorPickerElements(abbr); 694 695 cp.hexval.value = cp.initialColor.value; 696 697 var hexcolors = cp.hexColor2Decimal(cp.initialColor.value); 698 699 cp.rval.value = hexcolors.red; 700 701 cp.gval.value = hexcolors.green; 702 703 cp.bval.value = hexcolors.blue; 704 705 706 707 cp.redSlider.value = hexcolors.red; 708 709 cp.greenSlider.value = hexcolors.green; 710 711 cp.blueSlider.value = hexcolors.blue; 712 713 714 715 updateColorPicker(abbr); 716 717 cp.saveButton.disabled = true; 718 719 cp.resetButton.disabled = true; 720 721 722 723 } 724 725 // Get Complementary color 726 727 function invertColor(hex, bw = true) { 728 729 if (hex.indexOf('#') === 0) { 730 731 hex = hex.slice(1); 732 733 } 734 735 var r = parseInt(hex.slice(0, 2), 16), 736 737 g = parseInt(hex.slice(2, 4), 16), 738 739 b = parseInt(hex.slice(4, 6), 16); 740 741 if (bw) { 742 743 // http://stackoverflow.com/a/3943023/112731 744 745 return (r * 0.299 + g * 0.587 + b * 0.114) > 186 746 747 ? '#000000' 748 749 : '#FFFFFF'; 750 751 } 752 753 // invert color components 754 755 r = (255 - r).toString(16).digits(2); 756 757 g = (255 - g).toString(16).digits(2); 758 759 b = (255 - b).toString(16).digits(2); 760 761 // pad each with zeros and return 762 763 return "#" + r + g + b; 764 765 } 766 767 function showDropDown(listBoxID) { 768 769 var listBox = document.getElementById(listBoxID) 770 771 if (listBox.style.display == "") { 772 773 listBox.style.display = "inline-block"; 774 775 } else { 776 777 listBox.style.display = ""; 778 779 } 780 781 } 782 783 function selectThisFont(fontDataElement) { 784 785 var fontData = JSON.parse(fontDataElement.getAttribute("data-font")); 786 787 var row = fontData['data-row']; 788 789 var fontName = row['fontName'] 790 791 var fontBase = row['fontFile-base']; 792 793 var fontFile = fontData['url'] + fontBase + ".ttf"; 794 795 var fontSampleImg = fontData['url'] + fontBase + ".png"; 796 797 798 799 var textBox = document.getElementById(fontData['text-box']); 800 801 var listBox = document.getElementById(fontData['list-box']); 802 803 804 805 var selectedFontNameElement = document.getElementById("selectedFontName") 806 807 var selectedFontSampleElement = document.getElementById("selectedFontSample") 808 809 810 811 selectedFontNameElement.innerHTML = fontName 812 813 814 815 var img = document.getElementById("sampleFontImage") 816 817 if (img != null) { 818 819 if (img.parentNode != null) { 820 821 img.parentNode.removeChild(img); 822 823 } 824 825 img.remove(); 826 827 } 828 829 img = document.createElement("img") 830 831 img.setAttribute("id", "sampleFontImage") 832 833 img.src = fontSampleImg 834 835 img.style.cssText = "visibility:visible;display:inline;"; 836 837 selectedFontSampleElement.appendChild(img) 838 839 840 841 textBox.style.display = "inline"; 842 843 listBox.style.display = "none"; 844 845 846 847 var xmlhttp = new XMLHttpRequest(); 848 849 var data = new FormData(); 850 851 data.append("action", "saveDefaultFont"); 852 853 data.append("fontName", fontName); 854 855 data.append("fontFile-base", fontBase); 856 857 858 859 xmlhttp.open("POST", ajaxurl,true); 860 861 xmlhttp.onreadystatechange = function () { 862 863 864 865 if (4 == xmlhttp.readyState) { 866 867 // strip the AJAX zero from wp_die() WORDPRESS ONLY 868 869 var response = (xmlhttp.responseText.length >= 1 ? 870 871 xmlhttp.responseText.left(xmlhttp.responseText.length - 1) : 872 873 xmlhttp.responseText); 874 875 switch (xmlhttp.status) { 876 877 case 200: // Everything is Okay 878 879 /* If responseText is not empty, there might be a request to overwrite 880 881 * or a request to delete that needs to be displayed. 882 883 * else, reload the page. 884 885 * <= 1 accounts for the AJAX return of zero that sometimes shows up 886 887 * despite my best efforts to avoid that. 888 889 */ 890 891 if (response.length <= 0) { 892 893 // do nothing. Just return. 894 895 896 897 } else { 898 899 // display any output from the wp_ajax_* function. 900 901 pas_cth_js_processResponse(response); 902 903 } 904 905 break; 906 907 908 909 case 400: // There was an error 910 911 msg = "400 Error:<br>" + xmlhttp.statusText; 912 913 pas_cth_js_showBox().innerHTML = msg; 914 915 break; 916 917 } 918 919 } 920 921 } 922 923 xmlhttp.send(data); 924 925 } 926 927 function test(abbr) { 928 929 var r = document.getElementById(abbr + "_rval_cell") 930 931 r.style.backgroundColor = "#00FF00"; 932 933 934 935 var rslidercell = document.getElementById(abbr + "_redSlider_cell") 936 937 var gslidercell = document.getElementById(abbr + "_greenSlider_cell") 938 939 var bslidercell = document.getElementById(abbr + "_blueSlider_cell") 940 941 } 942 943 944 945 function makeItDarker(element) { 946 947 var abbr = element.id.left(element.id.length - "_darkerBTN".length); 948 949 var cp = new colorPickerElements(abbr); 950 951 952 953 var cv = new colorValues(cp); 954 955 956 957 var minColor = getMinColor(cv.redValue, cv.greenValue, cv.blueValue); 958 959 var adjustValue = 255 * 0.05; // 5% 960 961 962 963 cp.rval.value = (parseInt(cp.rval.value, 10) - adjustValue < 0 ? 0 : parseInt(cp.rval.value, 10) - adjustValue); 964 965 cp.redSlider.value = cp.rval.value; 966 967 968 969 cp.gval.value = (parseInt(cp.gval.value, 10) - adjustValue < 0 ? 0 : parseInt(cp.gval.value, 10) - adjustValue); 970 971 cp.greenSlider.value = cp.gval.value; 972 973 974 975 cp.bval.value = (parseInt(cp.bval.value, 10) - adjustValue < 0 ? 0 : parseInt(cp.bval.value, 10) - adjustValue); 976 977 cp.blueSlider.value = cp.bval.value; 978 979 updateColorPicker(abbr); 980 981 } 982 983 function makeItLighter(element) { 984 985 var abbr = element.id.left(element.id.length - "_lighterBTN".length); 986 987 var cp = new colorPickerElements(abbr); 988 989 990 991 var cv = new colorValues(cp); 992 993 994 995 var maxColor = getMaxColor(cv.redValue, cv.greenValue, cv.blueValue); 996 997 var adjustValue = 255 * 0.05; // 5% 998 999 1000 1001 cp.rval.value = (parseInt(cp.rval.value, 10) + adjustValue > 255 ? 255 : parseInt(cp.rval.value, 10) + adjustValue); 1002 1003 cp.redSlider.value = cp.rval.value; 1004 1005 1006 1007 cp.gval.value = (parseInt(cp.gval.value, 10) + adjustValue > 255 ? 255 : parseInt(cp.gval.value, 10) + adjustValue); 1008 1009 cp.greenSlider.value = cp.gval.value; 1010 1011 1012 1013 cp.bval.value = (parseInt(cp.bval.value, 10) + adjustValue > 255 ? 255 : parseInt(cp.bval.value, 10) + adjustValue); 1014 1015 cp.blueSlider.value = cp.bval.value; 1016 1017 updateColorPicker(abbr); 1018 1019 } 1020 1021 function setWebColor(element, color) { 1022 1023 var abbr = element.getAttribute("data-abbr"); 1024 1025 var cp = new colorPickerElements(abbr); 1026 1027 var decvalues = cp.hexColor2Decimal(color); 1028 1029 1030 1031 cp.rval.value = decvalues.red; 1032 1033 cp.gval.value = decvalues.green; 1034 1035 cp.bval.value = decvalues.blue; 1036 1037 1038 1039 cp.redSlider.value = decvalues.red; 1040 1041 cp.greenSlider.value = decvalues.green; 1042 1043 cp.blueSlider.value = decvalues.blue; 1044 1045 cp.hexval.value = color; 1046 1047 1048 1049 updateColorPicker(abbr); 1050 1051 } 1052 1053 function generateScreenShot(abbr) { 1054 1055 var saveBTNs = new eList(document.getElementsByClassName("saveButton")).toArray(); 1056 1057 var unsavedCount = 0; 1058 1059 1060 1061 saveBTNs.map(function (cell) { 1062 1063 if (! cell.disabled ) { 1064 1065 unsavedCount++; 1066 1067 } 1068 1069 }); 1070 1071 1072 1073 if (unsavedCount > 0) { 1074 1075 var box = displayError("Please save or reset your changes before attempting to generate a new screenshot for your child theme."); 929 var theBody = document.getElementsByTagName("body")[0]; 1076 930 1077 931 var p = document.createElement("P"); 1078 932 1079 p.innerHTML = "close [X]"; 933 p.appendChild(document.createTextNode("[X] close")); 934 935 936 937 var img = document.createElement("IMG"); 938 939 img.src = site_url + "/wp-content/themes/" + stylesheet + "/" + filename + "?cacheBuster=" + Date.now(); 940 941 box.appendChild(img); 1080 942 1081 943 box.appendChild(p); 1082 944 1083 return;1084 1085 }1086 1087 var displayScreenshotFile = function (xmlResponse) {1088 1089 var parser = new DOMParser();1090 1091 var xmlDoc = parser.parseFromString(xmlResponse,"text/xml");1092 1093 var records = xmlDoc.getElementsByTagName("record");1094 1095 var site_url = records[0].getElementsByTagName("siteURL")[0].textContent;1096 1097 var stylesheet = records[0].getElementsByTagName("stylesheet")[0].textContent;1098 1099 var filename = records[0].getElementsByTagName("filename")[0].textContent;1100 1101 1102 1103 var box = document.createElement("DIV");1104 1105 box.onclick = function () {1106 1107 if (this.parentNode != null) {1108 1109 this.parentNode.removeChild(this);1110 1111 }1112 1113 this.remove();1114 1115 }1116 1117 var theBody = document.getElementsByTagName("body")[0];1118 1119 box.id = "screenshotBox";1120 1121 var p = document.createElement("P");1122 1123 p.appendChild(document.createTextNode("[X] close"));1124 1125 1126 1127 var img = document.createElement("IMG");1128 1129 img.src = site_url + "/wp-content/themes/" + stylesheet + "/" + filename + "?cacheBuster=" + Date.now();1130 1131 box.appendChild(img);1132 1133 box.appendChild(p);1134 1135 theBody.appendChild(box);1136 1137 945 } 1138 946 -
child-themes-helper/trunk/js/edit_file.js
r2057158 r2074973 1 "use strict;" 1 2 if (typeof String.prototype.toBold == "undefined") { 2 3 … … 145 146 var element = document.getElementById(event.srcElement.dataset.elementid); 146 147 147 var xmlhttp = new XMLHttpRequest(); 148 149 var data = new FormData(); 148 var dataBlock = {}; 150 149 151 150 var jsInput = JSON.parse(element.getAttribute("data-jsdata")); … … 187 186 188 187 189 xmlhttp.open("POST", ajaxurl, true); 190 191 192 193 data.append("action", 'editFile'); 194 195 data.append("directory", jsInput['directory'] ); 196 197 data.append("file", jsInput['file']); 198 199 data.append("themeType", jsInput['themeType'] ); 200 201 202 203 xmlhttp.onreadystatechange = function () { 204 205 if (4 == xmlhttp.readyState) { 206 207 var response = (xmlhttp.responseText.length >= 1 ? 208 209 xmlhttp.responseText.left(xmlhttp.responseText.length - 1) : 210 211 xmlhttp.responseText); 212 213 214 215 switch (xmlhttp.status) { 216 217 case 200: // Everything is okay 218 219 if (response.length <= 0) { 220 221 location.reload(); 222 223 } else { 224 225 /* 226 227 * Function pas_cth_js_processResponse is in the js_common_fn.js file 228 229 * which then passes control back to the processEditFile() in this file. 230 231 */ 232 233 pas_cth_js_processResponse(response); 234 235 } 236 237 break; 238 239 240 241 case 400: 242 243 msg = "400 Error:<br>" + xmlhttp.statusText; 244 245 pas_cth_js_showBox().innerHTML = msg; 246 247 break; 188 dataBlock.directory = jsInput['directory']; 189 dataBlock.file = jsInput['file']; 190 dataBlock.themeType = jsInput['themeType']; 191 192 193 pas_cth_js_AJAXCall('editFile', dataBlock, pas_cth_js_successCallback, pas_cth_js_failureCallback); 194 } 195 196 function captureKeystrokes(element) { 197 198 switch (event.keyCode) { 199 200 case 9: 201 202 event.preventDefault(); 203 204 insertTextAtCursor(String.fromCharCode(event.keyCode)); 205 206 editBoxChange(); 207 208 break; 209 210 case 10: 211 212 case 13: 213 214 event.preventDefault(); 215 216 insertTextAtCursor(String.fromCharCode(10)); 217 218 editBoxChange(); 219 220 break; 221 222 case 90: // CAP Z 223 224 if (event.ctrlKey) { // CTRL-Z (undo) // doesn't currently work in all cases. Need to rewrite the edit handling to use execCommand. 248 225 249 226 } 250 227 228 break; 229 230 case 16: // left shift 231 232 case 8: // backspace 233 234 case 17: // left CTRL 235 236 break; 237 238 default: 239 240 break; 241 242 } 243 244 } 245 246 function clearSelection() { 247 248 var sel = window.getSelection ? window.getSelection() : document.selection; 249 250 if (sel) { 251 252 if (sel.removeAllRanges) { 253 254 sel.removeAllRanges(); 255 256 } else if (sel.empty) { 257 258 sel.empty(); 259 251 260 } 252 261 253 262 } 254 263 255 xmlhttp.send(data) 256 257 } 258 259 function captureKeystrokes(element) { 260 261 switch (event.keyCode) { 262 263 case 9: 264 265 event.preventDefault(); 266 267 insertTextAtCursor(String.fromCharCode(event.keyCode)); 268 269 editBoxChange(); 270 271 break; 272 273 case 10: 274 275 case 13: 276 277 event.preventDefault(); 278 279 insertTextAtCursor(String.fromCharCode(10)); 280 281 editBoxChange(); 282 283 break; 284 285 case 90: // CAP Z 286 287 if (event.ctrlKey) { // CTRL-Z (undo) // doesn't currently work in all cases. Need to rewrite the edit handling to use execCommand. 288 289 } 290 291 break; 292 293 case 16: // left shift 294 295 case 8: // backspace 296 297 case 17: // left CTRL 298 299 break; 300 301 default: 302 303 break; 304 305 } 306 307 } 308 309 function clearSelection() { 310 311 var sel = window.getSelection ? window.getSelection() : document.selection; 312 313 if (sel) { 314 315 if (sel.removeAllRanges) { 316 317 sel.removeAllRanges(); 318 319 } else if (sel.empty) { 320 321 sel.empty(); 322 264 } 265 266 function insertTextAtCursor(text) { 267 268 var sel, range, html; 269 270 var cursorPosition = saveSelection(); 271 272 273 274 if (window.getSelection) { 275 276 sel = window.getSelection(); 277 278 279 280 if (sel.getRangeAt && sel.rangeCount) { 281 282 range = sel.getRangeAt(0); 283 284 range.deleteContents(); 285 286 restoreSelection(cursorPosition); 287 288 range.insertNode( document.createTextNode(text) ); 289 290 range.collapse(); 291 292 } 293 294 } else if (document.selection && document.selection.createRange) { 295 296 document.selection.createRange().text = text; 297 298 document.selection.collapse(); 299 300 } 301 302 303 304 305 306 } 307 308 function saveSelection() { 309 310 if (window.getSelection) { 311 312 sel = window.getSelection(); 313 314 if (sel.getRangeAt && sel.rangeCount) { 315 316 return sel.getRangeAt(0); 317 318 } 319 320 } else if (document.selection && document.selection.createRange) { 321 322 return document.selection.createRange(); 323 324 } 325 326 return null; 327 328 } 329 330 331 332 function restoreSelection(range) { 333 334 if (range) { 335 336 if (window.getSelection) { 337 338 sel = window.getSelection(); 339 340 sel.removeAllRanges(); 341 342 sel.addRange(range); 343 344 } else if (document.selection && range.select) { 345 346 range.select(); 347 348 } 349 350 } 351 352 } 353 354 function processEditFile(response) { 355 356 var ee = new pas_cth_js_editElements(); 357 358 var responseSections = parseOutput(response); 359 360 responseSections.ARGS = JSON.parse(responseSections.ARGS); 361 362 363 364 ee.directoryINP.value = responseSections.ARGS['directory']; 365 366 ee.filenameINP.value = responseSections.ARGS['file']; 367 368 ee.themeTypeINP.value = responseSections.ARGS['themeType']; 369 370 ee.readOnlyFlag.value = responseSections.ARGS['readOnlyFlag']; 371 372 ee.filenameDisplay.innerHTML = "FILE: " + responseSections.ARGS['directory'] + "/" + responseSections.ARGS['file']; 373 374 375 376 ee.efSaveButton.disabled = true; 377 378 379 380 ee.editBox.innerHTML = responseSections.EDITBOX 381 382 383 384 enableContent(ee); 385 386 387 388 if (ee.readOnlyFlag.value.toLowerCase() == "true") { 389 390 ee.readOnlyMsg.style.display = "inline"; 391 392 } else { 393 394 ee.readOnlyMsg.style.display = "none"; 395 396 } 397 398 399 400 ee.editBox.onkeydown = function () { captureKeystrokes(this) } 401 402 403 404 ee.shield.style.display = "inline"; 405 406 ee.editFile.style.display = "grid"; 407 408 409 410 } 411 412 function enableContent(elements) { 413 414 elements.editBox.contentEditable = true; 415 416 417 418 elements.efSaveButton.contentEditable = false; 419 420 elements.efCloseButton.contentEditable = false; 421 422 423 424 elements.savePrompt.contentEditable = false; 425 426 elements.spSaveButton.contentEditable = false; 427 428 elements.spCloseButton.contentEditable = false; 429 430 } 431 432 433 434 function pas_cth_js_closeEditFile() { 435 436 var ee = new pas_cth_js_editElements(); 437 438 439 440 if ( ! ee.efSaveButton.disabled) { // not disabled = visible 441 442 ee.savePrompt.style.display = "inline" 443 444 ee.efSaveButton.disabled = true; 445 446 } else { 447 448 // ee.themeGrid.style.display = "inline-grid"; 449 450 ee.editFile.style.display = "none"; 451 452 ee.shield.style.display = "none"; 453 454 ee.editBox.innerHTML = ""; 455 456 ee.savePrompt.style.display = "none"; 457 458 } 459 460 } 461 462 function pas_cth_js_closeFile() { 463 464 var ee = new pas_cth_js_editElements(); 465 466 467 468 ee.efSaveButton.disabled = true; 469 470 ee.savePrompt.style.display = "none"; 471 472 pas_cth_js_closeEditFile(); 473 474 475 476 } 477 478 function editBoxChange() { 479 480 if (document.getElementById("themeType").value.toLowerCase() == "child") { 481 482 document.getElementById("ef_saveButton").disabled = false; 483 484 } 485 486 } 487 488 function debug(element) { 489 490 var ee = new pas_cth_js_editElements(); 491 492 } 493 494 function pas_cth_js_saveFile() { 495 496 var ee = new pas_cth_js_editElements(); 497 498 499 500 var fileContents = ""; 501 502 var dataBlock = {}; 503 504 505 fileContents = ee.editBox.innerText; // .replace(/</g, "<").replace(/>/g, ">"); 506 507 508 509 dataBlock.fileContents = fileContents; 510 dataBlock.file = ee.filenameINP.value; 511 dataBlock.directory = ee.directoryINP.value; 512 dataBlock.themeType = ee.themeTypeINP.value; 513 514 ee.efSaveButton.disabled = true; // last possible chance to disable the button. 515 516 517 518 pas_cth_js_closeEditFile(); // Closing only clears the div and hides it. Not destroyed. 519 520 521 var successCallback = function (response) { 522 if (response.length) { 523 pas_cth_js_processResponse(response); 524 pas_cth_js_hideWait(); 323 525 } 324 325 } 326 327 } 328 329 function insertTextAtCursor(text) { 330 331 var sel, range, html; 332 333 var cursorPosition = saveSelection(); 334 335 336 337 if (window.getSelection) { 338 339 sel = window.getSelection(); 340 341 342 343 if (sel.getRangeAt && sel.rangeCount) { 344 345 range = sel.getRangeAt(0); 346 347 range.deleteContents(); 348 349 restoreSelection(cursorPosition); 350 351 range.insertNode( document.createTextNode(text) ); 352 353 range.collapse(); 354 355 } 356 357 } else if (document.selection && document.selection.createRange) { 358 359 document.selection.createRange().text = text; 360 361 document.selection.collapse(); 362 363 } 364 365 366 367 368 369 } 370 371 function saveSelection() { 372 373 if (window.getSelection) { 374 375 sel = window.getSelection(); 376 377 if (sel.getRangeAt && sel.rangeCount) { 378 379 return sel.getRangeAt(0); 380 381 } 382 383 } else if (document.selection && document.selection.createRange) { 384 385 return document.selection.createRange(); 386 387 } 388 389 return null; 390 391 } 392 393 394 395 function restoreSelection(range) { 396 397 if (range) { 398 399 if (window.getSelection) { 400 401 sel = window.getSelection(); 402 403 sel.removeAllRanges(); 404 405 sel.addRange(range); 406 407 } else if (document.selection && range.select) { 408 409 range.select(); 410 411 } 412 413 } 414 415 } 416 417 function processEditFile(response) { 418 419 var ee = new pas_cth_js_editElements(); 420 421 var responseSections = parseOutput(response); 422 423 responseSections.ARGS = JSON.parse(responseSections.ARGS); 424 425 426 427 ee.directoryINP.value = responseSections.ARGS['directory']; 428 429 ee.filenameINP.value = responseSections.ARGS['file']; 430 431 ee.themeTypeINP.value = responseSections.ARGS['themeType']; 432 433 ee.readOnlyFlag.value = responseSections.ARGS['readOnlyFlag']; 434 435 ee.filenameDisplay.innerHTML = "FILE: " + responseSections.ARGS['directory'] + "/" + responseSections.ARGS['file']; 436 437 438 439 ee.efSaveButton.disabled = true; 440 441 442 443 ee.editBox.innerHTML = responseSections.EDITBOX 444 445 446 447 enableContent(ee); 448 449 450 451 if (ee.readOnlyFlag.value.toLowerCase() == "true") { 452 453 ee.readOnlyMsg.style.display = "inline"; 454 455 } else { 456 457 ee.readOnlyMsg.style.display = "none"; 458 459 } 460 461 462 463 ee.editBox.onkeydown = function () { captureKeystrokes(this) } 464 465 466 467 ee.shield.style.display = "inline"; 468 469 ee.editFile.style.display = "grid"; 470 471 472 473 } 474 475 function enableContent(elements) { 476 477 elements.editBox.contentEditable = true; 478 479 480 481 elements.efSaveButton.contentEditable = false; 482 483 elements.efCloseButton.contentEditable = false; 484 485 486 487 elements.savePrompt.contentEditable = false; 488 489 elements.spSaveButton.contentEditable = false; 490 491 elements.spCloseButton.contentEditable = false; 492 493 } 494 495 496 497 function pas_cth_js_closeEditFile() { 498 499 var ee = new pas_cth_js_editElements(); 500 501 502 503 if ( ! ee.efSaveButton.disabled) { 504 505 ee.savePrompt.style.cssText = "display:inline;" 506 507 ee.efSaveButton.disabled = true; 508 509 } else { 510 511 // ee.themeGrid.style.display = "inline-grid"; 512 513 ee.editFile.style.display = "none"; 514 515 ee.shield.style.display = "none"; 516 517 ee.editBox.innerHTML = ""; 518 519 ee.savePrompt.style.display = "none"; 520 521 } 522 523 } 524 525 function pas_cth_js_closeFile() { 526 527 var ee = new pas_cth_js_editElements(); 528 529 530 531 ee.efSaveButton.disabled = true; 532 533 ee.savePrompt.style.display = "none"; 534 535 pas_cth_js_closeEditFile(); 536 537 538 539 } 540 541 function editBoxChange() { 542 543 if (document.getElementById("themeType").value.toLowerCase() == "child") { 544 545 document.getElementById("ef_saveButton").disabled = false; 546 547 } 548 549 } 550 551 function debug(element) { 552 553 var ee = new pas_cth_js_editElements(); 554 555 } 556 557 function pas_cth_js_saveFile() { 558 559 var ee = new pas_cth_js_editElements(); 560 561 562 563 var xmlhttp = new XMLHttpRequest(); 564 565 var data = new FormData(); 566 567 var fileContents = ""; 568 569 570 571 xmlhttp.open("POST", ajaxurl, true); 572 573 574 575 fileContents = ee.editBox.innerText; // .replace(/</g, "<").replace(/>/g, ">"); 576 577 578 579 data.append("fileContents", fileContents); 580 581 data.append("file", ee.filenameINP.value); 582 583 data.append("directory", ee.directoryINP.value); 584 585 data.append("themeType", ee.themeTypeINP.value); 586 587 data.append("action", "saveFile"); 588 589 590 591 ee.efSaveButton.disabled = true; // last possible chance to disable the button. 592 593 594 595 pas_cth_js_closeEditFile(); // Closing only clears the div and hides it. Not destroyed. 596 597 598 599 xmlhttp.onreadystatechange = function () { 600 601 if (4 == xmlhttp.readyState) { 602 603 var response = (xmlhttp.responseText.length >= 1 ? 604 605 xmlhttp.responseText.left(xmlhttp.responseText.length - 1) : 606 607 xmlhttp.responseText); 608 609 610 611 switch (xmlhttp.status) { 612 613 case 200: // Everything is okay 614 615 if (response.length <= 0) { 616 617 618 619 } else { 620 621 pas_cth_js_processResponse(response); 622 623 } 624 625 break; 626 627 628 629 case 400: 630 631 case 500: 632 633 msg = xmlhttp.status + " Error:<br>" + xmlhttp.statusText; 634 635 pas_cth_js_showBox().innerHTML = msg; 636 637 break; 638 639 } 640 641 } 642 643 } 644 645 xmlhttp.send(data); 646 526 } 527 528 pas_cth_js_AJAXCall('saveFile', dataBlock, successCallback, pas_cth_js_failureCallback); 647 529 } 648 530 -
child-themes-helper/trunk/js/js_common_fn.js
r2057158 r2074973 1 "use strict;" 1 2 if(typeof String.prototype.ltrim == "undefined") 2 3 … … 21 22 22 23 24 function pas_cth_DOMFunctions() { 25 var self = this; 26 this.killElement = function (element) { 27 if (element == null || element == undefined) { return false; } 28 var e; 29 if (typeof element == "string") { 30 e = document.getElementById(element); 31 } else { 32 e = element; 33 } 34 35 if (e.parentNode != null) { 36 e.parentNode.removeChild(e); 37 } 38 e.remove(); 39 } 40 this.kill = function (element) { 41 if (element == null || element == undefined) { return false; } 42 this.killElement(element); 43 } 44 this.createBox = function (id, parent = null, bKillFirst = true) { 45 if (parent == null) { parent = document.getElementsByTagName("body")[0]; } 46 var box = document.getElementById(id); 47 if (box != null && bKillFirst) { 48 this.killElement(box); 49 box = null; 50 } 51 52 box = document.createElement("DIV"); 53 box.id = id; 54 55 parent.appendChild(box); 56 return box; 57 } 58 this.displayError = function (str) { 59 var box = this.createBox("popupErrorMessage"); 60 box.onclick = function () { 61 self.killElement(box); 62 } 63 box.innerHTML = str; 64 return box; 65 } 66 this.getPosition = function (element = null) { 67 if (element == null) { return null; } 68 var rect = element.getBoundingClientRect(); 69 70 return {left : rect.left, top: rect.top, width : Math.abs(rect.right - rect.left), height : Math.abs(rect.bottom - rect.top), 'element' : element }; 71 } 72 this.getElementTree = function (element) { 73 if (element == null) { 74 return []; 75 } else { 76 return element.getElementsByTagName("*"); 77 } 78 } 79 this.searchTree = function (rootElement, tree, pointElement) { 80 var found = false; 81 82 if (rootElement == pointElement) { 83 return true; 84 } else { 85 for (ndx = 0; ndx < tree.length && ! found; ndx++) { 86 found = (tree[ndx] == pointElement ? true : false); 87 } 88 return found; 89 } 90 } 91 } 92 23 93 var mousePosition = {x:0, y:0, element:null}; 24 94 95 var pas_cth_library = new pas_cth_DOMFunctions(); 25 96 26 97 … … 50 121 51 122 if (key != "action") { 52 53 data.append(key, dataBlock[key]); 123 data.append(key, dataBlock[key]); 124 } 125 }); 126 127 } 128 129 xmlhttp.open("POST", ajaxurl, true); 130 131 xmlhttp.onreadystatechange = function () { 132 133 if (4 == xmlhttp.readyState) { 134 135 // The next line strips the admin_ajax.php 1 byte response from the beginning of the response. 136 137 // Usually, admin_ajax.php returns a zero. This strips that. 138 139 var response = (xmlhttp.responseText.length >= 1 ? xmlhttp.responseText.left(xmlhttp.responseText.length - 1) : ""); 140 141 if (xmlhttp.status == 200) { 142 143 if (callback != null) { 144 145 callback(response); 146 147 } 148 149 } else { 150 151 if (error_callback != null) { 152 153 error_callback(xmlhttp.statusText, response); 154 155 } else { 156 157 alert("AJAX Error:\n\n" + xmlhttp.statusText + "\n\n" + response); 158 159 } 54 160 55 161 } 56 162 57 });58 59 }60 61 xmlhttp.open("POST", ajaxurl, true);62 63 xmlhttp.onreadystatechange = function () {64 65 if (4 == xmlhttp.readyState) {66 67 // The next line strips the admin_ajax.php 1 byte response from the beginning of the response.68 69 // Usually, admin_ajax.php returns a zero. This strips that.70 71 var response = (xmlhttp.responseText.length >= 1 ? xmlhttp.responseText.left(xmlhttp.responseText.length - 1) : "");72 73 if (xmlhttp.status == 200) {74 75 if (callback != null) {76 77 callback(response);78 79 }80 81 } else {82 83 if (error_callback != null) {84 85 error_callback(xmlhttp.statusText, response);86 87 } else {88 89 alert("AJAX Error:\n\n" + xmlhttp.statusText + "\n\n" + response);90 91 }92 93 }94 95 163 } 96 164 … … 103 171 if (document.getElementById("childGrid") != null && document.getElementById("parentGrid") != null) { 104 172 105 window.onresize = function (e) { 106 173 window.addEventListener("resize", function (e) { 107 174 var childGrid = document.getElementById("childGrid") 108 175 … … 126 193 127 194 } 128 129 } 130 131 function getElementTree(element) { 132 133 if (element == null) { 134 135 return []; 195 ); 196 } 197 198 var windowFlag = false; 199 200 201 202 if (window.location.href.indexOf("manage_child_themes") >= 0) { 203 window.addEventListener("click", function (e) { 204 205 if (windowFlag) { 206 207 windowFlag = false; 208 209 return; 210 211 } 212 213 if (e.clientX == undefined || e.clientY == undefined) { 214 215 return; 216 217 } 218 219 220 221 var pointElement = null; 222 223 var actionBox = document.getElementById("pas_cth_actionBox"); 224 225 var errorMessageBox = document.getElementsByName("errorMessageBox")[0]; 226 227 228 229 pointElement = document.elementFromPoint(e.clientX, e.clientY); 230 231 232 233 var tree = pas_cth_library.getElementTree(actionBox); 234 235 var found = false; 236 237 found = pas_cth_library.searchTree(actionBox, tree, pointElement); 238 239 240 241 if (! found) { 242 243 tree = pas_cth_library.getElementTree(errorMessageBox); 244 245 found = pas_cth_library.searchTree(errorMessageBox, tree, pointElement); 246 247 } 248 249 250 251 if (! found) { 252 253 pas_cth_library.kill(actionBox); 254 255 pas_cth_library.kill(errorMessageBox); 256 257 } 258 259 }); 260 261 } 262 263 264 265 // KillMe kills the error message boxes. 266 267 // After the last box has been destroyed, kill the actionBox div too. 268 269 function pas_cth_js_killMe(element) { 270 271 var elements; 272 273 if (element.parentNode != null) { 274 275 element.parentNode.removeChild(element); 276 277 } 278 279 element.remove(); 280 281 282 283 elements = document.getElementsByName("errorMessageBox"); 284 285 if (0 == elements.length) { 286 287 var actionBox = document.getElementById("pas_cth_actionBox"); 288 289 if (actionBox.parentNode != null) { 290 291 actionBox.parentNode.removeChild(actionBox); 292 293 } 294 295 actionBox.remove(); 296 297 } 298 299 } 300 301 function pas_cth_js_popupMessage(abbr, msg) { 302 303 var box = document.getElementById("popupMessageBox") 304 305 box.innerHTML = msg; 306 307 box.style.position = "fixed"; 308 309 box.style.left = mousePosition.x + 100 + "px"; 310 311 box.style.top = mousePosition.y - 40 + "px"; 312 313 box.style.display = "inline"; 314 315 setTimeout(function () { 316 317 var p = document.getElementById("popupMessageBox") 318 319 p.innerHTML = ""; 320 321 p.style.display = "none"; 322 323 }, 2000); 324 325 } 326 327 // Process the xmlhttp.responseText that was echo'd during the AJAX call 328 329 function pas_cth_js_processResponse(response) { 330 331 if ("ABBREVIATION:{" == response.left("ABBREVIATION:{".length).toUpperCase()) { 332 333 abbr = response.right(response.length - "ABBREVIATION:{".length); 334 335 abbr = abbr.left(abbr.length - 1); 336 337 pas_cth_js_popupMessage(abbr, "color saved"); 338 339 document.getElementById("popupMessageBox").style.display = "inline"; 340 341 } else if ("EDITFILEOUTPUT:{" == response.left("EDITFILEOUTPUT:{".length).toUpperCase()) { 342 343 response = response.right(response.length - "EDITFILEOUTPUT:{".length); 344 345 response = response.left(response.length - 1); 346 347 processEditFile(response); 348 349 } else if ("DEBUG:{" == response.left("DEBUG:{".length).toUpperCase()) { 350 351 pas_cth_library.kill("pas_cth_actionBox"); 352 353 debugResponse = response.right(response.length - "debug:{".length); 354 355 debugResponse = debugResponse.left(debugResponse.length - 1); 356 357 358 box = pas_cth_js_createBox('debugBox', 'debug'); 359 360 box.innerHTML = debugResponse; 361 362 // Nothing special. We've got output from the PHP function, dump it to the screen. 136 363 137 364 } else { 138 365 139 return element.getElementsByTagName("*"); 140 141 } 142 143 } 144 145 function kill(element) { 146 147 if (element == null) { 148 149 return false; 150 151 } 152 153 if (element.parentNode != null) { 154 155 element.parentNode.removeChild(element); 156 157 } 158 159 element.remove(); 160 161 return true; 162 163 } 164 165 function searchTree(rootElement, tree, pointElement) { 166 167 var found = false; 168 169 170 171 if (rootElement == pointElement) { 172 173 return true; 174 366 if (response.length > 0) { 367 368 pas_cth_js_createBox("pas_cth_actionBox", "").innerHTML = response; 369 370 windowFlag = true; 371 372 } 373 374 } 375 376 } 377 378 function pas_cth_js_showBox() { 379 380 return pas_cth_library.createBox("pas_cth_actionBox"); 381 } 382 383 function pas_cth_js_createBox(id, className = "", parent = document.getElementsByTagName("body")[0], clickClose = false) { 384 385 var box = pas_cth_library.createBox(id, parent); 386 387 if (className.trim.length > 0) { 388 389 box.className = className; 390 391 } 392 393 394 395 if (clickClose) { 396 397 box.onclick= function () { 398 pas_cth_library.kill(this); } 175 399 } else { 176 400 177 for (ndx = 0; ndx < tree.length && ! found; ndx++) { 178 179 found = (tree[ndx] == pointElement ? true : false); 180 181 } 182 183 return found; 184 185 } 186 187 } 188 189 var windowFlag = false; 190 191 192 193 if (window.location.href.indexOf("manage_child_themes") >= 0) { 194 195 window.onclick = function (e) { 196 197 if (windowFlag) { 198 199 windowFlag = false; 200 201 return; 202 203 } 204 205 if (e.clientX == undefined || e.clientY == undefined) { 206 207 return; 208 209 } 210 211 212 213 var pointElement = null; 214 215 var actionBox = document.getElementById("pas_cth_actionBox"); 216 217 var errorMessageBox = document.getElementsByName("errorMessageBox")[0]; 218 219 220 221 pointElement = document.elementFromPoint(e.clientX, e.clientY); 222 223 224 225 var tree = getElementTree(actionBox); 226 227 var found = false; 228 229 found = searchTree(actionBox, tree, pointElement); 230 231 232 233 if (! found) { 234 235 tree = getElementTree(errorMessageBox); 236 237 found = searchTree(errorMessageBox, tree, pointElement); 238 239 } 240 241 242 243 if (! found) { 244 245 kill(actionBox); 246 247 kill(errorMessageBox); 248 249 } 250 251 } 252 253 } 254 255 256 257 // KillMe kills the error message boxes. 258 259 // After the last box has been destroyed, kill the actionBox div too. 260 261 function pas_cth_js_killMe(element) { 262 263 var elements; 264 265 if (element.parentNode != null) { 266 267 element.parentNode.removeChild(element); 268 269 } 270 271 element.remove(); 272 273 274 275 elements = document.getElementsByName("errorMessageBox"); 276 277 if (0 == elements.length) { 278 279 var actionBox = document.getElementById("pas_cth_actionBox"); 280 281 if (actionBox.parentNode != null) { 282 283 actionBox.parentNode.removeChild(actionBox); 284 285 } 286 287 actionBox.remove(); 288 289 } 290 291 } 292 293 function pas_cth_js_popupMessage(abbr, msg) { 294 295 var box = document.getElementById("popupMessageBox") 296 297 box.innerHTML = msg; 298 299 box.style.position = "fixed"; 300 301 box.style.left = mousePosition.x + 100 + "px"; 302 303 box.style.top = mousePosition.y - 40 + "px"; 304 305 box.style.display = "inline"; 306 307 setTimeout(function () { 308 309 var p = document.getElementById("popupMessageBox") 310 311 p.innerHTML = ""; 312 313 p.style.display = "none"; 314 315 }, 2000); 316 317 } 318 319 // Process the xmlhttp.responseText that was echo'd during the AJAX call 320 321 function pas_cth_js_processResponse(response) { 322 323 if ("ABBREVIATION:{" == response.left("ABBREVIATION:{".length).toUpperCase()) { 324 325 abbr = response.right(response.length - "ABBREVIATION:{".length); 326 327 abbr = abbr.left(abbr.length - 1); 328 329 pas_cth_js_popupMessage(abbr, "color saved"); 330 331 document.getElementById("popupMessageBox").style.display = "inline"; 332 333 } else if ("EDITFILEOUTPUT:{" == response.left("EDITFILEOUTPUT:{".length).toUpperCase()) { 334 335 response = response.right(response.length - "EDITFILEOUTPUT:{".length); 336 337 response = response.left(response.length - 1); 338 339 processEditFile(response); 340 341 } else if ("DEBUG:{" == response.left("DEBUG:{".length).toUpperCase()) { 342 343 actionBox = document.getElementById("pas_cth_actionBox"); 344 345 if (actionBox != null && actionBox != undefined) { 346 347 if (actionBox.parentNode != null) { 348 349 actionBox.parentNode.removeChild(actionBox); 350 351 } 352 353 actionBox.remove(); 354 355 } 356 357 debugResponse = response.right(response.length - "debug:{".length); 358 359 debugResponse = debugResponse.left(debugResponse.length - 1); 360 361 box = pas_cth_js_createBox('debugBox', 'debug'); 362 363 box.innerHTML = debugResponse; 364 365 // Nothing special. We've got output from the PHP function, dump it to the screen. 401 var dismissBTN = document.createElement("p") 402 403 dismissBTN.setAttribute("id", "dismissBox"); 404 405 box.appendChild(dismissBTN); 406 407 dismissBTN.innerHTML = "DISMISS"; 408 409 dismissBTN.onclick = function () { 410 411 pas_cth_library.kill("pas_cth_actionBox"); 412 } 413 414 } 415 416 return box; 417 418 } 419 420 function pas_cth_js_addCloseButton(id, parent, text) { 421 422 var element = document.createElement("p"); 423 424 element.setAttribute("id", id); 425 426 427 parent.appendChild(element); 428 429 element.innerHTML = text; 430 431 element.onclick = function () { 432 433 var myParent = this.parentNode; 434 435 var myGrandParent = myParent.parentNode; 436 437 438 439 if (myGrandParent != null) { 440 441 myGrandParent.removeChild(myParent); 442 443 myParent.remove(); 444 445 } 446 447 } 448 449 } 450 451 function getTopLeftPosition(obj = null) { 452 453 if (obj != null) { 454 455 return pas_cth_library.getPosition(obj); 366 456 367 457 } else { 368 458 369 if (response.length > 0) {370 371 pas_cth_js_createBox("pas_cth_actionBox", "").innerHTML = response;372 373 windowFlag = true;374 375 }376 377 }378 379 }380 381 function pas_cth_js_showBox() {382 383 return pas_cth_js_createBox("pas_cth_actionBox", "");384 385 }386 387 function pas_cth_js_createBox(id, className = "", parent = document.getElementsByTagName("body")[0], clickClose = false) {388 389 var box = document.getElementById(id);390 391 if (box != null && box != undefined) {392 393 if (box.parentNode != null) {394 395 box.parentNode.removeChild(box);396 397 }398 399 box.remove();400 401 }402 403 box = document.createElement("div");404 405 box.setAttribute("id", id);406 407 if (className.trim.length > 0) {408 409 box.className = className;410 411 }412 413 414 415 parent.appendChild(box);416 417 418 419 if (clickClose) {420 421 box.onclick= function () {422 423 if (this.parentNode != null) {424 425 this.parentNode.removeChild(this);426 427 }428 429 this.remove();430 431 }432 433 } else {434 435 var dismissBTN = document.createElement("p")436 437 dismissBTN.setAttribute("id", "dismissBox");438 439 box.appendChild(dismissBTN);440 441 dismissBTN.innerHTML = "DISMISS";442 443 dismissBTN.onclick = function () {444 445 var ab = document.getElementById("pas_cth_actionBox");446 447 if (ab.parentNode != null) {448 449 ab.parentNode.removeChild(ab);450 451 }452 453 ab.remove();454 455 }456 457 458 459 460 461 /*462 463 box.oncontextmenu = function () {464 465 box.style.width = "100%";466 467 box.style.height = "100%";468 469 box.style.position = "absolute";470 471 box.style.left = "180px";472 473 box.style.top = "40px";474 475 box.style.zIndex = 9999999;476 477 box.style.overflow = "scroll";478 479 box.style.marginTop = "0px";480 481 box.style.marginLeft = "0px";482 483 return false;484 485 }486 487 */488 489 }490 491 return box;492 493 }494 495 /*496 497 function findPos(obj) {498 499 var curleft = curtop = 0;500 501 if (obj.offsetParent) {502 503 do {504 505 curleft += obj.offsetLeft;506 507 curtop += obj.offsetTop;508 509 } while (obj = obj.offsetParent);510 511 }512 513 return {left:curleft ,top:curtop};514 515 }516 517 */518 519 function getPosition(element) {520 521 var rect = element.getBoundingClientRect();522 523 524 525 return {left : rect.left, top: rect.top, width : Math.abs(rect.right - rect.left), height : Math.abs(rect.bottom - rect.top) };526 527 }528 529 function pas_cth_js_addCloseButton(id, parent, text) {530 531 var element = document.createElement("p");532 533 element.setAttribute("id", id);534 535 // element.setAttribute("contentEditable", false);536 537 parent.appendChild(element);538 539 element.innerHTML = text;540 541 element.onclick = function () {542 543 var myParent = this.parentNode;544 545 var myGrandParent = myParent.parentNode;546 547 548 549 if (myGrandParent != null) {550 551 myGrandParent.removeChild(myParent);552 553 myParent.remove();554 555 }556 557 }558 559 }560 561 function getTopLeftPosition(obj = null) {562 563 if (obj != null) {564 565 return getPosition(obj);566 567 } else {568 569 459 return null; 570 460 … … 572 462 573 463 } 574 575 function displayError(str) {576 577 var box = document.getElementById("popupErrorMessage");578 579 var theBody = document.getElementsByTagName("body")[0];580 581 if (box != null) {582 583 if (box.parentNode != null) { box.parentNode.removeChild(box); }584 585 box.remove();586 587 }588 589 box = pas_cth_js_createBox("popupErrorMessage", "", theBody, true);590 591 box.appendChild(document.createTextNode(str));592 593 return box;594 595 } -
child-themes-helper/trunk/js/menu.js
r2057158 r2074973 155 155 var jsdata = JSON.parse(element.getAttribute("data-jsdata")); 156 156 157 var elementID = Date.now(); 157 var elementID = Date.now(); // clock ticks since midnight at the epoch. Guarantees a unique ID number. 158 158 159 159 var childGrid = document.getElementById("childGrid"); -
child-themes-helper/trunk/js/pasChildThemes.js
r2057158 r2074973 1 "use strict;" 1 2 /* pasChildThemes.js 2 3 3 4 * This file contains nearly pure JavaScript code. 4 5 5 * With the exception of XMLHttpRequest() and JSON, no other WordPress core, nor 3rd party JavaScript6 7 * libraries are used, herein.8 9 6 */ 10 7 … … 17 14 */ 18 15 16 if (typeof(String.prototype.trim) == "undefined") { 17 String.prototype.trim = function () { 18 return this.ltrim().rtrim(); 19 } 20 } 19 21 function pas_cth_js_selectFile(event) { 20 22 21 23 var element = document.getElementById(event.srcElement.dataset.elementid); 22 24 23 var xmlhttp = new XMLHttpRequest();24 25 var data = new FormData();26 27 25 var jsInput; 28 26 … … 107 105 } 108 106 107 function pas_cth_js_showWait() { 108 var body = document.getElementsByTagName("body")[0]; 109 body.style.cursor = "wait"; 110 } 111 function pas_cth_js_hideWait() { 112 var body = document.getElementsByTagName("body")[0]; 113 body.style.cursor = ""; 114 } 115 var pas_cth_js_spinTimer = 0; 116 var pas_cth_js_spinPosition = 0; 117 118 function pas_cth_js_spin() { 119 } 120 109 121 110 122 … … 121 133 function pas_cth_js_removeChildFile(element) { 122 134 123 var xmlhttp = new XMLHttpRequest();124 125 var data = new FormData();126 127 135 var jsInput = JSON.parse(element.getAttribute("data-jsdata")); 128 136 129 130 131 /* AJAX call to pas_cth_AJAXFunctions::verifyRemoveFile() 132 133 * in 'classes/class_ajax_functions.php' 137 var dataBlock = {}; 138 139 pas_cth_js_showWait(); 140 141 142 // $_POST[] values in pas_cth_AJAXFunctions::verifyRemoveFile() 143 dataBlock.directory = jsInput['directory']; 144 dataBlock.file = jsInput['file']; 145 146 var successCallback = function (response) { 147 if (response.length) { 148 pas_cth_js_processResponse(response); 149 pas_cth_js_hideWait(); 150 } else { 151 location.reload(); 152 } 153 } 154 var failureCallback = function (status, response) { 155 var msg = "400 Error:<br>" + status; 156 pas_cth_js_showBox().innerHTML = msg; 157 pas_cth_js_hideWait(); 158 } 159 160 pas_cth_js_AJAXCall(jsInput['action'], dataBlock, successCallback, failureCallback); 161 } 162 163 /* pas_cth_js_deleteChildFile() is called from an onclick event in a popup error box 164 165 * set up in pas_cth_AJAXFunctions::verifyRemoveFile() in 'classes/class_ajax_functions.php' 166 167 * 134 168 135 169 */ 136 170 137 xmlhttp.open("POST", ajaxurl, true); 138 139 140 141 data.append("action", jsInput['action']); // verifyRemoveFile 142 143 144 145 // $_POST[] values in pas_cth_AJAXFunctions::verifyRemoveFile() 146 147 data.append("directory", jsInput['directory'] ); 148 149 data.append("file", jsInput['file']); 150 151 152 153 154 155 xmlhttp.onreadystatechange = function () { 156 157 if (4 == xmlhttp.readyState) { 158 159 var response = (xmlhttp.responseText.length >= 1 ? 160 161 xmlhttp.responseText.left(xmlhttp.responseText.length - 1) : 162 163 xmlhttp.responseText); 164 165 166 167 switch (xmlhttp.status) { 168 169 case 200: // Everything is okay 170 171 if (response.length <= 0) { 172 173 location.reload(); 174 175 } else { 176 177 pas_cth_js_processResponse(response); 178 179 } 180 181 break; 182 183 184 185 case 400: 186 187 msg = "400 Error:<br>" + xmlhttp.statusText; 188 189 pas_cth_js_showBox().innerHTML = msg; 190 191 break; 192 171 function pas_cth_js_deleteChildFile(element) { 172 173 var jsInput = JSON.parse(element.getAttribute("data-jsdata")); 174 175 var dataBlock = {}; 176 177 pas_cth_js_showWait(); 178 179 180 // $_POST[] values in pas_cth_AJAXFunctions::deleteFile() 181 182 dataBlock.directory = jsInput['directory']; 183 dataBlock.file = jsInput['file']; 184 185 var successCallback = function (response) { 186 if (response.length) { 187 pas_cth_js_processResponse(response); 188 pas_cth_js_hideWait(); 189 } else { 190 location.reload(); 191 } 192 } 193 var failureCallback = function(status, response) { 194 var msg = "400 Error:<br>" + status; 195 pas_cth_js_showBox().innerHTML = msg; 196 pas_cth_js_hideWait(); 197 } 198 199 pas_cth_js_AJAXCall 200 (jsInput['action'], dataBlock, successCallback, failureCallback); 201 } 202 203 function pas_cth_js_successCallback(response) { 204 if (response.length) { 205 pas_cth_js_processResponse(response); 206 pas_cth_js_hideWait(); 207 } else { 208 location.reload(); 209 } 210 } 211 function pas_cth_js_failureCallback(status, response) { 212 var msg = "400 Error:<br>" + status; 213 pas_cth_js_showBox().innerHTML = msg; 214 pas_cth_js_hideWait(); 215 } 216 /* 217 218 * pas_cth_js_copyTemplateFile() responds to an onclick event set up pas_cth_AJAXFunctions::selectFile() 219 220 * in 'classes/class_ajax_functions.php' when a user clicks a file in the template theme files list. 221 222 */ 223 224 function pas_cth_js_copyTemplateFile(element) { 225 226 var jsInput = JSON.parse(element.getAttribute("data-jsdata")); 227 228 var dataBlock = {}; 229 230 231 // $_POST[] values in pas_cth_AJAXFunctions::verifyCopyFile() 232 233 dataBlock.directory = jsInput['directory']; 234 dataBlock.file = jsInput['file']; 235 236 pas_cth_js_showWait(); 237 238 var successCallback = function (response) { 239 if (response.length) { 240 pas_cth_js_processResponse(response); 241 pas_cth_js_hideWait(); 242 } else { 243 location.reload(); 244 } 245 } 246 var failureCallback = function (status, response) { 247 var msg = "400 Error:<br>" + status + "<HR>" + response; 248 pas_cth_js_showBox().innerHTML = msg; 249 pas_cth_js_hideWait(); 250 } 251 252 pas_cth_js_AJAXCall(jsInput['action'], dataBlock, successCallback, failureCallback); 253 } 254 255 function pas_cth_js_overwriteFile(element) { 256 257 var jsInput = JSON.parse(element.getAttribute("data-jsdata")); 258 259 var dataBlock = {}; 260 261 pas_cth_js_showWait(); 262 263 264 dataBlock.directory = jsInput['directory']; 265 dataBlock.file = jsInput['file']; 266 267 // copyFile 268 pas_cth_js_AJAXCall(jsInput['action'], dataBlock, pas_cth_js_successCallback, pas_cth_js_failureCallback); 269 } 270 271 function pas_cth_js_resetChildThemeForm(frm) { 272 var formElements = frm.elements, ndx; 273 for (ndx = 0; ndx < formElements.length; ndx++) { 274 formElements[ndx].style.backgroundColor = ""; 275 } 276 frm.reset(); 277 } 278 /* The pas_cth_js_createChildTheme() function processes the form in 279 280 * pas_cth_ChildThemesHelper::manage_child_themes() in file 'classes/class_childThemesHelper.php' 281 282 * without actually executing a "Submit" on that form. This prevents the page refresh and allows 283 284 * us to redirect to the admin_url("themes.php") page once the child theme has been created. 285 286 */ 287 288 function pas_cth_js_createChildTheme(element) { 289 var ndx = 0, 290 291 frm = element.form, 292 formElements = frm.elements, 293 dataBlock = {}, 294 jsInput, 295 action, 296 e, err = 0; 297 298 pas_cth_js_showWait(); 299 300 // Used to validate the data in the form before making the AJAX call to save the data and create the child theme. 301 this.test = function (elementValue = "", elementPattern = "", elementRequiredFlag = false) { 302 var re; 303 var result = false; 304 305 if (elementRequiredFlag) { 306 if (elementValue.length) { 307 if (elementPattern.length) { // element is required, value is not blank, pattern exists, return true if value matches pattern. 308 re = new RegExp(elementPattern); 309 result = re.test(elementValue); 310 } else { // element is required, value is not blank, no pattern specified, so any value will do, return true 311 result = true; 312 } 313 } else { // element is required, value is blank, return false; 314 result = false; 193 315 } 194 195 } 196 197 } 198 199 xmlhttp.send(data) 200 201 } 202 203 /* pas_cth_js_deleteChildFile() is called from an onclick event in a popup error box 204 205 * set up in pas_cth_AJAXFunctions::verifyRemoveFile() in 'classes/class_ajax_functions.php' 206 207 * 208 209 */ 210 211 function pas_cth_js_deleteChildFile(element) { 212 213 var xmlhttp = new XMLHttpRequest(); 214 215 var data = new FormData(); 216 217 var jsInput = JSON.parse(element.getAttribute("data-jsdata")); 218 219 220 221 // AJAX call to pas_cth_AJAXFunctions::deleteFile() in 'classes/class_ajax_functions.php' 222 223 xmlhttp.open("POST", ajaxurl, true); 224 225 data.append("action", jsInput['action']); 226 227 228 229 // $_POST[] values in pas_cth_AJAXFunctions::deleteFile() 230 231 data.append("directory", jsInput['directory'] ); 232 233 data.append("file", jsInput['file']); 234 235 236 237 238 239 xmlhttp.onreadystatechange = function () { 240 241 if (4 == xmlhttp.readyState) { 242 243 var response = (xmlhttp.responseText.length >= 1 ? 244 245 xmlhttp.responseText.left(xmlhttp.responseText.length - 1) : 246 247 xmlhttp.responseText); 248 249 250 251 switch (xmlhttp.status) { 252 253 case 200: // Everything is okay 254 255 if (response.length <= 0) { 256 257 location.reload(); 258 259 } else { 260 261 pas_cth_js_processResponse(response); 262 263 } 264 265 break; 266 267 268 269 case 400: 270 271 msg = "400 Error:<br>" + xmlhttp.statusText; 272 273 pas_cth_js_showBox().innerHTML = msg; 274 275 break; 276 316 } else { 317 if (elementPattern.length) { 318 if (elementValue.length) { // element is NOT required, value is not blank, pattern exists, return true if value matches pattern 319 re = new RegExp(elementPattern); 320 result = re.test(elementValue); 321 } else { // element is NOT required. value is blank. return true; 322 result = true; 323 } 324 } else { // element is NOT required, pattern is blank, return true 325 result = true; 277 326 } 278 279 } 280 281 } 282 283 xmlhttp.send(data); 284 285 } 286 287 /* 288 289 * pas_cth_js_copyTemplateFile() responds to an onclick event set up pas_cth_AJAXFunctions::selectFile() 290 291 * in 'classes/class_ajax_functions.php' when a user clicks a file in the template theme files list. 292 293 */ 294 295 function pas_cth_js_copyTemplateFile(element) { 296 297 var xmlhttp = new XMLHttpRequest(); 298 299 var data = new FormData(); 300 301 var jsInput = JSON.parse(element.getAttribute("data-jsdata")); 302 303 304 305 // AJAX call to pas_cth_AJAXFunctions::verifyCopyFile() in 'classes/class_ajax_functions.php' 306 307 xmlhttp.open("POST", ajaxurl, true); 308 309 data.append("action", jsInput['action']); 310 311 312 313 // $_POST[] values in pas_cth_AJAXFunctions::verifyCopyFile() 314 315 data.append("directory", jsInput['directory'] ); 316 317 data.append("file", jsInput['file']); 318 319 320 321 xmlhttp.onreadystatechange = function () { 322 323 if (4 == xmlhttp.readyState) { 324 325 var response = (1 <= xmlhttp.responseText.length ? 326 327 xmlhttp.responseText.left(xmlhttp.responseText.length - 1) : 328 329 xmlhttp.responseText); 330 331 332 333 switch (xmlhttp.status) { 334 335 case 200: // Everything is okay 336 337 if (response.length <= 0) { 338 339 location.reload(); 340 341 } else { 342 343 pas_cth_js_processResponse(response); 344 345 } 346 347 break; 348 349 350 351 case 400: 352 353 msg = "400 Error:<br>" + xmlhttp.statusText + "<HR>" + response; 354 355 pas_cth_js_showBox().innerHTML = msg; 356 357 break; 358 359 } 360 361 } 362 363 } 364 365 xmlhttp.send(data); 366 367 } 368 369 function pas_cth_js_overwriteFile(element) { 370 371 var xmlhttp = new XMLHttpRequest(); 372 373 var data = new FormData(); 374 375 var jsInput = JSON.parse(element.getAttribute("data-jsdata")); 376 377 378 379 // AJAX call to pas_cth_AJAXFunctions::copyFile() in 'classes/class_ajax_functions.php' 380 381 xmlhttp.open("POST", ajaxurl, true); 382 383 data.append("action", jsInput["action"]); // copyFile 384 385 386 387 // $_POST[] values in pas_cth_AJAXFunctions::copyFile() 388 389 data.append("directory", jsInput["directory"]); 390 391 data.append("file", jsInput["file"]); 392 393 394 395 xmlhttp.onreadystatechange = function () { 396 397 if (4 == xmlhttp.readyState) { 398 399 var response = (xmlhttp.responseText.length >= 1 ? 400 401 xmlhttp.responseText.left(xmlhttp.responseText.length - 1) : 402 403 xmlhttp.responseText); 404 405 406 407 switch (xmlhttp.status) { 408 409 case 200: // Everything is okay 410 411 if (response.length <= 0) { 412 413 location.reload(); 414 415 } else { 416 417 pas_cth_js_processResponse(response); 418 419 } 420 421 break; 422 423 424 425 case 400: // There was an error 426 427 msg = "400 Error:<br>" + xmlhttp.statusText; 428 429 pas_cth_js_showBox().innerHTML = msg; 430 431 break; 432 433 } 434 435 } 436 437 } 438 439 440 441 xmlhttp.send(data); 442 443 } 444 445 /* The pas_cth_js_createChildTheme() function processes the form in 446 447 * pas_cth_ChildThemesHelper::manage_child_themes() in file 'classes/class_childThemesHelper.php' 448 449 * without actually executing a "Submit" on that form. This prevents the page refresh and allows 450 451 * us to redirect to the admin_url("themes.php") page once the child theme has been created. 452 453 */ 454 455 function pas_cth_js_createChildTheme(element) { 456 457 var frm = element.form; 458 459 var formElements = frm.elements; 460 461 var xmlhttp = new XMLHttpRequest(); 462 463 var data = new FormData(); 464 465 var jsInput; 327 } 328 return result; 329 } 330 331 var outputMessage = ""; 332 333 for (ndx = 0; ndx < formElements.length; ndx++) { 334 e = formElements[ndx]; 335 if (! this.test(e.value, e.dataset.pattern, e.required) ) { 336 e.style.backgroundColor = "#FFFF90"; 337 outputMessage += (outputMessage.length ? "<hr>" + e.dataset.message : e.dataset.message); 338 err++; 339 } 340 } 341 if (err) { 342 var errorBox = pas_cth_library.displayError(outputMessage); 343 errorBox.style.width = "300px"; 344 errorBox.style.height = "300px"; 345 errorBox.style.overflowY = "scroll"; 346 errorBox.style.marginLeft = "-150px"; 347 errorBox.style.marginTop = "-150px"; 348 349 pas_cth_js_hideWait(); 350 351 return; 352 } 353 466 354 467 355 … … 482 370 483 371 case "INPUT": 484 485 data.append(formElements[ndx].name,486 487 formElements[ndx].value);488 372 if (formElements[ndx].name.toLowerCase() == "action") { 373 action = formElements[ndx].value; 374 } else { 375 dataBlock[formElements[ndx].name] = formElements[ndx].value; 376 } 489 377 break; 490 491 378 case "TEXTAREA": 492 493 data.append(formElements[ndx].name, 494 495 formElements[ndx].value); 496 379 dataBlock[formElements[ndx].name] = formElements[ndx].value; 497 380 break; 498 499 381 case "SELECT": 500 501 data.append(formElements[ndx].name, 502 503 formElements[ndx].options[formElements[ndx].selectedIndex].value); 504 382 dataBlock[formElements[ndx].name] = formElements[ndx].options[formElements[ndx].selectedIndex].value; 505 383 break; 506 507 384 case "BUTTON": 508 509 385 // ignore 510 511 386 break; 512 513 } 514 515 } 516 387 } 388 389 } 390 var successCallback = function (response) { 391 if ("SUCCESS:" == response.left("SUCCESS:".length)) { 392 location.href='/wp-admin/themes.php'; 393 } else if (response.length >= 1) { 394 pas_cth_js_processResponse(response); 395 pas_cth_js_hideWait(); 396 } 397 } 517 398 // AJAX call to pas_cth_AJAXFunctions::createChildTheme() in 'classes/class_ajax_functions.php' 518 519 xmlhttp.open("POST", ajaxurl, true); 520 521 522 523 xmlhttp.onreadystatechange = function () { 524 525 if (4 == xmlhttp.readyState) { 526 527 // strip the AJAX zero from wp_die() WORDPRESS ONLY 528 529 var response = (xmlhttp.responseText.length >= 1 ? 530 531 xmlhttp.responseText.left(xmlhttp.responseText.length - 1) : 532 533 xmlhttp.responseText); 534 535 536 537 switch (xmlhttp.status) { 538 539 case 200: // Everything is Okay 540 541 /* If responseText is not empty, there might be a request to overwrite 542 543 * or a request to delete that needs to be displayed. 544 545 * else, reload the page. 546 547 * <= 1 accounts for the AJAX return of zero that sometimes shows up 548 549 * despite my best efforts to avoid that. 550 551 */ 552 553 if ("SUCCESS:" == response.left("SUCCESS:".length)) { 554 555 location.href="/wp-admin/themes.php"; 556 557 } else if (response.length >= 1) { 558 559 pas_cth_js_processResponse(response); 560 561 } 562 563 break; 564 565 566 567 case 400: // There was an error 568 569 msg = "400 Error:<br>" + xmlhttp.statusText + "<br>" + response; 570 571 pas_cth_js_showBox().innerHTML = msg; 572 573 break; 574 575 } 576 577 } 578 579 } 580 581 xmlhttp.send(data); 399 pas_cth_js_AJAXCall(action, dataBlock, successCallback, pas_cth_js_failureCallback); 582 400 583 401 } … … 600 418 601 419 } 420 pas_cth_js_hideWait(); 602 421 603 422 } … … 620 439 621 440 } 441 pas_cth_js_hideWait(); 622 442 623 443 } … … 629 449 function pas_cth_js_SetOption(element) { 630 450 631 var xmlhttp = new XMLHttpRequest(); 632 633 var data = new FormData(); 634 635 636 637 data.append('action', 'saveOptions'); 638 639 data.append('optionName', element.name); 640 641 data.append('optionValue', element.value); 642 643 644 645 xmlhttp.open("POST", ajaxurl, true); 646 647 xmlhttp.onreadystatechange = function () { 648 649 if (4 == xmlhttp.readyState) { 650 651 // strip the AJAX zero from wp_die() WORDPRESS ONLY 652 653 var response = (xmlhttp.responseText.length >= 1 ? 654 655 xmlhttp.responseText.left(xmlhttp.responseText.length - 1) : 656 657 xmlhttp.responseText); 658 659 660 661 switch (xmlhttp.status) { 662 663 case 200: // Everything is Okay 664 665 /* If responseText is not empty, there might be a request to overwrite 666 667 * or a request to delete that needs to be displayed. 668 669 * else, reload the page. 670 671 * <= 1 accounts for the AJAX return of zero that sometimes shows up 672 673 * despite my best efforts to avoid that. 674 675 */ 676 677 if ("SUCCESS:" == response.left("SUCCESS:".length)) { 678 679 location.href="/wp-admin/themes.php" 680 681 } else if (response.length >= 1) { 682 683 pas_cth_js_showBox().innerHTML = response; 684 685 } 686 687 break; 688 689 690 691 case 400: // There was an error 692 693 msg = "400 Error:<br>" + xmlhttp.statusText + "<br>" + response; 694 695 pas_cth_js_showBox().innerHTML = msg; 696 697 break; 698 699 } 700 701 } 702 703 } 704 705 xmlhttp.send(data); 706 707 } 708 709 function pas_cth_js_mouseOver(element) { 710 711 var jsdata = JSON.parse(element.getAttribute("data-jsdata")); 712 713 var themeType = jsdata['themeType']; 714 715 var filename = jsdata['file']; 716 717 var msg; 718 719 var mID = document.getElementById("hoverPrompt"); 720 721 722 723 724 725 switch (themeType.toLowerCase()) { 726 727 case "child": 728 729 msg = "File: <font class='fileHighlight'>" + filename + "</font><br>" + 730 731 "<div id='innerLine'>" + 732 733 " <font class='actionPrompt'>Left Click</font> to <font class='redHighlight'>Remove</font> from the Child Theme.<br>" + 734 735 " <br>" + 736 737 " <font class='actionPrompt'>Right Click</font> to <font class='redHighlight'>Edit</font> the file." + 738 739 "</div>"; 451 var dataBlock = {}; 452 453 454 dataBlock.optionName = element.name; 455 dataBlock.optionValue = element.value; 456 457 var successCallback = function (response) { 458 alert("Here"); 459 if ("SUCCESS:" == response.left("SUCCESS:".length)) { 460 location.href = "/wp-admin/themes.php"; 461 } else if (response.length >= 1) { 462 pas_cth_js_showBox().innerHTML = response; 463 } 464 pas_cth_js_hideWait(); 465 } 466 467 pas_cth_js_AJAXCall('saveOptions', dataBlock, successCallback, pas_cth_js_failureCallback); 468 } 469 470 function showChild() { 471 472 document.getElementById("childGrid").style.display = "inline"; 473 474 document.getElementById("parentGrid").style.display = "none"; 475 476 } 477 478 function showParent() { 479 480 document.getElementById("childGrid").style.display = "none"; 481 482 document.getElementById("parentGrid").style.display = "inline"; 483 484 } 485 486 function debugTip(action, msg) { 487 488 switch (action.toLowerCase()) { 489 490 case "show": 491 492 var tipBox = document.createElement("div") 493 494 tipBox.setAttribute("id", "tipBox") 495 496 tipBox.setAttribute("class", "tipBox"); 497 498 tipBox.innerHTML = msg; 499 500 501 502 tipBox.style.left = (mousePosition.x + 10) + "px"; 503 504 tipBox.style.top = (mousePosition.y + 10) + "px"; 505 506 document.getElementsByTagName("body")[0].appendChild(tipBox); 740 507 741 508 break; 742 509 743 case "parent": 744 745 msg = "File: <font class='fileHighlight'>" + filename + "</font><br>" + 746 747 "<div id='innerLine'>" + 748 749 " <font class='actionPrompt'>Left Click</font> to <font class='redHighlight'>Copy</font> to the Child Theme.<br>" + 750 751 " <br>" + 752 753 " <font class='actionPrompt'>Right Click</font> to <font class='redHighlight'>Edit</font> the file." + 754 755 "</div>"; 510 case "hide": 511 512 kill(document.getElementById("tipBox")); 756 513 757 514 break; … … 759 516 } 760 517 761 mID.innerHTML = msg; 762 763 mID.style.cssText = "visibility:visible;"; 764 765 mID.style.left = mousePosition["x"] + 25 + "px"; 766 767 mID.style.top = mousePosition["y"] + "px"; 768 769 } 770 771 function pas_cth_js_mouseOut(element) { 772 773 var mID = document.getElementById("hoverPrompt"); 774 775 mID.style.visibility = "hidden"; 776 777 mID.innerHTML = ""; 778 779 } 780 781 function showChild() { 782 783 document.getElementById("childGrid").style.display = "inline"; 784 785 document.getElementById("parentGrid").style.display = "none"; 786 787 } 788 789 function showParent() { 790 791 document.getElementById("childGrid").style.display = "none"; 792 793 document.getElementById("parentGrid").style.display = "inline"; 794 795 } 796 797 function debugTip(action, msg) { 798 799 switch (action.toLowerCase()) { 800 801 case "show": 802 803 var tipBox = document.createElement("div") 804 805 tipBox.setAttribute("id", "tipBox") 806 807 tipBox.setAttribute("class", "tipBox"); 808 809 tipBox.innerHTML = msg; 810 811 812 813 tipBox.style.left = (mousePosition.x + 10) + "px"; 814 815 tipBox.style.top = (mousePosition.y + 10) + "px"; 816 817 document.getElementsByTagName("body")[0].appendChild(tipBox); 818 819 break; 820 821 case "hide": 822 823 kill(document.getElementById("tipBox")); 824 825 break; 826 827 } 828 829 } 830 831 function pas_cth_validateField(element) { 832 833 if (element.value.trim().length == 0) { 834 518 } 519 520 function pas_cth_validateField(element = null) { 521 522 if (element == null) { 835 523 return; 836 837 }838 839 if ( element.pattern.trim().length == 0) {524 } 525 var strValue = element.value.trim(); 526 var ptrn = element.dataset.pattern.trim(); 527 if (strValue.length == 0 || ptrn.length == 0) { 840 528 841 529 return; … … 843 531 } 844 532 845 var re = new RegExp( element.pattern);533 var re = new RegExp(ptrn); 846 534 847 535 var box; … … 857 545 858 546 859 if (! re.test( element.value)) {547 if (! re.test(strValue)) { 860 548 861 549 box = pas_cth_js_createBox(boxID, className, parent, onclickFunction); 862 550 863 box.innerHTML = element. getAttribute("data-message")+ "<br><br>Click on this messagebox to close it";551 box.innerHTML = element.dataset.message + "<br><br>Click on this messagebox to close it"; 864 552 865 553 } -
child-themes-helper/trunk/js/tabs.js
r2057158 r2074973 96 96 } 97 97 } 98 document.getElementsByTagName("body")[0].style.cursor = "wait"; 98 99 pas_cth_js_AJAXCall("setDefaultChildTheme", dataBlock, reloadFN); 99 100 } -
child-themes-helper/trunk/readme.txt
r2073439 r2074973 6 6 Requires at least: 4.7.0 7 7 Tested up to: 5.1.1 8 Stable tag: 2. 1.18 Stable tag: 2.2 9 9 Requires PHP: 5.6.31 10 10 License: GPLv2 or later … … 15 15 == Description == 16 16 1. **The Child Themes Helper is a tool....** 17 ...developed for those child theme developers who write or modify PHP code in the development of their child themes. Previous versions of the Child Themes Helper required the child theme being modified be the activated theme. That is no longer the case. However, you will still need to set a child theme to be an "Active Theme" on the Options tab, but it does not have to be the activated theme.17 ...developed for those child theme developers who **write or modify PHP code in the development of their child themes**. Previous versions of the Child Themes Helper required the child theme being modified be the activated theme. That is no longer the case. However, you will still need to set a child theme to be an "Active Theme" on the Options tab, but it does not have to be the activated theme. 18 18 19 19 1. **Copy files from Parent Theme to Child Theme** … … 37 37 38 38 1. **Notes** 39 - *PHP Versions*40 The Child Themes Helper plugin has been tested and found to work with PHP 5.6.31, PHP 7.2.7, and PHP 7.3.0.41 42 39 - *Troubleshooting Installation Issues* 43 The primary filename and primary folder name of the Child Themes Helper changed (in v2.1) from pasChildThemes and pasChildThemes.php to child-themes-helper and child-themes-helper.php. This *may* cause some problems during the installation. If you experience problems, I suggest that you deactivate the plugin and delete it. Then reinstall the Child Themes Helper v2.1 from the WordPress Plugins repository. 44 45 - *What would you like to see in this plugin?* 40 If you are upgrading the Child Themes Helper from a version prior to version 2.0, you might have problems installing the upgrade. 41 The most frequent problem is that the upgrade fails and displays a nasty message at the top of the plugins page. WordPress then politely deactivates the Child Themes Helper plugin. 42 If you experience this problem, the solution is to: **deactivate the plugin** if it isn't already deactivated. **Delete the plugin**. And then **reinstall the Child Themes Helper** directly from the WordPress plugins repository. 43 44 New with Child Themes Helper v2.0, the primary folder name ("~/plugins/pasChildThemes) and the primary file name (pasChildThemes.php) were changed to (~/plugins/child-themes-helper) and (child-themes-helper.php) to make the plugin match the WordPress assigned slug. 45 Under certain circumstances, probably due to either browser caching or website caching, this causes the upgrade to fail. 46 47 - *PHP Developer Tool* 48 The Child Themes Helper is meant as a PHP developer's tool to help the WordPress PHP developer make direct changes to a child theme's PHP code. It is **NOT** a GUI, drag -n- drop tool to help non-developers build a child theme. 49 50 - *Child Themes Helper on GitHub* 51 The GitHub repository for this plugin can be found [here](https://github.com/PaulSwarthout/pasChildThemes). Stable versions are usually found on the WordPress SVN repository. Intermediate versions are often found on GitHub. 52 53 - *Child Themes Helper access* 54 The Child Themes Helper is accessed from the WordPress dashboard under the heading "Child Themes Helper". The menu item may be found immediately below the *Appearance* Dashboard menu item. 55 56 - *Platform Support* 57 The Child Themes Helper was developed on Microsoft IIS 10 and tested on both Windows' and Linux -based web servers. 58 59 - *If you like the Child Themes Helper plugin, please consider writing a review [here](https://wordpress.org/support/plugin/child-themes-helper/reviews/#new-post). Thank you.* 60 61 - *Development versions* 62 Versions 2\.1, 1\.2 are available for download and install. 46 63 47 64 - *Screenshot* … … 56 73 In a future release, there will be a lock feature on the options page to prevent accidental overwrites of the screenshot file. Also, in a future release, there will be the ability to select an existing graphic and crop it as necessary, instead of generating one. 57 74 58 - *Child Themes Helper access*59 The Child Themes Helper is accessed from the WordPress dashboard under the heading "Child Themes Helper". The menu item may be found immediately below the *Appearance* Dashboard menu item.60 61 - *Platform Support*62 The Child Themes Helper plugin has been tested with both WordPress running on a Windows server and with WordPress running on a Linux server. Development is done on a Windows platform. If you find any compatibility issues with Linux, please let me know.63 64 - *Child Themes Helper on GitHub*65 The GitHub repository for this plugin can be found [here](https://github.com/PaulSwarthout/pasChildThemes). Stable versions are usually found on the WordPress SVN repository. Intermediate versions are often found on GitHub.66 67 - *Development versions*68 Versions 1\.2, 1\.1\.3 and 1\.0 are available for download and install.69 70 75 - *Known Bug* 71 76 Although the Child Themes Helper plugin is mostly responsive, the Edit File functionality doesn't work very well on small screens. But does anybody actually modify themes on smartphones and tablets? (Please say 'No'). … … 76 81 - This plugin may be installed through the usual method of installing and activating WordPress plugins. The first time you open the Child Themes Helper plugin page on your dashboard, it will look a bit different from the previous version. Instead of a stack of menu options on the dashboard menu, there is a single menu option "Child Themes Helper" and it opens to a page featuring tabs across the top -- one for each area of functionality. Previous versions worked on the currently active Child Theme, but effective with this release, you are free to modify any child theme that has been created. You will still need to specify the "active" theme, but it does not have to be the "activated" theme. The first time you use it, you will only be able to set an active theme on the Options tab, or create a new child theme. 77 82 78 - If you experience problems installing or activating version 2.1 , after having an earlier version installed, please deactivate it, delete it, and then reinstall it. The primary folder name and the primary plugin filename changed with this release. It may conflict with an earlier version and crash upon install.83 - If you experience problems installing or activating version 2.1 or later, after having an earlier version installed, please deactivate it, delete it, and then reinstall it. The primary folder name and the primary plugin filename changed with this release. It may conflict with an earlier version and crash upon install. 79 84 80 85 - The Child Themes Helper plugin requires an active theme be specified (Options tab). Unlike previous versions, this "active theme" does NOT have to be the currently "Activated" theme. … … 89 94 == Frequently Asked Questions == 90 95 96 = Do I have to keep the Child Themes Helper installed and/or activated? = 97 98 No. You should at least deactivate all plugins and themes that you are not using. That will decrease your website's load times. The Child Themes Helper leaves nothing behind that is required for you to be able to use your child themes or temporary graphics files. Feel free to uninstall it and/or deactivate it once you've completed your child theme. 99 91 100 = What is next? = 92 101 … … 100 109 = Where I can see the Child Themes Helper in action? = 101 110 102 I am glad you asked. Starting with version 1.2 (version 2. 1is not yet installed on that page), you can visit [my demo page](http://www.1acsi.com) and take it for a test drive. Create your own child theme. Copy files to the newly created child theme. Generate screenshots. Change the Screenshot options. In short, put it through its paces. And don't worry about screwing up the website. It's there for that purpose.111 I am glad you asked. Starting with version 1.2 (version 2.2 is not yet installed on that page), you can visit [my demo page](http://www.1acsi.com) and take it for a test drive. Create your own child theme. Copy files to the newly created child theme. Generate screenshots. Change the Screenshot options. In short, put it through its paces. And don't worry about screwing up the website. It's there for that purpose. 103 112 104 113 = I generated a screenshot but it didn't change. Why not? = … … 106 115 You did nothing wrong. Your browser will cache the screenshot file to help your website to load more quickly. The solution is to clear your browser's image cache. [Here's a good article](https://kb.iu.edu/d/ahic) that I found that gives great directions on how to accomplish that. 107 116 108 = What does the "Generate ScreenShot" option do? =109 110 The WordPress Themes page displays a graphic for each theme. A newly created child theme does not have a graphic. The Generate ScreenShot menu option creates a temporary graphic. Generally, developers will use a copy of a header image for their screenshot. But rather than leaving it blank until later, the Child Themes Helper plugin will create a temporary graphic which displays the child theme name, the parent theme name, a message indicating that the child theme was created using the Child Themes Helper and the Child Themes Helper's developer's web address. It is expected that the developer will want to replace this temporary graphic with their own custom graphic at a later time. Please check out [my demo page](http://www.1acsi.com) where you are welcome to take the Child Themes Helper plugin for a test drive.111 112 117 = Why create a screenshot? I'm just going to delete it later anyway. = 113 118 … … 116 121 == Screenshots == 117 122 118 1. The files for the Child Theme are displayed in the left-hand pane. The name, 'MyChildTheme' for example 119 is the name of your Child Theme. The page scrolls. 120 2. The files for the Template / Parent Theme's, or the Child Theme's parent theme, are displayed in the right-hand pane. 121 For this example, the Child Theme was created as a child of the 'Twenty Sixteen' theme and it's name appears at the top. The page scrolls. 123 1. When you first install the Child Themes Helper, and attempt to open the dashboard page, Child Themes Helper, you will see a long description, which you can hide by click the "Expert Mode" checkbox at the top. Below the description will be a list of your installed themes. 124 2. If you don't already have a Child Theme, you can click the Create Child Theme tab at the top and create one. 125 3. Once you have created a child theme, the first dialog will list the installed themes plus your new child theme. Click the large radio button to select your child theme. Note: this does NOT activate your child theme. 126 4. If your screen is wide enough, you will see the child theme files listed on the left and the parent theme files listed on the right. If you are using a mobile device or a tablet that is not wide enough, then you will only see the child theme files list or the parent theme files list, and a button where you can switch back and forth. 127 5. Right click on a file in either the child theme files or the parent theme files to open a popup menu. On the child theme files list, you will see the ability to remove a file from the child theme or edit the file. On the parent theme files list, you will see the ability to copy the file to the child theme or view the contents of the file. 128 6. Choosing Edit Child Theme file will let you open the file in a simple editor. 129 7. After copying the footer.php file from the parent theme to the child theme, we have opened it in the simple editor. 130 8. The Screenshot tab lets you create a temporary graphic that will display on the Dashboard >> Appearance >> Themes page for your child theme. Most developers will replace this image during their child theme development, but it makes a nice placeholder in the meantime. 131 9. You can change the font, the text color, and the background color of your temporary graphic. You can add fonts to the plugin's ~/assets/fonts folder and they will be automatically available. Click the Generate Screenshot button and a window will open with a copy of your new temporary graphic. Go to the website's themes page to see it as it was intended to be used. 122 132 123 133 == Changelog == 134 135 = 2.2 = 136 - Added "wait" cursors in the places where there is a delay in processing ... i.e., it's not immediate. It's lightning fast in the test environment, but not as fast when it has to move large quantities of data through the Internet. 137 138 - Modified the AJAX calls to be consistent. 139 140 - I discovered that some of my vanilla Javascript function names conflicted with function names in other plugins. I created a vanilla Javascript library which contains those functions. From a structural perspective, think "CLASS", but Javascript doesn't support classes. 124 141 125 142 = 2.1.1 =
Note: See TracChangeset
for help on using the changeset viewer.