Child Theme Configurator - Version 2.2.0

Version Description

  • Cross domain Parse error
  • Showing "reconfigure" message on new install
  • Manual upgrade Pro from plugin
  • Add pre_option stylesheet and template filters to Preview class
  • Use child theme name on duplicate
  • Ability to force/unforce dependency
  • Identify and handle imported stylesheets, convert to links
  • Fixes related to testing if CTC Pro is installed
Download this release

Release Info

Developer lilaeamedia
Plugin Icon 128x128 Child Theme Configurator
Version 2.2.0
Comparing to
See all releases

Code changes from version 1.7.9 to 2.2.0

Files changed (45) hide show
  1. child-theme-configurator.php +56 -39
  2. css/chld-thm-cfg.min.css +0 -1
  3. css/{chld-thm-cfg.css → chldthmcfg.css} +347 -319
  4. includes/class-ctc-admin.php +0 -1621
  5. includes/class-ctc-preview.php +0 -72
  6. includes/class-ctc-ui.php +0 -243
  7. includes/classes/Admin.php +2146 -0
  8. includes/classes/Analysis.php +262 -0
  9. includes/{class-ctc-css.php → classes/CSS.php} +728 -319
  10. includes/{class-ctc.php → classes/Core.php} +67 -24
  11. includes/classes/Packer.php +398 -0
  12. includes/classes/Preview.php +164 -0
  13. includes/classes/UI.php +344 -0
  14. includes/classes/Upgrade.php +294 -0
  15. includes/forms/addl_panels.php +6 -6
  16. includes/forms/addl_tabs.php +2 -2
  17. includes/forms/backups.php +1 -1
  18. includes/forms/current-theme.php +8 -0
  19. includes/forms/debug-toggle.php +9 -0
  20. includes/forms/file-form-buttons.php +13 -0
  21. includes/forms/file.php +3 -1
  22. includes/forms/fileform.php +7 -28
  23. includes/forms/files.php +4 -9
  24. includes/forms/main.php +39 -16
  25. includes/forms/notices.php +116 -0
  26. includes/forms/parent-child.php +456 -282
  27. includes/forms/query-selector.php +5 -4
  28. includes/forms/related.php +1 -1
  29. includes/forms/rule-value.php +1 -0
  30. includes/forms/settings-errors.php +60 -0
  31. includes/forms/tabs.php +19 -21
  32. includes/forms/theme-menu.php +19 -0
  33. includes/forms/zipform.php +9 -0
  34. includes/help/de_DE.php +79 -81
  35. includes/help/en_US.php +50 -52
  36. js/chld-thm-cfg.js +0 -1540
  37. js/chld-thm-cfg.min.js +0 -1
  38. js/chldthmcfg.js +2165 -0
  39. js/chldthmcfg.min.js +2 -0
  40. js/ctcgrad.js +192 -192
  41. js/jquery-ui-selectmenu.js +1715 -1715
  42. js/spectrum.js +1 -1
  43. lang/child-theme-configurator-de_DE.mo +0 -0
  44. lang/child-theme-configurator-de_DE.po +953 -539
  45. lang/child-theme-configurator.pot +118 -80
child-theme-configurator.php CHANGED
@@ -5,49 +5,66 @@ if ( !defined( 'ABSPATH' ) ) exit;
5
  /*
6
  Plugin Name: Child Theme Configurator
7
  Plugin URI: http://www.childthemeconfigurator.com
8
- Description: Create child themes and customize styles, templates and functions. Enqueues stylesheets and web fonts. Handles rgba, vendor-prefixes and more.
9
- Version: 1.7.9
10
  Author: Lilaea Media
11
  Author URI: http://www.lilaeamedia.com
12
- Text Domain: chld_thm_cfg
13
  Domain Path: /lang
14
  License: GPLv2
15
- Copyright (C) 2014-2015 Lilaea Media
16
  */
17
-
18
- defined( 'CHLD_THM_CFG_DIR' ) or
19
- define( 'CHLD_THM_CFG_DIR', dirname( __FILE__ ) );
20
- defined( 'CHLD_THM_CFG_URL' ) or
21
- define( 'CHLD_THM_CFG_URL', plugin_dir_url( __FILE__ ) );
22
- defined( 'CHLD_THM_CFG_OPTIONS' ) or
23
- define( 'CHLD_THM_CFG_OPTIONS', 'chld_thm_cfg_options' );
24
-
25
- if ( is_admin() )
26
- include_once( dirname( __FILE__ ) . '/includes/class-ctc.php' );
27
-
28
- if ( isset( $_GET['preview_ctc'] ) )
29
- include_once( dirname( __FILE__ ) . '/includes/class-ctc-preview.php' );
30
-
31
- add_filter( 'style_loader_src', 'chld_thm_cfg_plugins_version', 10, 2 );
32
 
33
- function chld_thm_cfg_plugins_version( $src, $handle ) {
34
- if ( strstr( $src, get_stylesheet() ) )
35
- $src = preg_replace( "/ver=(.*?)(\&|$)/", 'ver=' . wp_get_theme()->Version . "$2", $src );
36
- return $src;
37
- }
38
-
39
- register_uninstall_hook( __FILE__, 'chld_thm_cfg_uninstall' );
40
-
41
- function chld_thm_cfg_uninstall() {
42
- delete_option( CHLD_THM_CFG_OPTIONS );
43
- delete_option( CHLD_THM_CFG_OPTIONS . '_configvars' );
44
- delete_option( CHLD_THM_CFG_OPTIONS . '_dict_qs' );
45
- delete_option( CHLD_THM_CFG_OPTIONS . '_dict_sel' );
46
- delete_option( CHLD_THM_CFG_OPTIONS . '_dict_query' );
47
- delete_option( CHLD_THM_CFG_OPTIONS . '_dict_rule' );
48
- delete_option( CHLD_THM_CFG_OPTIONS . '_dict_val' );
49
- delete_option( CHLD_THM_CFG_OPTIONS . '_dict_seq' );
50
- delete_option( CHLD_THM_CFG_OPTIONS . '_sel_ndx' );
51
- delete_option( CHLD_THM_CFG_OPTIONS . '_val_ndx' );
52
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
 
5
  /*
6
  Plugin Name: Child Theme Configurator
7
  Plugin URI: http://www.childthemeconfigurator.com
8
+ Description: When using the Customizer is not enough - Create child themes and customize styles, templates, functions and more.
9
+ Version: 2.2.0
10
  Author: Lilaea Media
11
  Author URI: http://www.lilaeamedia.com
12
+ Text Domain: child-theme-configurator
13
  Domain Path: /lang
14
  License: GPLv2
15
+ Copyright (C) 2014-2016 Lilaea Media
16
  */
17
+ // define CTC constants
18
+ defined( 'LF' ) or define( 'LF', "\n" );
19
+ defined( 'CHLD_THM_CFG_DIR' ) or define( 'CHLD_THM_CFG_DIR', dirname( __FILE__ ) );
20
+ defined( 'CHLD_THM_CFG_URL' ) or define( 'CHLD_THM_CFG_URL', plugin_dir_url( __FILE__ ) );
21
+ defined( 'CHLD_THM_CFG_OPTIONS' ) or define( 'CHLD_THM_CFG_OPTIONS', 'chld_thm_cfg_options' );
 
 
 
 
 
 
 
 
 
 
22
 
23
+ // activate autoloader
24
+ spl_autoload_register( 'chld_thm_cfg_autoload' );
25
+
26
+ function chld_thm_cfg_autoload( $class ) {
27
+ $base = str_replace( 'ChildThemeConfigurator', '', $class );
28
+ $file = dirname( __FILE__ ) . '/includes/classes/' . ( '' == $base ? 'Core' : $base ) . '.php';
29
+ if ( file_exists( $file ) )
30
+ include_once( $file );
31
+ }
32
+
33
+ // load CTC Core for admin calls
34
+ if ( is_admin() )
35
+ add_action( 'plugins_loaded', 'ChildThemeConfigurator::init', 5 );
36
+
37
+ // handle CTC Preview
38
+ if ( isset( $_GET['preview_ctc'] ) ):
39
+ // replace core preview function with CTCP function for quick preview
40
+ remove_action( 'setup_theme', 'preview_theme' );
41
+ new ChildThemeConfiguratorPreview();
42
+ endif;
43
+
44
+ // append timestamp to linked stylesheets to force cache refresh
45
+ add_filter( 'style_loader_src', 'chld_thm_cfg_version', 10, 2 );
46
+
47
+ function chld_thm_cfg_version( $src, $handle ) {
48
+ if ( strstr( $src, get_stylesheet() ) ):
49
+ $src = preg_replace( "/ver=(.*?)(\&|$)/", 'ver=' . wp_get_theme()->Version . "$2", $src );
50
+ endif;
51
+ return $src;
52
+ }
53
+
54
+ // remove configuration data on uninstall
55
+ register_uninstall_hook( __FILE__, 'chld_thm_cfg_uninstall' );
56
+
57
+ function chld_thm_cfg_uninstall() {
58
+ delete_site_option( CHLD_THM_CFG_OPTIONS );
59
+ delete_site_option( CHLD_THM_CFG_OPTIONS . '_configvars' );
60
+ delete_site_option( CHLD_THM_CFG_OPTIONS . '_dict_qs' );
61
+ delete_site_option( CHLD_THM_CFG_OPTIONS . '_dict_sel' );
62
+ delete_site_option( CHLD_THM_CFG_OPTIONS . '_dict_query' );
63
+ delete_site_option( CHLD_THM_CFG_OPTIONS . '_dict_rule' );
64
+ delete_site_option( CHLD_THM_CFG_OPTIONS . '_dict_val' );
65
+ delete_site_option( CHLD_THM_CFG_OPTIONS . '_dict_seq' );
66
+ delete_site_option( CHLD_THM_CFG_OPTIONS . '_dict_token' );
67
+ delete_site_option( CHLD_THM_CFG_OPTIONS . '_sel_ndx' );
68
+ delete_site_option( CHLD_THM_CFG_OPTIONS . '_val_ndx' );
69
+ }
70
 
css/chld-thm-cfg.min.css DELETED
@@ -1 +0,0 @@
1
- body{background:0 0!important}p{line-height:1.4}.wrap h1,.wrap h2{font-size:23px;font-weight:400;line-height:29px;margin:.5em 0 1em}a.nav-tab,a.nav-tab:active,a.nav-tab:focus{outline:0;-moz-box-shadow:none;-webkit-box-shadow:none;box-shadow:none}h2 .ctc-recent-tab,h2 .nav-tab{font-size:13px;padding:6px 8px;font-weight:700;line-height:24px}.ctc-option-panel-container{position:relative;min-height:1100px;width:100%;overflow:auto}.ctc-three-col{-moz-columns:3;-moz-column-gap:3em;-webkit-columns:3;-webkit-column-gap:3em;columns:3;column-gap:3em}#all_styles_panel ul li,#ctc_recent_selectors ul li{margin:0}#all_styles_panel ul li a,#ctc_recent_selectors ul li a{text-decoration:none;font-size:.8em;line-height:1.2;word-wrap:break-word;display:block;padding:.5em}#all_styles_panel ul li a:focus,#all_styles_panel ul li a:hover,#ctc_recent_selectors ul li a:focus,#ctc_recent_selectors ul li a:hover{background-color:#fff;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}#view_child_options_panel,#view_parnt_options_panel{white-space:pre;overflow:auto;font-family:monospace;word-wrap:normal}.ctc-option-panel{visibility:hidden;position:absolute;width:100%;top:0;left:0;padding:10px 0 0}.ctc-recent-container{top:0;right:0;position:absolute;max-width:200px;width:17%;display:none;overflow:auto;visibility:visible;left:inherit;background-color:#E4E4E4}#ctc_recent_selectors{padding:0 8px}#live_preview_panel iframe{width:100%;min-height:1100px}a.ctc-recent-tab{float:right;border:1px solid #ccc;border-bottom:none;background-color:#E4E4E4;color:#555;display:inline-block;text-decoration:none;margin:-1px 0 0;box-shadow:none;-moz-box-shadow:none;-webkit-box-shadow:none;outline:0}.ctc-input-cell,.ctc-input-cell-wide{margin-right:2%;display:block;float:left}.ctc-option-panel-active{visibility:visible}.ctc-swatch{display:block;float:left;font-size:16px;padding:0;line-height:1;overflow:hidden}.ctc-hidden{display:none}.ctc-swatch.ctc-specific{min-height:60px;max-height:100px;max-width:100px;margin:0 2% 0 0}.ctc-selector-inner-container .ctc-swatch.ctc-specific{max-width:13%}.ctc-parent-row{clear:both;position:relative;margin:4px 0}.ctc-input-cell{width:30%;max-width:350px;word-wrap:break-word}.ctc-selector-inner-container .ctc-input-cell{width:35%}.ctc-input-cell-wide{width:60%}.ctc-input-cell-wide input[type=text]{width:100%}.ctc-input-cell-wide textarea{width:100%;height:200px;white-space:pre;overflow:auto;font-family:inherit;word-wrap:normal}.ctc-selector-inner-container .ctc-button-cell,.ctc-selector-inner-container .ctc-input-cell.ctc-button-cell{width:8%}.ctc-textarea-button-cell{margin:4px 10px 15px;text-align:right;float:right}.ctc-rewrite-toggle{font-size:.8em;padding-left:1em;display:none;outline:0}.ctc-delete-input{font-size:.8em;float:right;color:#8b0000;text-decoration:none}.ctc-selector-container{clear:both;background:#f9f9f9;border:1px solid #ddd;padding:10px;position:absolute;min-height:300px;width:80%;left:15%;top:30px;display:none;z-index:99999;-moz-box-shadow:0 2px 10px rgba(0,0,0,.3);-webkit-box-shadow:0 2px 10px rgba(0,0,0,.3);box-shadow:0 2px 10px rgba(0,0,0,.3)}.ctc-selector-inner-container{position:relative;min-height:300px;overflow:auto}.ctc-status-icon.failure,.ctc-status-icon.success{display:block;float:right;position:relative;height:16px;width:16px;margin:4px}.ctc-exit{display:block;width:20px;height:20px;position:absolute;top:-13px;right:-13px;transition:none!important;z-index:999;border:3px solid #f9f9f9;-moz-border-radius:16px;-webkit-border-radius:16px;border-radius:16px}.ctc-exit:active,.ctc-exit:hover{background-position:right top}.ctc-selector-row{clear:both;margin:0;padding:8px 0;border-top:1px solid #ddd;border-bottom:1px solid #fff}.ctc-input-row{clear:both;margin:4px 0;padding:4px 0;border-bottom:1px solid #ddd;position:relative}.howto.sep{border-bottom:1px solid #fff;margin-bottom:.5em;padding-bottom:.5em}.ctc-selector-cell{float:left;width:30%;margin-right:2%}.ctc-child-input-cell{display:block;float:left;margin-right:2%}.ctc-child-input-cell-container{float:left;width:40%;margin-right:2%}.ctc-child-input-cell-container label{float:left;clear:both;width:100px;margin-right:2%}.ctc-disabled{opacity:.5}.ctc-select{max-width:100%}.ctc-child-input-cell input[type=text].ctc-input-wide{width:200px}#ctc_additional_css_label{cursor:pointer}#ctc_additional_css_label span{white-space:nowrap}.clearfix:after,.clearfix:before{content:' ';display:table;margin:0;padding:0}.clear,.clearfix:after{clear:both}.ie7 .clearfix{zoom:1}.smaller{font-size:.85em}.writable{color:red}.ui-state-focus,.ui-state-hover,.ui-widget-content .ui-state-focus,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-focus,.ui-widget-header .ui-state-hover{background-color:#DADADA;color:#212121}.ui-menu .ui-menu-item{position:relative;margin:0;padding:3px 1em 3px .4em;cursor:pointer;min-height:0;overflow:hidden;text-overflow:ellipsis;max-width:450px}.ctc-section-toggle{position:relative;cursor:pointer}.ctc-section-toggle:after{content:"\f140";font:400 20px/1 dashicons;color:#999;vertical-align:bottom}.ctc-section-toggle.open:after{content:"\f142"}a.ctc-section-toggle,a.ctc-section-toggle:active,a.ctc-section-toggle:hover,a.ctc-section-toggle:visited{text-decoration:none;float:right;font-size:.85em;box-shadow:none;-moz-box-shadow:none;-webkit-box-shadow:none;outline:0}.ctc-section-toggle-content{display:none;position:relative;margin:0;padding:1px 0}.ctc-theme-only{margin:0;padding:0;position:relative}h3.theme-name{margin:.25em 0;font-size:1.2em}.ctc-theme-option{max-width:250px}.ctc-theme-option-left{float:left;width:40%;margin-right:5%}.ctc-theme-option-right{float:right;width:55%;margin-right:0;font-size:.9em;line-height:1.3}.ctc-theme-option-image{height:auto;width:100%;border:1px solid #ddd}.ui-widget-content{border:1px solid #aaa;background-color:#fff}.ui-widget-header{border:1px solid #aaa;background-color:#ccc;font-weight:700}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #d3d3d3;font-weight:400;color:#555}.ui-state-focus,.ui-widget-content .ui-state-active,.ui-widget-content .ui-state-focus,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-active,.ui-widget-header .ui-state-focus,.ui-widget-header .ui-state-hover{font-weight:400;color:#212121}.ui-selectmenu-menu{padding:0;margin:0;position:absolute;top:0;left:0;display:none}.ui-selectmenu-menu .ui-menu{overflow:auto;max-height:372px;margin-top:0;overflow-x:hidden}.ui-selectmenu-menu .ui-menu .ui-menu-item{padding:6px}.ui-selectmenu-open{display:block}.ui-selectmenu-button{display:inline-block;overflow:hidden;position:relative;text-decoration:none;cursor:pointer;min-width:200px}.ui-selectmenu-button span.ui-icon{right:.5em;left:auto;margin-top:-10px;position:absolute;top:50%}.ui-icon-triangle-1-s:before{display:inline-block;-webkit-font-smoothing:antialiased;font:400 20px/1 dashicons;content:"\f140"}.ui-selectmenu-button span.ui-selectmenu-text{text-align:left;padding:.4em 2.1em .4em 1em;display:block;line-height:1.4;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}#get_pro_panel h1{font-size:1.75em;color:#c64200}#get_pro_panel h3{font-size:1.4em;margin-bottom:0}#get_pro_panel p{font-size:1em;margin:.5em 0}.ctc-input-cell .update-nag,.ctc-input-cell-wide.update-nag{margin:0}.ctc-input-cell-wide.update-nag{margin-bottom:1em}#get_pro_panel ul,.ctc-input-cell-wide.update-nag ul{list-style:square}#get_pro_panel li,.ctc-input-cell-wide.update-nag li{margin-left:2em}#get_pro_panel h3 a{display:block;padding:5px 10px;background-color:#c64200;color:#fff;text-decoration:none;text-align:center}#get_pro_panel h3 a:hover{background-color:#FF902E;color:#fff}#get_pro_panel img{max-width:100%;height:auto}.sp-container{position:absolute;top:0;left:0;display:inline-block;z-index:9999994;overflow:hidden}.sp-container.sp-flat,.sp-top{position:relative}.sp-container,.sp-container *{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.sp-top{width:100%;display:inline-block}.sp-alpha-handle,.sp-color,.sp-dragger,.sp-hue,.sp-sat,.sp-slider,.sp-top-inner,.sp-val{position:absolute}.sp-top-inner{top:0;left:0;bottom:0;right:0}.sp-color{top:0;left:0;bottom:0;right:20%}.sp-hue{top:0;right:0;bottom:0;left:84%;height:100%}.sp-clear-enabled .sp-hue{top:33px;height:77.5%}.sp-fill{padding-top:80%}.sp-sat,.sp-val{top:0;left:0;right:0;bottom:0}.sp-alpha-enabled .sp-top{margin-bottom:18px}.sp-alpha-enabled .sp-alpha{display:block}.sp-alpha-handle{top:-4px;bottom:-4px;width:6px;left:50%;cursor:pointer;border:1px solid #000;background:#fff;opacity:.8}.sp-alpha{display:none;bottom:-14px;right:0;left:0;height:8px}.sp-alpha-inner{border:1px solid #333}.sp-clear{display:none}.sp-clear.sp-clear-display{background-position:center}.sp-clear-enabled .sp-clear{display:block;position:absolute;top:0;right:0;bottom:0;left:84%;height:28px}.sp-alpha,.sp-alpha-handle,.sp-clear,.sp-container,.sp-container button,.sp-container.sp-dragging .sp-input,.sp-dragger,.sp-preview,.sp-replacer,.sp-slider{-webkit-user-select:none;-moz-user-select:-moz-none;-o-user-select:none;user-select:none}.sp-container.sp-buttons-disabled .sp-button-container,.sp-container.sp-input-disabled .sp-input-container,.sp-container.sp-palette-buttons-disabled .sp-palette-button-container,.sp-initial-disabled .sp-initial,.sp-palette-disabled .sp-palette-container,.sp-palette-only .sp-picker-container{display:none}.sp-sat{background-image:-webkit-gradient(linear,0 0,100% 0,from(#FFF),to(rgba(204,154,129,0)));background-image:-webkit-linear-gradient(left,#FFF,rgba(204,154,129,0));background-image:-moz-linear-gradient(left,#fff,rgba(204,154,129,0));background-image:-o-linear-gradient(left,#fff,rgba(204,154,129,0));background-image:-ms-linear-gradient(left,#fff,rgba(204,154,129,0));background-image:linear-gradient(to right,#fff,rgba(204,154,129,0));-ms-filter:"progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr=#FFFFFFFF, endColorstr=#00CC9A81)";filter:progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr='#FFFFFFFF', endColorstr='#00CC9A81')}.sp-val{background-image:-webkit-gradient(linear,0 100%,0 0,from(#000),to(rgba(204,154,129,0)));background-image:-webkit-linear-gradient(bottom,#000,rgba(204,154,129,0));background-image:-moz-linear-gradient(bottom,#000,rgba(204,154,129,0));background-image:-o-linear-gradient(bottom,#000,rgba(204,154,129,0));background-image:-ms-linear-gradient(bottom,#000,rgba(204,154,129,0));background-image:linear-gradient(to top,#000,rgba(204,154,129,0));-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#00CC9A81, endColorstr=#FF000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00CC9A81', endColorstr='#FF000000')}.sp-hue{background:-moz-linear-gradient(top,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red 100%);background:-ms-linear-gradient(top,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red 100%);background:-o-linear-gradient(top,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red 100%);background:-webkit-gradient(linear,left top,left bottom,from(red),color-stop(.17,#ff0),color-stop(.33,#0f0),color-stop(.5,#0ff),color-stop(.67,#00f),color-stop(.83,#f0f),to(red));background:-webkit-linear-gradient(top,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red 100%);background:linear-gradient(to bottom,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red 100%)}.sp-1{height:17%;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0000', endColorstr='#ffff00')}.sp-2{height:16%;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff00', endColorstr='#00ff00')}.sp-3{height:17%;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ff00', endColorstr='#00ffff')}.sp-4{height:17%;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ffff', endColorstr='#0000ff')}.sp-5{height:16%;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0000ff', endColorstr='#ff00ff')}.sp-6{height:17%;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff00ff', endColorstr='#ff0000')}.sp-hidden{display:none!important}.sp-cf:after,.sp-cf:before{content:"";display:table}.sp-cf:after{clear:both}@media (max-device-width:480px){.sp-color{right:40%}.sp-hue{left:63%}.sp-fill{padding-top:60%}}.sp-dragger{border-radius:5px;height:5px;width:5px;border:1px solid #fff;background:#000;cursor:pointer;top:0;left:0}.sp-slider{top:0;cursor:pointer;height:3px;left:-1px;right:-1px;border:1px solid #000;background:#fff;opacity:.8}.sp-container{border-radius:0;background-color:#ECECEC;border:1px solid #f0c49B;padding:0}.sp-clear,.sp-color,.sp-container,.sp-container button,.sp-container input,.sp-hue{font:400 12px "Lucida Grande","Lucida Sans Unicode","Lucida Sans",Geneva,Verdana,sans-serif;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}.sp-top{margin-bottom:3px}.sp-clear,.sp-color,.sp-hue{border:1px solid #666}.sp-input-container{float:right;width:100px;margin-bottom:4px}.sp-initial-disabled .sp-input-container,.sp-input{width:100%}.sp-input{font-size:12px!important;border:1px inset;padding:4px 5px;margin:0;background:0 0;border-radius:3px;color:#222}.sp-input:focus{border:1px solid orange}.sp-input.sp-validation-error{border:1px solid red;background:#fdd}.sp-palette-container,.sp-picker-container{float:left;position:relative;padding:10px 10px 300px;margin-bottom:-290px}.sp-picker-container{width:172px;border-left:solid 1px #fff}.sp-palette-container{border-right:solid 1px #ccc;max-width:60px}.sp-palette-only .sp-palette-container{border:0}.sp-palette .sp-thumb-el{display:block;position:relative;float:left;cursor:pointer}.sp-palette .sp-thumb-el.sp-thumb-active,.sp-palette .sp-thumb-el:hover{border-color:orange}.sp-thumb-el{position:relative}.sp-initial{float:left;border:1px solid #333}.sp-initial span{width:30px;height:25px;border:none;display:block;float:left;margin:0}.sp-initial .sp-clear-display{background-position:center}.sp-button-container,.sp-palette-button-container{float:right}.sp-replacer{margin:0;overflow:hidden;cursor:pointer;padding:4px;display:inline-block;border:1px solid #91765d;background:#eee;color:#333;vertical-align:middle}.sp-replacer.sp-active,.sp-replacer:hover{border-color:#F0C49B;color:#111}.sp-replacer.sp-disabled{cursor:default;border-color:silver;color:silver}.sp-dd{padding:2px 0;height:16px;line-height:16px;float:left;font-size:10px;font-family:sans-serif}.sp-preview{width:25px;height:20px;border:1px solid #222;margin-right:5px;float:left;z-index:0}.sp-palette{max-width:220px}.sp-palette .sp-thumb-el{width:16px;height:16px;margin:2px 1px;border:1px solid #d0d0d0}.sp-container{padding-bottom:0}.sp-container button{background-color:#eee;background-image:-webkit-linear-gradient(top,#eee,#ccc);background-image:-moz-linear-gradient(top,#eee,#ccc);background-image:-ms-linear-gradient(top,#eee,#ccc);background-image:-o-linear-gradient(top,#eee,#ccc);background-image:linear-gradient(to bottom,#eee,#ccc);border:1px solid #ccc;border-bottom:1px solid #bbb;border-radius:3px;color:#333;font-size:14px;line-height:1;padding:5px 4px;text-align:center;text-shadow:0 1px 0 #eee;vertical-align:middle}.sp-container button:hover{background-color:#ddd;background-image:-webkit-linear-gradient(top,#ddd,#bbb);background-image:-moz-linear-gradient(top,#ddd,#bbb);background-image:-ms-linear-gradient(top,#ddd,#bbb);background-image:-o-linear-gradient(top,#ddd,#bbb);background-image:linear-gradient(to bottom,#ddd,#bbb);border:1px solid #bbb;border-bottom:1px solid #999;cursor:pointer;text-shadow:0 1px 0 #ddd}.sp-container button:active{border:1px solid #aaa;border-bottom:1px solid #888;-webkit-box-shadow:inset 0 0 5px 2px #aaa,0 1px 0 0 #eee;-moz-box-shadow:inset 0 0 5px 2px #aaa,0 1px 0 0 #eee;-ms-box-shadow:inset 0 0 5px 2px #aaa,0 1px 0 0 #eee;-o-box-shadow:inset 0 0 5px 2px #aaa,0 1px 0 0 #eee;box-shadow:inset 0 0 5px 2px #aaa,0 1px 0 0 #eee}.sp-cancel{font-size:11px;color:#d93f3f!important;margin:0 5px 0 0;padding:2px;vertical-align:middle;text-decoration:none}.sp-cancel:hover{color:#d93f3f!important;text-decoration:underline}.sp-palette span.sp-thumb-active,.sp-palette span:hover{border-color:#000}.sp-alpha,.sp-preview,.sp-thumb-el{position:relative;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.sp-alpha-inner,.sp-preview-inner,.sp-thumb-inner{display:block;position:absolute;top:0;left:0;bottom:0;right:0}.sp-palette .sp-thumb-inner{background-position:50% 50%;background-repeat:no-repeat}.sp-palette .sp-thumb-light.sp-thumb-active .sp-thumb-inner{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIVJREFUeNpiYBhsgJFMffxAXABlN5JruT4Q3wfi/0DsT64h8UD8HmpIPCWG/KemIfOJCUB+Aoacx6EGBZyHBqI+WsDCwuQ9mhxeg2A210Ntfo8klk9sOMijaURm7yc1UP2RNCMbKE9ODK1HM6iegYLkfx8pligC9lCD7KmRof0ZhjQACDAAceovrtpVBRkAAAAASUVORK5CYII=)}.sp-palette .sp-thumb-dark.sp-thumb-active .sp-thumb-inner{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAMdJREFUOE+tkgsNwzAMRMugEAahEAahEAZhEAqlEAZhEAohEAYh81X2dIm8fKpEspLGvudPOsUYpxE2BIJCroJmEW9qJ+MKaBFhEMNabSy9oIcIPwrB+afvAUFoK4H0tMaQ3XtlrggDhOVVMuT4E5MMG0FBbCEYzjYT7OxLEvIHQLY2zWwQ3D+9luyOQTfKDiFD3iUIfPk8VqrKjgAiSfGFPecrg6HN6m/iBcwiDAo7WiBeawa+Kwh7tZoSCGLMqwlSAzVDhoK+6vH4G0P5wdkAAAAASUVORK5CYII=)}.sp-clear-display{background-repeat:no-repeat;background-position:center;background-image:url(data:image/gif;base64,R0lGODlhFAAUAPcAAAAAAJmZmZ2dnZ6enqKioqOjo6SkpKWlpaampqenp6ioqKmpqaqqqqurq/Hx8fLy8vT09PX19ff39/j4+Pn5+fr6+vv7+wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAP8ALAAAAAAUABQAAAihAP9FoPCvoMGDBy08+EdhQAIJCCMybCDAAYUEARBAlFiQQoMABQhKUJBxY0SPICEYHBnggEmDKAuoPMjS5cGYMxHW3IiT478JJA8M/CjTZ0GgLRekNGpwAsYABHIypcAgQMsITDtWJYBR6NSqMico9cqR6tKfY7GeBCuVwlipDNmefAtTrkSzB1RaIAoXodsABiZAEFB06gIBWC1mLVgBa0AAOw==)}
 
css/{chld-thm-cfg.css → chldthmcfg.css} RENAMED
@@ -1,16 +1,43 @@
1
  body {
2
- background:none !important;
3
  }
4
  p {
5
- line-height:1.4;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  }
7
- .wrap h1, .wrap h2 {
8
  font-size: 23px;
9
  font-weight: 400;
10
  line-height: 29px;
11
  margin: .5em 0 1em;
12
  }
13
- a.nav-tab, a.nav-tab:focus, a.nav-tab:active {
14
  outline: none;
15
  -moz-box-shadow: none;
16
  -webkit-box-shadow: none;
@@ -22,30 +49,33 @@ a.nav-tab, a.nav-tab:focus, a.nav-tab:active {
22
  line-height:1;
23
  height:2em;*/
24
  }
25
- h2 .nav-tab, h2 .ctc-recent-tab {
26
  font-size: 13px;
27
  padding: 6px 8px;
28
  font-weight: 700;
29
- line-height: 24px;
 
 
 
 
30
  }
31
  .ctc-option-panel-container {
32
  position: relative;
33
  min-height: 1100px;
34
- width:100%;
35
  overflow: auto;
36
  }
37
  .ctc-three-col {
38
- -moz-columns:3;
39
- -moz-column-gap:3em;
40
- -webkit-columns:3;
41
- -webkit-column-gap:3em;
42
- columns:3;
43
- column-gap:3em;
44
  }
45
  #ctc_recent_selectors ul li, #all_styles_panel ul li {
46
  margin: 0;
47
  }
48
-
49
  #ctc_recent_selectors ul li a, #all_styles_panel ul li a {
50
  text-decoration: none;
51
  font-size: .8em;
@@ -54,21 +84,18 @@ h2 .nav-tab, h2 .ctc-recent-tab {
54
  display: block;
55
  padding: .5em;
56
  }
57
-
58
  #ctc_recent_selectors ul li a:hover, #ctc_recent_selectors ul li a:focus, #all_styles_panel ul li a:hover, #all_styles_panel ul li a:focus {
59
  background-color: #fff;
60
  -webkit-box-shadow: none;
61
  -moz-box-shadow: none;
62
  box-shadow: none;
63
  }
64
-
65
  #view_child_options_panel, #view_parnt_options_panel {
66
  white-space: pre;
67
  overflow: auto;
68
  font-family: monospace;
69
  word-wrap: normal;
70
  }
71
-
72
  .ctc-option-panel {
73
  visibility: hidden;
74
  position: absolute;
@@ -76,22 +103,21 @@ h2 .nav-tab, h2 .ctc-recent-tab {
76
  width: 100%;
77
  top: 0;
78
  left: 0;
79
- padding: 10px 0 0;
80
- /* transition: width 1s ease;
81
  -moz-transition: width 1s ease;
82
  -webkit-transition: width 1s ease;
83
  -o-transition: width 1s ease; */
84
  }
85
  .ctc-recent-container {
86
- top:0;
87
- right:0;
88
- position:absolute;
89
  max-width: 200px;
90
  width: 17%;
91
  display: none;
92
  overflow: auto;
93
- visibility:visible;
94
- left:inherit;
95
  background-color: #E4E4E4;
96
  }
97
  #ctc_recent_selectors {
@@ -102,27 +128,66 @@ h2 .nav-tab, h2 .ctc-recent-tab {
102
  min-height: 1100px;
103
  }
104
  a.ctc-recent-tab {
105
- float:right;
106
- border:1px solid #ccc;
107
  border-bottom: none;
108
  background-color: #E4E4E4;
109
  color: #555;
110
  display: inline-block;
111
  text-decoration: none;
112
  margin: -1px 0 0 0;
113
- /* margin: 1px 0 -1px; */
114
  box-shadow: none;
115
- -moz-box-shadow:none;
116
  -webkit-box-shadow: none;
117
- outline:none;
118
  }
119
  .ctc-recent-tab h3 {
120
  }
121
-
122
  .ctc-option-panel-active {
123
  visibility: visible;
124
  }
125
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
  .ctc-swatch {
127
  display: block;
128
  float: left;
@@ -131,11 +196,9 @@ a.ctc-recent-tab {
131
  line-height: 1;
132
  overflow: hidden;
133
  }
134
-
135
  .ctc-hidden {
136
  display: none;
137
  }
138
-
139
  .ctc-swatch.ctc-specific {
140
  min-height: 60px;
141
  max-height: 100px;
@@ -144,17 +207,15 @@ a.ctc-recent-tab {
144
  border: 1px solid #ddd;*/
145
  }
146
  .ctc-selector-inner-container .ctc-swatch.ctc-specific {
147
- max-width:13%;
148
  }
149
  .ctc-parent-row {
150
  clear: both;
151
  position: relative;
152
  margin: 4px 0;
153
  }
154
-
155
  .ctc-parent-value {
156
  }
157
-
158
  .ctc-input-cell {
159
  display: block;
160
  float: left;
@@ -164,7 +225,7 @@ a.ctc-recent-tab {
164
  word-wrap: break-word;
165
  }
166
  .ctc-selector-inner-container .ctc-input-cell {
167
- width:35%;
168
  }
169
  .ctc-input-cell-wide {
170
  display: block;
@@ -172,40 +233,38 @@ a.ctc-recent-tab {
172
  width: 60%;
173
  margin-right: 2%;
174
  }
175
-
176
  .ctc-input-cell-wide input[type="text"] {
177
  width: 100%;
178
  }
179
-
180
- .ctc-input-cell-wide textarea {
181
  width: 100%;
182
  height: 200px;
 
 
 
183
  white-space: pre;
184
  overflow: auto;
185
  font-family: inherit;
186
  word-wrap: normal;
187
  }
188
-
 
 
189
  .ctc-save-input {
190
  }
191
-
192
  .ctc-selector-inner-container .ctc-button-cell, .ctc-selector-inner-container .ctc-input-cell.ctc-button-cell {
193
  width: 8%;
194
  }
195
-
196
  .ctc-textarea-button-cell {
197
  margin: 4px 10px 15px;
198
  /*width: 85px;*/
199
  text-align: right;
200
  float: right;
201
  }
202
-
203
  .ctc-selector-link {
204
  }
205
-
206
  .ctc-selector-handle {
207
  }
208
-
209
  .ctc-rewrite-toggle {
210
  font-size: 0.8em;
211
  padding-left: 1em;
@@ -214,11 +273,10 @@ a.ctc-recent-tab {
214
  }
215
  .ctc-delete-input {
216
  font-size: 0.8em;
217
- float:right;
218
  color: darkred;
219
- text-decoration:none;
220
  }
221
-
222
  .ctc-selector-container {
223
  clear: both;
224
  background: #f9f9f9;
@@ -235,18 +293,15 @@ a.ctc-recent-tab {
235
  -webkit-box-shadow: 0 2px 10px rgba(0,0,0,0.3);
236
  box-shadow: 0 2px 10px rgba(0,0,0,0.3);
237
  }
238
-
239
  .ctc-selector-inner-container {
240
  position: relative;
241
  min-height: 300px;
242
  /*max-height: 500px;*/
243
  overflow: auto;
244
  }
245
-
246
  .ctc-status-icon {
247
- /*max-width: 4%;*/
248
  }
249
-
250
  .ctc-status-icon.success {
251
  display: block;
252
  float: right;
@@ -255,7 +310,6 @@ a.ctc-recent-tab {
255
  width: 16px;
256
  margin: 4px;
257
  }
258
-
259
  .ctc-status-icon.failure {
260
  display: block;
261
  float: right;
@@ -264,7 +318,6 @@ a.ctc-recent-tab {
264
  width: 16px;
265
  margin: 4px;
266
  }
267
-
268
  .ctc-exit {
269
  display: block;
270
  width: 20px;
@@ -279,14 +332,11 @@ a.ctc-recent-tab {
279
  -webkit-border-radius: 16px;
280
  border-radius: 16px;
281
  }
282
-
283
  .ctc-exit:hover, .ctc-exit:active {
284
  background-position: right top;
285
  }
286
-
287
  .ctc-query-heading {
288
  }
289
-
290
  .ctc-selector-row {
291
  clear: both;
292
  margin: 0;
@@ -294,7 +344,6 @@ a.ctc-recent-tab {
294
  border-top: 1px solid #ddd;
295
  border-bottom: 1px solid #fff;
296
  }
297
-
298
  .ctc-input-row {
299
  clear: both;
300
  margin: 4px 0;
@@ -302,92 +351,63 @@ a.ctc-recent-tab {
302
  border-bottom: 1px solid #ddd;
303
  position: relative;
304
  }
305
-
306
  .ctc-selector-value {
307
  }
308
  .howto.sep {
309
  border-bottom: 1px solid #fff;
310
- margin-bottom: .5em;
311
- padding-bottom: .5em;
 
 
 
 
 
 
312
  }
313
  .ctc-selector-cell {
314
  float: left;
315
  width: 30%;
316
  margin-right: 2%;
317
  }
318
-
319
  .ctc-child-input-cell {
320
  display: block;
321
  float: left;
322
  margin-right: 2%;
323
  }
324
-
325
  .ctc-child-input-cell-container {
326
  float: left;
327
  width: 40%;
328
  margin-right: 2%;
329
  }
330
-
331
  .ctc-child-input-cell-container label {
332
  float: left;
333
  clear: both;
334
  width: 100px;
335
  margin-right: 2%;
336
  }
337
-
338
  .ctc-child-input-cell input[type="text"] {
339
  /*width:60px;*/
340
  }
341
-
342
  .ctc-disabled {
343
  opacity: 0.5;
344
  }
345
-
346
  .ctc-select {
347
  max-width: 100%;
348
  }
349
-
350
  .ctc-child-input-cell input[type="text"].ctc-input-wide {
351
  width: 200px;
352
  }
353
-
354
  #ctc_additional_css_label {
355
  cursor: pointer;
356
  }
357
-
358
  #ctc_additional_css_label span {
359
  white-space: nowrap;
360
  }
361
-
362
- .clearfix:after, .clearfix:before {
363
- content: ' ';
364
- display: table;
365
- margin: 0;
366
- padding: 0;
367
- }
368
-
369
- .clearfix:after, .clear {
370
- clear: both;
371
- }
372
-
373
- .ie7 .clearfix {
374
- zoom: 1;
375
- }
376
-
377
- .smaller {
378
- font-size: .85em;
379
- }
380
-
381
- .writable {
382
- color: red;
383
- }
384
-
385
  /* added in 1.5.4 because it is not being loaded by the admin */
386
  .ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus {
387
  background-color: #DADADA;
388
  color: #212121;
389
  }
390
-
391
  .ui-menu .ui-menu-item {
392
  position: relative;
393
  margin: 0px;
@@ -398,7 +418,6 @@ a.ctc-recent-tab {
398
  text-overflow: ellipsis;
399
  max-width: 450px;
400
  }
401
-
402
  /*** Added in 1.6.0 for new options ***/
403
  .ctc-section-toggle {
404
  /*margin:0;
@@ -406,55 +425,54 @@ a.ctc-recent-tab {
406
  position: relative;
407
  cursor: pointer;
408
  }
409
-
410
- .ctc-section-toggle:after {
411
  content: "\f140";
412
- font: 400 20px/1 dashicons;
 
 
 
413
  color: #999;
414
- vertical-align: bottom;
 
 
 
415
  }
416
-
417
- .ctc-section-toggle.open:after {
418
  content: "\f142";
419
  }
420
  a.ctc-section-toggle, a.ctc-section-toggle:hover, a.ctc-section-toggle:active, a.ctc-section-toggle:visited {
421
  text-decoration: none;
422
- float:right;
423
- font-size:.85em;
424
- box-shadow:none;
425
- -moz-box-shadow:none;
426
- -webkit-box-shadow:none;
427
- outline:none;
428
  }
429
  .ctc-section-toggle-content {
430
  display: none;
431
  position: relative;
432
- margin:0;
433
- padding:1px 0;
434
  }
435
-
436
  /*** Added in 1.6.0 for new Theme chooser ***/
437
  .ctc-theme-only {
438
  margin: 0;
439
  padding: 0;
440
  position: relative;
441
  }
442
-
443
  h3.theme-name {
444
  margin: .25em 0;
445
  font-size: 1.2em;
446
  }
447
-
448
  .ctc-theme-option {
449
  max-width: 250px;
450
  }
451
-
452
  .ctc-theme-option-left {
453
  float: left;
454
  width: 40%;
455
  margin-right: 5%;
456
  }
457
-
458
  .ctc-theme-option-right {
459
  float: right;
460
  width: 55%;
@@ -462,42 +480,38 @@ h3.theme-name {
462
  font-size: .9em;
463
  line-height: 1.3;
464
  }
465
-
466
  .ctc-theme-option-image {
467
  height: auto;
468
  width: 100%;
469
  border: 1px solid #ddd;
470
  }
471
-
 
 
472
  /* jquery UI widget classes */
473
 
474
  .ui-widget-content {
475
  border: 1px solid #aaa;
476
  background-color: #fff;
477
  }
478
-
479
  .ui-widget-header {
480
  border: 1px solid #aaa;
481
  background-color: #ccc;
482
  font-weight: bold;
483
  }
484
-
485
  .ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default {
486
  border: 1px solid #d3d3d3;
487
  font-weight: normal;
488
  color: #555555;
489
  }
490
-
491
  .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus {
492
  font-weight: normal;
493
  color: #212121;
494
  }
495
-
496
  .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active {
497
  font-weight: normal;
498
  color: #212121;
499
  }
500
-
501
  /* jQuery UI selectmenu classes */
502
 
503
  .ui-selectmenu-menu {
@@ -508,7 +522,6 @@ h3.theme-name {
508
  left: 0;
509
  display: none;
510
  }
511
-
512
  .ui-selectmenu-menu .ui-menu {
513
  overflow: auto;
514
  max-height: 372px;
@@ -516,15 +529,12 @@ h3.theme-name {
516
  /* Support: IE7 */
517
  overflow-x: hidden;/*padding-bottom: 1px;*/
518
  }
519
-
520
  .ui-selectmenu-menu .ui-menu .ui-menu-item {
521
  padding: 6px;
522
  }
523
-
524
  .ui-selectmenu-open {
525
  display: block;
526
  }
527
-
528
  .ui-selectmenu-button {
529
  display: inline-block;
530
  overflow: hidden;
@@ -532,8 +542,8 @@ h3.theme-name {
532
  text-decoration: none;
533
  cursor: pointer;
534
  min-width: 200px;
 
535
  }
536
-
537
  .ui-selectmenu-button span.ui-icon {
538
  right: 0.5em;
539
  left: auto;
@@ -541,14 +551,12 @@ h3.theme-name {
541
  position: absolute;
542
  top: 50%;
543
  }
544
-
545
  .ui-icon-triangle-1-s:before {
546
  display: inline-block;
547
  -webkit-font-smoothing: antialiased;
548
  font: normal 20px/1 'dashicons';
549
  content: "\f140";
550
  }
551
-
552
  .ui-selectmenu-button span.ui-selectmenu-text {
553
  text-align: left;
554
  padding: 0.4em 2.1em 0.4em 1em;
@@ -560,39 +568,37 @@ h3.theme-name {
560
  }
561
  /* get pro tab styles */
562
  #get_pro_panel h1 {
563
- font-size:1.75em;
564
  color: rgb(198, 66, 0);
565
  }
566
  #get_pro_panel h3 {
567
- font-size:1.4em;
568
- margin-bottom:0;
569
  }
570
-
571
  #get_pro_panel p {
572
- font-size:1em;
573
  margin: .5em 0;
574
  }
575
- .ctc-input-cell .update-nag, .ctc-input-cell-wide.update-nag {
576
  margin: 0;
577
  }
578
- .ctc-input-cell-wide.update-nag {
579
- margin-bottom:1em;
580
  }
581
- #get_pro_panel ul, .ctc-input-cell-wide.update-nag ul {
582
  list-style: square;
583
  }
584
- #get_pro_panel li, .ctc-input-cell-wide.update-nag li {
585
- margin-left:2em;
586
  }
587
  #get_pro_panel h3 a {
588
  display: block;
589
- padding:5px 10px;
590
  background-color: rgb(198, 66, 0);
591
  color: #fff;
592
  text-decoration: none;
593
  text-align: center;
594
  }
595
-
596
  #get_pro_panel h3 a:hover {
597
  background-color: #FF902E;
598
  color: #fff;
@@ -601,7 +607,53 @@ h3.theme-name {
601
  max-width: 100%;
602
  height: auto;
603
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
604
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
605
  /***
606
  Spectrum Colorpicker v1.7.0
607
  https://github.com/bgrins/spectrum
@@ -610,12 +662,12 @@ License: MIT
610
  ***/
611
 
612
  .sp-container {
613
- position:absolute;
614
- top:0;
615
- left:0;
616
- display:inline-block;
617
- *display: inline;
618
- *zoom: 1;
619
  /* https://github.com/bgrins/spectrum/issues/40 */
620
  z-index: 9999994;
621
  overflow: hidden;
@@ -623,60 +675,54 @@ License: MIT
623
  .sp-container.sp-flat {
624
  position: relative;
625
  }
626
-
627
  /* Fix for * { box-sizing: border-box; } */
628
- .sp-container,
629
- .sp-container * {
630
  -webkit-box-sizing: content-box;
631
- -moz-box-sizing: content-box;
632
- box-sizing: content-box;
633
  }
634
-
635
  /* http://ansciath.tumblr.com/post/7347495869/css-aspect-ratio */
636
  .sp-top {
637
- position:relative;
638
- width: 100%;
639
- display:inline-block;
640
  }
641
  .sp-top-inner {
642
- position:absolute;
643
- top:0;
644
- left:0;
645
- bottom:0;
646
- right:0;
647
  }
648
  .sp-color {
649
  position: absolute;
650
- top:0;
651
- left:0;
652
- bottom:0;
653
- right:20%;
654
  }
655
  .sp-hue {
656
  position: absolute;
657
- top:0;
658
- right:0;
659
- bottom:0;
660
- left:84%;
661
  height: 100%;
662
  }
663
-
664
  .sp-clear-enabled .sp-hue {
665
- top:33px;
666
  height: 77.5%;
667
  }
668
-
669
  .sp-fill {
670
  padding-top: 80%;
671
  }
672
  .sp-sat, .sp-val {
673
  position: absolute;
674
- top:0;
675
- left:0;
676
- right:0;
677
- bottom:0;
678
  }
679
-
680
  .sp-alpha-enabled .sp-top {
681
  margin-bottom: 18px;
682
  }
@@ -684,8 +730,8 @@ License: MIT
684
  display: block;
685
  }
686
  .sp-alpha-handle {
687
- position:absolute;
688
- top:-4px;
689
  bottom: -4px;
690
  width: 6px;
691
  left: 50%;
@@ -705,33 +751,28 @@ License: MIT
705
  .sp-alpha-inner {
706
  border: solid 1px #333;
707
  }
708
-
709
  .sp-clear {
710
  display: none;
711
  }
712
-
713
  .sp-clear.sp-clear-display {
714
  background-position: center;
715
  }
716
-
717
  .sp-clear-enabled .sp-clear {
718
  display: block;
719
- position:absolute;
720
- top:0px;
721
- right:0;
722
- bottom:0;
723
- left:84%;
724
  height: 28px;
725
  }
726
-
727
  /* Don't allow text selection */
728
- .sp-container, .sp-replacer, .sp-preview, .sp-dragger, .sp-slider, .sp-alpha, .sp-clear, .sp-alpha-handle, .sp-container.sp-dragging .sp-input, .sp-container button {
729
- -webkit-user-select:none;
730
  -moz-user-select: -moz-none;
731
- -o-user-select:none;
732
  user-select: none;
733
  }
734
-
735
  .sp-container.sp-input-disabled .sp-input-container {
736
  display: none;
737
  }
@@ -747,22 +788,19 @@ License: MIT
747
  .sp-palette-disabled .sp-palette-container {
748
  display: none;
749
  }
750
-
751
  .sp-initial-disabled .sp-initial {
752
  display: none;
753
  }
754
-
755
-
756
  /* Gradients for hue, saturation and value instead of images. Not pretty... but it works */
757
  .sp-sat {
758
- background-image: -webkit-gradient(linear, 0 0, 100% 0, from(#FFF), to(rgba(204, 154, 129, 0)));
759
  background-image: -webkit-linear-gradient(left, #FFF, rgba(204, 154, 129, 0));
760
  background-image: -moz-linear-gradient(left, #fff, rgba(204, 154, 129, 0));
761
  background-image: -o-linear-gradient(left, #fff, rgba(204, 154, 129, 0));
762
  background-image: -ms-linear-gradient(left, #fff, rgba(204, 154, 129, 0));
763
  background-image: linear-gradient(to right, #fff, rgba(204, 154, 129, 0));
764
  -ms-filter: "progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr=#FFFFFFFF, endColorstr=#00CC9A81)";
765
- filter : progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr='#FFFFFFFF', endColorstr='#00CC9A81');
766
  }
767
  .sp-val {
768
  background-image: -webkit-gradient(linear, 0 100%, 0 0, from(#000000), to(rgba(204, 154, 129, 0)));
@@ -772,9 +810,8 @@ License: MIT
772
  background-image: -ms-linear-gradient(bottom, #000, rgba(204, 154, 129, 0));
773
  background-image: linear-gradient(to top, #000, rgba(204, 154, 129, 0));
774
  -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#00CC9A81, endColorstr=#FF000000)";
775
- filter : progid:DXImageTransform.Microsoft.gradient(startColorstr='#00CC9A81', endColorstr='#FF000000');
776
  }
777
-
778
  .sp-hue {
779
  background: -moz-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
780
  background: -ms-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
@@ -783,66 +820,76 @@ License: MIT
783
  background: -webkit-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
784
  background: linear-gradient(to bottom, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
785
  }
786
-
787
  /* IE filters do not support multiple color stops.
788
  Generate 6 divs, line them up, and do two color gradients for each.
789
  Yes, really.
790
  */
791
  .sp-1 {
792
- height:17%;
793
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0000', endColorstr='#ffff00');
794
  }
795
  .sp-2 {
796
- height:16%;
797
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff00', endColorstr='#00ff00');
798
  }
799
  .sp-3 {
800
- height:17%;
801
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ff00', endColorstr='#00ffff');
802
  }
803
  .sp-4 {
804
- height:17%;
805
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ffff', endColorstr='#0000ff');
806
  }
807
  .sp-5 {
808
- height:16%;
809
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0000ff', endColorstr='#ff00ff');
810
  }
811
  .sp-6 {
812
- height:17%;
813
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff00ff', endColorstr='#ff0000');
814
  }
815
-
816
  .sp-hidden {
817
  display: none !important;
818
  }
819
-
820
  /* Clearfix hack */
821
- .sp-cf:before, .sp-cf:after { content: ""; display: table; }
822
- .sp-cf:after { clear: both; }
823
- .sp-cf { *zoom: 1; }
 
 
 
 
 
 
 
824
 
825
  /* Mobile devices, make hue slider bigger so it is easier to slide */
826
  @media (max-device-width: 480px) {
827
- .sp-color { right: 40%; }
828
- .sp-hue { left: 63%; }
829
- .sp-fill { padding-top: 60%; }
 
 
 
 
 
 
830
  }
831
  .sp-dragger {
832
- border-radius: 5px;
833
- height: 5px;
834
- width: 5px;
835
- border: 1px solid #fff;
836
- background: #000;
837
- cursor: pointer;
838
- position:absolute;
839
- top:0;
840
- left: 0;
841
  }
842
  .sp-slider {
843
  position: absolute;
844
- top:0;
845
- cursor:pointer;
846
  height: 3px;
847
  left: -1px;
848
  right: -1px;
@@ -850,7 +897,6 @@ License: MIT
850
  background: white;
851
  opacity: .8;
852
  }
853
-
854
  /*
855
  Theme authors:
856
  Here are the basic themeable display options (colors, fonts, global widths).
@@ -876,35 +922,34 @@ See http://bgrins.github.io/spectrum/themes/ for instructions.
876
  .sp-color, .sp-hue, .sp-clear {
877
  border: solid 1px #666;
878
  }
879
-
880
  /* Input */
881
  .sp-input-container {
882
- float:right;
883
  width: 100px;
884
  margin-bottom: 4px;
885
  }
886
- .sp-initial-disabled .sp-input-container {
887
  width: 100%;
888
  }
889
  .sp-input {
890
- font-size: 12px !important;
891
- border: 1px inset;
892
- padding: 4px 5px;
893
- margin: 0;
894
- width: 100%;
895
- background:transparent;
896
- border-radius: 3px;
897
- color: #222;
898
- }
899
- .sp-input:focus {
900
  border: 1px solid orange;
901
  }
902
  .sp-input.sp-validation-error {
903
  border: 1px solid red;
904
  background: #fdd;
905
  }
906
- .sp-picker-container , .sp-palette-container {
907
- float:left;
908
  position: relative;
909
  padding: 10px;
910
  padding-bottom: 300px;
@@ -914,34 +959,30 @@ See http://bgrins.github.io/spectrum/themes/ for instructions.
914
  width: 172px;
915
  border-left: solid 1px #fff;
916
  }
917
-
918
  /* Palettes */
919
  .sp-palette-container {
920
  border-right: solid 1px #ccc;
921
  max-width: 60px;
922
  }
923
-
924
  .sp-palette-only .sp-palette-container {
925
  border: 0;
926
  }
927
-
928
  .sp-palette .sp-thumb-el {
929
  display: block;
930
- position:relative;
931
- float:left;
932
  width: 24px;
933
  height: 15px;
934
  margin: 3px;
935
  cursor: pointer;
936
- border:solid 2px transparent;
937
  }
938
  .sp-palette .sp-thumb-el:hover, .sp-palette .sp-thumb-el.sp-thumb-active {
939
  border-color: orange;
940
  }
941
  .sp-thumb-el {
942
- position:relative;
943
  }
944
-
945
  /* Initial */
946
  .sp-initial {
947
  float: left;
@@ -950,31 +991,27 @@ See http://bgrins.github.io/spectrum/themes/ for instructions.
950
  .sp-initial span {
951
  width: 30px;
952
  height: 25px;
953
- border:none;
954
- display:block;
955
- float:left;
956
- margin:0;
957
  }
958
-
959
  .sp-initial .sp-clear-display {
960
  background-position: center;
961
  }
962
-
963
  /* Buttons */
964
- .sp-palette-button-container,
965
- .sp-button-container {
966
  float: right;
967
  }
968
-
969
  /* Replacer (the little preview div that shows up instead of the <input>) */
970
  .sp-replacer {
971
- margin:0;
972
- overflow:hidden;
973
- cursor:pointer;
974
  padding: 4px;
975
- display:inline-block;
976
- *zoom: 1;
977
- *display: inline;
978
  border: solid 1px #91765d;
979
  background: #eee;
980
  color: #333;
@@ -985,7 +1022,7 @@ See http://bgrins.github.io/spectrum/themes/ for instructions.
985
  color: #111;
986
  }
987
  .sp-replacer.sp-disabled {
988
- cursor:default;
989
  border-color: silver;
990
  color: silver;
991
  }
@@ -993,54 +1030,50 @@ See http://bgrins.github.io/spectrum/themes/ for instructions.
993
  padding: 2px 0;
994
  height: 16px;
995
  line-height: 16px;
996
- float:left;
997
- font-size:10px;
998
- font-family:sans-serif;
999
  }
1000
  .sp-preview {
1001
- position:relative;
1002
- width:25px;
1003
  height: 20px;
1004
  border: solid 1px #222;
1005
  margin-right: 5px;
1006
- float:left;
1007
  z-index: 0;
1008
  }
1009
-
1010
  .sp-palette {
1011
- *width: 220px;
1012
  max-width: 220px;
1013
  }
1014
  .sp-palette .sp-thumb-el {
1015
- width:16px;
1016
  height: 16px;
1017
- margin:2px 1px;
1018
  border: solid 1px #d0d0d0;
1019
  }
1020
-
1021
  .sp-container {
1022
- padding-bottom:0;
1023
  }
1024
-
1025
-
1026
  /* Buttons: http://hellohappy.org/css3-buttons/ */
1027
  .sp-container button {
1028
- background-color: #eeeeee;
1029
- background-image: -webkit-linear-gradient(top, #eeeeee, #cccccc);
1030
- background-image: -moz-linear-gradient(top, #eeeeee, #cccccc);
1031
- background-image: -ms-linear-gradient(top, #eeeeee, #cccccc);
1032
- background-image: -o-linear-gradient(top, #eeeeee, #cccccc);
1033
- background-image: linear-gradient(to bottom, #eeeeee, #cccccc);
1034
- border: 1px solid #ccc;
1035
- border-bottom: 1px solid #bbb;
1036
- border-radius: 3px;
1037
- color: #333;
1038
- font-size: 14px;
1039
- line-height: 1;
1040
- padding: 5px 4px;
1041
- text-align: center;
1042
- text-shadow: 0 1px 0 #eee;
1043
- vertical-align: middle;
1044
  }
1045
  .sp-container button:hover {
1046
  background-color: #dddddd;
@@ -1066,48 +1099,43 @@ See http://bgrins.github.io/spectrum/themes/ for instructions.
1066
  .sp-cancel {
1067
  font-size: 11px;
1068
  color: #d93f3f !important;
1069
- margin:0;
1070
- padding:2px;
1071
  margin-right: 5px;
1072
  vertical-align: middle;
1073
- text-decoration:none;
1074
-
1075
  }
1076
  .sp-cancel:hover {
1077
  color: #d93f3f !important;
1078
  text-decoration: underline;
1079
  }
1080
-
1081
-
1082
  .sp-palette span:hover, .sp-palette span.sp-thumb-active {
1083
  border-color: #000;
1084
  }
1085
-
1086
  .sp-preview, .sp-alpha, .sp-thumb-el {
1087
- position:relative;
1088
  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);
1089
  }
1090
  .sp-preview-inner, .sp-alpha-inner, .sp-thumb-inner {
1091
- display:block;
1092
- position:absolute;
1093
- top:0;left:0;bottom:0;right:0;
 
 
 
1094
  }
1095
-
1096
  .sp-palette .sp-thumb-inner {
1097
  background-position: 50% 50%;
1098
  background-repeat: no-repeat;
1099
  }
1100
-
1101
  .sp-palette .sp-thumb-light.sp-thumb-active .sp-thumb-inner {
1102
  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIVJREFUeNpiYBhsgJFMffxAXABlN5JruT4Q3wfi/0DsT64h8UD8HmpIPCWG/KemIfOJCUB+Aoacx6EGBZyHBqI+WsDCwuQ9mhxeg2A210Ntfo8klk9sOMijaURm7yc1UP2RNCMbKE9ODK1HM6iegYLkfx8pligC9lCD7KmRof0ZhjQACDAAceovrtpVBRkAAAAASUVORK5CYII=);
1103
  }
1104
-
1105
  .sp-palette .sp-thumb-dark.sp-thumb-active .sp-thumb-inner {
1106
  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAMdJREFUOE+tkgsNwzAMRMugEAahEAahEAZhEAqlEAZhEAohEAYh81X2dIm8fKpEspLGvudPOsUYpxE2BIJCroJmEW9qJ+MKaBFhEMNabSy9oIcIPwrB+afvAUFoK4H0tMaQ3XtlrggDhOVVMuT4E5MMG0FBbCEYzjYT7OxLEvIHQLY2zWwQ3D+9luyOQTfKDiFD3iUIfPk8VqrKjgAiSfGFPecrg6HN6m/iBcwiDAo7WiBeawa+Kwh7tZoSCGLMqwlSAzVDhoK+6vH4G0P5wdkAAAAASUVORK5CYII=);
1107
  }
1108
-
1109
  .sp-clear-display {
1110
- background-repeat:no-repeat;
1111
  background-position: center;
1112
  background-image: url(data:image/gif;base64,R0lGODlhFAAUAPcAAAAAAJmZmZ2dnZ6enqKioqOjo6SkpKWlpaampqenp6ioqKmpqaqqqqurq/Hx8fLy8vT09PX19ff39/j4+Pn5+fr6+vv7+wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAP8ALAAAAAAUABQAAAihAP9FoPCvoMGDBy08+EdhQAIJCCMybCDAAYUEARBAlFiQQoMABQhKUJBxY0SPICEYHBnggEmDKAuoPMjS5cGYMxHW3IiT478JJA8M/CjTZ0GgLRekNGpwAsYABHIypcAgQMsITDtWJYBR6NSqMico9cqR6tKfY7GeBCuVwlipDNmefAtTrkSzB1RaIAoXodsABiZAEFB06gIBWC1mLVgBa0AAOw==);
1113
  }
1
  body {
2
+ background: none !important;
3
  }
4
  p {
5
+ line-height: 1.4;
6
+ }
7
+ #ctc_main .clear {
8
+ clear: both;
9
+ display: unset;
10
+ overflow: unset;
11
+ visibility: unset;
12
+ width: unset;
13
+ height: unset;
14
+ }
15
+ #ctc_main .clearfix:before, #ctc_main .clearfix:after {
16
+ content: ' ';
17
+ display: table;
18
+ margin: 0;
19
+ padding: 0;
20
+ }
21
+ #ctc_main .clearfix:after {
22
+ clear: both;
23
+ }
24
+ #ctc_main .ie7 .clearfix {
25
+ zoom: 1;
26
+ }
27
+ #ctc_main .smaller {
28
+ font-size: .85em;
29
+ }
30
+
31
+ #ctc_main .writable, #ctc_main .writable a {
32
+ color: red;
33
  }
34
+ #ctc_main .wrap h1, .wrap h2 {
35
  font-size: 23px;
36
  font-weight: 400;
37
  line-height: 29px;
38
  margin: .5em 0 1em;
39
  }
40
+ #ctc_main a.nav-tab, #ctc_main a.nav-tab:focus, #ctc_main a.nav-tab:active {
41
  outline: none;
42
  -moz-box-shadow: none;
43
  -webkit-box-shadow: none;
49
  line-height:1;
50
  height:2em;*/
51
  }
52
+ #ctc_main h2 .nav-tab, #ctc_main h2 .ctc-recent-tab {
53
  font-size: 13px;
54
  padding: 6px 8px;
55
  font-weight: 700;
56
+ line-height: 1.2;
57
+ height:32px;
58
+ max-width:60px;
59
+ white-space:normal;
60
+ text-align:center;
61
  }
62
  .ctc-option-panel-container {
63
  position: relative;
64
  min-height: 1100px;
65
+ width: 100%;
66
  overflow: auto;
67
  }
68
  .ctc-three-col {
69
+ -moz-columns: 3;
70
+ -moz-column-gap: 3em;
71
+ -webkit-columns: 3;
72
+ -webkit-column-gap: 3em;
73
+ columns: 3;
74
+ column-gap: 3em;
75
  }
76
  #ctc_recent_selectors ul li, #all_styles_panel ul li {
77
  margin: 0;
78
  }
 
79
  #ctc_recent_selectors ul li a, #all_styles_panel ul li a {
80
  text-decoration: none;
81
  font-size: .8em;
84
  display: block;
85
  padding: .5em;
86
  }
 
87
  #ctc_recent_selectors ul li a:hover, #ctc_recent_selectors ul li a:focus, #all_styles_panel ul li a:hover, #all_styles_panel ul li a:focus {
88
  background-color: #fff;
89
  -webkit-box-shadow: none;
90
  -moz-box-shadow: none;
91
  box-shadow: none;
92
  }
 
93
  #view_child_options_panel, #view_parnt_options_panel {
94
  white-space: pre;
95
  overflow: auto;
96
  font-family: monospace;
97
  word-wrap: normal;
98
  }
 
99
  .ctc-option-panel {
100
  visibility: hidden;
101
  position: absolute;
103
  width: 100%;
104
  top: 0;
105
  left: 0;
106
+ padding: 10px 0 0;/* transition: width 1s ease;
 
107
  -moz-transition: width 1s ease;
108
  -webkit-transition: width 1s ease;
109
  -o-transition: width 1s ease; */
110
  }
111
  .ctc-recent-container {
112
+ top: 0;
113
+ right: 0;
114
+ position: absolute;
115
  max-width: 200px;
116
  width: 17%;
117
  display: none;
118
  overflow: auto;
119
+ visibility: visible;
120
+ left: inherit;
121
  background-color: #E4E4E4;
122
  }
123
  #ctc_recent_selectors {
128
  min-height: 1100px;
129
  }
130
  a.ctc-recent-tab {
131
+ float: right;
132
+ border: 1px solid #ccc;
133
  border-bottom: none;
134
  background-color: #E4E4E4;
135
  color: #555;
136
  display: inline-block;
137
  text-decoration: none;
138
  margin: -1px 0 0 0;
139
+ /* margin: 1px 0 -1px; */
140
  box-shadow: none;
141
+ -moz-box-shadow: none;
142
  -webkit-box-shadow: none;
143
+ outline: none;
144
  }
145
  .ctc-recent-tab h3 {
146
  }
 
147
  .ctc-option-panel-active {
148
  visibility: visible;
149
  }
150
+ .ctc-step {
151
+ -moz-border-radius: 50%;
152
+ -webkit-border-radius: 50%;
153
+ border-radius: 50%;
154
+ text-align: center;
155
+ font-weight: 700;
156
+ font-style: normal;
157
+ }
158
+ .ctc-step-number {
159
+ color: #fff;
160
+ font-size: 20px;
161
+ width: 24px;
162
+ height: 24px;
163
+ line-height: 1.1;
164
+ padding: 8px;
165
+ float: left;
166
+ display: block;
167
+ margin-right: 8px;
168
+ margin-bottom: 2em;
169
+ }
170
+ .ctc-step-letter {
171
+ color: #fff;
172
+ font-size: 1em;
173
+ width: 24px;
174
+ height: 24px;
175
+ padding: 8px;
176
+ line-height: 1;
177
+ float: right;
178
+ display: block;
179
+ margin-right: -8px;
180
+ margin-top: 8px;
181
+ }
182
+ .ctc-step + strong {
183
+ font-size: 1.1em;
184
+ }
185
+ .ctc-step + strong.shift:before {
186
+ position: relative;
187
+ content: '';
188
+ display: block;
189
+ height: 10px;
190
+ }
191
  .ctc-swatch {
192
  display: block;
193
  float: left;
196
  line-height: 1;
197
  overflow: hidden;
198
  }
 
199
  .ctc-hidden {
200
  display: none;
201
  }
 
202
  .ctc-swatch.ctc-specific {
203
  min-height: 60px;
204
  max-height: 100px;
207
  border: 1px solid #ddd;*/
208
  }
209
  .ctc-selector-inner-container .ctc-swatch.ctc-specific {
210
+ max-width: 13%;
211
  }
212
  .ctc-parent-row {
213
  clear: both;
214
  position: relative;
215
  margin: 4px 0;
216
  }
 
217
  .ctc-parent-value {
218
  }
 
219
  .ctc-input-cell {
220
  display: block;
221
  float: left;
225
  word-wrap: break-word;
226
  }
227
  .ctc-selector-inner-container .ctc-input-cell {
228
+ width: 35%;
229
  }
230
  .ctc-input-cell-wide {
231
  display: block;
233
  width: 60%;
234
  margin-right: 2%;
235
  }
 
236
  .ctc-input-cell-wide input[type="text"] {
237
  width: 100%;
238
  }
239
+ #ctc_main textarea {
 
240
  width: 100%;
241
  height: 200px;
242
+ font-size: 12px;
243
+ }
244
+ .ctc-input-cell-wide textarea {
245
  white-space: pre;
246
  overflow: auto;
247
  font-family: inherit;
248
  word-wrap: normal;
249
  }
250
+ #ctc_theme_attributes_content .ctc-input-cell-wide textarea {
251
+ white-space: normal;
252
+ }
253
  .ctc-save-input {
254
  }
 
255
  .ctc-selector-inner-container .ctc-button-cell, .ctc-selector-inner-container .ctc-input-cell.ctc-button-cell {
256
  width: 8%;
257
  }
 
258
  .ctc-textarea-button-cell {
259
  margin: 4px 10px 15px;
260
  /*width: 85px;*/
261
  text-align: right;
262
  float: right;
263
  }
 
264
  .ctc-selector-link {
265
  }
 
266
  .ctc-selector-handle {
267
  }
 
268
  .ctc-rewrite-toggle {
269
  font-size: 0.8em;
270
  padding-left: 1em;
273
  }
274
  .ctc-delete-input {
275
  font-size: 0.8em;
276
+ float: right;
277
  color: darkred;
278
+ text-decoration: none;
279
  }
 
280
  .ctc-selector-container {
281
  clear: both;
282
  background: #f9f9f9;
293
  -webkit-box-shadow: 0 2px 10px rgba(0,0,0,0.3);
294
  box-shadow: 0 2px 10px rgba(0,0,0,0.3);
295
  }
 
296
  .ctc-selector-inner-container {
297
  position: relative;
298
  min-height: 300px;
299
  /*max-height: 500px;*/
300
  overflow: auto;
301
  }
 
302
  .ctc-status-icon {
303
+ /*max-width: 4%;*/
304
  }
 
305
  .ctc-status-icon.success {
306
  display: block;
307
  float: right;
310
  width: 16px;
311
  margin: 4px;
312
  }
 
313
  .ctc-status-icon.failure {
314
  display: block;
315
  float: right;
318
  width: 16px;
319
  margin: 4px;
320
  }
 
321
  .ctc-exit {
322
  display: block;
323
  width: 20px;
332
  -webkit-border-radius: 16px;
333
  border-radius: 16px;
334
  }
 
335
  .ctc-exit:hover, .ctc-exit:active {
336
  background-position: right top;
337
  }
 
338
  .ctc-query-heading {
339
  }
 
340
  .ctc-selector-row {
341
  clear: both;
342
  margin: 0;
344
  border-top: 1px solid #ddd;
345
  border-bottom: 1px solid #fff;
346
  }
 
347
  .ctc-input-row {
348
  clear: both;
349
  margin: 4px 0;
351
  border-bottom: 1px solid #ddd;
352
  position: relative;
353
  }
 
354
  .ctc-selector-value {
355
  }
356
  .howto.sep {
357
  border-bottom: 1px solid #fff;
358
+ margin-bottom: 1em;
359
+ padding-bottom: 1em;
360
+ }
361
+ .indent {
362
+ padding-left: 1.75em;
363
+ }
364
+ .howto.indent {
365
+ margin-top: .25em;
366
  }
367
  .ctc-selector-cell {
368
  float: left;
369
  width: 30%;
370
  margin-right: 2%;
371
  }
 
372
  .ctc-child-input-cell {
373
  display: block;
374
  float: left;
375
  margin-right: 2%;
376
  }
 
377
  .ctc-child-input-cell-container {
378
  float: left;
379
  width: 40%;
380
  margin-right: 2%;
381
  }
 
382
  .ctc-child-input-cell-container label {
383
  float: left;
384
  clear: both;
385
  width: 100px;
386
  margin-right: 2%;
387
  }
 
388
  .ctc-child-input-cell input[type="text"] {
389
  /*width:60px;*/
390
  }
 
391
  .ctc-disabled {
392
  opacity: 0.5;
393
  }
 
394
  .ctc-select {
395
  max-width: 100%;
396
  }
 
397
  .ctc-child-input-cell input[type="text"].ctc-input-wide {
398
  width: 200px;
399
  }
 
400
  #ctc_additional_css_label {
401
  cursor: pointer;
402
  }
 
403
  #ctc_additional_css_label span {
404
  white-space: nowrap;
405
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
406
  /* added in 1.5.4 because it is not being loaded by the admin */
407
  .ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus {
408
  background-color: #DADADA;
409
  color: #212121;
410
  }
 
411
  .ui-menu .ui-menu-item {
412
  position: relative;
413
  margin: 0px;
418
  text-overflow: ellipsis;
419
  max-width: 450px;
420
  }
 
421
  /*** Added in 1.6.0 for new options ***/
422
  .ctc-section-toggle {
423
  /*margin:0;
425
  position: relative;
426
  cursor: pointer;
427
  }
428
+ .ctc-section-toggle:before {
 
429
  content: "\f140";
430
+ font-weight: 400;
431
+ font-size: 1.5em;
432
+ line-height: 1;
433
+ font-family: dashicons;
434
  color: #999;
435
+ display: block;
436
+ float: right;
437
+ width: 1em;
438
+ height: 1em;
439
  }
440
+ .ctc-section-toggle.open:before {
 
441
  content: "\f142";
442
  }
443
  a.ctc-section-toggle, a.ctc-section-toggle:hover, a.ctc-section-toggle:active, a.ctc-section-toggle:visited {
444
  text-decoration: none;
445
+ float: right;
446
+ font-size: .85em;
447
+ box-shadow: none;
448
+ -moz-box-shadow: none;
449
+ -webkit-box-shadow: none;
450
+ outline: none;
451
  }
452
  .ctc-section-toggle-content {
453
  display: none;
454
  position: relative;
455
+ margin: 0;
456
+ padding: 1px 0;
457
  }
 
458
  /*** Added in 1.6.0 for new Theme chooser ***/
459
  .ctc-theme-only {
460
  margin: 0;
461
  padding: 0;
462
  position: relative;
463
  }
 
464
  h3.theme-name {
465
  margin: .25em 0;
466
  font-size: 1.2em;
467
  }
 
468
  .ctc-theme-option {
469
  max-width: 250px;
470
  }
 
471
  .ctc-theme-option-left {
472
  float: left;
473
  width: 40%;
474
  margin-right: 5%;
475
  }
 
476
  .ctc-theme-option-right {
477
  float: right;
478
  width: 55%;
480
  font-size: .9em;
481
  line-height: 1.3;
482
  }
 
483
  .ctc-theme-option-image {
484
  height: auto;
485
  width: 100%;
486
  border: 1px solid #ddd;
487
  }
488
+ #ctc_theme_attributes_content, #ctc_stylesheet_handling_content {
489
+ padding: 1.5em 2.5em;
490
+ }
491
  /* jquery UI widget classes */
492
 
493
  .ui-widget-content {
494
  border: 1px solid #aaa;
495
  background-color: #fff;
496
  }
 
497
  .ui-widget-header {
498
  border: 1px solid #aaa;
499
  background-color: #ccc;
500
  font-weight: bold;
501
  }
 
502
  .ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default {
503
  border: 1px solid #d3d3d3;
504
  font-weight: normal;
505
  color: #555555;
506
  }
 
507
  .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus {
508
  font-weight: normal;
509
  color: #212121;
510
  }
 
511
  .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active {
512
  font-weight: normal;
513
  color: #212121;
514
  }
 
515
  /* jQuery UI selectmenu classes */
516
 
517
  .ui-selectmenu-menu {
522
  left: 0;
523
  display: none;
524
  }
 
525
  .ui-selectmenu-menu .ui-menu {
526
  overflow: auto;
527
  max-height: 372px;
529
  /* Support: IE7 */
530
  overflow-x: hidden;/*padding-bottom: 1px;*/
531
  }
 
532
  .ui-selectmenu-menu .ui-menu .ui-menu-item {
533
  padding: 6px;
534
  }
 
535
  .ui-selectmenu-open {
536
  display: block;
537
  }
 
538
  .ui-selectmenu-button {
539
  display: inline-block;
540
  overflow: hidden;
542
  text-decoration: none;
543
  cursor: pointer;
544
  min-width: 200px;
545
+ padding: .4em 0;
546
  }
 
547
  .ui-selectmenu-button span.ui-icon {
548
  right: 0.5em;
549
  left: auto;
551
  position: absolute;
552
  top: 50%;
553
  }
 
554
  .ui-icon-triangle-1-s:before {
555
  display: inline-block;
556
  -webkit-font-smoothing: antialiased;
557
  font: normal 20px/1 'dashicons';
558
  content: "\f140";
559
  }
 
560
  .ui-selectmenu-button span.ui-selectmenu-text {
561
  text-align: left;
562
  padding: 0.4em 2.1em 0.4em 1em;
568
  }
569
  /* get pro tab styles */
570
  #get_pro_panel h1 {
571
+ font-size: 1.75em;
572
  color: rgb(198, 66, 0);
573
  }
574
  #get_pro_panel h3 {
575
+ font-size: 1.4em;
576
+ margin-bottom: 0;
577
  }
 
578
  #get_pro_panel p {
579
+ font-size: 1em;
580
  margin: .5em 0;
581
  }
582
+ .ctc-input-cell .notice-warning, .ctc-input-cell-wide.notice-warning {
583
  margin: 0;
584
  }
585
+ .ctc-input-cell-wide.notice-warning {
586
+ margin-bottom: 1em;
587
  }
588
+ #get_pro_panel ul, .ctc-input-cell-wide.notice-warning ul {
589
  list-style: square;
590
  }
591
+ #get_pro_panel li, .ctc-input-cell-wide.notice-warning li {
592
+ margin-left: 2em;
593
  }
594
  #get_pro_panel h3 a {
595
  display: block;
596
+ padding: 5px 10px;
597
  background-color: rgb(198, 66, 0);
598
  color: #fff;
599
  text-decoration: none;
600
  text-align: center;
601
  }
 
602
  #get_pro_panel h3 a:hover {
603
  background-color: #FF902E;
604
  color: #fff;
607
  max-width: 100%;
608
  height: auto;
609
  }
610
+ .ctc_analyze_loading {
611
+ display: inline-block;
612
+ line-height: 2em;
613
+ }
614
+ #ctc_main .dashicons-before:before {
615
+ float: left;
616
+ margin-top: .5em;
617
+ margin-right: .5em;
618
+ font-size: 2em;
619
+ content: "\f534";
620
+ }
621
+ #ctc_main .dashicons-before.error:before {
622
+ color: #DC3232;
623
+ }
624
+ #ctc_main .dashicons-before.notice-warning:before {
625
+ color: #FFBA00;
626
+ }
627
+ #ctc_main .dashicons-before.updated:before {
628
+ color: #46B450;
629
+ content: "\f147";
630
+ }
631
+ /* big buttons that are hard to miss */
632
 
633
+ .wp-core-ui .button-primary, .wp-core-ui .button-secondary {
634
+ border-color: none;
635
+ text-shadow: none;
636
+ font-size: 1.3em;
637
+ line-height: 1.3;
638
+ height: auto;
639
+ margin: 0;
640
+ padding: .5em 1em;
641
+ border: none;
642
+ -webkit-border-radius: 3px;
643
+ border-radius: 3px;
644
+ }
645
+ /* fixed position debug output */
646
+ #ctc_main textarea#ctc_debug_box {
647
+ position: fixed;
648
+ bottom: 0;
649
+ z-index: 10000;
650
+ width: 82%;
651
+ height: 170px;
652
+ font-size:11px;
653
+ }
654
+ #ctc_stylesheet_files {
655
+ display:none;
656
+ }
657
  /***
658
  Spectrum Colorpicker v1.7.0
659
  https://github.com/bgrins/spectrum
662
  ***/
663
 
664
  .sp-container {
665
+ position: absolute;
666
+ top: 0;
667
+ left: 0;
668
+ display: inline-block;
669
+ *display: inline;
670
+ *zoom: 1;
671
  /* https://github.com/bgrins/spectrum/issues/40 */
672
  z-index: 9999994;
673
  overflow: hidden;
675
  .sp-container.sp-flat {
676
  position: relative;
677
  }
 
678
  /* Fix for * { box-sizing: border-box; } */
679
+ .sp-container, .sp-container * {
 
680
  -webkit-box-sizing: content-box;
681
+ -moz-box-sizing: content-box;
682
+ box-sizing: content-box;
683
  }
 
684
  /* http://ansciath.tumblr.com/post/7347495869/css-aspect-ratio */
685
  .sp-top {
686
+ position: relative;
687
+ width: 100%;
688
+ display: inline-block;
689
  }
690
  .sp-top-inner {
691
+ position: absolute;
692
+ top: 0;
693
+ left: 0;
694
+ bottom: 0;
695
+ right: 0;
696
  }
697
  .sp-color {
698
  position: absolute;
699
+ top: 0;
700
+ left: 0;
701
+ bottom: 0;
702
+ right: 20%;
703
  }
704
  .sp-hue {
705
  position: absolute;
706
+ top: 0;
707
+ right: 0;
708
+ bottom: 0;
709
+ left: 84%;
710
  height: 100%;
711
  }
 
712
  .sp-clear-enabled .sp-hue {
713
+ top: 33px;
714
  height: 77.5%;
715
  }
 
716
  .sp-fill {
717
  padding-top: 80%;
718
  }
719
  .sp-sat, .sp-val {
720
  position: absolute;
721
+ top: 0;
722
+ left: 0;
723
+ right: 0;
724
+ bottom: 0;
725
  }
 
726
  .sp-alpha-enabled .sp-top {
727
  margin-bottom: 18px;
728
  }
730
  display: block;
731
  }
732
  .sp-alpha-handle {
733
+ position: absolute;
734
+ top: -4px;
735
  bottom: -4px;
736
  width: 6px;
737
  left: 50%;
751
  .sp-alpha-inner {
752
  border: solid 1px #333;
753
  }
 
754
  .sp-clear {
755
  display: none;
756
  }
 
757
  .sp-clear.sp-clear-display {
758
  background-position: center;
759
  }
 
760
  .sp-clear-enabled .sp-clear {
761
  display: block;
762
+ position: absolute;
763
+ top: 0px;
764
+ right: 0;
765
+ bottom: 0;
766
+ left: 84%;
767
  height: 28px;
768
  }
 
769
  /* Don't allow text selection */
770
+ .sp-container, .sp-replacer, .sp-preview, .sp-dragger, .sp-slider, .sp-alpha, .sp-clear, .sp-alpha-handle, .sp-container.sp-dragging .sp-input, .sp-container button {
771
+ -webkit-user-select: none;
772
  -moz-user-select: -moz-none;
773
+ -o-user-select: none;
774
  user-select: none;
775
  }
 
776
  .sp-container.sp-input-disabled .sp-input-container {
777
  display: none;
778
  }
788
  .sp-palette-disabled .sp-palette-container {
789
  display: none;
790
  }
 
791
  .sp-initial-disabled .sp-initial {
792
  display: none;
793
  }
 
 
794
  /* Gradients for hue, saturation and value instead of images. Not pretty... but it works */
795
  .sp-sat {
796
+ background-image: -webkit-gradient(linear, 0 0, 100% 0, from(#FFF), to(rgba(204, 154, 129, 0)));
797
  background-image: -webkit-linear-gradient(left, #FFF, rgba(204, 154, 129, 0));
798
  background-image: -moz-linear-gradient(left, #fff, rgba(204, 154, 129, 0));
799
  background-image: -o-linear-gradient(left, #fff, rgba(204, 154, 129, 0));
800
  background-image: -ms-linear-gradient(left, #fff, rgba(204, 154, 129, 0));
801
  background-image: linear-gradient(to right, #fff, rgba(204, 154, 129, 0));
802
  -ms-filter: "progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr=#FFFFFFFF, endColorstr=#00CC9A81)";
803
+ filter : progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr='#FFFFFFFF', endColorstr='#00CC9A81');
804
  }
805
  .sp-val {
806
  background-image: -webkit-gradient(linear, 0 100%, 0 0, from(#000000), to(rgba(204, 154, 129, 0)));
810
  background-image: -ms-linear-gradient(bottom, #000, rgba(204, 154, 129, 0));
811
  background-image: linear-gradient(to top, #000, rgba(204, 154, 129, 0));
812
  -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#00CC9A81, endColorstr=#FF000000)";
813
+ filter : progid:DXImageTransform.Microsoft.gradient(startColorstr='#00CC9A81', endColorstr='#FF000000');
814
  }
 
815
  .sp-hue {
816
  background: -moz-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
817
  background: -ms-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
820
  background: -webkit-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
821
  background: linear-gradient(to bottom, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
822
  }
 
823
  /* IE filters do not support multiple color stops.
824
  Generate 6 divs, line them up, and do two color gradients for each.
825
  Yes, really.
826
  */
827
  .sp-1 {
828
+ height: 17%;
829
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0000', endColorstr='#ffff00');
830
  }
831
  .sp-2 {
832
+ height: 16%;
833
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff00', endColorstr='#00ff00');
834
  }
835
  .sp-3 {
836
+ height: 17%;
837
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ff00', endColorstr='#00ffff');
838
  }
839
  .sp-4 {
840
+ height: 17%;
841
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ffff', endColorstr='#0000ff');
842
  }
843
  .sp-5 {
844
+ height: 16%;
845
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0000ff', endColorstr='#ff00ff');
846
  }
847
  .sp-6 {
848
+ height: 17%;
849
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff00ff', endColorstr='#ff0000');
850
  }
 
851
  .sp-hidden {
852
  display: none !important;
853
  }
 
854
  /* Clearfix hack */
855
+ .sp-cf:before, .sp-cf:after {
856
+ content: "";
857
+ display: table;
858
+ }
859
+ .sp-cf:after {
860
+ clear: both;
861
+ }
862
+ .sp-cf {
863
+ *zoom: 1;
864
+ }
865
 
866
  /* Mobile devices, make hue slider bigger so it is easier to slide */
867
  @media (max-device-width: 480px) {
868
+ .sp-color {
869
+ right: 40%;
870
+ }
871
+ .sp-hue {
872
+ left: 63%;
873
+ }
874
+ .sp-fill {
875
+ padding-top: 60%;
876
+ }
877
  }
878
  .sp-dragger {
879
+ border-radius: 5px;
880
+ height: 5px;
881
+ width: 5px;
882
+ border: 1px solid #fff;
883
+ background: #000;
884
+ cursor: pointer;
885
+ position: absolute;
886
+ top: 0;
887
+ left: 0;
888
  }
889
  .sp-slider {
890
  position: absolute;
891
+ top: 0;
892
+ cursor: pointer;
893
  height: 3px;
894
  left: -1px;
895
  right: -1px;
897
  background: white;
898
  opacity: .8;
899
  }
 
900
  /*
901
  Theme authors:
902
  Here are the basic themeable display options (colors, fonts, global widths).
922
  .sp-color, .sp-hue, .sp-clear {
923
  border: solid 1px #666;
924
  }
 
925
  /* Input */
926
  .sp-input-container {
927
+ float: right;
928
  width: 100px;
929
  margin-bottom: 4px;
930
  }
931
+ .sp-initial-disabled .sp-input-container {
932
  width: 100%;
933
  }
934
  .sp-input {
935
+ font-size: 12px !important;
936
+ border: 1px inset;
937
+ padding: 4px 5px;
938
+ margin: 0;
939
+ width: 100%;
940
+ background: transparent;
941
+ border-radius: 3px;
942
+ color: #222;
943
+ }
944
+ .sp-input:focus {
945
  border: 1px solid orange;
946
  }
947
  .sp-input.sp-validation-error {
948
  border: 1px solid red;
949
  background: #fdd;
950
  }
951
+ .sp-picker-container, .sp-palette-container {
952
+ float: left;
953
  position: relative;
954
  padding: 10px;
955
  padding-bottom: 300px;
959
  width: 172px;
960
  border-left: solid 1px #fff;
961
  }
 
962
  /* Palettes */
963
  .sp-palette-container {
964
  border-right: solid 1px #ccc;
965
  max-width: 60px;
966
  }
 
967
  .sp-palette-only .sp-palette-container {
968
  border: 0;
969
  }
 
970
  .sp-palette .sp-thumb-el {
971
  display: block;
972
+ position: relative;
973
+ float: left;
974
  width: 24px;
975
  height: 15px;
976
  margin: 3px;
977
  cursor: pointer;
978
+ border: solid 2px transparent;
979
  }
980
  .sp-palette .sp-thumb-el:hover, .sp-palette .sp-thumb-el.sp-thumb-active {
981
  border-color: orange;
982
  }
983
  .sp-thumb-el {
984
+ position: relative;
985
  }
 
986
  /* Initial */
987
  .sp-initial {
988
  float: left;
991
  .sp-initial span {
992
  width: 30px;
993
  height: 25px;
994
+ border: none;
995
+ display: block;
996
+ float: left;
997
+ margin: 0;
998
  }
 
999
  .sp-initial .sp-clear-display {
1000
  background-position: center;
1001
  }
 
1002
  /* Buttons */
1003
+ .sp-palette-button-container, .sp-button-container {
 
1004
  float: right;
1005
  }
 
1006
  /* Replacer (the little preview div that shows up instead of the <input>) */
1007
  .sp-replacer {
1008
+ margin: 0;
1009
+ overflow: hidden;
1010
+ cursor: pointer;
1011
  padding: 4px;
1012
+ display: inline-block;
1013
+ *zoom: 1;
1014
+ *display: inline;
1015
  border: solid 1px #91765d;
1016
  background: #eee;
1017
  color: #333;
1022
  color: #111;
1023
  }
1024
  .sp-replacer.sp-disabled {
1025
+ cursor: default;
1026
  border-color: silver;
1027
  color: silver;
1028
  }
1030
  padding: 2px 0;
1031
  height: 16px;
1032
  line-height: 16px;
1033
+ float: left;
1034
+ font-size: 10px;
1035
+ font-family: sans-serif;
1036
  }
1037
  .sp-preview {
1038
+ position: relative;
1039
+ width: 25px;
1040
  height: 20px;
1041
  border: solid 1px #222;
1042
  margin-right: 5px;
1043
+ float: left;
1044
  z-index: 0;
1045
  }
 
1046
  .sp-palette {
1047
+ *width: 220px;
1048
  max-width: 220px;
1049
  }
1050
  .sp-palette .sp-thumb-el {
1051
+ width: 16px;
1052
  height: 16px;
1053
+ margin: 2px 1px;
1054
  border: solid 1px #d0d0d0;
1055
  }
 
1056
  .sp-container {
1057
+ padding-bottom: 0;
1058
  }
 
 
1059
  /* Buttons: http://hellohappy.org/css3-buttons/ */
1060
  .sp-container button {
1061
+ background-color: #eeeeee;
1062
+ background-image: -webkit-linear-gradient(top, #eeeeee, #cccccc);
1063
+ background-image: -moz-linear-gradient(top, #eeeeee, #cccccc);
1064
+ background-image: -ms-linear-gradient(top, #eeeeee, #cccccc);
1065
+ background-image: -o-linear-gradient(top, #eeeeee, #cccccc);
1066
+ background-image: linear-gradient(to bottom, #eeeeee, #cccccc);
1067
+ border: 1px solid #ccc;
1068
+ border-bottom: 1px solid #bbb;
1069
+ border-radius: 3px;
1070
+ color: #333;
1071
+ font-size: 14px;
1072
+ line-height: 1;
1073
+ padding: 5px 4px;
1074
+ text-align: center;
1075
+ text-shadow: 0 1px 0 #eee;
1076
+ vertical-align: middle;
1077
  }
1078
  .sp-container button:hover {
1079
  background-color: #dddddd;
1099
  .sp-cancel {
1100
  font-size: 11px;
1101
  color: #d93f3f !important;
1102
+ margin: 0;
1103
+ padding: 2px;
1104
  margin-right: 5px;
1105
  vertical-align: middle;
1106
+ text-decoration: none;
 
1107
  }
1108
  .sp-cancel:hover {
1109
  color: #d93f3f !important;
1110
  text-decoration: underline;
1111
  }
 
 
1112
  .sp-palette span:hover, .sp-palette span.sp-thumb-active {
1113
  border-color: #000;
1114
  }
 
1115
  .sp-preview, .sp-alpha, .sp-thumb-el {
1116
+ position: relative;
1117
  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);
1118
  }
1119
  .sp-preview-inner, .sp-alpha-inner, .sp-thumb-inner {
1120
+ display: block;
1121
+ position: absolute;
1122
+ top: 0;
1123
+ left: 0;
1124
+ bottom: 0;
1125
+ right: 0;
1126
  }
 
1127
  .sp-palette .sp-thumb-inner {
1128
  background-position: 50% 50%;
1129
  background-repeat: no-repeat;
1130
  }
 
1131
  .sp-palette .sp-thumb-light.sp-thumb-active .sp-thumb-inner {
1132
  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIVJREFUeNpiYBhsgJFMffxAXABlN5JruT4Q3wfi/0DsT64h8UD8HmpIPCWG/KemIfOJCUB+Aoacx6EGBZyHBqI+WsDCwuQ9mhxeg2A210Ntfo8klk9sOMijaURm7yc1UP2RNCMbKE9ODK1HM6iegYLkfx8pligC9lCD7KmRof0ZhjQACDAAceovrtpVBRkAAAAASUVORK5CYII=);
1133
  }
 
1134
  .sp-palette .sp-thumb-dark.sp-thumb-active .sp-thumb-inner {
1135
  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAMdJREFUOE+tkgsNwzAMRMugEAahEAahEAZhEAqlEAZhEAohEAYh81X2dIm8fKpEspLGvudPOsUYpxE2BIJCroJmEW9qJ+MKaBFhEMNabSy9oIcIPwrB+afvAUFoK4H0tMaQ3XtlrggDhOVVMuT4E5MMG0FBbCEYzjYT7OxLEvIHQLY2zWwQ3D+9luyOQTfKDiFD3iUIfPk8VqrKjgAiSfGFPecrg6HN6m/iBcwiDAo7WiBeawa+Kwh7tZoSCGLMqwlSAzVDhoK+6vH4G0P5wdkAAAAASUVORK5CYII=);
1136
  }
 
1137
  .sp-clear-display {
1138
+ background-repeat: no-repeat;
1139
  background-position: center;
1140
  background-image: url(data:image/gif;base64,R0lGODlhFAAUAPcAAAAAAJmZmZ2dnZ6enqKioqOjo6SkpKWlpaampqenp6ioqKmpqaqqqqurq/Hx8fLy8vT09PX19ff39/j4+Pn5+fr6+vv7+wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAP8ALAAAAAAUABQAAAihAP9FoPCvoMGDBy08+EdhQAIJCCMybCDAAYUEARBAlFiQQoMABQhKUJBxY0SPICEYHBnggEmDKAuoPMjS5cGYMxHW3IiT478JJA8M/CjTZ0GgLRekNGpwAsYABHIypcAgQMsITDtWJYBR6NSqMico9cqR6tKfY7GeBCuVwlipDNmefAtTrkSzB1RaIAoXodsABiZAEFB06gIBWC1mLVgBa0AAOw==);
1141
  }
includes/class-ctc-admin.php DELETED
@@ -1,1621 +0,0 @@
1
- <?php
2
- // Exit if accessed directly
3
- if ( !defined( 'ABSPATH' ) ) exit;
4
-
5
- /*
6
- Class: Child_Theme_Configurator
7
- Plugin URI: http://www.childthemeconfigurator.com/
8
- Description: Main Controller Class
9
- Version: 1.7.9
10
- Author: Lilaea Media
11
- Author URI: http://www.lilaeamedia.com/
12
- Text Domain: chld_thm_cfg
13
- Domain Path: /lang
14
- License: GPLv2
15
- Copyright (C) 2014-2015 Lilaea Media
16
- */
17
- class ChildThemeConfiguratorAdmin {
18
-
19
- // state
20
- var $is_ajax;
21
- var $is_get;
22
- var $is_post;
23
- var $skip_form;
24
- var $fs;
25
-
26
- var $fs_prompt;
27
- var $fs_method;
28
- var $uploadsubdir;
29
- var $menuName; // backward compatibility with plugin extension
30
- var $cache_updates = TRUE;
31
- var $debug = '';
32
- var $is_debug = 0;
33
- var $swatch_text = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
34
- var $max_sel;
35
- var $sel_limit;
36
- // state arrays
37
- var $themes = array();
38
- var $errors = array();
39
- var $files = array();
40
- var $updates = array();
41
- var $memory = array();
42
- // objects
43
- var $css;
44
- var $ui;
45
- // config arrays
46
- var $postarrays = array(
47
- 'ctc_img',
48
- 'ctc_file_parnt',
49
- 'ctc_file_child',
50
- 'ctc_additional_css',
51
- );
52
- var $configfields = array(
53
- 'theme_parnt',
54
- 'child_type',
55
- 'theme_child',
56
- 'child_template',
57
- 'child_name',
58
- 'child_themeuri',
59
- 'child_author',
60
- 'child_authoruri',
61
- 'child_descr',
62
- 'child_tags',
63
- 'child_version',
64
- 'configtype', // backward compatability
65
- 'nowarn',
66
- );
67
- var $actionfields = array(
68
- 'load_styles',
69
- 'parnt_templates_submit',
70
- 'child_templates_submit',
71
- 'image_submit',
72
- 'theme_image_submit',
73
- 'theme_screenshot_submit',
74
- 'export_child_zip',
75
- 'reset_permission',
76
- 'templates_writable_submit',
77
- 'set_writable',
78
- 'upgrade',
79
- );
80
- var $imgmimes = array(
81
- 'jpg|jpeg|jpe' => 'image/jpeg',
82
- 'gif' => 'image/gif',
83
- 'png' => 'image/png',
84
- );
85
- var $excludes = array(
86
- 'inc',
87
- 'core',
88
- 'lang',
89
- 'css',
90
- 'js',
91
- 'lib',
92
- 'theme',
93
- 'options',
94
- );
95
-
96
- function __construct() {
97
- $this->menuName = CHLD_THM_CFG_MENU; // backward compatability for plugins extension
98
- $this->is_post = ( 'POST' == $_SERVER[ 'REQUEST_METHOD' ] );
99
- $this->is_get = ( 'GET' == $_SERVER[ 'REQUEST_METHOD' ] );
100
- $this->is_debug = get_option( CHLD_THM_CFG_OPTIONS . '_debug' );
101
- if ( $this->is_debug && ( $this->debug = get_site_transient( CHLD_THM_CFG_OPTIONS . '_debug' ) ) )
102
- delete_site_transient( CHLD_THM_CFG_OPTIONS . '_debug' );
103
- // sel_limit is now calculated based on free memory to prevent out of memory on serialization
104
- $bytes_free = $this->get_free_memory();
105
- $this->sel_limit = ( int ) ( $bytes_free / CHLD_THM_CFG_BPSEL );
106
- $this->debug( 'Free memory: ' . $bytes_free . ' max selectors: ' . $this->sel_limit, __FUNCTION__ );
107
- //$this->set_benchmark( 'before', 'execute', 'program' );
108
- }
109
-
110
- function enqueue_scripts() {
111
- wp_enqueue_style( 'chld-thm-cfg-admin', CHLD_THM_CFG_URL . 'css/chld-thm-cfg.min.css', array(), '1.7.9' );
112
-
113
- // we need to use local jQuery UI Widget/Menu/Selectmenu 1.11.2 because selectmenu is not included in < 1.11.2
114
- // this will be updated in a later release to use WP Core scripts when it is widely adopted
115
- if ( !wp_script_is( 'jquery-ui-selectmenu', 'registered' ) ): // selectmenu.min.js
116
- wp_enqueue_script( 'jquery-ui-selectmenu', CHLD_THM_CFG_URL . 'js/selectmenu.min.js',
117
- array( 'jquery','jquery-ui-core','jquery-ui-position' ), FALSE, TRUE );
118
- endif;
119
- wp_enqueue_script( 'ctc-spectrum', CHLD_THM_CFG_URL . 'js/spectrum.min.js', array( 'jquery' ), FALSE, TRUE );
120
- wp_enqueue_script( 'ctc-thm-cfg-ctcgrad', CHLD_THM_CFG_URL . 'js/ctcgrad.min.js', array( 'jquery' ), FALSE, TRUE );
121
- wp_enqueue_script( 'chld-thm-cfg-admin', CHLD_THM_CFG_URL . 'js/chld-thm-cfg.min.js',
122
- array(
123
- 'jquery-ui-autocomplete',
124
- 'jquery-ui-selectmenu',
125
- 'ctc-spectrum',
126
- 'ctc-thm-cfg-ctcgrad'
127
- ), FALSE, TRUE );
128
- $localize_array = apply_filters( 'chld_thm_cfg_localize_script', array(
129
- 'ssl' => is_ssl(),
130
- 'homeurl' => get_home_url() . '?preview_ctc=' . wp_create_nonce(),
131
- 'ajaxurl' => admin_url( 'admin-ajax.php' ),
132
- 'theme_uri' => get_theme_root_uri(),
133
- 'page' => CHLD_THM_CFG_MENU,
134
- 'themes' => $this->themes,
135
- 'source' => apply_filters( 'chld_thm_cfg_source_uri', get_theme_root_uri() . '/'
136
- . $this->css->get_prop( 'parnt' ) . '/style.css', $this->css ),
137
- 'target' => apply_filters( 'chld_thm_cfg_target_uri', get_theme_root_uri() . '/'
138
- . $this->css->get_prop( 'child' ) . '/style.css', $this->css ),
139
- 'parnt' => $this->css->get_prop( 'parnt' ),
140
- 'child' => $this->css->get_prop( 'child' ),
141
- 'addl_css' => $this->css->get_prop( 'addl_css' ),
142
- 'imports' => $this->css->get_prop( 'imports' ),
143
- 'is_debug' => $this->is_debug,
144
- '_background_url_txt' => __( 'URL/None', 'child-theme-configurator' ),
145
- '_background_origin_txt' => __( 'Origin', 'child-theme-configurator' ),
146
- '_background_color1_txt' => __( 'Color 1', 'child-theme-configurator' ),
147
- '_background_color2_txt' => __( 'Color 2', 'child-theme-configurator' ),
148
- '_border_width_txt' => __( 'Width/None', 'child-theme-configurator' ),
149
- '_border_style_txt' => __( 'Style', 'child-theme-configurator' ),
150
- '_border_color_txt' => __( 'Color', 'child-theme-configurator' ),
151
- 'swatch_txt' => $this->swatch_text,
152
- 'load_txt' => __( 'Are you sure? This will replace your current settings.', 'child-theme-configurator' ),
153
- 'important_txt' => __( '<span style="font-size:10px">!</span>', 'child-theme-configurator' ),
154
- 'selector_txt' => __( 'Selectors', 'child-theme-configurator' ),
155
- 'close_txt' => __( 'Close', 'child-theme-configurator' ),
156
- 'edit_txt' => __( 'Edit Selector', 'child-theme-configurator' ),
157
- 'cancel_txt' => __( 'Cancel', 'child-theme-configurator' ),
158
- 'rename_txt' => __( 'Rename', 'child-theme-configurator' ),
159
- 'css_fail_txt' => __( 'The stylesheet cannot be displayed.', 'child-theme-configurator' ),
160
- 'child_only_txt' => __( '(Child Only)', 'child-theme-configurator' ),
161
- 'inval_theme_txt' => __( 'Please enter a valid Child Theme.', 'child-theme-configurator' ),
162
- 'inval_name_txt' => __( 'Please enter a valid Child Theme name.', 'child-theme-configurator' ),
163
- 'theme_exists_txt' => __( '<strong>%s</strong> exists. Please enter a different Child Theme', 'child-theme-configurator' ),
164
- 'js_txt' => __( 'The page could not be loaded correctly.',
165
- 'child-theme-configurator' ),
166
- 'jquery_txt' => __( 'Conflicting or out-of-date jQuery libraries were loaded by another plugin:',
167
- 'child-theme-configurator' ),
168
- 'plugin_txt' => __( 'Deactivating or replacing plugins may resolve this issue.', 'child-theme-configurator' ),
169
- 'contact_txt' => sprintf( __( '%sWhy am I seeing this?%s',
170
- 'child-theme-configurator' ),
171
- '<a target="_blank" href="' . CHLD_THM_CFG_DOCS_URL . '/how-to-use/#script_dep">',
172
- '</a>' ),
173
- 'nosels_txt' => __( 'No Styles Available. Try "Parse Additional Stylesheets."', 'child-theme-configurator' ),
174
- ) );
175
- wp_localize_script(
176
- 'chld-thm-cfg-admin',
177
- 'ctcAjax',
178
- apply_filters( 'chld_thm_cfg_localize_array', $localize_array )
179
- );
180
- }
181
-
182
- /**
183
- * initialize configurator
184
- */
185
- function ctc_page_init () {
186
- // get all available themes
187
- $this->get_themes();
188
- // load config data and validate
189
- $this->load_config();
190
- // perform any checks prior to processing config data
191
- do_action( 'chld_thm_cfg_preprocess' );
192
- // process any additional forms
193
- do_action( 'chld_thm_cfg_forms', $this ); // hook for custom forms
194
- // process main post data
195
- $this->process_post();
196
- // initialize UI
197
- include_once( CHLD_THM_CFG_DIR . '/includes/class-ctc-ui.php' );
198
- $this->ui = new ChildThemeConfiguratorUI();
199
- // initialize help
200
- $this->ui->render_help_content();
201
- // load styles and scripts
202
- add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ), 99 );
203
- // load web fonts for this theme
204
- $this->load_imports();
205
- }
206
-
207
- function render() {
208
- $this->ui->render();
209
- }
210
-
211
- function get_themes() {
212
- // create cache of theme info
213
- $this->themes = array( 'child' => array(), 'parnt' => array() );
214
- foreach ( wp_get_themes() as $theme ):
215
- // organize into parent and child themes
216
- $group = $theme->parent() ? 'child' : 'parnt';
217
- // get the theme slug
218
- $slug = $theme->get_stylesheet();
219
- // get the theme slug
220
- $version = $theme->get( 'Version' );
221
- // strip auto-generated timestamp from CTC child theme version
222
- if ( 'child' == $group ) $version = preg_replace("/\.\d{6}\d+$/", '', $version );
223
- // add theme to themes array
224
- $this->themes[ $group ][ $slug ] = array(
225
- 'Template' => $theme->get( 'Template' ),
226
- 'Name' => $theme->get( 'Name' ),
227
- 'ThemeURI' => $theme->get( 'ThemeURI' ),
228
- 'Author' => $theme->get( 'Author' ),
229
- 'AuthorURI' => $theme->get( 'AuthorURI' ),
230
- 'Descr' => $theme->get( 'Description' ),
231
- 'Tags' => $theme->get( 'Tags' ),
232
- 'Version' => $version,
233
- 'screenshot' => $theme->get_screenshot(),
234
- 'allowed' => $theme->is_allowed(),
235
- );
236
- endforeach;
237
- }
238
-
239
- function validate_post( $action = 'ctc_update', $noncefield = '_wpnonce', $cap = 'install_themes' ) {
240
- // security: request must be post, user must have permission, referrer must be local and nonce must match
241
- return ( $this->is_post
242
- && current_user_can( $cap ) // ( 'edit_themes' )
243
- && ( $this->is_ajax ? check_ajax_referer( $action, $noncefield, FALSE ) :
244
- check_admin_referer( $action, $noncefield, FALSE ) ) );
245
- }
246
-
247
- function load_config() {
248
- include_once( CHLD_THM_CFG_DIR . '/includes/class-ctc-css.php' );
249
- $this->css = new ChildThemeConfiguratorCSS();
250
- if ( FALSE !== $this->css->load_config() ):
251
- // if themes do not exist reinitialize
252
- if ( ! $this->check_theme_exists( $this->css->get_prop( 'child' ) )
253
- || ! $this->check_theme_exists( $this->css->get_prop( 'parnt' ) ) ):
254
- add_action( 'admin_notices', array( $this, 'config_notice' ) );
255
- $this->css = new ChildThemeConfiguratorCSS();
256
- $this->css->enqueue = 'enqueue';
257
- endif;
258
- else:
259
- // this is a fresh install
260
- $this->css->enqueue = 'enqueue';
261
- endif;
262
- do_action( 'chld_thm_cfg_load' );
263
- if ( $this->is_get ):
264
- if ( $this->css->get_prop( 'child' ) ):
265
- // get filesystem credentials if available
266
- $this->verify_creds();
267
- $stylesheet = apply_filters( 'chld_thm_cfg_target', $this->css->get_child_target( 'style.css' ), $this->css );
268
- // check file permissions
269
- if ( !is_writable( $stylesheet ) && !$this->fs ):
270
- add_action( 'admin_notices', array( $this, 'writable_notice' ) );
271
- endif;
272
- // enqueue flag will be null for existing install < 1.6.0
273
- if ( !isset( $this->css->enqueue ) ):
274
- add_action( 'admin_notices', array( $this, 'enqueue_notice' ) );
275
- endif;
276
- endif;
277
- // check if max selectors reached
278
- if ( isset( $this->css->max_sel ) && $this->css->max_sel ):
279
- $this->debug( 'Max selectors exceeded.', __FUNCTION__ );
280
- //$this->errors[] = __( 'Maximum number of styles exceeded.', 'child-theme-configurator' );
281
- add_filter( 'chld_thm_cfg_update_msg', array( $this, 'max_styles_notice' ), 20 );
282
- endif;
283
- // check if file ownership is messed up from old version or other plugin
284
- // by comparing owner of plugin to owner of child theme:
285
- if ( fileowner( $this->css->get_child_target( '' ) ) != fileowner( CHLD_THM_CFG_DIR ) ):
286
- add_action( 'admin_notices', array( $this, 'owner_notice' ) );
287
- endif;
288
- endif;
289
- }
290
-
291
- function cache_debug() {
292
- $this->updates[] = array(
293
- 'obj' => 'debug',
294
- 'key' => '',
295
- 'data' => $this->print_debug( TRUE ),
296
- );
297
- }
298
- /**
299
- * ajax callback for saving form data
300
- */
301
- function ajax_save_postdata( $action = 'ctc_update' ) {
302
- $this->is_ajax = TRUE;
303
-
304
- // security check
305
- if ( $this->validate_post( $action ) ):
306
- if ( 'ctc_plugin' == $action ) do_action( 'chld_thm_cfg_pluginmode' );
307
- $this->verify_creds(); // initialize filesystem access
308
- // get configuration data from options API
309
- if ( FALSE !== $this->load_config() ): // sanity check: only update if config data exists
310
- if ( isset( $_POST[ 'ctc_is_debug' ] ) ):
311
- // toggle debug
312
- $this->toggle_debug();
313
- else:
314
- $this->css->parse_post_data(); // parse any passed values
315
- // if child theme config has been set up, save new data
316
- // return recent edits and selected stylesheets as cache updates
317
- if ( $this->css->get_prop( 'child' ) ):
318
- // hook for add'l plugin files and subdirectories
319
- do_action( 'chld_thm_cfg_addl_files', $this );
320
- $this->css->write_css();
321
- // add any additional updates to pass back to browser
322
- do_action( 'chld_thm_cfg_cache_updates' );
323
- /*
324
- $this->updates[] = array(
325
- 'obj' => 'addl_css',
326
- 'key' => '',
327
- 'data' => $this->css->get_prop( 'addl_css' ),
328
- );
329
- */
330
- endif;
331
-
332
- // update config data in options API
333
- $this->css->save_config();
334
- endif;
335
- endif;
336
- endif;
337
- $result = $this->css->obj_to_utf8( $this->updates );
338
- // send all updates back to browser to update cache
339
- die( json_encode( $result ) );
340
- }
341
-
342
- /**
343
- * ajax callback to query config data
344
- */
345
- function ajax_query_css( $action = 'ctc_update' ) {
346
- $this->is_ajax = TRUE;
347
- if ( $this->validate_post( $action ) ):
348
- if ( 'ctc_plugin' == $action ) do_action( 'chld_thm_cfg_pluginmode' );
349
- $this->load_config();
350
- $regex = "/^ctc_query_/";
351
- foreach( preg_grep( $regex, array_keys( $_POST ) ) as $key ):
352
- $name = preg_replace( $regex, '', $key );
353
- $param[ $name ] = sanitize_text_field( $_POST[ $key ] );
354
- endforeach;
355
- if ( !empty( $param[ 'obj' ] ) ):
356
- // add any additional updates to pass back to browser
357
- $this->updates[] = array(
358
- 'key' => isset( $param[ 'key' ] ) ? $param[ 'key' ] : '',
359
- 'obj' => $param[ 'obj' ],
360
- 'data' => $this->css->get_prop( $param[ 'obj' ], $param ),
361
- );
362
- do_action( 'chld_thm_cfg_cache_updates' );
363
- die( json_encode( $this->updates ) );
364
- endif;
365
- endif;
366
- die( 0 );
367
- }
368
-
369
- /***
370
- * Handles processing for all form submissions.
371
- * Older versions ( < 1.6.0 ) smelled like spaghetti so we moved conditions
372
- * to switch statement with the main setup logic in a separate function.
373
- */
374
- function process_post() {
375
- // make sure this is a post
376
- if ( $this->is_post ):
377
- // see if a valid action was passed
378
- foreach ( $this->actionfields as $field ):
379
- if ( in_array( 'ctc_' . $field, array_keys( $_POST ) ) ):
380
- $actionfield = $field;
381
- break;
382
- endif;
383
- endforeach;
384
- if ( empty( $actionfield ) ) return FALSE;
385
-
386
- // make sure post passes security checkpoint
387
- $this->errors = array();
388
- if ( $this->validate_post( apply_filters( 'chld_thm_cfg_action', 'ctc_update' ) ) ):
389
- // zip export does not require filesystem access so check that first
390
- if ( 'export_child_zip' == $actionfield ):
391
- $this->export_zip();
392
- // if we get here the zip failed
393
- $this->errors[] = __( 'Zip file creation failed.', 'child-theme-configurator' );
394
- // all other actions require filesystem access
395
- else:
396
- // handle uploaded file before checking filesystem
397
- if ( 'theme_image_submit' == $actionfield && isset( $_FILES[ 'ctc_theme_image' ] ) ):
398
- $this->handle_file_upload( 'ctc_theme_image', $this->imgmimes );
399
- elseif ( 'theme_screenshot_submit' == $actionfield && isset( $_FILES[ 'ctc_theme_screenshot' ] ) ):
400
- $this->handle_file_upload( 'ctc_theme_screenshot', $this->imgmimes );
401
- endif;
402
- // now we need to check filesystem access
403
- $args = preg_grep( "/nonce/", array_keys( $_POST ), PREG_GREP_INVERT );
404
- $this->verify_creds( $args );
405
- if ( $this->fs ):
406
- $msg = FALSE;
407
- // we have filesystem access so proceed with specific actions
408
- switch( $actionfield ):
409
- case 'load_styles':
410
- // main child theme setup function
411
- $msg = $this->setup_child_theme();
412
- break;
413
-
414
- case 'parnt_templates_submit':
415
- // copy parent templates to child
416
- if ( isset( $_POST[ 'ctc_file_parnt' ] ) ):
417
- foreach ( $_POST[ 'ctc_file_parnt' ] as $file ):
418
- $this->copy_parent_file( sanitize_text_field( $file ) );
419
- endforeach;
420
- $msg = '8&tab=file_options';
421
- endif;
422
- break;
423
-
424
- case 'child_templates_submit':
425
- // delete child theme files
426
- if ( isset( $_POST[ 'ctc_file_child' ] ) ):
427
- if ( in_array( 'functions', $_POST[ 'ctc_file_child' ] ) ):
428
- $this->errors[] =
429
- __( 'The Functions file is required and cannot be deleted.',
430
- 'child-theme-configurator' );
431
- else:
432
- foreach ( $_POST[ 'ctc_file_child' ] as $file ):
433
- $this->delete_child_file( sanitize_text_field( $file ),
434
- ( preg_match( "/^style|ctc\-plugins/", $file ) ? 'css' : 'php' ) );
435
- endforeach;
436
- $msg = '8&tab=file_options';
437
- endif;
438
- endif;
439
- break;
440
-
441
- case 'image_submit':
442
- // delete child theme images
443
- if ( isset( $_POST[ 'ctc_img' ] ) ):
444
- foreach ( $_POST[ 'ctc_img' ] as $file ):
445
- $this->delete_child_file( 'images/' . sanitize_text_field( $file ), 'img' );
446
- endforeach;
447
- $msg = '8&tab=file_options';
448
- endif;
449
- break;
450
-
451
- case 'templates_writable_submit':
452
- // make specific files writable ( systems not running suExec )
453
- if ( isset( $_POST[ 'ctc_file_child' ] ) ):
454
- foreach ( $_POST[ 'ctc_file_child' ] as $file ):
455
- $this->set_writable( sanitize_text_field( $file ),
456
- ( 0 === strpos( $file, 'style' ) ? 'css' : 'php' ) );
457
- endforeach;
458
- $msg = '8&tab=file_options';
459
- endif;
460
- break;
461
-
462
- case 'set_writable':
463
- // make child theme style.css and functions.php writable ( systems not running suExec )
464
- $this->set_writable(); // no argument defaults to style.css
465
- $this->set_writable( 'functions' );
466
- $msg = '8&tab=file_options';
467
- break;
468
-
469
- case 'reset_permission':
470
- // make child theme read-only ( systems not running suExec )
471
- $this->unset_writable();
472
- $msg = '8&tab=file_options';
473
- break;
474
-
475
- case 'theme_image_submit':
476
- // move uploaded child theme images (now we have filesystem access)
477
- if ( isset( $_POST[ 'movefile' ] ) ):
478
- $this->move_file_upload( 'images' );
479
- $msg = '8&tab=file_options';
480
- endif;
481
- break;
482
-
483
- case 'theme_screenshot_submit':
484
- // move uploaded child theme screenshot (now we have filesystem access)
485
- if ( isset( $_POST[ 'movefile' ] ) ):
486
- // remove old screenshot
487
- foreach( array_keys( $this->imgmimes ) as $extreg ):
488
- foreach ( explode( '|', $extreg ) as $ext ):
489
- $this->delete_child_file( 'screenshot', $ext );
490
- endforeach;
491
- endforeach;
492
- $this->move_file_upload( '' );
493
- $msg = '8&tab=file_options';
494
- endif;
495
- break;
496
- default:
497
- // assume we are on the files tab so just redirect there
498
- $msg = '8&tab=file_options';
499
- endswitch;
500
- endif; // end filesystem condition
501
- endif; // end zip export condition
502
- if ( empty( $this->errors ) && empty( $this->fs_prompt ) )
503
- // no errors so we redirect with confirmation message
504
- $this->update_redirect( $msg );
505
- // otherwise fail gracefully
506
- $msg = NULL;
507
- return FALSE;
508
- endif; // end post validation condition
509
- // if you end up here you are not welcome
510
- $msg = NULL;
511
- $this->errors[] = __( 'You do not have permission to configure child themes.', 'child-theme-configurator' );
512
- endif; // end request method condition
513
- return FALSE;
514
- }
515
-
516
- function toggle_debug() {
517
- $debug = '';
518
- if ( $_POST[ 'ctc_is_debug' ] ):
519
- $this->is_debug = 1;
520
- $debug = $this->print_debug( TRUE );
521
- else:
522
- $this->is_debug = 0;
523
- endif;
524
- update_option( CHLD_THM_CFG_OPTIONS . '_debug', $this->is_debug );
525
- $this->updates[] = array(
526
- 'obj' => 'debug',
527
- 'key' => '',
528
- 'data' => $debug,
529
- );
530
- }
531
-
532
- /***
533
- * Handle the creation or update of a child theme
534
- */
535
- function setup_child_theme() {
536
- // sanitize and extract config fields into local vars
537
- foreach ( $this->configfields as $configfield ):
538
-
539
- $varparts = explode( '_', $configfield );
540
- $varname = end( $varparts );
541
- ${$varname} = empty( $_POST[ 'ctc_' . $configfield ] ) ? '' :
542
- preg_replace( "/\s+/s", ' ', sanitize_text_field( $_POST[ 'ctc_' . $configfield ] ) );
543
- $this->debug( 'Extracting var ' . $varname . ' from ctc_' . $configfield . ' value: ' . ${$varname} , __FUNCTION__ );
544
- endforeach;
545
-
546
- // legacy plugin extension needs parent/child values but this version disables the inputs
547
- // so get we them from current css object
548
- if ( !$this->is_theme( $configtype ) && $this->is_legacy() ):
549
- $parnt = $this->css->get_prop( 'parnt' );
550
- $child = $this->css->get_prop( 'child' );
551
- $name = $this->css->get_prop( 'child_name' );
552
- endif;
553
-
554
- // validate parent and child theme inputs
555
- if ( $parnt ):
556
- if ( ! $this->check_theme_exists( $parnt ) ):
557
- $this->errors[] = sprintf(
558
- __( '%s does not exist. Please select a valid Parent Theme.',
559
- 'child-theme-configurator' ), $parnt );
560
- endif;
561
- else:
562
- $this->errors[] = __( 'Please select a valid Parent Theme.', 'child-theme-configurator' );
563
- endif;
564
- if ( 'existing' == $type && empty( $child ) ):
565
- $this->errors[] = __( 'Please enter a valid Child Theme directory.', 'child-theme-configurator' );
566
- endif;
567
- if ( empty( $name ) ):
568
- $name = ucfirst( $child );
569
- endif;
570
- // if this is a shiny brand new child theme certain rules apply
571
- if ( 'new' == $type ):
572
- if ( empty( $template ) && empty( $name ) ):
573
- $this->errors[] = __( 'Please enter a valid Child Theme template name.', 'child-theme-configurator' );
574
- else:
575
- $child = preg_replace( "%[^\w\-]%", '', empty( $template ) ? $name : $template );
576
- if ( $this->check_theme_exists( $child ) ):
577
- $this->errors[] = sprintf(
578
- __( '<strong>%s</strong> exists. Please enter a different Child Theme template name.',
579
- 'child-theme-configurator' ), $child );
580
- endif;
581
- endif;
582
- endif;
583
-
584
- // clone existing child theme
585
- if ( 'existing' == $type && isset( $_POST[ 'ctc_duplicate_theme' ] ) ):
586
- $clone = strtolower( preg_replace( "%[^\w\-]%", '', sanitize_text_field( $_POST[ 'ctc_duplicate_theme_slug' ] ) ) );
587
- if ( empty( $clone ) ):
588
- $this->errors[] = __( 'Please enter a valid Child Theme template name.', 'child-theme-configurator' );
589
- else:
590
- if ( $this->check_theme_exists( $clone ) ):
591
- $this->errors[] = sprintf(
592
- __( '<strong>%s</strong> exists. Please enter a different Child Theme template name.',
593
- 'child-theme-configurator' ), $clone );
594
- else:
595
- $this->clone_child_theme( $child, $clone );
596
- if ( empty( $this->errors ) ):
597
- $this->copy_theme_mods( $child, $clone );
598
- $child = $clone;
599
- endif;
600
- endif;
601
- endif;
602
- endif;
603
-
604
- if ( FALSE === $this->verify_child_dir( $child ) ):
605
- $this->errors[] = __( 'Your theme directories are not writable.', 'child-theme-configurator' );
606
- add_action( 'admin_notices', array( $this, 'writable_notice' ) );
607
- endif;
608
-
609
- // if no errors so far, we are good to create child theme
610
- if ( empty( $this->errors ) ):
611
- // save imports in case this is a rebuild
612
- $imports = $this->css->imports;
613
- $nowarn = ( $nowarn || $this->css->nowarn ) ? 1 : 0;
614
- // reset everything else
615
- $this->css = new ChildThemeConfiguratorCSS();
616
- // restore imports if this is a rebuild
617
- $this->css->imports = $imports;
618
- $this->css->nowarn = $nowarn;
619
- // parse parent stylesheet if theme or legacy plugin extension
620
- if ( $this->is_theme( $configtype ) || $this->is_legacy() ):
621
- add_action( 'chld_thm_cfg_parse_stylesheets', array( &$this, 'parse_parent_stylesheet' ) );
622
- if ( is_multisite() )
623
- add_action( 'chld_thm_cfg_addl_options', array( &$this, 'network_enable' ) );
624
- endif;
625
-
626
- add_action( 'chld_thm_cfg_parse_stylesheets', array( &$this, 'parse_additional_stylesheets' ) );
627
- add_action( 'chld_thm_cfg_parse_stylesheets', array( &$this, 'parse_child_stylesheet' ) );
628
-
629
- // function to support wp_filesystem requirements
630
- if ( $this->is_theme( $configtype ) ):
631
- // is theme means this is not a plugin stylesheet config
632
- add_action( 'chld_thm_cfg_addl_files', array( &$this, 'add_base_files' ), 10, 2 );
633
- add_action( 'chld_thm_cfg_addl_files', array( &$this, 'copy_screenshot' ), 10, 2 );
634
- add_action( 'chld_thm_cfg_addl_files', array( &$this, 'enqueue_parent_css' ), 15, 2 );
635
- elseif( $this->is_legacy() && has_action( 'chld_thm_cfg_addl_files' ) ):
636
- // backwards compatability for plugins extension < 2.0.0 (before pro)
637
- // action exists so we have to hijack it to use new filesystem checks
638
- remove_all_actions( 'chld_thm_cfg_addl_files' );
639
- add_action( 'chld_thm_cfg_addl_files', array( &$this, 'write_addl_files' ), 10, 2 );
640
- $this->css->set_prop( 'configtype', $configtype );
641
- endif;
642
-
643
- // update with new parameters
644
- $this->css->set_prop( 'parnt', $parnt );
645
- $this->css->set_prop( 'child', $child );
646
- $this->css->set_prop( 'child_name', $name );
647
- $this->css->set_prop( 'child_author', $author );
648
- $this->css->set_prop( 'child_themeuri', $themeuri );
649
- $this->css->set_prop( 'child_authoruri', $authoruri );
650
- $this->css->set_prop( 'child_descr', $descr );
651
- $this->css->set_prop( 'child_tags', $tags );
652
- $this->css->set_prop( 'child_version', strlen( $version ) ? $version : '1.0' );
653
-
654
- $this->css->set_prop( 'nowarn', $nowarn );
655
- // set stylesheet handling option
656
- if ( isset( $_POST[ 'ctc_parent_enqueue' ] ) )
657
- $this->css->set_prop( 'enqueue', sanitize_text_field( $_POST[ 'ctc_parent_enqueue' ] ) );
658
- elseif ( !$this->is_theme( $configtype ) )
659
- $this->css->set_prop( 'enqueue', 'enqueue' );
660
-
661
- // plugin hooks for additional stylesheet handling options
662
- do_action( 'chld_thm_cfg_stylesheet_handling' );
663
- do_action( 'chld_thm_cfg_existing_theme' );
664
- // plugin hook to parse additional or non-standard files
665
- do_action( 'chld_thm_cfg_parse_stylesheets' );
666
-
667
- // copy menus, widgets and other customizer options from parent to child if selected
668
- if ( isset( $_POST[ 'ctc_parent_mods' ] ) ) // && empty( $_POST[ 'ctc_duplicate_theme' ] ) )
669
- $this->copy_theme_mods( $parnt, $child );
670
-
671
- // run code generation function in read-only mode to add existing external stylesheet links to config data
672
- $this->enqueue_parent_css( $this->css, TRUE );
673
- // hook for add'l plugin files and subdirectories. Must run after stylesheets are parsed to apply latest options
674
- do_action( 'chld_thm_cfg_addl_files', $this );
675
- // do not continue if errors
676
- if ( empty ( $this->errors ) ):
677
- // set flag to skip import link conversion on ajax save
678
- $this->css->converted = 1;
679
-
680
- // try to write new stylsheet. If it fails send alert.
681
- if ( FALSE === $this->css->write_css( isset( $_POST[ 'ctc_backup' ] ) ) ):
682
- $this->debug( 'failed to write', __FUNCTION__ );
683
- $this->errors[] = __( 'Your stylesheet is not writable.', 'child-theme-configurator' );
684
- add_action( 'admin_notices', array( $this, 'writable_notice' ) );
685
- return FALSE;
686
- endif;
687
-
688
- // save new object to WP options table
689
- $this->css->save_config();
690
-
691
- // plugin hook for additional child theme setup functions
692
- do_action( 'chld_thm_cfg_addl_options', $this );
693
-
694
- // return message id 1, which says new child theme created successfully;
695
- return 1;
696
- endif;
697
- endif;
698
- return FALSE;
699
- }
700
-
701
- function load_imports() {
702
- // allows fonts and other externals to be previewed
703
- // loads early not to conflict with admin stylesheets
704
- if ( $imports = $this->css->get_prop( 'imports' ) ):
705
- $ext = 0;
706
- foreach ( $imports as $import ):
707
- $this->convert_import_to_enqueue( $import, ++$ext, TRUE );
708
- endforeach;
709
- endif;
710
- }
711
-
712
- /*
713
- * TODO: this is a stub for future use
714
- */
715
- function sanitize_options( $input ) {
716
- return $input;
717
- }
718
-
719
- /**
720
- * remove slashes and non-alphas from stylesheet name
721
- */
722
- function sanitize_slug( $slug ) {
723
- return preg_replace( "/[^\w\-]/", '', $slug );
724
- }
725
-
726
- function update_redirect( $msg = 1 ) {
727
- if ( empty( $this->is_ajax ) ):
728
- if ( $this->is_debug )
729
- set_site_transient( CHLD_THM_CFG_OPTIONS . '_debug', $this->debug, 3600 );
730
- $ctcpage = apply_filters( 'chld_thm_cfg_admin_page', CHLD_THM_CFG_MENU );
731
- $screen = get_current_screen()->id;
732
- wp_safe_redirect(
733
- ( strstr( $screen, '-network' ) ? network_admin_url( 'themes.php' ) : admin_url( 'tools.php' ) )
734
- . '?page=' . $ctcpage . ( $msg ? '&updated=' . $msg : '' ) );
735
- die();
736
- endif;
737
- }
738
-
739
- function verify_child_dir( $path ) {
740
- $this->debug( 'Verifying child dir: ' . $path, __FUNCTION__ );
741
- if ( !$this->fs ):
742
- $this->debug( 'No filesystem access.', __FUNCTION__ );
743
- return FALSE; // return if no filesystem access
744
- endif;
745
- global $wp_filesystem;
746
- $themedir = $wp_filesystem->find_folder( get_theme_root() );
747
- if ( ! $wp_filesystem->is_writable( $themedir ) ):
748
- $this->debug( 'Directory not writable: ' . $themedir, __FUNCTION__ );
749
- return FALSE;
750
- endif;
751
- $childparts = explode( '/', $this->normalize_path( $path ) );
752
- while ( count( $childparts ) ):
753
- $subdir = array_shift( $childparts );
754
- if ( empty( $subdir ) ) continue;
755
- $themedir = trailingslashit( $themedir ) . $subdir;
756
- if ( ! $wp_filesystem->is_dir( $themedir ) ):
757
- if ( ! $wp_filesystem->mkdir( $themedir, FS_CHMOD_DIR ) ):
758
- $this->debug( 'Could not make directory: ' . $themedir, __FUNCTION__ );
759
- return FALSE;
760
- endif;
761
- elseif ( ! $wp_filesystem->is_writable( $themedir ) ):
762
- $this->debug( 'Directory not writable: ' . $themedir, __FUNCTION__ );
763
- return FALSE;
764
- endif;
765
- endwhile;
766
- $this->debug( 'Child dir verified: ' . $themedir, __FUNCTION__ );
767
- return TRUE;
768
- }
769
-
770
- function add_base_files( $obj ){
771
- // add functions.php file
772
- $contents = "<?php
773
- // Exit if accessed directly
774
- if ( !defined( 'ABSPATH' ) ) exit;
775
- ";
776
- $this->write_child_file( 'functions.php', $contents );
777
- $this->write_child_file( 'style.css', $this->css->get_css_header() );
778
- }
779
-
780
- // parses @import syntax and converts to wp_enqueue_style statement
781
- function convert_import_to_enqueue( $import, $count, $execute = FALSE ) {
782
- $relpath = $this->css->get_prop( 'child' );
783
- $import = preg_replace( "#^.*?url\(([^\)]+?)\).*#", "$1", $import );
784
- $import = preg_replace( "#[\'\"]#", '', $import );
785
- $path = $this->css->convert_rel_url( trim( $import ), $relpath , FALSE );
786
- $abs = preg_match( '%(https?:)?//%', $path );
787
- if ( $execute )
788
- wp_enqueue_style( 'chld_thm_cfg_ext' . $count, $abs ? $path : trailingslashit( get_theme_root_uri() ) . $path );
789
- else
790
- return "wp_enqueue_style( 'chld_thm_cfg_ext" . $count . "', "
791
- . ( $abs ? "'" . $path . "'" : "trailingslashit( get_theme_root_uri() ) . '" . $path . "'" ) . ' );';
792
- }
793
-
794
- // converts enqueued path into @import statement for config settings
795
- function convert_enqueue_to_import( $path ) {
796
- if ( preg_match( '%(https?:)?//%', $path ) ):
797
- $this->css->imports[ 'child' ]['@import url(' . $path . ')'] = 1;
798
- return;
799
- endif;
800
- $regex = '#^' . preg_quote( trailingslashit( $this->css->get_prop( 'child' ) ) ) . '#';
801
- $path = preg_replace( $regex, '', $path, -1, $count );
802
- if ( $count ):
803
- $this->css->imports[ 'child' ]['@import url(' . $path . ')'] = 1;
804
- return;
805
- endif;
806
- $parent = trailingslashit( $this->css->get_prop( 'parnt' ) );
807
- $regex = '#^' . preg_quote( $parent ) . '#';
808
- $path = preg_replace( $regex, '../' . $parent, $path, -1, $count );
809
- if ( $count )
810
- $this->css->imports[ 'child' ]['@import url(' . $path . ')'] = 1;
811
- }
812
-
813
- /**
814
- * Generates wp_enqueue_script code block for child theme functions file
815
- * Enqueues parent and/or child stylesheet depending on value of 'enqueue' setting.
816
- * If external imports are present, it enqueues them as well.
817
- */
818
- function enqueue_parent_code(){
819
- $imports = $this->css->get_prop( 'imports' );
820
- $enqueues = array();
821
- $code = '';
822
- // enqueue parent stylesheet
823
- if ( 'enqueue' == $this->css->enqueue || 'both' == $this->css->enqueue )
824
- $enqueues[] = " wp_enqueue_style( 'chld_thm_cfg_parent', trailingslashit( get_template_directory_uri() ) . 'style.css' );";
825
- // enqueue external stylesheets (previously used @import in the stylesheet)
826
- if ( !empty( $imports ) ):
827
- $ext = 0;
828
- foreach ( $imports as $import ):
829
- $ext++;
830
- $enqueues[] = ' ' . $this->convert_import_to_enqueue( $import, $ext );
831
- endforeach;
832
- endif;
833
- if ( count( $enqueues ) ):
834
- $code = "// AUTO GENERATED - Do not modify or remove comment markers above or below:
835
- ";
836
- $code .= "
837
-
838
- if ( !function_exists( 'chld_thm_cfg_parent_css' ) ):
839
- function chld_thm_cfg_parent_css() {
840
- ";
841
- $code .= implode( "\n", $enqueues );
842
- $code .= "
843
- }
844
- endif;
845
- add_action( 'wp_enqueue_scripts', 'chld_thm_cfg_parent_css' );
846
- ";
847
- endif;
848
- // enqueue child stylesheet. This feature was added to avoid using @import to load parent stylesheet when links are hard-coded into header.php
849
- if ( 'child' == $this->css->enqueue || 'both' == $this->css->enqueue ):
850
- $code .= "
851
- if ( !function_exists( 'chld_thm_cfg_child_css' ) ):
852
- function chld_thm_cfg_child_css() {
853
- wp_enqueue_style( 'chld_thm_cfg_child', get_stylesheet_uri() );
854
- }
855
- endif;
856
- add_action( 'wp_enqueue_scripts', 'chld_thm_cfg_child_css', 999 );
857
- ";
858
- endif;
859
- return explode( "\n", apply_filters( 'chld_thm_cfg_enqueue_code_filter', $code ) );
860
- }
861
-
862
- // updates function file with wp_enqueue_script code block. If getexternals flag is passed function is run in read-only mode
863
- function enqueue_parent_css( $obj, $getexternals = FALSE ) {
864
- $marker = 'ENQUEUE PARENT ACTION';
865
- $insertion = $this->enqueue_parent_code();
866
- if ( $filename = $this->css->is_file_ok( $this->css->get_child_target( 'functions.php' ), 'write' ) )
867
- $this->insert_with_markers( $filename, $marker, $insertion, $getexternals );
868
- }
869
-
870
- /**
871
- * Update functions file with wp_enqueue_style code block. Runs in read-only mode if getexternals is passed.
872
- * This function uses the same method as the WP core function that updates .htaccess
873
- * we would have used WP's insert_with_markers function,
874
- * but it does not use wp_filesystem API.
875
- */
876
- function insert_with_markers( $filename, $marker, $insertion, $getexternals = FALSE ) {
877
- if ( count( $this->errors ) ):
878
- $this->debug( 'Errors detected, returning', __FUNCTION__ );
879
- return FALSE;
880
- endif;
881
- // first check if this is an ajax update
882
- if ( $this->is_ajax && is_readable( $filename ) && is_writable( $filename ) ):
883
- // ok to proceed
884
- $this->debug( 'Ajax update, bypassing wp filesystem.', __FUNCTION__ );
885
- $markerdata = explode( "\n", @file_get_contents( $filename ) );
886
- elseif ( !$this->fs ):
887
- $this->debug( 'No filesystem access.', __FUNCTION__ );
888
- return FALSE; // return if no filesystem access
889
- else:
890
- global $wp_filesystem;
891
- if( !$wp_filesystem->exists( $this->fspath( $filename ) ) ):
892
- // make sure file exists with php header
893
- $this->debug( 'No functions file, creating...', __FUNCTION__ );
894
- $this->add_base_files( $this );
895
- endif;
896
- // get_contents_array returns extra linefeeds so just split it ourself
897
- $markerdata = explode( "\n", $wp_filesystem->get_contents( $this->fspath( $filename ) ) );
898
- endif;
899
- $newfile = '';
900
- $externals = array();
901
- $phpopen = 0;
902
- $in_comment = 0;
903
- $foundit = FALSE;
904
- $lasttoken = '';
905
- if ( $markerdata ):
906
- $state = TRUE;
907
- foreach ( $markerdata as $n => $markerline ) {
908
- // update open state
909
- $openstars = 0;
910
- $closestars = 0;
911
- // remove double slash comment to end of line
912
- $str = preg_replace( "/\/\/.*$/", '', $markerline );
913
- preg_match_all("/(<\?|\?>|\*\/|\/\*)/", $str, $matches );
914
- if ( $matches ):
915
- foreach ( $matches[1] as $token ):
916
- $lasttoken = $token;
917
- if ( '/*' == $token ):
918
- $in_comment = 1;
919
- elseif ( '*/' == $token ):
920
- $in_comment = 0;
921
- elseif ( '<?' == $token && !$in_comment ):
922
- $phpopen = 1;
923
- elseif ( '?>' == $token && !$in_comment ):
924
- $phpopen = 0;
925
- endif;
926
- endforeach;
927
- endif;
928
- if ( strpos( $markerline, '// BEGIN ' . $marker ) !== FALSE )
929
- $state = FALSE;
930
- if ( $state ):
931
- if ( $n + 1 < count( $markerdata ) )
932
- $newfile .= "{$markerline}\n";
933
- else
934
- $newfile .= "{$markerline}";
935
- elseif ( $getexternals ):
936
- // look for existing external stylesheets and add to imports config data
937
- if ( preg_match( "/wp_enqueue_style.+?'chld_thm_cfg_ext\d+'.+?'(.+?)'/", $markerline, $matches ) )
938
- $this->convert_enqueue_to_import( $matches[ 1 ] );
939
- endif;
940
- if ( strpos( $markerline, '// END ' . $marker ) !== FALSE ):
941
- $newfile .= "// BEGIN {$marker}\n";
942
- if ( is_array( $insertion ) )
943
- foreach ( $insertion as $insertline )
944
- $newfile .= "{$insertline}\n";
945
- $newfile .= "// END {$marker}\n";
946
- $state = TRUE;
947
- $foundit = TRUE;
948
- endif;
949
- }
950
- else:
951
- $this->debug( 'Could not parse functions file', __FUNCTION__ );
952
- return FALSE;
953
- endif;
954
- if ( $foundit ):
955
- $this->debug( 'Found marker, replaced inline', __FUNCTION__ );
956
- else:
957
- // verify there is no PHP close tag at end of file
958
- if ( ! $phpopen ):
959
- $this->debug( 'PHP not open', __FUNCTION__ );
960
- $this->errors[] = __( 'A closing PHP tag was detected in Child theme functions file so "Parent Stylesheet Handling" option was not configured. Closing PHP at the end of the file is discouraged as it can cause premature HTTP headers. Please edit <code>functions.php</code> to remove the final <code>?&gt;</code> tag and click "Generate/Rebuild Child Theme Files" again.', 'child-theme-configurator' );
961
- return FALSE;
962
- //$newfile .= '<?php' . LF;
963
- endif;
964
- $newfile .= "\n// BEGIN {$marker}\n";
965
- foreach ( $insertion as $insertline )
966
- $newfile .= "{$insertline}\n";
967
- $newfile .= "// END {$marker}\n";
968
- endif;
969
- // only write file when getexternals is false
970
- if ( ! $getexternals ):
971
- $this->debug( 'Writing new functions file...', __FUNCTION__ );
972
- if ( $this->is_ajax && is_writable( $filename ) ):
973
- if ( FALSE === @file_put_contents( $filename, $newfile ) ):
974
- $this->debug( 'Ajax write failed.', __FUNCTION__ );
975
- return FALSE;
976
- endif;
977
- elseif ( FALSE === $wp_filesystem->put_contents( $this->fspath( $filename ), $newfile ) ):
978
- $this->debug( 'Filesystem write failed.', __FUNCTION__ );
979
- return FALSE;
980
- endif;
981
- $this->css->converted = 1;
982
- endif;
983
- }
984
-
985
- // creates/updates file via filesystem API
986
- function write_child_file( $file, $contents ) {
987
- if ( !$this->fs ):
988
- $this->debug( 'No filesystem access.', __FUNCTION__ );
989
- return FALSE; // return if no filesystem access
990
- endif;
991
- global $wp_filesystem;
992
- if ( $file = $this->css->is_file_ok( $this->css->get_child_target( $file ), 'write' ) ):
993
- if ( !$wp_filesystem->exists( $this->fspath( $file ) ) ):
994
- $this->debug( 'Writing to filesystem: ' . $file, __FUNCTION__ );
995
- if ( FALSE === $wp_filesystem->put_contents( $this->fspath( $file ), $contents ) ):
996
- $this->debug( 'Filesystem write failed.', __FUNCTION__ );
997
- return FALSE;
998
- endif;
999
- else:
1000
- $this->debug( 'File exists.', __FUNCTION__ );
1001
- return FALSE;
1002
- endif;
1003
- else:
1004
- $this->debug( 'No directory.', __FUNCTION__ );
1005
- return FALSE;
1006
- endif;
1007
- $this->debug( 'Filesystem write successful.', __FUNCTION__ );
1008
- }
1009
-
1010
- function copy_screenshot( $obj ) {
1011
- // always copy screenshot
1012
- $this->copy_parent_file( 'screenshot' );
1013
- }
1014
-
1015
- function copy_parent_file( $file, $ext = 'php' ) {
1016
- if ( !$this->fs ):
1017
- $this->debug( 'No filesystem access.', __FUNCTION__ );
1018
- return FALSE; // return if no filesystem access
1019
- endif;
1020
- global $wp_filesystem;
1021
- $parent_file = NULL;
1022
- if ( 'screenshot' == $file ):
1023
- foreach ( array_keys( $this->imgmimes ) as $extreg ):
1024
- foreach( explode( '|', $extreg ) as $ext ):
1025
- if ( $parent_file = $this->css->is_file_ok( $this->css->get_parent_source( 'screenshot.' . $ext ) ) ) break;
1026
- endforeach;
1027
- if ( $parent_file ):
1028
- $parent_file = $this->fspath( $parent_file );
1029
- break;
1030
- endif;
1031
- endforeach;
1032
- else:
1033
- $parent_file = $this->fspath( $this->css->is_file_ok( $this->css->get_parent_source( $file . '.' . $ext ) ) );
1034
- endif;
1035
- // get child theme + file + ext ( passing empty string and full child path to theme_basename )
1036
- $child_file = $this->css->get_child_target( $file . '.' . $ext );
1037
- // return true if file already exists
1038
- if ( $wp_filesystem->exists( $this->fspath( $child_file ) ) ) return TRUE;
1039
- $child_dir = dirname( $this->theme_basename( '', $child_file ) );
1040
- $this->debug( 'Verifying child dir... ', __FUNCTION__ );
1041
- if ( $parent_file // sanity check
1042
- && $child_file // sanity check
1043
- && $this->verify_child_dir( $child_dir ) //create child subdir if necessary
1044
- && $wp_filesystem->copy( $parent_file, $this->fspath( $child_file ), FS_CHMOD_FILE ) ) return TRUE;
1045
- $this->errors[] = __( 'Could not copy file:' . $parent_file, 'child-theme-configurator' );
1046
- }
1047
-
1048
- function delete_child_file( $file, $ext = 'php' ) {
1049
- if ( !$this->fs ):
1050
- $this->debug( 'No filesystem access.', __FUNCTION__ );
1051
- return FALSE; // return if no filesystem access
1052
- endif;
1053
- global $wp_filesystem;
1054
- // verify file is in child theme and exists before removing.
1055
- $file = ( 'img' == $ext ? $file : $file . '.' . $ext );
1056
- if ( $child_file = $this->css->is_file_ok( $this->css->get_child_target( $file ), 'write' ) ):
1057
- if ( $wp_filesystem->exists( $this->fspath( $child_file ) ) ):
1058
- if ( $wp_filesystem->delete( $this->fspath( $child_file ) ) ):
1059
- return TRUE;
1060
- else:
1061
- $this->errors[] = __( 'Could not delete file.', 'child-theme-configurator' );
1062
- $this->debug( 'Could not delete file', __FUNCTION__ );
1063
- endif;
1064
- endif;
1065
- endif;
1066
- }
1067
-
1068
- function get_files( $theme, $type = 'template' ) {
1069
- if ( !isset( $this->files[ $theme ] ) ):
1070
- $this->files[ $theme ] = array();
1071
- $imgext = '(' . implode( '|', array_keys( $this->imgmimes ) ) . ')';
1072
- foreach ( $this->css->recurse_directory(
1073
- trailingslashit( get_theme_root() ) . $theme, '', TRUE ) as $file ):
1074
- $file = $this->theme_basename( $theme, $file );
1075
- if ( preg_match( "/^style\-(\d+)\.css$/", $file, $matches ) ):
1076
- $date = date_i18n( 'D, j M Y g:i A', strtotime( $matches[ 1 ] ) );
1077
- $this->files[ $theme ][ 'backup' ][ $file ] = $date;
1078
- elseif ( preg_match( "/^ctc\-plugins\-(\d+)\.css$/", $file, $matches ) ):
1079
- $date = date_i18n( 'D, j M Y g:i A', strtotime( $matches[ 1 ] ) );
1080
- $this->files[ $theme ][ 'pluginbackup' ][ $file ] = $date;
1081
- elseif ( preg_match( "/\.php$/", $file ) ):
1082
- $this->files[ $theme ][ 'template' ][] = $file;
1083
- elseif ( preg_match( "/\.css$/", $file ) && 'style.css' != $file ):
1084
- $this->files[ $theme ][ 'stylesheet' ][] = $file;
1085
- elseif ( preg_match( "/^images\/.+?\." . $imgext . "$/", $file ) ):
1086
- $this->files[ $theme ][ 'img' ][] = $file;
1087
- endif;
1088
- endforeach;
1089
- endif;
1090
- $types = explode(",", $type);
1091
- $files = array();
1092
- foreach ( $types as $type )
1093
- if ( isset( $this->files[ $theme ][ $type ] ) )
1094
- $files = array_merge( $this->files[ $theme ][ $type ], $files );
1095
- return $files;
1096
- }
1097
-
1098
- function theme_basename( $theme, $file ) {
1099
- $file = $this->normalize_path( $file );
1100
- // if no theme passed, returns theme + file
1101
- $themedir = trailingslashit( $this->normalize_path( get_theme_root() ) ) . ( '' == $theme ? '' : trailingslashit( $theme ) );
1102
- $this->debug( 'Themedir: ' . $themedir . ' File: ' . $file , __FUNCTION__ );
1103
- return preg_replace( '%^' . preg_quote( $themedir ) . '%', '', $file );
1104
- }
1105
-
1106
- function uploads_basename( $file ) {
1107
- $file = $this->normalize_path( $file );
1108
- $uplarr = wp_upload_dir();
1109
- $upldir = trailingslashit( $this->normalize_path( $uplarr[ 'basedir' ] ) );
1110
- return preg_replace( '%^' . preg_quote( $upldir ) . '%', '', $file );
1111
- }
1112
-
1113
- function uploads_fullpath( $file ) {
1114
- $file = $this->normalize_path( $file );
1115
- $uplarr = wp_upload_dir();
1116
- $upldir = trailingslashit( $this->normalize_path( $uplarr[ 'basedir' ] ) );
1117
- return $upldir . $file;
1118
- }
1119
-
1120
- function serialize_postarrays() {
1121
- foreach ( $this->postarrays as $field )
1122
- if ( isset( $_POST[ $field ] ) && is_array( $_POST[ $field ] ) )
1123
- $_POST[ $field ] = implode( "%%", $_POST[ $field ] );
1124
- }
1125
-
1126
- function unserialize_postarrays() {
1127
- foreach ( $this->postarrays as $field )
1128
- if ( isset( $_POST[ $field ] ) && !is_array( $_POST[ $field ] ) )
1129
- $_POST[ $field ] = explode( "%%", $_POST[ $field ] );
1130
- }
1131
-
1132
- function set_writable( $file = NULL ) {
1133
-
1134
- $file = isset( $file ) ? $this->css->get_child_target( $file . '.php' ) :
1135
- apply_filters( 'chld_thm_cfg_target', $this->css->get_child_target(), $this->css );
1136
- if ( $this->fs ): // filesystem access
1137
- global $wp_filesystem;
1138
- if ( $file && $wp_filesystem->chmod( $this->fspath( $file ), 0666 ) ) return;
1139
- endif;
1140
- $this->errors[] = __( 'Could not set write permissions.', 'child-theme-configurator' );
1141
- add_action( 'admin_notices', array( $this, 'writable_notice' ) );
1142
- return FALSE;
1143
- }
1144
-
1145
- function clone_child_theme( $child, $clone ) {
1146
- if ( !$this->fs ) return FALSE; // return if no filesystem access
1147
- global $wp_filesystem;
1148
- // set child theme if not set for get_child_target to use new child theme as source
1149
- $this->css->set_prop( 'child', $child );
1150
-
1151
- $dir = untrailingslashit( $this->css->get_child_target( '' ) );
1152
- $themedir = trailingslashit( get_theme_root() );
1153
- $fsthemedir = $this->fspath( $themedir );
1154
- $files = $this->css->recurse_directory( $dir, NULL, TRUE );
1155
- $errors = array();
1156
- foreach ( $files as $file ):
1157
- $childfile = $this->theme_basename( $child, $this->normalize_path( $file ) );
1158
- $newfile = trailingslashit( $clone ) . $childfile;
1159
- $childpath = $fsthemedir . trailingslashit( $child ) . $childfile;
1160
- $newpath = $fsthemedir . $newfile;
1161
- $this->debug( 'Verifying child dir... ', __FUNCTION__ );
1162
- if ( $this->verify_child_dir( is_dir( $file ) ? $newfile : dirname( $newfile ) ) ):
1163
- if ( is_file( $file ) && !@$wp_filesystem->copy( $childpath, $newpath ) ):
1164
- $errors[] = 'could not copy ' . $newpath;
1165
- endif;
1166
- else:
1167
- $errors[] = 'invalid dir: ' . $newfile;
1168
- endif;
1169
- endforeach;
1170
- }
1171
-
1172
- function unset_writable() {
1173
- if ( !$this->fs ) return FALSE; // return if no filesystem access
1174
- global $wp_filesystem;
1175
- $dir = untrailingslashit( $this->css->get_child_target( '' ) );
1176
- $child = $this->theme_basename( '', $dir );
1177
- $newchild = untrailingslashit( $child ) . '-new';
1178
- $themedir = trailingslashit( get_theme_root() );
1179
- $fsthemedir = $this->fspath( $themedir );
1180
- // is child theme owned by user?
1181
- if ( fileowner( $dir ) == fileowner( $themedir ) ):
1182
- $copy = FALSE;
1183
- $wp_filesystem->chmod( $dir );
1184
- // recursive chmod ( as user )
1185
- // WP_Filesystem RECURSIVE CHMOD IS FLAWED! IT SETS ALL CHILDREN TO PERM OF OUTERMOST DIR
1186
- //if ( $wp_filesystem->chmod( $this->fspath( $dir ), FALSE, TRUE ) ):
1187
- //endif;
1188
- else:
1189
- $copy = TRUE;
1190
- endif;
1191
- // n -> copy entire folder ( as user )
1192
- $files = $this->css->recurse_directory( $dir, NULL, TRUE );
1193
- $errors = array();
1194
- foreach ( $files as $file ):
1195
- $childfile = $this->theme_basename( $child, $this->normalize_path( $file ) );
1196
- $newfile = trailingslashit( $newchild ) . $childfile;
1197
- $childpath = $fsthemedir . trailingslashit( $child ) . $childfile;
1198
- $newpath = $fsthemedir . $newfile;
1199
- if ( $copy ):
1200
- $this->debug( 'Verifying child dir... ', __FUNCTION__ );
1201
- if ( $this->verify_child_dir( is_dir( $file ) ? $newfile : dirname( $newfile ) ) ):
1202
- if ( is_file( $file ) && !$wp_filesystem->copy( $childpath, $newpath ) ):
1203
- $errors[] = 'could not copy ' . $newpath;
1204
- endif;
1205
- else:
1206
- $errors[] = 'invalid dir: ' . $newfile;
1207
- endif;
1208
- else:
1209
- $wp_filesystem->chmod( $this->fspath( $file ) );
1210
- endif;
1211
- endforeach;
1212
- if ( $copy ):
1213
- // verify copy ( as webserver )
1214
- $newfiles = $this->css->recurse_directory( trailingslashit( $themedir ) . $newchild, NULL, TRUE );
1215
- $deleteddirs = $deletedfiles = 0;
1216
- if ( count( $newfiles ) == count( $files ) ):
1217
- // rename old ( as webserver )
1218
- if ( !$wp_filesystem->exists( trailingslashit( $fsthemedir ) . $child . '-old' ) )
1219
- $wp_filesystem->move( trailingslashit( $fsthemedir ) . $child, trailingslashit( $fsthemedir ) . $child . '-old' );
1220
- // rename new ( as user )
1221
- if ( !$wp_filesystem->exists( trailingslashit( $fsthemedir ) . $child ) )
1222
- $wp_filesystem->move( trailingslashit( $fsthemedir ) . $newchild, trailingslashit( $fsthemedir ) . $child );
1223
- // remove old files ( as webserver )
1224
- $oldfiles = $this->css->recurse_directory( trailingslashit( $themedir ) . $child . '-old', NULL, TRUE );
1225
- array_unshift( $oldfiles, trailingslashit( $themedir ) . $child . '-old' );
1226
- foreach ( array_reverse( $oldfiles ) as $file ):
1227
- if ( $wp_filesystem->delete( $this->fspath( $file ) )
1228
- || ( is_dir( $file ) && @rmdir( $file ) )
1229
- || ( is_file( $file ) && @unlink( $file ) ) ):
1230
- $deletedfiles++;
1231
- endif;
1232
- endforeach;
1233
- if ( $deletedfiles != count( $oldfiles ) ):
1234
- $errors[] = 'deleted: ' . $deletedfiles . ' != ' . count( $oldfiles ) . ' files';
1235
- endif;
1236
- else:
1237
- $errors[] = 'newfiles != files';
1238
- endif;
1239
- endif;
1240
- if ( count( $errors ) ):
1241
- $this->errors[] = __( 'There were errors while resetting permissions.', 'child-theme-configurator' ) ;
1242
- add_action( 'admin_notices', array( $this, 'writable_notice' ) );
1243
- endif;
1244
- }
1245
-
1246
- function set_skip_form() {
1247
- $this->skip_form = TRUE;
1248
- }
1249
-
1250
- function handle_file_upload( $field, $childdir = NULL, $mimes = NULL ){
1251
- $uploadedfile = $_FILES[ $field ];
1252
- $upload_overrides = array(
1253
- 'test_form' => FALSE,
1254
- 'mimes' => ( is_array( $mimes ) ? $mimes : NULL )
1255
- );
1256
- if ( ! function_exists( 'wp_handle_upload' ) ) require_once( ABSPATH . 'wp-admin/includes/file.php' );
1257
- $movefile = wp_handle_upload( $uploadedfile, $upload_overrides );
1258
- if ( isset( $movefile[ 'error' ] ) ):
1259
- $this->errors[] = $movefile[ 'error' ];
1260
- return FALSE;
1261
- endif;
1262
- $_POST[ 'movefile' ] = $this->uploads_basename( $movefile[ 'file' ] );
1263
- }
1264
-
1265
- function move_file_upload( $subdir = 'images' ) {
1266
- if ( !$this->fs ) return FALSE; // return if no filesystem access
1267
- global $wp_filesystem;
1268
- $source_file = sanitize_text_field( $_POST[ 'movefile' ] );
1269
- $target_file = ( '' == $subdir ?
1270
- preg_replace( "%^.+(\.\w+)$%", "screenshot$1", basename( $source_file ) ) :
1271
- trailingslashit( $subdir ) . basename( $source_file ) );
1272
- $this->debug( 'Verifying child dir... ', __FUNCTION__ );
1273
- if ( FALSE !== $this->verify_child_dir( trailingslashit( $this->css->get_prop( 'child' ) ) . $subdir ) ):
1274
- $source_path = $this->fspath( $this->uploads_fullpath( $source_file ) );
1275
- if ( $target_path = $this->css->is_file_ok( $this->css->get_child_target( $target_file ), 'write' ) ):
1276
- $target_path = $this->fspath( $target_path );
1277
- if ( $wp_filesystem->exists( $source_path ) ):
1278
- if ( $wp_filesystem->move( $source_path, $target_path ) ) return TRUE;
1279
- endif;
1280
- endif;
1281
- endif;
1282
-
1283
- $this->errors[] = __( 'Could not upload file.', 'child-theme-configurator' );
1284
- }
1285
-
1286
- function export_zip() {
1287
- if ( ( $child = $this->css->get_prop( 'child' ) )
1288
- && ( $dir = $this->css->is_file_ok( dirname( $this->css->get_child_target() ), 'search' ) )
1289
- && ( $version = preg_replace( "%[^\w\.\-]%", '', $this->css->get_prop( 'version' ) ) ) ):
1290
- // use php system upload dir to store temp files so that we can use pclzip
1291
- $tmpdir = ini_get( 'upload_tmp_dir' ) ? ini_get( 'upload_tmp_dir' ) : sys_get_temp_dir();
1292
- $file = trailingslashit( $tmpdir ) . $child . '-' . $version . '.zip';
1293
- mbstring_binary_safe_encoding();
1294
-
1295
- require_once( ABSPATH . 'wp-admin/includes/class-pclzip.php' );
1296
-
1297
- $archive = new PclZip( $file );
1298
- if ( $archive->create( $dir, PCLZIP_OPT_REMOVE_PATH, dirname( $dir ) ) == 0 ) return FALSE;
1299
- reset_mbstring_encoding();
1300
- header( 'Content-Description: File Transfer' );
1301
- header( 'Content-Type: application/octet-stream' );
1302
- header( 'Content-Length: ' . filesize( $file ) );
1303
- header( 'Content-Disposition: attachment; filename=' . basename( $file ) );
1304
- header( 'Expires: 0' );
1305
- header( 'Cache-Control: must-revalidate' );
1306
- header( 'Pragma: public' );
1307
- readfile( $file );
1308
- unlink( $file );
1309
- die();
1310
- endif;
1311
- }
1312
-
1313
- /*
1314
- *
1315
- */
1316
- function verify_creds( $args = array() ) {
1317
- $this->fs_prompt = $this->fs = FALSE;
1318
- //fs prompt does not support arrays as post data - serialize arrays
1319
- $this->serialize_postarrays();
1320
- // generate callback url
1321
- $ctcpage = apply_filters( 'chld_thm_cfg_admin_page', CHLD_THM_CFG_MENU );
1322
- $url = is_multisite() ? network_admin_url( 'themes.php?page=' . $ctcpage ) :
1323
- admin_url( 'tools.php?page=' . $ctcpage );
1324
- $nonce_url = wp_nonce_url( $url, apply_filters( 'chld_thm_cfg_action', 'ctc_update' ), '_wpnonce' );
1325
- // buffer output so we can process prior to http header
1326
- ob_start();
1327
- if ( $creds = request_filesystem_credentials( $nonce_url, '', FALSE, FALSE, $args ) ):
1328
- // check filesystem permission if direct or ftp creds exist
1329
- if ( WP_Filesystem( $creds ) )
1330
- // login ok
1331
- $this->fs = TRUE;
1332
- else
1333
- // incorrect credentials, get form with error flag
1334
- $creds = request_filesystem_credentials( $nonce_url, '', TRUE, FALSE, $args );
1335
- else:
1336
- // no credentials, initialize unpriveledged filesystem object
1337
- WP_Filesystem();
1338
- endif;
1339
- // if form was generated, store it
1340
- $this->fs_prompt = ob_get_contents();
1341
- // now we can read/write if fs is TRUE otherwise fs_prompt will contain form
1342
- ob_end_clean();
1343
- //fs prompt does not support arrays as post data - unserialize arrays
1344
- $this->unserialize_postarrays();
1345
- }
1346
-
1347
- /*
1348
- * convert 'direct' filepath into wp_filesystem filepath
1349
- */
1350
- function fspath( $file ){
1351
- if ( ! $this->fs ) return FALSE; // return if no filesystem access
1352
- global $wp_filesystem;
1353
- if ( is_dir( $file ) ):
1354
- $dir = $file;
1355
- $base = '';
1356
- else:
1357
- $dir = dirname( $file );
1358
- $base = basename( $file );
1359
- endif;
1360
- $fsdir = $wp_filesystem->find_folder( $dir );
1361
- return trailingslashit( $fsdir ) . $base;
1362
- }
1363
-
1364
- function writable_notice() {
1365
- ?> <div class="update-nag" style="display:block">
1366
- <div class="ctc-section-toggle" id="ctc_perm_options"><?php _e( 'The child theme is in read-only mode and Child Theme Configurator cannot apply changes. Click to see options', 'child-theme-configurator' ); ?></div><div class="ctc-section-toggle-content" id="ctc_perm_options_content"><p><ol><?php
1367
- $ctcpage = apply_filters( 'chld_thm_cfg_admin_page', CHLD_THM_CFG_MENU );
1368
- if ( 'WIN' != substr( strtoupper( PHP_OS ), 0, 3 ) ):
1369
- _e( '<li>Temporarily set write permissions by clicking the button below. When you are finished editing, revert to read-only by clicking "Make read-only" under the "Files" tab.</li>', 'child-theme-configurator' );
1370
- ?><form action="?page=<?php echo $ctcpage; ?>" method="post">
1371
- <?php wp_nonce_field( apply_filters( 'chld_thm_cfg_action', 'ctc_update' ) ); ?>
1372
- <input name="ctc_set_writable" class="button" type="submit" value="<?php _e( 'Make files writable', 'child-theme-configurator' ); ?>"/></form><?php endif;
1373
- _e( '<li><a target="_blank" href="http://codex.wordpress.org/Editing_wp-config.php#WordPress_Upgrade_Constants" title="Editin wp-config.php">Add your FTP/SSH credentials to the WordPress config file</a>.</li>', 'child-theme-configurator' );
1374
- if ( isset( $_SERVER[ 'SERVER_SOFTWARE' ] ) && preg_match( '%iis%i',$_SERVER[ 'SERVER_SOFTWARE' ] ) )
1375
- _e( '<li><a target="_blank" href="http://technet.microsoft.com/en-us/library/cc771170" title="Setting Application Pool Identity">Assign WordPress to an application pool that has write permissions</a> (Windows IIS systems).</li>', 'child-theme-configurator' );
1376
- _e( '<li><a target="_blank" href="http://codex.wordpress.org/Changing_File_Permissions" title="Changing File Permissions">Set write permissions on the server manually</a> (not recommended).</li>', 'child-theme-configurator' );
1377
- if ( 'WIN' != substr( strtoupper( PHP_OS ), 0, 3 ) ):
1378
- _e( '<li>Run PHP under Apache with suEXEC (contact your web host).</li>', 'child-theme-configurator' );
1379
- endif; ?>
1380
- </ol></p></div>
1381
- </div>
1382
- <?php
1383
- }
1384
-
1385
- function owner_notice() {
1386
- $ctcpage = apply_filters( 'chld_thm_cfg_admin_page', CHLD_THM_CFG_MENU );
1387
- ?>
1388
- <div class="update-nag">
1389
- <p><?php _e( 'This Child Theme is not owned by your website account. It may have been created by a prior version of this plugin or by another program. Moving forward, it must be owned by your website account to make changes. Child Theme Configurator will attempt to correct this when you click the button below.', 'child-theme-configurator' ) ?></p>
1390
- <form action="?page=<?php echo $ctcpage; ?>" method="post">
1391
- <?php wp_nonce_field( apply_filters( 'chld_thm_cfg_action', 'ctc_update' ) ); ?>
1392
- <input name="ctc_reset_permission" class="button" type="submit" value="<?php _e( 'Correct Child Theme Permissions', 'child-theme-configurator' ); ?>"/></form> </div>
1393
- <?php
1394
- }
1395
-
1396
- function enqueue_notice() {
1397
- ?>
1398
- <div class="update-nag">
1399
- <p><?php _e( 'Child Theme Configurator needs to update its interal data. Please set your preferences below and click "Generate Child Theme Files" to update your configuration.', 'child-theme-configurator' ) ?></p>
1400
- </div>
1401
- <?php
1402
- }
1403
-
1404
- function max_styles_notice( $msg ) {
1405
- return $msg . ' ' . sprintf( __( '<strong>However, some styles could not be parsed due to memory limits.</strong> Try deselecting "Additional Stylesheets" below and click "Generate/Rebuild Child Theme Files". %sWhy am I seeing this?%s', 'child-theme-configurator' ),
1406
- '<a target="_blank" href="' . LILAEAMEDIA_URL . '/child-theme-configurator#php_memory">',
1407
- '</a>' );
1408
- return $msg;
1409
- }
1410
-
1411
- function config_notice() {
1412
- ?>
1413
- <div class="update-nag">
1414
- <p><?php _e( 'Child Theme Configurator did not detect any configuration data because a previously configured Child Theme has been removed. Please set your preferences below and click "Generate Child Theme Files".', 'child-theme-configurator' ) ?></p>
1415
- </div>
1416
- <?php
1417
- }
1418
-
1419
- // back compatibility function for legacy plugins extension
1420
- function write_addl_files( $obj ) {
1421
- global $chld_thm_cfg_plugins;
1422
- if ( !is_object( $chld_thm_cfg_plugins ) || !$this->fs ) return FALSE;
1423
- $configtype = $this->css->get_prop( 'configtype' );
1424
- //echo $configtype . LF;
1425
- if ( 'theme' == $configtype || !( $def = $chld_thm_cfg_plugins->defs->get_def( $configtype ) ) ) return FALSE;
1426
- $child = trailingslashit( $this->css->get_prop( 'child' ) );
1427
- if ( isset( $def[ 'addl' ] ) && is_array( $def[ 'addl' ] ) && count( $def[ 'addl' ] ) ):
1428
- foreach ( $def[ 'addl' ] as $path => $type ):
1429
-
1430
- // sanitize the crap out of the target data -- it will be used to create paths
1431
- $path = $this->normalize_path( preg_replace( "%[^\w\\//\-]%", '', sanitize_text_field( $child . $path ) ) );
1432
- $this->debug( 'Verifying child dir... ', __FUNCTION__ );
1433
- if ( ( 'dir' == $type && FALSE === $this->verify_child_dir( $path ) )
1434
- || ( 'dir' != $type && FALSE === $this->write_child_file( $path, '' ) ) ):
1435
- //$this->errors[] = __( 'Your theme directories are not writable.', 'chld_thm_cfg_plugins' );
1436
- endif;
1437
- endforeach;
1438
- endif;
1439
- // write main def file
1440
- if ( isset( $def[ 'target' ] ) ):
1441
- $path = $this->normalize_path( preg_replace( "%[^\w\\//\-\.]%", '', sanitize_text_field( $def[ 'target' ] ) ) ); //$child .
1442
- if ( FALSE === $this->write_child_file( $path, '' ) ):
1443
- //echo "invalid path: " . $path . ' ' . ' was: ' . $def[ 'target' ] . LF;
1444
- //$this->errors[] = __( 'Your stylesheet is not writable.', 'chld_thm_cfg_plugins' );
1445
- return FALSE;
1446
- endif;
1447
- endif;
1448
- }
1449
-
1450
- // backwards compatability < WP 3.9
1451
- function normalize_path( $path ) {
1452
- $path = str_replace( '\\', '/', $path );
1453
- $path = preg_replace( '|/+|','/', $path );
1454
- return $path;
1455
- }
1456
-
1457
- // case insensitive theme search
1458
- function check_theme_exists( $theme ) {
1459
- $search_array = array_map( 'strtolower', array_keys( wp_get_themes() ) );
1460
- return in_array( strtolower( $theme ), $search_array );
1461
- }
1462
-
1463
- // helper functions to support legacy plugin extension
1464
- function is_legacy() {
1465
- return defined('CHLD_THM_CFG_PLUGINS_VERSION')
1466
- && version_compare( CHLD_THM_CFG_PLUGINS_VERSION, '2.0.0', '<' );
1467
- }
1468
-
1469
- /* not using plugin mode */
1470
- function is_theme( $configtype = '' ) {
1471
- // if filter returns a value, we are using plugin mode
1472
- // otherwise if configtype has a value and it is not a theme then we are in legacy plugin mode
1473
- $pluginmode = apply_filters( 'chld_thm_cfg_action', NULL );
1474
- if ( $pluginmode || ( !empty( $configtype ) && 'theme' != $configtype ) ):
1475
- return FALSE;
1476
- endif;
1477
- if ( $this->is_legacy()
1478
- && is_object( $this->css )
1479
- && ( $configtype = $this->css->get_prop( 'configtype' ) )
1480
- && !empty( $configtype ) && 'theme' != $configtype ):
1481
- return FALSE;
1482
- endif;
1483
- return TRUE;
1484
- }
1485
-
1486
- /* returns parent theme either from existing config or passed as post var */
1487
- function get_current_parent() {
1488
- if ( isset( $_GET[ 'ctc_parent' ] ) && ( $parent = sanitize_text_field( $_GET[ 'ctc_parent' ] ) ) )
1489
- return $parent;
1490
- elseif ( $parent = $this->css->get_prop( 'parnt' ) )
1491
- return $parent;
1492
- else return get_template();
1493
- }
1494
-
1495
- /* returns child theme either from existing config or passed as post var */
1496
- function get_current_child() {
1497
- if ( isset( $_GET[ 'ctc_child' ] ) && ( $child = sanitize_text_field( $_GET[ 'ctc_child' ] ) ) )
1498
- return $child;
1499
- elseif ( $child = $this->css->get_prop( 'child' ) )
1500
- return $child;
1501
- else return get_stylesheet();
1502
- }
1503
- /* debug backtrace with extraneous steps (missing class, function or line) removed */
1504
- function backtrace_summary() {
1505
- $bt = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS );
1506
- $thisstep = array_shift( $bt );
1507
- foreach ( $bt as $ndx => $step )
1508
- if ( isset( $step[ 'class' ] ) && isset( $step[ 'function' ] ) && isset( $step[ 'line' ] ) )
1509
- echo $ndx . ': ' . $step[ 'class' ] . ' ' . $step[ 'function' ] . ' ' . $step[ 'line' ] . LF;
1510
- }
1511
-
1512
- function debug( $msg = NULL, $fn = NULL) {
1513
- $this->debug .= ( isset( $fn ) ? $fn . ': ' : '' ) . ( isset( $msg ) ? $msg . LF : '' );
1514
- }
1515
-
1516
- function set_benchmark( $step, $key, $label ) {
1517
- $this->memory[ $key ][ $label ][ $step ][ 'memory' ] = memory_get_usage();
1518
- $this->memory[ $key ][ $label ][ $step ][ 'peak' ] = memory_get_peak_usage();
1519
-
1520
- $this->memory[ $key ][ $label ][ $step ][ 'selectors' ] = isset( $this->css ) ? $this->css->qskey : 0;
1521
- }
1522
-
1523
- function calc_memory_usage() {
1524
- //$this->debug( print_r( $this->memory, TRUE ), __FUNCTION__ );
1525
-
1526
- $results = array();
1527
- foreach ( $this->memory as $key => $labels ):
1528
- if ( !is_array( $labels ) ) continue;
1529
- foreach ( $labels as $label => $steps ):
1530
- //if ( isset( $steps[ 'before' ] ) && isset( $steps[ 'after ' ] ) ):
1531
- $results[] = $key . '|' . $label . '|'
1532
- . ( $steps[ 'after' ][ 'memory' ] - $steps[ 'before' ][ 'memory' ] ) . '|'
1533
- . ( $steps[ 'after' ][ 'peak' ] - $steps[ 'before' ][ 'peak' ] ) . '|'
1534
- . ( $steps[ 'after' ][ 'peak' ] - $steps[ 'before' ][ 'memory' ] ) . '|'
1535
- . $steps[ 'after' ][ 'selectors' ] . '|'
1536
- . ( $steps[ 'after' ][ 'selectors' ] - $steps[ 'before' ][ 'selectors' ] );
1537
- //endif;
1538
- endforeach;
1539
- endforeach;
1540
- $this->debug( "\n" . implode( "\n", $results ), __FUNCTION__ );
1541
- }
1542
-
1543
- function get_free_memory() {
1544
- $limit = (int) ini_get('memory_limit') * 1024 * 1024;
1545
- $used = memory_get_usage();
1546
- return $limit - $used;
1547
- }
1548
-
1549
- function print_debug( $noecho = FALSE ) {
1550
- $debug = '<textarea style="width:100%;height:200px">' . LF . $this->debug . LF . '</textarea>' . LF;
1551
- if ( $noecho ) return $debug;
1552
- echo $debug;
1553
- }
1554
-
1555
- function parse_parent_stylesheet() {
1556
- $this->css->parse_css_file( 'parnt' );
1557
- }
1558
-
1559
- function parse_child_stylesheet() {
1560
- // get revert/backup
1561
- $revert = isset( $_POST[ 'ctc_revert' ] ) ? sanitize_text_field( $_POST[ 'ctc_revert' ] ) : '';
1562
- // parse child stylesheet, backup or skip ( to reset )
1563
- $this->css->parse_css_file( 'child', $revert );
1564
- }
1565
-
1566
- function parse_additional_stylesheets() {
1567
- // parse additional stylesheets
1568
- if ( isset( $_POST[ 'ctc_additional_css' ] ) && is_array( $_POST[ 'ctc_additional_css' ] ) ):
1569
- $this->css->addl_css = array();
1570
- foreach ( $_POST[ 'ctc_additional_css' ] as $file ):
1571
- $file = sanitize_text_field( $file );
1572
- $this->css->parse_css_file( 'parnt', $file );
1573
- $this->css->addl_css[] = $file;
1574
- endforeach;
1575
- endif;
1576
- }
1577
-
1578
- function copy_theme_mods( $from, $to ) {
1579
-
1580
- // we can copy settings from parent to child even if neither is currently active
1581
- // so we need cases for active parent, active child or neither
1582
-
1583
- // get active theme
1584
- $active_theme = get_stylesheet();
1585
- $this->debug( 'from: ' . $from . ' to: ' . $to . ' active: ' . $active_theme, __FUNCTION__ );
1586
- // create temp array from parent settings
1587
- $child_mods = get_option( 'theme_mods_' . $from );
1588
- if ( $active_theme == $from ):
1589
- $this->debug( 'from is active, using active widgets', __FUNCTION__ );
1590
- // if parent theme is active, get widgets from active sidebars_widgets array
1591
- $child_widgets = retrieve_widgets();
1592
- else:
1593
- $this->debug( 'from not active, using theme mods widgets', __FUNCTION__ );
1594
- // otherwise get widgets from parent theme mods
1595
- $child_widgets = $child_mods[ 'sidebars_widgets' ][ 'data' ];
1596
- endif;
1597
- if ( $active_theme == $to ):
1598
- $this->debug( 'to active, setting active widgets', __FUNCTION__ );
1599
- // if child theme is active, remove widgets from temp array
1600
- unset( $child_mods[ 'sidebars_widgets' ] );
1601
- // copy widgets to active sidebars_widgets array
1602
- wp_set_sidebars_widgets( $child_widgets );
1603
- else:
1604
- $this->debug( 'child not active, saving widgets in theme mods', __FUNCTION__ );
1605
- // otherwise copy widgets to temp array with time stamp
1606
- $child_mods[ 'sidebars_widgets' ][ 'data' ] = $child_widgets;
1607
- $child_mods[ 'sidebars_widgets' ][ 'time' ] = time();
1608
- endif;
1609
- $this->debug( 'saving child theme mods:' . LF . print_r( $child_mods, TRUE ), __FUNCTION__ );
1610
- // copy temp array to child mods
1611
- update_option( 'theme_mods_' . $to, $child_mods );
1612
- }
1613
-
1614
- function network_enable() {
1615
- if ( $child = $this->css->get_prop( 'child' ) ):
1616
- $allowed_themes = get_site_option( 'allowedthemes' );
1617
- $allowed_themes[ $child ] = true;
1618
- update_site_option( 'allowedthemes', $allowed_themes );
1619
- endif;
1620
- }
1621
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/class-ctc-preview.php DELETED
@@ -1,72 +0,0 @@
1
- <?php
2
- // Exit if accessed directly
3
- if ( !defined( 'ABSPATH' ) ) exit;
4
-
5
- class ChildThemeConfiguratorPreview {
6
- /**
7
- * Replaces core function to start preview theme output buffer.
8
- */
9
- static function preview_theme() {
10
- // are we previewing?
11
- if ( ! isset( $_GET[ 'template' ] ) || !wp_verify_nonce( $_GET['preview_ctc'] ) )
12
- return;
13
- // can user preview?
14
- if ( !current_user_can( 'switch_themes' ) )
15
- return;
16
- // hide admin bar in preview
17
- if ( isset( $_GET[ 'preview_iframe' ] ) )
18
- show_admin_bar( false );
19
- // sanitize template param
20
- $_GET[ 'template' ] = preg_replace( '|[^a-z0-9_./-]|i', '', $_GET[ 'template' ] );
21
- // check for manipulations
22
- if ( validate_file( $_GET[ 'template' ] ) )
23
- return;
24
- // replace future get_template calls with preview template
25
- add_filter( 'template', 'ChildThemeConfiguratorPreview::preview_theme_template_filter' );
26
-
27
- if ( isset( $_GET[ 'stylesheet' ] ) ):
28
- // sanitize stylesheet param
29
- $_GET['stylesheet'] = preg_replace( '|[^a-z0-9_./-]|i', '', $_GET['stylesheet'] );
30
- // check for manipulations
31
- if ( validate_file( $_GET['stylesheet'] ) )
32
- return;
33
- // replace future get_stylesheet calls with preview stylesheet
34
- add_filter( 'stylesheet', 'ChildThemeConfiguratorPreview::preview_theme_stylesheet_filter' );
35
- endif;
36
- // swap out theme mods with preview theme mods
37
- add_filter( 'pre_option_theme_mods_' . get_option( 'stylesheet' ),
38
- 'ChildThemeConfiguratorPreview::preview_mods' );
39
- }
40
-
41
- /**
42
- * Retrieves child theme mods for preview
43
- */
44
- static function preview_mods() {
45
- if ( ! isset( $_GET[ 'stylesheet' ] ) || get_option( 'stylesheet' ) == $_GET[ 'stylesheet' ] ) return false;
46
- return get_option( 'theme_mods_' . preg_replace('|[^a-z0-9_./-]|i', '', $_GET['stylesheet']) );
47
- }
48
-
49
- /**
50
- * Function to modify the current template when previewing a theme
51
- *
52
- * @return string
53
- */
54
- static function preview_theme_template_filter() {
55
- return ( isset($_GET['template']) && current_user_can( 'switch_themes' ) ) ? $_GET['template'] : '';
56
- }
57
-
58
- /**
59
- * Function to modify the current stylesheet when previewing a theme
60
- *
61
- * @return string
62
- */
63
- static function preview_theme_stylesheet_filter() {
64
- return ( isset( $_GET['stylesheet'] ) && current_user_can( 'switch_themes' ) ) ? $_GET['stylesheet'] : '';
65
- }
66
- }
67
-
68
- // replace core preview function with CTCP function for quick preview
69
- remove_action( 'setup_theme', 'preview_theme' );
70
- add_action( 'setup_theme', 'ChildThemeConfiguratorPreview::preview_theme' );
71
-
72
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/class-ctc-ui.php DELETED
@@ -1,243 +0,0 @@
1
- <?php
2
- // Exit if accessed directly
3
- if ( !defined( 'ABSPATH' ) ) exit;
4
- /*
5
- Class: Child_Theme_Configurator_UI
6
- Plugin URI: http://www.childthemeconfigurator.com/
7
- Description: Handles the plugin User Interface
8
- Version: 1.7.9
9
- Author: Lilaea Media
10
- Author URI: http://www.lilaeamedia.com/
11
- Text Domain: chld_thm_cfg
12
- Domain Path: /lang
13
- License: GPLv2
14
- Copyright (C) 2014-2015 Lilaea Media
15
- */
16
- class ChildThemeConfiguratorUI {
17
-
18
- var $warnings = array();
19
-
20
- // helper function to globalize ctc object
21
- function ctc() {
22
- return ChildThemeConfigurator::ctc();
23
- }
24
-
25
- function render() {
26
- $css = $this->ctc()->css;
27
- $themes = $this->ctc()->themes;
28
- $child = $css->get_prop( 'child' );
29
- $hidechild = ( count( $themes[ 'child' ] ) ? '' : 'style="display:none"' );
30
- $enqueueset = ( isset( $css->enqueue ) && $child );
31
- $this->ctc()->debug( 'Enqueue set: ' . ( $enqueueset ? 'TRUE' : 'FALSE' ), __FUNCTION__ );
32
- if ( empty( $css->nowarn ) ) $this->parent_theme_check();
33
- $imports = $css->get_prop( 'imports' );
34
- $id = 0;
35
- $this->ctc()->fs_method = get_filesystem_method();
36
- add_thickbox();
37
- add_filter( 'chld_thm_cfg_files_tab_filter', array( $this, 'render_files_tab_options' ) );
38
- add_action( 'chld_thm_cfg_tabs', array( $this, 'render_addl_tabs' ), 10, 4 );
39
- add_action( 'chld_thm_cfg_panels', array( $this, 'render_addl_panels' ), 10, 4 );
40
- add_action( 'chld_thm_cfg_related_links', array( $this, 'lilaea_plug' ) );
41
- if ( $this->ctc()->is_debug ):
42
- $this->ctc()->debug( 'adding new debug action...', __FUNCTION__ );
43
- add_action( 'chld_thm_cfg_print_debug', array( $this->ctc(), 'print_debug' ) );
44
- endif;
45
- include ( CHLD_THM_CFG_DIR . '/includes/forms/main.php' );
46
- }
47
-
48
- function parent_theme_check() {
49
- // check header for hard-coded
50
- $bad_practice_descr = array(
51
- // Stylesheets should be enqueued using the <code>wp_enqueue_scripts</code> action.
52
- 'links' => __( 'A stylesheet link tag is hard-coded into the header template.', 'child-theme-configurator' ),
53
- 'enqueue' => __( '<code>wp_enqueue_style()</code> called from the header template.', 'child-theme-configurator' ),
54
- // <code>wp_head()</code> should be located just before the closing <code>&lt;/head&gt;</code> tag.
55
- 'wphead' => __( 'Code exists between the <code>wp_head()</code> function and the closing <code>&lt;/head&gt;</code> tag.', 'child-theme-configurator'),
56
- );
57
- $parentfile = trailingslashit( get_theme_root() ) . trailingslashit( $this->ctc()->get_current_parent() ) . 'header.php';
58
- $childfile = trailingslashit( get_theme_root() ) . trailingslashit( $this->ctc()->css->get_prop( 'child' ) ) . 'header.php';
59
- if ( $file = ( file_exists( $childfile ) ? $childfile : ( file_exists( $parentfile ) ? $parentfile : FALSE ) ) ):
60
- $contents = file_get_contents( $file );
61
- $contents = preg_replace( "/\/\/.*?(\?>|\n)|\/\*.*?\*\/|<\!\-\-.*?\-\->/s", '', $contents );
62
- // check for linked stylesheets
63
- if ( preg_match( '/rel=[\'"]stylesheet[\'"]/is', $contents ) ) $this->warnings[] = $bad_practice_descr[ 'links' ];
64
- if ( preg_match( '/wp_enqueue_style/is', $contents ) ) $this->warnings[] = $bad_practice_descr[ 'enqueue' ];
65
- // check for code after wp_head
66
- if ( preg_match( '/wp_head(.*?)<\/head>/is', $contents, $matches ) ):
67
- $codeafter = preg_replace( "/[\(\)\?>;\s]/s", '', $matches[ 1 ] );
68
- if ( !empty( $codeafter ) ) $this->warnings[] = $bad_practice_descr[ 'wphead' ];
69
- endif;
70
- endif;
71
- }
72
-
73
- function render_theme_menu( $template = 'child', $selected = NULL ) {
74
-
75
- ?>
76
- <select class="ctc-select" id="ctc_theme_<?php echo $template; ?>" name="ctc_theme_<?php echo $template; ?>" style="visibility:hidden" <?php echo $this->ctc()->is_theme() ? '' : ' disabled '; ?> ><?php
77
- foreach ( $this->ctc()->themes[ $template ] as $slug => $theme )
78
- echo '<option value="' . $slug . '"' . ( $slug == $selected ? ' selected' : '' ) . '>'
79
- . esc_attr( $theme[ 'Name' ] ) . '</option>' . LF;
80
- ?>
81
- </select>
82
- <div style="display:none">
83
- <?php
84
- foreach ( $this->ctc()->themes[ $template ] as $slug => $theme )
85
- include ( CHLD_THM_CFG_DIR . '/includes/forms/themepreview.php' ); ?>
86
- </div>
87
- <?php
88
- }
89
-
90
- function render_file_form( $template = 'parnt' ) {
91
- global $wp_filesystem;
92
- if ( $theme = $this->ctc()->css->get_prop( $template ) ):
93
- $themeroot = trailingslashit( get_theme_root() ) . trailingslashit( $theme );
94
- $files = $this->ctc()->get_files( $theme );
95
- $counter = 0;
96
- sort( $files );
97
- ob_start();
98
- foreach ( $files as $file ):
99
- $templatefile = preg_replace( '%\.php$%', '', $file );
100
- $excludes = implode( "|", ( array ) apply_filters( 'chld_thm_cfg_template_excludes', $this->ctc()->excludes ) );
101
- if ( 'parnt' == $template && ( preg_match( '%^(' . $excludes . ' )\w*\/%',$templatefile )
102
- || 'functions' == basename( $templatefile ) ) ) continue;
103
- include ( CHLD_THM_CFG_DIR . '/includes/forms/file.php' );
104
- endforeach;
105
- if ( 'child' == $template && ( $backups = $this->ctc()->get_files( $theme, 'backup,pluginbackup' ) ) ):
106
- foreach ( $backups as $backup => $label ):
107
- $templatefile = preg_replace( '%\.css$%', '', $backup );
108
- include ( CHLD_THM_CFG_DIR . '/includes/forms/backup.php' );
109
- endforeach;
110
- endif;
111
- $inputs = ob_get_contents();
112
- ob_end_clean();
113
- if ( $counter ):
114
- include ( CHLD_THM_CFG_DIR . '/includes/forms/fileform.php' );
115
- endif;
116
- endif;
117
- }
118
-
119
- function render_image_form() {
120
-
121
- if ( $theme = $this->ctc()->css->get_prop( 'child' ) ):
122
- $themeuri = trailingslashit( get_theme_root_uri() ) . trailingslashit( $theme );
123
- $files = $this->ctc()->get_files( $theme, 'img' );
124
-
125
- $counter = 0;
126
- sort( $files );
127
- ob_start();
128
- foreach ( $files as $file ):
129
- $templatefile = preg_replace( '/^images\//', '', $file );
130
- include( CHLD_THM_CFG_DIR . '/includes/forms/image.php' );
131
- endforeach;
132
- $inputs = ob_get_contents();
133
- ob_end_clean();
134
- if ( $counter ) include( CHLD_THM_CFG_DIR . '/includes/forms/images.php' );
135
- endif;
136
- }
137
-
138
- function get_theme_screenshot() {
139
-
140
- foreach ( array_keys( $this->ctc()->imgmimes ) as $extreg ):
141
- foreach ( explode( '|', $extreg ) as $ext ):
142
- if ( $screenshot = $this->ctc()->css->is_file_ok( $this->ctc()->css->get_child_target( 'screenshot.' . $ext ) ) ):
143
- $screenshot = trailingslashit( get_theme_root_uri() ) . $this->ctc()->theme_basename( '', $screenshot );
144
- return $screenshot . '?' . time();
145
- endif;
146
- endforeach;
147
- endforeach;
148
- return FALSE;
149
- }
150
-
151
- function settings_errors() {
152
-
153
- if ( count( $this->ctc()->errors ) ):
154
- echo '<div class="error"><ul>' . LF;
155
- foreach ( $this->ctc()->errors as $err ):
156
- echo '<li>' . $err . '</li>' . LF;
157
- endforeach;
158
- echo '</ul></div>' . LF;
159
- elseif ( isset( $_GET[ 'updated' ] ) ):
160
- echo '<div class="updated">' . LF;
161
- if ( 8 == $_GET[ 'updated' ] ):
162
- echo '<p>' . __( 'Child Theme files modified successfully.', 'child-theme-configurator' ) . '</p>' . LF;
163
- else:
164
- $child_theme = wp_get_theme( $this->ctc()->css->get_prop( 'child' ) );
165
- echo '<p>' . apply_filters( 'chld_thm_cfg_update_msg', sprintf( __( 'Child Theme <strong>%s</strong> has been generated successfully.
166
- ', 'child-theme-configurator' ), $child_theme->Name ), $this->ctc() ) . LF;
167
- if ( $this->ctc()->is_theme() ):
168
- echo '<strong>' . __( 'IMPORTANT:', 'child-theme-configurator' ) . LF;
169
- if ( is_multisite() && !$child_theme->is_allowed() ):
170
- echo 'You must <a href="' . network_admin_url( '/themes.php' ) . '" title="' . __( 'Go to Themes', 'child-theme-configurator' ) . '" class="ctc-live-preview">' . __( 'Network enable', 'child-theme-configurator' ) . '</a> ' . __( 'your child theme.', 'child-theme-configurator' );
171
- else:
172
- echo '<a href="' . admin_url( '/customize.php?theme=' . $this->ctc()->css->get_prop( 'child' ) ) . '" title="' . __( 'Live Preview', 'child-theme-configurator' ) . '" class="ctc-live-preview">' . __( 'Test your child theme', 'child-theme-configurator' ) . '</a> ' . __( 'before activating.', 'child-theme-configurator' );
173
- endif;
174
- echo '</strong></p>' . LF;
175
- endif;
176
- endif;
177
- echo '</div>' . LF;
178
- endif;
179
- }
180
-
181
- function render_help_content() {
182
- global $wp_version;
183
- if ( version_compare( $wp_version, '3.3' ) >= 0 ) {
184
-
185
- $screen = get_current_screen();
186
-
187
- // load help content via output buffer so we can use plain html for updates
188
- // then use regex to parse for help tab parameter values
189
-
190
- $regex_sidebar = '/' . preg_quote( '<!-- BEGIN sidebar -->' ) . '(.*?)' . preg_quote( '<!-- END sidebar -->' ) . '/s';
191
- $regex_tab = '/' . preg_quote( '<!-- BEGIN tab -->' ) . '\s*<h\d id="(.*?)">(.*?)<\/h\d>(.*?)' . preg_quote( '<!-- END tab -->' ) . '/s';
192
- $locale = get_locale();
193
- $dir = CHLD_THM_CFG_DIR . '/includes/help/';
194
- $file = $dir . $locale . '.php';
195
- if ( !is_readable( $file ) ) $file = $dir . 'en_US.php';
196
- ob_start();
197
- include( $file );
198
- $help_raw = ob_get_contents();
199
- ob_end_clean();
200
- // parse raw html for tokens
201
- preg_match( $regex_sidebar, $help_raw, $sidebar );
202
- preg_match_all( $regex_tab, $help_raw, $tabs );
203
-
204
- // Add help tabs
205
- if ( isset( $tabs[ 1 ] ) ):
206
- //$priority = 0;
207
- while( count( $tabs[ 1 ] ) ):
208
- $id = array_shift( $tabs[ 1 ] );
209
- $title = array_shift( $tabs[ 2 ] );
210
- $content = array_shift( $tabs[ 3 ] );
211
- $screen->add_help_tab( array(
212
- 'id' => $id,
213
- 'title' => $title,
214
- 'content' => $content,
215
- //'priority' => ++$priority,
216
- ) );
217
- endwhile;
218
- endif;
219
- if ( isset( $sidebar[ 1 ] ) )
220
- $screen->set_help_sidebar( $sidebar[ 1 ] );
221
-
222
- }
223
- }
224
-
225
- function render_addl_tabs( $ctc, $active_tab = NULL, $hidechild = '' ) {
226
- include ( CHLD_THM_CFG_DIR . '/includes/forms/addl_tabs.php' );
227
- }
228
-
229
- function render_addl_panels( $ctc, $active_tab = NULL, $hidechild = '' ) {
230
- include ( CHLD_THM_CFG_DIR . '/includes/forms/addl_panels.php' );
231
- }
232
-
233
- function lilaea_plug() {
234
- include ( CHLD_THM_CFG_DIR . '/includes/forms/related.php' );
235
- }
236
-
237
- function render_files_tab_options( $output ) {
238
- $regex = '%<div class="ctc\-input\-cell clear">.*?(</form>).*%s';
239
- $output = preg_replace( $regex, "$1", $output );
240
- return $output;
241
- }
242
- }
243
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/classes/Admin.php ADDED
@@ -0,0 +1,2146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Exit if accessed directly
3
+ if ( !defined( 'ABSPATH' ) ) exit;
4
+
5
+ /*
6
+ Class: ChildThemeConfiguratorAdmin
7
+ Plugin URI: http://www.childthemeconfigurator.com/
8
+ Description: Main Controller Class
9
+ Version: 2.2.0
10
+ Author: Lilaea Media
11
+ Author URI: http://www.lilaeamedia.com/
12
+ Text Domain: child-theme-configurator
13
+ Domain Path: /lang
14
+ License: GPLv2
15
+ Copyright (C) 2014-2016 Lilaea Media
16
+ */
17
+ class ChildThemeConfiguratorAdmin {
18
+
19
+ // state
20
+ var $genesis;
21
+ //var $reorder;
22
+ var $processdone;
23
+ var $childtype;
24
+ var $template;
25
+ var $is_ajax;
26
+ var $is_get;
27
+ var $is_post;
28
+ var $skip_form;
29
+ var $fs;
30
+ var $encoding;
31
+
32
+ var $fs_prompt;
33
+ var $fs_method;
34
+ var $uploadsubdir;
35
+ var $menuName; // backward compatibility with plugin extension
36
+ var $cache_updates = TRUE;
37
+ var $debug;
38
+ var $is_debug;
39
+ var $is_new;
40
+ // memory checks
41
+ var $max_sel;
42
+ var $sel_limit;
43
+ var $mem_limit;
44
+ // state arrays
45
+ var $themes = array();
46
+ var $errors = array();
47
+ var $files = array();
48
+ var $updates = array();
49
+ // objects
50
+ var $css;
51
+ var $ui;
52
+ // config arrays
53
+ var $postarrays = array(
54
+ 'ctc_img',
55
+ 'ctc_file_parnt',
56
+ 'ctc_file_child',
57
+ 'ctc_additional_css',
58
+ );
59
+ var $configfields = array(
60
+ 'theme_parnt',
61
+ 'child_type',
62
+ 'theme_child',
63
+ 'child_template',
64
+ 'child_name',
65
+ 'child_themeuri',
66
+ 'child_author',
67
+ 'child_authoruri',
68
+ 'child_descr',
69
+ 'child_tags',
70
+ 'child_version',
71
+ 'repairheader',
72
+ 'ignoreparnt',
73
+ 'handling',
74
+ 'enqueue',
75
+ 'configtype', // backward compatability - no longer used
76
+ );
77
+ var $actionfields = array(
78
+ 'load_styles',
79
+ 'parnt_templates_submit',
80
+ 'child_templates_submit',
81
+ 'image_submit',
82
+ 'theme_image_submit',
83
+ 'theme_screenshot_submit',
84
+ 'export_child_zip',
85
+ 'export_theme',
86
+ 'reset_permission',
87
+ 'templates_writable_submit',
88
+ 'set_writable',
89
+ 'upgrade',
90
+ );
91
+ var $imgmimes = array(
92
+ 'jpg|jpeg|jpe' => 'image/jpeg',
93
+ 'gif' => 'image/gif',
94
+ 'png' => 'image/png',
95
+ );
96
+
97
+ function __construct() {
98
+ $this->processdone = FALSE;
99
+ $this->genesis = FALSE;
100
+ //$this->reorder = FALSE;
101
+ $this->is_new = FALSE;
102
+ $this->encoding = WP_Http_Encoding::is_available();
103
+ $this->menuName = CHLD_THM_CFG_MENU; // backward compatability for plugins extension
104
+ $this->is_post = ( 'POST' == $_SERVER[ 'REQUEST_METHOD' ] );
105
+ $this->is_get = ( 'GET' == $_SERVER[ 'REQUEST_METHOD' ] );
106
+ $this->is_debug = get_option( CHLD_THM_CFG_OPTIONS . '_debug' );
107
+ $this->debug = '';
108
+ $this->errors = array();
109
+ }
110
+
111
+ /**
112
+ * initialize configurator
113
+ */
114
+ function ctc_page_init () {
115
+ // get all available themes
116
+ $this->get_themes();
117
+ $this->childtype = count( $this->themes[ 'child' ] ) ? 'existing' : 'new';
118
+
119
+ // load config data and validate
120
+ $this->load_config();
121
+ // perform any checks prior to processing config data
122
+ do_action( 'chld_thm_cfg_preprocess' );
123
+ // process any additional forms
124
+ do_action( 'chld_thm_cfg_forms' ); // hook for custom forms
125
+ // process main post data
126
+ $this->process_post();
127
+ // initialize UI
128
+ $this->ui = new ChildThemeConfiguratorUI();
129
+ // initialize help
130
+ $this->ui->render_help_content();
131
+ }
132
+
133
+ function render() {
134
+ $this->ui->render();
135
+ }
136
+
137
+ /* helper function to retreive css object properties */
138
+ function get( $property, $params = NULL ) {
139
+ return $this->css->get_prop( $property, $params );
140
+ }
141
+
142
+ function get_themes() {
143
+ // create cache of theme info
144
+ $this->themes = array( 'child' => array(), 'parnt' => array() );
145
+ foreach ( wp_get_themes() as $theme ):
146
+ // organize into parent and child themes
147
+ $group = $theme->parent() ? 'child' : 'parnt';
148
+ // get the theme slug
149
+ $slug = $theme->get_stylesheet();
150
+ // get the theme slug
151
+ $version = $theme->get( 'Version' );
152
+ // strip auto-generated timestamp from CTC child theme version
153
+ if ( 'child' == $group ) $version = preg_replace("/\.\d{6}\d+$/", '', $version );
154
+ // add theme to themes array
155
+ $this->themes[ $group ][ $slug ] = array(
156
+ 'Template' => $theme->get( 'Template' ),
157
+ 'Name' => $theme->get( 'Name' ),
158
+ 'ThemeURI' => $theme->get( 'ThemeURI' ),
159
+ 'Author' => $theme->get( 'Author' ),
160
+ 'AuthorURI' => $theme->get( 'AuthorURI' ),
161
+ 'Descr' => $theme->get( 'Description' ),
162
+ 'Tags' => $theme->get( 'Tags' ),
163
+ 'Version' => $version,
164
+ 'screenshot' => $theme->get_screenshot(),
165
+ 'allowed' => $theme->is_allowed(),
166
+ );
167
+ endforeach;
168
+ }
169
+
170
+ function validate_post( $action = 'ctc_update', $noncefield = '_wpnonce', $cap = 'install_themes' ) {
171
+ // security: request must be post, user must have permission, referrer must be local and nonce must match
172
+ return ( $this->is_post
173
+ && current_user_can( $cap ) // ( 'edit_themes' )
174
+ && ( $this->is_ajax ? check_ajax_referer( $action, $noncefield, FALSE ) :
175
+ check_admin_referer( $action, $noncefield, FALSE ) ) );
176
+ }
177
+
178
+ function load_config() {
179
+ $this->css = new ChildThemeConfiguratorCSS();
180
+ if ( FALSE !== $this->css->load_config() ):
181
+ $this->debug( 'config exists', __FUNCTION__, __CLASS__, __CLASS__ );
182
+ // if themes do not exist reinitialize
183
+ if ( ! $this->check_theme_exists( $this->get( 'child' ) )
184
+ || ! $this->check_theme_exists( $this->get( 'parnt' ) ) ):
185
+ $this->debug( 'theme does not exist', __FUNCTION__, __CLASS__, __CLASS__ );
186
+ add_action( 'admin_notices', array( $this, 'config_notice' ) );
187
+ $this->css = new ChildThemeConfiguratorCSS();
188
+ $this->css->enqueue = 'enqueue';
189
+ endif;
190
+ else:
191
+ $this->debug( 'config does not exist', __FUNCTION__, __CLASS__, __CLASS__ );
192
+ // this is a fresh install
193
+ $this->css->enqueue = 'enqueue';
194
+ endif;
195
+ do_action( 'chld_thm_cfg_load' );
196
+ if ( $this->is_get ):
197
+ if ( $this->get( 'child' ) ):
198
+ // get filesystem credentials if available
199
+ $this->verify_creds();
200
+ $stylesheet = apply_filters(
201
+ 'chld_thm_cfg_target',
202
+ $this->css->get_child_target( $this->get_child_stylesheet() ),
203
+ $this->css );
204
+ // check file permissions
205
+ if ( !is_writable( $stylesheet ) && !$this->fs )
206
+ add_action( 'admin_notices', array( $this, 'writable_notice' ) );
207
+ if ( $fsize = $this->get( 'fsize' ) ):
208
+ $test = filesize( $stylesheet );
209
+ $this->debug( 'filesize saved: ' . $fsize . ' current: ' . $test, __FUNCTION__, __CLASS__, __CLASS__ );
210
+ if ( $test != $fsize )
211
+ add_action( 'admin_notices', array( $this, 'changed_notice' ) );
212
+ endif;
213
+ // enqueue flag will be null for existing install < 1.6.0
214
+ if ( !$this->get( 'enqueue' ) ):
215
+ $this->debug( 'no enqueue:', __FUNCTION__, __CLASS__, __CLASS__ );
216
+
217
+ add_action( 'admin_notices', array( $this, 'enqueue_notice' ) );
218
+ endif;
219
+ endif;
220
+ if ( !$this->seen_upgrade_notice() ):
221
+ add_action( 'admin_notices', array( $this, 'upgrade_notice' ) );
222
+ endif;
223
+ /**
224
+ * Future use: check if max selectors reached
225
+ *
226
+ if ( $this->get( 'max_sel' ) ):
227
+ $this->debug( 'Max selectors exceeded.', __FUNCTION__, __CLASS__, __CLASS__ );
228
+ //$this->errors[] = __( 'Maximum number of styles exceeded.', 'child-theme-configurator' );
229
+ add_action( 'admin_notices', array( $this, 'max_styles_notice' ) );
230
+ endif;
231
+ */
232
+ // check if file ownership is messed up from old version or other plugin
233
+ // by comparing owner of plugin to owner of child theme:
234
+ if ( fileowner( $this->css->get_child_target( '' ) ) != fileowner( CHLD_THM_CFG_DIR ) )
235
+ add_action( 'admin_notices', array( $this, 'owner_notice' ) );
236
+ endif;
237
+ }
238
+
239
+ /**
240
+ * ajax callback for saving form data
241
+ */
242
+ function ajax_save_postdata( $action = 'ctc_update' ) {
243
+ $this->is_ajax = TRUE;
244
+ $this->debug( 'ajax save ', __FUNCTION__, __CLASS__ );
245
+ // security check
246
+ if ( $this->validate_post( $action ) ):
247
+ if ( 'ctc_plugin' == $action ) do_action( 'chld_thm_cfg_pluginmode' );
248
+ $this->verify_creds(); // initialize filesystem access
249
+ add_action( 'chld_thm_cfg_cache_updates', array( $this, 'cache_debug' ) );
250
+ // get configuration data from options API
251
+ if ( FALSE !== $this->load_config() ): // sanity check: only update if config data exists
252
+ if ( isset( $_POST[ 'ctc_is_debug' ] ) ):
253
+ // toggle debug
254
+ $this->toggle_debug();
255
+ else:
256
+ $this->css->parse_post_data(); // parse any passed values
257
+ // if child theme config has been set up, save new data
258
+ // return recent edits and selected stylesheets as cache updates
259
+ if ( $this->get( 'child' ) ):
260
+ // hook for add'l plugin files and subdirectories
261
+ do_action( 'chld_thm_cfg_addl_files' );
262
+ $this->css->write_css();
263
+ /*
264
+ $this->updates[] = array(
265
+ 'obj' => 'addl_css',
266
+ 'key' => '',
267
+ 'data' => $this->get( 'addl_css' ),
268
+ );
269
+ */
270
+ endif;
271
+
272
+ // update config data in options API
273
+ $this->save_config();
274
+ endif;
275
+ // add any additional updates to pass back to browser
276
+ do_action( 'chld_thm_cfg_cache_updates' );
277
+ endif;
278
+ endif;
279
+ $result = $this->css->obj_to_utf8( $this->updates );
280
+ // send all updates back to browser to update cache
281
+ die( json_encode( $result ) );
282
+ }
283
+
284
+ function save_config() {
285
+ // update config data in options API
286
+ $this->css->save_config();
287
+ }
288
+
289
+ /**
290
+ * ajax callback to query config data
291
+ */
292
+ function ajax_query_css( $action = 'ctc_update' ) {
293
+ $this->is_ajax = TRUE;
294
+ if ( $this->validate_post( $action ) ):
295
+ if ( 'ctc_plugin' == $action ) do_action( 'chld_thm_cfg_pluginmode' );
296
+ $this->load_config();
297
+ add_action( 'chld_thm_cfg_cache_updates', array( $this, 'cache_debug' ) );
298
+ $regex = "/^ctc_query_/";
299
+ foreach( preg_grep( $regex, array_keys( $_POST ) ) as $key ):
300
+ $name = preg_replace( $regex, '', $key );
301
+ $param[ $name ] = sanitize_text_field( $_POST[ $key ] );
302
+ endforeach;
303
+ $this->debug( 'ajax params: ' . print_r( $param, TRUE ), __FUNCTION__, __CLASS__, __CLASS__ );
304
+ if ( !empty( $param[ 'obj' ] ) ):
305
+ // add any additional updates to pass back to browser
306
+ $this->updates[] = array(
307
+ 'key' => isset( $param[ 'key' ] ) ? $param[ 'key' ] : '',
308
+ 'obj' => $param[ 'obj' ],
309
+ 'data' => $this->get( $param[ 'obj' ], $param ),
310
+ );
311
+ do_action( 'chld_thm_cfg_cache_updates' );
312
+ die( json_encode( $this->updates ) );
313
+ endif;
314
+ endif;
315
+ die( 0 );
316
+ }
317
+
318
+ /**
319
+ * check if user has been notified about upgrade
320
+ */
321
+ function seen_upgrade_notice() {
322
+ $seen_upgrade_version = get_user_meta( get_current_user_id(), 'chld_thm_cfg_upgrade_notice', TRUE );
323
+ return version_compare( $seen_upgrade_version, CHLD_THM_CFG_PREV_VERSION, '>=' );
324
+ }
325
+
326
+ /**
327
+ * ajax callback to dismiss upgrade notice
328
+ */
329
+ function ajax_dismiss_notice( $action = 'ctc_update' ) {
330
+ $this->is_ajax = TRUE;
331
+ if ( $this->validate_post( $action ) ):
332
+ update_user_meta( get_current_user_id(), 'chld_thm_cfg_upgrade_notice' , CHLD_THM_CFG_VERSION );
333
+ $this->updates[] = array(
334
+ 'key' => '',
335
+ 'obj' => 'dismiss',
336
+ 'data' => CHLD_THM_CFG_VERSION,
337
+ );
338
+ die( json_encode( $this->updates ) );
339
+ endif;
340
+ die( 0 );
341
+ }
342
+
343
+ function ajax_analyze() {
344
+ $this->is_ajax = TRUE;
345
+ if ( $this->validate_post( 'ctc_update' ) ):
346
+ $analysis = new ChildThemeConfiguratorAnalysis();
347
+ $analysis->do_analysis();
348
+ die( json_encode( $analysis->get_analysis() ) );
349
+ endif;
350
+ die( 0 );
351
+ }
352
+
353
+ function get_pathinfo( $path ){
354
+ $pathinfo = pathinfo( $path );
355
+ $path = ( preg_match( "/^[\.\/]/", $pathinfo[ 'dirname' ] ) ? '' : $pathinfo[ 'dirname' ] . '/' ) . $pathinfo[ 'filename' ];
356
+ return array( $path, $pathinfo[ 'extension' ] );
357
+ }
358
+ /**
359
+ * Handles processing for all form submissions.
360
+ * Moved conditions to switch statement with the main setup logic in a separate function.
361
+ */
362
+ function process_post() {
363
+ // make sure this is a post
364
+ if ( $this->is_post ):
365
+ // see if a valid action was passed
366
+ foreach ( $this->actionfields as $field ):
367
+ if ( in_array( 'ctc_' . $field, array_keys( $_POST ) ) ):
368
+ $actionfield = $field;
369
+ break;
370
+ endif;
371
+ endforeach;
372
+ if ( empty( $actionfield ) ) return FALSE;
373
+
374
+ // make sure post passes security checkpoint
375
+ if ( $this->validate_post( apply_filters( 'chld_thm_cfg_action', 'ctc_update' ) ) ):
376
+ // reset debug log
377
+ delete_site_transient( CHLD_THM_CFG_OPTIONS . '_debug' );
378
+ // handle uploaded file before checking filesystem
379
+ if ( 'theme_image_submit' == $actionfield && isset( $_FILES[ 'ctc_theme_image' ] ) ):
380
+ $this->handle_file_upload( 'ctc_theme_image', $this->imgmimes );
381
+ elseif ( 'theme_screenshot_submit' == $actionfield && isset( $_FILES[ 'ctc_theme_screenshot' ] ) ):
382
+ $this->handle_file_upload( 'ctc_theme_screenshot', $this->imgmimes );
383
+ endif;
384
+ // now we need to check filesystem access
385
+ $args = preg_grep( "/nonce/", array_keys( $_POST ), PREG_GREP_INVERT );
386
+ $this->verify_creds( $args );
387
+ if ( $this->fs ):
388
+ $msg = FALSE;
389
+ // we have filesystem access so proceed with specific actions
390
+ switch( $actionfield ):
391
+ case 'export_child_zip':
392
+ case 'export_theme':
393
+ $this->export_theme();
394
+ // if we get here the zip failed
395
+ $this->errors[] = __( 'Zip file creation failed.', 'child-theme-configurator' );
396
+ break;
397
+ case 'load_styles':
398
+ // main child theme setup function
399
+ $msg = $this->setup_child_theme();
400
+ break;
401
+
402
+ case 'parnt_templates_submit':
403
+ // copy parent templates to child
404
+ if ( isset( $_POST[ 'ctc_file_parnt' ] ) ):
405
+ foreach ( $_POST[ 'ctc_file_parnt' ] as $file ):
406
+ list( $path, $ext ) = $this->get_pathinfo( sanitize_text_field( $file ) );
407
+ $this->copy_parent_file( $path, $ext );
408
+ endforeach;
409
+ $msg = '8&tab=file_options';
410
+ endif;
411
+ break;
412
+
413
+ case 'child_templates_submit':
414
+ // delete child theme files
415
+ if ( isset( $_POST[ 'ctc_file_child' ] ) ):
416
+
417
+ foreach ( $_POST[ 'ctc_file_child' ] as $file ):
418
+ list( $path, $ext ) = $this->get_pathinfo( sanitize_text_field( $file ) );
419
+ if ( 'functions' == $path ):
420
+ $this->errors[] =
421
+ __( 'The Functions file is required and cannot be deleted.', 'child-theme-configurator' );
422
+ continue;
423
+ else:
424
+ $this->delete_child_file( $path, $ext );
425
+ endif;
426
+ endforeach;
427
+ $msg = '8&tab=file_options';
428
+ endif;
429
+ break;
430
+
431
+ case 'image_submit':
432
+ // delete child theme images
433
+ if ( isset( $_POST[ 'ctc_img' ] ) ):
434
+ foreach ( $_POST[ 'ctc_img' ] as $file )
435
+ $this->delete_child_file( 'images/' . sanitize_text_field( $file ), 'img' );
436
+ $msg = '8&tab=file_options';
437
+ endif;
438
+ break;
439
+
440
+ case 'templates_writable_submit':
441
+ // make specific files writable ( systems not running suExec )
442
+ if ( isset( $_POST[ 'ctc_file_child' ] ) ):
443
+ foreach ( $_POST[ 'ctc_file_child' ] as $file ):
444
+ list( $path, $ext ) = $this->get_pathinfo( sanitize_text_field( $file ) );
445
+ $this->set_writable( $path, $ext );
446
+ endforeach;
447
+ $msg = '8&tab=file_options';
448
+ endif;
449
+ break;
450
+
451
+ case 'set_writable':
452
+ // make child theme style.css and functions.php writable ( systems not running suExec )
453
+ $this->set_writable(); // no argument defaults to style.css
454
+ $this->set_writable( 'functions' );
455
+ $msg = '8&tab=file_options';
456
+ break;
457
+
458
+ case 'reset_permission':
459
+ // make child theme read-only ( systems not running suExec )
460
+ $this->unset_writable();
461
+ $msg = '8&tab=file_options';
462
+ break;
463
+
464
+ case 'theme_image_submit':
465
+ // move uploaded child theme images (now we have filesystem access)
466
+ if ( isset( $_POST[ 'movefile' ] ) ):
467
+ $this->move_file_upload( 'images' );
468
+ $msg = '8&tab=file_options';
469
+ endif;
470
+ break;
471
+
472
+ case 'theme_screenshot_submit':
473
+ // move uploaded child theme screenshot (now we have filesystem access)
474
+ if ( isset( $_POST[ 'movefile' ] ) ):
475
+ // remove old screenshot
476
+ foreach( array_keys( $this->imgmimes ) as $extreg ):
477
+ foreach ( explode( '|', $extreg ) as $ext )
478
+ $this->delete_child_file( 'screenshot', $ext );
479
+ endforeach;
480
+ $this->move_file_upload( '' );
481
+ $msg = '8&tab=file_options';
482
+ endif;
483
+ break;
484
+ default:
485
+ // assume we are on the files tab so just redirect there
486
+ $msg = '8&tab=file_options';
487
+ endswitch;
488
+ endif; // end filesystem condition
489
+ if ( empty( $this->errors ) && empty( $this->fs_prompt ) ):
490
+ $this->processdone = TRUE;
491
+ //die( '<pre><code><small>' . print_r( $_POST, TRUE ) . '</small></code></pre>' );
492
+ // no errors so we redirect with confirmation message
493
+ $this->update_redirect( $msg );
494
+ endif;
495
+ // otherwise fail gracefully
496
+ $msg = NULL;
497
+ return FALSE;
498
+ endif; // end post validation condition
499
+ // if you end up here you are persona non grata
500
+ $msg = NULL;
501
+ $this->errors[] = __( 'You do not have permission to configure child themes.', 'child-theme-configurator' );
502
+ endif; // end request method condition
503
+ return FALSE;
504
+ }
505
+
506
+ /**
507
+ * Handle the creation or update of a child theme
508
+ */
509
+ function setup_child_theme() {
510
+ $msg = 1;
511
+ $this->is_new = TRUE;
512
+ // sanitize and extract config fields into local vars
513
+ foreach ( $this->configfields as $configfield ):
514
+ $varparts = explode( '_', $configfield );
515
+ $varname = end( $varparts );
516
+ ${$varname} = empty( $_POST[ 'ctc_' . $configfield ] ) ? '' :
517
+ preg_replace( "/\s+/s", ' ', sanitize_text_field( $_POST[ 'ctc_' . $configfield ] ) );
518
+ $this->debug( 'Extracting var ' . $varname . ' from ctc_' . $configfield . ' value: ' . ${$varname} , __FUNCTION__, __CLASS__ );
519
+ endforeach;
520
+
521
+ if ( isset( $type ) ) $this->childtype = $type;
522
+
523
+ // legacy plugin extension needs parent/new values but this version disables the inputs
524
+ // so get we them from current css object
525
+ if ( !$this->is_theme( $configtype ) && $this->is_legacy() ):
526
+ $parnt = $this->get( 'parnt' );
527
+ $child = $this->get( 'child' );
528
+ $name = $this->get( 'child_name' );
529
+ endif;
530
+ // validate parent and child theme inputs
531
+ if ( $parnt ):
532
+ if ( ! $this->check_theme_exists( $parnt ) ):
533
+ $this->errors[] = sprintf(
534
+ __( '%s does not exist. Please select a valid Parent Theme.', 'child-theme-configurator' ), $parnt );
535
+ endif;
536
+ else:
537
+ $this->errors[] = __( 'Please select a valid Parent Theme.', 'child-theme-configurator' );
538
+ endif;
539
+
540
+ // if this is reset, duplicate or existing, we must have a child theme
541
+ if ( 'new' != $type && empty( $child ) ):
542
+ $this->errors[] = __( 'Please select a valid Child Theme.', 'child-theme-configurator' );
543
+ // if this is a new or duplicate child theme we must validate child theme directory
544
+ elseif ( 'new' == $type || 'duplicate' == $type ):
545
+ if ( empty( $template ) && empty( $name ) ):
546
+ $this->errors[] = __( 'Please enter a valid Child Theme directory name.', 'child-theme-configurator' );
547
+ else:
548
+ $template_sanitized = preg_replace( "%[^\w\-]%", '', empty( $template ) ? $name : $template );
549
+ if ( $this->check_theme_exists( $template_sanitized ) ):
550
+ $this->errors[] = sprintf(
551
+ __( '<strong>%s</strong> exists. Please enter a different Child Theme template name.', 'child-theme-configurator' ), $template_sanitized );
552
+ elseif ( 'duplicate' == $type ):
553
+ // clone existing child theme
554
+ $this->clone_child_theme( $child, $template_sanitized );
555
+ if ( !empty( $this->errors ) ) return FALSE;
556
+ // if no errors, copy menus, widgets and customizer options
557
+ $this->copy_theme_mods( $child, $template_sanitized );
558
+ $msg = 3;
559
+ else:
560
+ $msg = 2;
561
+ endif;
562
+ $child = $template_sanitized;
563
+ endif;
564
+
565
+ endif;
566
+
567
+ // verify_child_dir creates child theme directory if it doesn't exist.
568
+ if ( FALSE === $this->verify_child_dir( $child ) ):
569
+ // if it returns false then it could not create directory.
570
+ $this->errors[] = __( 'Your theme directories are not writable.', 'child-theme-configurator' );
571
+ add_action( 'admin_notices', array( $this, 'writable_notice' ) );
572
+ return FALSE;
573
+ endif;
574
+
575
+ // load or reset config
576
+ if ( 'reset' == $type ):
577
+ $this->debug( 'resetting child theme', __FUNCTION__, __CLASS__ );
578
+ $this->reset_child_theme();
579
+ $this->enqueue_parent_css();
580
+ $msg = 4;
581
+ else:
582
+
583
+ // if any errors, bail before we create css object
584
+ if ( !empty( $this->errors ) ) return FALSE;
585
+
586
+ // if no name is passed, create one from the child theme directory
587
+ if ( empty( $name ) ):
588
+ $name = ucfirst( $child );
589
+ endif;
590
+
591
+ /**
592
+ * before we configure the child theme we need to check if this is a rebuild
593
+ * and compare some of the original settings to the new settings.
594
+ */
595
+ //$oldchild = $this->get( 'child' );
596
+ //$oldimports = $this->get( 'imports' );
597
+ //$oldenqueue = $this->get( 'enqueue' );
598
+ $oldhandling = $this->get( 'handling' );
599
+ // reset everything else
600
+ $this->css = new ChildThemeConfiguratorCSS();
601
+ // restore imports if this is a rebuild
602
+ //$this->css->imports[ 'child' ] = $oldimports;
603
+
604
+ // update with new parameters
605
+ if ( !$this->is_theme( $configtype ) )
606
+ $this->css->set_prop( 'enqueue', 'enqueue' );
607
+ else
608
+ $this->css->set_prop( 'enqueue', $enqueue );
609
+ $this->css->set_prop( 'handling', $handling );
610
+ $this->css->set_prop( 'ignoreparnt', $ignoreparnt );
611
+
612
+ $this->css->set_prop( 'parnt', $parnt );
613
+ $this->css->set_prop( 'child', $child );
614
+ $this->css->set_prop( 'child_name', $name );
615
+ $this->css->set_prop( 'child_author', $author );
616
+ $this->css->set_prop( 'child_themeuri', $themeuri );
617
+ $this->css->set_prop( 'child_authoruri', $authoruri );
618
+ $this->css->set_prop( 'child_descr', $descr );
619
+ $this->css->set_prop( 'child_tags', $tags );
620
+ $this->css->set_prop( 'child_version', strlen( $version ) ? $version : '1.0' );
621
+
622
+ if ( isset( $_POST[ 'ctc_action' ] ) && 'plugin' == $_POST[ 'ctc_action' ] ):
623
+ // this is for PRO plugins
624
+ $this->css->addl_css = array();
625
+ if ( isset( $_POST[ 'ctc_additional_css' ] ) && is_array( $_POST[ 'ctc_additional_css' ] ) ):
626
+ foreach ( $_POST[ 'ctc_additional_css' ] as $file )
627
+ $this->css->addl_css[] = sanitize_text_field( $file );
628
+ endif;
629
+ add_action( 'chld_thm_cfg_parse_stylesheets', array( $this, 'parse_child_stylesheet_to_target' ) );
630
+ elseif ( isset( $_POST[ 'ctc_analysis' ] ) ):
631
+ // this is for themes
632
+ $this->evaluate_signals();
633
+ endif;
634
+
635
+ // v2.1.3 - force dependency for specific stylesheets
636
+ $this->css->forcedep = array();
637
+ if ( isset( $_POST[ 'ctc_forcedep' ] ) && is_array( $_POST[ 'ctc_forcedep' ] ) ):
638
+ foreach ( $_POST[ 'ctc_forcedep' ] as $handle )
639
+ $this->css->forcedep[ sanitize_text_field( $handle ) ] = 1;
640
+ endif;
641
+
642
+ // roll back CTC Pro Genesis handling option
643
+ if ( $this->genesis ):
644
+ $handling = 'separate';
645
+ $enqueue = 'none';
646
+ $ignoreparnt = TRUE;
647
+ if ( $this->backup_or_restore_file( 'ctc-style.css', TRUE, 'style.css' ) &&
648
+ $this->backup_or_restore_file( 'style.css', TRUE, 'ctc-genesis.css' ) ):
649
+ $this->delete_child_file( 'ctc-genesis', 'css' );
650
+ else:
651
+ $this->errors[] = __( 'Could not upgrade child theme', 'child-theme-configurator' );
652
+ endif;
653
+ endif;
654
+
655
+ // if any errors, bail before we set action hooks or write to filesystem
656
+ if ( !empty( $this->errors ) ) return FALSE;
657
+
658
+ // override enqueue action for parent theme if it is already being loaded
659
+ if ( 'enqueue' == $enqueue && ( $this->get( 'parntloaded' ) || !$this->get( 'hasstyles' ) || $ignoreparnt ) ) $enqueue = 'none';
660
+
661
+ // parse parent stylesheet if theme or legacy plugin extension
662
+ if ( $this->is_theme( $configtype ) || $this->is_legacy() ):
663
+ // do we parse parent stylesheet?
664
+
665
+ if ( $this->get( 'hasstyles' ) && !$ignoreparnt ):
666
+ $this->debug( 'Adding action: parse_parent_stylesheet_to_source', __FUNCTION__, __CLASS__ );
667
+ add_action( 'chld_thm_cfg_parse_stylesheets', array( $this, 'parse_parent_stylesheet_to_source' ) );
668
+ endif;
669
+
670
+ // automatically network enable new theme // FIXME: shouldn't this be an option?
671
+ if ( is_multisite() )
672
+ add_action( 'chld_thm_cfg_addl_options', array( $this, 'network_enable' ) );
673
+ endif;
674
+ $this->debug( 'Adding action: parse_additional_stylesheets_to_source', __FUNCTION__, __CLASS__ );
675
+ add_action( 'chld_thm_cfg_parse_stylesheets', array( $this, 'parse_additional_stylesheets_to_source' ) );
676
+
677
+ if ( 'separate' == $handling ):
678
+ // parse child theme style.css into source config
679
+ $this->debug( 'Adding action: parse_child_stylesheet_to_source', __FUNCTION__, __CLASS__ );
680
+ add_action( 'chld_thm_cfg_parse_stylesheets', array( $this, 'parse_child_stylesheet_to_source' ) );
681
+ // parse child theme ctc-style.css into target config
682
+ $this->debug( 'Adding action: parse_custom_stylesheet_to_target', __FUNCTION__, __CLASS__ );
683
+ add_action( 'chld_thm_cfg_parse_stylesheets', array( $this, 'parse_custom_stylesheet_to_target' ) );
684
+ elseif ( 'primary' == $handling ):
685
+ // parse child theme style.css into target config
686
+ $this->debug( 'Adding action: parse_child_stylesheet_to_target', __FUNCTION__, __CLASS__ );
687
+ add_action( 'chld_thm_cfg_parse_stylesheets', array( $this, 'parse_child_stylesheet_to_target' ) );
688
+ if ( $oldhandling != $handling ):
689
+ $this->debug( 'Adding action: parse_custom_stylesheet_to_target', __FUNCTION__, __CLASS__ );
690
+ add_action( 'chld_thm_cfg_parse_stylesheets', array( $this, 'parse_custom_stylesheet_to_target' ) );
691
+ endif;
692
+ endif;
693
+
694
+ // function to support wp_filesystem requirements
695
+ if ( $this->is_theme( $configtype ) ):
696
+ // is theme means this is not a plugin stylesheet config
697
+ add_action( 'chld_thm_cfg_addl_files', array( $this, 'add_base_files' ), 10, 2 );
698
+ add_action( 'chld_thm_cfg_addl_files', array( $this, 'copy_screenshot' ), 10, 2 );
699
+ add_action( 'chld_thm_cfg_addl_files', array( $this, 'enqueue_parent_css' ), 15, 2 );
700
+ if ( $repairheader && 'reset' != $type ):
701
+ add_action( 'chld_thm_cfg_addl_files', array( $this, 'repair_header' ) );
702
+ endif;
703
+
704
+ endif;
705
+
706
+ // plugin hooks for additional stylesheet handling options
707
+ // do_action( 'chld_thm_cfg_stylesheet_handling' );
708
+ // do_action( 'chld_thm_cfg_existing_theme' );
709
+
710
+ // plugin hook to parse additional or non-standard files
711
+ do_action( 'chld_thm_cfg_parse_stylesheets' );
712
+ // copy menus, widgets and other customizer options from parent to child if selected
713
+ if ( isset( $_POST[ 'ctc_parent_mods' ] ) && 'duplicate' != $type )
714
+ $this->copy_theme_mods( $parnt, $child );
715
+ // run code generation function in read-only mode to add existing external stylesheet links to config data
716
+ $this->enqueue_parent_css( TRUE );
717
+ // hook for add'l plugin files and subdirectories. Must run after stylesheets are parsed to apply latest options
718
+ do_action( 'chld_thm_cfg_addl_files' );
719
+ // do not continue if errors
720
+ if ( !empty ( $this->errors ) ) return FALSE;
721
+ //echo ' no errors! saving...' . LF;
722
+ if ( 'separate' == $handling ):
723
+ $this->debug( 'Writing new stylesheet header...', __FUNCTION__, __CLASS__ );
724
+ $this->rewrite_stylesheet_header();
725
+ endif;
726
+ // set flag to skip import link conversion on ajax save
727
+ $this->css->set_prop( 'converted', 1 );
728
+
729
+ // try to write new stylsheet. If it fails send alert.
730
+ $this->debug( 'Writing new CSS...', __FUNCTION__, __CLASS__ );
731
+ if ( FALSE === $this->css->write_css() ):
732
+ //$this->debug( print_r( debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS ), TRUE ), __FUNCTION__, __CLASS__ );
733
+ $this->errors[] = __( 'Your stylesheet is not writable.', 'child-theme-configurator' );
734
+ add_action( 'admin_notices', array( $this, 'writable_notice' ) );
735
+ return FALSE;
736
+ endif;
737
+ // get files to reload templates in new css object
738
+ $this->get_files( $parnt );
739
+ endif;
740
+ $this->debug( 'Saving new config...', __FUNCTION__, __CLASS__ );
741
+ // save new object to WP options table
742
+ $this->save_config();
743
+ $this->debug( 'Firing additional options action...', __FUNCTION__, __CLASS__ );
744
+ // plugin hook for additional child theme setup functions
745
+ do_action( 'chld_thm_cfg_addl_options' );
746
+ //$this->dump_configs();
747
+ // return message id 1, which says new child theme created successfully;
748
+ return $msg;
749
+ }
750
+
751
+ /*
752
+ * TODO: this is a stub for future use
753
+ */
754
+ function sanitize_options( $input ) {
755
+ return $input;
756
+ }
757
+
758
+ /**
759
+ * remove slashes and non-alphas from stylesheet name
760
+ */
761
+ function sanitize_slug( $slug ) {
762
+ return preg_replace( "/[^\w\-]/", '', $slug );
763
+ }
764
+
765
+ function update_redirect( $msg = 1 ) {
766
+ $this->log_debug();
767
+ if ( empty( $this->is_ajax ) ):
768
+ $ctcpage = apply_filters( 'chld_thm_cfg_admin_page', CHLD_THM_CFG_MENU );
769
+ $screen = get_current_screen()->id;
770
+ wp_safe_redirect(
771
+ ( strstr( $screen, '-network' ) ? network_admin_url( 'themes.php' ) : admin_url( 'tools.php' ) )
772
+ . '?page=' . $ctcpage . ( $msg ? '&updated=' . $msg : '' ) );
773
+ die();
774
+ endif;
775
+ }
776
+
777
+ function verify_child_dir( $path ) {
778
+ $this->debug( 'Verifying child dir: ' . $path, __FUNCTION__, __CLASS__ );
779
+ if ( !$this->fs ):
780
+ $this->debug( 'No filesystem access.', __FUNCTION__, __CLASS__ );
781
+ return FALSE; // return if no filesystem access
782
+ endif;
783
+ global $wp_filesystem;
784
+ $themedir = $wp_filesystem->find_folder( get_theme_root() );
785
+ if ( ! $wp_filesystem->is_writable( $themedir ) ):
786
+ $this->debug( 'Directory not writable: ' . $themedir, __FUNCTION__, __CLASS__ );
787
+ return FALSE;
788
+ endif;
789
+ $childparts = explode( '/', $this->normalize_path( $path ) );
790
+ while ( count( $childparts ) ):
791
+ $subdir = array_shift( $childparts );
792
+ if ( empty( $subdir ) ) continue;
793
+ $themedir = trailingslashit( $themedir ) . $subdir;
794
+ if ( ! $wp_filesystem->is_dir( $themedir ) ):
795
+ if ( ! $wp_filesystem->mkdir( $themedir, FS_CHMOD_DIR ) ):
796
+ $this->debug( 'Could not make directory: ' . $themedir, __FUNCTION__, __CLASS__ );
797
+ return FALSE;
798
+ endif;
799
+ elseif ( ! $wp_filesystem->is_writable( $themedir ) ):
800
+ $this->debug( 'Directory not writable: ' . $themedir, __FUNCTION__, __CLASS__ );
801
+ return FALSE;
802
+ endif;
803
+ endwhile;
804
+ $this->debug( 'Child dir verified: ' . $themedir, __FUNCTION__, __CLASS__ );
805
+ return TRUE;
806
+ }
807
+
808
+ function add_base_files( $obj ){
809
+ //$this->debug( LF . LF, __FUNCTION__, __CLASS__ );
810
+ // add functions.php file
811
+ $contents = "<?php
812
+ // Exit if accessed directly
813
+ if ( !defined( 'ABSPATH' ) ) exit;
814
+ ";
815
+ $handling = $this->get( 'handling' );
816
+ $this->write_child_file( 'functions.php', $contents );
817
+ $this->backup_or_restore_file( 'style.css' );
818
+ $contents = $this->css->get_css_header_comment( $handling );
819
+ $this->debug( 'writing initial stylesheet header...' . LF . $contents, __FUNCTION__, __CLASS__ );
820
+ $this->write_child_file( 'style.css', $contents );
821
+ if ( 'separate' == $handling ):
822
+ $this->backup_or_restore_file( 'ctc-style.css' );
823
+ $this->write_child_file( 'ctc-style.css', $contents . LF );
824
+ endif;
825
+ }
826
+
827
+ // parses @import syntax and converts to wp_enqueue_style statement
828
+ function convert_import_to_enqueue( $import, $count, $execute = FALSE ) {
829
+ $relpath = $this->get( 'child' );
830
+ $import = preg_replace( "#^.*?url\(([^\)]+?)\).*#", "$1", $import );
831
+ $import = preg_replace( "#[\'\"]#", '', $import );
832
+ $path = $this->css->convert_rel_url( trim( $import ), $relpath , FALSE );
833
+ $abs = preg_match( '%(https?:)?//%', $path );
834
+ if ( $execute )
835
+ wp_enqueue_style( 'chld_thm_cfg_ext' . $count, $abs ? $path : trailingslashit( get_theme_root_uri() ) . $path );
836
+ else
837
+ return "wp_enqueue_style( 'chld_thm_cfg_ext" . $count . "', "
838
+ . ( $abs ? "'" . $path . "'" : "trailingslashit( get_theme_root_uri() ) . '" . $path . "'" ) . ' );';
839
+ }
840
+
841
+ // converts enqueued path into @import statement for config settings
842
+ function convert_enqueue_to_import( $path ) {
843
+ if ( preg_match( '%(https?:)?//%', $path ) ):
844
+ $this->css->imports[ 'child' ]['@import url(' . $path . ')'] = 1;
845
+ return;
846
+ endif;
847
+ $regex = '#^' . preg_quote( trailingslashit( $this->get( 'child' ) ) ) . '#';
848
+ $path = preg_replace( $regex, '', $path, -1, $count );
849
+ if ( $count ):
850
+ $this->css->imports[ 'child' ]['@import url(' . $path . ')'] = 1;
851
+ return;
852
+ endif;
853
+ $parent = trailingslashit( $this->get( 'parnt' ) );
854
+ $regex = '#^' . preg_quote( $parent ) . '#';
855
+ $path = preg_replace( $regex, '../' . $parent, $path, -1, $count );
856
+ if ( $count )
857
+ $this->css->imports[ 'child' ]['@import url(' . $path . ')'] = 1;
858
+ }
859
+
860
+ /**
861
+ * Generates wp_enqueue_script code block for child theme functions file
862
+ * Enqueues parent and/or child stylesheet depending on value of 'enqueue' setting.
863
+ * If external imports are present, it enqueues them as well.
864
+ */
865
+ function enqueue_parent_code(){
866
+ //$this->debug( print_r( debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS ), TRUE ), __FUNCTION__, __CLASS__ );
867
+ $imports = $this->get( 'imports' );
868
+ $enqueues = array();
869
+ $code = "// AUTO GENERATED - Do not modify or remove comment markers above or below:" . LF;
870
+ $deps = $this->get( 'parnt_deps' );
871
+ $enq = $this->get( 'enqueue' );
872
+ $handling = $this->get( 'handling' );
873
+ $hasstyles = $this->get( 'hasstyles' );
874
+ $childloaded = $this->get( 'childloaded' );
875
+ $parntloaded = $this->get( 'parntloaded' );
876
+ $cssunreg = $this->get( 'cssunreg' );
877
+ $csswphead = $this->get( 'csswphead' );
878
+ $cssnotheme = $this->get( 'cssnotheme' );
879
+ $ignoreparnt = $this->get( 'ignoreparnt' );
880
+ $priority = $this->get( 'qpriority' );
881
+ $reorder = $this->get( 'reorder' );
882
+ $this->debug( 'forcedep: ' . print_r( $this->get( 'forcedep' ), TRUE ) . ' deps: ' . print_r( $deps, TRUE ) . ' enq: ' . $enq . ' handling: ' . $handling
883
+ . ' hasstyles: ' . $hasstyles . ' parntloaded: ' . $parntloaded . ' childloaded: ' . $childloaded . ' reorder: ' . $reorder
884
+ . ' ignoreparnt: ' . $ignoreparnt . ' priority: ' . $priority . ' childtype: ' . $this->childtype, __FUNCTION__, __CLASS__ );
885
+ // enqueue parent stylesheet
886
+ if ( 'enqueue' == $enq && $hasstyles && !$parntloaded && !$ignoreparnt ):
887
+ $code .= "
888
+ if ( !function_exists( 'chld_thm_cfg_parent_css' ) ):
889
+ function chld_thm_cfg_parent_css() {
890
+ wp_enqueue_style( 'chld_thm_cfg_parent', trailingslashit( get_template_directory_uri() ) . 'style.css', array( " . implode( ',', $deps ) . " ) );
891
+ }
892
+ endif;
893
+ add_action( 'wp_enqueue_scripts', 'chld_thm_cfg_parent_css', " . $priority . " );
894
+ ";
895
+ // if loading parent theme, reset deps and add parent stylesheet
896
+ $deps = array( "'chld_thm_cfg_parent'" );
897
+
898
+ endif;
899
+
900
+ // force a stylesheet dependency if parent is loading out of sequence
901
+ if ( 'separate' != $handling && $childloaded && $reorder && ( $parntloaded || in_array( 'chld_thm_cfg_parent', $deps ) ) ):
902
+ $dephandle = $parntloaded ? $parntloaded : 'chld_thm_cfg_parent';
903
+ $code .= "
904
+ if ( !function_exists( 'chld_thm_cfg_add_parent_dep' ) ):
905
+ function chld_thm_cfg_add_parent_dep() {
906
+ global \$wp_styles;
907
+ array_unshift( \$wp_styles->registered[ '" . $childloaded . "' ]->deps, '" . $dephandle . "' );
908
+ }
909
+ endif;
910
+ add_action( 'wp_head', 'chld_thm_cfg_add_parent_dep', 2 );
911
+ ";
912
+ endif;
913
+
914
+ // enqueue external stylesheets (previously used @import in the stylesheet)
915
+ if ( !empty( $imports ) ):
916
+ $ext = 0;
917
+ foreach ( $imports as $import ):
918
+ if ( !empty( $import ) ):
919
+ $ext++;
920
+ $enqueues[] = ' ' . $this->convert_import_to_enqueue( $import, $ext );
921
+ endif;
922
+ endforeach;
923
+ endif;
924
+ // if child not loaded, enqueue it and add it to dependencies
925
+ if ( 'separate' != $handling && ( ( $csswphead || $cssunreg || $cssnotheme )
926
+ || ( 'new' != $this->childtype && !$childloaded )
927
+ ) ):
928
+ $deps = array_merge( $deps, $this->get( 'child_deps' ) );
929
+ $enqueues[] = " wp_enqueue_style( 'chld_thm_cfg_child', trailingslashit( get_stylesheet_directory_uri() ) . 'style.css', array( " . implode( ',', $deps ) . " ) );";
930
+ // if loading child theme stylesheet, reset deps and add child stylesheet
931
+ $deps = array( "'chld_thm_cfg_child'" );
932
+ endif;
933
+ if ( 'separate' == $handling ):
934
+ $deps = array_merge( $deps, $this->get( 'child_deps' ) );
935
+ $enqueues[] = " wp_enqueue_style( 'chld_thm_cfg_separate', trailingslashit( get_stylesheet_directory_uri() ) . 'ctc-style.css', array( " . implode( ',', $deps ) . " ) );";
936
+ endif;
937
+ if ( count( $enqueues ) ):
938
+ $code .= "
939
+ if ( !function_exists( 'child_theme_configurator_css' ) ):
940
+ function child_theme_configurator_css() {" . LF;
941
+ $code .= implode( "\n", $enqueues );
942
+ $code .= "
943
+ }
944
+ endif;
945
+ add_action( 'wp_enqueue_scripts', 'child_theme_configurator_css' );" . LF;
946
+ endif;
947
+ if ( $ignoreparnt )
948
+ $code .= "
949
+ defined( 'CHLD_THM_CFG_IGNORE_PARENT' ) or define( 'CHLD_THM_CFG_IGNORE_PARENT', TRUE );" . LF;
950
+ //$this->debug( $code, __FUNCTION__, __CLASS__ );
951
+ return explode( "\n", $code ); // apply_filters( 'chld_thm_cfg_enqueue_code_filter', $code ) ); // FIXME?
952
+ }
953
+
954
+ // updates function file with wp_enqueue_script code block. If getexternals flag is passed function is run in read-only mode
955
+ function enqueue_parent_css( $getexternals = FALSE ) {
956
+ $this->debug( 'enqueueing parent css: getexternals = ' . $getexternals, __FUNCTION__, __CLASS__ );
957
+ $marker = 'ENQUEUE PARENT ACTION';
958
+ $insertion = $this->enqueue_parent_code();
959
+ if ( $filename = $this->css->is_file_ok( $this->css->get_child_target( 'functions.php' ), 'write' ) ):
960
+ $this->insert_with_markers( $filename, $marker, $insertion, $getexternals );
961
+ /// FIXME - reset for Pro version
962
+ if ( !$getexternals && 'reset' == $this->childtype ):
963
+ $marker = 'CTC ENQUEUE PLUGIN ACTION';
964
+ $this->insert_with_markers( $filename, $marker, array() );
965
+ endif;
966
+ endif;
967
+ }
968
+
969
+ /**
970
+ * Update functions file with wp_enqueue_style code block. Runs in read-only mode if getexternals is passed.
971
+ * This function uses the same method as the WP core function that updates .htaccess
972
+ * we would have used WP's insert_with_markers function,
973
+ * but it does not use wp_filesystem API.
974
+ */
975
+ function insert_with_markers( $filename, $marker, $insertion, $getexternals = FALSE ) {
976
+ if ( count( $this->errors ) ):
977
+ $this->debug( 'Errors detected, returning', __FUNCTION__, __CLASS__ );
978
+ return FALSE;
979
+ endif;
980
+ // first check if this is an ajax update
981
+ if ( $this->is_ajax && is_readable( $filename ) && is_writable( $filename ) ):
982
+ // ok to proceed
983
+ $this->debug( 'Ajax update, bypassing wp filesystem.', __FUNCTION__, __CLASS__ );
984
+ $markerdata = explode( "\n", @file_get_contents( $filename ) );
985
+ elseif ( !$this->fs ):
986
+ $this->debug( 'No filesystem access.', __FUNCTION__, __CLASS__ );
987
+ return FALSE; // return if no filesystem access
988
+ else:
989
+ global $wp_filesystem;
990
+ if( !$wp_filesystem->exists( $this->fspath( $filename ) ) ):
991
+ if ( $getexternals ):
992
+ $this->debug( 'Read only and no functions file yet, returning...', __FUNCTION__, __CLASS__ );
993
+ return FALSE;
994
+ else:
995
+ // make sure file exists with php header
996
+ $this->debug( 'No functions file, creating...', __FUNCTION__, __CLASS__ );
997
+ $this->add_base_files( $this );
998
+ endif;
999
+ endif;
1000
+ // get_contents_array returns extra linefeeds so just split it ourself
1001
+ $markerdata = explode( "\n", $wp_filesystem->get_contents( $this->fspath( $filename ) ) );
1002
+ endif;
1003
+ $newfile = '';
1004
+ $externals = array();
1005
+ $phpopen = 0;
1006
+ $in_comment = 0;
1007
+ $foundit = FALSE;
1008
+ if ( $markerdata ):
1009
+ $state = TRUE;
1010
+ foreach ( $markerdata as $n => $markerline ):
1011
+ // remove double slash comment to end of line
1012
+ $str = preg_replace( "/\/\/.*$/", '', $markerline );
1013
+ preg_match_all("/(<\?|\?>|\*\/|\/\*)/", $str, $matches );
1014
+ if ( $matches ):
1015
+ foreach ( $matches[1] as $token ):
1016
+ if ( '/*' == $token ):
1017
+ $in_comment = 1;
1018
+ elseif ( '*/' == $token ):
1019
+ $in_comment = 0;
1020
+ elseif ( '<?' == $token && !$in_comment ):
1021
+ $phpopen = 1;
1022
+ elseif ( '?>' == $token && !$in_comment ):
1023
+ $phpopen = 0;
1024
+ endif;
1025
+ endforeach;
1026
+ endif;
1027
+ if ( strpos( $markerline, '// BEGIN ' . $marker ) !== FALSE )
1028
+ $state = FALSE;
1029
+ if ( $state ):
1030
+ if ( $n + 1 < count( $markerdata ) )
1031
+ $newfile .= "{$markerline}\n";
1032
+ else
1033
+ $newfile .= "{$markerline}";
1034
+ elseif ( $getexternals ):
1035
+ // look for existing external stylesheets and add to imports config data
1036
+ if ( preg_match( "/wp_enqueue_style.+?'chld_thm_cfg_ext\d+'.+?'(.+?)'/", $markerline, $matches ) ):
1037
+ $this->debug( 'external link found : ' . $matches[ 1 ] );
1038
+ $this->convert_enqueue_to_import( $matches[ 1 ] );
1039
+ endif;
1040
+ endif;
1041
+ if ( strpos( $markerline, '// END ' . $marker ) !== FALSE ):
1042
+ if ( 'reset' != $this->childtype ):
1043
+ $newfile .= "// BEGIN {$marker}\n";
1044
+ if ( is_array( $insertion ) )
1045
+ foreach ( $insertion as $insertline )
1046
+ $newfile .= "{$insertline}\n";
1047
+ $newfile .= "// END {$marker}\n";
1048
+ endif;
1049
+ $state = TRUE;
1050
+ $foundit = TRUE;
1051
+ endif;
1052
+ endforeach;
1053
+ else:
1054
+ $this->debug( 'Could not parse functions file', __FUNCTION__, __CLASS__ );
1055
+ return FALSE;
1056
+ endif;
1057
+ if ( $foundit ):
1058
+ $this->debug( 'Found marker, replaced inline', __FUNCTION__, __CLASS__ );
1059
+ else:
1060
+ if ( 'reset' != $this->childtype ):
1061
+ // verify there is no PHP close tag at end of file
1062
+ if ( ! $phpopen ):
1063
+ $this->debug( 'PHP not open', __FUNCTION__, __CLASS__ );
1064
+ //$this->errors[] = __( 'A closing PHP tag was detected in Child theme functions file so "Parent Stylesheet Handling" option was not configured. Closing PHP at the end of the file is discouraged as it can cause premature HTTP headers. Please edit <code>functions.php</code> to remove the final <code>?&gt;</code> tag and click "Generate/Rebuild Child Theme Files" again.', 'child-theme-configurator' );
1065
+ //return FALSE;
1066
+ $newfile .= '<?php' . LF;
1067
+ endif;
1068
+ $newfile .= "\n// BEGIN {$marker}\n";
1069
+ foreach ( $insertion as $insertline )
1070
+ $newfile .= "{$insertline}\n";
1071
+ $newfile .= "// END {$marker}\n";
1072
+ endif;
1073
+ endif;
1074
+ // only write file when getexternals is false
1075
+ if ( $getexternals ):
1076
+ $this->debug( 'Read only, returning.', __FUNCTION__, __CLASS__ );
1077
+ else:
1078
+ $mode = 'direct' == $this->fs_method ? FALSE : 0666;
1079
+ $this->debug( 'Writing new functions file...', __FUNCTION__, __CLASS__ );
1080
+ if ( $this->is_ajax && is_writable( $filename ) ):
1081
+ // with ajax we have to bypass wp filesystem so file must already be writable
1082
+ if ( FALSE === @file_put_contents( $filename, $newfile ) ):
1083
+ $this->debug( 'Ajax write failed.', __FUNCTION__, __CLASS__ );
1084
+ return FALSE;
1085
+ endif;
1086
+ elseif ( FALSE === $wp_filesystem->put_contents(
1087
+ $this->fspath( $filename ),
1088
+ $newfile,
1089
+ $mode
1090
+ ) ): // chmod will fail unless we have fs access. user can secure files after configuring
1091
+ $this->debug( 'Filesystem write failed.', __FUNCTION__, __CLASS__ );
1092
+ return FALSE;
1093
+ endif;
1094
+ $this->css->set_prop( 'converted', 1 );
1095
+ endif;
1096
+ }
1097
+
1098
+ // creates/updates file via filesystem API
1099
+ function write_child_file( $file, $contents ) {
1100
+ //$this->debug( LF . LF, __FUNCTION__, __CLASS__ );
1101
+ if ( !$this->fs ):
1102
+ $this->debug( 'No filesystem access, returning.', __FUNCTION__, __CLASS__ );
1103
+ return FALSE; // return if no filesystem access
1104
+ endif;
1105
+ global $wp_filesystem;
1106
+ if ( $file = $this->css->is_file_ok( $this->css->get_child_target( $file ), 'write' ) ):
1107
+ $mode = 'direct' == $this->fs_method ? FALSE : 0666;
1108
+ $file = $this->fspath( $file );
1109
+ if ( $wp_filesystem->exists( $file ) ):
1110
+ $this->debug( 'File exists, returning.', __FUNCTION__, __CLASS__ );
1111
+ return FALSE;
1112
+ else:
1113
+ $this->debug( 'Writing to filesystem: ' . $file . LF . $contents, __FUNCTION__, __CLASS__ );
1114
+ if ( FALSE === $wp_filesystem->put_contents(
1115
+ $file,
1116
+ $contents,
1117
+ $mode
1118
+ ) ):
1119
+ $this->debug( 'Filesystem write failed, returning.', __FUNCTION__, __CLASS__ );
1120
+ return FALSE;
1121
+ endif;
1122
+ endif;
1123
+ else:
1124
+ $this->debug( 'No directory, returning.', __FUNCTION__, __CLASS__ );
1125
+ return FALSE;
1126
+ endif;
1127
+ $this->debug( 'Filesystem write successful.', __FUNCTION__, __CLASS__ );
1128
+ }
1129
+
1130
+ function copy_screenshot() {
1131
+ // always copy screenshot
1132
+ $this->copy_parent_file( 'screenshot' );
1133
+ }
1134
+
1135
+ function copy_parent_file( $file, $ext = 'php' ) {
1136
+ if ( !$this->fs ):
1137
+ $this->debug( 'No filesystem access.', __FUNCTION__, __CLASS__ );
1138
+ return FALSE; // return if no filesystem access
1139
+ endif;
1140
+ global $wp_filesystem;
1141
+ $parent_file = NULL;
1142
+ if ( 'screenshot' == $file ):
1143
+ foreach ( array_keys( $this->imgmimes ) as $extreg ):
1144
+ foreach( explode( '|', $extreg ) as $ext ):
1145
+ if ( $parent_file = $this->css->is_file_ok( $this->css->get_parent_source( 'screenshot.' . $ext ) ) ) break;
1146
+ endforeach;
1147
+ if ( $parent_file ):
1148
+ $parent_file = $this->fspath( $parent_file );
1149
+ break;
1150
+ endif;
1151
+ endforeach;
1152
+ else:
1153
+ $parent_file = $this->fspath( $this->css->is_file_ok( $this->css->get_parent_source( $file . '.' . $ext ) ) );
1154
+ endif;
1155
+ // get child theme + file + ext ( passing empty string and full child path to theme_basename )
1156
+ $child_file = $this->css->get_child_target( $file . '.' . $ext );
1157
+ // return true if file already exists
1158
+ if ( $wp_filesystem->exists( $this->fspath( $child_file ) ) ) return TRUE;
1159
+ $child_dir = dirname( $this->theme_basename( '', $child_file ) );
1160
+ $this->debug( 'Verifying child dir... ', __FUNCTION__, __CLASS__ );
1161
+ if ( $parent_file // sanity check
1162
+ && $child_file // sanity check
1163
+ && $this->verify_child_dir( $child_dir ) //create child subdir if necessary
1164
+ && $wp_filesystem->copy( $parent_file, $this->fspath( $child_file ), FS_CHMOD_FILE ) ):
1165
+ $this->debug( 'Filesystem copy successful', __FUNCTION__, __CLASS__ );
1166
+ return TRUE;
1167
+ endif;
1168
+ $this->errors[] = __( 'Could not copy file:' . $parent_file, 'child-theme-configurator' );
1169
+ }
1170
+
1171
+ function delete_child_file( $file, $ext = 'php' ) {
1172
+ if ( !$this->fs ):
1173
+ $this->debug( 'No filesystem access.', __FUNCTION__, __CLASS__ );
1174
+ return FALSE; // return if no filesystem access
1175
+ endif;
1176
+ global $wp_filesystem;
1177
+ // verify file is in child theme and exists before removing.
1178
+ $file = ( 'img' == $ext ? $file : $file . '.' . $ext );
1179
+ if ( $child_file = $this->css->is_file_ok( $this->css->get_child_target( $file ), 'write' ) ):
1180
+ if ( $wp_filesystem->exists( $this->fspath( $child_file ) ) ):
1181
+ if ( $wp_filesystem->delete( $this->fspath( $child_file ) ) ):
1182
+ return TRUE;
1183
+ else:
1184
+ $this->errors[] = __( 'Could not delete ' . $ext . ' file.', 'child-theme-configurator' );
1185
+ $this->debug( 'Could not delete ' . $ext . ' file', __FUNCTION__, __CLASS__ );
1186
+ endif;
1187
+ endif;
1188
+ endif;
1189
+ }
1190
+
1191
+ function get_files( $theme, $type = 'template' ) {
1192
+ $isparent = ( $theme === $this->get( 'parnt' ) );
1193
+ if ( 'template' == $type && $isparent && ( $templates = $this->get( 'templates' ) ) ):
1194
+ return $templates;
1195
+ elseif ( !isset( $this->files[ $theme ] ) ):
1196
+
1197
+ $this->files[ $theme ] = array();
1198
+ $imgext = '(' . implode( '|', array_keys( $this->imgmimes ) ) . ')';
1199
+ foreach ( $this->css->recurse_directory(
1200
+ trailingslashit( get_theme_root() ) . $theme, '', TRUE ) as $filepath ):
1201
+ $file = $this->theme_basename( $theme, $filepath );
1202
+ if ( preg_match( "/^style\-(\d+)\.css$/", $file, $matches ) ):
1203
+ $date = date_i18n( 'D, j M Y g:i A', strtotime( $matches[ 1 ] ) );
1204
+ $this->files[ $theme ][ 'backup' ][ $file ] = $date;
1205
+ //$this->debug( 'This is a backup file', __FUNCTION__, __CLASS__ );
1206
+ elseif ( strstr( $file, "ctcbackup" ) ):
1207
+ $date = date_i18n( 'D, j M Y g:i A', filemtime( $filepath ) );
1208
+ $this->files[ $theme ][ 'backup' ][ $file ] = $date;
1209
+ elseif ( preg_match( "/^ctc\-plugins\-(\d+)\.css$/", $file, $matches ) ):
1210
+ $date = date_i18n( 'D, j M Y g:i A', strtotime( $matches[ 1 ] ) );
1211
+ $this->files[ $theme ][ 'pluginbackup' ][ $file ] = $date;
1212
+ //$this->debug( 'This is a plugin backup file', __FUNCTION__, __CLASS__ );
1213
+ elseif ( preg_match( "/\.php$/", $file ) ):
1214
+ if ( $isparent ):
1215
+
1216
+ if ( ( $file_verified = $this->css->is_file_ok( $this->css->get_parent_source( $file, $theme ) , 'read' ) ) ):
1217
+ $this->debug( 'scanning ' . $file_verified . '... ', __FUNCTION__, __CLASS__ );
1218
+ // read 2k at a time and bail if code detected
1219
+ $template = FALSE;
1220
+ if ( $handle = fopen( $file_verified, "rb") ):
1221
+ while ( !feof( $handle ) ) {
1222
+ $contents = fread($handle, 2048);
1223
+ if ( preg_match( "/\w+\s*\(/", $contents ) ):
1224
+ $template = TRUE;
1225
+ if ( preg_match( "/(function \w+?|require(_once)?)\s*\(/", $contents ) ):
1226
+ $template = FALSE;
1227
+ break;
1228
+ endif;
1229
+ endif;
1230
+ }
1231
+ fclose( $handle );
1232
+ endif;
1233
+ if ( $template )
1234
+ $this->files[ $theme ][ 'template' ][] = $file;
1235
+ endif;
1236
+ else:
1237
+ //$this->debug( 'Child PHP, adding to templates', __FUNCTION__, __CLASS__ );
1238
+ $this->files[ $theme ][ 'template' ][] = $file;
1239
+ endif;
1240
+ elseif ( preg_match( "/\.css$/", $file )
1241
+ && ( !in_array( $file, array(
1242
+ 'style.css',
1243
+ 'ctc-style.css',
1244
+ 'ctc-plugins.css'
1245
+ ) ) ) ):
1246
+ $this->files[ $theme ][ 'stylesheet' ][] = $file;
1247
+ //$this->debug( 'This is a stylesheet', __FUNCTION__, __CLASS__ );
1248
+ elseif ( preg_match( "/\.(js|txt)$/", $file ) ):
1249
+ $this->files[ $theme ][ 'txt' ][] = $file;
1250
+ elseif ( preg_match( "/^images\/.+?\." . $imgext . "$/", $file ) ):
1251
+ $this->files[ $theme ][ 'img' ][] = $file;
1252
+ //$this->debug( 'This is an image file', __FUNCTION__, __CLASS__ );
1253
+ else:
1254
+ $this->files[ $theme ][ 'other' ][] = $file;
1255
+ endif;
1256
+ endforeach;
1257
+ endif;
1258
+ if ( $isparent ):
1259
+ //$this->debug( 'Setting CSS object templates parameter', __FUNCTION__, __CLASS__ );
1260
+ $this->css->templates = $this->files[ $theme ][ 'template' ];
1261
+ endif;
1262
+ $types = explode( ",", $type );
1263
+ $files = array();
1264
+ foreach ( $types as $type ):
1265
+ if ( isset( $this->files[ $theme ][ $type ] ) )
1266
+ $files = array_merge( $this->files[ $theme ][ $type ], $files );
1267
+ endforeach;
1268
+ return $files;
1269
+ }
1270
+
1271
+ function theme_basename( $theme, $file ) {
1272
+ $file = $this->normalize_path( $file );
1273
+ // if no theme passed, returns theme + file
1274
+ $themedir = trailingslashit( $this->normalize_path( get_theme_root() ) ) . ( '' == $theme ? '' : trailingslashit( $theme ) );
1275
+ //$this->debug( 'Themedir: ' . $themedir . ' File: ' . $file , __FUNCTION__, __CLASS__ );
1276
+ return preg_replace( '%^' . preg_quote( $themedir ) . '%', '', $file );
1277
+ }
1278
+
1279
+ function uploads_basename( $file ) {
1280
+ $file = $this->normalize_path( $file );
1281
+ $uplarr = wp_upload_dir();
1282
+ $upldir = trailingslashit( $this->normalize_path( $uplarr[ 'basedir' ] ) );
1283
+ return preg_replace( '%^' . preg_quote( $upldir ) . '%', '', $file );
1284
+ }
1285
+
1286
+ function uploads_fullpath( $file ) {
1287
+ $file = $this->normalize_path( $file );
1288
+ $uplarr = wp_upload_dir();
1289
+ $upldir = trailingslashit( $this->normalize_path( $uplarr[ 'basedir' ] ) );
1290
+ return $upldir . $file;
1291
+ }
1292
+
1293
+ function serialize_postarrays() {
1294
+ foreach ( $this->postarrays as $field )
1295
+ if ( isset( $_POST[ $field ] ) && is_array( $_POST[ $field ] ) )
1296
+ $_POST[ $field ] = implode( "%%", $_POST[ $field ] );
1297
+ }
1298
+
1299
+ function unserialize_postarrays() {
1300
+ foreach ( $this->postarrays as $field )
1301
+ if ( isset( $_POST[ $field ] ) && !is_array( $_POST[ $field ] ) )
1302
+ $_POST[ $field ] = explode( "%%", $_POST[ $field ] );
1303
+ }
1304
+
1305
+ function set_writable( $file = NULL ) {
1306
+
1307
+ if ( isset( $file ) ):
1308
+ $file = $this->css->get_child_target( $file . '.php' );
1309
+ else:
1310
+ $file = apply_filters( 'chld_thm_cfg_target', $this->css->get_child_target( 'separate' == $this->get( 'handling' ) ? 'ctc-style.css' : 'style.css' ), $this->css );
1311
+ endif;
1312
+ if ( $this->fs ): // filesystem access
1313
+ if ( is_writable( $file ) ) return;
1314
+ global $wp_filesystem;
1315
+ if ( $file && $wp_filesystem->chmod( $this->fspath( $file ), 0666 ) ) return;
1316
+ endif;
1317
+ $this->errors[] = __( 'Could not set write permissions.', 'child-theme-configurator' );
1318
+ add_action( 'admin_notices', array( $this, 'writable_notice' ) );
1319
+ return FALSE;
1320
+ }
1321
+
1322
+ function clone_child_theme( $child, $clone ) {
1323
+ if ( !$this->fs ) return FALSE; // return if no filesystem access
1324
+ global $wp_filesystem;
1325
+ // set child theme if not set for get_child_target to use new child theme as source
1326
+ $this->css->set_prop( 'child', $child );
1327
+
1328
+ $dir = untrailingslashit( $this->css->get_child_target( '' ) );
1329
+ $themedir = trailingslashit( get_theme_root() );
1330
+ $fsthemedir = $this->fspath( $themedir );
1331
+ $files = $this->css->recurse_directory( $dir, NULL, TRUE );
1332
+ $errors = array();
1333
+ foreach ( $files as $file ):
1334
+ $childfile = $this->theme_basename( $child, $this->normalize_path( $file ) );
1335
+ $newfile = trailingslashit( $clone ) . $childfile;
1336
+ $childpath = $fsthemedir . trailingslashit( $child ) . $childfile;
1337
+ $newpath = $fsthemedir . $newfile;
1338
+ $this->debug( 'Verifying child dir... ', __FUNCTION__, __CLASS__ );
1339
+ if ( $this->verify_child_dir( is_dir( $file ) ? $newfile : dirname( $newfile ) ) ):
1340
+ if ( is_file( $file ) && !@$wp_filesystem->copy( $childpath, $newpath ) ):
1341
+ $errors[] = 'could not copy ' . $newpath;
1342
+ endif;
1343
+ else:
1344
+ $errors[] = 'invalid dir: ' . $newfile;
1345
+ endif;
1346
+ endforeach;
1347
+ }
1348
+
1349
+ function unset_writable() {
1350
+ if ( !$this->fs ) return FALSE; // return if no filesystem access
1351
+ global $wp_filesystem;
1352
+ $dir = untrailingslashit( $this->css->get_child_target( '' ) );
1353
+ $child = $this->theme_basename( '', $dir );
1354
+ $newchild = untrailingslashit( $child ) . '-new';
1355
+ $themedir = trailingslashit( get_theme_root() );
1356
+ $fsthemedir = $this->fspath( $themedir );
1357
+ // is child theme owned by user?
1358
+ if ( fileowner( $dir ) == fileowner( $themedir ) ):
1359
+ $copy = FALSE;
1360
+ $wp_filesystem->chmod( $dir );
1361
+ // recursive chmod ( as user )
1362
+ // WP_Filesystem RECURSIVE CHMOD IS FLAWED! IT SETS ALL CHILDREN TO PERM OF OUTERMOST DIR
1363
+ //if ( $wp_filesystem->chmod( $this->fspath( $dir ), FALSE, TRUE ) ):
1364
+ //endif;
1365
+ else:
1366
+ $copy = TRUE;
1367
+ endif;
1368
+ // n -> copy entire folder ( as user )
1369
+ $files = $this->css->recurse_directory( $dir, NULL, TRUE );
1370
+ $errors = array();
1371
+ foreach ( $files as $file ):
1372
+ $childfile = $this->theme_basename( $child, $this->normalize_path( $file ) );
1373
+ $newfile = trailingslashit( $newchild ) . $childfile;
1374
+ $childpath = $fsthemedir . trailingslashit( $child ) . $childfile;
1375
+ $newpath = $fsthemedir . $newfile;
1376
+ if ( $copy ):
1377
+ $this->debug( 'Verifying child dir... ' . $file, __FUNCTION__, __CLASS__ );
1378
+ if ( $this->verify_child_dir( is_dir( $file ) ? $newfile : dirname( $newfile ) ) ):
1379
+ if ( is_file( $file ) && !$wp_filesystem->copy( $childpath, $newpath ) ):
1380
+ $errors[] = 'could not copy ' . $newpath;
1381
+ endif;
1382
+ else:
1383
+ $errors[] = 'invalid dir: ' . $newfile;
1384
+ endif;
1385
+ else:
1386
+ $wp_filesystem->chmod( $this->fspath( $file ) );
1387
+ endif;
1388
+ endforeach;
1389
+ if ( $copy ):
1390
+ // verify copy ( as webserver )
1391
+ $newfiles = $this->css->recurse_directory( trailingslashit( $themedir ) . $newchild, NULL, TRUE );
1392
+ $deleteddirs = $deletedfiles = 0;
1393
+ if ( count( $newfiles ) == count( $files ) ):
1394
+ // rename old ( as webserver )
1395
+ if ( !$wp_filesystem->exists( trailingslashit( $fsthemedir ) . $child . '-old' ) )
1396
+ $wp_filesystem->move( trailingslashit( $fsthemedir ) . $child, trailingslashit( $fsthemedir ) . $child . '-old' );
1397
+ // rename new ( as user )
1398
+ if ( !$wp_filesystem->exists( trailingslashit( $fsthemedir ) . $child ) )
1399
+ $wp_filesystem->move( trailingslashit( $fsthemedir ) . $newchild, trailingslashit( $fsthemedir ) . $child );
1400
+ // remove old files ( as webserver )
1401
+ $oldfiles = $this->css->recurse_directory( trailingslashit( $themedir ) . $child . '-old', NULL, TRUE );
1402
+ array_unshift( $oldfiles, trailingslashit( $themedir ) . $child . '-old' );
1403
+ foreach ( array_reverse( $oldfiles ) as $file ):
1404
+ if ( $wp_filesystem->delete( $this->fspath( $file ) )
1405
+ || ( is_dir( $file ) && @rmdir( $file ) )
1406
+ || ( is_file( $file ) && @unlink( $file ) ) ):
1407
+ $deletedfiles++;
1408
+ endif;
1409
+ endforeach;
1410
+ if ( $deletedfiles != count( $oldfiles ) ):
1411
+ $errors[] = 'deleted: ' . $deletedfiles . ' != ' . count( $oldfiles ) . ' files';
1412
+ endif;
1413
+ else:
1414
+ $errors[] = 'newfiles != files';
1415
+ endif;
1416
+ endif;
1417
+ if ( count( $errors ) ):
1418
+ $this->errors[] = __( 'There were errors while resetting permissions.', 'child-theme-configurator' ) ;
1419
+ add_action( 'admin_notices', array( $this, 'writable_notice' ) );
1420
+ endif;
1421
+ }
1422
+
1423
+ function set_skip_form() {
1424
+ $this->skip_form = TRUE;
1425
+ }
1426
+
1427
+ function handle_file_upload( $field, $childdir = NULL, $mimes = NULL ){
1428
+ $uploadedfile = $_FILES[ $field ];
1429
+ $upload_overrides = array(
1430
+ 'test_form' => FALSE,
1431
+ 'mimes' => ( is_array( $mimes ) ? $mimes : NULL )
1432
+ );
1433
+ if ( ! function_exists( 'wp_handle_upload' ) ) require_once( ABSPATH . 'wp-admin/includes/file.php' );
1434
+ $movefile = wp_handle_upload( $uploadedfile, $upload_overrides );
1435
+ if ( isset( $movefile[ 'error' ] ) ):
1436
+ $this->errors[] = $movefile[ 'error' ];
1437
+ return FALSE;
1438
+ endif;
1439
+ $_POST[ 'movefile' ] = $this->uploads_basename( $movefile[ 'file' ] );
1440
+ }
1441
+
1442
+ function move_file_upload( $subdir = 'images' ) {
1443
+ if ( !$this->fs ) return FALSE; // return if no filesystem access
1444
+ global $wp_filesystem;
1445
+ $source_file = sanitize_text_field( $_POST[ 'movefile' ] );
1446
+ $target_file = ( '' == $subdir ?
1447
+ preg_replace( "%^.+(\.\w+)$%", "screenshot$1", basename( $source_file ) ) :
1448
+ trailingslashit( $subdir ) . basename( $source_file ) );
1449
+ $source_path = $this->uploads_fullpath( $source_file );
1450
+ $source_dir = dirname( $source_path );
1451
+ $mode = 0;
1452
+ if ( FALSE !== $this->verify_child_dir( trailingslashit( $this->get( 'child' ) ) . $subdir ) ):
1453
+
1454
+ if ( $target_path = $this->css->is_file_ok( $this->css->get_child_target( $target_file ), 'write' ) ):
1455
+ $fs_target_path = $this->fspath( $target_path );
1456
+ $fs_source_path = $this->fspath( $source_path );
1457
+ if ( $wp_filesystem->exists( $fs_source_path ) ):
1458
+ // in case source dir is not writable by wp_filesystem
1459
+ //$fs_source_dir = dirname( $fs_source_path );
1460
+ //if ( !$wp_filesystem->is_writable( $fs_source_dir ) ):
1461
+ // wp_filesystem->is_writable always returns true so just try chmod as webserver
1462
+ $mode = fileperms( $source_dir );
1463
+ if ( $mode ) :
1464
+ $writemode = $mode | 0666;
1465
+ if ( $set_perms = @chmod( $source_dir, $writemode ) )
1466
+ $this->debug( 'Changed source dir permissions from ' . substr( sprintf( '%o', $mode ), -4 ) . ' to ' . substr( sprintf( '%o', $writemode ), -4 ), __FUNCTION__ );
1467
+ endif;
1468
+ //endif;
1469
+ if ( @$wp_filesystem->move( $fs_source_path, $fs_target_path ) ):
1470
+ if ( $mode && $set_perms ):
1471
+ if ( @chmod( $source_dir, $mode ) )
1472
+ $this->debug( 'Reset source dir permissions to ' . substr( sprintf( '%o', $mode ), -4 ), __FUNCTION__ );
1473
+ endif;
1474
+ return TRUE;
1475
+ else:
1476
+ if ( $mode && $set_perms ):
1477
+ if ( @chmod( $source_dir, $mode ) )
1478
+ $this->debug( 'Reset source dir permissions to ' . substr( sprintf( '%o', $mode ), -4 ), __FUNCTION__ );
1479
+ endif;
1480
+ $this->debug( 'Could not move file from ' . $source_path . ' to ' . $target_file, __FUNCTION__ );
1481
+ endif;
1482
+ else:
1483
+ $this->debug( 'Source file does not exist: ' . $source_path, __FUNCTION__ );
1484
+ endif;
1485
+ else:
1486
+ $this->debug( 'Target file not OK: ' . $target_file, __FUNCTION__ );
1487
+ endif;
1488
+ else:
1489
+ $this->debug( 'Could not verify child dir', __FUNCTION__ );
1490
+ endif;
1491
+
1492
+ $this->errors[] = __( 'Could not upload file.', 'child-theme-configurator' );
1493
+ }
1494
+
1495
+ /**
1496
+ * exports theme as zip archive.
1497
+ * As of version 2.03, parent themes can be exported as well
1498
+ */
1499
+ function export_theme() {
1500
+ $version = '';
1501
+ if ( empty( $_POST[ 'ctc_export_theme' ] ) ):
1502
+ $template = $this->get( 'child' );
1503
+ $version = preg_replace( "%[^\w\.\-]%", '', $this->get( 'version' ) );
1504
+ else:
1505
+ $template = sanitize_text_field( $_POST[ 'ctc_export_theme' ] );
1506
+ if ( ( $theme = wp_get_theme( $template ) ) && is_object( $theme ) )
1507
+ $version = preg_replace( "%\.\d{10}$%", '', $theme->Version );
1508
+ endif;
1509
+ // make sure directory exists and is in themes folder
1510
+ if ( ( $dir = $this->css->is_file_ok( trailingslashit( get_theme_root() ) . $template, 'search' ) ) ):
1511
+ if ( $tmpdir = $this->get_tmp_dir() ):
1512
+ $file = trailingslashit( $tmpdir ) . $template . ( empty( $version ) ? '' : '-' . $version ) . '.zip';
1513
+ $this->export_zip_file( $file, $dir );
1514
+ else:
1515
+ return FALSE;
1516
+ endif;
1517
+ else:
1518
+ $this->errors = __( 'Invalid theme root directory.', 'child-theme-configurator' );
1519
+ endif;
1520
+ }
1521
+
1522
+ function get_tmp_dir(){
1523
+ // Try to use php system upload dir to store temp files first
1524
+ $tmpdir = ini_get( 'upload_tmp_dir' ) ? ini_get( 'upload_tmp_dir' ) : sys_get_temp_dir();
1525
+ if ( !is_writable( $tmpdir ) ):
1526
+ // try uploads directory
1527
+ $uploads = wp_upload_dir();
1528
+ $tmpdir = $uploads[ 'basedir' ];
1529
+ if ( !is_writable( $tmpdir ) ):
1530
+ $this->errors[] = __( 'No writable temp directory.', 'child-theme-configurator' );
1531
+ return FALSE;
1532
+ endif;
1533
+ endif;
1534
+ return $tmpdir;
1535
+ }
1536
+
1537
+ function export_zip_file( $file, $source ) {
1538
+ if ( file_exists( $file ) ) unlink ( $file );
1539
+
1540
+ mbstring_binary_safe_encoding();
1541
+
1542
+ // PclZip ships with WordPress
1543
+ require_once( ABSPATH . 'wp-admin/includes/class-pclzip.php' );
1544
+
1545
+ $archive = new PclZip( $file );
1546
+ if ( $response = $archive->create( $source, PCLZIP_OPT_REMOVE_PATH, dirname( $source ) ) ):
1547
+
1548
+ reset_mbstring_encoding();
1549
+ header( 'Content-Description: File Transfer' );
1550
+ header( 'Content-Type: application/octet-stream' );
1551
+ header( 'Content-Length: ' . filesize( $file ) );
1552
+ header( 'Content-Disposition: attachment; filename=' . basename( $file ) );
1553
+ header( 'Expires: 0' );
1554
+ header( 'Cache-Control: must-revalidate' );
1555
+ header( 'Pragma: public' );
1556
+ readfile( $file );
1557
+ unlink( $file );
1558
+ die();
1559
+ else:
1560
+ $this->errors[] = __( 'PclZip returned zero bytes.', 'child-theme-configurator' );
1561
+ endif;
1562
+ }
1563
+ /*
1564
+ *
1565
+ */
1566
+ function verify_creds( $args = array() ) {
1567
+ $this->fs_prompt = $this->fs = FALSE;
1568
+ //fs prompt does not support arrays as post data - serialize arrays
1569
+ $this->serialize_postarrays();
1570
+ // generate callback url
1571
+ $ctcpage = apply_filters( 'chld_thm_cfg_admin_page', CHLD_THM_CFG_MENU );
1572
+ $url = is_multisite() ? network_admin_url( 'themes.php?page=' . $ctcpage ) :
1573
+ admin_url( 'tools.php?page=' . $ctcpage );
1574
+ $nonce_url = wp_nonce_url( $url, apply_filters( 'chld_thm_cfg_action', 'ctc_update' ), '_wpnonce' );
1575
+ // buffer output so we can process prior to http header
1576
+ ob_start();
1577
+ if ( $creds = request_filesystem_credentials( $nonce_url, '', FALSE, FALSE, $args ) ):
1578
+ // check filesystem permission if direct or ftp creds exist
1579
+ if ( WP_Filesystem( $creds ) )
1580
+ // login ok
1581
+ $this->fs = TRUE;
1582
+ else
1583
+ // incorrect credentials, get form with error flag
1584
+ $creds = request_filesystem_credentials( $nonce_url, '', TRUE, FALSE, $args );
1585
+ else:
1586
+ // no credentials, initialize unpriveledged filesystem object
1587
+ WP_Filesystem();
1588
+ endif;
1589
+ // if form was generated, store it
1590
+ $this->fs_prompt = ob_get_contents();
1591
+ // now we can read/write if fs is TRUE otherwise fs_prompt will contain form
1592
+ ob_end_clean();
1593
+ //fs prompt does not support arrays as post data - unserialize arrays
1594
+ $this->unserialize_postarrays();
1595
+ }
1596
+
1597
+ /*
1598
+ * convert 'direct' filepath into wp_filesystem filepath
1599
+ */
1600
+ function fspath( $file ){
1601
+ if ( ! $this->fs ) return FALSE; // return if no filesystem access
1602
+ global $wp_filesystem;
1603
+ if ( is_dir( $file ) ):
1604
+ $dir = $file;
1605
+ $base = '';
1606
+ else:
1607
+ $dir = dirname( $file );
1608
+ $base = basename( $file );
1609
+ endif;
1610
+ $fsdir = $wp_filesystem->find_folder( $dir );
1611
+ return trailingslashit( $fsdir ) . $base;
1612
+ }
1613
+
1614
+ // backwards compatability < WP 3.9
1615
+ function normalize_path( $path ) {
1616
+ $path = str_replace( '\\', '/', $path );
1617
+ // accommodates windows NT paths without C: prefix
1618
+ $path = substr( $path, 0, 1 ) . preg_replace( '|/+|','/', substr( $path, 1 ) );
1619
+ if ( ':' === substr( $path, 1, 1 ) )
1620
+ $path = ucfirst( $path );
1621
+ return $path;
1622
+ }
1623
+
1624
+ // case insensitive theme search
1625
+ function check_theme_exists( $theme ) {
1626
+ $search_array = array_map( 'strtolower', array_keys( wp_get_themes() ) );
1627
+ return in_array( strtolower( $theme ), $search_array );
1628
+ }
1629
+
1630
+ // helper functions to support legacy plugin extension
1631
+ function is_legacy() {
1632
+ return defined('CHLD_THM_CFG_PLUGINS_VERSION')
1633
+ && version_compare( CHLD_THM_CFG_PLUGINS_VERSION, '2.0.0', '<' );
1634
+ }
1635
+
1636
+ /* not using plugin mode */
1637
+ function is_theme( $configtype = '' ) {
1638
+ // if filter returns a value, we are using plugin mode
1639
+ // otherwise if configtype has a value and it is not a theme then we are in legacy plugin mode
1640
+ $pluginmode = apply_filters( 'chld_thm_cfg_action', NULL );
1641
+ if ( $pluginmode || ( !empty( $configtype ) && 'theme' != $configtype ) ):
1642
+ return FALSE;
1643
+ endif;
1644
+ if ( $this->is_legacy()
1645
+ && is_object( $this->css )
1646
+ && ( $configtype = $this->get( 'configtype' ) )
1647
+ && !empty( $configtype ) && 'theme' != $configtype ):
1648
+ return FALSE;
1649
+ endif;
1650
+ return TRUE;
1651
+ }
1652
+
1653
+ /* returns parent theme either from existing config or passed as post var */
1654
+ function get_current_parent() {
1655
+ // check if child was passed and use Template value
1656
+ //if ( isset( $_GET[ 'ctc_theme_child' ] ) && ( $child = sanitize_text_field( $_GET[ 'ctc_theme_child' ] ) ) )
1657
+ // return $this->themes[ 'child' ][ $child ][ 'Template' ];
1658
+ // otherwise check if parent was passed
1659
+ //if ( isset( $_GET[ 'ctc_theme_parnt' ] ) && ( $parent = sanitize_text_field( $_GET[ 'ctc_theme_parnt' ] ) ) )
1660
+ // return $parent;
1661
+ // otherwise use css object value
1662
+ //else
1663
+ if ( $parent = $this->get( 'parnt' ) )
1664
+ return $parent;
1665
+ // otherwise use template value
1666
+ else return get_template();
1667
+ }
1668
+
1669
+ /* returns child theme either from existing config or passed as post var */
1670
+ function get_current_child() {
1671
+ // check if parent was passed
1672
+ //if ( isset( $_GET[ 'ctc_theme_child' ] ) && ( $child = sanitize_text_field( $_GET[ 'ctc_theme_child' ] ) ) )
1673
+ // return $child;
1674
+ // otherwise use css object value
1675
+ //else
1676
+ if ( $child = $this->get( 'child' ) )
1677
+ return $child;
1678
+ // otherwise use stylesheet value
1679
+ else return get_stylesheet();
1680
+ }
1681
+
1682
+ function toggle_debug() {
1683
+ $debug = '';
1684
+ if ( $_POST[ 'ctc_is_debug' ] ):
1685
+ $this->is_debug = 1;
1686
+ else:
1687
+ $this->is_debug = 0;
1688
+ endif;
1689
+ update_option( CHLD_THM_CFG_OPTIONS . '_debug', $this->is_debug, FALSE );
1690
+ delete_site_transient( CHLD_THM_CFG_OPTIONS . '_debug' );
1691
+ }
1692
+
1693
+ function debug( $msg = NULL, $fn = NULL, $cl = NULL ) {
1694
+ if ( $this->is_debug )
1695
+ $this->debug .= ( isset( $cl ) ? $cl . '::' : '' ) . ( isset( $fn ) ? $fn . ' -- ' : '' ) . ( isset( $msg ) ? $msg . LF : '' );
1696
+ }
1697
+
1698
+ function log_debug() {
1699
+ $this->debug( '*** END OF REQUEST ***', __FUNCTION__, __CLASS__ );
1700
+ // save debug data for 1 hour
1701
+ set_site_transient( CHLD_THM_CFG_OPTIONS . '_debug', $this->debug, 3600 );
1702
+ }
1703
+ function get_debug() {
1704
+ return get_site_transient( CHLD_THM_CFG_OPTIONS . '_debug' ) . LF . $this->debug;
1705
+ }
1706
+ function cache_debug() {
1707
+ $this->debug( '*** END OF REQUEST ***', __FUNCTION__, __CLASS__ );
1708
+ $this->updates[] = array(
1709
+ 'obj' => 'debug',
1710
+ 'key' => '',
1711
+ 'data' => $this->debug,
1712
+ );
1713
+ }
1714
+ function parse_parent_stylesheet_to_source() {
1715
+ $this->css->parse_css_file( 'parnt' );
1716
+ }
1717
+
1718
+ function parse_child_stylesheet_to_source() {
1719
+ $this->css->parse_css_file( 'child', 'style.css', 'parnt' );
1720
+ }
1721
+
1722
+ function parse_child_stylesheet_to_target() {
1723
+ $this->css->parse_css_file( 'child', 'style.css' );
1724
+ }
1725
+
1726
+ function parse_custom_stylesheet_to_target() {
1727
+ $this->css->parse_css_file( 'child', 'ctc-style.css' );
1728
+ }
1729
+
1730
+ function parse_genesis_stylesheet_to_source() {
1731
+ $this->css->parse_css_file( 'child', 'ctc-genesis.css', 'parnt' );
1732
+ }
1733
+
1734
+ function parse_additional_stylesheets_to_source() {
1735
+ // parse additional stylesheets
1736
+ foreach ( $this->css->addl_css as $file ):
1737
+ //$file = sanitize_text_field( $file );
1738
+ $this->css->parse_css_file( 'parnt', $file );
1739
+ endforeach;
1740
+ $this->debug( print_r( $this->css->addl_css, TRUE ), __FUNCTION__, __CLASS__ );
1741
+ //endif;
1742
+ }
1743
+
1744
+ function reset_child_theme() {
1745
+ $parnt = $this->get( 'parnt' );
1746
+ $child = $this->get( 'child' );
1747
+ $name = $this->get( 'child_name' );
1748
+ $this->css = new ChildThemeConfiguratorCSS();
1749
+ $this->css->set_prop( 'parnt', $parnt );
1750
+ $this->css->set_prop( 'child', $child );
1751
+ $this->css->set_prop( 'child_name', $name );
1752
+ $this->css->set_prop( 'enqueue', 'enqueue' );
1753
+ $this->backup_or_restore_file( 'header.php', TRUE );
1754
+ $this->delete_child_file( 'header.ctcbackup', 'php' );
1755
+ $this->backup_or_restore_file( 'style.css', TRUE );
1756
+ $this->delete_child_file( 'style.ctcbackup', 'css' );
1757
+ $this->backup_or_restore_file( 'ctc-style.css', TRUE );
1758
+ $this->delete_child_file( 'ctc-style.ctcbackup', 'css' );
1759
+ }
1760
+
1761
+ // we can copy settings from parent to child even if neither is currently active
1762
+ // so we need cases for active parent, active child or neither
1763
+ function copy_theme_mods( $from, $to ) {
1764
+ if ( strlen( $from ) && strlen( $to ) ):
1765
+ $this->set_theme_mods( $to, $this->get_theme_mods( $from ) );
1766
+ endif;
1767
+ }
1768
+
1769
+
1770
+ function get_theme_mods( $theme ){
1771
+ // get active theme
1772
+ $active_theme = get_stylesheet();
1773
+ // create temp array from parent settings
1774
+ $mods = get_option( 'theme_mods_' . $theme );
1775
+ if ( $active_theme == $theme ):
1776
+ $this->debug( 'from is active, using active widgets', __FUNCTION__, __CLASS__ );
1777
+ // if parent theme is active, get widgets from active sidebars_widgets array
1778
+ $mods[ 'sidebars_widgets' ][ 'data' ] = retrieve_widgets();
1779
+ else:
1780
+ $this->debug( 'from not active, using theme mods widgets', __FUNCTION__, __CLASS__ );
1781
+ // otherwise get widgets from parent theme mods
1782
+ $mods[ 'sidebars_widgets' ][ 'data' ] = empty( $mods[ 'sidebars_widgets' ][ 'data' ] ) ?
1783
+ array( 'wp_inactive_widgets' => array() ) : $mods[ 'sidebars_widgets' ][ 'data' ];
1784
+ endif;
1785
+ return $mods;
1786
+ }
1787
+
1788
+ function set_theme_mods( $theme, $mods ){
1789
+ $active_theme = get_stylesheet();
1790
+ $widgets = $mods[ 'sidebars_widgets' ][ 'data' ];
1791
+ if ( $active_theme == $theme ):
1792
+ $this->debug( 'to active, setting active widgets', __FUNCTION__, __CLASS__ );
1793
+ // copy widgets to active sidebars_widgets array
1794
+ wp_set_sidebars_widgets( $mods[ 'sidebars_widgets' ][ 'data' ] );
1795
+ // if child theme is active, remove widgets from temp array
1796
+ unset( $mods[ 'sidebars_widgets' ] );
1797
+ else:
1798
+ $this->debug( 'child not active, saving widgets in theme mods', __FUNCTION__, __CLASS__ );
1799
+ // otherwise copy widgets to temp array with time stamp
1800
+ // array value is already set
1801
+ //$mods[ 'sidebars_widgets' ][ 'data' ] = $widgets;
1802
+ $mods[ 'sidebars_widgets' ][ 'time' ] = time();
1803
+ endif;
1804
+ //$this->debug( 'saving child theme mods:' . LF . print_r( $mods, TRUE ), __FUNCTION__, __CLASS__ );
1805
+ // copy temp array to child mods
1806
+ update_option( 'theme_mods_' . $theme, $mods );
1807
+ }
1808
+
1809
+ function network_enable() {
1810
+ if ( $child = $this->get( 'child' ) ):
1811
+ $allowed_themes = get_site_option( 'allowedthemes' );
1812
+ $allowed_themes[ $child ] = true;
1813
+ update_site_option( 'allowedthemes', $allowed_themes );
1814
+ endif;
1815
+ }
1816
+
1817
+ function backup_or_restore_file( $source, $restore = FALSE, $target = NULL ){
1818
+ $action = $restore ? 'Restore' : 'Backup';
1819
+ $this->debug( LF . LF . $action . ' main stylesheet...', __FUNCTION__, __CLASS__ );
1820
+ if ( !$this->fs ):
1821
+ $this->debug( 'No filesystem access, returning', __FUNCTION__, __CLASS__ );
1822
+ return FALSE; // return if no filesystem access
1823
+ endif;
1824
+ list( $base, $suffix ) = explode( '.', $source );
1825
+ if ( empty( $target ) )
1826
+ $target = $base . '.ctcbackup.' . $suffix;
1827
+ if ( $restore ):
1828
+ $source = $target;
1829
+ $target = $base . '.' . $suffix;
1830
+ endif;
1831
+ $fstarget = $this->fspath( $this->css->get_child_target( $target ) );
1832
+ $fssource = $this->fspath( $this->css->get_child_target( $source ) );
1833
+ global $wp_filesystem;
1834
+ if ( ( !$wp_filesystem->exists( $fssource ) ) || ( !$restore && $wp_filesystem->exists( $fstarget ) ) ):
1835
+ $this->debug( 'No stylesheet, returning', __FUNCTION__, __CLASS__ );
1836
+ return FALSE;
1837
+ endif;
1838
+ if ( $wp_filesystem->copy( $fssource, $fstarget, FS_CHMOD_FILE ) ):
1839
+ $this->debug( 'Filesystem ' . $action . ' successful', __FUNCTION__, __CLASS__ );
1840
+ return TRUE;
1841
+ else:
1842
+ $this->debug( 'Filesystem ' . $action . ' failed', __FUNCTION__, __CLASS__ );
1843
+ return FALSE;
1844
+ endif;
1845
+ }
1846
+
1847
+ function rewrite_stylesheet_header(){
1848
+ $this->debug( LF . LF . 'Rewriting main stylesheet header...', __FUNCTION__, __CLASS__ );
1849
+ if ( !$this->fs ):
1850
+ $this->debug( 'No filesystem access, returning', __FUNCTION__, __CLASS__ );
1851
+ return FALSE; // return if no filesystem access
1852
+ endif;
1853
+ $origcss = $this->css->get_child_target( 'style.css' );
1854
+ $fspath = $this->fspath( $origcss );
1855
+ global $wp_filesystem;
1856
+ if( !$wp_filesystem->exists( $fspath ) ):
1857
+ $this->debug( 'No stylesheet, returning', __FUNCTION__, __CLASS__ );
1858
+ return FALSE;
1859
+ endif;
1860
+ // get_contents_array returns extra linefeeds so just split it ourself
1861
+ $contents = $wp_filesystem->get_contents( $fspath );
1862
+ $child_headers = $this->css->get_css_header();
1863
+ if ( is_array( $child_headers ) )
1864
+ $regex = implode( '|', array_map( 'preg_quote', array_keys( $child_headers ) ) );
1865
+ else $regex = 'NO HEADERS';
1866
+ $regex = '/(' . $regex . '):.*$/';
1867
+ $this->debug( 'regex: ' . $regex, __FUNCTION__, __CLASS__ );
1868
+ $header = str_replace( "\r", LF, substr( $contents, 0, 8192 ) );
1869
+ $contents = substr( $contents, 8192 );
1870
+ $this->debug( 'original header: ' . LF . substr( $header, 0, 1024 ), __FUNCTION__, __CLASS__ );
1871
+ //$this->debug( 'stripping @import rules...', __FUNCTION__, __CLASS__ );
1872
+ // strip out existing @import lines
1873
+ $header = preg_replace( '#\@import\s+url\(.+?\);\s*#s', '', $header );
1874
+ // parse header line by line
1875
+ $headerdata = explode( "\n", $header );
1876
+ $in_comment = 0;
1877
+ $found_header = 0;
1878
+ $headerdone = 0;
1879
+ $newheader = '';
1880
+ if ( $headerdata ):
1881
+ $this->debug( 'parsing header...', __FUNCTION__, __CLASS__ );
1882
+ foreach ( $headerdata as $n => $headerline ):
1883
+ preg_match_all("/(\*\/|\/\*)/", $headerline, $matches );
1884
+ if ( $matches ):
1885
+ foreach ( $matches[1] as $token ):
1886
+ if ( '/*' == $token ):
1887
+ $in_comment = 1;
1888
+ elseif ( '*/' == $token ):
1889
+ $in_comment = 0;
1890
+ endif;
1891
+ endforeach;
1892
+ endif;
1893
+ if ( $in_comment ):
1894
+ $this->debug( 'in comment', __FUNCTION__, __CLASS__ );
1895
+ if ( preg_match( $regex, $headerline, $matches ) && !empty( $matches[ 1 ] ) ):
1896
+ $found_header = 1;
1897
+ $key = $matches[ 1 ];
1898
+ $this->debug( 'found header: ' . $key, __FUNCTION__, __CLASS__ );
1899
+ if ( array_key_exists( $key, $child_headers ) ):
1900
+ $this->debug( 'child header value exists: ', __FUNCTION__, __CLASS__ );
1901
+ $value = trim( $child_headers[ $key ] );
1902
+ unset( $child_headers[ $key ] );
1903
+ if ( $value ):
1904
+ $this->debug( 'setting ' . $key . ' to ' . $value, __FUNCTION__, __CLASS__ );
1905
+ $count = 0;
1906
+ $headerline = preg_replace(
1907
+ $regex,
1908
+ ( empty( $value ) ? '' : $key . ': ' . $value ),
1909
+ $headerline
1910
+ );
1911
+ else:
1912
+ $this->debug( 'removing ' . $key, __FUNCTION__, __CLASS__ );
1913
+ continue;
1914
+ endif;
1915
+ endif;
1916
+ endif;
1917
+ $newheader .= $headerline . LF;
1918
+ elseif ( $found_header && !$headerdone ): // we have gone in and out of header block; insert any remaining parameters
1919
+ //$this->debug( 'not in comment and after header', __FUNCTION__, __CLASS__ );
1920
+ foreach ( $child_headers as $key => $value ):
1921
+ $this->debug( 'inserting ' . $key . ': ' . $value, __FUNCTION__, __CLASS__ );
1922
+ if ( empty( $value ) ) continue;
1923
+ $newheader .= $key . ': ' . trim( $value ) . "\n";
1924
+ endforeach;
1925
+ // if importing parent, add after this line
1926
+ $newheader .= $headerline . "\n" . $this->css->get_css_imports();
1927
+ $headerdone = 1;
1928
+ else:
1929
+ //$this->debug( 'not in comment', __FUNCTION__, __CLASS__ );
1930
+ $newheader .= $headerline . LF;
1931
+ endif;
1932
+ endforeach;
1933
+ $this->debug( 'new header: ' . LF . substr( $newheader, 0, 1024 ), __FUNCTION__, __CLASS__ );
1934
+ if ( !$found_header ) return FALSE;
1935
+ endif;
1936
+ $contents = $newheader . $contents;
1937
+ if ( FALSE === $wp_filesystem->put_contents( $fspath, $contents ) ):
1938
+ //$this->debug( 'Filesystem write to ' . $fspath . ' failed.', __FUNCTION__, __CLASS__ );
1939
+ else:
1940
+ //$this->debug( 'Filesystem write to ' . $fspath . ' successful.', __FUNCTION__, __CLASS__ );
1941
+ endif;
1942
+ //die( '<pre><code>' . $contents . '</code></pre>');
1943
+ }
1944
+
1945
+ function max_styles_notice() {
1946
+ $this->ui->render_notices( 'max_styles' );
1947
+ }
1948
+
1949
+ function config_notice() {
1950
+ $this->ui->render_notices( 'config' );
1951
+ }
1952
+
1953
+ function writable_notice() {
1954
+ $this->ui->render_notices( 'writable' );
1955
+ }
1956
+
1957
+ function enqueue_notice() {
1958
+ $this->ui->render_notices( 'enqueue' );
1959
+ }
1960
+
1961
+ function owner_notice() {
1962
+ $this->ui->render_notices( 'owner' );
1963
+ }
1964
+
1965
+ function changed_notice() {
1966
+ $this->ui->render_notices( 'changed' );
1967
+ }
1968
+
1969
+ function upgrade_notice() {
1970
+ $this->ui->render_notices( 'upgrade' );
1971
+ }
1972
+
1973
+ function get_child_stylesheet() {
1974
+ $handling = $this->get( 'handling' );
1975
+ if ( 'separate' == $handling )
1976
+ return 'ctc-style.css';
1977
+ elseif ( 'reset' == $this->childtype )
1978
+ return FALSE;
1979
+ else
1980
+ return 'style.css';
1981
+ }
1982
+ /**
1983
+ * for themes with hard-coded stylesheets,
1984
+ * change references to stylesheet_uri to template_directory_uri
1985
+ * and move wp_head to end of head if possible
1986
+ */
1987
+ function repair_header() {
1988
+ // return if no flaws detected
1989
+ if ( ! $this->get( 'cssunreg' ) && !$this->get( 'csswphead' ) ) return;
1990
+ $this->debug( 'repairing parent header', __FUNCTION__, __CLASS__ );
1991
+ // try to copy from parent
1992
+ $this->copy_parent_file( 'header' );
1993
+ // try to backup child header template
1994
+ $this->backup_or_restore_file( 'header.php' );
1995
+ // fetch current header template
1996
+ global $wp_filesystem;
1997
+ $cssstr = "get_template_directory_uri()";
1998
+ $wphstr = '<?php // MODIFIED BY CTC' . LF . 'wp_head();' . LF . '?>' . LF . '</head>';
1999
+ $filename = $this->css->get_child_target( 'header.php' );
2000
+ $contents = $wp_filesystem->get_contents( $this->fspath( $filename ) );
2001
+
2002
+ // change hard-wired stylesheet link so it loads parent theme instead
2003
+ if ( $this->get( 'cssunreg' ) || $this->get( 'csswphead' ) ):
2004
+ $repairs = 0;
2005
+ $contents = preg_replace( "#(get_bloginfo\(\s*['\"]stylesheet_url['\"]\s*\)|get_stylesheet_uri\(\s*\))#s", $cssstr . ' . "/style.css"', $contents, -1, $count );
2006
+ $repairs += $count;
2007
+ $contents = preg_replace( "#([^_])bloginfo\(\s*['\"]stylesheet_url['\"]\s*\)#s", "$1echo " . $cssstr . ' . "/style.css"', $contents, -1, $count );
2008
+ $repairs += $count;
2009
+ $contents = preg_replace( "#([^_])bloginfo\(\s*['\"]stylesheet_directory['\"]\s*\)#s", "$1echo " . $cssstr, $contents, -1, $count );
2010
+ $repairs += $count;
2011
+ $contents = preg_replace( "#(trailingslashit\()?(\s*)get_stylesheet_directory_uri\(\s*\)(\s*\))?\s*\.\s*['\"]\/?([\w\-\.\/]+?)\.css['\"]#s",
2012
+ "$2echo $cssstr . '$3.css'", $contents, -1, $count );
2013
+ $repairs += $count;
2014
+ if ( $repairs )
2015
+ $this->css->set_prop( 'parntloaded', TRUE );
2016
+ endif;
2017
+
2018
+ // put wp_head() call at the end of <head> section where it belongs
2019
+ if ( $this->get( 'csswphead' ) ):
2020
+ $contents = preg_replace( "#wp_head\(\s*\)\s*;#s", '', $contents );
2021
+ $contents = preg_replace( "#</head>#s", $wphstr, $contents );
2022
+ $contents = preg_replace( "#\s*<\?php\s*\?>\s*#s", LF, $contents ); // clean up
2023
+ endif;
2024
+
2025
+ // write new header template to child theme
2026
+ $this->debug( 'Writing to filesystem: ' . $filename . LF . $contents, __FUNCTION__, __CLASS__ );
2027
+ if ( FALSE === $wp_filesystem->put_contents( $this->fspath( $filename ), $contents ) ):
2028
+ $this->debug( 'Filesystem write failed, returning.', __FUNCTION__, __CLASS__ );
2029
+ return FALSE;
2030
+ endif;
2031
+ //die( '<textarea>' . $contents . '</textarea>' );
2032
+ }
2033
+
2034
+ /**
2035
+ * Evaluate signals collected from theme preview and set configuration accordingly
2036
+ */
2037
+ function evaluate_signals() {
2038
+ if ( !isset( $_POST[ 'ctc_analysis' ] ) ) return;
2039
+ $analysis = json_decode( urldecode( $_POST[ 'ctc_analysis' ] ) );
2040
+ //die( print_r( $analysis, TRUE ) );
2041
+ // stylesheets loaded outside wp_styles queue
2042
+ $unregs = array( 'thm_past_wphead', 'thm_unregistered', 'dep_unregistered', 'css_past_wphead', 'dep_past_wphead' );
2043
+ //echo '<pre><code>' . print_r( $analysis, TRUE ) . "</code></pre>\n";
2044
+
2045
+ // if this is a self-contained child theme ( e.g., Genesis ) use child as baseline
2046
+ $baseline = $this->get( 'ignoreparnt' ) ? 'child' : 'parnt';
2047
+ $this->debug( 'baseline: ' . $baseline, __FUNCTION__, __CLASS__ );
2048
+
2049
+ $this->css->parnt_deps = array();
2050
+ $this->css->child_deps = array();
2051
+ $this->css->addl_css = array();
2052
+
2053
+ // store imported parent stylesheets so they are parsed
2054
+ if ( isset( $analysis->parnt->imports ) ):
2055
+ foreach ( $analysis->parnt->imports as $import ):
2056
+ if ( preg_match( '%(https?:)?//%', $import ) ) continue; // ignore external links
2057
+ $this->css->addl_css[] = sanitize_text_field( $import );
2058
+ endforeach;
2059
+ endif;
2060
+
2061
+ // store stylesheet dependencies
2062
+ if ( isset( $analysis->{ $baseline } ) ):
2063
+ if ( isset( $analysis->{ $baseline }->deps ) ):
2064
+ foreach ( $analysis->{ $baseline }->deps[ 0 ] as $deparray ):
2065
+ if ( !in_array( $deparray[ 0 ], $unregs ) ):
2066
+ $this->css->parnt_deps[] = $deparray[ 0 ];
2067
+ endif;
2068
+ if ( !preg_match( "/^style([\-\.]min)?\.css$/", $deparray[ 1 ] ) ):
2069
+ // bootstrap wastes memory among other resources
2070
+ //if ( !preg_match( "/bootstrap/i", $deparray[ 0 ] ) && !preg_match( "/bootstrap/i", $deparray[ 1 ] ) )
2071
+ $this->css->addl_css[] = sanitize_text_field( $deparray[ 1 ] );
2072
+ endif;
2073
+ endforeach;
2074
+ foreach ( $analysis->{ $baseline }->deps[ 1 ] as $deparray ):
2075
+ if ( !in_array( $deparray[ 0 ], $unregs ) ):
2076
+ $this->css->child_deps[] = $deparray[ 0 ];
2077
+ endif;
2078
+ if ( 'separate' == $this->get( 'handling' ) || !empty( $analysis->{ $baseline }->signals->ctc_child_loaded ) ):
2079
+ if ( !preg_match( "/^style([\-\.]min)?\.css$/", $deparray[ 1 ] ) ):
2080
+ //if ( !preg_match( "/bootstrap/", $deparray[ 0 ] ) && !preg_match( "/bootstrap/", $deparray[ 1 ] ) )
2081
+ $this->css->addl_css[] = sanitize_text_field( $deparray[ 1 ] );
2082
+ endif;
2083
+ endif;
2084
+ endforeach;
2085
+ endif;
2086
+ endif;
2087
+ // store parent theme signals
2088
+ if ( isset( $analysis->{ $baseline }->signals ) ):
2089
+ $this->css->set_prop( 'hasstyles', isset( $analysis->{ $baseline }->signals->thm_no_styles ) ? 0 : 1 );
2090
+ $this->css->set_prop( 'csswphead', isset( $analysis->{ $baseline }->signals->thm_past_wphead ) ? 1 : 0 );
2091
+ $this->css->set_prop( 'cssunreg', isset( $analysis->{ $baseline }->signals->thm_unregistered ) ? 1 : 0 );
2092
+ if ( isset( $analysis->{ $baseline }->signals->thm_parnt_loaded ) ):
2093
+ $this->set_enqueue_priority( $analysis, $baseline );
2094
+ endif;
2095
+ endif;
2096
+ if ( isset( $analysis->child->signals ) ):
2097
+ // test these again for child theme
2098
+ $this->css->set_prop( 'csswphead', isset( $analysis->child->signals->thm_past_wphead ) ? 1 : 0 );
2099
+ $this->css->set_prop( 'cssunreg', isset( $analysis->child->signals->thm_unregistered ) ? 1 : 0 );
2100
+ // special case where theme does not link child stylesheet at all
2101
+ $this->css->set_prop( 'cssnotheme', isset( $analysis->child->signals->thm_notheme ) ? 1 : 0 );
2102
+ if ( isset( $analysis->child->signals->thm_child_loaded ) ):
2103
+ $this->css->set_prop( 'childloaded', $analysis->child->signals->thm_child_loaded );
2104
+ $this->set_enqueue_priority( $analysis, 'child' );
2105
+ else:
2106
+ $this->css->set_prop( 'childloaded', 0 );
2107
+ endif;
2108
+ // if theme loads parent theme when is_child_theme, add child dependency
2109
+ if ( isset( $analysis->child->signals->thm_parnt_loaded ) ):
2110
+ $this->css->set_prop( 'parntloaded', $analysis->child->signals->thm_parnt_loaded );
2111
+ if ( 'thm_unregistered' != $analysis->child->signals->thm_parnt_loaded ):
2112
+ array_unshift( $this->css->child_deps, $analysis->child->signals->thm_parnt_loaded );
2113
+ endif;
2114
+ else:
2115
+ $this->css->set_prop( 'parntloaded', 0 );
2116
+ endif;
2117
+
2118
+ // if main styleheet is loading out of sequence, force dependency
2119
+ if ( isset( $analysis->child->signals->ctc_parnt_reorder ) )
2120
+ $this->css->set_prop( 'reorder', 1 );
2121
+ // roll back CTC Pro Genesis handling option
2122
+ if ( isset( $analysis->child->signals->ctc_gen_loaded ) )
2123
+ $this->genesis = TRUE;
2124
+ endif;
2125
+ }
2126
+
2127
+ /**
2128
+ * Set the priority of the enqueue hook
2129
+ * by matching the hook handle of the primary stylesheet ( thm_parnt_loaded or thm_child_loaded )
2130
+ * to the hook handles that were passed by the preview fetched by the analyzer.
2131
+ * This allows the stylesheets to be enqueued in the correct order.
2132
+ */
2133
+ function set_enqueue_priority( $analysis, $baseline ){
2134
+ foreach ( $analysis->{ $baseline }->irreg as $irreg ):
2135
+ $handles = explode( ',', $irreg );
2136
+ $priority = array_shift( $handles );
2137
+ $handle = $analysis->{ $baseline }->signals->{ 'thm_' . $baseline . '_loaded' };
2138
+ if ( in_array( $handle, $handles ) ):
2139
+ $this->debug( '(baseline: ' . $baseline . ') match: ' . $handle . ' setting priority: ' . $priority, __FUNCTION__, __CLASS__ );
2140
+ $this->css->set_prop( 'qpriority', $priority );
2141
+ break;
2142
+ endif;
2143
+ endforeach;
2144
+ }
2145
+
2146
+ }
includes/classes/Analysis.php ADDED
@@ -0,0 +1,262 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Exit if accessed directly
3
+ if ( !defined( 'ABSPATH' ) ) exit;
4
+
5
+ /*
6
+ Class: ChildThemeConfiguratorAnalysis
7
+ Plugin URI: http://www.childthemeconfigurator.com/
8
+ Description: Theme Analyzer Class
9
+ Version: 2.1.3
10
+ Author: Lilaea Media
11
+ Author URI: http://www.lilaeamedia.com/
12
+ Text Domain: child-theme-configurator
13
+ Domain Path: /lang
14
+ License: GPLv2
15
+ Copyright (C) 2014-2016 Lilaea Media
16
+ */
17
+ class ChildThemeConfiguratorAnalysis {
18
+
19
+ private $params;
20
+ private $url;
21
+ private $response;
22
+ private $analysis;
23
+
24
+ function __construct(){
25
+ $this->params = array(
26
+ 'template' => isset( $_POST[ 'template' ] ) ? $_POST[ 'template' ] : '',
27
+ 'stylesheet' => isset( $_POST[ 'stylesheet' ] ) ? $_POST[ 'stylesheet' ] : '',
28
+ 'preview_ctc' => wp_create_nonce(),
29
+ 'now' => time(),
30
+ );
31
+
32
+ }
33
+
34
+ // helper function to globalize ctc object
35
+ function ctc() {
36
+ return ChildThemeConfigurator::ctc();
37
+ }
38
+
39
+
40
+ function is_child(){
41
+ return $this->params[ 'template' ] !== $this->params[ 'stylesheet' ];
42
+ }
43
+
44
+ function fetch_page(){
45
+ $this->url = get_home_url() . '?' . build_query( $this->params );
46
+ $args = array(
47
+ 'cookies' => $_COOKIE,
48
+ );
49
+ $this->response = wp_remote_get( $this->url, $args );
50
+ }
51
+
52
+ function do_analysis(){
53
+
54
+ $this->fetch_page();
55
+
56
+ $this->analysis = array(
57
+ 'url' => $this->url,
58
+ 'queue' => array(),
59
+ 'imports' => array(),
60
+ 'irreg' => array(),
61
+ 'dependencies' => array(),
62
+ 'errors' => array(),
63
+ 'deps' => array( array(), array() ),
64
+ 'signals' => array(
65
+ /*
66
+ err_fatal: 0,
67
+ err_fnf: 0,
68
+ err_other: 0,
69
+ ctc_sep_loaded: 0,
70
+ ctc_ext_loaded: 0,
71
+ ctc_child_loaded: 0,
72
+ ctc_parnt_loaded: 0,
73
+ thm_wrong_order: 0,
74
+ thm_past_wphead: 0,
75
+ thm_unregistered: 0,
76
+ thm_parnt_loaded: 0,
77
+ thm_child_loaded: 0,
78
+ thm_is_ctc: 0,
79
+ thm_no_styles: 0,
80
+ thm_notheme: 0
81
+ */
82
+ ),
83
+ );
84
+ if ( is_wp_error( $this->response ) ):
85
+ $this->analysis[ 'signals' ][ 'failure' ] = 1;
86
+ return;
87
+ else:
88
+ $body = $this->response[ 'body' ];
89
+ endif;
90
+ $themepath = preg_replace( "|^https?://|", '', get_theme_root_uri() );
91
+ $escaped = preg_quote( $this->params[ 'template' ] ) . ( $this->is_child() ? '|' . preg_quote( $this->params[ 'stylesheet' ] ) : '' );
92
+ $regex_link = '%<link( rel=["\']stylesheet["\'] id=[\'"]([^\'"]+?)[\'"])?[^>]+?' .
93
+ preg_quote( $themepath ) . '/(' . $escaped . ')/([^"\']+\.css)(\?[^"\']+)?["\'][^>]+>%si';
94
+ $regex_err = '%<br \/>\n[^\n]+?(fatal|strict|notice|warning|error).+?<br \/>%si'; //[\s\S]
95
+
96
+ $themeloaded = 0; // flag when style.css link is detected
97
+ $testloaded = 0; // flag when test link is detected
98
+ $this->ctc()->debug( 'regex link: ' . $regex_link . ' regex err: ' . $regex_err, __FUNCTION__ );
99
+ // retrieve enqueued stylesheet ids
100
+ if ( preg_match( '/BEGIN WP QUEUE\n(.*?)\nEND WP QUEUE/s', $body, $matches ) ):
101
+ $this->analysis[ 'queue' ] = explode( "\n", $matches[ 1 ] );
102
+ //console.log( 'QUEUE:' );
103
+ //console.log( analysis.queue );
104
+ else:
105
+ $this->analysis[ 'queue' ] = array();
106
+ $this->analysis[ 'signals' ][ 'thm_noqueue' ] = 1;
107
+ //analysis.signals.failure = 1;
108
+ //console.log( 'NO QUEUE' );
109
+ endif;
110
+ if ( preg_match( '/BEGIN IMPORT STYLESHEETS\n(.*?)\nEND IMPORT STYLESHEETS/s', $body, $matches ) ):
111
+ $this->analysis[ 'imports' ] = explode( "\n", $matches[ 1 ] );
112
+ else:
113
+ $this->analysis[ 'imports' ] = array();
114
+ endif;
115
+ if ( preg_match( '/BEGIN CTC IRREGULAR\n(.*?)\nEND CTC IRREGULAR/s', $body, $matches ) ):
116
+ $this->analysis[ 'irreg' ] = explode( "\n", $matches[ 1 ] );
117
+ else:
118
+ $this->analysis[ 'irreg' ] = array();
119
+ endif;
120
+ if ( preg_match( "/CHLD_THM_CFG_IGNORE_PARENT/", $body ) ):
121
+ $this->analysis[ 'signals' ][ 'thm_ignoreparnt' ] = 1;
122
+ //console.log( 'thm_ignoreparnt' );
123
+ endif;
124
+ if ( preg_match( "/IS_CTC_THEME/", $body ) ):
125
+ $this->analysis[ 'signals' ][ 'thm_is_ctc' ] = 1;
126
+ //console.log( 'thm_is_ctc' );
127
+ endif;
128
+
129
+ if ( preg_match( "/NO_CTC_STYLES/", $body ) ):
130
+ $this->analysis[ 'signals' ][ 'thm_no_styles' ] = 1;
131
+ //console.log( 'thm_no_styles' );
132
+ endif;
133
+ if ( preg_match( "/HAS_CTC_IMPORT/", $body ) ):
134
+ $this->analysis[ 'signals' ][ 'thm_has_import' ] = 1;
135
+ //console.log( 'thm_has_import' );
136
+ endif;
137
+
138
+ // remove comments to avoid flagging conditional stylesheets ( IE compatability, etc. )
139
+ $body = preg_replace( '/<!\-\-.*?\-\->/s', '', $body );
140
+ //console.log( 'PARSE:' );
141
+ preg_match_all( $regex_err, $body, $regexmatch );
142
+ foreach( $regexmatch[ 0 ] as $msg ):
143
+ $msg = preg_replace( "/<.*?>/s", '', $msg );
144
+ $this->analysis[ 'errors' ][] = $msg;
145
+ $this->analysis[ 'signals' ][ 'err_php' ] = 1;
146
+ if ( strstr( $msg, "Fatal error" ) )
147
+ $this->analysis[ 'signals' ][ 'err_fatal' ] = 1;
148
+
149
+ //else if ( errstr.match( /(FileNotFoundException|Failed opening|failed to open stream)/i ) ) {
150
+ //analysis.signals.err_fnf = 1;
151
+ //}
152
+ endforeach;
153
+ preg_match_all( $regex_link, $body, $regexmatch );
154
+ foreach( $regexmatch[ 0 ] as $msg ):
155
+ $stylesheetid = preg_replace( '/\-css$/', '', array_shift( $regexmatch[ 2 ] ) );
156
+ $stylesheettheme = array_shift( $regexmatch[ 3 ] );
157
+ $stylesheetpath = array_shift( $regexmatch[ 4 ] );
158
+
159
+ $linktheme = $this->params[ 'template' ] == $stylesheettheme ? 'parnt' : 'child';
160
+ $noid = 0;
161
+ //console.log( 'stylesheetid: ' + stylesheetid + ' stylesheetpath: ' + stylesheetpath );
162
+ // flag stylesheet links that have no id or are not in wp_styles
163
+ if ( '' == $stylesheetid || !in_array( $stylesheetid, $this->analysis[ 'queue' ] ) ):
164
+ $noid = 1;
165
+ //console.log( 'no id for ' + stylesheetpath + '!' );
166
+ elseif ( 0 === strpos( $stylesheetid, 'chld_thm_cfg' ) ): // handle ctc-generated links
167
+ // console.log( 'ctc link detected: ' + stylesheetid + ' themeloaded: ' + themeloaded );
168
+ if ( preg_match( '/^ctc\-style([\-\.]min)?\.css$/', $stylesheetpath ) ):
169
+ //console.log( 'separate stylesheet detected' );
170
+ $themeloaded = 1;
171
+ $this->analysis[ 'signals' ][ 'ctc_sep_loaded' ] = 1; // flag that separate stylesheet has been detected
172
+ elseif ( preg_match( '/^ctc\-genesis([\-\.]min)?\.css$/', $stylesheetpath ) ):
173
+ //console.log( 'genesis stylesheet detected' );
174
+ $themeloaded = 1;
175
+ $this->analysis[ 'signals' ][ 'ctc_gen_loaded' ] = 1; // flag that genesis "parent" has been detected
176
+ elseif ( preg_match( '/^chld_thm_cfg_ext/', $stylesheetid ) ):
177
+ $this->analysis[ 'signals' ][ 'ctc_ext_loaded' ] = 1; // flag that external stylesheet link detected
178
+ $this->analysis[ 'deps' ][ $themeloaded ][] = array( $stylesheetid, $stylesheetpath );
179
+ elseif ( 'chld_thm_cfg_child' == $stylesheetid ):
180
+ $this->analysis[ 'signals' ][ 'ctc_child_loaded' ] = 1; // flag that ctc child stylesheet link detected
181
+ $this->analysis[ 'deps' ][ $themeloaded ][] = array( $stylesheetid, $stylesheetpath );
182
+ elseif ( 'chld_thm_cfg_parent' == $stylesheetid ):
183
+ $this->analysis[ 'signals' ][ 'ctc_parnt_loaded' ] = 1; // flag that ctc parent stylesheet link detected
184
+ $this->analysis[ 'deps' ][ $themeloaded ][] = array( $stylesheetid, $stylesheetpath );
185
+ if ( $themeloaded )
186
+ //console.log( 'parent link out of sequence' );
187
+ $this->analysis[ 'signals' ][ 'ctc_parnt_reorder' ] = 1; // flag that ctc parent stylesheet link out of order
188
+ endif;
189
+ continue;
190
+ endif;
191
+ // flag main theme stylesheet link
192
+ if ( preg_match( '/^style([\-\.]min)?\.css$/', $stylesheetpath ) ):
193
+ //console.log( linktheme + ' theme stylesheet detected: ' + stylesheettheme + '/' + stylesheetpath );
194
+ $themeloaded = 1; // flag that main theme stylesheet has been detected
195
+ // if main theme stylesheet link has no id then it is unregistered ( hard-wired )
196
+ if ( 'parnt' == $linktheme ):
197
+ if ( $noid ):
198
+ $this->analysis[ 'signals' ][ 'thm_parnt_loaded' ] = 'thm_unregistered';
199
+ else:
200
+ $this->analysis[ 'signals' ][ 'thm_parnt_loaded' ] = $stylesheetid;
201
+ // check that parent stylesheet is loaded before child stylesheet
202
+ if ( 'child' == $themetype && $this->analysis[ 'signals' ][ 'thm_child_loaded' ] ):
203
+ $this->analysis[ 'signals' ][ 'ctc_parnt_reorder' ] = 1;
204
+ endif;
205
+ endif;
206
+ else:
207
+ $this->analysis[ 'signals' ][ 'thm_child_loaded' ] = $noid ? 'thm_unregistered' : $stylesheetid;
208
+ endif;
209
+ if ( $noid ):
210
+ if ( $testloaded ):
211
+ $this->analysis[ 'signals' ][ 'thm_past_wphead' ] = 1;
212
+ $this->analysis[ 'deps' ][ $themeloaded ][] = array( 'thm_past_wphead', $stylesheetpath );
213
+ //console.log( 'Unreachable theme stylesheet detected' );
214
+ else:
215
+ $this->analysis[ 'signals' ][ 'thm_unregistered' ] = 1;
216
+ $this->analysis[ 'deps' ][ $themeloaded ][] = array( 'thm_unregistered', $stylesheetpath );
217
+ //console.log( 'Unregistered theme stylesheet detected' );
218
+ endif;
219
+ else:
220
+ $this->analysis[ 'deps' ][ $themeloaded ][] = array( $stylesheetid, $stylesheetpath );
221
+ //console.log( 'Theme stylesheet OK!' );
222
+ endif;
223
+
224
+ elseif ( 'ctc-test.css' == $stylesheetpath ): // flag test stylesheet link
225
+ //console.log( 'end of queue reached' );
226
+ $testloaded = 1; // flag that test queue has been detected ( end of wp_head )
227
+ else:
228
+ $err = NULL;
229
+ // if stylesheet link has id and loads before main theme stylesheet, add it as a dependency
230
+ // otherwise add it as a parse option
231
+ if ( $noid )
232
+ $err = 'dep_unregistered';
233
+
234
+ if ( $testloaded ):
235
+ if ( $themeloaded ):
236
+ //console.log( 'Unreachable stylesheet detected!' + stylesheetpath );
237
+ $err = 'css_past_wphead';
238
+ else:
239
+ $err = 'dep_past_wphead';
240
+ endif;
241
+ endif;
242
+ // Flag stylesheet links that have no id and are loaded after main theme stylesheet.
243
+ // This indicates loading outside of wp_head()
244
+ if ( $err ):
245
+ $this->analysis[ 'signals' ][ $err ] = 1;
246
+ $stylesheetid = $err;
247
+ else:
248
+ // add to no force options
249
+ $this->analysis[ 'dependencies' ][ $stylesheetid ] = 1;
250
+ endif;
251
+ $this->analysis[ 'deps' ][ $themeloaded ][] = array( $stylesheetid, $stylesheetpath );
252
+ endif;
253
+ endforeach;
254
+ if ( ! $themeloaded )
255
+ $this->analysis[ 'signals' ][ 'thm_notheme' ] = 1; // flag that no theme stylesheet has been detected
256
+
257
+ }
258
+
259
+ function get_analysis(){
260
+ return $this->analysis;
261
+ }
262
+ }
includes/{class-ctc-css.php → classes/CSS.php} RENAMED
@@ -6,15 +6,17 @@ if ( !defined( 'ABSPATH' ) ) exit;
6
  Class: ChildThemeConfiguratorCSS
7
  Plugin URI: http://www.childthemeconfigurator.com/
8
  Description: Handles all CSS input, output, parsing, normalization and storage
9
- Version: 1.7.9
10
  Author: Lilaea Media
11
  Author URI: http://www.lilaeamedia.com/
12
  Text Domain: chld_thm_cfg
13
  Domain Path: /lang
14
  License: GPLv2
15
- Copyright (C) 2014-2015 Lilaea Media
16
  */
 
17
  class ChildThemeConfiguratorCSS {
 
18
  // data dictionaries
19
  var $dict_query; // @media queries and 'base'
20
  var $dict_sel; // selectors
@@ -22,8 +24,8 @@ class ChildThemeConfiguratorCSS {
22
  var $dict_rule; // css rules
23
  var $dict_val; // css values
24
  var $dict_seq; // child load order (priority)
 
25
  // hierarchies
26
- var $sel_ndx; // query => selector hierarchy
27
  var $val_ndx; // selector => rule => value hierarchy
28
  // key counters
29
  var $qskey; // counter for dict_qs
@@ -31,17 +33,29 @@ class ChildThemeConfiguratorCSS {
31
  var $selkey; // counter for dict_sel
32
  var $rulekey; // counter for dict_rule
33
  var $valkey; // counter for dict_val
34
- // miscellaneous properties
35
- var $imports; // @import rules
36
- var $styles; // temporary update cache
37
  var $child; // child theme slug
38
  var $parnt; // parent theme slug
39
  var $configtype; // legacy plugin slug
40
- var $addl_css; // parent additional stylesheets
41
- var $recent; // history of edited styles
42
- var $enqueue; // load parent css method (enqueue, import, none)
43
- var $converted; // @imports coverted to <link>?
44
- var $nowarn; // ignore stylesheet handling warnings
 
 
 
 
 
 
 
 
 
 
 
 
45
  var $child_name; // child theme name
46
  var $child_author; // child theme author
47
  var $child_authoruri; // child theme author website
@@ -49,9 +63,20 @@ class ChildThemeConfiguratorCSS {
49
  var $child_descr; // child theme description
50
  var $child_tags; // child theme tags
51
  var $child_version; // stylesheet version
 
 
 
 
 
 
 
 
52
  var $max_sel;
 
 
53
  var $temparray;
54
- var $vendorrule = array(
 
55
  'box\-sizing',
56
  'font\-smoothing',
57
  'border(\-(top|right|bottom|left))*\-radius',
@@ -69,12 +94,21 @@ class ChildThemeConfiguratorCSS {
69
  );
70
  var $configvars = array(
71
  'addl_css',
72
- // the enqueue flag prevents the transition from 1.5.4
73
- // from breaking the stylesheet by forcing the user to regenerate
74
- // the config data before updating the stylesheet. Otherwise,
75
- // removing the @import for the parent stylesheet will cause
76
- // the parent core styles to be missing.
77
- 'enqueue',
 
 
 
 
 
 
 
 
 
78
  'max_sel',
79
  'imports',
80
  'child_version',
@@ -92,31 +126,34 @@ class ChildThemeConfiguratorCSS {
92
  'qskey',
93
  'selkey',
94
  'querykey',
 
95
  'recent',
96
  'converted',
97
- 'nowarn',
 
98
  );
99
  var $dicts = array(
100
- 'dict_qs',
101
- 'dict_sel',
102
- 'dict_query',
103
- 'dict_rule',
104
- 'dict_val',
105
- 'dict_seq',
106
- 'sel_ndx',
107
- 'val_ndx',
108
  );
 
109
 
110
  function __construct() {
 
111
  // scalars
112
  $this->querykey = 0;
113
  $this->selkey = 0;
114
  $this->qskey = 0;
115
  $this->rulekey = 0;
116
  $this->valkey = 0;
117
- $this->child = '';
118
- $this->parnt = '';
119
- $this->configtype = 'theme'; // legacy support
120
  $this->child_name = '';
121
  $this->child_author = 'Child Theme Configurator';
122
  $this->child_themeuri = '';
@@ -124,94 +161,148 @@ class ChildThemeConfiguratorCSS {
124
  $this->child_descr = '';
125
  $this->child_tags = '';
126
  $this->child_version = '1.0';
127
- $this->max_sel = 0;
 
 
 
 
 
 
 
 
128
 
129
  // multi-dim arrays
130
- $this->dict_qs = array();
131
- $this->dict_sel = array();
132
- $this->dict_query = array();
133
- $this->dict_rule = array();
134
- $this->dict_val = array();
135
- $this->dict_seq = array();
136
- $this->sel_ndx = array();
137
- $this->val_ndx = array();
138
- $this->addl_css = array();
139
- $this->recent = array();
140
  $this->imports = array( 'child' => array(), 'parnt' => array() );
 
 
 
141
  }
142
 
143
  // helper function to globalize ctc object
144
  function ctc() {
145
  return ChildThemeConfigurator::ctc();
146
  }
 
 
 
 
 
 
 
 
 
 
 
147
 
148
- // loads current ctc config data into local memory
149
- function load_config() {
150
- $option = CHLD_THM_CFG_OPTIONS . apply_filters( 'chld_thm_cfg_option', '' );
151
- //echo 'loading option: ' . $option . LF;
152
- if ( ( $configarray = get_site_option( $option . '_configvars' ) ) && count( $configarray ) ):
153
- foreach ( $this->configvars as $configkey ):
154
- if ( isset( $configarray[ $configkey ] ) )
155
- $this->{$configkey} = $configarray[ $configkey ];
156
- endforeach;
157
- $this->ctc()->debug( 'configvars: ' . print_r( $configarray, TRUE ), __FUNCTION__ );
158
- foreach ( $this->dicts as $configkey ):
159
- if ( ( $configarray = get_site_option( $option . '_' . $configkey ) ) && count( $configarray ) )
160
- $this->{$configkey} = $configarray;
161
- endforeach;
162
- else:
163
- return FALSE;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
  endif;
 
165
  }
166
 
167
  // writes ctc config data to options api
168
  function save_config( $override = NULL ) {
 
 
169
  global $wpdb;
170
  if ( isset( $override ) ) $option = $override;
171
  else $option = apply_filters( 'chld_thm_cfg_option', '' );
172
  $option = CHLD_THM_CFG_OPTIONS . $option;
173
- //echo 'saving option: ' . $option . LF;
174
  $configarray = array();
175
  foreach ( $this->configvars as $configkey )
176
- $configarray[ $configkey ] = $this->{$configkey};
177
- $this->ctc()->debug( 'configvars: ' . print_r( $configarray, TRUE ), __FUNCTION__ );
178
  if ( is_multisite() ):
179
  update_site_option( $option . '_configvars', $configarray );
180
  else:
181
  // do not autoload ( passing false above only works if value changes
182
  update_option( $option . '_configvars', $configarray, FALSE );
183
  endif;
184
- foreach ( $this->dicts as $configkey ):
185
- if ( is_multisite() ):
186
- update_site_option( $option . '_' . $configkey, $this->{$configkey} );
187
- else:
188
- // do not autoload ( passing false above only works if value changes
189
- update_option( $option . '_' . $configkey, $this->{$configkey}, FALSE );
 
 
 
 
190
  endif;
191
  endforeach;
 
 
 
 
 
 
 
 
 
 
 
192
  }
193
-
194
  /**
195
  * get_prop
196
  * Getter interface (data sliced different ways depending on objname )
197
  */
198
- function get_prop( $objname, $params = NULL ) {
199
- switch ( $objname ):
 
 
 
 
 
 
200
  case 'imports':
201
- return $this->obj_to_utf8( is_array( $this->imports[ 'child' ] ) ?
 
202
  ( current( $this->imports[ 'child' ] ) == 1 ?
203
  array_keys( $this->imports[ 'child' ] ) :
204
  array_keys( array_flip( $this->imports[ 'child' ] ) ) ) :
205
  array() );
206
  case 'queries':
207
- return $this->obj_to_utf8( $this->denorm_sel_ndx() );
208
  case 'selectors':
209
  return empty( $params[ 'key' ] ) ?
210
- array() : $this->obj_to_utf8( $this->denorm_sel_ndx( $params[ 'key' ] ) );
211
  case 'rule_val':
212
  return empty( $params[ 'key' ] ) ? array() : $this->denorm_rule_val( $params[ 'key' ] );
213
  case 'val_qry':
214
- if ( isset( $params[ 'rule' ] ) && isset( $this->dict_rule[ $params[ 'rule' ] ] ) ):
215
  return empty( $params[ 'key' ] ) ?
216
  array() : $this->denorm_val_query( $params[ 'key' ], $params[ 'rule' ] );
217
  endif;
@@ -219,34 +310,70 @@ class ChildThemeConfiguratorCSS {
219
  return empty( $params[ 'key' ] ) ?
220
  array() : $this->obj_to_utf8( $this->denorm_sel_val( $params[ 'key' ] ) );
221
  case 'rules':
222
- ksort( $this->dict_rule );
223
- return $this->obj_to_utf8( $this->dict_rule );;
 
 
 
 
224
  case 'child':
225
  return $this->child;
226
  case 'parnt':
227
  return $this->parnt;
228
  case 'configtype': // legacy plugin extension support
229
  return $this->configtype;
 
 
230
  case 'addl_css':
231
- return isset( $this->addl_css ) ? $this->addl_css : array();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
232
  case 'child_name':
233
- return $this->child_name;
234
  case 'author':
235
- return $this->child_author;
236
  case 'themeuri':
237
  return isset( $this->child_themeuri ) ? $this->child_themeuri : FALSE;
238
  case 'authoruri':
239
  return isset( $this->child_authoruri ) ? $this->child_authoruri : FALSE;
240
  case 'descr':
241
- return isset( $this->child_descr ) ? $this->child_descr : FALSE;
242
  case 'tags':
243
- return isset( $this->child_tags ) ? $this->child_tags : FALSE;
244
  case 'version':
245
  return $this->child_version;
246
  case 'preview':
247
  $this->styles = '';
248
  if ( empty( $params[ 'key' ] ) || 'child' == $params[ 'key' ] ):
249
- $this->read_stylesheet( 'child' );
250
  else:
251
  if ( isset( $this->addl_css ) ):
252
  foreach ( $this->addl_css as $file ):
@@ -255,18 +382,22 @@ class ChildThemeConfiguratorCSS {
255
  $this->styles .= '/*** END ' . $file . ' ***/' . LF;
256
  endforeach;
257
  endif;
258
- list ( $template, $file ) = apply_filters( 'chld_thm_cfg_parent_preview_args', array( 'parnt', 'style.css' ) );
259
- if ( $this->ctc()->is_theme() || $this->ctc()->is_legacy() ):
260
- $this->styles .= '/*** BEGIN ' . $file . ' ***/' . LF;
261
- $this->read_stylesheet( $template, $file );
262
- $this->styles .= '/*** END ' . $file . ' ***/' . LF;
 
 
 
 
263
  endif;
264
  endif;
265
  $this->normalize_css();
266
  return $this->styles;
267
  break;
268
  default:
269
- return $this->obj_to_utf8( apply_filters( 'chld_thm_get_prop', NULL, $objname, $params ) );
270
  endswitch;
271
  return FALSE;
272
  }
@@ -275,9 +406,9 @@ class ChildThemeConfiguratorCSS {
275
  * set_prop
276
  * Setter interface (scalar values only)
277
  */
278
- function set_prop( $prop, $value ) {
279
- if ( is_null( $this->{ $prop } ) || is_scalar( $this->{ $prop } ) )
280
- $this->{ $prop } = $value;
281
  else return FALSE;
282
  }
283
 
@@ -291,31 +422,63 @@ class ChildThemeConfiguratorCSS {
291
  endif;
292
  }
293
 
 
 
 
 
 
 
294
  // creates header comments for stylesheet
295
  function get_css_header() {
296
- $parnt = $this->get_prop( 'parnt' );
297
- return '/*' . LF
298
- . 'Theme Name: ' . $this->get_prop( 'child_name' ) . LF
299
- . ( ( $attr = $this->get_prop( 'themeuri' ) ) ? 'Theme URI: ' . $attr . LF : '' )
300
- . 'Template: ' . $parnt . LF
301
- . 'Author: ' . $this->get_prop( 'author' ) . LF
302
- . ( ( $attr = $this->get_prop( 'authoruri' ) ) ? 'Author URI: ' . $attr . LF : '' )
303
- . ( ( $attr = $this->get_prop( 'descr' ) ) ? 'Description: ' . $attr . LF : '' )
304
- . ( ( $attr = $this->get_prop( 'tags' ) ) ? 'Tags: ' . $attr . LF : '' )
305
- . 'Version: ' . $this->get_prop( 'version' ) . '.' . time() . LF
306
- . 'Updated: ' . current_time( 'mysql' ) . LF
307
- . '*/' . LF . LF . '@charset "UTF-8";' . LF . LF
308
- . ( 'import' == $this->enqueue ? '@import url(\'../' . $parnt . '/style.css\');' . LF : '' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
309
  }
310
 
311
  // formats file path for child theme file
312
- function get_child_target( $file = 'style.css' ) {
313
- return trailingslashit( get_theme_root() ) . trailingslashit( $this->get_prop( 'child' ) ) . $file;
314
  }
315
 
316
  // formats file path for parent theme file
317
- function get_parent_source( $file = 'style.css' ) {
318
- return trailingslashit( get_theme_root() ) . trailingslashit( $this->get_prop( 'parnt' ) ) . $file;
319
  }
320
 
321
  /**
@@ -325,39 +488,63 @@ class ChildThemeConfiguratorCSS {
325
  * incrementing key value for dictionary
326
  */
327
  function get_dict_id( $dict, $value ) {
 
 
 
 
 
 
 
 
 
 
328
  $property = 'dict_' . $dict;
329
- $key = $dict . 'key';
330
- if ( !isset( $this->{ $property }[ $value ] ) )
331
- // add value to index
332
- $this->{ $property }[ $value ] = ++$this->{ $key };
333
- return $this->{ $property }[ $value ];
334
  }
335
 
 
 
 
 
 
 
 
 
 
 
 
 
336
  /**
337
  * get_qsid
338
  * query/selector id is the combination of two dictionary values
339
  * also throttles parsing if memory limit is reached
340
  */
341
  function get_qsid( $query, $sel ) {
342
- $q = $this->get_dict_id( 'query', $query );
343
- $s = $this->get_dict_id( 'sel', $sel );
344
- if ( !isset( $this->sel_ndx[ $q ][ $s ] ) ):
345
- // stop parsing if limit is reached to prevent out of memory on serialize
346
- if ( $this->qskey >= $this->ctc()->sel_limit ):
347
- $this->max_sel = 1;
348
- $this->ctc()->debug( 'Maximum num selectors reached ( limit: ' . $this->ctc()->sel_limit . ' )', __FUNCTION__ );
 
 
 
 
349
  return FALSE;
350
- endif;
351
- // increment key number
352
- $this->sel_ndx[ $q ][ $s ] = ++$this->qskey;
353
- $this->dict_qs[ $this->qskey ][ 's' ] = $s;
354
- $this->dict_qs[ $this->qskey ][ 'q' ] = $q;
355
- // update sequence for this selector if this is a later instance to keep cascade priority
356
- if ( !isset( $this->dict_seq[ $this->qskey ] ) )
357
- $this->dict_seq[ $this->qskey ] = $this->qskey;
358
-
359
  endif;
360
- return $this->sel_ndx[ $q ][ $s ];
 
 
 
 
 
 
 
 
361
  }
362
 
363
  /**
@@ -366,7 +553,7 @@ class ChildThemeConfiguratorCSS {
366
  * CTC object arrays, creating update cache in the process.
367
  * ( Update cache is returned to UI via AJAX to refresh page )
368
  * This has been refactored in v1.7.5 to accommodate multiple values per property.
369
- * @param $template parnt or child
370
  * @param $query media query
371
  * @param $sel selector
372
  * @param $rule property (rule)
@@ -386,62 +573,75 @@ class ChildThemeConfiguratorCSS {
386
  $rulevalid = NULL,
387
  $reset = FALSE
388
  ) {
389
- if ( $this->max_sel ) return;
390
- if ( FALSE === strpos( $query, '@' ) ):
391
  $query = 'base';
392
- endif;
393
  // normalize selector styling
394
  $sel = implode( ', ', preg_split( '#\s*,\s*#s', trim( $sel ) ) );
395
- if ( !( $qsid = $this->get_qsid( $query, $sel ) ) ) return;
396
-
397
  // set data and value
398
  if ( $rule ):
399
  // get ids and quit if max is reached ( get_qsid handles )
400
  $ruleid = $this->get_dict_id( 'rule', $rule );
401
  $valid = $this->get_dict_id( 'val', $value );
402
-
403
  /**
404
- * v1.7.5
405
- * modify existing data sructure to allow multiple property values
406
  */
407
-
408
- // create empty array if reset is TRUE
409
- // OR IF ruleval array does not exist
410
- if ( $reset || !isset( $this->val_ndx[ $qsid ][ $ruleid ][ $template ] )
411
- || !is_array( $this->val_ndx[ $qsid ][ $ruleid ][ $template ] ) )
412
- $this->val_ndx[ $qsid ][ $ruleid ][ $template ] = array();
413
- $this->convert_ruleval_array( $this->val_ndx[ $qsid ][ $ruleid ] );
414
- // rulevalid passed
 
 
 
 
 
 
 
 
 
 
 
415
  if ( isset( $rulevalid ) ):
416
- $this->unset_rule_value( $this->val_ndx[ $qsid ][ $ruleid ][ $template ], $rulevalid );
417
  // value empty?
418
  if ( '' === $value ):
419
  // value exist?
420
- elseif ( $id = $this->rule_value_exists( $this->val_ndx[ $qsid ][ $ruleid ][ $template ], $valid ) ):
421
- $this->unset_rule_value( $this->val_ndx[ $qsid ][ $ruleid ][ $template ], $id );
422
- $this->update_rule_value( $this->val_ndx[ $qsid ][ $ruleid ][ $template ], $rulevalid, $valid, $important );
423
  // update new value
424
  else:
425
- $this->update_rule_value( $this->val_ndx[ $qsid ][ $ruleid ][ $template ], $rulevalid, $valid, $important );
426
  endif;
427
  // rulevalid not passed
428
  else:
429
  // value exist?
430
- if ( $id = $this->rule_value_exists( $this->val_ndx[ $qsid ][ $ruleid ][ $template ], $valid ) ):
431
- $this->unset_rule_value( $this->val_ndx[ $qsid ][ $ruleid ][ $template ], $id );
432
- $this->update_rule_value( $this->val_ndx[ $qsid ][ $ruleid ][ $template ], $id, $valid, $important );
433
  // get new id and update new value
434
  else:
435
- $id = $this->get_rule_value_id( $this->val_ndx[ $qsid ][ $ruleid ][ $template ] );
436
- $this->update_rule_value( $this->val_ndx[ $qsid ][ $ruleid ][ $template ], $id, $valid, $important );
437
  endif;
438
  endif;
 
 
 
 
 
439
  // return query selector id
440
  return $qsid;
441
  endif;
442
  }
443
 
444
- /*
445
  * rule_value_exists
446
  * Determine if a value already exists for a property
447
  * and return its id
@@ -455,7 +655,7 @@ class ChildThemeConfiguratorCSS {
455
  return FALSE;
456
  }
457
 
458
- /*
459
  * get_rule_value_id
460
  * Generate a new rulevalid by iterating existing ids
461
  * and returning the next in sequence
@@ -467,7 +667,7 @@ class ChildThemeConfiguratorCSS {
467
  return $newid;
468
  }
469
 
470
- /*
471
  * update_rule_value
472
  * Generate a new value subarray
473
  */
@@ -479,7 +679,7 @@ class ChildThemeConfiguratorCSS {
479
  );
480
  }
481
 
482
- /*
483
  * unset_rule_value
484
  * Delete (splice) old value subarray from values
485
  */
@@ -487,7 +687,6 @@ class ChildThemeConfiguratorCSS {
487
  $index = 0;
488
  foreach ( $arr as $valarr ):
489
  if ( $id == $valarr[ 2 ] ):
490
- //echo 'found ' . $valarr[ 2 ] . '(index ' . $index . " )\n";
491
  array_splice( $arr, $index, 1 );
492
  break;
493
  endif;
@@ -495,15 +694,15 @@ class ChildThemeConfiguratorCSS {
495
  endforeach;
496
  }
497
 
498
- /*
499
  * prune_if_empty
500
  * Automatically cleans up hierarchies when no values exist
501
  * in either parent or child for a given selector.
502
  */
503
- function prune_if_empty( $qsid ) {
504
  $empty = $this->get_dict_id( 'val', '' );
505
- foreach ( $this->val_ndx[ $qsid ] as $ruleid => $arr ):
506
- foreach ( array( 'child', 'parnt' ) as $template ):
507
  if ( isset( $arr[ $template ] ) ):
508
  // v1.7.5: don't prune until converted to multi value format
509
  if ( !is_array( $arr[ $template ] ) ) return FALSE;
@@ -514,10 +713,10 @@ class ChildThemeConfiguratorCSS {
514
  endforeach;
515
  endforeach;
516
  // no values, prune from sel index, val index and qs dict data ( keep other dictionary records )
517
- unset( $this->sel_ndx[ $this->dict_qs[ $qsid ][ 'q' ] ][ $this->dict_qs[ $qsid ][ 's' ] ] );
518
  unset( $this->val_ndx[ $qsid ] );
519
  unset( $this->dict_qs[ $qsid ] );
520
  unset( $this->dict_seq[ $qsid ] );
 
521
  }
522
 
523
  /**
@@ -562,6 +761,14 @@ class ChildThemeConfiguratorCSS {
562
  * FIXME - this function has grown too monolithic - refactor and componentize
563
  */
564
  function parse_post_data() {
 
 
 
 
 
 
 
 
565
  $this->cache_updates = TRUE;
566
  if ( isset( $_POST[ 'ctc_new_selectors' ] ) ):
567
  $this->styles = $this->parse_css_input( LF . $_POST[ 'ctc_new_selectors' ] );
@@ -575,6 +782,18 @@ class ChildThemeConfiguratorCSS {
575
  $this->imports[ 'child' ] = array();
576
  $this->styles = $this->parse_css_input( $_POST[ 'ctc_child_imports' ] );
577
  $this->parse_css( 'child' );
 
 
 
 
 
 
 
 
 
 
 
 
578
  elseif ( isset( $_POST[ 'ctc_configtype' ] ) ):
579
  ob_start();
580
  do_action( 'chld_thm_cfg_get_stylesheets' );
@@ -601,7 +820,13 @@ class ChildThemeConfiguratorCSS {
601
  foreach ( preg_grep( '#^ctc_ovrd_child_seq_#', array_keys( $_POST ) ) as $post_key ):
602
  if ( preg_match( '#^ctc_ovrd_child_seq_(\d+)$#', $post_key, $matches ) ):
603
  $qsid = $matches[ 1 ];
604
- $this->dict_seq[ $qsid ] = intval( $_POST[ $post_key ] );
 
 
 
 
 
 
605
  endif;
606
  endforeach;
607
  $parts = array();
@@ -609,8 +834,8 @@ class ChildThemeConfiguratorCSS {
609
  if ( preg_match( '#^ctc_(ovrd|\d+)_child_([\w\-]+?)_(\d+?)_(\d+?)(_(.+))?$#', $post_key, $matches ) ):
610
  $valid = $matches[ 1 ];
611
  $rule = $matches[ 2 ];
612
- if ( NULL == $rule || !isset( $this->dict_rule[ $rule ] ) ) continue;
613
- $ruleid = $this->dict_rule[ $rule ];
614
  $qsid = $matches[ 3 ];
615
  $rulevalid = $matches[ 4 ];
616
  $value = $this->normalize_color( $this->sanitize( $this->parse_css_input( $_POST[ $post_key ] ) ) );
@@ -622,11 +847,12 @@ class ChildThemeConfiguratorCSS {
622
  $parts[ $qsid ][ $rule ][ 'values' ][ $rulevalid ][ 'important' ] = $important;
623
  $parts[ $qsid ][ $rule ][ 'query' ] = $selarr[ 'query' ];
624
  $parts[ $qsid ][ $rule ][ 'selector' ] = $selarr[ 'selector' ];
 
625
  else:
626
  if ( $newselector && $newselector != $selarr[ 'selector' ] ):
627
  // If this is a renamed selector, add new selector to array
628
  $newqsid = $this->update_arrays(
629
- 'child',
630
  $selarr[ 'query' ],
631
  $newselector,
632
  $rule,
@@ -634,9 +860,9 @@ class ChildThemeConfiguratorCSS {
634
  $important,
635
  $rulevalid
636
  );
637
- // clear the original selector's child value:
638
  $this->update_arrays(
639
- 'child',
640
  $selarr[ 'query' ],
641
  $selarr[ 'selector' ],
642
  $rule,
@@ -644,11 +870,16 @@ class ChildThemeConfiguratorCSS {
644
  0,
645
  $rulevalid
646
  );
647
- $this->dict_seq[ $newqsid ] = $this->dict_seq[ $qsid ];
 
 
 
 
 
648
  else:
649
  // otherwise, just update with the new values:
650
  $this->update_arrays(
651
- 'child',
652
  $selarr[ 'query' ],
653
  $selarr[ 'selector' ],
654
  $rule,
@@ -703,10 +934,12 @@ class ChildThemeConfiguratorCSS {
703
  else:
704
  $value = '';
705
  endif;
 
 
706
  if ( $newselector && $newselector != $rule_arr[ 'selector' ] ):
707
  // If this is a renamed selector, add new selector to array
708
  $newqsid = $this->update_arrays(
709
- 'child',
710
  $rule_arr[ 'query' ],
711
  $newselector,
712
  $rule,
@@ -714,9 +947,9 @@ class ChildThemeConfiguratorCSS {
714
  $rule_part[ 'important' ],
715
  $rulevalid
716
  );
717
- // clear the original selector's child value:
718
  $this->update_arrays(
719
- 'child',
720
  $rule_arr[ 'query' ],
721
  $rule_arr[ 'selector' ],
722
  $rule,
@@ -727,7 +960,7 @@ class ChildThemeConfiguratorCSS {
727
  else:
728
  // otherwise, just update with the new values:
729
  $this->update_arrays(
730
- 'child',
731
  $rule_arr[ 'query' ],
732
  $rule_arr[ 'selector' ],
733
  $rule,
@@ -739,14 +972,8 @@ class ChildThemeConfiguratorCSS {
739
  endforeach;
740
  endforeach;
741
  endforeach;
742
- // if this is a renamed selector, update sequence dict
743
- if ( $newqsid ):
744
- if ( !isset( $this->dict_seq[ $newqsid ] ) )
745
- $this->dict_seq[ $newqsid ] = $this->dict_seq[ $qsid ];
746
- endif;
747
- // remove if all values have been cleared
748
- $this->prune_if_empty( $qsid );
749
- $qsid = $newqsid ? $newqsid : $qsid;
750
  // return updated qsid to browser to update form
751
  if ( $this->ctc()->cache_updates ):
752
  $this->ctc()->updates[] = array(
@@ -759,7 +986,7 @@ class ChildThemeConfiguratorCSS {
759
  endif;
760
 
761
  // update enqueue function if imports have not been converted or new imports passed
762
- if ( isset( $_POST[ 'ctc_child_imports' ] ) || empty( $this->converted ) )
763
  add_action( 'chld_thm_cfg_addl_files', array( $this->ctc(), 'enqueue_parent_css' ), 15, 2 );
764
  }
765
 
@@ -773,7 +1000,7 @@ class ChildThemeConfiguratorCSS {
773
 
774
  // strips non printables and potential commands
775
  function sanitize( $styles ) {
776
- return sanitize_text_field( preg_replace( '/[^[:print:]]|\{.*/', '', $styles ) );
777
  }
778
 
779
  // escapes octal values in input to allow for specific ascii strings in content rule
@@ -792,11 +1019,15 @@ class ChildThemeConfiguratorCSS {
792
  */
793
  function parse_css_file( $template, $file = 'style.css', $cfgtemplate = FALSE ) {
794
  if ( '' == $file ) $file = 'style.css';
795
- // have we run out of memory?
 
 
 
796
  if ( $this->max_sel ):
797
- $this->ctc()->debug( 'Insufficient memory to parse file.', __FUNCTION__ );
798
  return FALSE;
799
  endif;
 
800
  // turn off caching when parsing files to reduce memory usage
801
  $this->ctc()->cache_updates = FALSE;
802
  $this->styles = ''; // reset styles
@@ -831,12 +1062,15 @@ class ChildThemeConfiguratorCSS {
831
  // read stylesheet
832
 
833
  if ( $stylesheet_verified = $this->is_file_ok( $stylesheet, 'read' ) ):
834
- // make sure we have space to parse
 
 
835
  if ( filesize( $stylesheet_verified ) * 3 > $this->ctc()->get_free_memory() ):
836
  $this->max_sel = 1;
837
- $this->ctc()->debug( 'Insufficient memory to read file', __FUNCTION__ );
838
  return;
839
  endif;
 
840
  $this->styles .= @file_get_contents( $stylesheet_verified ) . "\n";
841
  //echo 'count after get contents: ' . strlen( $this->styles ) . LF;
842
  else:
@@ -850,6 +1084,15 @@ class ChildThemeConfiguratorCSS {
850
  * FIXME - this function has grown too monolithic - refactor and componentize
851
  */
852
  function parse_css( $template, $basequery = NULL, $parse_imports = TRUE, $relpath = '', $reset = FALSE ) {
 
 
 
 
 
 
 
 
 
853
  if ( FALSE === strpos( $basequery, '@' ) ):
854
  $basequery = 'base';
855
  endif;
@@ -904,7 +1147,7 @@ class ChildThemeConfiguratorCSS {
904
  foreach( $matches[ 1 ] as $sel ):
905
  $stuff = array_shift( $matches[ 2 ] );
906
  $this->update_arrays(
907
- $template,
908
  $query,
909
  $sel
910
  );
@@ -956,11 +1199,17 @@ class ChildThemeConfiguratorCSS {
956
  $rule = preg_replace( '#(\-(o|ms|moz|webkit)\-)?(' . implode( '|', $this->vendorrule ) . ')#', "$3", $rule );
957
  if ( 'parnt' == $template && 'background-image' == $rule && strstr( $value, 'url(' ) )
958
  $value = $this->convert_rel_url( $value, $relpath );
959
- // by default, set semaphore true to allow multiple values
 
 
 
 
 
 
960
  if ( !$reset ) $resetrule[ $rule ] = TRUE;
961
 
962
  $qsid = $this->update_arrays(
963
- $template,
964
  $query,
965
  $sel,
966
  $rule,
@@ -983,10 +1232,12 @@ class ChildThemeConfiguratorCSS {
983
  );
984
  do_action( 'chld_thm_cfg_update_qsid', $qsid );
985
  endif;
 
986
  }
987
 
988
  // converts relative path to absolute path for preview
989
  function convert_rel_url( $value, $relpath, $url = TRUE ) {
 
990
  $path = preg_replace( '%url\([\'" ]*(.+?)[\'" ]*\)%', "$1", $value );
991
  if ( preg_match( '%(https?:)?//%', $path ) ) return $value;
992
  $pathparts = explode( '/', $path );
@@ -1000,7 +1251,7 @@ class ChildThemeConfiguratorCSS {
1000
  $newvalue = ( $url ? 'url(' : '' )
1001
  . ( $fileparts ? trailingslashit( implode( '/', $fileparts ) ) : '' )
1002
  . implode( '/', $newparts ) . ( $url ? ')' : '' );
1003
- $this->ctc()->debug( 'converted ' . $value . ' to ' . $newvalue . ' with ' . $relpath, __FUNCTION__ );
1004
  return $newvalue;
1005
  }
1006
 
@@ -1012,36 +1263,29 @@ class ChildThemeConfiguratorCSS {
1012
  * New selectors are appended to the end of each media query block.
1013
  * FIXME - this function has grown too monolithic - refactor and componentize
1014
  */
1015
- function write_css( $backup = FALSE ) {
1016
- // write new stylesheet
1017
- $output = apply_filters( 'chld_thm_cfg_css_header', $this->get_css_header(), $this );
1018
- // turn the dictionaries into indexes (value => id into id => value):
1019
- $rulearr = array_flip( $this->dict_rule );
1020
- $valarr = array_flip( $this->dict_val );
1021
- $selarr = array_flip( $this->dict_sel );
1022
-
1023
  foreach ( $this->sort_queries() as $query => $sort_order ):
1024
  $has_selector = 0;
1025
  $sel_output = '';
1026
- $selectors = $this->sel_ndx[ $this->dict_query[ $query ] ];
1027
  uasort( $selectors, array( $this, 'cmp_seq' ) );
1028
  if ( 'base' != $query ) $sel_output .= $query . ' {' . LF;
1029
  foreach ( $selectors as $selid => $qsid ):
1030
- if ( !empty( $this->val_ndx[ $qsid ] ) ):
1031
- $sel = $selarr[ $selid ];
1032
  $shorthand = array();
1033
  $rule_output = array();
1034
- foreach ( $this->val_ndx[ $qsid ] as $ruleid => $temparr ):
1035
  // normalize values for backward compatability
1036
- $this->convert_ruleval_array( $temparr );
1037
- if ( isset( $temparr[ 'child' ] ) &&
1038
- ( !isset( $temparr[ 'parnt' ] ) || $temparr[ 'parnt' ] != $temparr[ 'child' ] ) ):
1039
- foreach ( $temparr[ 'child' ] as $rulevalarr ):
1040
  $this->add_vendor_rules(
1041
  $rule_output,
1042
  $shorthand,
1043
- $rulearr[ $ruleid ],
1044
- $valarr[ $rulevalarr[ 0 ] ],
1045
  $rulevalarr[ 1 ],
1046
  $rulevalarr[ 2 ]
1047
  );
@@ -1075,30 +1319,23 @@ class ChildThemeConfiguratorCSS {
1075
  if ( 'base' != $query ) $sel_output .= '}' . LF;
1076
  if ( $has_selector ) $output .= $sel_output;
1077
  endforeach;
1078
- $stylesheet = apply_filters( 'chld_thm_cfg_target', $this->get_child_target(), $this );
1079
- //echo 'writing stylesheet: ' . $stylesheet . LF;
 
1080
  //echo //print_r(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), true) . LF;
1081
  if ( $stylesheet_verified = $this->is_file_ok( $stylesheet, 'write' ) ):
1082
  global $wp_filesystem; // this was initialized earlier;
1083
- // backup current stylesheet
1084
- if ( $backup && is_file( $stylesheet_verified ) ):
1085
- $timestamp = date( 'YmdHis', current_time( 'timestamp' ) );
1086
- $bakfile = preg_replace( "/\.css$/", '', $stylesheet_verified ) . '-' . $timestamp . '.css';
1087
- // don't write new stylesheet if backup fails
1088
- if ( !$wp_filesystem->copy(
1089
- $this->ctc()->fspath( $stylesheet_verified ),
1090
- $this->ctc()->fspath( $bakfile ) ) ) return FALSE;
1091
- endif;
1092
  // write new stylesheet:
1093
  // try direct write first, then wp_filesystem write
1094
  // stylesheet must already exist and be writable by web server
1095
  if ( $this->ctc()->is_ajax && is_writable( $stylesheet_verified ) ):
1096
  if ( FALSE === @file_put_contents( $stylesheet_verified, $output ) ):
1097
- $this->debug( 'Ajax write failed.', __FUNCTION__ );
1098
  return FALSE;
1099
  endif;
1100
- elseif ( FALSE === $wp_filesystem->put_contents( $this->ctc()->fspath( $stylesheet_verified ), $output ) ):
1101
- $this->debug( 'Filesystem write failed.', __FUNCTION__ );
1102
  return FALSE;
1103
  endif;
1104
  return TRUE;
@@ -1109,7 +1346,6 @@ class ChildThemeConfiguratorCSS {
1109
  function stringify_rule_output( &$rule_output ) {
1110
  $output = '';
1111
  asort( $rule_output );
1112
- //print_r( $rule_output );
1113
  foreach ( $rule_output as $rule => $sortstr )
1114
  $output .= ' ' . $rule . ";\n";
1115
  return $output;
@@ -1123,21 +1359,20 @@ class ChildThemeConfiguratorCSS {
1123
  * encode_shorthand
1124
  * converts CTC long syntax into CSS shorthand
1125
  * v1.7.5 refactored for multiple values per property
1126
- * FIXME - somehow condense all these foreach loops?
1127
  */
1128
  function encode_shorthand( $shorthand, &$rule_output ) {
1129
- //if ( $shorthand ) print_r( $shorthand );
1130
  foreach ( $shorthand as $property => $sides ):
1131
- if ( isset( $sides[ 'top' ] ) ):
1132
  foreach ( $sides[ 'top' ] as $tval => $tarr ):
1133
- if ( isset( $sides[ 'right' ] ) ):
1134
  $currseq = $tarr[ 1 ];
1135
  foreach ( $sides[ 'right' ] as $rval => $rarr ):
1136
  // value must exist from side and priority must match all sides
1137
- if ( isset( $sides[ 'bottom' ] ) && $tarr[ 0 ] == $rarr[ 0 ] ):
1138
  if ( $rarr[ 1 ] > $currseq ) $currseq = $rarr[ 1 ];
1139
  foreach ( $sides[ 'bottom' ] as $bval => $barr ):
1140
- if ( isset( $sides[ 'left' ] ) && $tarr[ 0 ] == $barr[ 0 ] ):
1141
  // use highest sort sequence of all sides
1142
  if ( $barr[ 1 ] > $currseq ) $currseq = $barr[ 1 ];
1143
  foreach ( $sides[ 'left' ] as $lval => $larr ):
@@ -1369,10 +1604,38 @@ class ChildThemeConfiguratorCSS {
1369
  */
1370
  function encode_gradient( $value ) {
1371
  // don't try this at home, kids
1372
- $regex = '#gradient[^\)]*?\((((to )?(top|bottom|left|right)?( (top|bottom|left|right))?|\d+deg),)?([^\w\#\)]*[\'"]?(\#\w{3,8}|rgba?\([\d., ]+?\)|hsla?\([\d%., ]+?\)|[a-z]+)( [\d.]+%)?)([^\w\#\)]*[\'"]?(\#\w{3,8}|rgba?\([\d., ]+?\)|hsla?\([\d%., ]+?\)|[a-z]+)( [\d.]+%)?)([^\w\)]*gradienttype=[\'"]?(\d)[\'"]?)?[^\w\)]*\)#i';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1373
  $param = $parts = array();
1374
  preg_match( $regex, $value, $parts );
1375
- if ( empty( $parts[ 14 ] ) ):
 
1376
  if ( empty( $parts[ 2 ] ) ):
1377
  $param[ 0 ] = 'top';
1378
  elseif ( 'to ' == $parts[ 3 ] ):
@@ -1384,28 +1647,28 @@ class ChildThemeConfiguratorCSS {
1384
  else:
1385
  $param[ 0 ] = trim( $parts[ 2 ] );
1386
  endif;
1387
- if ( empty( $parts[ 9 ] ) ):
1388
  $param[ 2 ] = '0%';
1389
  else:
1390
- $param[ 2 ] = trim( $parts[ 9 ] );
1391
  endif;
1392
- if ( empty( $parts[ 12 ] ) ):
1393
  $param[ 4 ] = '100%';
1394
  else:
1395
- $param[ 4 ] = trim( $parts[ 12 ] );
1396
  endif;
1397
- elseif( '0' == $parts[ 14 ] ):
1398
  $param[ 0 ] = 'top';
1399
  $param[ 2 ] = '0%';
1400
  $param[ 4 ] = '100%';
1401
- elseif ( '1' == $parts[ 14 ] ):
1402
  $param[ 0 ] = 'left';
1403
  $param[ 2 ] = '0%';
1404
  $param[ 4 ] = '100%';
1405
  endif;
1406
- if ( isset( $parts[ 8 ] ) && isset( $parts[ 11 ] ) ):
1407
- $param[ 1 ] = $parts[ 8 ];
1408
- $param[ 3 ] = $parts[ 11 ];
1409
  ksort( $param );
1410
  return implode( ':', $param );
1411
  else:
@@ -1451,21 +1714,23 @@ class ChildThemeConfiguratorCSS {
1451
  /**
1452
  * denorm_rule_val
1453
  * Return array of unique values corresponding to specific rule
1454
- * FIXME: only return child if no parent value exists
1455
  */
1456
  function denorm_rule_val( $ruleid ) {
 
 
1457
  $rule_sel_arr = array();
1458
- $val_arr = array_flip( $this->dict_val );
1459
- foreach ( $this->val_ndx as $qsid => $rules ):
1460
- if ( !isset( $rules[ $ruleid ] ) ) continue;
1461
- $this->convert_ruleval_array( $rules[ $ruleid ] );
1462
- foreach ( array( 'parnt', 'child' ) as $template ):
1463
- if ( isset( $rules[ $ruleid ][ $template ] ) ):
1464
- foreach ( $rules[ $ruleid ][ $template ] as $rulevalarr ):
1465
- $rule_sel_arr[ $rulevalarr[ 0 ] ] = $val_arr[ $rulevalarr[ 0 ] ];
1466
- endforeach;
1467
- endif;
1468
- endforeach;
1469
  endforeach;
1470
  return $rule_sel_arr;
1471
  }
@@ -1474,26 +1739,29 @@ class ChildThemeConfiguratorCSS {
1474
  * denorm_val_query
1475
  * Return array of queries, selectors, rules, and values corresponding to
1476
  * specific rule/value combo grouped by query, selector
1477
- * FIXME: only return child values corresponding to specific rulevalid of matching parent value
1478
  */
1479
  function denorm_val_query( $valid, $rule ) {
 
 
1480
  $value_query_arr = array();
1481
- if( $thisruleid = $this->get_dict_id( 'rule', $rule ) ):
1482
- foreach ( $this->val_ndx as $qsid => $rules ):
1483
- foreach ( $rules as $ruleid => $values ):
1484
- if ( $ruleid != $thisruleid ) continue;
1485
- $this->convert_ruleval_array( $values );
1486
- foreach ( array( 'parnt', 'child' ) as $template ):
1487
- if ( isset( $values[ $template ] ) ):
1488
- foreach ( $values[ $template ] as $rulevalarr ):
1489
- if ( $rulevalarr[ 0 ] != $valid ) continue;
1490
- $selarr = $this->denorm_query_sel( $qsid );
1491
- $value_query_arr[ $rule ][ $selarr[ 'query' ] ][ $qsid ] = $this->denorm_sel_val( $qsid );
 
 
1492
  endforeach;
1493
- endif;
1494
- endforeach;
1495
  endforeach;
1496
- endforeach;
1497
  endif;
1498
  return $value_query_arr;
1499
  }
@@ -1503,16 +1771,29 @@ class ChildThemeConfiguratorCSS {
1503
  * Return id, query and selector values of a specific qsid (query-selector ID)
1504
  */
1505
  function denorm_query_sel( $qsid ) {
1506
- if ( !isset( $this->dict_qs[ $qsid ] ) ) return array();
1507
- $queryarr = array_flip( $this->dict_query );
1508
- $selarr = array_flip( $this->dict_sel );
1509
- $this->dict_seq[ $qsid ] = isset( $this->dict_seq[ $qsid ] ) ? $this->dict_seq[ $qsid ] : $qsid;
1510
- return array(
 
 
 
 
 
 
 
 
 
 
 
 
1511
  'id' => $qsid,
1512
- 'query' => $queryarr[ $this->dict_qs[ $qsid ][ 'q' ] ],
1513
- 'selector' => $selarr[ $this->dict_qs[ $qsid ][ 's' ] ],
1514
- 'seq' => $this->dict_seq[ $qsid ],
1515
  );
 
1516
  }
1517
 
1518
  /**
@@ -1521,18 +1802,21 @@ class ChildThemeConfiguratorCSS {
1521
  * grouped by query, selector
1522
  */
1523
  function denorm_sel_val( $qsid ) {
 
 
 
1524
  $selarr = $this->denorm_query_sel( $qsid );
1525
- $valarr = array_flip( $this->dict_val );
1526
- $rulearr = array_flip( $this->dict_rule );
1527
- if ( isset( $this->val_ndx[ $qsid ] ) && is_array( $this->val_ndx[ $qsid ] ) ):
1528
- foreach ( $this->val_ndx[ $qsid ] as $ruleid => $values ):
1529
- // convert old value to new format
1530
- $this->convert_ruleval_array( $values );
1531
- foreach ( array( 'parnt', 'child' ) as $template ):
1532
  if ( isset( $values[ $template ] ) ):
1533
  foreach ( $values[ $template ] as $rulevalarr ):
1534
- $selarr[ 'value' ][ $rulearr[ $ruleid ] ][ $template ][] = array(
1535
- $valarr[ $rulevalarr[ 0 ] ],
1536
  $rulevalarr[ 1 ],
1537
  isset( $rulevalarr[ 2 ] ) ? $rulevalarr[ 2 ] : 1,
1538
  );
@@ -1541,18 +1825,23 @@ class ChildThemeConfiguratorCSS {
1541
  endforeach;
1542
  endforeach;
1543
  endif;
 
1544
  return $selarr;
1545
  }
1546
 
1547
  /**
 
 
1548
  * convert and/or normalize rule/value index
1549
  * to support multiple values per property ( rule )
1550
  * allows backward compatility with < v1.7.5
1551
  */
1552
  function convert_ruleval_array( &$arr ) {
 
1553
  foreach ( array( 'parnt', 'child' ) as $template ):
1554
  // skip if empty array
1555
  if ( !isset( $arr[ $template ] ) ) continue;
 
1556
  // check if using original data structure ( value is scalar )
1557
  if ( ! is_array( $arr[ $template ] ) ):
1558
  /**
@@ -1562,9 +1851,15 @@ class ChildThemeConfiguratorCSS {
1562
  * [1] => important
1563
  * [2] => priority
1564
  */
1565
- $temparr = array( array( $arr[ $template ], $arr[ 'i_' . $template ], 0, 1 ) );
1566
- $arr[ $template ] = $temparr;
 
1567
  endif;
 
 
 
 
 
1568
  $newarr = array();
1569
  // iterate each value and enforce array structure
1570
  foreach ( $arr[ $template ] as $rulevalid => $rulevalarr ):
@@ -1572,7 +1867,7 @@ class ChildThemeConfiguratorCSS {
1572
  if ( empty ( $rulevalarr ) ) continue;
1573
  //
1574
  if ( ! is_array( $rulevalarr ) ):
1575
- // important flag moves to individual value array
1576
  $important = isset( $arr[ 'i_' . $template ] ) ? $arr[ 'i_' . $template ] : 0;
1577
  unset( $arr[ 'i_' . $template ] );
1578
  $val = (int) $rulevalarr;
@@ -1584,22 +1879,78 @@ class ChildThemeConfiguratorCSS {
1584
  endforeach;
1585
  $arr[ $template ] = $newarr;
1586
  endforeach;
 
1587
  }
1588
 
1589
  /**
1590
- * denorm_sel_ndx
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1591
  * Return denormalized array containing query and selector heirarchy
1592
  */
1593
- function denorm_sel_ndx( $query = NULL ) {
1594
- $sel_ndx_norm = array();
1595
- $queryarr = array_flip( $this->dict_query );
1596
- $selarr = array_flip( $this->dict_sel );
1597
- foreach( $this->sel_ndx as $queryid => $sel ):
1598
- foreach( $sel as $selid => $qsid ):
1599
- $sel_ndx_norm[ $queryarr[ $queryid ] ][ $selarr[ $selid ] ] = $qsid;
 
 
 
 
 
 
 
 
1600
  endforeach;
1601
- endforeach;
1602
- return empty( $query ) ? array_keys( $sel_ndx_norm ) : $this->sort_selectors( $sel_ndx_norm[ $query ] );
 
 
 
 
1603
  }
1604
 
1605
  /**
@@ -1622,10 +1973,10 @@ class ChildThemeConfiguratorCSS {
1622
  * @media min-width queries in ascending order
1623
  */
1624
  function sort_queries() {
 
1625
  $queries = array();
1626
- $queryarr = array_flip( $this->dict_query );
1627
- foreach ( array_keys( $this->sel_ndx ) as $queryid ):
1628
- $query = $queryarr[ $queryid ];
1629
  if ( 'base' == $query ):
1630
  $queries[ 'base' ] = -999999;
1631
  continue;
@@ -1641,8 +1992,9 @@ class ChildThemeConfiguratorCSS {
1641
  }
1642
 
1643
  function sort_selectors( $selarr ) {
1644
- uksort( $selarr, array( $this, 'cmp_sel' ) );
1645
- return $selarr;
 
1646
  }
1647
 
1648
  function cmp_sel( $a, $b ) {
@@ -1654,8 +2006,10 @@ class ChildThemeConfiguratorCSS {
1654
 
1655
  // sort selectors based on dict_seq if exists, otherwise qsid
1656
  function cmp_seq( $a, $b ) {
1657
- $cmpa = isset( $this->dict_seq[ $a ] ) ? $this->dict_seq[ $a ] : $a;
1658
- $cmpb = isset( $this->dict_seq[ $b ] ) ? $this->dict_seq[ $b ] : $b;
 
 
1659
  if ( $cmpa == $cmpb ) return 0;
1660
  return ( $cmpa < $cmpb ) ? -1 : 1;
1661
  }
@@ -1688,36 +2042,37 @@ class ChildThemeConfiguratorCSS {
1688
  /**
1689
  * is_file_ok
1690
  * verify file exists and is in valid location
 
1691
  */
1692
  function is_file_ok( $stylesheet, $permission = 'read' ) {
1693
  // remove any ../ manipulations
1694
  $stylesheet = $this->ctc()->normalize_path( preg_replace( "%\.\./%", '/', $stylesheet ) );
1695
- $this->ctc()->debug( 'checking file: ' . $stylesheet, __FUNCTION__ );
1696
  if ( 'read' == $permission && !is_file( $stylesheet ) ):
1697
- $this->ctc()->debug( 'read: no file!', __FUNCTION__ );
1698
  return FALSE;
1699
  elseif ( 'write' == $permission && !is_dir( dirname( $stylesheet ) ) ):
1700
- $this->ctc()->debug( 'write: no dir!', __FUNCTION__ );
1701
  return FALSE;
1702
  elseif ( 'search' == $permission && !is_dir( $stylesheet ) ):
1703
- $this->ctc()->debug( 'search: no dir!', __FUNCTION__ );
1704
  return FALSE;
1705
  endif;
1706
  // check if in themes dir;
1707
  $regex = '%^' . preg_quote( $this->ctc()->normalize_path( get_theme_root() ) ) . '%';
1708
- $this->ctc()->debug( 'theme regex: ' . $regex, __FUNCTION__ );
1709
  if ( preg_match( $regex, $stylesheet ) ):
1710
- $this->ctc()->debug( $stylesheet . ' ok!', __FUNCTION__ );
1711
  return $stylesheet;
1712
  endif;
1713
  // check if in plugins dir
1714
  $regex = '%^' . preg_quote( $this->ctc()->normalize_path( WP_PLUGIN_DIR ) ) . '%';
1715
- $this->ctc()->debug( 'plugin regex: ' . $regex, __FUNCTION__ );
1716
  if ( preg_match( $regex, $stylesheet ) ):
1717
- $this->ctc()->debug( $stylesheet . ' ok!', __FUNCTION__ );
1718
  return $stylesheet;
1719
  endif;
1720
- $this->ctc()->debug( $stylesheet . ' is not in wp folders!', __FUNCTION__ );
1721
  return FALSE;
1722
  }
1723
 
@@ -1747,4 +2102,58 @@ class ChildThemeConfiguratorCSS {
1747
  function tolower( $matches ) {
1748
  return '#' . strtolower( $matches[ 1 ] );
1749
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1750
  }
6
  Class: ChildThemeConfiguratorCSS
7
  Plugin URI: http://www.childthemeconfigurator.com/
8
  Description: Handles all CSS input, output, parsing, normalization and storage
9
+ Version: 2.2.0
10
  Author: Lilaea Media
11
  Author URI: http://www.lilaeamedia.com/
12
  Text Domain: chld_thm_cfg
13
  Domain Path: /lang
14
  License: GPLv2
15
+ Copyright (C) 2014-2016 Lilaea Media
16
  */
17
+
18
  class ChildThemeConfiguratorCSS {
19
+
20
  // data dictionaries
21
  var $dict_query; // @media queries and 'base'
22
  var $dict_sel; // selectors
24
  var $dict_rule; // css rules
25
  var $dict_val; // css values
26
  var $dict_seq; // child load order (priority)
27
+ var $dict_token;
28
  // hierarchies
 
29
  var $val_ndx; // selector => rule => value hierarchy
30
  // key counters
31
  var $qskey; // counter for dict_qs
33
  var $selkey; // counter for dict_sel
34
  var $rulekey; // counter for dict_rule
35
  var $valkey; // counter for dict_val
36
+ var $tokenkey; // counter for dict_token
37
+
38
+ // from parent/child form
39
  var $child; // child theme slug
40
  var $parnt; // parent theme slug
41
  var $configtype; // legacy plugin slug
42
+ var $handling; // child stylesheet handling option
43
+ var $enqueue; // whether or not to load parent theme
44
+ var $ignoreparnt; // no not parse or enqueue parent
45
+ var $qpriority;
46
+ var $hasstyles;
47
+ var $parntloaded;
48
+ var $childloaded;
49
+ var $parnt_deps; //
50
+ var $child_deps; //
51
+ var $forcedep;
52
+ var $addl_css;
53
+ var $cssunreg;
54
+ var $csswphead;
55
+ var $cssnotheme;
56
+ var $reorder;
57
+
58
+ // header settings
59
  var $child_name; // child theme name
60
  var $child_author; // child theme author
61
  var $child_authoruri; // child theme author website
63
  var $child_descr; // child theme description
64
  var $child_tags; // child theme tags
65
  var $child_version; // stylesheet version
66
+
67
+ // miscellaneous properties
68
+ var $fsize; // used to check if styles changed since last update
69
+ var $converted; // @imports coverted to <link>?
70
+ var $version; // version of last saved data
71
+ var $templates; // cache of parent template files
72
+ var $imports; // @import rules
73
+ var $recent; // history of edited styles
74
  var $max_sel;
75
+ var $memory;
76
+ var $styles; // temporary update cache
77
  var $temparray;
78
+ var $instances = array();
79
+ var $vendorrule = array(
80
  'box\-sizing',
81
  'font\-smoothing',
82
  'border(\-(top|right|bottom|left))*\-radius',
94
  );
95
  var $configvars = array(
96
  'addl_css',
97
+ 'forcedep',
98
+ 'cssunreg',
99
+ 'csswphead',
100
+ 'cssnotheme',
101
+ 'reorder',
102
+ 'parnt_deps',
103
+ 'child_deps',
104
+ 'hasstyles',
105
+ 'parntloaded',
106
+ 'childloaded',
107
+ 'ignoreparnt',
108
+ 'qpriority',
109
+ 'enqueue',
110
+ 'handling',
111
+ 'templates',
112
  'max_sel',
113
  'imports',
114
  'child_version',
126
  'qskey',
127
  'selkey',
128
  'querykey',
129
+ 'tokenkey',
130
  'recent',
131
  'converted',
132
+ 'fsize',
133
+ 'version',
134
  );
135
  var $dicts = array(
136
+ 'dict_qs' => 0,
137
+ 'dict_sel' => 0,
138
+ 'dict_query' => 0,
139
+ 'dict_rule' => 0,
140
+ 'dict_val' => 0,
141
+ 'dict_seq' => 0,
142
+ 'dict_token' => 0,
143
+ 'val_ndx' => 0,
144
  );
145
+ var $packer; // packer object
146
 
147
  function __construct() {
148
+ $this->mem_chk();
149
  // scalars
150
  $this->querykey = 0;
151
  $this->selkey = 0;
152
  $this->qskey = 0;
153
  $this->rulekey = 0;
154
  $this->valkey = 0;
155
+ $this->max_sel = 0;
156
+
 
157
  $this->child_name = '';
158
  $this->child_author = 'Child Theme Configurator';
159
  $this->child_themeuri = '';
161
  $this->child_descr = '';
162
  $this->child_tags = '';
163
  $this->child_version = '1.0';
164
+
165
+ $this->configtype = 'theme'; // legacy support
166
+ $this->child = '';
167
+ $this->parnt = '';
168
+ $this->ignoreparnt = 0;
169
+ $this->qpriority = 10;
170
+ $this->version = '2.2.0';
171
+
172
+ // do not set enqueue, not being set is used to flag old versions
173
 
174
  // multi-dim arrays
175
+ $this->templates = array();
 
 
 
 
 
 
 
 
 
176
  $this->imports = array( 'child' => array(), 'parnt' => array() );
177
+
178
+ $this->recent = array();
179
+ $this->packer = new ChildThemeConfiguratorPacker();
180
  }
181
 
182
  // helper function to globalize ctc object
183
  function ctc() {
184
  return ChildThemeConfigurator::ctc();
185
  }
186
+ function mem_chk() {
187
+ $currmemory = $this->memory;
188
+ if ( function_exists( 'memory_get_peak_usage' ) ) {
189
+ $usage = memory_get_peak_usage();
190
+ } else {
191
+ $usage = memory_get_usage();
192
+ }
193
+ $this->memory = $usage;
194
+ $usage -= $currmemory;
195
+ return number_format( $this->memory / ( 1024 * 1024 ), 2 ) . ' MB diff ' . number_format( $usage / 1024, 2 ) . ' kB';
196
+ }
197
 
198
+ // loads current ctc config data
199
+ function load_config( $key = NULL ) {
200
+ //list(, $callerarr) = debug_backtrace(false);
201
+ //$caller = ( isset( $callerarr[ 'class' ] ) ? $callerarr[ 'class' ] . '::' : '' ) . $callerarr[ 'function' ];
202
+ if ( $key && isset( $this->dicts[ $key ] ) ):
203
+ $option = CHLD_THM_CFG_OPTIONS . apply_filters( 'chld_thm_cfg_option', '' );
204
+ if ( !$this->dicts[ $key ] ): // dict not loaded yet
205
+ //$this->ctc()->debug( 'memory before load: ' . $this->mem_chk(), __FUNCTION__, __CLASS__ );
206
+ //$this->ctc()->debug( $option . '_' . $key . ' -- called from ' . $caller, __FUNCTION__, __CLASS__ );
207
+ $this->{ $key } = $this->ctc()->is_new ? array() : get_site_option( $option . '_' . $key );
208
+ $this->dicts[ $key ] = 1; // flag as loaded
209
+ //$this->ctc()->debug( 'memory after load: ' . $this->mem_chk(), __FUNCTION__, __CLASS__ );
210
+ else:
211
+ //$this->ctc()->debug( $key . ' already loaded -- called from ' . $caller, __FUNCTION__, __CLASS__ );
212
+ endif;
213
+ endif;
214
+ if ( empty( $key ) && !isset( $this->enqueue ) ):
215
+ $option = CHLD_THM_CFG_OPTIONS . apply_filters( 'chld_thm_cfg_option', '' );
216
+ //$this->ctc()->debug( 'loading option: ' . $option . '_' . ( $key ? $key : 'configvars' )
217
+ // . ' -- called from ' . $caller, __FUNCTION__, __CLASS__ );
218
+ if ( ( $configarray = get_site_option( $option . '_configvars' ) ) && count( $configarray ) ):
219
+ foreach ( $this->configvars as $configkey ):
220
+ if ( isset( $configarray[ $configkey ] ) )
221
+ $this->{$configkey} = $configarray[ $configkey ];
222
+ endforeach;
223
+ // convert dictionaries from < 2.1.0
224
+ if ( empty( $configarray[ 'version' ] ) || version_compare( $configarray[ 'version' ], '2.1.0', '<' ) ):
225
+ $this->convert_dict_arrays();
226
+ else:
227
+ $this->ctc()->debug( 'dict format up to date', __FUNCTION__, __CLASS__ );
228
+ endif;
229
+ else:
230
+ return FALSE;
231
+ endif;
232
  endif;
233
+
234
  }
235
 
236
  // writes ctc config data to options api
237
  function save_config( $override = NULL ) {
238
+ // set latest stylesheet size
239
+ $this->get_stylesheet_path();
240
  global $wpdb;
241
  if ( isset( $override ) ) $option = $override;
242
  else $option = apply_filters( 'chld_thm_cfg_option', '' );
243
  $option = CHLD_THM_CFG_OPTIONS . $option;
 
244
  $configarray = array();
245
  foreach ( $this->configvars as $configkey )
246
+ $configarray[ $configkey ] = empty( $this->{$configkey} ) ? NULL : $this->{ $configkey };
247
+ //$this->ctc()->debug( 'saving option: ' . $option . '_configvars', __FUNCTION__, __CLASS__ );
248
  if ( is_multisite() ):
249
  update_site_option( $option . '_configvars', $configarray );
250
  else:
251
  // do not autoload ( passing false above only works if value changes
252
  update_option( $option . '_configvars', $configarray, FALSE );
253
  endif;
254
+
255
+ foreach ( $this->dicts as $configkey => $loaded ):
256
+ if ( $loaded ): // only save if dict is loaded
257
+ //$this->ctc()->debug( 'saving option: ' . $option . '_' . $configkey, __FUNCTION__, __CLASS__ );
258
+ if ( is_multisite() ):
259
+ update_site_option( $option . '_' . $configkey, $this->{$configkey} );
260
+ else:
261
+ // do not autoload ( passing false for update_site_option only works if value changes )
262
+ update_option( $option . '_' . $configkey, $this->{$configkey}, FALSE );
263
+ endif;
264
  endif;
265
  endforeach;
266
+
267
+ }
268
+
269
+ /**
270
+ * determine effective stylesheet path and measure size
271
+ */
272
+ function get_stylesheet_path() {
273
+ $stylesheet = apply_filters( 'chld_thm_cfg_target', $this->get_child_target( $this->ctc()->get_child_stylesheet() ), $this );
274
+ $this->fsize = filesize( $stylesheet );
275
+ $this->ctc()->debug( 'updated file size: ' . $this->fsize, __FUNCTION__, __CLASS__ );
276
+ return $stylesheet;
277
  }
 
278
  /**
279
  * get_prop
280
  * Getter interface (data sliced different ways depending on objname )
281
  */
282
+ function get_prop( $property, $params = NULL ) {
283
+ switch ( $property ):
284
+ case 'fsize':
285
+ return empty( $this->fsize ) ? FALSE : $this->fsize;
286
+ case 'converted':
287
+ return !empty( $this->converted );
288
+ case 'max_sel':
289
+ return empty( $this->max_sel ) ? FALSE : $this->max_sel;
290
  case 'imports':
291
+
292
+ return $this->obj_to_utf8( !empty( $this->imports[ 'child' ] ) && is_array( $this->imports[ 'child' ] ) ?
293
  ( current( $this->imports[ 'child' ] ) == 1 ?
294
  array_keys( $this->imports[ 'child' ] ) :
295
  array_keys( array_flip( $this->imports[ 'child' ] ) ) ) :
296
  array() );
297
  case 'queries':
298
+ return $this->obj_to_utf8( $this->denorm_dict_qs() );
299
  case 'selectors':
300
  return empty( $params[ 'key' ] ) ?
301
+ array() : $this->obj_to_utf8( $this->denorm_dict_qs( $params[ 'key' ] ) );
302
  case 'rule_val':
303
  return empty( $params[ 'key' ] ) ? array() : $this->denorm_rule_val( $params[ 'key' ] );
304
  case 'val_qry':
305
+ if ( isset( $params[ 'rule' ] ) ):
306
  return empty( $params[ 'key' ] ) ?
307
  array() : $this->denorm_val_query( $params[ 'key' ], $params[ 'rule' ] );
308
  endif;
310
  return empty( $params[ 'key' ] ) ?
311
  array() : $this->obj_to_utf8( $this->denorm_sel_val( $params[ 'key' ] ) );
312
  case 'rules':
313
+ $this->load_config( 'dict_rule' );
314
+ asort( $this->dict_rule );
315
+ //ksort( $this->dict_rule );
316
+ //return $this->obj_to_utf8( $this->dict_rule );
317
+ /** lookup ** -- need to flip array??? */
318
+ return $this->obj_to_utf8( array_flip( $this->dict_rule ) );
319
  case 'child':
320
  return $this->child;
321
  case 'parnt':
322
  return $this->parnt;
323
  case 'configtype': // legacy plugin extension support
324
  return $this->configtype;
325
+ case 'enqueue':
326
+ return empty( $this->enqueue ) ? FALSE : $this->enqueue;
327
  case 'addl_css':
328
+ return empty( $this->addl_css ) ? array() : $this->addl_css;
329
+ case 'parnt_imp':
330
+ return empty( $this->parnt_imp ) ? array() : $this->parnt_imp;
331
+ case 'forcedep': // v2.1.3
332
+ return empty( $this->forcedep ) ? array() : array_keys( $this->forcedep );
333
+ case 'parnt_deps':
334
+ return $this->quotify_dependencies( 'parnt_deps' );
335
+ case 'child_deps':
336
+ return $this->quotify_dependencies( 'child_deps' );
337
+ case 'templates':
338
+ return empty( $this->templates ) ? FALSE : $this->templates;
339
+ case 'ignoreparnt':
340
+ return empty( $this->ignoreparnt ) ? 0 : 1;
341
+ case 'qpriority':
342
+ return empty( $this->qpriority ) ? 10 : $this->qpriority;
343
+ case 'parntloaded':
344
+ return empty( $this->parntloaded ) ? FALSE : $this->parntloaded;
345
+ case 'childloaded':
346
+ return empty( $this->childloaded ) ? FALSE : $this->childloaded;
347
+ case 'hasstyles':
348
+ return empty( $this->hasstyles ) ? 0 : 1;
349
+ case 'cssunreg':
350
+ return empty( $this->cssunreg ) ? 0 : 1;
351
+ case 'csswphead':
352
+ return empty( $this->csswphead ) ? 0 : 1;
353
+ case 'cssnotheme':
354
+ return empty( $this->cssnotheme ) ? 0 : 1;
355
+ case 'reorder':
356
+ return empty( $this->reorder ) ? 0 : 1;
357
+ case 'handling':
358
+ return empty( $this->handling ) ? 'primary' : $this->handling;
359
  case 'child_name':
360
+ return stripslashes( $this->child_name );
361
  case 'author':
362
+ return stripslashes( $this->child_author );
363
  case 'themeuri':
364
  return isset( $this->child_themeuri ) ? $this->child_themeuri : FALSE;
365
  case 'authoruri':
366
  return isset( $this->child_authoruri ) ? $this->child_authoruri : FALSE;
367
  case 'descr':
368
+ return isset( $this->child_descr ) ? stripslashes( $this->child_descr ) : FALSE;
369
  case 'tags':
370
+ return isset( $this->child_tags ) ? stripslashes( $this->child_tags ) : FALSE;
371
  case 'version':
372
  return $this->child_version;
373
  case 'preview':
374
  $this->styles = '';
375
  if ( empty( $params[ 'key' ] ) || 'child' == $params[ 'key' ] ):
376
+ $this->read_stylesheet( 'child', $this->ctc()->get_child_stylesheet() );
377
  else:
378
  if ( isset( $this->addl_css ) ):
379
  foreach ( $this->addl_css as $file ):
382
  $this->styles .= '/*** END ' . $file . ' ***/' . LF;
383
  endforeach;
384
  endif;
385
+ if ( $this->get_prop( 'hasstyles' ) && !$this->get_prop( 'ignoreparnt' ) ):
386
+ $this->styles .= '/*** BEGIN Parent style.css ***/' . LF;
387
+ $this->read_stylesheet( 'parnt', 'style.css' );
388
+ $this->styles .= '/*** END Parent style.css ***/' . LF;
389
+ endif;
390
+ if ( 'separate' == $this->get_prop( 'handling' ) ):
391
+ $this->styles .= '/*** BEGIN Child style.css ***/' . LF;
392
+ $this->read_stylesheet( 'child', 'style.css' );
393
+ $this->styles .= '/*** END Child style.css ***/' . LF;
394
  endif;
395
  endif;
396
  $this->normalize_css();
397
  return $this->styles;
398
  break;
399
  default:
400
+ return $this->obj_to_utf8( apply_filters( 'chld_thm_get_prop', NULL, $property, $params ) );
401
  endswitch;
402
  return FALSE;
403
  }
406
  * set_prop
407
  * Setter interface (scalar values only)
408
  */
409
+ function set_prop( $property, $value ) {
410
+ if ( is_null( $this->{ $property } ) || is_scalar( $this->{ $property } ) )
411
+ $this->{ $property } = $value;
412
  else return FALSE;
413
  }
414
 
422
  endif;
423
  }
424
 
425
+ function quotify_dependencies( $prop ) {
426
+ $arr = array();
427
+ foreach ( array_diff( $this->{ $prop }, $this->get_prop( 'forcedep' ) ) as $el )
428
+ $arr[] = "'" . str_replace("'", "\'", $el ) . "'";
429
+ return $arr;
430
+ }
431
  // creates header comments for stylesheet
432
  function get_css_header() {
433
+ return array(
434
+ 'Theme Name' => $this->get_prop( 'child_name' ),
435
+ 'Theme URI' => ( ( $attr = $this->get_prop( 'themeuri' ) ) ? $attr : '' ),
436
+ 'Template' => $this->get_prop( 'parnt' ),
437
+ 'Author' => $this->get_prop( 'author' ),
438
+ 'Author URI' => ( ( $attr = $this->get_prop( 'authoruri' ) ) ? $attr : '' ),
439
+ 'Description' => ( ( $attr = $this->get_prop( 'descr' ) ) ? $attr : '' ),
440
+ 'Tags' => ( ( $attr = $this->get_prop( 'tags' ) ) ? $attr : '' ),
441
+ 'Version' => $this->get_prop( 'version' ) . '.' . time(),
442
+ 'Updated' => current_time( 'mysql' ),
443
+ );
444
+ }
445
+ function get_css_header_comment( $handling = 'primary' ) {
446
+ if ( 'separate' == $handling ):
447
+ $contents = "/*" . LF
448
+ . 'CTC Separate Stylesheet' . LF
449
+ . 'Updated: ' . current_time( 'mysql' ) . LF
450
+ . '*/' . LF;
451
+ else:
452
+ $contents = "/*" . LF;
453
+ foreach ( $this->get_css_header() as $param => $value ):
454
+ if ( $value ):
455
+ $contents .= $param . ': ' . $value . LF;
456
+ endif;
457
+ endforeach;
458
+ $contents .= LF . "*/" . LF . $this->get_css_imports();
459
+
460
+ endif;
461
+ return $contents;
462
+ }
463
+
464
+ function get_css_imports() {
465
+ $newheader = '';
466
+ if ( 'import' == $this->get_prop( 'enqueue' ) ):
467
+ $this->ctc()->debug( 'using import ', __FUNCTION__, __CLASS__ );
468
+ if ( ! $this->get_prop( 'ignoreparnt' ) )
469
+ $newheader .= "@import url('../" . $this->get_prop( 'parnt' ) . "/style.css');" . LF;
470
+ endif;
471
+ return $newheader;
472
  }
473
 
474
  // formats file path for child theme file
475
+ function get_child_target( $file = '', $theme = NULL ) {
476
+ return trailingslashit( get_theme_root() ) . trailingslashit( $theme ? $theme : $this->get_prop( 'child' ) ) . $file;
477
  }
478
 
479
  // formats file path for parent theme file
480
+ function get_parent_source( $file = 'style.css', $theme = NULL ) {
481
+ return trailingslashit( get_theme_root() ) . trailingslashit( $theme ? $theme : $this->get_prop( 'parnt' ) ) . $file;
482
  }
483
 
484
  /**
488
  * incrementing key value for dictionary
489
  */
490
  function get_dict_id( $dict, $value ) {
491
+ if ( FALSE === ( $id = $this->lookup_dict_value( $dict, $value ) ) ):
492
+ // add value to dictionary
493
+ $id = ++$this->{ $dict . 'key' };
494
+ $this->set_dict_value( $dict, $value, $id );
495
+ endif;
496
+ return $id;
497
+ }
498
+
499
+ function lookup_dict_value( $dict, $value ){
500
+ //$this->ctc()->debug( 'dict: ' . $dict . ' value: %' . $value . '%', __FUNCTION__, __CLASS__ );
501
  $property = 'dict_' . $dict;
502
+ if ( $id = array_search( (string) $value, $this->{ $property } ) )
503
+ return $id;
504
+ return FALSE;
 
 
505
  }
506
 
507
+ function get_dict_value( $dict, $id ) {
508
+ $property = 'dict_' . $dict;
509
+ return ( isset( $this->{ $property }[ $id ] ) )
510
+ ? $this->{ $property }[ $id ]
511
+ : FALSE;
512
+ }
513
+
514
+ function set_dict_value( $dict, $value, $id ) {
515
+ $property = 'dict_' . $dict;
516
+ $this->{ $property }[ $id ] = ( string ) $value;
517
+ }
518
+
519
  /**
520
  * get_qsid
521
  * query/selector id is the combination of two dictionary values
522
  * also throttles parsing if memory limit is reached
523
  */
524
  function get_qsid( $query, $sel ) {
525
+ $qs = $this->get_dict_id( 'query', $query ) . ':' . $this->get_dict_id( 'sel', $sel );
526
+ return $this->get_dict_id( 'qs', $qs );
527
+ }
528
+
529
+ function unpack_val_ndx( $qsid ){
530
+ if ( isset( $this->val_ndx[ $qsid ] ) ):
531
+ try {
532
+ $this->packer->reset( $this->packer->decode( $this->val_ndx[ $qsid ] ) );
533
+ return $this->packer->unpack();
534
+ } catch ( Exception $e ){
535
+ $this->ctc()->errors[] = 'Unpack failed -- ' . $e->getMessage();
536
  return FALSE;
537
+ }
 
 
 
 
 
 
 
 
538
  endif;
539
+ return FALSE;
540
+ }
541
+
542
+ function pack_val_ndx( $qsid, $valarr ){
543
+ try {
544
+ $this->val_ndx[ $qsid ] = $this->packer->encode( $this->packer->pack( $valarr ) );
545
+ } catch ( Exception $e ){
546
+ $this->ctc()->errors[] = 'Pack failed -- ' . $e->getMessage();
547
+ }
548
  }
549
 
550
  /**
553
  * CTC object arrays, creating update cache in the process.
554
  * ( Update cache is returned to UI via AJAX to refresh page )
555
  * This has been refactored in v1.7.5 to accommodate multiple values per property.
556
+ * @param $template p or c
557
  * @param $query media query
558
  * @param $sel selector
559
  * @param $rule property (rule)
573
  $rulevalid = NULL,
574
  $reset = FALSE
575
  ) {
576
+ // if ( $this->max_sel ) return; // Future use
577
+ if ( FALSE === strpos( $query, '@' ) )
578
  $query = 'base';
 
579
  // normalize selector styling
580
  $sel = implode( ', ', preg_split( '#\s*,\s*#s', trim( $sel ) ) );
581
+ $qsid = $this->get_qsid( $query, $this->tokenize( $sel ) );
 
582
  // set data and value
583
  if ( $rule ):
584
  // get ids and quit if max is reached ( get_qsid handles )
585
  $ruleid = $this->get_dict_id( 'rule', $rule );
586
  $valid = $this->get_dict_id( 'val', $value );
 
587
  /**
588
+ * v2.1.0
589
+ * pack/unpack val_ndx
590
  */
591
+ // create empty array IF value array does not exist
592
+ if ( FALSE === ( $valarr = $this->unpack_val_ndx( $qsid ) ) )
593
+ $valarr = array(
594
+ $ruleid => array(
595
+ $template => array(),
596
+ ),
597
+ );
598
+ // create empty array IF rule array does not exist
599
+ if ( !isset( $valarr[ $ruleid ] ) )
600
+ $valarr[ $ruleid ] = array(
601
+ $template => array(),
602
+ );
603
+ // create empty rule array if template is child and reset is TRUE
604
+ // or IF template array does not exist
605
+ if ( ( $reset && 'child' == $template ) || !isset( $valarr[ $ruleid ][ $template ] ) )
606
+ $valarr[ $ruleid ][ $template ] = array();
607
+
608
+ // rulevalid passed
609
+ //$this->ctc()->debug( 'rule: ' . $rule . ' ' . $ruleid . ' value: ' . ( '' == $value? 'NULL' : '%' . $value . '%' ) . ' ' . ( FALSE == $valid ? 'FALSE' : $valid ) . ' valarr: ' . print_r( $valarr, TRUE ), __FUNCTION__, __CLASS__ );
610
  if ( isset( $rulevalid ) ):
611
+ $this->unset_rule_value( $valarr[ $ruleid ][ $template ], $rulevalid );
612
  // value empty?
613
  if ( '' === $value ):
614
  // value exist?
615
+ elseif ( $id = $this->rule_value_exists( $valarr[ $ruleid ][ $template ], $valid ) ):
616
+ $this->unset_rule_value( $valarr[ $ruleid ][ $template ], $id );
617
+ $this->update_rule_value( $valarr[ $ruleid ][ $template ], $rulevalid, $valid, $important );
618
  // update new value
619
  else:
620
+ $this->update_rule_value( $valarr[ $ruleid ][ $template ], $rulevalid, $valid, $important );
621
  endif;
622
  // rulevalid not passed
623
  else:
624
  // value exist?
625
+ if ( $id = $this->rule_value_exists( $valarr[ $ruleid ][ $template ], $valid ) ):
626
+ $this->unset_rule_value( $valarr[ $ruleid ][ $template ], $id );
627
+ $this->update_rule_value( $valarr[ $ruleid ][ $template ], $id, $valid, $important );
628
  // get new id and update new value
629
  else:
630
+ $id = $this->get_rule_value_id( $valarr[ $ruleid ][ $template ] );
631
+ $this->update_rule_value( $valarr[ $ruleid ][ $template ], $id, $valid, $important );
632
  endif;
633
  endif;
634
+ // remove if all values have been cleared
635
+ if ( $this->prune_if_empty( $qsid, $valarr ) )
636
+ return FALSE;
637
+ //$this->ctc()->debug( 'revised valarr: ' . print_r( $valarr, TRUE ), __FUNCTION__, __CLASS__ );
638
+ $this->pack_val_ndx( $qsid, $valarr );
639
  // return query selector id
640
  return $qsid;
641
  endif;
642
  }
643
 
644
+ /**
645
  * rule_value_exists
646
  * Determine if a value already exists for a property
647
  * and return its id
655
  return FALSE;
656
  }
657
 
658
+ /**
659
  * get_rule_value_id
660
  * Generate a new rulevalid by iterating existing ids
661
  * and returning the next in sequence
667
  return $newid;
668
  }
669
 
670
+ /**
671
  * update_rule_value
672
  * Generate a new value subarray
673
  */
679
  );
680
  }
681
 
682
+ /**
683
  * unset_rule_value
684
  * Delete (splice) old value subarray from values
685
  */
687
  $index = 0;
688
  foreach ( $arr as $valarr ):
689
  if ( $id == $valarr[ 2 ] ):
 
690
  array_splice( $arr, $index, 1 );
691
  break;
692
  endif;
694
  endforeach;
695
  }
696
 
697
+ /**
698
  * prune_if_empty
699
  * Automatically cleans up hierarchies when no values exist
700
  * in either parent or child for a given selector.
701
  */
702
+ function prune_if_empty( $qsid, $valarr ) {
703
  $empty = $this->get_dict_id( 'val', '' );
704
+ foreach ( $valarr as $ruleid => $arr ):
705
+ foreach ( array( 'c', 'p' ) as $template ):
706
  if ( isset( $arr[ $template ] ) ):
707
  // v1.7.5: don't prune until converted to multi value format
708
  if ( !is_array( $arr[ $template ] ) ) return FALSE;
713
  endforeach;
714
  endforeach;
715
  // no values, prune from sel index, val index and qs dict data ( keep other dictionary records )
 
716
  unset( $this->val_ndx[ $qsid ] );
717
  unset( $this->dict_qs[ $qsid ] );
718
  unset( $this->dict_seq[ $qsid ] );
719
+ return TRUE;
720
  }
721
 
722
  /**
761
  * FIXME - this function has grown too monolithic - refactor and componentize
762
  */
763
  function parse_post_data() {
764
+ $this->load_config( 'dict_query' );
765
+ $this->load_config( 'dict_sel' );
766
+ $this->load_config( 'dict_token' );
767
+ $this->load_config( 'dict_rule' );
768
+ $this->load_config( 'dict_val' );
769
+ $this->load_config( 'val_ndx' );
770
+ $this->load_config( 'dict_seq' );
771
+ $this->load_config( 'dict_qs' );
772
  $this->cache_updates = TRUE;
773
  if ( isset( $_POST[ 'ctc_new_selectors' ] ) ):
774
  $this->styles = $this->parse_css_input( LF . $_POST[ 'ctc_new_selectors' ] );
782
  $this->imports[ 'child' ] = array();
783
  $this->styles = $this->parse_css_input( $_POST[ 'ctc_child_imports' ] );
784
  $this->parse_css( 'child' );
785
+
786
+ elseif ( isset( $_POST[ 'ctc_analysis' ] ) ):
787
+
788
+ if ( $this->ctc()->cache_updates ):
789
+ $this->ctc()->updates[] = array(
790
+ 'obj' => 'analysis',
791
+ 'data' => array(),
792
+ );
793
+ endif;
794
+
795
+ $this->ctc()->evaluate_signals( $this->get_prop( 'ignoreparnt' ) );
796
+
797
  elseif ( isset( $_POST[ 'ctc_configtype' ] ) ):
798
  ob_start();
799
  do_action( 'chld_thm_cfg_get_stylesheets' );
820
  foreach ( preg_grep( '#^ctc_ovrd_child_seq_#', array_keys( $_POST ) ) as $post_key ):
821
  if ( preg_match( '#^ctc_ovrd_child_seq_(\d+)$#', $post_key, $matches ) ):
822
  $qsid = $matches[ 1 ];
823
+ $seq = intval( $_POST[ $post_key ] );
824
+ $this->ctc()->debug( 'set seq( ' . $qsid . ' ): custom: ' . $seq, __FUNCTION__, __CLASS__ );
825
+ if ( $seq != $qsid ):
826
+ $this->set_dict_value( 'seq', $seq, $qsid );
827
+ else:
828
+ unset( $this->dict_seq[ $seq ] );
829
+ endif;
830
  endif;
831
  endforeach;
832
  $parts = array();
834
  if ( preg_match( '#^ctc_(ovrd|\d+)_child_([\w\-]+?)_(\d+?)_(\d+?)(_(.+))?$#', $post_key, $matches ) ):
835
  $valid = $matches[ 1 ];
836
  $rule = $matches[ 2 ];
837
+ if ( NULL == $rule || FALSE === $this->lookup_dict_value( 'rule', $rule ) )
838
+ continue;
839
  $qsid = $matches[ 3 ];
840
  $rulevalid = $matches[ 4 ];
841
  $value = $this->normalize_color( $this->sanitize( $this->parse_css_input( $_POST[ $post_key ] ) ) );
847
  $parts[ $qsid ][ $rule ][ 'values' ][ $rulevalid ][ 'important' ] = $important;
848
  $parts[ $qsid ][ $rule ][ 'query' ] = $selarr[ 'query' ];
849
  $parts[ $qsid ][ $rule ][ 'selector' ] = $selarr[ 'selector' ];
850
+ //$this->ctc()->debug( 'value: ' . $value . ' parts: ' . print_r( $parts, TRUE ), __FUNCTION__, __CLASS__ );
851
  else:
852
  if ( $newselector && $newselector != $selarr[ 'selector' ] ):
853
  // If this is a renamed selector, add new selector to array
854
  $newqsid = $this->update_arrays(
855
+ 'c',
856
  $selarr[ 'query' ],
857
  $newselector,
858
  $rule,
860
  $important,
861
  $rulevalid
862
  );
863
+ // clear the original selector's new value:
864
  $this->update_arrays(
865
+ 'c',
866
  $selarr[ 'query' ],
867
  $selarr[ 'selector' ],
868
  $rule,
870
  0,
871
  $rulevalid
872
  );
873
+ $seq = $this->get_dict_value( 'seq', $qsid );
874
+ if ( $seq != $newqsid ):
875
+ $this->set_dict_value( 'seq', $newqsid, $seq );
876
+ else:
877
+ unset( $this->dict_seq[ $newqsid ] );
878
+ endif;
879
  else:
880
  // otherwise, just update with the new values:
881
  $this->update_arrays(
882
+ 'c',
883
  $selarr[ 'query' ],
884
  $selarr[ 'selector' ],
885
  $rule,
934
  else:
935
  $value = '';
936
  endif;
937
+
938
+ //$this->ctc()->debug( 'modified value: ' . $value, __FUNCTION__, __CLASS__ );
939
  if ( $newselector && $newselector != $rule_arr[ 'selector' ] ):
940
  // If this is a renamed selector, add new selector to array
941
  $newqsid = $this->update_arrays(
942
+ 'c',
943
  $rule_arr[ 'query' ],
944
  $newselector,
945
  $rule,
947
  $rule_part[ 'important' ],
948
  $rulevalid
949
  );
950
+ // clear the original selector's new value:
951
  $this->update_arrays(
952
+ 'c',
953
  $rule_arr[ 'query' ],
954
  $rule_arr[ 'selector' ],
955
  $rule,
960
  else:
961
  // otherwise, just update with the new values:
962
  $this->update_arrays(
963
+ 'c',
964
  $rule_arr[ 'query' ],
965
  $rule_arr[ 'selector' ],
966
  $rule,
972
  endforeach;
973
  endforeach;
974
  endforeach;
975
+ if ( $newqsid )
976
+ $qsid = $newqsid;
 
 
 
 
 
 
977
  // return updated qsid to browser to update form
978
  if ( $this->ctc()->cache_updates ):
979
  $this->ctc()->updates[] = array(
986
  endif;
987
 
988
  // update enqueue function if imports have not been converted or new imports passed
989
+ if ( isset( $_POST[ 'ctc_analysis' ] ) || isset( $_POST[ 'ctc_child_imports' ] ) || !$this->get_prop( 'converted' ) )
990
  add_action( 'chld_thm_cfg_addl_files', array( $this->ctc(), 'enqueue_parent_css' ), 15, 2 );
991
  }
992
 
1000
 
1001
  // strips non printables and potential commands
1002
  function sanitize( $styles ) {
1003
+ return sanitize_text_field( preg_replace( '/[^[:print:]]|[\{\}].*/', '', $styles ) );
1004
  }
1005
 
1006
  // escapes octal values in input to allow for specific ascii strings in content rule
1019
  */
1020
  function parse_css_file( $template, $file = 'style.css', $cfgtemplate = FALSE ) {
1021
  if ( '' == $file ) $file = 'style.css';
1022
+
1023
+ /**
1024
+ * Future use: have we run out of memory?
1025
+ *
1026
  if ( $this->max_sel ):
1027
+ //$this->ctc()->debug( 'Insufficient memory to parse file.', __FUNCTION__, __CLASS__ );
1028
  return FALSE;
1029
  endif;
1030
+ */
1031
  // turn off caching when parsing files to reduce memory usage
1032
  $this->ctc()->cache_updates = FALSE;
1033
  $this->styles = ''; // reset styles
1062
  // read stylesheet
1063
 
1064
  if ( $stylesheet_verified = $this->is_file_ok( $stylesheet, 'read' ) ):
1065
+ /**
1066
+ * Future use: make sure we have space to parse
1067
+ *
1068
  if ( filesize( $stylesheet_verified ) * 3 > $this->ctc()->get_free_memory() ):
1069
  $this->max_sel = 1;
1070
+ //$this->ctc()->debug( 'Insufficient memory to read file', __FUNCTION__, __CLASS__ );
1071
  return;
1072
  endif;
1073
+ */
1074
  $this->styles .= @file_get_contents( $stylesheet_verified ) . "\n";
1075
  //echo 'count after get contents: ' . strlen( $this->styles ) . LF;
1076
  else:
1084
  * FIXME - this function has grown too monolithic - refactor and componentize
1085
  */
1086
  function parse_css( $template, $basequery = NULL, $parse_imports = TRUE, $relpath = '', $reset = FALSE ) {
1087
+ //$this->load_config( 'sel_ndx' );
1088
+ $this->load_config( 'val_ndx' );
1089
+ $this->load_config( 'dict_query' );
1090
+ $this->load_config( 'dict_sel' );
1091
+ $this->load_config( 'dict_token' );
1092
+ $this->load_config( 'dict_qs' );
1093
+ $this->load_config( 'dict_val' );
1094
+ $this->load_config( 'dict_rule' );
1095
+ $this->load_config( 'dict_seq' );
1096
  if ( FALSE === strpos( $basequery, '@' ) ):
1097
  $basequery = 'base';
1098
  endif;
1147
  foreach( $matches[ 1 ] as $sel ):
1148
  $stuff = array_shift( $matches[ 2 ] );
1149
  $this->update_arrays(
1150
+ 'child' == $template ? 'c' : 'p',
1151
  $query,
1152
  $sel
1153
  );
1199
  $rule = preg_replace( '#(\-(o|ms|moz|webkit)\-)?(' . implode( '|', $this->vendorrule ) . ')#', "$3", $rule );
1200
  if ( 'parnt' == $template && 'background-image' == $rule && strstr( $value, 'url(' ) )
1201
  $value = $this->convert_rel_url( $value, $relpath );
1202
+ /**
1203
+ * The reset flag forces the values for a given property (rule) to be rewritten completely
1204
+ * when using the raw CSS input or when reading from a stylesheet.
1205
+ * This permits complete blocks of style data to be entered verbatim, replacing existing styles.
1206
+ * When entering individual values from the Query/Selector inputs, multiple fallback values for existing
1207
+ * properties can be added in the order they are entered (e.g., margin: 1rem; margin: 1em;)
1208
+ */
1209
  if ( !$reset ) $resetrule[ $rule ] = TRUE;
1210
 
1211
  $qsid = $this->update_arrays(
1212
+ 'child' == $template ? 'c' : 'p',
1213
  $query,
1214
  $sel,
1215
  $rule,
1232
  );
1233
  do_action( 'chld_thm_cfg_update_qsid', $qsid );
1234
  endif;
1235
+
1236
  }
1237
 
1238
  // converts relative path to absolute path for preview
1239
  function convert_rel_url( $value, $relpath, $url = TRUE ) {
1240
+ if ( preg_match( '/data:/', $value ) ) return $value;
1241
  $path = preg_replace( '%url\([\'" ]*(.+?)[\'" ]*\)%', "$1", $value );
1242
  if ( preg_match( '%(https?:)?//%', $path ) ) return $value;
1243
  $pathparts = explode( '/', $path );
1251
  $newvalue = ( $url ? 'url(' : '' )
1252
  . ( $fileparts ? trailingslashit( implode( '/', $fileparts ) ) : '' )
1253
  . implode( '/', $newparts ) . ( $url ? ')' : '' );
1254
+ $this->ctc()->debug( 'converted ' . $value . ' to ' . $newvalue . ' with ' . $relpath, __FUNCTION__, __CLASS__ );
1255
  return $newvalue;
1256
  }
1257
 
1263
  * New selectors are appended to the end of each media query block.
1264
  * FIXME - this function has grown too monolithic - refactor and componentize
1265
  */
1266
+ function write_css() {
1267
+ $output = '';
 
 
 
 
 
 
1268
  foreach ( $this->sort_queries() as $query => $sort_order ):
1269
  $has_selector = 0;
1270
  $sel_output = '';
1271
+ $selectors = $this->denorm_dict_qs( $query, FALSE );
1272
  uasort( $selectors, array( $this, 'cmp_seq' ) );
1273
  if ( 'base' != $query ) $sel_output .= $query . ' {' . LF;
1274
  foreach ( $selectors as $selid => $qsid ):
1275
+ if ( $valarr = $this->unpack_val_ndx( $qsid ) ):
1276
+ $sel = $this->detokenize( $this->get_dict_value( 'sel', $selid ) );
1277
  $shorthand = array();
1278
  $rule_output = array();
1279
+ foreach ( $valarr as $ruleid => $temparr ):
1280
  // normalize values for backward compatability
1281
+ if ( isset( $temparr[ 'c' ] ) &&
1282
+ ( !isset( $temparr[ 'p' ] ) || $temparr[ 'p' ] != $temparr[ 'c' ] ) ):
1283
+ foreach ( $temparr[ 'c' ] as $rulevalarr ):
 
1284
  $this->add_vendor_rules(
1285
  $rule_output,
1286
  $shorthand,
1287
+ $this->get_dict_value( 'rule', $ruleid ),
1288
+ $this->get_dict_value( 'val', $rulevalarr[ 0 ] ),
1289
  $rulevalarr[ 1 ],
1290
  $rulevalarr[ 2 ]
1291
  );
1319
  if ( 'base' != $query ) $sel_output .= '}' . LF;
1320
  if ( $has_selector ) $output .= $sel_output;
1321
  endforeach;
1322
+ $output = $this->get_css_header_comment( $this->get_prop( 'handling' ) ) . LF . $output;
1323
+ $stylesheet = $this->get_stylesheet_path();
1324
+ $this->ctc()->debug( 'writing stylesheet: ' . $stylesheet, __FUNCTION__, __CLASS__ );
1325
  //echo //print_r(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), true) . LF;
1326
  if ( $stylesheet_verified = $this->is_file_ok( $stylesheet, 'write' ) ):
1327
  global $wp_filesystem; // this was initialized earlier;
1328
+ $mode = 'direct' == $this->ctc()->fs_method ? FALSE : 0666;
 
 
 
 
 
 
 
 
1329
  // write new stylesheet:
1330
  // try direct write first, then wp_filesystem write
1331
  // stylesheet must already exist and be writable by web server
1332
  if ( $this->ctc()->is_ajax && is_writable( $stylesheet_verified ) ):
1333
  if ( FALSE === @file_put_contents( $stylesheet_verified, $output ) ):
1334
+ $this->ctc()->debug( 'Ajax write failed.', __FUNCTION__, __CLASS__ );
1335
  return FALSE;
1336
  endif;
1337
+ elseif ( FALSE === $wp_filesystem->put_contents( $this->ctc()->fspath( $stylesheet_verified ), $output, $mode ) ):
1338
+ $this->ctc()->debug( 'Filesystem write failed.', __FUNCTION__, __CLASS__ );
1339
  return FALSE;
1340
  endif;
1341
  return TRUE;
1346
  function stringify_rule_output( &$rule_output ) {
1347
  $output = '';
1348
  asort( $rule_output );
 
1349
  foreach ( $rule_output as $rule => $sortstr )
1350
  $output .= ' ' . $rule . ";\n";
1351
  return $output;
1359
  * encode_shorthand
1360
  * converts CTC long syntax into CSS shorthand
1361
  * v1.7.5 refactored for multiple values per property
1362
+ * v2.1.0 to prevent incorrect rendering, do not use shorthand if multiple values exist for any side property.
1363
  */
1364
  function encode_shorthand( $shorthand, &$rule_output ) {
 
1365
  foreach ( $shorthand as $property => $sides ):
1366
+ if ( isset( $sides[ 'top' ] ) && 1 == count( $sides[ 'top' ] ) ):
1367
  foreach ( $sides[ 'top' ] as $tval => $tarr ):
1368
+ if ( isset( $sides[ 'right' ] ) && 1 == count( $sides[ 'right' ] ) ):
1369
  $currseq = $tarr[ 1 ];
1370
  foreach ( $sides[ 'right' ] as $rval => $rarr ):
1371
  // value must exist from side and priority must match all sides
1372
+ if ( isset( $sides[ 'bottom' ] ) && 1 == count( $sides[ 'bottom' ] ) && $tarr[ 0 ] == $rarr[ 0 ] ):
1373
  if ( $rarr[ 1 ] > $currseq ) $currseq = $rarr[ 1 ];
1374
  foreach ( $sides[ 'bottom' ] as $bval => $barr ):
1375
+ if ( isset( $sides[ 'left' ] ) && 1 == count( $sides[ 'left' ] ) && $tarr[ 0 ] == $barr[ 0 ] ):
1376
  // use highest sort sequence of all sides
1377
  if ( $barr[ 1 ] > $currseq ) $currseq = $barr[ 1 ];
1378
  foreach ( $sides[ 'left' ] as $lval => $larr ):
1604
  */
1605
  function encode_gradient( $value ) {
1606
  // don't try this at home, kids
1607
+ $regex = '/gradient[^\)]*?\( #exp descr
1608
+ ( #[1]
1609
+ ( #[2]
1610
+ (to\x20)? #[3] reverse
1611
+ (top|bottom|left|right)? #[4] direction1
1612
+ (\x20 #[5]
1613
+ (top|bottom|left|right))? #[6] direction2
1614
+ |\d+deg),)? # or angle
1615
+ (color-stop\()? #[7] optional
1616
+ ([^\w\#\)]*[\'"]? #[8]
1617
+ (\#\w{3,8} #[9] color (hex)
1618
+ |rgba?\([\d.,\x20]+?\) # red green blue (alpha)
1619
+ |hsla?\([\d%.,\x20]+?\) # hue sat. lum. (alpha)
1620
+ |[a-z]+) # color (name)
1621
+ (\x20+[\d.]+%?)?) #[10] stop position
1622
+ (\),\x20*)? #[11] optional close
1623
+ (color-stop\()? #[12] optional
1624
+ ([^\w\#\)]*[\'"]? #[13]
1625
+ (\#\w{3,8} #[14] color (hex)
1626
+ |rgba?\([\d.,\x20]+?\) # red green blue (alpha)
1627
+ |hsla?\([\d%.,\x20]+?\) # hue sat. lum. (alpha)
1628
+ |[a-z]+) # color (name)
1629
+ (\x20+[\d.]+%?)?) #[15] stop position
1630
+ (\))? #[16] optional close
1631
+ ([^\w\)]*gradienttype=[\'"]? #[17] IE
1632
+ (\d) #[18] IE
1633
+ [\'"]?)? # IE
1634
+ [^\w\)]*\)/ix';
1635
  $param = $parts = array();
1636
  preg_match( $regex, $value, $parts );
1637
+ //$this->ctc()->debug( 'gradient value: ' . $value . ' parts: ' . print_r( $parts, TRUE ), __FUNCTION__, __CLASS__ );
1638
+ if ( empty( $parts[ 18 ] ) ):
1639
  if ( empty( $parts[ 2 ] ) ):
1640
  $param[ 0 ] = 'top';
1641
  elseif ( 'to ' == $parts[ 3 ] ):
1647
  else:
1648
  $param[ 0 ] = trim( $parts[ 2 ] );
1649
  endif;
1650
+ if ( empty( $parts[ 10 ] ) ):
1651
  $param[ 2 ] = '0%';
1652
  else:
1653
+ $param[ 2 ] = trim( $parts[ 10 ] );
1654
  endif;
1655
+ if ( empty( $parts[ 15 ] ) ):
1656
  $param[ 4 ] = '100%';
1657
  else:
1658
+ $param[ 4 ] = trim( $parts[ 15 ] );
1659
  endif;
1660
+ elseif( '0' == $parts[ 18 ] ):
1661
  $param[ 0 ] = 'top';
1662
  $param[ 2 ] = '0%';
1663
  $param[ 4 ] = '100%';
1664
+ elseif ( '1' == $parts[ 18 ] ):
1665
  $param[ 0 ] = 'left';
1666
  $param[ 2 ] = '0%';
1667
  $param[ 4 ] = '100%';
1668
  endif;
1669
+ if ( isset( $parts[ 9 ] ) && isset( $parts[ 14 ] ) ):
1670
+ $param[ 1 ] = $parts[ 9 ];
1671
+ $param[ 3 ] = $parts[ 14 ];
1672
  ksort( $param );
1673
  return implode( ':', $param );
1674
  else:
1714
  /**
1715
  * denorm_rule_val
1716
  * Return array of unique values corresponding to specific rule
1717
+ * FIXME: only return child if no original value exists
1718
  */
1719
  function denorm_rule_val( $ruleid ) {
1720
+ $this->load_config( 'dict_val' );
1721
+ $this->load_config( 'val_ndx' );
1722
  $rule_sel_arr = array();
1723
+ foreach ( $this->val_ndx as $qsid => $p ):
1724
+ if ( $valarr = $this->unpack_val_ndx( $qsid ) ):
1725
+ if ( !isset( $valarr[ $ruleid ] ) ) continue;
1726
+ foreach ( array( 'p', 'c' ) as $template ):
1727
+ if ( isset( $valarr[ $ruleid ][ $template ] ) ):
1728
+ foreach ( $valarr[ $ruleid ][ $template ] as $rulevalarr ):
1729
+ $rule_sel_arr[ $rulevalarr[ 0 ] ] = $this->get_dict_value( 'val', $rulevalarr[ 0 ] );
1730
+ endforeach;
1731
+ endif;
1732
+ endforeach;
1733
+ endif;
1734
  endforeach;
1735
  return $rule_sel_arr;
1736
  }
1739
  * denorm_val_query
1740
  * Return array of queries, selectors, rules, and values corresponding to
1741
  * specific rule/value combo grouped by query, selector
1742
+ * FIXME: only return new values corresponding to specific rulevalid of matching original value
1743
  */
1744
  function denorm_val_query( $valid, $rule ) {
1745
+ $this->load_config( 'dict_rule' );
1746
+ $this->load_config( 'val_ndx' );
1747
  $value_query_arr = array();
1748
+ if ( $thisruleid = $this->get_dict_id( 'rule', $rule ) ):
1749
+ foreach ( $this->val_ndx as $qsid => $p ):
1750
+ if ( $valarr = $this->unpack_val_ndx( $qsid ) ):
1751
+ foreach ( $valarr as $ruleid => $values ):
1752
+ if ( $ruleid != $thisruleid ) continue;
1753
+ foreach ( array( 'p', 'c' ) as $template ):
1754
+ if ( isset( $values[ $template ] ) ):
1755
+ foreach ( $values[ $template ] as $rulevalarr ):
1756
+ if ( $rulevalarr[ 0 ] != $valid ) continue;
1757
+ $selarr = $this->denorm_query_sel( $qsid );
1758
+ $value_query_arr[ $rule ][ $selarr[ 'query' ] ][ $qsid ] = $this->denorm_sel_val( $qsid );
1759
+ endforeach;
1760
+ endif;
1761
  endforeach;
1762
+ endforeach;
1763
+ endif;
1764
  endforeach;
 
1765
  endif;
1766
  return $value_query_arr;
1767
  }
1771
  * Return id, query and selector values of a specific qsid (query-selector ID)
1772
  */
1773
  function denorm_query_sel( $qsid ) {
1774
+ $this->load_config( 'dict_query' );
1775
+ $this->load_config( 'dict_sel' );
1776
+ $this->load_config( 'dict_seq' );
1777
+ $this->load_config( 'dict_qs' );
1778
+ $this->load_config( 'dict_token' );
1779
+ if ( FALSE === ( $qs = $this->get_dict_value( 'qs', $qsid ) ) ):
1780
+ $this->ctc()->debug( $qsid . ' does not exist', __FUNCTION__, __CLASS__ );
1781
+ return array();
1782
+ endif;
1783
+ list( $q, $s ) = explode( ':', $qs );
1784
+ if ( $seq = $this->get_dict_value( 'seq', $qsid ) ):
1785
+ $this->ctc()->debug( 'get seq: custom: ' . $seq, __FUNCTION__, __CLASS__ );
1786
+ else:
1787
+ $seq = $qsid;
1788
+ $this->ctc()->debug( 'get seq: using qsid: ' . $qsid, __FUNCTION__, __CLASS__ );
1789
+ endif;
1790
+ $qselarr = array(
1791
  'id' => $qsid,
1792
+ 'query' => $this->get_dict_value( 'query', $q ),
1793
+ 'selector' => $this->detokenize( $this->get_dict_value( 'sel', $s ) ),
1794
+ 'seq' => $seq,
1795
  );
1796
+ return $qselarr;
1797
  }
1798
 
1799
  /**
1802
  * grouped by query, selector
1803
  */
1804
  function denorm_sel_val( $qsid ) {
1805
+ $this->load_config( 'dict_val' );
1806
+ $this->load_config( 'dict_rule' );
1807
+ $this->load_config( 'val_ndx' );
1808
  $selarr = $this->denorm_query_sel( $qsid );
1809
+ if ( $valarr = $this->unpack_val_ndx( $qsid ) ):
1810
+ //$this->ctc()->debug( 'valarr: ' . print_r( $valarr, TRUE ), __FUNCTION__, __CLASS__ );
1811
+ foreach ( $valarr as $ruleid => $values ):
1812
+ //$this->ctc()->debug( 'ruleid: ' . $ruleid, __FUNCTION__, __CLASS__ );
1813
+ foreach ( array( 'p', 'c' ) as $template ):
1814
+ $t = 'c' == $template ? 'child' : 'parnt';
1815
+ //$this->ctc()->debug( 'template: ' . $t, __FUNCTION__, __CLASS__ );
1816
  if ( isset( $values[ $template ] ) ):
1817
  foreach ( $values[ $template ] as $rulevalarr ):
1818
+ $selarr[ 'value' ][ $this->get_dict_value( 'rule', $ruleid ) ][ $t ][] = array(
1819
+ $this->get_dict_value( 'val', $rulevalarr[ 0 ] ),
1820
  $rulevalarr[ 1 ],
1821
  isset( $rulevalarr[ 2 ] ) ? $rulevalarr[ 2 ] : 1,
1822
  );
1825
  endforeach;
1826
  endforeach;
1827
  endif;
1828
+ //$this->ctc()->debug( print_r( $selarr, TRUE ), __FUNCTION__, __CLASS__ );
1829
  return $selarr;
1830
  }
1831
 
1832
  /**
1833
+ /**
1834
+ * v1.7.5
1835
  * convert and/or normalize rule/value index
1836
  * to support multiple values per property ( rule )
1837
  * allows backward compatility with < v1.7.5
1838
  */
1839
  function convert_ruleval_array( &$arr ) {
1840
+ //$this->ctc()->debug( 'original array: ' . print_r( $arr, TRUE ), __FUNCTION__, __CLASS__ );
1841
  foreach ( array( 'parnt', 'child' ) as $template ):
1842
  // skip if empty array
1843
  if ( !isset( $arr[ $template ] ) ) continue;
1844
+ $t = 'child' == $template ? 'c' : 'p';
1845
  // check if using original data structure ( value is scalar )
1846
  if ( ! is_array( $arr[ $template ] ) ):
1847
  /**
1851
  * [1] => important
1852
  * [2] => priority
1853
  */
1854
+ $arr[ $t ] = array( array( $arr[ $template ], $arr[ 'i_' . $template ], 0, 1 ) );
1855
+ else:
1856
+ $arr[ $t ] = $arr[ $template ];
1857
  endif;
1858
+ unset( $arr[ $template ] );
1859
+ endforeach;
1860
+ //$this->ctc()->debug( 'first pass: ' . print_r( $arr, TRUE ), __FUNCTION__, __CLASS__ );
1861
+ foreach ( array( 'p', 'c' ) as $template ):
1862
+ if ( !isset( $arr[ $template ] ) ) continue;
1863
  $newarr = array();
1864
  // iterate each value and enforce array structure
1865
  foreach ( $arr[ $template ] as $rulevalid => $rulevalarr ):
1867
  if ( empty ( $rulevalarr ) ) continue;
1868
  //
1869
  if ( ! is_array( $rulevalarr ) ):
1870
+ // important flag moves to individual value in array
1871
  $important = isset( $arr[ 'i_' . $template ] ) ? $arr[ 'i_' . $template ] : 0;
1872
  unset( $arr[ 'i_' . $template ] );
1873
  $val = (int) $rulevalarr;
1879
  endforeach;
1880
  $arr[ $template ] = $newarr;
1881
  endforeach;
1882
+ //$this->ctc()->debug( 'second pass: ' . print_r( $arr, TRUE ), __FUNCTION__, __CLASS__ );
1883
  }
1884
 
1885
  /**
1886
+ * Convert all internal data dictionaries to latest format.
1887
+ */
1888
+ function convert_dict_arrays(){
1889
+ $this->ctc()->debug( 'converting dictionaries from old format', __FUNCTION__, __CLASS__ );
1890
+ foreach ( $this->dicts as $dict => $loaded ):
1891
+ $this->load_config( $dict );
1892
+ switch ( $dict ):
1893
+ case 'dict_seq':
1894
+ case 'dict_token':
1895
+ continue;
1896
+ case 'sel_ndx':
1897
+ $this->{ $dict } = array();
1898
+ continue;
1899
+ case 'val_ndx':
1900
+ foreach ( $this->val_ndx as $qsid => $rulearr ):
1901
+ foreach ( $rulearr as $ruleid => $valarr )
1902
+ $this->convert_ruleval_array( $this->val_ndx[ $qsid ][ $ruleid ] );
1903
+ $this->pack_val_ndx( $qsid, $this->val_ndx[ $qsid ] );
1904
+ endforeach;
1905
+ continue;
1906
+ case 'dict_qs':
1907
+ $qsarr = array();
1908
+ foreach ( $this->dict_qs as $qsid => $arr ):
1909
+ $qs = $arr[ 'q' ] . ':' . $arr[ 's' ];
1910
+ $qsarr[ $qsid ] = $qs;
1911
+ endforeach;
1912
+ $this->dict_qs = $qsarr;
1913
+ continue;
1914
+ default:
1915
+ $this->{ $dict } = array_flip( $this->{ $dict } );
1916
+ foreach ( $this->{ $dict } as $key => $val ):
1917
+ if ( 'dict_sel' == $dict )
1918
+ $this->dict_sel[ $key ] = $this->tokenize( (string) $val );
1919
+ else
1920
+ $this->{ $dict }[ $key ] = ( string ) $val;
1921
+ endforeach;
1922
+ endswitch;
1923
+ //echo '<pre><code><small><strong>' . $dict . '</strong>' . print_r( $this->{ $dict }, TRUE) . '</small></code></pre>' . LF;
1924
+ endforeach;
1925
+ $this->save_config();
1926
+ }
1927
+
1928
+ /**
1929
+ * denorm_dict_qs
1930
  * Return denormalized array containing query and selector heirarchy
1931
  */
1932
+ function denorm_dict_qs( $query = NULL, $norm = TRUE ) {
1933
+ $this->load_config( 'dict_query' );
1934
+ $this->load_config( 'dict_sel' );
1935
+ $this->load_config( 'dict_token' );
1936
+ $this->load_config( 'dict_qs' );
1937
+ $retarray = array();
1938
+ if ( $query ):
1939
+ $q = $this->get_dict_id( 'query', $query );
1940
+ $selarr = preg_grep( '/^' . $q . ':/', $this->dict_qs );
1941
+ foreach ( $selarr as $qsid => $qs ):
1942
+ list( $q, $s ) = explode( ':', $qs );
1943
+ if ( $norm )
1944
+ $retarray[ $qsid ] = $this->detokenize( $this->get_dict_value( 'sel', $s ) );
1945
+ else
1946
+ $retarray[ $s ] = $qsid;
1947
  endforeach;
1948
+ else:
1949
+ return array_values( $this->dict_query );
1950
+ endif;
1951
+ if ( $norm )
1952
+ return $this->sort_selectors( $retarray );
1953
+ return $retarray;
1954
  }
1955
 
1956
  /**
1973
  * @media min-width queries in ascending order
1974
  */
1975
  function sort_queries() {
1976
+ $this->load_config( 'dict_query' );
1977
  $queries = array();
1978
+ foreach ( $this->dict_query as $queryid => $query ):
1979
+ /** lookup **/
 
1980
  if ( 'base' == $query ):
1981
  $queries[ 'base' ] = -999999;
1982
  continue;
1992
  }
1993
 
1994
  function sort_selectors( $selarr ) {
1995
+ $selarr = ( array ) $selarr;
1996
+ uasort( $selarr, array( $this, 'cmp_sel' ) );
1997
+ return array_flip( $selarr );
1998
  }
1999
 
2000
  function cmp_sel( $a, $b ) {
2006
 
2007
  // sort selectors based on dict_seq if exists, otherwise qsid
2008
  function cmp_seq( $a, $b ) {
2009
+ if ( FALSE === ( $cmpa = $this->get_dict_value( 'seq', $a ) ) )
2010
+ $cmpa = $a;
2011
+ if ( FALSE === ( $cmpb = $this->get_dict_value( 'seq', $b ) ) )
2012
+ $cmpb = $b;
2013
  if ( $cmpa == $cmpb ) return 0;
2014
  return ( $cmpa < $cmpb ) ? -1 : 1;
2015
  }
2042
  /**
2043
  * is_file_ok
2044
  * verify file exists and is in valid location
2045
+ * must be in theme or plugin folders
2046
  */
2047
  function is_file_ok( $stylesheet, $permission = 'read' ) {
2048
  // remove any ../ manipulations
2049
  $stylesheet = $this->ctc()->normalize_path( preg_replace( "%\.\./%", '/', $stylesheet ) );
2050
+ //$this->ctc()->debug( 'checking file: ' . $stylesheet, __FUNCTION__, __CLASS__ );
2051
  if ( 'read' == $permission && !is_file( $stylesheet ) ):
2052
+ $this->ctc()->debug( 'read ' . $stylesheet . ' no file!', __FUNCTION__, __CLASS__ );
2053
  return FALSE;
2054
  elseif ( 'write' == $permission && !is_dir( dirname( $stylesheet ) ) ):
2055
+ $this->ctc()->debug( 'write ' . $stylesheet . ' no dir!', __FUNCTION__, __CLASS__ );
2056
  return FALSE;
2057
  elseif ( 'search' == $permission && !is_dir( $stylesheet ) ):
2058
+ $this->ctc()->debug( 'search ' . $stylesheet . ' no dir!', __FUNCTION__, __CLASS__ );
2059
  return FALSE;
2060
  endif;
2061
  // check if in themes dir;
2062
  $regex = '%^' . preg_quote( $this->ctc()->normalize_path( get_theme_root() ) ) . '%';
2063
+ //$this->ctc()->debug( 'theme regex: ' . $regex, __FUNCTION__, __CLASS__ );
2064
  if ( preg_match( $regex, $stylesheet ) ):
2065
+ //$this->ctc()->debug( $stylesheet . ' ok!', __FUNCTION__, __CLASS__ );
2066
  return $stylesheet;
2067
  endif;
2068
  // check if in plugins dir
2069
  $regex = '%^' . preg_quote( $this->ctc()->normalize_path( WP_PLUGIN_DIR ) ) . '%';
2070
+ //$this->ctc()->debug( 'plugin regex: ' . $regex, __FUNCTION__, __CLASS__ );
2071
  if ( preg_match( $regex, $stylesheet ) ):
2072
+ //$this->ctc()->debug( $stylesheet . ' ok!', __FUNCTION__, __CLASS__ );
2073
  return $stylesheet;
2074
  endif;
2075
+ $this->ctc()->debug( $stylesheet . ' is not in wp folders!', __FUNCTION__, __CLASS__ );
2076
  return FALSE;
2077
  }
2078
 
2102
  function tolower( $matches ) {
2103
  return '#' . strtolower( $matches[ 1 ] );
2104
  }
2105
+
2106
+ function tokenize( $value ){
2107
+ return $value;
2108
+ // swap out commas and/or consecutive alphas with leading non-alpha if present
2109
+ $value = preg_replace_callback( "/(, |[_\W]?[^\W_]+)/", array( $this, 'get_token' ), $value );
2110
+ // trim off leading/trailing delimiter
2111
+ $value = preg_replace( "/^%%|%%$/", '', $value );
2112
+ // split into packable array
2113
+ $array = array_map( array( $this, 'to_int' ), preg_split( "/(%%)+/", $value ) );
2114
+ //echo '<pre><code><small>';
2115
+ //var_dump( $array );
2116
+ //echo '</small></code></pre>';
2117
+ try {
2118
+ return $this->packer->encode( $this->packer->pack( $array ) );
2119
+ } catch ( Exception $e ) {
2120
+ $this->ctc()->errors[] = 'Pack failed -- ' . $e->getMessage();
2121
+ }
2122
+ }
2123
+
2124
+ function to_int( $val ){
2125
+ return intval( $val ) == $val ? (int) $val : $val;
2126
+ }
2127
+
2128
+ function detokenize( $packed ){
2129
+ return $packed;
2130
+ // unpack array
2131
+ try {
2132
+ $this->packer->reset( $this->packer->decode( $packed ) );
2133
+ $array = $this->packer->unpack();
2134
+ } catch ( Exception $e ) {
2135
+ $this->ctc()->errors[] = 'Unpack failed -- ' . $e->getMessage();
2136
+ }
2137
+ $unpacked = array();
2138
+ // iterate array and replace tokens
2139
+ do {
2140
+ $token = array_shift( $array );
2141
+ if ( 'integer' == gettype( $token ) )
2142
+ $unpacked[] = $this->get_dict_value( 'token', $token );
2143
+ else
2144
+ $unpacked[] = $token;
2145
+ } while( $array );
2146
+
2147
+ // assemble array
2148
+ return implode( '', $unpacked );
2149
+ }
2150
+
2151
+ function get_token( $matches ){
2152
+ $token = $matches[ 1 ];
2153
+ $id = $this->get_dict_id( 'token', $token );
2154
+ $this->instances[ $id ] = isset( $this->instances[ $id ] )
2155
+ ? $this->instances[ $id ] + 1
2156
+ : 1;
2157
+ return '%%' . $id . '%%';
2158
+ }
2159
  }
includes/{class-ctc.php → classes/Core.php} RENAMED
@@ -3,47 +3,92 @@
3
  if ( !defined( 'ABSPATH' ) ) exit;
4
 
5
  class ChildThemeConfigurator {
 
6
  static $instance;
 
 
 
 
7
  static function init() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
 
9
  // verify WP version support
10
  global $wp_version;
11
- if ( version_compare( $wp_version, CHLD_THM_CFG_MIN_WP_VERSION ) < 0 ):
12
  add_action( 'admin_notices', 'ChildthemeConfigurator::version_notice' );
13
  return;
14
- endif;
 
 
 
 
 
15
  // setup admin hooks
16
  if ( is_multisite() )
17
  add_action( 'network_admin_menu', 'ChildThemeConfigurator::network_admin' );
18
  add_action( 'admin_menu', 'ChildThemeConfigurator::admin' );
 
 
 
19
  // setup ajax actions
20
  add_action( 'wp_ajax_ctc_update', 'ChildThemeConfigurator::save' );
21
  add_action( 'wp_ajax_ctc_query', 'ChildThemeConfigurator::query' );
 
 
 
 
22
  // initialize languages
23
  add_action( 'init', 'ChildThemeConfigurator::lang' );
 
 
 
 
24
  }
 
25
  static function ctc() {
26
  // create admin object
27
- global $chld_thm_cfg; /// backward compat
28
  if ( !isset( self::$instance ) ):
29
- include_once( CHLD_THM_CFG_DIR . '/includes/class-ctc-admin.php' );
30
  self::$instance = new ChildThemeConfiguratorAdmin( __FILE__ );
31
  endif;
32
- $chld_thm_cfg = self::$instance; // backward compat
33
  return self::$instance;
34
  }
 
35
  static function lang() {
36
  // initialize languages
37
- load_plugin_textdomain( 'child-theme-configurator', FALSE, basename( CHLD_THM_CFG_DIR ) . '/lang' );
38
  }
 
39
  static function save() {
40
  // ajax write
41
  self::ctc()->ajax_save_postdata();
42
  }
 
43
  static function query() {
44
  // ajax read
45
  self::ctc()->ajax_query_css();
46
- }
 
 
 
 
 
 
 
 
 
47
  static function network_admin() {
48
  $hook = add_theme_page(
49
  __( 'Child Theme Configurator', 'child-theme-configurator' ),
@@ -52,8 +97,9 @@ if ( !defined( 'ABSPATH' ) ) exit;
52
  CHLD_THM_CFG_MENU,
53
  'ChildThemeConfigurator::render'
54
  );
55
- add_action( 'load-' . $hook, 'ChildThemeConfigurator::page_init' );
56
  }
 
57
  static function admin() {
58
  $hook = add_management_page(
59
  __( 'Child Theme Configurator', 'child-theme-configurator' ),
@@ -65,39 +111,36 @@ if ( !defined( 'ABSPATH' ) ) exit;
65
  add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), 'ChildThemeConfigurator::action_links' );
66
  add_action( 'load-' . $hook, 'ChildThemeConfigurator::page_init' );
67
  }
 
68
  static function action_links( $actions ) {
69
  $actions[] = '<a href="' . admin_url( 'tools.php?page=' . CHLD_THM_CFG_MENU ). '">'
70
  . __( 'Child Themes', 'child-theme-configurator' ) . '</a>' . LF;
71
  return $actions;
72
  }
 
73
  static function page_init() {
74
  // start admin controller
75
  self::ctc()->ctc_page_init();
76
  }
 
77
  static function render() {
78
  // display admin page
79
  self::ctc()->render();
80
  }
 
81
  static function version_notice() {
82
  deactivate_plugins( plugin_basename( __FILE__ ) );
83
  unset( $_GET[ 'activate' ] );
84
- echo '<div class="update-nag"><p>' .
85
  sprintf( __( 'Child Theme Configurator requires WordPress version %s or later.', 'child-theme-configurator' ),
86
  CHLD_THM_CFG_MIN_WP_VERSION ) . '</p></div>' . LF;
87
  }
88
- }
89
- defined( 'LF' ) or define( 'LF', "\n" );
90
- defined( 'LILAEAMEDIA_URL' ) or
91
- define( 'LILAEAMEDIA_URL', "http://www.lilaeamedia.com" );
92
- defined( 'CHLD_THM_CFG_DOCS_URL' ) or
93
- define( 'CHLD_THM_CFG_DOCS_URL', "http://www.childthemeconfigurator.com" );
94
- define( 'CHLD_THM_CFG_VERSION', '1.7.9' );
95
- define( 'CHLD_THM_CFG_MIN_WP_VERSION', '3.7' );
96
- defined( 'CHLD_THM_CFG_BPSEL' ) or
97
- define( 'CHLD_THM_CFG_BPSEL', '2500' );
98
- defined( 'CHLD_THM_CFG_MAX_RECURSE_LOOPS' ) or
99
- define( 'CHLD_THM_CFG_MAX_RECURSE_LOOPS', '1000' );
100
- defined( 'CHLD_THM_CFG_MENU' ) or
101
- define( 'CHLD_THM_CFG_MENU', 'chld_thm_cfg_menu' );
102
 
103
- add_action( 'plugins_loaded', 'ChildThemeConfigurator::init' );
 
 
 
 
 
 
 
3
  if ( !defined( 'ABSPATH' ) ) exit;
4
 
5
  class ChildThemeConfigurator {
6
+
7
  static $instance;
8
+ static $plugin = 'child-theme-configurator/child-theme-configurator.php';
9
+ static $oldpro = 'child-theme-configurator-plugins/child-theme-configurator-plugins.php';
10
+ static $ctcpro = 'child-theme-configurator-pro/child-theme-configurator-pro.php';
11
+
12
  static function init() {
13
+ defined( 'LILAEAMEDIA_URL' ) or
14
+ define( 'LILAEAMEDIA_URL', "http://www.lilaeamedia.com" );
15
+ defined( 'CHLD_THM_CFG_DOCS_URL' ) or
16
+ define( 'CHLD_THM_CFG_DOCS_URL', "http://www.childthemeconfigurator.com" );
17
+ define( 'CHLD_THM_CFG_VERSION', '2.2.0' );
18
+ define( 'CHLD_THM_CFG_PREV_VERSION', '1.7.9.1' );
19
+ define( 'CHLD_THM_CFG_MIN_WP_VERSION', '3.7' );
20
+ define( 'CHLD_THM_CFG_PRO_MIN_VERSION', '2.2.0' );
21
+ defined( 'CHLD_THM_CFG_BPSEL' ) or
22
+ define( 'CHLD_THM_CFG_BPSEL', '2500' );
23
+ defined( 'CHLD_THM_CFG_MAX_RECURSE_LOOPS' ) or
24
+ define( 'CHLD_THM_CFG_MAX_RECURSE_LOOPS', '1000' );
25
+ defined( 'CHLD_THM_CFG_MENU' ) or
26
+ define( 'CHLD_THM_CFG_MENU', 'chld_thm_cfg_menu' );
27
 
28
  // verify WP version support
29
  global $wp_version;
30
+ if ( version_compare( $wp_version, CHLD_THM_CFG_MIN_WP_VERSION, '<' ) ):
31
  add_action( 'admin_notices', 'ChildthemeConfigurator::version_notice' );
32
  return;
33
+ endif;
34
+ if ( file_exists( trailingslashit( dirname( CHLD_THM_CFG_DIR ) ) . self::$oldpro )
35
+ || file_exists( trailingslashit( dirname( CHLD_THM_CFG_DIR ) ) . self::$ctcpro ) ):
36
+ // check if old version is installed
37
+ add_action( 'admin_init', 'ChildThemeConfiguratorUpgrade::check_version' );
38
+ endif;
39
  // setup admin hooks
40
  if ( is_multisite() )
41
  add_action( 'network_admin_menu', 'ChildThemeConfigurator::network_admin' );
42
  add_action( 'admin_menu', 'ChildThemeConfigurator::admin' );
43
+ // add plugin upgrade notification
44
+ add_action( 'in_plugin_update_message-' . self::$plugin,
45
+ 'ChildThemeConfigurator::upgrade_notice', 10, 2 );
46
  // setup ajax actions
47
  add_action( 'wp_ajax_ctc_update', 'ChildThemeConfigurator::save' );
48
  add_action( 'wp_ajax_ctc_query', 'ChildThemeConfigurator::query' );
49
+ add_action( 'wp_ajax_ctc_dismiss', 'ChildThemeConfigurator::dismiss' );
50
+ add_action( 'wp_ajax_pro_dismiss', 'ChildThemeConfiguratorUpgrade::ajax_dismiss_notice' );
51
+ add_action( 'wp_ajax_ctc_analyze', 'ChildThemeConfigurator::analyze' );
52
+
53
  // initialize languages
54
  add_action( 'init', 'ChildThemeConfigurator::lang' );
55
+
56
+ // prevent old Pro activation
57
+ if ( isset( $_GET[ 'action' ] ) && isset( $_GET[ 'plugin' ] ) && 'activate' == $_GET[ 'action' ] && self::$oldpro == $_GET[ 'plugin' ] )
58
+ unset( $_GET[ 'action' ] );
59
  }
60
+
61
  static function ctc() {
62
  // create admin object
 
63
  if ( !isset( self::$instance ) ):
 
64
  self::$instance = new ChildThemeConfiguratorAdmin( __FILE__ );
65
  endif;
 
66
  return self::$instance;
67
  }
68
+
69
  static function lang() {
70
  // initialize languages
71
+ load_plugin_textdomain( 'child-theme-configurator', FALSE, basename( CHLD_THM_CFG_DIR ) . '/lang' );
72
  }
73
+
74
  static function save() {
75
  // ajax write
76
  self::ctc()->ajax_save_postdata();
77
  }
78
+
79
  static function query() {
80
  // ajax read
81
  self::ctc()->ajax_query_css();
82
+ }
83
+
84
+ static function dismiss() {
85
+ self::ctc()->ajax_dismiss_notice();
86
+ }
87
+
88
+ static function analyze() {
89
+ self::ctc()->ajax_analyze();
90
+ }
91
+
92
  static function network_admin() {
93
  $hook = add_theme_page(
94
  __( 'Child Theme Configurator', 'child-theme-configurator' ),
97
  CHLD_THM_CFG_MENU,
98
  'ChildThemeConfigurator::render'
99
  );
100
+ add_action( 'load-' . $hook, 'ChildThemeConfigurator::page_init' );
101
  }
102
+
103
  static function admin() {
104
  $hook = add_management_page(
105
  __( 'Child Theme Configurator', 'child-theme-configurator' ),
111
  add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), 'ChildThemeConfigurator::action_links' );
112
  add_action( 'load-' . $hook, 'ChildThemeConfigurator::page_init' );
113
  }
114
+
115
  static function action_links( $actions ) {
116
  $actions[] = '<a href="' . admin_url( 'tools.php?page=' . CHLD_THM_CFG_MENU ). '">'
117
  . __( 'Child Themes', 'child-theme-configurator' ) . '</a>' . LF;
118
  return $actions;
119
  }
120
+
121
  static function page_init() {
122
  // start admin controller
123
  self::ctc()->ctc_page_init();
124
  }
125
+
126
  static function render() {
127
  // display admin page
128
  self::ctc()->render();
129
  }
130
+
131
  static function version_notice() {
132
  deactivate_plugins( plugin_basename( __FILE__ ) );
133
  unset( $_GET[ 'activate' ] );
134
+ echo '<div class="notice-warning notice is-dismissible"><p>' .
135
  sprintf( __( 'Child Theme Configurator requires WordPress version %s or later.', 'child-theme-configurator' ),
136
  CHLD_THM_CFG_MIN_WP_VERSION ) . '</p></div>' . LF;
137
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
 
139
+ static function upgrade_notice( $current, $new ){
140
+ if ( isset( $new->upgrade_notice ) && strlen( trim ( $new->upgrade_notice ) ) )
141
+ echo '<p style="background-color:#d54d21;padding:1em;color:#fff;margin: 9px 0">'
142
+ . esc_html( $new->upgrade_notice ) . '</p>';
143
+ }
144
+
145
+ }
146
+
includes/classes/Packer.php ADDED
@@ -0,0 +1,398 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ Some portions based on msgpack.php
5
+ Copyright (c) 2015-2016 Eugene Leonovich
6
+ The MIT License (MIT)
7
+ Some portions based on base91.php
8
+ Copyright (c) 2005-2006 Joachim Henke
9
+ http://base91.sourceforge.net/
10
+ */
11
+
12
+ class ChildThemeConfiguratorPacker {
13
+
14
+ const NON_UTF8_REGEX = '/(
15
+ [\xC0-\xC1] # Invalid UTF-8 Bytes
16
+ | [\xF5-\xFF] # Invalid UTF-8 Bytes
17
+ | \xE0[\x80-\x9F] # Overlong encoding of prior code point
18
+ | \xF0[\x80-\x8F] # Overlong encoding of prior code point
19
+ | [\xC2-\xDF](?![\x80-\xBF]) # Invalid UTF-8 Sequence Start
20
+ | [\xE0-\xEF](?![\x80-\xBF]{2}) # Invalid UTF-8 Sequence Start
21
+ | [\xF0-\xF4](?![\x80-\xBF]{3}) # Invalid UTF-8 Sequence Start
22
+ | (?<=[\x0-\x7F\xF5-\xFF])[\x80-\xBF] # Invalid UTF-8 Sequence Middle
23
+ | (?<![\xC2-\xDF]|[\xE0-\xEF]|[\xE0-\xEF][\x80-\xBF]|[\xF0-\xF4]|[\xF0-\xF4][\x80-\xBF]|[\xF0-\xF4][\x80-\xBF]{2})[\x80-\xBF] # Overlong Sequence
24
+ | (?<=[\xE0-\xEF])[\x80-\xBF](?![\x80-\xBF]) # Short 3 byte sequence
25
+ | (?<=[\xF0-\xF4])[\x80-\xBF](?![\x80-\xBF]{2}) # Short 4 byte sequence
26
+ | (?<=[\xF0-\xF4][\x80-\xBF])[\x80-\xBF](?![\x80-\xBF]) # Short 4 byte sequence (2)
27
+ )/x';
28
+ var $enctab = array(
29
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
30
+ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
31
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
32
+ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
33
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '!', '#', '$',
34
+ '%', '&', '(', ')', '*', '+', ',', '.', '/', ':', ';', '<', '=',
35
+ '>', '?', '@', '[', ']', '^', '_', '`', '{', '|', '}', '~', '"'
36
+ );
37
+ var $dectab;
38
+ var $buffer;
39
+ var $offset;
40
+
41
+ function __construct(){
42
+ $this->dectab = array_flip( $this->enctab );
43
+ }
44
+
45
+ function reset( $buffer = '' ){
46
+ $this->buffer = $buffer;
47
+ $this->offset = 0;
48
+ }
49
+
50
+ public function pack( $value ) {
51
+
52
+ switch ( gettype( $value ) ) {
53
+ case 'array': return array_values( $value ) === $value
54
+ ? $this->packArray( $value )
55
+ : $this->packMap( $value );
56
+
57
+ case 'string': return preg_match( self::NON_UTF8_REGEX, $value )
58
+ ? $this->packBin( $value )
59
+ : $this->packStr( $value );
60
+
61
+ case 'integer': return $this->packInt( $value );
62
+ case 'NULL': return $this->packNil();
63
+ case 'boolean': return $this->packBool( $value );
64
+ }
65
+
66
+ throw new PackingFailedException( $value, 'Unsupported type.' );
67
+ }
68
+
69
+ public function packNil() {
70
+
71
+ return "\xc0";
72
+ }
73
+
74
+ public function packBool( $val ) {
75
+
76
+ return $val ? "\xc3" : "\xc2";
77
+ }
78
+
79
+ public function packArray( array $array ) {
80
+
81
+ $size = count( $array );
82
+ $data = self::packArrayHeader( $size );
83
+
84
+ foreach ( $array as $val ) {
85
+ $data .= $this->pack( $val );
86
+ }
87
+
88
+ return $data;
89
+ }
90
+
91
+ private static function packArrayHeader( $size ) {
92
+
93
+ if ( $size <= 0xf ) {
94
+ return chr( 0x90 | $size );
95
+ }
96
+ if ( $size <= 0xffff ) {
97
+ return pack( 'Cn', 0xdc, $size );
98
+ }
99
+
100
+ return pack( 'CN', 0xdd, $size );
101
+ }
102
+
103
+ public function packMap( array $map ) {
104
+
105
+ $size = count( $map );
106
+ $data = self::packMapHeader( $size );
107
+
108
+ foreach ( $map as $key => $val ) {
109
+ $data .= $this->pack( $key );
110
+ $data .= $this->pack( $val );
111
+ }
112
+
113
+ return $data;
114
+ }
115
+
116
+ private static function packMapHeader( $size ) {
117
+
118
+ if ( $size <= 0xf ) {
119
+ return chr( 0x80 | $size );
120
+ }
121
+ if ( $size <= 0xffff ) {
122
+ return pack( 'Cn', 0xde, $size );
123
+ }
124
+
125
+ return pack( 'CN', 0xdf, $size );
126
+ }
127
+
128
+ public function packStr( $str ) {
129
+
130
+ $len = strlen( $str );
131
+
132
+ if ( $len < 32 ) {
133
+ return chr( 0xa0 | $len ) . $str;
134
+ }
135
+ if ( $len <= 0xff ) {
136
+ return pack( 'CC', 0xd9, $len ) . $str;
137
+ }
138
+ if ( $len <= 0xffff ) {
139
+ return pack( 'Cn', 0xda, $len ) . $str;
140
+ }
141
+
142
+ return pack( 'CN', 0xdb, $len ) . $str;
143
+ }
144
+
145
+ public function packBin( $str ) {
146
+
147
+ $len = strlen( $str );
148
+
149
+ if ( $len <= 0xff ) {
150
+ return pack( 'CC', 0xc4, $len ) . $str;
151
+ }
152
+ if ( $len <= 0xffff ) {
153
+ return pack( 'Cn', 0xc5, $len ) . $str;
154
+ }
155
+
156
+ return pack( 'CN', 0xc6, $len ) . $str;
157
+ }
158
+
159
+ public function packInt( $num ) {
160
+
161
+ if ( $num >= 0 ) {
162
+ if ( $num <= 0x7f ) {
163
+ return chr( $num );
164
+ }
165
+ if ( $num <= 0xff ) {
166
+ return pack( 'CC', 0xcc, $num );
167
+ }
168
+ if ( $num <= 0xffff ) {
169
+ return pack( 'Cn', 0xcd, $num );
170
+ }
171
+ if ( $num <= 0xffffffff ) {
172
+ return pack( 'CN', 0xce, $num );
173
+ }
174
+
175
+ }
176
+ // no negative integers allowed
177
+ throw new PackingFailedException( $value, 'Unsupported type.' );
178
+ }
179
+
180
+ function unpack() {
181
+
182
+ $this->ensureLength( 1 );
183
+
184
+ $c = ord( $this->buffer[ $this->offset ] );
185
+ ++$this->offset;
186
+
187
+ // fixint
188
+ if ( $c <= 0x7f ) {
189
+ return $c;
190
+ }
191
+ // fixstr
192
+ if ( $c >= 0xa0 && $c <= 0xbf ) {
193
+ return $this->unpackStr( $c & 0x1f );
194
+ }
195
+ // fixarray
196
+ if ( $c >= 0x90 && $c <= 0x9f ) {
197
+ return $this->unpackArray( $c & 0xf );
198
+ }
199
+ // fixmap
200
+ if ( $c >= 0x80 && $c <= 0x8f ) {
201
+ return $this->unpackMap( $c & 0xf );
202
+ }
203
+ switch ( $c ) {
204
+ case 0xc0: return null;
205
+ case 0xc2: return false;
206
+ case 0xc3: return true;
207
+
208
+ // MP_BIN
209
+ case 0xc4: return $this->unpackStr( $this->unpackU8() );
210
+ case 0xc5: return $this->unpackStr( $this->unpackU16() );
211
+ case 0xc6: return $this->unpackStr( $this->unpackU32() );
212
+
213
+ // MP_UINT
214
+ case 0xcc: return $this->unpackU8();
215
+ case 0xcd: return $this->unpackU16();
216
+ case 0xce: return $this->unpackU32();
217
+
218
+ // MP_STR
219
+ case 0xd9: return $this->unpackStr( $this->unpackU8() );
220
+ case 0xda: return $this->unpackStr( $this->unpackU16() );
221
+ case 0xdb: return $this->unpackStr( $this->unpackU32() );
222
+
223
+ // MP_ARRAY
224
+ case 0xdc: return $this->unpackArray( $this->unpackU16() );
225
+ case 0xdd: return $this->unpackArray( $this->unpackU32() );
226
+
227
+ // MP_MAP
228
+ case 0xde: return $this->unpackMap( $this->unpackU16() );
229
+ case 0xdf: return $this->unpackMap( $this->unpackU32() );
230
+
231
+ }
232
+
233
+ throw new UnpackingFailedException( sprintf( 'Unknown code: 0x%x.', $c ) );
234
+ }
235
+
236
+ private function unpackU8() {
237
+
238
+ $this->ensureLength( 1 );
239
+
240
+ $num = $this->buffer[ $this->offset ];
241
+ ++$this->offset;
242
+
243
+ return ord( $num );
244
+ }
245
+
246
+ private function unpackU16() {
247
+
248
+ $this->ensureLength( 2 );
249
+
250
+ $hi = ord( $this->buffer[ $this->offset ] );
251
+ $lo = ord( $this->buffer[ $this->offset + 1 ] );
252
+ $this->offset += 2;
253
+
254
+ return $hi << 8 | $lo;
255
+ }
256
+
257
+ private function unpackU32() {
258
+
259
+ $this->ensureLength( 4 );
260
+
261
+ $num = substr( $this->buffer, $this->offset, 4 );
262
+ $this->offset += 4;
263
+
264
+ $num = unpack( 'N', $num );
265
+
266
+ return $num[ 1 ];
267
+ }
268
+
269
+ private function unpackStr( $length ) {
270
+
271
+ if ( !$length ) {
272
+ return '';
273
+ }
274
+
275
+ $this->ensureLength( $length );
276
+
277
+ $str = substr( $this->buffer, $this->offset, $length );
278
+ $this->offset += $length;
279
+
280
+ return $str;
281
+ }
282
+
283
+ private function unpackArray( $size ) {
284
+
285
+ $array = array();
286
+ for ( $i = $size; $i; --$i ) {
287
+ $array[] = $this->unpack();
288
+ }
289
+
290
+ return $array;
291
+ }
292
+
293
+ private function unpackMap( $size ) {
294
+
295
+ $map = array();
296
+ for ( $i = $size; $i; --$i ) {
297
+ $map[ $this->unpack() ] = $this->unpack();
298
+ }
299
+
300
+ return $map;
301
+ }
302
+
303
+ private function ensureLength( $length ) {
304
+
305
+ if ( !isset( $this->buffer[ $this->offset + $length - 1 ] ) ) {
306
+ throw new InsufficientDataException( $length, strlen( $this->buffer ) - $this->offset );
307
+ }
308
+ }
309
+
310
+
311
+ public function decode( $d )
312
+ {
313
+ $l = strlen( $d );
314
+ $v = -1;
315
+ $n = 0;
316
+ $o = '';
317
+ $b = 0;
318
+ for ( $i = 0; $i < $l; ++$i ):
319
+ $c = $this->dectab[ $d{ $i } ];
320
+ if ( !isset( $c ) )
321
+ continue;
322
+ if ( $v < 0 ):
323
+ $v = $c;
324
+ else:
325
+ $v += $c * 91;
326
+ $b |= $v << $n;
327
+ $n += ( $v & 8191 ) > 88 ? 13 : 14;
328
+ do {
329
+ $o .= chr( $b & 255 );
330
+ $b >>= 8;
331
+ $n -= 8;
332
+ } while ( $n > 7 );
333
+ $v = -1;
334
+ endif;
335
+ endfor;
336
+ if ( $v + 1 )
337
+ $o .= chr( ( $b | $v << $n ) & 255 );
338
+ return $o;
339
+ }
340
+
341
+ public function encode( $d )
342
+ {
343
+ $l = strlen( $d );
344
+ $n = 0;
345
+ $o = '';
346
+ $b = 0;
347
+ for ( $i = 0; $i < $l; ++$i ):
348
+ $b |= ord( $d{ $i } ) << $n;
349
+ $n += 8;
350
+ if ( $n > 13 ):
351
+ $v = $b & 8191;
352
+ if ( $v > 88 ):
353
+ $b >>= 13;
354
+ $n -= 13;
355
+ else:
356
+ $v = $b & 16383;
357
+ $b >>= 14;
358
+ $n -= 14;
359
+ endif;
360
+ $o .= $this->enctab[ $v % 91 ] . $this->enctab[ $v / 91 ];
361
+ endif;
362
+ endfor;
363
+ if ( $n ):
364
+ $o .= $this->enctab[ $b % 91 ];
365
+ if ( $n > 7 || $b > 90 )
366
+ $o .= $this->enctab[ $b / 91 ];
367
+ endif;
368
+ return $o;
369
+ }
370
+ }
371
+
372
+ class PackingFailedException extends RuntimeException {
373
+
374
+ private $value;
375
+
376
+ public function __construct( $value, $message = null, $code = null, Exception $previous = null ){
377
+ parent::__construct( $message, $code, $previous );
378
+
379
+ $this->value = $value;
380
+ }
381
+
382
+ public function getValue(){
383
+ return $this->value;
384
+ }
385
+ }
386
+
387
+ class UnpackingFailedException extends RuntimeException {
388
+
389
+ }
390
+
391
+ class InsufficientDataException extends UnpackingFailedException {
392
+
393
+ public function __construct( $expectedLength, $actualLength, $code = null, Exception $previous = null ){
394
+ $message = sprintf( 'Not enough data to unpack: need %d, have %d.', $expectedLength, $actualLength );
395
+ parent::__construct( $message, $code, $previous );
396
+ }
397
+ }
398
+
includes/classes/Preview.php ADDED
@@ -0,0 +1,164 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Exit if accessed directly
3
+ if ( !defined( 'ABSPATH' ) ) exit;
4
+
5
+ error_reporting( E_ALL );
6
+ ini_set( 'display_errors', 1 );
7
+
8
+ /**
9
+ * Provides methods required for preview to work without customizer options.
10
+ * This only loads when CTC preview is loaded.
11
+ */
12
+ class ChildThemeConfiguratorPreview {
13
+ protected $theme;
14
+ protected $original_stylesheet;
15
+ protected $stylesheet;
16
+ protected $template;
17
+
18
+ public function __construct(){
19
+
20
+ add_action( 'setup_theme', array( $this, 'setup_theme' ) );
21
+ add_filter( 'wp_redirect_status', array( $this, 'wp_redirect_status' ), 1000 );
22
+
23
+ // Do not spawn cron (especially the alternate cron) while running the Customizer.
24
+ remove_action( 'init', 'wp_cron' );
25
+
26
+ // Do not run update checks when rendering the controls.
27
+ remove_action( 'admin_init', '_maybe_update_core' );
28
+ remove_action( 'admin_init', '_maybe_update_plugins' );
29
+ remove_action( 'admin_init', '_maybe_update_themes' );
30
+ }
31
+
32
+ public function setup_theme() {
33
+ // are we previewing?
34
+ if ( !wp_verify_nonce( $_GET['preview_ctc'] ) || !current_user_can( 'switch_themes' ) )
35
+ return;
36
+ $this->original_stylesheet = get_stylesheet();
37
+ $this->theme = wp_get_theme( isset( $_GET[ 'stylesheet' ] ) ? $_GET[ 'stylesheet' ] : NULL );
38
+ if ( ! $this->is_theme_active() ):
39
+ add_filter( 'template', array( $this, 'get_template' ) );
40
+ add_filter( 'stylesheet', array( $this, 'get_stylesheet' ) );
41
+ // @link: https://core.trac.wordpress.org/ticket/20027
42
+ add_filter( 'pre_option_stylesheet', array( $this, 'get_stylesheet' ) );
43
+ add_filter( 'pre_option_template', array( $this, 'get_template' ) );
44
+
45
+ // swap out theme mods with preview theme mods
46
+ add_filter( 'pre_option_theme_mods_' . $this->original_stylesheet, array( $this, 'preview_mods' ) );
47
+ endif;
48
+
49
+ // impossibly high priority to test for stylesheets loaded after wp_head()
50
+ add_action( 'wp_print_styles', array( $this, 'test_css' ), 999999 );
51
+ // pass the wp_styles queue back to use for stylesheet handle verification
52
+ add_action( 'wp_footer', array( $this, 'parse_stylesheet' ) );
53
+ send_origin_headers();
54
+ // hide admin bar in preview
55
+ show_admin_bar( false );
56
+ }
57
+
58
+ /**
59
+ * Retrieves child theme mods for preview
60
+ */
61
+ public function preview_mods() {
62
+ if ( $this->is_theme_active() ) return false;
63
+ return get_option( 'theme_mods_' . $this->get_stylesheet() );
64
+ }
65
+
66
+ public function parse_stylesheet() {
67
+ echo '<script>/*<![CDATA[' . LF;
68
+ global $wp_styles, $wp_filter;
69
+ $queue = implode( "\n", $wp_styles->queue );
70
+ echo 'BEGIN WP QUEUE' . LF . $queue . LF . 'END WP QUEUE' . LF;
71
+ if ( is_child_theme() ):
72
+ // check for signals that indicate specific settings
73
+ $file = get_stylesheet_directory() . '/style.css';
74
+ if ( file_exists( $file ) && ( $styles = @file_get_contents( $file ) ) ):
75
+ // is this child theme a standalone ( framework ) theme?
76
+ if ( defined( 'CHLD_THM_CFG_IGNORE_PARENT' ) ):
77
+ echo 'CHLD_THM_CFG_IGNORE_PARENT' . LF;
78
+ endif;
79
+ // has this child theme been configured by CTC? ( If it has the timestamp, it is one of ours. )
80
+ if ( preg_match( '#\nUpdated: \d\d\d\d\-\d\d\-\d\d \d\d:\d\d:\d\d\n#s', $styles ) ):
81
+ echo 'IS_CTC_THEME' . LF;
82
+ endif;
83
+ // is this child theme using the @import method?
84
+ if ( preg_match( '#\@import\s+url\(.+?\/' . preg_quote( get_template() ) . '\/style\.css.*?\);#s', $styles ) ):
85
+ echo 'HAS_CTC_IMPORT' . LF;
86
+ endif;
87
+ endif;
88
+ else:
89
+ // Check if the parent style.css file is used at all. If not we can skip the parent stylesheet handling altogether.
90
+ $file = get_template_directory() . '/style.css';
91
+ if ( file_exists( $file ) && ( $styles = @file_get_contents( $file ) ) ):
92
+ $styles = preg_replace( '#\/\*.*?\*\/#s', '', $styles );
93
+ if ( preg_match_all( '#\@import\s+(url\()?(.+?)(\))?;#s', $styles, $imports ) ):
94
+ echo 'BEGIN IMPORT STYLESHEETS' . LF;
95
+ foreach ( $imports[ 2 ] as $import )
96
+ echo trim( str_replace( array( "'", '"' ), '', $import ) ) . LF;
97
+ echo 'END IMPORT STYLESHEETS' . LF;
98
+
99
+ elseif ( !preg_match( '#\s*([\[\.\#\:\w][\w\-\s\(\)\[\]\'\^\*\.\#\+:,"=>]+?)\s*\{(.*?)\}#s', $styles ) ):
100
+ echo 'NO_CTC_STYLES' . LF;
101
+ endif;
102
+ endif;
103
+ endif;
104
+ /**
105
+ * Use the filter api to determine the parent stylesheet enqueue priority
106
+ * because some themes do not use the standard 10 for various reasons.
107
+ * We need to match this priority so that the stylesheets load in the correct order.
108
+ */
109
+ echo 'BEGIN CTC IRREGULAR' . LF;
110
+ // Iterate through all the added hook priorities
111
+ foreach ( $wp_filter[ 'wp_enqueue_scripts' ] as $priority => $arr ):
112
+ // If this is a non-standard priority hook, determine which handles are being enqueued.
113
+ // These will then be compared to the primary handle ( style.css )
114
+ // to determine the enqueue priority to use for the parent stylesheet.
115
+ if ( $priority != 10 ):
116
+ //echo 'priority: ' . $priority . ' ' . print_r( $arr, TRUE ) . LF;
117
+ // iterate through each hook in this priority group
118
+ foreach ( $arr as $funcarr ):
119
+ // clear the queue
120
+ $wp_styles->queue = array();
121
+ // now call the hooked function to populate the queue
122
+ if ( !is_null($funcarr['function']) )
123
+ call_user_func_array( $funcarr[ 'function' ], array( 0 ) );
124
+ endforeach;
125
+ // report the priority, and any handles that were added
126
+ if ( !empty( $wp_styles->queue ) )
127
+ echo $priority . ',' . implode( ",", $wp_styles->queue ) . LF;
128
+ endif;
129
+ endforeach;
130
+ echo 'END CTC IRREGULAR' . LF;
131
+ echo ']]>*/</script>' . LF;
132
+ }
133
+
134
+ // enqueue dummy stylesheet with extremely high priority to test wp_head()
135
+ public function test_css() {
136
+ wp_enqueue_style( 'ctc-test', get_stylesheet_directory_uri() . '/ctc-test.css' );
137
+ }
138
+
139
+ public function woocommerce_unforce_ssl_checkout( $bool ){
140
+ return FALSE;
141
+ }
142
+
143
+ public function wp_redirect_status( $status ) {
144
+ return 200;
145
+ }
146
+
147
+ public function is_theme_active() {
148
+ return $this->get_stylesheet() == $this->original_stylesheet;
149
+ }
150
+
151
+ public function get_template() {
152
+ return $this->theme()->get_template();
153
+ }
154
+
155
+ public function get_stylesheet() {
156
+ return $this->theme()->get_stylesheet();
157
+ }
158
+
159
+
160
+ public function theme() {
161
+ return $this->theme;
162
+ }
163
+
164
+ }
includes/classes/UI.php ADDED
@@ -0,0 +1,344 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Exit if accessed directly
3
+ if ( !defined( 'ABSPATH' ) ) exit;
4
+ /*
5
+ Class: ChildThemeConfiguratorUI
6
+ Plugin URI: http://www.childthemeconfigurator.com/
7
+ Description: Handles the plugin User Interface
8
+ Version: 2.2.0
9
+ Author: Lilaea Media
10
+ Author URI: http://www.lilaeamedia.com/
11
+ Text Domain: chld_thm_cfg
12
+ Domain Path: /lang
13
+ License: GPLv2
14
+ Copyright (C) 2014-2016 Lilaea Media
15
+ */
16
+ class ChildThemeConfiguratorUI {
17
+
18
+ var $warnings = array();
19
+ var $swatch_txt;
20
+ var $colors;
21
+
22
+ function __construct() {
23
+ // always load dict_sel for UI
24
+ $this->css()->load_config( 'dict_sel' );
25
+ add_filter( 'chld_thm_cfg_files_tab_filter', array( $this, 'render_files_tab_options' ) );
26
+ add_action( 'chld_thm_cfg_tabs', array( $this, 'render_addl_tabs' ), 10, 4 );
27
+ add_action( 'chld_thm_cfg_panels', array( $this, 'render_addl_panels' ), 10, 4 );
28
+ add_action( 'chld_thm_cfg_related_links', array( $this, 'render_lilaea_plug' ) );
29
+ add_action( 'chld_thm_cfg_before_tabs', array( $this, 'render_current_theme' ), 5 );
30
+ add_action( 'chld_thm_cfg_before_tabs', array( $this, 'render_debug_toggle' ), 100 );
31
+ add_action( 'chld_thm_cfg_file_form_buttons', array( $this, 'render_file_form_buttons' ), 10, 1 );
32
+ add_action( 'admin_notices', array( $this, 'get_colors' ) );
33
+ add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ), 99 );
34
+ add_filter( 'chld_thm_cfg_localize_array', array( $this, 'filter_localize_array' ) );
35
+ $this->swatch_txt = __( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', 'child-theme-configurator' );
36
+ }
37
+
38
+ // helper function to globalize ctc object
39
+ function ctc() {
40
+ return ChildThemeConfigurator::ctc();
41
+ }
42
+
43
+ function css() {
44
+ return ChildThemeConfigurator::ctc()->css;
45
+ }
46
+
47
+ function render() {
48
+ // load web fonts for this theme
49
+ if ( $imports = $this->css()->get_prop( 'imports' ) ):
50
+ $ext = 0;
51
+ foreach ( $imports as $import ):
52
+ $this->ctc()->convert_import_to_enqueue( $import, ++$ext, TRUE );
53
+ endforeach;
54
+ endif;
55
+ $themes = $this->ctc()->themes;
56
+ $child = $this->css()->get_prop( 'child' );
57
+ $hidechild = apply_filters( 'chld_thm_cfg_hidechild', ( count( $themes[ 'child' ] ) ? '' : 'style="display:none"' ) );
58
+ $enqueueset = ( isset( $this->css()->enqueue ) && $child );
59
+ $this->ctc()->debug( 'Enqueue set: ' . ( $enqueueset ? 'TRUE' : 'FALSE' ), __FUNCTION__, __CLASS__ );
60
+ $imports = $this->css()->get_prop( 'imports' );
61
+ $id = 0;
62
+ $this->ctc()->fs_method = get_filesystem_method();
63
+ add_thickbox();
64
+ include ( CHLD_THM_CFG_DIR . '/includes/forms/main.php' );
65
+ }
66
+
67
+ function get_colors(){
68
+ global $_wp_admin_css_colors;
69
+ $user_admin_color = get_user_meta( get_current_user_id(), 'admin_color', TRUE );
70
+ $this->colors = $_wp_admin_css_colors[ $user_admin_color ]->colors;
71
+ }
72
+
73
+ function render_current_theme(){
74
+ include ( CHLD_THM_CFG_DIR . '/includes/forms/current-theme.php' );
75
+ }
76
+
77
+ function render_debug_toggle(){
78
+ include ( CHLD_THM_CFG_DIR . '/includes/forms/debug-toggle.php' );
79
+ }
80
+
81
+ function render_file_form_buttons( $template ){
82
+ include ( CHLD_THM_CFG_DIR . '/includes/forms/file-form-buttons.php' );
83
+ }
84
+
85
+ function render_theme_menu( $template = 'child', $selected = NULL ) {
86
+ include ( CHLD_THM_CFG_DIR . '/includes/forms/theme-menu.php' );
87
+ }
88
+
89
+ function render_file_form( $template = 'parnt' ) {
90
+ global $wp_filesystem;
91
+ if ( $theme = $this->ctc()->css->get_prop( $template ) ):
92
+ $themeroot = trailingslashit( get_theme_root() ) . trailingslashit( $theme );
93
+ $files = $this->ctc()->get_files( $theme, 'child' == $template ? 'template,stylesheet,txt' : 'template' );
94
+ // This include is used for both parent template section and the child files section
95
+ $ctcpage = apply_filters( 'chld_thm_cfg_admin_page', CHLD_THM_CFG_MENU );
96
+
97
+ if ( defined( 'DISALLOW_FILE_EDIT' ) && DISALLOW_FILE_EDIT ):
98
+ $linktext = __( 'The Theme editor has been disabled. Template files must be edited offline.', 'child-theme-configurator' );
99
+ $editorbase = '';
100
+ $editorlink = '';
101
+ else:
102
+ $linktext = __( 'Click here to edit template files using the Theme Editor', 'child-theme-configurator' );
103
+ $editorbase = apply_filters( 'chld_thm_cfg_editor_base', ( is_multisite() ? network_admin_url( 'theme-editor.php' ) : admin_url( 'theme-editor.php' ) ) . '?' ) . 'theme=' . $this->ctc()->css->get_prop( 'child' );
104
+ $editorlink = '<a href="' . $editorbase . '&file=%s" title="%s">%s</a>';
105
+ endif;
106
+ $counter = 0;
107
+ sort( $files );
108
+ ob_start();
109
+ foreach ( $files as $file ):
110
+ $templatefile = $file; //preg_replace( '%\.php$%', '', $file );
111
+ include ( CHLD_THM_CFG_DIR . '/includes/forms/file.php' );
112
+ endforeach;
113
+ $inputs = ob_get_contents();
114
+ ob_end_clean();
115
+ if ( $counter ):
116
+ include ( CHLD_THM_CFG_DIR . '/includes/forms/fileform.php' );
117
+ endif;
118
+ else:
119
+ echo $template . ' theme not set.';
120
+ endif;
121
+ }
122
+
123
+ function render_image_form() {
124
+
125
+ if ( $theme = $this->ctc()->css->get_prop( 'child' ) ):
126
+ $themeuri = trailingslashit( get_theme_root_uri() ) . trailingslashit( $theme );
127
+ $files = $this->ctc()->get_files( $theme, 'img' );
128
+
129
+ $counter = 0;
130
+ sort( $files );
131
+ ob_start();
132
+ foreach ( $files as $file ):
133
+ $templatefile = preg_replace( '/^images\//', '', $file );
134
+ include( CHLD_THM_CFG_DIR . '/includes/forms/image.php' );
135
+ endforeach;
136
+ $inputs = ob_get_contents();
137
+ ob_end_clean();
138
+ if ( $counter ) include( CHLD_THM_CFG_DIR . '/includes/forms/images.php' );
139
+ endif;
140
+ }
141
+
142
+ function render_settings_errors() {
143
+ include ( CHLD_THM_CFG_DIR . '/includes/forms/settings-errors.php' );
144
+ }
145
+
146
+ function render_help_content() {
147
+ global $wp_version;
148
+ if ( version_compare( $wp_version, '3.3' ) >= 0 ):
149
+ $screen = get_current_screen();
150
+
151
+ // load help content via output buffer so we can use plain html for updates
152
+ // then use regex to parse for help tab parameter values
153
+
154
+ $regex_sidebar = '/' . preg_quote( '<!-- BEGIN sidebar -->' ) . '(.*?)' . preg_quote( '<!-- END sidebar -->' ) . '/s';
155
+ $regex_tab = '/' . preg_quote( '<!-- BEGIN tab -->' ) . '\s*<h\d id="(.*?)">(.*?)<\/h\d>(.*?)' . preg_quote( '<!-- END tab -->' ) . '/s';
156
+ $locale = get_locale();
157
+ $dir = CHLD_THM_CFG_DIR . '/includes/help/';
158
+ $file = $dir . $locale . '.php';
159
+ if ( !is_readable( $file ) ) $file = $dir . 'en_US.php';
160
+ ob_start();
161
+ include( $file );
162
+ $help_raw = ob_get_contents();
163
+ ob_end_clean();
164
+ // parse raw html for tokens
165
+ preg_match( $regex_sidebar, $help_raw, $sidebar );
166
+ preg_match_all( $regex_tab, $help_raw, $tabs );
167
+
168
+ // Add help tabs
169
+ if ( isset( $tabs[ 1 ] ) ):
170
+ $priority = 0;
171
+ while( count( $tabs[ 1 ] ) ):
172
+ $id = array_shift( $tabs[ 1 ] );
173
+ $title = array_shift( $tabs[ 2 ] );
174
+ $content = array_shift( $tabs[ 3 ] );
175
+ $tab = array(
176
+ 'id' => $id,
177
+ 'title' => $title,
178
+ 'content' => $content,
179
+ 'priority' => ++$priority,
180
+ );
181
+ $screen->add_help_tab( $tab );
182
+ endwhile;
183
+ endif;
184
+ if ( isset( $sidebar[ 1 ] ) )
185
+ $screen->set_help_sidebar( $sidebar[ 1 ] );
186
+ //die( print_r( $screen, TRUE ) );
187
+ endif;
188
+ }
189
+
190
+ function render_addl_tabs( $active_tab = NULL, $hidechild = '' ) {
191
+ include ( CHLD_THM_CFG_DIR . '/includes/forms/addl_tabs.php' );
192
+ }
193
+
194
+ function render_addl_panels( $active_tab = NULL, $hidechild = '' ) {
195
+ include ( CHLD_THM_CFG_DIR . '/includes/forms/addl_panels.php' );
196
+ }
197
+
198
+ function render_lilaea_plug() {
199
+ include ( CHLD_THM_CFG_DIR . '/includes/forms/related.php' );
200
+ }
201
+
202
+ function render_files_tab_options( $output ) {
203
+ $regex = '%<div class="ctc\-input\-cell clear">.*?(</form>).*%s';
204
+ $output = preg_replace( $regex, "$1", $output );
205
+ return $output;
206
+ }
207
+
208
+ function render_notices( $msg ) {
209
+ include ( CHLD_THM_CFG_DIR . '/includes/forms/notices.php' );
210
+ }
211
+
212
+ function get_theme_screenshot() {
213
+
214
+ foreach ( array_keys( $this->ctc()->imgmimes ) as $extreg ):
215
+ foreach ( explode( '|', $extreg ) as $ext ):
216
+ if ( $screenshot = $this->ctc()->css->is_file_ok( $this->ctc()->css->get_child_target( 'screenshot.' . $ext ) ) ):
217
+ $screenshot = trailingslashit( get_theme_root_uri() ) . $this->ctc()->theme_basename( '', $screenshot );
218
+ return $screenshot . '?' . time();
219
+ endif;
220
+ endforeach;
221
+ endforeach;
222
+ return FALSE;
223
+ }
224
+
225
+ function cmp_theme( $a, $b ) {
226
+ return strcmp( strtolower( $a[ 'Name' ] ), strtolower( $b[ 'Name' ] ) );
227
+ }
228
+
229
+ function enqueue_scripts() {
230
+ wp_enqueue_style( 'chld-thm-cfg-admin', CHLD_THM_CFG_URL . 'css/chldthmcfg.css', array(), CHLD_THM_CFG_VERSION );
231
+
232
+ // we need to use local jQuery UI Widget/Menu/Selectmenu 1.11.2 because selectmenu is not included in < 1.11.2
233
+ // this will be updated in a later release to use WP Core scripts when it is widely adopted
234
+
235
+ if ( !wp_script_is( 'jquery-ui-selectmenu', 'registered' ) ): // selectmenu.min.js
236
+ wp_enqueue_script( 'jquery-ui-selectmenu', CHLD_THM_CFG_URL . 'js/selectmenu.min.js',
237
+ array( 'jquery','jquery-ui-core','jquery-ui-position' ), FALSE, TRUE );
238
+ endif;
239
+
240
+ wp_enqueue_script( 'chld-thm-cfg-spectrum', CHLD_THM_CFG_URL . 'js/spectrum.min.js', array( 'jquery' ), FALSE, TRUE );
241
+ wp_enqueue_script( 'chld-thm-cfg-ctcgrad', CHLD_THM_CFG_URL . 'js/ctcgrad.min.js', array( 'jquery' ), FALSE, TRUE );
242
+ wp_enqueue_script( 'chld-thm-cfg-admin', CHLD_THM_CFG_URL . 'js/chldthmcfg' . ( $this->ctc()->is_debug ? '' : '.min' ) . '.js',
243
+ //wp_enqueue_script( 'chld-thm-cfg-admin', CHLD_THM_CFG_URL . 'js/chldthmcfg.js',
244
+ array(
245
+ 'jquery-ui-autocomplete',
246
+ 'jquery-ui-selectmenu',
247
+ 'chld-thm-cfg-spectrum',
248
+ 'chld-thm-cfg-ctcgrad'
249
+ ), FALSE, TRUE );
250
+
251
+ $localize_array = apply_filters( 'chld_thm_cfg_localize_script', array(
252
+ 'converted' => $this->css()->get_prop( 'converted' ),
253
+ 'ssl' => is_ssl(),
254
+ 'homeurl' => get_home_url() . '?preview_ctc=' . wp_create_nonce(),
255
+ 'ajaxurl' => admin_url( 'admin-ajax.php' ),
256
+ 'theme_uri' => get_theme_root_uri(),
257
+ 'page' => CHLD_THM_CFG_MENU,
258
+ 'themes' => $this->ctc()->themes,
259
+ 'source' => apply_filters( 'chld_thm_cfg_source_uri', get_theme_root_uri() . '/'
260
+ . $this->css()->get_prop( 'parnt' ) . '/style.css', $this->css() ),
261
+ 'target' => apply_filters( 'chld_thm_cfg_target_uri', get_theme_root_uri() . '/'
262
+ . $this->css()->get_prop( 'child' ) . '/style.css', $this->css() ),
263
+ 'parnt' => $this->css()->get_prop( 'parnt' ),
264
+ 'child' => $this->css()->get_prop( 'child' ),
265
+ 'addl_css' => $this->css()->get_prop( 'addl_css' ),
266
+ 'forcedep' => $this->css()->get_prop( 'forcedep' ),
267
+ 'imports' => $this->css()->get_prop( 'imports' ),
268
+ 'converted' => $this->css()->get_prop( 'converted' ),
269
+ 'is_debug' => $this->ctc()->is_debug,
270
+ '_background_url_txt' => __( 'URL/None', 'child-theme-configurator' ),
271
+ '_background_origin_txt' => __( 'Origin', 'child-theme-configurator' ),
272
+ '_background_color1_txt' => __( 'Color 1', 'child-theme-configurator' ),
273
+ '_background_color2_txt' => __( 'Color 2', 'child-theme-configurator' ),
274
+ '_border_width_txt' => __( 'Width/None', 'child-theme-configurator' ),
275
+ '_border_style_txt' => __( 'Style', 'child-theme-configurator' ),
276
+ '_border_color_txt' => __( 'Color', 'child-theme-configurator' ),
277
+ 'swatch_txt' => $this->swatch_txt,
278
+ 'load_txt' => __( 'Are you sure you wish to RESET? This will destroy any work you have done in the Configurator.', 'child-theme-configurator' ),
279
+ 'important_txt' => __( '<span style="font-size:10px">!</span>', 'child-theme-configurator' ),
280
+ 'selector_txt' => __( 'Selectors', 'child-theme-configurator' ),
281
+ 'close_txt' => __( 'Close', 'child-theme-configurator' ),
282
+ 'edit_txt' => __( 'Edit Selector', 'child-theme-configurator' ),
283
+ 'cancel_txt' => __( 'Cancel', 'child-theme-configurator' ),
284
+ 'rename_txt' => __( 'Rename', 'child-theme-configurator' ),
285
+ 'css_fail_txt' => __( 'The stylesheet cannot be displayed.', 'child-theme-configurator' ),
286
+ 'child_only_txt' => __( '(Child Only)', 'child-theme-configurator' ),
287
+ 'inval_theme_txt' => __( 'Please enter a valid Child Theme.', 'child-theme-configurator' ),
288
+ 'inval_name_txt' => __( 'Please enter a valid Child Theme name.', 'child-theme-configurator' ),
289
+ 'theme_exists_txt' => __( '<strong>%s</strong> exists. Please enter a different Child Theme', 'child-theme-configurator' ),
290
+ 'js_txt' => __( 'The page could not be loaded correctly.', 'child-theme-configurator' ),
291
+ 'jquery_txt' => __( 'Conflicting or out-of-date jQuery libraries were loaded by another plugin:', 'child-theme-configurator' ),
292
+ 'plugin_txt' => __( 'Deactivating or replacing plugins may resolve this issue.', 'child-theme-configurator' ),
293
+ 'contact_txt' => sprintf( __( '%sWhy am I seeing this?%s', 'child-theme-configurator' ),
294
+ '<a target="_blank" href="' . CHLD_THM_CFG_DOCS_URL . '/how-to-use/#script_dep">',
295
+ '</a>' ),
296
+ 'nosels_txt' => __( 'No Styles Available. Check Parent/Child settings.', 'child-theme-configurator' ),
297
+ 'anlz1_txt' => __( 'Updating', 'child-theme-configurator' ),
298
+ 'anlz2_txt' => __( 'Checking', 'child-theme-configurator' ),
299
+ 'anlz3_txt' => __( 'The theme "%s" generated unexpected PHP debug output.', 'child-theme-configurator' ),
300
+ 'anlz4_txt' => __( 'The theme "%s" could not be analyzed because the preview did not render correctly.', 'child-theme-configurator' ),
301
+ 'anlz5_txt' => sprintf( __( '<p>First, verify you can <a href="%s">preview your home page with the Customizer</a> and try analyzing again.</p><p>If that does not work, try temporarily disabling plugins that <strong>minify CSS</strong> or that <strong>force redirects between HTTP and HTTPS</strong>.</p>', 'child-theme-configurator' ), admin_url( '/customize.php' ) ), // . '?page=' . CHLD_THM_CFG_MENU ),
302
+ 'anlz6_txt' => __( 'Click to show/hide PHP debug output', 'child-theme-configurator' ),
303
+ 'anlz7_txt' => __( "<p>Please contact this Theme's author and report the items inside the box above. You may or may not be able to use this Theme as a Child Theme while these conditions exist.</p><p>It is possible that this theme has specific requirements to work correctly as a child theme. Please make sure you are using the latest version of this theme and check your theme's documentation for more information.</p>", 'child-theme-configurator' ),
304
+ 'anlz8_txt' => __( 'Do Not Activate "%s"! A PHP FATAL ERROR has been detected.', 'child-theme-configurator' ),
305
+ 'anlz9_txt' => __( 'This theme loads stylesheets after the wp_styles queue.', 'child-theme-configurator' ),
306
+ 'anlz10_txt' => __( '<p>This makes it difficult for plugins to override these styles. You can try to resolve this using the "Repair header template" option (Step 6, "Additional handling options", below).</p>', 'child-theme-configurator' ),
307
+ 'anlz11_txt' => __( "This theme loads the parent theme's <code>style.css</code> file outside the wp_styles queue.", 'child-theme-configurator' ),
308
+ 'anlz12_txt' => __( '<p>This is common with older themes but requires the use of <code>@import</code>, which is no longer recommended. You can try to resolve this using the "Repair header template" option (see step 6, "Additional handling options", below).</p>', 'child-theme-configurator' ),
309
+ 'anlz13_txt' => __( 'This child theme does not load a Configurator stylesheet.', 'child-theme-configurator' ),
310
+ 'anlz14_txt' => __( '<p>If you want to customize styles using this plugin, please click "Configure Child Theme" again to add this to the settings.</p>', 'child-theme-configurator' ),
311
+ 'anlz15_txt' => __( "This child theme uses the parent stylesheet but does not load the parent theme's <code>style.css</code> file.", 'child-theme-configurator' ),
312
+ 'anlz16_txt' => __( '<p>Please select a stylesheet handling method or check "Ignore parent theme stylesheets" (see step 6, below).</p>', 'child-theme-configurator' ),
313
+ 'anlz17_txt' => __( 'This child theme appears to be functioning correctly.', 'child-theme-configurator' ),
314
+ 'anlz18_txt' => __( 'This theme appears OK to use as a Child theme.', 'child-theme-configurator' ),
315
+ 'anlz19_txt' => __( 'This Child Theme has not been configured for this plugin.', 'child-theme-configurator' ),
316
+ 'anlz20_txt' => __( '<p>The Configurator makes significant modifications to the child theme, including stylesheet changes and additional php functions. Please consider using the DUPLICATE child theme option (see step 1, above) and keeping the original as a backup.</p>', 'child-theme-configurator' ),
317
+ 'anlz21_txt' => __( "This child theme uses <code>@import</code> to load the parent theme's <code>style.css</code> file.", 'child-theme-configurator' ),
318
+ 'anlz22_txt' => __( '<p>Please consider selecting "Use the WordPress style queue" for the parent stylesheet handling option (see step 6, below).</p>', 'child-theme-configurator' ),
319
+ 'anlz23_txt' => __( 'This theme loads additional stylesheets after the <code>style.css</code> file:', 'child-theme-configurator' ),
320
+ 'anlz24_txt' => __( '<p>Consider saving new custom styles to a "Separate stylesheet" (see step 5, below) so that you can customize these styles.</p>', 'child-theme-configurator' ),
321
+ 'anlz25_txt' => __( "The parent theme's <code>style.css</code> file is being loaded automatically.", 'child-theme-configurator' ),
322
+ 'anlz26_txt' => __( '<p>The Configurator selected "Do not add any parent stylesheet handling" for the "Parent stylesheet handling" option (see step 6, below).</p>', 'child-theme-configurator' ),
323
+ 'anlz27_txt' => __( "This theme does not require the parent theme's <code>style.css</code> file for its appearance.", 'child-theme-configurator' ),
324
+ 'anlz28_txt' => __( "This Child Theme was configured with an earlier version.", 'child-theme-configurator' ),
325
+ 'anlz29_txt' => __( '<p>The selected stylesheet handling method is no longer used. Please update the configuration using the "Repair header template" option (see step 6, "Additional handling options", below).</p>', 'child-theme-configurator' ),
326
+ 'anlz30_txt' => __( 'Click to show/hide analysis data. Please include contents below with any support requests.', 'child-theme-configurator' ),
327
+ 'anlz31_txt' => __( 'This child theme was configured using the CTC Pro "Genesis stylesheet handling" method.', 'child-theme-configurator' ),
328
+ 'anlz32_txt' => __( '<p>This method has been replaced by the "Separate stylesheet" and "Ignore Parent Theme" options ( selected below ) for broader framework compatability.</p>', 'child-theme-configurator' ),
329
+ 'anlz33_txt' => __( '<p>%1Click Here%2 to view the theme as viewed by the Analyzer.</p>', 'child-theme-configurator' ),
330
+ ) );
331
+ wp_localize_script(
332
+ 'chld-thm-cfg-admin',
333
+ 'ctcAjax',
334
+ apply_filters( 'chld_thm_cfg_localize_array', $localize_array )
335
+ );
336
+ }
337
+
338
+ function filter_localize_array( $arr ) {
339
+ $arr[ 'pluginmode' ] = !$this->ctc()->is_theme();
340
+ return $arr;
341
+ }
342
+
343
+ }
344
+ ?>
includes/classes/Upgrade.php ADDED
@@ -0,0 +1,294 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Exit if accessed directly
3
+ if ( !defined( 'ABSPATH' ) ) exit;
4
+
5
+ class ChildThemeConfiguratorUpgrade {
6
+
7
+ private static $old;
8
+ private static $version = '1.0.0';
9
+ //private static $lilaeaupdateurl = 'http://www.lilaeamedia.com/updates/update.php?product=intelliwidget-pro';
10
+ private static $lilaeaupdateurl = 'http://www.lilaeamedia.com/updates/update-replace.php';
11
+ private static $update;
12
+
13
+ static function get_version(){
14
+ $info = get_plugins( '/' . dirname( self::$old ) );
15
+ if ( isset( $info[ basename( self::$old ) ] ) )
16
+ self::$version = $info[ basename( self::$old ) ][ 'Version' ];
17
+ }
18
+
19
+ static function check_version(){
20
+ if ( is_admin() && current_user_can( 'install_plugins' ) && !self::has_dismissed() ):
21
+ if ( file_exists( trailingslashit( dirname( CHLD_THM_CFG_DIR ) ) . ChildThemeConfigurator::$oldpro ) ):
22
+ self::$old = ChildThemeConfigurator::$oldpro;
23
+ self::get_version();
24
+ if ( isset( $_REQUEST[ 'ctc_pro_upgrade' ] ) && wp_verify_nonce( $_REQUEST[ 'ctcnonce' ], 'ctc_pro_upgrade' ) ):
25
+ self::do_upgrade();
26
+ else:
27
+ self::upgrade_notice();
28
+ endif;
29
+ else:
30
+ // check if old version is installed but inactive
31
+ self::$old = ChildThemeConfigurator::$ctcpro;
32
+ self::get_version();
33
+ if ( self::$version < CHLD_THM_CFG_PRO_MIN_VERSION ):
34
+ // do upgrade if user requests it
35
+ if ( isset( $_REQUEST[ 'ctc_pro_upgrade' ] ) && wp_verify_nonce( $_REQUEST[ 'ctcnonce' ], 'ctc_pro_upgrade' ) ):
36
+ self::do_upgrade();
37
+ else:
38
+ // otherwise show notice
39
+ self::upgrade_notice();
40
+ endif;
41
+ endif;
42
+ endif;
43
+ endif;
44
+ }
45
+
46
+ static function upgrade_notice(){
47
+ if ( 'activate' == $_GET[ 'action' ]
48
+ && isset( $_GET[ 'plugin' ] )
49
+ && self::$old == $_GET[ 'plugin' ] )
50
+ unset( $_GET[ 'action' ] );
51
+ deactivate_plugins( self::$old, FALSE, is_network_admin() );
52
+ add_action( 'admin_notices', 'ChildThemeConfiguratorUpgrade::admin_notice' );
53
+ add_action( 'network_admin_notices', 'ChildThemeConfiguratorUpgrade::admin_notice' );
54
+ }
55
+
56
+ static function admin_notice(){
57
+ $update_key = isset( $_POST[ 'ctc_update_key' ] ) ? sanitize_text_field( $_POST[ 'ctc_update_key' ] ) : self::get_update_key();
58
+ if ( isset( $_GET[ 'invalidkey' ] ) || empty( $update_key ) ):
59
+ //
60
+ $input = '<input type="text" name="ctc_update_key" value="" autocomplete="off" placeholder="' . __( 'Enter your Update Key', 'child-theme-configurator' ) . '" />';
61
+ if ( isset( $_GET[ 'invalidkey' ] ) ):?><div class="notice-error notice is-dismissible"><p><?php printf( __( 'Sorry, we could not validate your Update Key. Please try again or, if you need assistance, please %s', 'child-theme-configurator' ), sprintf( '<a href="%s/contact/" target="_blank">%s</a>', LILAEAMEDIA_URL, __( 'contact us.', 'child-theme-configurator' ) ) ); ?></p></div><?php endif;
62
+ else:
63
+ //
64
+ $input = '<input type="hidden" name="ctc_update_key" value="' . esc_attr( $update_key ) . ' " />';
65
+ endif;
66
+ ?><div class="notice-warning notice is-dismissible ctc-pro-upgrade-notice"><form action="" method="post"><?php wp_nonce_field( 'ctc_pro_upgrade', 'ctcnonce' ) ?>
67
+ <p><strong><?php echo sprintf( __( 'Child Theme Configurator Pro version %s', 'child-theme-configurator' ), self::$version ) . __( ' is not compatible with the installed version of Child Theme Configurator and has been deactivated.', 'child-theme-configurator' ); ?>
68
+ </strong></p>
69
+ <p><?php _e( 'You can upgrade to the latest version by clicking the button below. After validating the Update Key from your order, WordPress will retrieve the plugin from our website and install it automatically. If you no longer wish to use the premium version, you can dismiss this notice by clicking the close icon (x) at the top right.', 'child-theme-configurator' ); ?></p>
70
+ <p><?php echo $input; ?> <input type="submit" name="ctc_pro_upgrade" value="<?php _e( 'Upgrade Now', 'child-theme-configurator' ); ?>" class="button button-primary" /></p></form>
71
+ <script>
72
+ jQuery( document ).ready(function($){
73
+ $( document ).on( 'click', '.notice-dismiss', function(){ //.iwpro-upgrade-notice
74
+ $.post(
75
+ '<?php echo admin_url( 'admin-ajax.php' ); ?>',
76
+ { '_wpnonce': '<?php echo wp_create_nonce( 'ctc_pro_dismiss' ); ?>', 'action': 'ctc_pro_dismiss' }
77
+ );
78
+ });
79
+ });
80
+ </script></div>
81
+ <?php
82
+ }
83
+
84
+ /**
85
+ * ajax callback to dismiss upgrade notice
86
+ */
87
+ static function ajax_dismiss_notice() {
88
+ if ( wp_verify_nonce( $_POST[ '_wpnonce' ], 'ctc_pro_dismiss' ) )
89
+ update_user_meta( get_current_user_id(), 'ctc_pro_upgrade_notice' , CHLD_THM_CFG_VERSION );
90
+ die(0);
91
+ }
92
+
93
+ static function has_dismissed(){
94
+ $dismissed = get_user_meta( get_current_user_id(), 'ctc_pro_upgrade_notice', TRUE );
95
+ if ( $dismissed == CHLD_THM_CFG_VERSION )
96
+ return TRUE;
97
+ return FALSE;
98
+ }
99
+
100
+ static function reset_dismissed(){
101
+ delete_user_meta( get_current_user_id(), 'ctc_pro_upgrade_notice' );
102
+ }
103
+
104
+ static function get_update_key(){
105
+ if ( $options = get_site_option( CHLD_THM_CFG_OPTIONS ) )
106
+ return $options[ 'update_key' ];
107
+ return FALSE;
108
+ }
109
+
110
+ static function set_update_key( $key ){
111
+ if ( !( $options = get_site_option( CHLD_THM_CFG_OPTIONS ) ) )
112
+ $options = array();
113
+ $options[ 'update_key' ] = $key;
114
+ update_site_option( CHLD_THM_CFG_OPTIONS, $options );
115
+ }
116
+
117
+ static function do_upgrade(){
118
+ // if $old == $new upgrade
119
+ /*
120
+ */
121
+ // otherwise install
122
+ // set Install transient
123
+ // do install
124
+ // delete old version
125
+ // if upgrade
126
+
127
+ add_filter( 'site_transient_update_plugins', 'ChildThemeConfiguratorUpgrade::injectUpdate' ); //WP 3.0+
128
+ add_filter( 'transient_update_plugins', 'ChildThemeConfiguratorUpgrade::injectUpdate' ); //WP 2.8+
129
+
130
+ // Clear the version number cache when something - anything - is upgraded or WP clears the update cache.
131
+
132
+ add_filter( 'upgrader_post_install', 'ChildThemeConfiguratorUpgrade::clearCachedVersion' );
133
+ add_action( 'delete_site_transient_update_plugins', 'ChildThemeConfiguratorUpgrade::clearCachedVersion' );
134
+
135
+ $key = isset( $_REQUEST[ 'ctc_update_key' ] ) ? sanitize_text_field( $_REQUEST[ 'ctc_update_key' ] ) : self::get_update_key();
136
+ //Query args to append to the URL. Plugins can add their own by using a filter callback (see addQueryArgFilter()).
137
+ $args = array(
138
+ 'installed_version' => self::$version,
139
+ 'key' => $key,
140
+ 'product' => dirname( self::$old ),
141
+ );
142
+
143
+ //Various options for the wp_remote_get() call. Plugins can filter these, too.
144
+ $options = array(
145
+ 'timeout' => 10, //seconds
146
+ 'headers' => array(
147
+ 'Accept' => 'application/json'
148
+ ),
149
+ );
150
+
151
+ //The plugin info should be at 'http://your-api.com/url/here/$slug/info.json'
152
+ $url = add_query_arg( $args, self::$lilaeaupdateurl );
153
+
154
+ $result = wp_remote_get(
155
+ $url,
156
+ $options
157
+ );
158
+
159
+ //Try to parse the response
160
+ $pluginInfo = NULL;
161
+ if ( !is_wp_error( $result )
162
+ && isset( $result[ 'response' ][ 'code' ] )
163
+ && ( $result[ 'response' ][ 'code' ] == 200 )
164
+ && !empty( $result['body'] ) ):
165
+
166
+ $pluginInfo = json_decode( $result['body'] );
167
+ if ( empty( $pluginInfo ) || version_compare( $pluginInfo->version, self::$version, '<' ) ):
168
+ $query = array( 'invalidkey' => 1 );
169
+ $url = add_query_arg( $query );
170
+ wp_redirect( $url );
171
+ die();
172
+ endif;
173
+ // create update object
174
+ $update = new StdClass;
175
+
176
+ $update->id = 0;
177
+ $update->slug = $pluginInfo->slug;
178
+ $update->new_version = $pluginInfo->version;
179
+ $update->url = $pluginInfo->homepage;
180
+ $update->package = $pluginInfo->download_url;
181
+ if ( !empty( $pluginInfo->upgrade_notice ) )
182
+ $update->upgrade_notice = $pluginInfo->upgrade_notice;
183
+ self::$update = $update;
184
+
185
+ // add update to cache
186
+ wp_update_plugins();
187
+ // run upgrader
188
+ $title = __( 'Update Plugin' );
189
+ $plugin = self::$old;
190
+ //$nonce = 'ctc_pro_upgrade'; //'upgrade-plugin_' . $plugin;
191
+ $nonce = 'upgrade-plugin_' . self::$old;
192
+ $url = 'update.php?action=upgrade-plugin&plugin=' . urlencode( self::$old )
193
+ . '&ctc_pro_upgrade=1&ctcnonce=' . $_REQUEST[ 'ctcnonce' ];
194
+ wp_enqueue_script( 'updates' );
195
+ include_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
196
+ require_once( ABSPATH . 'wp-admin/admin-header.php' );
197
+
198
+ $upgrader = new Plugin_Upgrader( new Plugin_Upgrader_Skin( compact( 'title', 'nonce', 'url', 'plugin' ) ) );
199
+ //return;
200
+ $upgrader->upgrade( $plugin );
201
+
202
+ include(ABSPATH . 'wp-admin/admin-footer.php');
203
+ self::set_update_key( $key );
204
+
205
+ endif;
206
+ }
207
+
208
+ static function injectUpdate( $updates ){
209
+
210
+ if ( !empty( self::$update ) ):
211
+
212
+ if ( !is_object( $updates ) ):
213
+ $updates = new StdClass();
214
+ $updates->response = array();
215
+ endif;
216
+
217
+ $updates->response[ self::$old ] = self::$update;
218
+
219
+ elseif ( isset( $updates, $updates->response ) ):
220
+
221
+ unset( $updates->response[ self::$old ] );
222
+
223
+ endif;
224
+ return $updates;
225
+ }
226
+
227
+ static function clearCachedVersion( $args = NULL ){
228
+ self::$update = NULL;
229
+ return $args;
230
+ }
231
+
232
+ /**
233
+ * deletes old version of plugin without removing option settings
234
+ */
235
+ static function delete_old_version() {
236
+ if ( isset( $_REQUEST[ 'deleted' ] ) ) return;
237
+ $slug = dirname( self::$old );
238
+ // clean up hooks from < 2.2.0
239
+ wp_clear_scheduled_hook( 'check_plugin_updates-' . $slug );
240
+ delete_option( 'external_updates-' . $slug );
241
+ // remove old Pro version
242
+ if ( current_user_can( 'delete_plugins' ) ):
243
+ $redir = NULL;
244
+ if ( isset( $_GET[ 'action' ] ) ):
245
+ // unset action parameter if it is for old CTC Pro
246
+ if ( 'activate' == $_GET[ 'action' ]
247
+ && isset( $_GET[ 'plugin' ] )
248
+ && self::$old == $_GET[ 'plugin' ] ):
249
+ unset( $_GET[ 'action' ] );
250
+ // handle two-step FTP Authentication form
251
+ elseif ( 'delete-selected' == $_GET[ 'action' ]
252
+ && isset( $_GET[ 'verify-delete' ] )
253
+ && isset( $_GET[ 'checked' ] )
254
+ && self::$old == $_GET[ 'checked' ][ 0 ] ):
255
+
256
+ unset( $_GET[ 'action' ] );
257
+ unset( $_GET[ 'checked' ] );
258
+ unset( $_GET[ 'verify-delete' ] );
259
+ unset( $_REQUEST[ 'action' ] );
260
+ unset( $_REQUEST[ 'checked' ] );
261
+ unset( $_REQUEST[ 'verify-delete' ] );
262
+
263
+ $redir = self_admin_url( "plugins.php?activate=true" );
264
+ elseif ( 'activate' != $_GET[ 'action' ] ):
265
+ return;
266
+ endif;
267
+ endif;
268
+ // deactivate old Pro version
269
+ deactivate_plugins( self::$old, FALSE, is_network_admin() );
270
+ // remove uninstall hook so that options are preserved
271
+ $uninstallable_plugins = (array) get_option( 'uninstall_plugins' );
272
+ if ( isset( $uninstallable_plugins[ self::$old ] ) ):
273
+ unset( $uninstallable_plugins[ self::$old ] );
274
+ update_option( 'uninstall_plugins', $uninstallable_plugins );
275
+ endif;
276
+ unset( $uninstallable_plugins );
277
+ // remove old Pro version
278
+ $delete_result = delete_plugins( array( self::$old ) );
279
+ //Store the result in a cache rather than a URL param due to object type & length
280
+ global $user_ID;
281
+ set_transient( 'plugins_delete_result_' . $user_ID, $delete_result );
282
+ // force plugin cache to reload
283
+ wp_cache_delete( 'plugins', 'plugins' );
284
+
285
+ // if this is two-step FTP authentication, redirect back to activated
286
+ if ( $redir ):
287
+ if ( is_wp_error( $delete_result ) )
288
+ $redir = self_admin_url( "plugins.php?deleted=" . self::$old );
289
+ wp_redirect( $redir );
290
+ exit;
291
+ endif;
292
+ endif;
293
+ }
294
+ }
includes/forms/addl_panels.php CHANGED
@@ -1,13 +1,13 @@
1
  <?php
2
  // Exit if accessed directly
3
  if ( !defined( 'ABSPATH' ) ) exit;
4
- if ( !defined( 'CHLD_THM_CFG_PLUGINS_VERSION' ) ):
5
  ?><div id="get_pro_panel" class="ctc-option-panel<?php echo 'get_pro' == $active_tab ? ' ctc-option-panel-active' : ''; ?>" <?php echo $hidechild; ?> >
6
  <div class="ctc-input-row clearfix">
7
  <div class="ctc-input-cell"><div style="padding:0 40px">
8
  <h1>Upgrade Offer</h1>
9
  <p class="larger"><?php _e( 'Use coupon code', 'child-theme-configurator' ); ?><code><strong><?php _e( 'wordpress-org', 'child-theme-configurator' ); ?></strong></code><?php _e( 'and get <strong>20% off entire order</strong>.', 'child-theme-configurator' ); ?></p>
10
- <h3><a target="_blank" href="<?php echo LILAEAMEDIA_URL; ?>/cart/?add-to-cart=1710" title="<?php _e( 'Order Now', 'child-theme-configurator' ); ?>"><?php _e( 'Order Now', 'child-theme-configurator' ); ?></a></h3><small><?php _e( '*Prices and offers subject to change.', 'child-theme-configurator' ); ?></small><hr style="margin:20px 0" />
11
  <a target="_blank" href="<?php echo LILAEAMEDIA_URL; ?>/plugins/intelliwidget/" title="<?php _e( 'Learn more about IntelliWidget', 'child-theme-configurator' ); ?>"><img src="<?php echo CHLD_THM_CFG_URL . 'css/iw-banner.jpg'; ?>" width="430" height="430" /></a>
12
  <p><?php _e( 'IntelliWidget is a versatile widget manager that does the work of multiple plugins by combining custom page menus, featured posts, sliders and other dynamic content features into a single plugin that can display on a per-page or site-wide basis.', 'child-theme-configurator' ); ?> <a target="_blank" href="<?php echo LILAEAMEDIA_URL; ?>/plugins/intelliwidget/" title="<?php _e( 'Learn more about IntelliWidget', 'child-theme-configurator' ); ?>">
13
  <?php _e( 'Learn more', 'child-theme-configurator'); ?><i class="dashicons dashicons-external" style="text-decoration:none"></i></a></p><hr style="margin:20px 0" />
@@ -24,20 +24,20 @@ if ( !defined( 'CHLD_THM_CFG_PLUGINS_VERSION' ) ):
24
  <ul>
25
  <li><h3><?php _e( 'Customize Plugin Stylesheets', 'child-theme-configurator' ); ?></h3>
26
  <p><?php _e( 'Apply the power of CTC\'s top-rated interface to your site\'s plugin styles. All new design makes it much easier to get the results you want.', 'child-theme-configurator' ); ?></p></li>
27
- <li><h3><?php _e( 'Quick Preview', 'child-theme-configurator' ); ?></h3><p><?php _e( 'Test your child theme with a single click.', 'child-theme-configurator' ); ?></p></li>
28
  <li><h3><?php _e( 'Color Palettes', 'child-theme-configurator' ); ?></h3><p><?php _e( 'Keep the colors you select just a click away. No more searching for hex codes and RGB values.', 'child-theme-configurator' ); ?></p></li>
29
  <li><h3><?php _e( 'Find related styles', 'child-theme-configurator' ); ?></h3><p><?php _e( 'Use the "All Styles" panel to edit groups of selectors from a single combined list.', 'child-theme-configurator' ); ?></p></li>
30
  <li><h3><?php _e( 'Find styles by Nav Menu', 'child-theme-configurator' ); ?></h3><p><?php _e( 'Tweak menus quickly and easily.', 'child-theme-configurator' ); ?></p></li>
31
  <li><h3><?php _e( 'Most recent edits', 'child-theme-configurator' ); ?></h3><p><?php _e( 'Return to recently edited selectors from a toggleable sidebar.', 'child-theme-configurator' ); ?></p></li>
32
- <li><h3><?php _e( 'Genesis Framework Support', 'child-theme-configurator' ); ?></h3>
33
- <p><?php _e( 'Automatically detects and configures Genesis Child Themes with more frameworks on the way.', 'child-theme-configurator' ); ?></p></li>
34
  <li><h3><?php _e( 'Top-rated Online Support', 'child-theme-configurator' ); ?></h3></li>
35
  <li><h3><?php _e( 'Online Documentation', 'child-theme-configurator' ); ?></h3></li>
36
  <li><h3><?php _e( 'Tutorial Videos', 'child-theme-configurator' ); ?></h3></li>
37
  </ul>
38
  <h1>Upgrade Offer</h1>
39
  <p class="larger"><?php _e( 'Use coupon code', 'child-theme-configurator' ); ?><code><strong><?php _e( 'wordpress-org', 'child-theme-configurator' ); ?></strong></code><?php _e( 'and get <strong>20% off entire order</strong>.', 'child-theme-configurator' ); ?></p>
40
- <h3><a target="_blank" href="<?php echo LILAEAMEDIA_URL; ?>/cart/?add-to-cart=1710" title="<?php _e( 'Order Now', 'child-theme-configurator' ); ?>"><?php _e( 'Order Now', 'child-theme-configurator' ); ?></a></h3><small><?php _e( '*Prices and offers subject to change.', 'child-theme-configurator' ); ?></small>
41
  </div>
42
  </div></div><?php
43
  endif;
1
  <?php
2
  // Exit if accessed directly
3
  if ( !defined( 'ABSPATH' ) ) exit;
4
+ if ( !defined( 'CHLD_THM_CFG_PRO_VERSION' ) ):
5
  ?><div id="get_pro_panel" class="ctc-option-panel<?php echo 'get_pro' == $active_tab ? ' ctc-option-panel-active' : ''; ?>" <?php echo $hidechild; ?> >
6
  <div class="ctc-input-row clearfix">
7
  <div class="ctc-input-cell"><div style="padding:0 40px">
8
  <h1>Upgrade Offer</h1>
9
  <p class="larger"><?php _e( 'Use coupon code', 'child-theme-configurator' ); ?><code><strong><?php _e( 'wordpress-org', 'child-theme-configurator' ); ?></strong></code><?php _e( 'and get <strong>20% off entire order</strong>.', 'child-theme-configurator' ); ?></p>
10
+ <h3><a target="_blank" href="<?php echo LILAEAMEDIA_URL; ?>/cart/?add-to-cart=4549" title="<?php _e( 'Order Now', 'child-theme-configurator' ); ?>"><?php _e( 'Order Now', 'child-theme-configurator' ); ?></a></h3><small><?php _e( '*Prices and offers subject to change.', 'child-theme-configurator' ); ?></small><hr style="margin:20px 0" />
11
  <a target="_blank" href="<?php echo LILAEAMEDIA_URL; ?>/plugins/intelliwidget/" title="<?php _e( 'Learn more about IntelliWidget', 'child-theme-configurator' ); ?>"><img src="<?php echo CHLD_THM_CFG_URL . 'css/iw-banner.jpg'; ?>" width="430" height="430" /></a>
12
  <p><?php _e( 'IntelliWidget is a versatile widget manager that does the work of multiple plugins by combining custom page menus, featured posts, sliders and other dynamic content features into a single plugin that can display on a per-page or site-wide basis.', 'child-theme-configurator' ); ?> <a target="_blank" href="<?php echo LILAEAMEDIA_URL; ?>/plugins/intelliwidget/" title="<?php _e( 'Learn more about IntelliWidget', 'child-theme-configurator' ); ?>">
13
  <?php _e( 'Learn more', 'child-theme-configurator'); ?><i class="dashicons dashicons-external" style="text-decoration:none"></i></a></p><hr style="margin:20px 0" />
24
  <ul>
25
  <li><h3><?php _e( 'Customize Plugin Stylesheets', 'child-theme-configurator' ); ?></h3>
26
  <p><?php _e( 'Apply the power of CTC\'s top-rated interface to your site\'s plugin styles. All new design makes it much easier to get the results you want.', 'child-theme-configurator' ); ?></p></li>
27
+ <li><h3><?php _e( 'Quick Preview', 'child-theme-configurator' ); ?></h3><p><?php _e( 'Preview your child theme with a single click.', 'child-theme-configurator' ); ?></p></li>
28
  <li><h3><?php _e( 'Color Palettes', 'child-theme-configurator' ); ?></h3><p><?php _e( 'Keep the colors you select just a click away. No more searching for hex codes and RGB values.', 'child-theme-configurator' ); ?></p></li>
29
  <li><h3><?php _e( 'Find related styles', 'child-theme-configurator' ); ?></h3><p><?php _e( 'Use the "All Styles" panel to edit groups of selectors from a single combined list.', 'child-theme-configurator' ); ?></p></li>
30
  <li><h3><?php _e( 'Find styles by Nav Menu', 'child-theme-configurator' ); ?></h3><p><?php _e( 'Tweak menus quickly and easily.', 'child-theme-configurator' ); ?></p></li>
31
  <li><h3><?php _e( 'Most recent edits', 'child-theme-configurator' ); ?></h3><p><?php _e( 'Return to recently edited selectors from a toggleable sidebar.', 'child-theme-configurator' ); ?></p></li>
32
+ <li><h3><?php _e( 'Add Child Theme Files', 'child-theme-configurator' ); ?></h3>
33
+ <p><?php _e( 'Create new template and script files right from the admin.', 'child-theme-configurator' ); ?></p></li>
34
  <li><h3><?php _e( 'Top-rated Online Support', 'child-theme-configurator' ); ?></h3></li>
35
  <li><h3><?php _e( 'Online Documentation', 'child-theme-configurator' ); ?></h3></li>
36
  <li><h3><?php _e( 'Tutorial Videos', 'child-theme-configurator' ); ?></h3></li>
37
  </ul>
38
  <h1>Upgrade Offer</h1>
39
  <p class="larger"><?php _e( 'Use coupon code', 'child-theme-configurator' ); ?><code><strong><?php _e( 'wordpress-org', 'child-theme-configurator' ); ?></strong></code><?php _e( 'and get <strong>20% off entire order</strong>.', 'child-theme-configurator' ); ?></p>
40
+ <h3><a target="_blank" href="<?php echo LILAEAMEDIA_URL; ?>/cart/?add-to-cart=4549" title="<?php _e( 'Order Now', 'child-theme-configurator' ); ?>"><?php _e( 'Order Now', 'child-theme-configurator' ); ?></a></h3><small><?php _e( '*Prices and offers subject to change.', 'child-theme-configurator' ); ?></small>
41
  </div>
42
  </div></div><?php
43
  endif;
includes/forms/addl_tabs.php CHANGED
@@ -1,11 +1,11 @@
1
  <?php
2
  // Exit if accessed directly
3
  if ( !defined( 'ABSPATH' ) ) exit;
4
- if ( !defined( 'CHLD_THM_CFG_PLUGINS_VERSION' ) ):
5
  ?>
6
  <a id="get_pro" href="?page=<?php echo CHLD_THM_CFG_MENU; ?>&amp;tab=get_pro"
7
  class="nav-tab<?php echo 'get_pro' == $active_tab ? ' nav-tab-active' : ''; ?>" <?php echo $hidechild; ?>>
8
- <?php _e( 'Upgrade', 'chld_thm_cfg_plugins' ); ?>
9
  </a>
10
  <?php
11
  endif;
1
  <?php
2
  // Exit if accessed directly
3
  if ( !defined( 'ABSPATH' ) ) exit;
4
+ if ( !defined( 'CHLD_THM_CFG_PRO_VERSION' ) ):
5
  ?>
6
  <a id="get_pro" href="?page=<?php echo CHLD_THM_CFG_MENU; ?>&amp;tab=get_pro"
7
  class="nav-tab<?php echo 'get_pro' == $active_tab ? ' nav-tab-active' : ''; ?>" <?php echo $hidechild; ?>>
8
+ <?php _e( 'Upgrade', 'child-theme-configurator' ); ?>
9
  </a>
10
  <?php
11
  endif;
includes/forms/backups.php CHANGED
@@ -3,7 +3,7 @@ if ( !defined( 'ABSPATH' ) ) exit;
3
  // Additional stylesheets
4
  ?><br/>
5
  <?php
6
- foreach ( $this->get_files( $this->css->get_prop( 'child' ), 'backup' ) as $backup => $label ): ?>
7
  <label>
8
  <input class="ctc_checkbox" id="ctc_revert_<?php echo $backup; ?>" name="ctc_revert" type="radio"
9
  value="<?php echo $backup; ?>" />
3
  // Additional stylesheets
4
  ?><br/>
5
  <?php
6
+ foreach ( $this->get_files( $this->css()->get_prop( 'child' ), 'backup' ) as $backup => $label ): ?>
7
  <label>
8
  <input class="ctc_checkbox" id="ctc_revert_<?php echo $backup; ?>" name="ctc_revert" type="radio"
9
  value="<?php echo $backup; ?>" />
includes/forms/current-theme.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Exit if accessed directly
3
+ if ( !defined( 'ABSPATH' ) ) exit;
4
+ if ( $childname = $this->css()->get_prop( 'child_name' ) ): ?>
5
+ <div class="ctc-input-cell">
6
+ <h3><?php echo __( 'Currently loaded', 'child-theme-configurator' ). ': ' . $childname; ?></h3>
7
+ </div>
8
+ <?php endif;
includes/forms/debug-toggle.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Exit if accessed directly
3
+ if ( !defined( 'ABSPATH' ) ) exit;
4
+ ?>
5
+ <label for="ctc_is_debug" style="font-size:9px;float:right">
6
+ <input class="ctc_checkbox" id="ctc_is_debug" name="ctc_is_debug" type="checkbox"
7
+ value="1" <?php echo checked( $this->ctc()->is_debug, 1 ); ?> autocomplete="off" />
8
+ <?php _e( 'Debug', 'child-theme-configurator' ); ?>
9
+ </label>
includes/forms/file-form-buttons.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Exit if accessed directly
3
+ if ( !defined( 'ABSPATH' ) ) exit;
4
+
5
+ if ( 'child' == $template && !$this->ctc()->fs ): ?>
6
+
7
+ <input class="ctc_submit button button-primary" id="ctc_templates_writable_submit"
8
+ name="ctc_templates_writable_submit" type="submit"
9
+ value="<?php _e( 'Make Selected Writable', 'child-theme-configurator' ); ?>" />
10
+ <?php endif; ?>
11
+ <input class="ctc_submit button button-primary" id="ctc_<?php echo $template; ?>_templates_submit"
12
+ name="ctc_<?php echo $template; ?>_templates_submit" type="submit"
13
+ value="<?php echo ( 'parnt' == $template ? __( 'Copy Selected to Child Theme', 'child-theme-configurator' ) : __( 'Delete Selected', 'child-theme-configurator' ) ); ?>" />
includes/forms/file.php CHANGED
@@ -6,4 +6,6 @@ if ( !defined( 'ABSPATH' ) ) exit;
6
  <input class="ctc_checkbox" id="ctc_file_<?php echo $template . '_' . ++$counter; ?>"
7
  name="ctc_file_<?php echo $template; ?>[]" type="checkbox"
8
  value="<?php echo $templatefile; ?>" />
9
- <?php echo $templatefile; ?></label>
 
 
6
  <input class="ctc_checkbox" id="ctc_file_<?php echo $template . '_' . ++$counter; ?>"
7
  name="ctc_file_<?php echo $template; ?>[]" type="checkbox"
8
  value="<?php echo $templatefile; ?>" />
9
+ <?php echo 'child' == $template ? apply_filters( 'chld_thm_cfg_editor_link', $templatefile, $editorlink ) : $templatefile; ?></label>
10
+
11
+
includes/forms/fileform.php CHANGED
@@ -1,20 +1,6 @@
1
  <?php
2
  if ( !defined( 'ABSPATH' ) ) exit;
3
  // Files Section
4
- // This include is used for both parent template section and the child files section
5
- $ctcpage = apply_filters( 'chld_thm_cfg_admin_page', CHLD_THM_CFG_MENU );
6
-
7
- if ( defined( 'DISALLOW_FILE_EDIT' ) && DISALLOW_FILE_EDIT ):
8
- $linktext = __( 'The Theme editor has been disabled. Template files must be edited offline.', 'child-theme-configurator' );
9
- $editorlink = '';
10
- $editorlinkend = '';
11
- else:
12
- $linktext = __( 'Click here to edit template files using the Theme Editor', 'child-theme-configurator' );
13
- $adminbase = 'theme-editor.php?theme=' . $this->ctc()->css->get_prop( 'child' )
14
- . ( 'parnt' == $template ? '&file=functions.php' : '' );
15
- $editorlink = '<a href="' . ( is_multisite() ? network_admin_url( $adminbase ) : admin_url( $adminbase ) ) . '" title="' . $linktext . '">';
16
- $editorlinkend = '</a>';
17
- endif;
18
  ?>
19
  <div class="ctc-input-row clearfix" id="input_row_<?php echo $template; ?>_templates">
20
  <form id="ctc_<?php echo $template; ?>_templates_form" method="post" action="?page=<?php echo $ctcpage; ?>&amp;tab=file_options">
@@ -25,17 +11,17 @@ endif;
25
  <?php
26
  if ( 'parnt' == $template ): ?>
27
  <p class="howto">
28
- <?php _e( 'Copy PHP template files from the parent theme by selecting them here.', 'child-theme-configurator' ); ?>
29
- </p>
30
- <p><strong>
31
  <?php _e( 'CAUTION: If your child theme is active, the child theme version of the file will be used instead of the parent immediately after it is copied.', 'child-theme-configurator' );?>
32
  </strong></p>
33
- <p class="howto"> <?php echo sprintf( __( 'The %s file is generated separately and cannot be copied here.', 'child-theme-configurator' ),
34
- $editorlink . '<code>functions.php</code>' . $editorlinkend
35
  );
36
  else: ?>
37
  <p class="howto">
38
- <?php echo $editorlink . $linktext . $editorlinkend; ?>
39
  </p>
40
  <p class="howto">
41
  <?php
@@ -51,14 +37,7 @@ else: ?>
51
  <div class="ctc-input-cell-wide"> <?php echo $inputs; ?></div>
52
  <div class="ctc-input-cell"> <strong>&nbsp;</strong> </div>
53
  <div class="ctc-input-cell-wide" style="margin-top:10px;margin-bottom:10px">
54
- <?php if ( 'child' == $template && !$this->ctc()->fs ): ?>
55
- <input class="ctc_submit button button-primary" id="ctc_templates_writable_submit"
56
- name="ctc_templates_writable_submit" type="submit"
57
- value="<?php _e( 'Make Selected Writable', 'child-theme-configurator' ); ?>" />&nbsp; &nbsp;
58
- <?php endif; ?>
59
- <input class="ctc_submit button button-primary" id="ctc_<?php echo $template; ?>_templates_submit"
60
- name="ctc_<?php echo $template; ?>_templates_submit" type="submit"
61
- value="<?php echo ( 'parnt' == $template ? __( 'Copy Selected to Child Theme', 'child-theme-configurator' ) : __( 'Delete Selected', 'child-theme-configurator' ) ); ?>" />
62
  </div>
63
  </form>
64
  </div>
1
  <?php
2
  if ( !defined( 'ABSPATH' ) ) exit;
3
  // Files Section
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  ?>
5
  <div class="ctc-input-row clearfix" id="input_row_<?php echo $template; ?>_templates">
6
  <form id="ctc_<?php echo $template; ?>_templates_form" method="post" action="?page=<?php echo $ctcpage; ?>&amp;tab=file_options">
11
  <?php
12
  if ( 'parnt' == $template ): ?>
13
  <p class="howto">
14
+ <?php _e( 'Copy PHP templates from the parent theme by selecting them here. The Configurator defines a template as a Theme PHP file having no PHP functions or classes. Other PHP files cannot be safely overridden by a child theme.', 'child-theme-configurator' ); ?>
15
+ </p>
16
+ <p class="howto"><strong>
17
  <?php _e( 'CAUTION: If your child theme is active, the child theme version of the file will be used instead of the parent immediately after it is copied.', 'child-theme-configurator' );?>
18
  </strong></p>
19
+ <p class="howto"> <?php printf( __( 'The %s file is generated separately and cannot be copied here.', 'child-theme-configurator' ),
20
+ sprintf( $editorlink, 'functions.php', 'Click to edit functions.php', '<code>functions.php</code>' )
21
  );
22
  else: ?>
23
  <p class="howto">
24
+ <?php printf( $editorlink, 'functions.php', 'Click to edit functions.php', 'Click to edit files using the Theme Editor' ); ?>
25
  </p>
26
  <p class="howto">
27
  <?php
37
  <div class="ctc-input-cell-wide"> <?php echo $inputs; ?></div>
38
  <div class="ctc-input-cell"> <strong>&nbsp;</strong> </div>
39
  <div class="ctc-input-cell-wide" style="margin-top:10px;margin-bottom:10px">
40
+ <?php do_action( 'chld_thm_cfg_file_form_buttons', $template ); ?>
 
 
 
 
 
 
 
41
  </div>
42
  </form>
43
  </div>
includes/forms/files.php CHANGED
@@ -53,17 +53,12 @@ if ( !defined( 'ABSPATH' ) ) exit;
53
  </form>
54
  </div>
55
  <div class="ctc-input-row clearfix" id="input_row_screenshot">
56
- <form id="ctc_export_form" method="post" action="?page=<?php echo CHLD_THM_CFG_MENU; ?>">
57
- <?php wp_nonce_field( apply_filters( 'chld_thm_cfg_action', 'ctc_update' ) ); ?>
58
  <div class="ctc-input-cell"> <strong>
59
  <?php _e( 'Export Child Theme as Zip Archive', 'child-theme-configurator' ); ?>
60
- </strong> </div>
61
- <div class="ctc-input-cell-wide">
62
- <input class="ctc_submit button button-primary" id="ctc_export_child_zip"
63
- name="ctc_export_child_zip" type="submit"
64
- value="<?php _e( 'Export', 'child-theme-configurator' ); ?>" />
65
- </div>
66
- </form>
67
  </div>
68
  <?php if ( 'direct' != $this->ctc()->fs_method ): ?>
69
  <div class="ctc-input-row clearfix" id="input_row_permissions">
53
  </form>
54
  </div>
55
  <div class="ctc-input-row clearfix" id="input_row_screenshot">
 
 
56
  <div class="ctc-input-cell"> <strong>
57
  <?php _e( 'Export Child Theme as Zip Archive', 'child-theme-configurator' ); ?>
58
+ </strong> <p class="howto"><?php _e( 'Click "Export Zip" to save a backup of the currently loaded child theme. You can export any of your themes from the Parent/Child tab.' ); ?></p></div>
59
+ <div class="ctc-input-cell-wide"><?php
60
+ include ( CHLD_THM_CFG_DIR . '/includes/forms/zipform.php' );
61
+ ?></div>
 
 
 
62
  </div>
63
  <?php if ( 'direct' != $this->ctc()->fs_method ): ?>
64
  <div class="ctc-input-row clearfix" id="input_row_permissions">
includes/forms/main.php CHANGED
@@ -1,18 +1,30 @@
1
  <?php
2
  if ( !defined( 'ABSPATH' ) ) exit;
 
 
3
  // main CTC Page
4
  ?>
5
  <style type="text/css">
 
 
 
 
 
 
 
 
 
 
 
 
6
  .ctc-status-icon.success {
7
  background:url(<?php echo admin_url( 'images/yes.png' );
8
  ?>) no-repeat;
9
  }
10
-
11
  .ctc-status-icon.failure {
12
  background:url(<?php echo admin_url( 'images/no.png' );
13
  ?>) no-repeat;
14
  }
15
-
16
  .ctc-exit {
17
  background:#f9f9f9 url(<?php echo includes_url( 'images/xit-2x.gif' );
18
  ?>) left top no-repeat;
@@ -20,42 +32,53 @@ background:#f9f9f9 url(<?php echo includes_url( 'images/xit-2x.gif' );
20
  </style>
21
  <div class="wrap" id="ctc_main">
22
  <?php do_action( 'chld_thm_cfg_related_links' ); ?>
23
- <h2><?php echo apply_filters( 'chld_thm_cfg_header', __( 'Child Theme Configurator', 'child-theme-configurator' ) . ' ' . __( 'version', 'child-theme-configurator' ) . ' ' . CHLD_THM_CFG_VERSION ); ?></h2>
24
  <?php
25
  if ( $this->ctc()->is_post && !$this->ctc()->fs ):
 
26
  echo $this->ctc()->fs_prompt;
27
- else: ?>
 
 
 
 
28
  <div id="ctc_error_notice">
29
- <?php $this->settings_errors(); ?>
30
  </div>
31
- <?php
32
  // if flag has been set because an action is required, do not render interface
33
  if ( !$this->ctc()->skip_form ):
34
  include ( CHLD_THM_CFG_DIR . '/includes/forms/tabs.php' );
35
- ?><div id="ctc_option_panel_wrapper" style="position:relative">
 
36
  <div class="ctc-option-panel-container">
37
  <?php
38
- $parent_child_panel = apply_filters( 'chld_thm_cfg_pc_panel',
39
- CHLD_THM_CFG_DIR . '/includes/forms/parent-child.php' );
40
- include ( $parent_child_panel );
41
  if ( $enqueueset ):
42
  include ( CHLD_THM_CFG_DIR . '/includes/forms/rule-value.php' );
43
- include ( CHLD_THM_CFG_DIR . '/includes/forms/query-selector.php' );
44
- include ( CHLD_THM_CFG_DIR . '/includes/forms/webfonts.php' ); ?>
 
45
  <div id="view_child_options_panel"
46
  class="ctc-option-panel<?php echo 'view_child_options' == $active_tab ? ' ctc-option-panel-active' : ''; ?>" <?php echo $hidechild; ?>> </div>
47
  <div id="view_parnt_options_panel"
48
  class="ctc-option-panel<?php echo 'view_parnt_options' == $active_tab ? ' ctc-option-panel-active' : ''; ?>" <?php echo $hidechild; ?>> </div>
49
  <?php
50
- if ( '' == $hidechild ):
51
  include ( CHLD_THM_CFG_DIR . '/includes/forms/files.php' );
52
- endif;
53
- do_action( 'chld_thm_cfg_panels', $this->ctc(), $active_tab, $hidechild );
54
  endif;
55
  ?>
56
  </div>
57
- <?php do_action( 'chld_thm_cfg_sidebar' ); ?></div><?php
 
 
58
  endif;
59
  endif;
60
  ?>
 
 
 
 
 
61
  </div>
1
  <?php
2
  if ( !defined( 'ABSPATH' ) ) exit;
3
+ // backward compat
4
+ $css = $this->css();
5
  // main CTC Page
6
  ?>
7
  <style type="text/css">
8
+ .ctc-step-number {
9
+ background-color: <?php echo $this->colors[ 3 ];
10
+ ?>;
11
+ }
12
+ .ctc-step-letter {
13
+ background-color: <?php echo $this->colors[ 2 ];
14
+ ?>;
15
+ }
16
+ .ctc-step + strong {
17
+ color: <?php echo $this->colors[ 1 ];
18
+ ?>;
19
+ }
20
  .ctc-status-icon.success {
21
  background:url(<?php echo admin_url( 'images/yes.png' );
22
  ?>) no-repeat;
23
  }
 
24
  .ctc-status-icon.failure {
25
  background:url(<?php echo admin_url( 'images/no.png' );
26
  ?>) no-repeat;
27
  }
 
28
  .ctc-exit {
29
  background:#f9f9f9 url(<?php echo includes_url( 'images/xit-2x.gif' );
30
  ?>) left top no-repeat;
32
  </style>
33
  <div class="wrap" id="ctc_main">
34
  <?php do_action( 'chld_thm_cfg_related_links' ); ?>
35
+ <h2><?php echo apply_filters( 'chld_thm_cfg_header', __( 'Child Theme Configurator', 'child-theme-configurator' ) . ' ' . __( 'version', 'child-theme-configurator' ) . ' ' . CHLD_THM_CFG_VERSION ); ?></h2>
36
  <?php
37
  if ( $this->ctc()->is_post && !$this->ctc()->fs ):
38
+ //die( 'in fs prompt' );
39
  echo $this->ctc()->fs_prompt;
40
+ else:
41
+ ?>
42
+ <div class="clearfix" >
43
+ <?php do_action( 'chld_thm_cfg_before_tabs' ); ?>
44
+ </div>
45
  <div id="ctc_error_notice">
46
+ <?php $this->render_settings_errors(); ?>
47
  </div>
48
+ <?php
49
  // if flag has been set because an action is required, do not render interface
50
  if ( !$this->ctc()->skip_form ):
51
  include ( CHLD_THM_CFG_DIR . '/includes/forms/tabs.php' );
52
+ ?>
53
+ <div id="ctc_option_panel_wrapper" style="position:relative">
54
  <div class="ctc-option-panel-container">
55
  <?php
56
+ include ( CHLD_THM_CFG_DIR . '/includes/forms/parent-child.php' );
 
 
57
  if ( $enqueueset ):
58
  include ( CHLD_THM_CFG_DIR . '/includes/forms/rule-value.php' );
59
+ include ( CHLD_THM_CFG_DIR . '/includes/forms/query-selector.php' );
60
+ if ( $this->ctc()->is_theme() )
61
+ include ( CHLD_THM_CFG_DIR . '/includes/forms/webfonts.php' ); ?>
62
  <div id="view_child_options_panel"
63
  class="ctc-option-panel<?php echo 'view_child_options' == $active_tab ? ' ctc-option-panel-active' : ''; ?>" <?php echo $hidechild; ?>> </div>
64
  <div id="view_parnt_options_panel"
65
  class="ctc-option-panel<?php echo 'view_parnt_options' == $active_tab ? ' ctc-option-panel-active' : ''; ?>" <?php echo $hidechild; ?>> </div>
66
  <?php
67
+ if ( '' == $hidechild && $this->ctc()->is_theme() )
68
  include ( CHLD_THM_CFG_DIR . '/includes/forms/files.php' );
69
+ do_action( 'chld_thm_cfg_panels', $active_tab, $hidechild );
 
70
  endif;
71
  ?>
72
  </div>
73
+ <?php do_action( 'chld_thm_cfg_sidebar' ); ?>
74
+ </div>
75
+ <?php
76
  endif;
77
  endif;
78
  ?>
79
+ <div id="ctc_debug_container">
80
+ <?php if ( $this->ctc()->is_debug ): ?>
81
+ <textarea id="ctc_debug_box"><?php echo $this->ctc()->get_debug(); ?></textarea>
82
+ <?php endif; ?>
83
+ </div>
84
  </div>
includes/forms/notices.php ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Exit if accessed directly
3
+ if ( !defined( 'ABSPATH' ) ) exit;
4
+ ?>
5
+
6
+ <div class="notice-warning notice is-dismissible<?php echo ( 'upgrade' == $msg ? ' ctc-upgrade-notice' : '' ); ?>" style="display:block">
7
+ <?php
8
+ switch( $msg ):
9
+
10
+ case 'writable': ?>
11
+ <p class="ctc-section-toggle" id="ctc_perm_options">
12
+ <?php _e( 'The child theme is in read-only mode and Child Theme Configurator cannot apply changes. Click to see options', 'child-theme-configurator' ); ?>
13
+ </p>
14
+ <div class="ctc-section-toggle-content" id="ctc_perm_options_content">
15
+ <p>
16
+ <ol>
17
+ <?php
18
+ $ctcpage = apply_filters( 'chld_thm_cfg_admin_page', CHLD_THM_CFG_MENU );
19
+ if ( 'WIN' != substr( strtoupper( PHP_OS ), 0, 3 ) ):
20
+ _e( '<li>Temporarily set write permissions by clicking the button below. When you are finished editing, revert to read-only by clicking "Make read-only" under the "Files" tab.</li>', 'child-theme-configurator' );
21
+ ?>
22
+ <form action="" method="post">
23
+ <?php wp_nonce_field( apply_filters( 'chld_thm_cfg_action', 'ctc_update' ) ); ?>
24
+ <input name="ctc_set_writable" class="button" type="submit" value="<?php _e( 'Make files writable', 'child-theme-configurator' ); ?>"/>
25
+ </form>
26
+ <?php endif;
27
+ _e( '<li><a target="_blank" href="http://codex.wordpress.org/Editing_wp-config.php#WordPress_Upgrade_Constants" title="Editin wp-config.php">Add your FTP/SSH credentials to the WordPress config file</a>.</li>', 'child-theme-configurator' );
28
+ if ( isset( $_SERVER[ 'SERVER_SOFTWARE' ] ) && preg_match( '%iis%i',$_SERVER[ 'SERVER_SOFTWARE' ] ) )
29
+ _e( '<li><a target="_blank" href="http://technet.microsoft.com/en-us/library/cc771170" title="Setting Application Pool Identity">Assign WordPress to an application pool that has write permissions</a> (Windows IIS systems).</li>', 'child-theme-configurator' );
30
+ _e( '<li><a target="_blank" href="http://codex.wordpress.org/Changing_File_Permissions" title="Changing File Permissions">Set write permissions on the server manually</a> (not recommended).</li>', 'child-theme-configurator' );
31
+ if ( 'WIN' != substr( strtoupper( PHP_OS ), 0, 3 ) ):
32
+ _e( '<li>Run PHP under Apache with suEXEC (contact your web host).</li>', 'child-theme-configurator' );
33
+ endif; ?>
34
+ </ol>
35
+ </p>
36
+ </div>
37
+ <?php
38
+ break;
39
+
40
+
41
+ case 'owner':
42
+
43
+ $ctcpage = apply_filters( 'chld_thm_cfg_admin_page', CHLD_THM_CFG_MENU ); // FIXME? ?>
44
+ <p>
45
+ <?php _e( 'This Child Theme has incorrect ownership permissions. Child Theme Configurator will attempt to correct this when you click the button below.', 'child-theme-configurator' ) ?>
46
+ </p>
47
+ <p>
48
+ <form action="" method="post">
49
+ <?php
50
+ wp_nonce_field( apply_filters( 'chld_thm_cfg_action', 'ctc_update' ) ); ?>
51
+ <input name="ctc_reset_permission" class="button" type="submit" value="<?php _e( 'Correct Child Theme Permissions', 'child-theme-configurator' ); ?>"/>
52
+ </form>
53
+ </p>
54
+ <?php
55
+ break;
56
+
57
+
58
+ case 'enqueue': ?>
59
+ <p>
60
+ <?php _e( 'Child Theme Configurator needs to update its internal data. Please set your preferences below and click "Generate Child Theme Files" to update your configuration.', 'child-theme-configurator' ) ?>
61
+ </p>
62
+ <?php
63
+ break;
64
+
65
+
66
+ case 'max_styles':
67
+
68
+ echo sprintf( __( '<strong>However, some styles could not be parsed due to memory limits.</strong> Try deselecting "Additional Stylesheets" below and click "Generate/Rebuild Child Theme Files". %sWhy am I seeing this?%s', 'child-theme-configurator' ),
69
+ '<a target="_blank" href="' . LILAEAMEDIA_URL . '/child-theme-configurator#php_memory">',
70
+ '</a>' );
71
+ break;
72
+
73
+
74
+ case 'config': ?>
75
+ <p>
76
+ <?php _e( 'Child Theme Configurator did not detect any configuration data because a previously configured Child Theme has been removed. Please follow the steps for "CONFIGURE an existing Child Theme" under the "Parent/Child" Tab.', 'child-theme-configurator' ) ?>
77
+ </p>
78
+ <?php
79
+ break;
80
+
81
+
82
+ case 'changed': ?>
83
+ <p>
84
+ <?php _e( 'Your stylesheet has changed since the last time you used the Configurator. Please follow the steps for "CONFIGURE an existing Child Theme" under the "Parent/Child" Tab or you will lose these changes.', 'child-theme-configurator' ) ?>
85
+ </p>
86
+ <?php
87
+ break;
88
+
89
+
90
+ case 'upgrade':
91
+ $child = $this->css()->get_prop( 'child' );
92
+ ?>
93
+ <?php if ( $child ): ?>
94
+ <div class="clearfix">
95
+ <?php endif; ?>
96
+ <h3>
97
+ <?php _e( 'Thank you for installing Child Theme Configurator.', 'child-theme-configurator' ); ?>
98
+ </h3>
99
+ <p class="howto">
100
+ <?php _e( 'A lot of time and testing has gone into this release but there may be edge cases. If you have any questions, please', 'child-theme-configurator' ); ?>
101
+ <a href="<?php echo LILAEAMEDIA_URL; ?>/contact" target="_blank">
102
+ <?php _e( 'Contact Us.', 'child-theme-configurator' ); ?>
103
+ </a></p>
104
+ <p class="howto">
105
+ <?php _e( 'For more information, please open the Help tab at the top right or ', 'child-theme-configurator' ) ?>
106
+ <a href="http://www.childthemeconfigurator.com/tutorial-videos/" target="_blank">
107
+ <?php _e( 'click here to view the latest videos.', 'child-theme-configurator' ); ?>
108
+ </a></p>
109
+ <?php if ( $child ): ?>
110
+ <p>
111
+ <?php _e( 'It is a good idea to save a Zip Archive of your Child Theme before using CTC for the first time. Click the "save backup" link ( see Step 2, below ) to export your themes.', 'child-theme-configurator' ); ?>
112
+ </p>
113
+ </div>
114
+ <?php endif; ?>
115
+ <?php endswitch; ?>
116
+ </div>
includes/forms/parent-child.php CHANGED
@@ -1,303 +1,477 @@
1
- <?php
2
- if ( !defined( 'ABSPATH' ) ) exit;
3
  // Parent/Child Panel
4
  ?>
5
 
6
  <div id="parent_child_options_panel" class="ctc-option-panel<?php echo 'parent_child_options' == $active_tab ? ' ctc-option-panel-active' : ''; ?>">
7
- <form id="ctc_load_form" method="post" action=""><!-- ?page=<?php echo CHLD_THM_CFG_MENU; ?>"-->
8
- <?php
 
 
 
9
  wp_nonce_field( 'ctc_update' );
10
  //if ( '' == $hidechild )
11
- do_action( 'chld_thm_cfg_controls', $this->ctc() );
12
  $disabled = $this->ctc()->is_legacy() && !$this->ctc()->is_theme() ? ' disabled ' : '';
13
  $disabledclass = $this->ctc()->is_legacy() && !$this->ctc()->is_theme() ? ' ctc-disabled ' : '';
14
- ?>
15
- <div class="ctc-input-row clearfix ctc-themeonly-container<?php echo $disabledclass; ?>" id="input_row_parnt">
16
- <div class="ctc-input-cell"> <strong>
17
- <?php _e( 'Parent Theme', 'child-theme-configurator' ); ?>
18
- </strong> </div>
19
- <div class="ctc-input-cell">
20
- <?php $this->render_theme_menu( 'parnt', $this->ctc()->get_current_parent() ); ?>
21
- </div>
22
- </div>
23
- <div class="ctc-input-row clearfix ctc-themeonly-container<?php echo $disabledclass; ?>" id="input_row_child">
24
- <div class="ctc-input-cell ctc-section-toggle" id="ctc_theme_attributes"> <strong>
25
- <?php _e( 'Child Theme', 'child-theme-configurator' ); ?>
26
- </strong>
27
- <?php _e( '(click to edit additional fields)', 'child-theme-configurator' ); ?>
28
- </div>
29
- <div class="ctc-input-cell">
30
  <input class="ctc-radio ctc-themeonly" id="ctc_child_type_new" name="ctc_child_type" type="radio" value="new"
31
- <?php echo ( !empty( $hidechild ) ? 'checked' : '' ); ?>
32
- <?php echo $hidechild . ' ' . $disabled;?> />
33
- <label for="ctc_child_type_new">
34
- <?php _e( 'Create New Child Theme', 'child-theme-configurator' ); ?>
 
 
 
35
  </label>
36
- </div>
37
- <div class="ctc-input-cell">
 
 
 
 
 
38
  <input class="ctc-radio ctc-themeonly" id="ctc_child_type_existing" name="ctc_child_type" type="radio" value="existing"
39
- <?php echo ( empty( $hidechild ) ? 'checked' : '' ); ?>
40
- <?php echo $hidechild . ' ' . $disabled; ?> />
41
- &nbsp;
42
- <label for="ctc_child_type_existing" <?php echo $hidechild;?>>
43
- <?php _e( 'Use Existing Child Theme', 'child-theme-configurator' ); ?>
44
- </label>
45
- </div>
46
- <div class="ctc-input-cell" style="clear:both"> <strong>&nbsp;</strong> </div>
47
- <div class="ctc-input-cell" >
48
- <input class="ctc_text ctc-themeonly" id="ctc_child_template" name="ctc_child_template" type="text" placeholder="<?php _e( 'New Child Theme Slug', 'child-theme-configurator' ); ?>" autocomplete="off" <?php echo $disabled; ?> />
49
- </div>
50
- <?php if ( '' == $hidechild ): ?>
51
- <div class="ctc-input-cell">
52
- <?php $this->render_theme_menu( 'child', $this->ctc()->get_current_child() ); ?>
53
- </div>
54
- <?php endif; ?>
55
- </div>
56
- <div class="ctc-section-toggle-content" id="ctc_theme_attributes_content">
57
- <div class="ctc-input-row clearfix ctc-themeonly-container<?php echo $disabledclass; ?>" id="input_row_child_name">
58
- <div class="ctc-input-cell"> <strong>
59
- <?php _e( 'Child Theme Name', 'child-theme-configurator' ); ?>
60
- </strong> </div>
61
- <div class="ctc-input-cell-wide">
62
- <input class="ctc_text ctc-themeonly" id="ctc_child_name" name="ctc_child_name" type="text"
63
- value="<?php echo esc_attr( $css->get_prop( 'child_name' ) ); ?>" placeholder="<?php _e( 'Theme Name', 'child-theme-configurator' ); ?>" autocomplete="off" <?php echo $disabled; ?> /> </div></div>
64
- <div class="ctc-input-row clearfix ctc-themeonly-container<?php echo $disabledclass; ?>" id="input_row_child_website">
65
- <div class="ctc-input-cell"> <strong>
66
- <?php _e( 'Theme Website', 'child-theme-configurator' ); ?>
67
- </strong> </div>
68
- <div class="ctc-input-cell-wide">
69
- <input class="ctc_text ctc-themeonly" id="ctc_child_themeuri" name="ctc_child_themeuri" type="text"
70
- value="<?php echo esc_attr( $css->get_prop( 'themeuri' ) ); ?>" placeholder="<?php _e( 'Theme Website', 'child-theme-configurator' ); ?>" autocomplete="off" <?php echo $disabled; ?> /> </div></div>
71
- <div class="ctc-input-row clearfix ctc-themeonly-container<?php echo $disabledclass; ?>" id="input_row_child_author">
72
- <div class="ctc-input-cell"> <strong>
73
- <?php _e( 'Author', 'child-theme-configurator' ); ?>
74
- </strong> </div>
75
- <div class="ctc-input-cell-wide">
76
- <input class="ctc_text" id="ctc_child_author" name="ctc_child_author" type="text"
77
- value="<?php echo esc_attr( $css->get_prop( 'author' ) ); ?>" placeholder="<?php _e( 'Author', 'child-theme-configurator' ); ?>" autocomplete="off" />
78
- </div></div>
79
- <div class="ctc-input-row clearfix ctc-themeonly-container<?php echo $disabledclass; ?>" id="input_row_child_authoruri">
80
- <div class="ctc-input-cell"> <strong>
81
- <?php _e( 'Author Website', 'child-theme-configurator' ); ?>
82
- </strong> </div>
83
- <div class="ctc-input-cell-wide">
84
- <input class="ctc_text ctc-themeonly" id="ctc_child_authoruri" name="ctc_child_authoruri" type="text"
85
- value="<?php echo esc_attr( $css->get_prop( 'authoruri' ) ); ?>" placeholder="<?php _e( 'Author Website', 'child-theme-configurator' ); ?>" autocomplete="off" <?php echo $disabled; ?> /> </div></div>
86
- <div class="ctc-input-row clearfix ctc-themeonly-container<?php echo $disabledclass; ?>" id="input_row_child_descr">
87
- <div class="ctc-input-cell"> <strong>
88
- <?php _e( 'Theme Description', 'child-theme-configurator' ); ?>
89
- </strong> </div>
90
- <div class="ctc-input-cell-wide">
91
- <textarea class="ctc_text ctc-themeonly" id="ctc_child_descr" name="ctc_child_descr" placeholder="<?php _e( 'Description', 'child-theme-configurator' ); ?>" autocomplete="off" <?php echo $disabled; ?> ><?php echo esc_textarea( $css->get_prop( 'descr' ) ); ?></textarea> </div></div>
92
- <div class="ctc-input-row clearfix ctc-themeonly-container<?php echo $disabledclass; ?>" id="input_row_child_tags">
93
- <div class="ctc-input-cell"> <strong>
94
- <?php _e( 'Theme Tags', 'child-theme-configurator' ); ?>
95
- </strong> </div>
96
- <div class="ctc-input-cell-wide">
97
- <textarea class="ctc_text ctc-themeonly" id="ctc_child_tags" name="ctc_child_tags" placeholder="<?php _e( 'Tags', 'child-theme-configurator' ); ?>" autocomplete="off" <?php echo $disabled; ?> ><?php echo esc_textarea( $css->get_prop( 'tags' ) ); ?></textarea></div></div>
98
- <div class="ctc-input-row clearfix ctc-themeonly-container<?php echo $disabledclass; ?>" id="input_row_child_version">
99
- <div class="ctc-input-cell"> <strong>
100
- <?php _e( 'Version', 'child-theme-configurator' ); ?>
101
- </strong> </div>
102
- <div class="ctc-input-cell">
103
- <input class="ctc_text" id="ctc_child_version" name="ctc_child_version" type="text"
104
- value="<?php echo esc_attr( $css->get_prop( 'version' ) ); ?>" placeholder="<?php _e( 'Version', 'child-theme-configurator' ); ?>" autocomplete="off" />
105
- </div>
106
- </div>
107
- <div class="ctc-input-row clearfix ctc-themeonly-container<?php echo $disabledclass; ?>" id="input_row_duplicate_theme" <?php echo $hidechild;?>>
108
- <div class="ctc-input-cell"> <strong>
109
- <?php _e( 'Duplicate Existing Child Theme', 'child-theme-configurator' ); ?>
110
- </strong> </div>
111
- <div class="ctc-input-cell">
112
- <input class="ctc_checkbox ctc-themeonly" id="ctc_duplicate_theme" name="ctc_duplicate_theme" type="checkbox"
113
- value="1" <?php echo $disabled; ?> />
114
- <input class="ctc_text" id="ctc_duplicate_theme_slug" name="ctc_duplicate_theme_slug" type="text"
115
- value="" placeholder="<?php _e( 'Duplicate Theme Slug', 'child-theme-configurator' ); ?>" autocomplete="off" />
116
- </div>
117
- <div class="ctc-input-cell howto"> <strong>
118
- <?php _e( 'NOTE:', 'child-theme-configurator' ); ?>
119
- </strong>
120
- <?php _e( 'This will copy all child theme files and apply changes to new version.', 'child-theme-configurator' ); ?>
121
- </div>
122
- </div>
123
- <div class="ctc-input-row clearfix" id="input_row_debug">
124
- <div class="ctc-input-cell">
125
  <strong>
126
- <?php _e( 'Debug', 'chld_thm_cfg_plugins' ); ?>
127
  </strong>
128
- </div>
129
- <div class="ctc-input-cell">
130
- <input class="ctc_checkbox" id="ctc_is_debug" name="ctc_is_debug" type="checkbox"
131
- value="1" <?php echo checked( $this->ctc()->is_debug, 1 ); ?> autocomplete="off" />
132
- </div>
133
- <div class="ctc-input-cell howto">
134
- <?php _e( 'Check the box to enable debugging output.', 'chld_thm_cfg_plugins' ); ?>
135
- </div>
136
- </div>
137
- </div>
138
- <?php $parent_handling = ( isset( $css->enqueue ) ? $css->enqueue : 'enqueue' ); ?>
139
- <div class="ctc-input-row clearfix ctc-themeonly-container<?php echo $disabledclass; ?>">
140
- <div class="ctc-input-cell ctc-section-toggle" id="ctc_stylesheet_handling">
141
- <strong><?php _e( 'Stylesheet handling', 'child-theme-configurator' ); ?></strong>
142
- <?php _e( '(click to view options)', 'child-theme-configurator' ); ?>
143
- </div><?php if ( empty( $css->nowarn ) && count( $this->warnings ) && in_array( $css->enqueue, array( 'none', 'enqueue' ) ) ):?>
144
- <div class="ctc-input-cell-wide update-nag"><strong><?php _e( 'This theme may not apply child theme styles correctly with the current settings:', 'child-theme-configurator' ); ?></strong><ul class="smaller">
145
- <?php foreach ( $this->warnings as $warning ) echo '<li>' . $warning . '</li>' . LF; ?>
146
- </ul><span class="alignright"><label class="smaller"><input type="checkbox" name="ctc_nowarn" value="1" /><?php _e( "Don't show again.", 'child-theme-configurator'); ?></label> &nbsp; <a href="#" class="ctc-section-toggle" id="ctc_stylesheet_handling2"><?php _e( 'View options', 'child-theme-configurator'); ?></a></span></div>
147
- <?php endif; ?>
148
- <div class="ctc-section-toggle-content clear" id="ctc_stylesheet_handling_content">
149
- <div class="ctc-input-cell clear"><a href="<?php echo CHLD_THM_CFG_DOCS_URL; ?>/how-to-use/#stylesheet_handling" target="_blank"><?php _e( 'Which option should I use?', 'child-theme-configurator' ); ?></a></div>
150
- <div class="ctc-input-cell">
151
- <label>
152
- <input class="ctc_radio ctc-themeonly" id="ctc_parent_enqueue_none" name="ctc_parent_enqueue" type="radio"
153
- value="none" <?php checked( 'none', $parent_handling ); ?> <?php echo $disabled; ?> />
154
- <?php _e( 'None (handled by theme)', 'child-theme-configurator' ); ?>
155
- </label>
156
- </div>
157
- <div class="ctc-input-cell howto sep">
158
- <?php _e( 'Select this option if all stylesheets are correctly enqueued for child themes. If you find that styles are not being applied correctly, use a different option.', 'child-theme-configurator' ); ?>
159
- </div>
160
- <div class="ctc-input-cell clear">&nbsp;</div>
161
- <div class="ctc-input-cell">
162
- <label>
163
- <input class="ctc_radio ctc-themeonly" id="ctc_parent_enqueue_enqueue" name="ctc_parent_enqueue" type="radio"
164
- value="enqueue" <?php checked( 'enqueue', $parent_handling ); ?> <?php echo $disabled; ?> />
165
- <?php _e( 'Enqueue parent stylesheet (default)', 'child-theme-configurator' ); ?>
166
  </label>
167
- </strong> </div>
168
- <div class="ctc-input-cell howto sep"><?php _e( "Select this option if the theme enqueues the active stylesheet but has no special handling for child themes. Start with this option if unsure.", 'child-theme-configurator' ); ?>
169
- </div>
170
  <div class="ctc-input-cell clear">&nbsp;</div>
171
- <div class="ctc-input-cell">
172
- <label>
173
- <input class="ctc_radio ctc-themeonly" id="ctc_parent_enqueue_child" name="ctc_parent_enqueue" type="radio"
174
- value="child" <?php checked( 'child', $parent_handling ); ?> <?php echo $disabled; ?> />
175
- <?php _e( 'Enqueue child stylesheet', 'child-theme-configurator' ); ?>
176
- </label>
177
- </strong> </div>
178
- <div class="ctc-input-cell howto sep"><?php _e( 'Select this option if the theme enqueues the parent stylesheet but does not enqueue the child stylesheet at all. This can happen if <code>get_template()</code> or <code>get_template_directory_uri()</code> is used to link the stylesheet.', 'child-theme-configurator' ); ?>
179
- </div>
180
- <div class="ctc-input-cell clear"><?php if ( count( $this->warnings ) ): ?><div class="update-nag">
181
- <strong><?php _e( 'Recommended for this theme:', 'child-theme-configurator' ); ?></strong></div>
182
- <?php endif; ?>&nbsp;</div>
183
- <div class="ctc-input-cell">
184
- <label>
185
- <input class="ctc_radio ctc-themeonly" id="ctc_parent_enqueue_both" name="ctc_parent_enqueue" type="radio"
186
- value="both" <?php checked( 'both', $parent_handling ); ?> <?php echo $disabled; ?> />
187
- <?php _e( 'Enqueue both parent and child stylesheets', 'child-theme-configurator' ); ?>
188
  </label>
189
- </strong> </div>
190
- <div class="ctc-input-cell howto sep"><?php _e( 'Select this option if stylesheet link tags are hard-coded into the header template (common in older themes). This enables the child stylesheet to override the parent stylesheet without using <code>@import</code>.', 'child-theme-configurator' ); ?>
191
- </div><?php do_action( 'chld_thm_cfg_enqueue_options' ); ?>
192
  <div class="ctc-input-cell clear">&nbsp;</div>
193
- <div class="ctc-input-cell">
194
- <label>
195
- <input class="ctc_radio ctc-themeonly" id="ctc_parent_enqueue_import" name="ctc_parent_enqueue" type="radio"
196
- value="import" <?php checked( 'import', $parent_handling ); ?> <?php echo $disabled; ?> />
197
- <?php _e( '<code>@import</code> parent stylesheet', 'child-theme-configurator' ); ?>
198
- </label>
199
- </strong> </div>
200
- <div class="ctc-input-cell howto"><?php _e( "This option imports the parent stylesheet from the child stylesheet. This enables the child stylesheet to override the parent stylesheet, but using <code>@import</code> is no longer recommended.", 'child-theme-configurator' ); ?>
201
- </div>
202
- </div></div><?php if ( ! is_multisite() || ! empty( $this->ctc()->themes[ 'parnt' ][ $this->ctc()->get_current_parent() ][ 'allowed' ] ) ): ?>
203
- <div class="ctc-input-row clearfix ctc-themeonly-container<?php echo $disabledclass; ?>">
204
- <div class="ctc-input-cell"> <strong><label for="ctc_parent_mods">
205
- <?php _e( 'Copy Parent Theme Menus, Widgets and other Customizer Options', 'child-theme-configurator' ); ?>
206
- </label></strong> </div>
207
- <div class="ctc-input-cell">
208
- <input class="ctc_checkbox ctc-themeonly" id="ctc_parent_mods" name="ctc_parent_mods" type="checkbox"
209
- value="1" <?php echo $disabled; ?> />
210
- </div>
211
- <div class="ctc-input-cell howto"> <strong>
212
- <?php _e( 'NOTE:', 'child-theme-configurator' ); ?>
213
- </strong>
214
- <?php _e( 'This will overwrite child theme options you may have already set.', 'child-theme-configurator' ); ?>
215
- </div>
216
- </div><?php endif; ?>
217
- <?php if ( '' == $hidechild ): ?>
218
- <div class="ctc-input-row clearfix">
219
- <div class="ctc-input-cell"> <strong><label for="ctc_backup">
220
- <?php _e( 'Backup current stylesheet', 'child-theme-configurator' ); ?>
221
- </label></strong> </div>
222
- <div class="ctc-input-cell">
223
- <input class="ctc_checkbox" id="ctc_backup" name="ctc_backup" type="checkbox"
224
- value="1" />
225
- </div>
226
- <div class="ctc-input-cell howto"> <strong>
227
- <?php _e( 'NOTE:', 'child-theme-configurator' ); ?>
228
  </strong>
229
- <?php _e( 'This creates a copy of the current stylesheet before applying changes. You can remove old backup files using the Files tab.', 'child-theme-configurator' ); ?>
230
- </div>
231
- </div>
232
- <div class="ctc-input-row clearfix">
233
- <div class="ctc-input-cell ctc-section-toggle" id="ctc_revert_css"> <strong>
234
- <?php _e( 'Reset/Restore from backup', 'child-theme-configurator' ); ?>
235
- </strong> </div>
236
- <div class="ctc-input-cell-wide ctc-section-toggle-content" id="ctc_revert_css_content">
237
- <label>
238
- <input class="ctc_checkbox" id="ctc_revert_none" name="ctc_revert" type="radio"
239
- value="" checked="" />
240
- <?php _e( 'Leave unchanged', 'child-theme-configurator' );?>
241
  </label>
242
- <br/>
243
- <label>
244
- <input class="ctc_checkbox" id="ctc_revert_all" name="ctc_revert" type="radio"
245
- value="all" />
246
- <?php _e( 'Reset all', 'child-theme-configurator' );?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
247
  </label>
248
- <div id="ctc_backup_files"><?php
249
- foreach ( $this->ctc()->get_files( $css->get_prop( 'child' ), 'backup' ) as $backup => $label ): ?>
250
- <label>
251
- <input class="ctc_checkbox" id="ctc_revert_<?php echo $backup; ?>" name="ctc_revert" type="radio"
252
- value="<?php echo $backup; ?>" />
253
- <?php echo __( 'Restore backup from', 'child-theme-configurator' ) . ' ' . $label; ?></label>
254
- <br/>
255
- <?php endforeach; ?>
256
- </div>
257
- </div>
258
- </div>
259
- <?php endif; ?>
260
- <div class="ctc-input-row clearfix" id="ctc_stylesheet_files">
261
- <?php
262
- // Additional stylesheets
263
- $stylesheets = $this->ctc()->get_files( $this->ctc()->get_current_parent(), 'stylesheet' );
264
- if ( count( $stylesheets ) ):?>
265
- <div class="ctc-input-cell ctc-section-toggle" id="ctc_additional_css_files"> <strong>
266
- <?php _e( 'Parse additional stylesheets', 'child-theme-configurator' ); ?>
267
- </strong> </div>
268
- <div class="ctc-input-cell-wide ctc-section-toggle-content" id="ctc_additional_css_files_content">
269
- <p style="margin-top:0" class="howto">
270
- <?php _e( 'Stylesheets that are currently being loaded by the parent theme are automatically selected below (except for Bootstrap stylesheets which add a large amount data to the configuration). To further reduce overhead, select only the additional stylesheets you wish to customize.', 'child-theme-configurator' ); ?>
271
- </p>
272
- <ul>
273
- <?php foreach ( $stylesheets as $stylesheet ): ?>
274
- <li>
275
- <label>
276
- <input class="ctc_checkbox" name="ctc_additional_css[]" type="checkbox"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
277
  value="<?php echo $stylesheet; ?>" />
278
- <?php echo esc_attr( $stylesheet ); ?></label>
279
- </li>
280
- <?php endforeach; ?>
281
- </ul>
282
- </div><?php
283
- endif; ?>
284
- </div>
285
- <div class="ctc-input-row clearfix">
286
- <?php if ( '' == $hidechild && !$enqueueset ): ?>
287
- <div class="ctc-input-cell"> <strong>&nbsp;</strong> </div>
288
- <div class="ctc-input-cell-wide">
289
- <div class="update-nag">
290
- <strong><?php _e( 'Please read before you click:', 'child-theme-configurator' ); ?></strong>
291
- <p><?php _e( 'This plugin makes significant modifications to your child theme, to include changing CSS, removing comments and adding php functions.', 'child-theme-configurator' ); ?>
292
- <?php _e( 'If you are using an existing Child Theme,', 'child-theme-configurator' ); ?> <a href="<?php echo CHLD_THM_CFG_DOCS_URL; ?>/how-to-use/#duplicating-existing-child-themes" target="_blank"><?php _e( 'please consider using the Duplicate Child Theme option', 'child-theme-configurator' ); ?></a> <?php _e( 'before proceeding.', 'child-theme-configurator' ); ?></p>
293
- </div><p>&nbsp;</p></div>
294
- <?php endif; ?>
295
- <div class="ctc-input-cell"> <strong>&nbsp;</strong> </div>
296
- <div class="ctc-input-cell">
297
- <input class="ctc_submit button button-primary" id="ctc_load_styles" name="ctc_load_styles" type="submit"
298
- value="<?php _e( 'Generate/Rebuild Child Theme Files', 'child-theme-configurator' ); ?>" disabled />
299
- </div>
300
- </div>
301
- </form>
302
- <div id="ctc_debug_container"><?php do_action( 'chld_thm_cfg_print_debug' ); ?></div>
303
- </div>
1
+ <?php
2
+ if ( !defined( 'ABSPATH' ) )exit;
3
  // Parent/Child Panel
4
  ?>
5
 
6
  <div id="parent_child_options_panel" class="ctc-option-panel<?php echo 'parent_child_options' == $active_tab ? ' ctc-option-panel-active' : ''; ?>">
7
+ <form id="ctc_load_form" method="post" action="">
8
+
9
+ <?php if ( $this->ctc()->is_theme() ): ?>
10
+
11
+ <?php // theme inputs
12
  wp_nonce_field( 'ctc_update' );
13
  //if ( '' == $hidechild )
14
+ do_action( 'chld_thm_cfg_controls' );
15
  $disabled = $this->ctc()->is_legacy() && !$this->ctc()->is_theme() ? ' disabled ' : '';
16
  $disabledclass = $this->ctc()->is_legacy() && !$this->ctc()->is_theme() ? ' ctc-disabled ' : '';
17
+
18
+ ?><input type="hidden" name="ctc_analysis" value=""/>
19
+ <div class="ctc-input-row clearfix ctc-themeonly-container<?php echo $disabledclass; ?>" id="input_row_child">
20
+ <div class="ctc-input-cell"><span class="ctc-step ctc-step-number">1</span>
21
+ <strong class="shift">
22
+ <?php _e( 'Select an action:', 'child-theme-configurator' ); ?>
23
+ </strong>
24
+ </div>
25
+ <div class="ctc-input-cell-wide">
26
+ <label>
 
 
 
 
 
 
27
  <input class="ctc-radio ctc-themeonly" id="ctc_child_type_new" name="ctc_child_type" type="radio" value="new"
28
+ <?php echo ( 'new' == $this->ctc()->childtype ? 'checked' : '' ); ?> />
29
+ <strong>
30
+ <?php _e( 'CREATE a new Child Theme', 'child-theme-configurator' ); ?>
31
+ </strong>
32
+ <p class="howto indent sep">
33
+ <?php _e( 'Install a new customizable child theme using an installed theme as a parent.', 'child-theme-configurator' ); ?>
34
+ </p>
35
  </label>
36
+
37
+
38
+ <!-- /div -->
39
+ <?php if ( '' == $hidechild ): ?>
40
+ <!-- div class="ctc-input-cell clear">&nbsp;</div>
41
+ <div class="ctc-input-cell-wide" -->
42
+ <label>
43
  <input class="ctc-radio ctc-themeonly" id="ctc_child_type_existing" name="ctc_child_type" type="radio" value="existing"
44
+ <?php echo ( 'new' != $this->ctc()->childtype ? 'checked' : '' ); ?> />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  <strong>
46
+ <?php _e( 'CONFIGURE an existing Child Theme', 'child-theme-configurator' ); ?>
47
  </strong>
48
+ <p class="howto indent sep">
49
+ <?php _e( 'Set up a previously installed child theme for use with the Configurator or to modify current settings.', 'child-theme-configurator' ); ?>
50
+ </p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  </label>
52
+
53
+
54
+ <!-- /div>
55
  <div class="ctc-input-cell clear">&nbsp;</div>
56
+ <div class="ctc-input-cell-wide" -->
57
+ <label>
58
+ <input class="ctc-radio ctc-themeonly" id="ctc_child_type_duplicate" name="ctc_child_type" type="radio" value="duplicate" />
59
+ <strong>
60
+ <?php _e( 'DUPLICATE an existing Child Theme', 'child-theme-configurator' ); ?>
61
+ </strong>
62
+ <p class="howto indent sep">
63
+ <?php _e( 'Make a complete copy of an existing Child Theme in a new directory, including any menus, widgets and other Customizer settings. The option to copy the Parent Theme settings (step 8, below) is disabled with this action.', 'child-theme-configurator' ); ?>
64
+ </p>
 
 
 
 
 
 
 
 
65
  </label>
66
+
67
+
68
+ <!-- /div>
69
  <div class="ctc-input-cell clear">&nbsp;</div>
70
+ <div class="ctc-input-cell-wide" -->
71
+ <label>
72
+ <input class="ctc-radio ctc-themeonly" id="ctc_child_type_reset" name="ctc_child_type" type="radio" value="reset" />
73
+ <strong>
74
+ <?php _e( 'RESET an existing Child Theme (this will destroy any work you have done in the Configurator)', 'child-theme-configurator' ); ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  </strong>
76
+ <p class="howto indent">
77
+ <?php _e( 'Revert the Child theme stylesheet and functions files to their state before the initial configuration or last reset. Additional child theme files will not be removed, but you can delete them under the Files tab.', 'child-theme-configurator' ); ?>
78
+ </p>
 
 
 
 
 
 
 
 
 
79
  </label>
80
+
81
+
82
+ </div>
83
+ <?php endif; ?>
84
+ </div>
85
+ <div class="ctc-input-row clearfix ctc-themeonly-container<?php echo $disabledclass; ?>" id="input_row_new_theme_option" style="display:none">
86
+ <div class="ctc-input-cell" style="clear:both"><span class="ctc-step ctc-step-number">2</span>
87
+ <strong>
88
+ <?php _e( 'Select a Parent Theme:', 'child-theme-configurator' ); ?>
89
+ </strong>
90
+ <p class="howto indent">
91
+ <a href="#" class="ctc-backup-theme">
92
+ <?php _e( 'Click here to save a backup of the selected theme.', 'child-theme-configurator' ); ?>
93
+ </a>
94
+ </p>
95
+ </div>
96
+ <div class="ctc-input-cell">
97
+ <?php $this->render_theme_menu( 'parnt', $this->ctc()->get_current_parent() ); ?>
98
+ <input type="button" class="button button-primary ctc-analyze-theme" value="<?php _e( 'Analyze', 'child-theme-configurator' ); ?>"/>
99
+ </div>
100
+ <div class="ctc-input-cell"><span class="ctc-analyze-howto"><span class="ctc-step ctc-step-number">3</span>
101
+ <strong>
102
+ <?php _e( 'Analyze Parent Theme', 'child-theme-configurator' ); ?>
103
+ </strong>
104
+ <p class="howto indent">
105
+ <?php _e( 'Click "Analyze" to determine stylesheet dependencies and other potential issues.' ); ?>
106
+ </p>
107
+ </span>
108
+ </div>
109
+ <div class="ctc-input-cell clear">&nbsp;</div>
110
+ <div class="ctc-input-cell-wide ctc-analysis" id="parnt_analysis_notice">&nbsp;</div>
111
+ </div>
112
+ <?php if ( '' == $hidechild ): ?>
113
+ <div class="ctc-input-row clearfix ctc-themeonly-container<?php echo $disabledclass; ?>" id="input_row_existing_theme_option" style="display:none">
114
+ <div class="ctc-input-cell"><span class="ctc-step ctc-step-number">2</span>
115
+ <strong>
116
+ <?php _e( 'Select a Child Theme:', 'child-theme-configurator' ); ?>
117
+ </strong>
118
+ <p class="howto indent">
119
+ <a href="#" class="ctc-backup-theme">
120
+ <?php _e( 'Click here to save a backup of the selected theme.', 'child-theme-configurator' ); ?>
121
+ </a>
122
+ </p>
123
+ </div>
124
+ <div class="ctc-input-cell">
125
+ <?php $this->render_theme_menu( 'child', $this->ctc()->get_current_child() ); ?>
126
+ <input type="button" class="button button-primary ctc-analyze-theme" value="<?php _e( 'Analyze', 'child-theme-configurator' ); ?>"/>
127
+ </div>
128
+ <div class="ctc-input-cell"><span class="ctc-analyze-howto"><span class="ctc-step ctc-step-number">3</span>
129
+ <strong>
130
+ <?php _e( 'Analyze Child Theme', 'child-theme-configurator' ); ?>
131
+ </strong>
132
+ <p class="howto indent">
133
+ <?php _e( 'Click "Analyze" to determine stylesheet dependencies and other potential issues.', 'child-theme-configurator' ); ?>
134
+ </p>
135
+ </span>
136
+ </div>
137
+ <div class="ctc-input-cell clear">&nbsp;</div>
138
+ <div class="ctc-input-cell-wide ctc-analysis" id="child_analysis_notice">&nbsp;</div>
139
+ </div>
140
+ <?php
141
+ endif; ?>
142
+ <div class="ctc-input-row clearfix ctc-themeonly-container<?php echo $disabledclass; ?>" id="input_row_new_theme_slug" style="display:none">
143
+ <div class="ctc-input-cell" style="clear:both"><span class="ctc-step ctc-step-number">4</span>
144
+ <strong class="shift">
145
+ <?php _e( 'Name the new theme directory:', 'child-theme-configurator' ); ?>
146
+ </strong>
147
+ </div>
148
+ <div class="ctc-input-cell">
149
+ <input class="ctc_text ctc-themeonly" id="ctc_child_template" name="ctc_child_template" type="text" placeholder="<?php _e( 'Directory Name', 'child-theme-configurator' ); ?>" autocomplete="off" <?php echo $disabled; ?> />
150
+ </div>
151
+ <div class="ctc-input-cell"><span class="howto">
152
+ <strong>
153
+ <?php _e( 'NOTE:', 'child-theme-configurator' ); ?>
154
+ </strong>
155
+ <?php _e( 'This is NOT the name of the Child Theme. You can customize the name, description, etc. in step 7, below.', 'child-theme-configurator' ); ?></span>
156
+
157
+ </div>
158
+ </div>
159
+ <div class="ctc-input-row clearfix ctc-themeonly-container<?php echo $disabledclass; ?>" id="input_row_theme_slug" style="display:none">
160
+ <div class="ctc-input-cell" style="clear:both"><span class="ctc-step ctc-step-number">4</span>
161
+ <strong class="shift">
162
+ <?php _e( 'Verify Child Theme directory:', 'child-theme-configurator' ); ?>
163
+ </strong>
164
+ </div>
165
+ <div class="ctc-input-cell"><code id="theme_slug_container">
166
+ </code>
167
+
168
+
169
+ </div>
170
+ <div class="ctc-input-cell">
171
+ <span class="howto">
172
+ <?php _e( 'For verification only (you cannot modify the directory of an existing Child Theme).', 'child-theme-configurator' ); ?>
173
+ </span>
174
+ </div>
175
+ </div>
176
+ <?php
177
+ $handling = $this->ctc()->get( 'handling' );
178
+ $ignoreparnt = $this->ctc()->get( 'ignoreparnt' );
179
+ $enqueue = $this->ctc()->get( 'enqueue' );
180
+ $this->ctc()->debug( 'handling: ' . $handling . ' ignore: ' . $ignoreparnt . ' enqueue: ' . $enqueue, 'parent-child.php' );
181
+ ?>
182
+ <div class="ctc-input-row clearfix ctc-themeonly-container<?php echo $disabledclass; ?>" id="input_row_stylesheet_handling_container" style="display:none">
183
+ <div class="ctc-input-cell clear" id="input_row_stylesheet_handling"><span class="ctc-step ctc-step-number">5</span>
184
+ <strong class="shift">
185
+ <?php _e( 'Select where to save new styles:', 'child-theme-configurator' ); ?>
186
+ </strong>
187
+ </div>
188
+ <div class="ctc-input-cell-wide sep">
189
+ <div id="child_handling_notice"></div>
190
+ <label>
191
+ <input class="ctc_radio ctc-themeonly" id="ctc_handling_primary" name="ctc_handling" type="radio"
192
+ value="primary" <?php checked( $handling, 'primary' ); ?> <?php echo $disabled; ?> autocomplete="off" />
193
+ <strong>
194
+ <?php _e( "Primary Stylesheet (style.css)", 'child-theme-configurator' ); ?>
195
+ </strong>
196
+ <p class="howto indent sep">
197
+ <?php _e( 'Save new custom styles directly to the Child Theme primary stylesheet, replacing the existing values. The primary stylesheet will load in the order set by the theme.', 'child-theme-configurator' ); ?>
198
+ </p>
199
+ </label>
200
+
201
+
202
+ </div>
203
+ <div class="ctc-input-cell clear">&nbsp;</div>
204
+ <div class="ctc-input-cell-wide">
205
+ <label>
206
+ <input class="ctc_radio ctc-themeonly" id="ctc_handling_separate" name="ctc_handling" type="radio"
207
+ value="separate" <?php checked( $handling, 'separate' ); ?> <?php echo $disabled; ?> autocomplete="off" />
208
+ <strong>
209
+ <?php _e( 'Separate Stylesheet', 'child-theme-configurator' ); ?>
210
+ </strong>
211
+ <p class="howto indent">
212
+ <?php _e( 'Save new custom styles to a separate stylesheet and use any existing child theme styles as a baseline. Select this option if you want to preserve the original child theme styles instead of overwriting them. This option also allows you to customize stylesheets that load after the primary stylesheet.', 'child-theme-configurator' ); ?>
213
+ </p>
214
+ </label>
215
+
216
+
217
+ </div>
218
+ </div>
219
+ <div class="ctc-input-row clearfix ctc-themeonly-container<?php echo $disabledclass; ?>" id="input_row_parent_handling_container" style="display:none">
220
+ <div class="ctc-input-cell clear" id="input_row_parent_handling" title="<?php _e( 'Click to expand', 'child-theme-configurator' ); ?>"><span class="ctc-step ctc-step-number">6</span>
221
+ <strong class="shift">
222
+ <?php _e( 'Select Parent Theme stylesheet handling:', 'child-theme-configurator' ); ?>
223
+ </strong>
224
+ <p class="howto"></p>
225
+ </div>
226
+ <div class="ctc-input-cell-wide sep">
227
+ <div id="parent_handling_notice"></div>
228
+ <?php // deprecated enqueue values
229
+ if ( 'both' == $enqueue || 'child' == $enqueue ):
230
+ $enqueue = 'enqueue';
231
+ endif; ?>
232
+ <label>
233
+ <input class="ctc_checkbox ctc-themeonly" id="ctc_enqueue_enqueue" name="ctc_enqueue" type="radio"
234
+ value="enqueue" <?php checked( $enqueue, 'enqueue' ); ?> <?php echo $disabled; ?> autocomplete="off" />
235
+ <strong>
236
+ <?php _e( 'Use the WordPress style queue.', 'child-theme-configurator' ); ?>
237
+ </strong>
238
+ </label>
239
+
240
+
241
+ <p class="howto indent sep">
242
+ <?php _e( "Let the Configurator determine the appropriate actions and dependencies and update the functions file automatically.", 'child-theme-configurator' ); ?>
243
+ </p>
244
+ <label>
245
+ <input class="ctc_checkbox ctc-themeonly" id="ctc_enqueue_import" name="ctc_enqueue" type="radio"
246
+ value="import" <?php checked( $enqueue, 'import' ); ?> <?php echo $disabled; ?> autocomplete="off" />
247
+ <strong>
248
+ <?php _e( 'Use <code>@import</code> in the child theme stylesheet.', 'child-theme-configurator' ); ?>
249
+ </strong>
250
+ </label>
251
+
252
+
253
+ <p class="howto indent sep">
254
+ <?php _e( "Only use this option if the parent stylesheet cannot be loaded using the WordPress style queue. Using <code>@import</code> is not recommended.", 'child-theme-configurator' ); ?>
255
+ </p>
256
+ <label>
257
+ <input class="ctc_checkbox ctc-themeonly" id="ctc_enqueue_none" name="ctc_enqueue" type="radio"
258
+ value="none" <?php checked( $enqueue, 'none' ); ?> <?php echo $disabled; ?> autocomplete="off" />
259
+ <strong>
260
+ <?php _e( 'Do not add any parent stylesheet handling.', 'child-theme-configurator' ); ?>
261
+ </strong>
262
+ <p class="howto indent sep">
263
+ <?php _e( "Select this option if this theme already handles the parent theme stylesheet or if the parent theme's <code>style.css</code> file is not used for its appearance.", 'child-theme-configurator' ); ?>
264
+ </p>
265
+ </label>
266
+
267
+ </div>
268
+ <div class="ctc-input-cell clear">
269
+ <strong style="float:right">
270
+ <?php _e( 'Advanced handling options', 'child-theme-configurator' ); ?>:</strong>
271
+ <p class="howto">
272
+ </p>
273
+ </div>
274
+ <div class="ctc-input-cell-wide">
275
+ <label><input class="ctc_checkbox ctc-themeonly" id="ctc_ignoreparnt" name="ctc_ignoreparnt" type="checkbox"
276
+ value="1" autocomplete="off" />
277
+ <strong><?php _e( 'Ignore parent theme stylesheets.', 'child-theme-configurator' ); ?></strong>
278
+ <p class="howto indent"><?php _e( 'Do not load or parse the parent theme styles. Only use this option if the Child Theme uses a Framework like Genesis and only uses child theme stylesheets for its appearance.', 'child-theme-configurator' ); ?></p></label>
279
+ </div>
280
+ <div id="ctc_repairheader_container" style="display:none">
281
+ <div class="ctc-input-cell clear">
282
+ <p class="howto">
283
+ </p>
284
+ </div>
285
+ <div class="ctc-input-cell-wide sep">
286
+ <label><input class="ctc_checkbox ctc-themeonly" id="ctc_repairheader" name="ctc_repairheader" type="checkbox"
287
+ value="1" autocomplete="off" />
288
+ <strong><?php _e( 'Repair the header template in the child theme.', 'child-theme-configurator' ); ?></strong>
289
+ <p class="howto indent"><?php _e( 'Let the Configurator (try to) resolve any stylesheet issues listed above. This can fix many, but not all, common problems.', 'child-theme-configurator' ); ?></p></label>
290
+ </div>
291
+ </div>
292
+ <div id="ctc_dependencies_container" style="display:none">
293
+ <div class="ctc-input-cell clear">
294
+ <p class="howto">
295
+ </p>
296
+ </div>
297
+ <div class="ctc-input-cell-wide sep">
298
+ <strong class="indent">
299
+ <?php _e( 'Remove stylesheet dependencies', 'child-theme-configurator' ); ?>
300
+ </strong>
301
+ <p class="howto indent">
302
+ <?php _e( 'By default, the order of stylesheets that load prior to the primary stylesheet is preserved by treating them as dependencies. In rare cases, stylesheets are detected in the preview that are not used site-wide. If necessary, dependency can be removed for specific stylesheets below.', 'child-theme-configurator' ); ?>
303
+ </p>
304
+ <div id="ctc_dependencies"></div>
305
+ </div>
306
+ </div>
307
+ <?php //do_action( 'chld_thm_cfg_enqueue_options' ); // removed for ctc 2.0 ?>
308
+ </div>
309
+ <div class="ctc-input-row clearfix ctc-themeonly-container<?php echo $disabledclass; ?>" id="ctc_child_header_parameters" style="display:none">
310
+ <div class="ctc-input-cell ctc-section-toggle" id="ctc_theme_attributes" title="<?php _e( 'Click to toggle form', 'child-theme-configurator' ); ?>"><span class="ctc-step ctc-step-number">7</span>
311
+ <strong>
312
+ <?php _e( 'Customize the Child Theme Name, Description, Author, Version, etc.:', 'child-theme-configurator' ); ?>
313
+ </strong>
314
+ <span class="howto">
315
+ <?php _e( '(Click to toggle form)', 'child-theme-configurator' ); ?>
316
+ </span>
317
+ </div>
318
+ <div class="clear ctc-section-toggle-content" id="ctc_theme_attributes_content">
319
+ <div class="ctc-input-row clearfix ctc-themeonly-container<?php echo $disabledclass; ?>" id="input_row_child_name">
320
+ <div class="ctc-input-cell">
321
+ <strong>
322
+ <?php _e( 'Child Theme Name', 'child-theme-configurator' ); ?>
323
+ </strong>
324
+ </div>
325
+ <div class="ctc-input-cell-wide">
326
+ <input class="ctc_text ctc-themeonly" id="ctc_child_name" name="ctc_child_name" type="text" value="<?php echo esc_attr( $this->ctc()->get( 'child_name' ) ); ?>" placeholder="<?php _e( 'Theme Name', 'child-theme-configurator' ); ?>" autocomplete="off" <?php echo $disabled; ?> />
327
+ </div>
328
+ </div>
329
+ <div class="ctc-input-row clearfix ctc-themeonly-container<?php echo $disabledclass; ?>" id="input_row_child_website">
330
+ <div class="ctc-input-cell">
331
+ <strong>
332
+ <?php _e( 'Theme Website', 'child-theme-configurator' ); ?>
333
+ </strong>
334
+ </div>
335
+ <div class="ctc-input-cell-wide">
336
+ <input class="ctc_text ctc-themeonly" id="ctc_child_themeuri" name="ctc_child_themeuri" type="text" value="<?php echo esc_attr( $this->ctc()->get( 'themeuri' ) ); ?>" placeholder="<?php _e( 'Theme Website', 'child-theme-configurator' ); ?>" autocomplete="off" <?php echo $disabled; ?> />
337
+ </div>
338
+ </div>
339
+ <div class="ctc-input-row clearfix ctc-themeonly-container<?php echo $disabledclass; ?>" id="input_row_child_author">
340
+ <div class="ctc-input-cell">
341
+ <strong>
342
+ <?php _e( 'Author', 'child-theme-configurator' ); ?>
343
+ </strong>
344
+ </div>
345
+ <div class="ctc-input-cell-wide">
346
+ <input class="ctc_text" id="ctc_child_author" name="ctc_child_author" type="text" value="<?php echo esc_attr( $this->ctc()->get( 'author' ) ); ?>" placeholder="<?php _e( 'Author', 'child-theme-configurator' ); ?>" autocomplete="off"/>
347
+ </div>
348
+ </div>
349
+ <div class="ctc-input-row clearfix ctc-themeonly-container<?php echo $disabledclass; ?>" id="input_row_child_authoruri">
350
+ <div class="ctc-input-cell">
351
+ <strong>
352
+ <?php _e( 'Author Website', 'child-theme-configurator' ); ?>
353
+ </strong>
354
+ </div>
355
+ <div class="ctc-input-cell-wide">
356
+ <input class="ctc_text ctc-themeonly" id="ctc_child_authoruri" name="ctc_child_authoruri" type="text" value="<?php echo esc_attr( $this->ctc()->get( 'authoruri' ) ); ?>" placeholder="<?php _e( 'Author Website', 'child-theme-configurator' ); ?>" autocomplete="off" <?php echo $disabled; ?> />
357
+ </div>
358
+ </div>
359
+ <div class="ctc-input-row clearfix ctc-themeonly-container<?php echo $disabledclass; ?>" id="input_row_child_descr">
360
+ <div class="ctc-input-cell">
361
+ <strong>
362
+ <?php _e( 'Theme Description', 'child-theme-configurator' ); ?>
363
+ </strong>
364
+ </div>
365
+ <div class="ctc-input-cell-wide">
366
+ <textarea class="ctc_text ctc-themeonly" id="ctc_child_descr" name="ctc_child_descr" placeholder="<?php _e( 'Description', 'child-theme-configurator' ); ?>" autocomplete="off" <?php echo $disabled; ?> ><?php echo esc_textarea( $this->ctc()->get( 'descr' ) ); ?></textarea>
367
+ </div>
368
+ </div>
369
+ <div class="ctc-input-row clearfix ctc-themeonly-container<?php echo $disabledclass; ?>" id="input_row_child_tags">
370
+ <div class="ctc-input-cell">
371
+ <strong>
372
+ <?php _e( 'Theme Tags', 'child-theme-configurator' ); ?>
373
+ </strong>
374
+ </div>
375
+ <div class="ctc-input-cell-wide">
376
+ <textarea class="ctc_text ctc-themeonly" id="ctc_child_tags" name="ctc_child_tags" placeholder="<?php _e( 'Tags', 'child-theme-configurator' ); ?>" autocomplete="off" <?php echo $disabled; ?> ><?php echo esc_textarea( $this->ctc()->get( 'tags' ) ); ?></textarea>
377
+ </div>
378
+ </div>
379
+ <div class="clearfix ctc-themeonly-container<?php echo $disabledclass; ?>" id="input_row_child_version">
380
+ <div class="ctc-input-cell">
381
+ <strong>
382
+ <?php _e( 'Version', 'child-theme-configurator' ); ?>
383
+ </strong>
384
+ </div>
385
+ <div class="ctc-input-cell">
386
+ <input class="ctc_text" id="ctc_child_version" name="ctc_child_version" type="text" value="<?php echo esc_attr( $this->ctc()->get( 'version' ) ); ?>" placeholder="<?php _e( 'Version', 'child-theme-configurator' ); ?>" autocomplete="off"/>
387
+ </div>
388
+ </div>
389
+ </div>
390
+ </div>
391
+ <?php //if ( ! is_multisite() || ! empty( $this->ctc()->themes[ 'parnt' ][ $this->ctc()->get_current_parent() ][ 'allowed' ] ) ): ?>
392
+ <div class="ctc-input-row clearfix ctc-themeonly-container<?php echo $disabledclass; ?>" id="ctc_copy_theme_mods" style="display:none">
393
+ <div class="ctc-input-cell">
394
+ <label for="ctc_parent_mods"><span class="ctc-step ctc-step-number">8</span><strong>
395
+ <?php _e( 'Copy Menus, Widgets and other Customizer Settings from the Parent Theme to the Child Theme:', 'child-theme-configurator' ); ?>
396
+ </strong> </label>
397
+ </div>
398
+ <div class="ctc-input-cell-wide howto">
399
+ <label for="ctc_parent_mods">
400
+ <input class="ctc_checkbox ctc-themeonly" id="ctc_parent_mods" name="ctc_parent_mods" type="checkbox"
401
+ value="1" <?php echo $disabled; ?> />
402
+ <strong>
403
+ <?php _e( 'NOTE:', 'child-theme-configurator' ); ?>
404
+ </strong>
405
+ <?php _e( "This option replaces the Child Theme's existing Menus, Widgets and other Customizer Settings with those from the Parent Theme. You should only need to use this option the first time you configure a Child Theme.", 'child-theme-configurator' ); ?>
406
  </label>
407
+
408
+
409
+ </div>
410
+ </div>
411
+ <?php //endif; ?>
412
+
413
+ <div class="ctc-input-row clearfix" id="ctc_configure_submit" style="display:none">
414
+ <div class="ctc-input-cell"><span class="ctc-step ctc-step-number">9</span>
415
+ <strong class="shift">
416
+ <?php _e( 'Click to run the Configurator:', 'child-theme-configurator' ); ?>
417
+ </strong>
418
+ </div>
419
+ <div class="ctc-input-cell-wide">
420
+ <input class="ctc_submit button button-primary" id="ctc_load_styles" name="ctc_load_styles" type="submit" value="<?php _e( 'Configure Child Theme', 'child-theme-configurator' ); ?>" disabled/>
421
+ </div>
422
+ </div>
423
+
424
+ <?php
425
+ else :
426
+
427
+
428
+ // plugin inputs
429
+ wp_nonce_field( 'ctc_plugin' );
430
+ ?>
431
+ <input class="ctc-hidden" id="ctc_theme_parnt" name="ctc_theme_parnt" type="hidden" value="<?php echo $this->ctc()->css->get_prop( 'parnt' ); ?>"/>
432
+ <input class="ctc-hidden" id="ctc_theme_child" name="ctc_theme_child" type="hidden" value="<?php echo $this->ctc()->css->get_prop( 'child' ); ?>"/>
433
+ <input class="ctc-hidden" id="ctc_action" name="ctc_action" type="hidden" value="plugin"/>
434
+ <input class="ctc-hidden" id="ctc_child_type" name="ctc_child_type" type="hidden" value="existing"/>
435
+ <div class="ctc-input-cell-wide ctc-analysis" id="child_analysis_notice">&nbsp;</div>
436
+ <div class="ctc-input-row clearfix" id="ctc_stylesheet_files">
437
+ <?php
438
+ $stylesheets = ChildThemeConfiguratorPro::ctcp()->get_css_files();
439
+ if ( count( $stylesheets ) ): ?>
440
+ <div class="ctc-input-cell ctc-section-toggle" id="ctc_additional_css_files">
441
+ <strong>
442
+ <?php _e( 'Parse Plugin stylesheets:', 'chld_thm_cfg' ); ?>
443
+ </strong>
444
+ </div>
445
+ <div class="ctc-input-cell-wide ctc-section-toggle-content" id="ctc_additional_css_files_content" style="display:block">
446
+ <p style="margin-top:0">
447
+ <?php _e( 'Select the plugin stylesheets you wish to customize below.', 'chld_thm_cfg' ); ?>
448
+ </p>
449
+ <ul>
450
+ <?php
451
+ foreach ( $stylesheets as $stylesheet => $label ): ?>
452
+ <li><label>
453
+ <input class="ctc_checkbox" name="ctc_additional_css[]" type="checkbox"
454
  value="<?php echo $stylesheet; ?>" />
455
+ <?php echo $label; ?></label>
456
+
457
+ </li>
458
+ <?php
459
+ endforeach; ?>
460
+ </ul>
461
+ </div>
462
+ <?php
463
+ endif; ?>
464
+ </div>
465
+ <div class="ctc-input-row clearfix" id="ctc_configure_submit_plugins" style="display:none">
466
+ <div class="ctc-input-cell">
467
+ <strong class="shift">
468
+ <?php _e( 'Click to run the Configurator:', 'child-theme-configurator' ); ?>
469
+ </strong>
470
+ </div>
471
+ <div class="ctc-input-cell-wide">
472
+ <input class="ctc_submit button button-primary" id="ctc_load_styles_plugins" name="ctc_load_styles" type="submit" value="<?php _e( 'Configure Plugin Styles', 'child-theme-configurator' ); ?>" disabled/>
473
+ </div>
474
+ </div>
475
+ <?php endif; ?>
476
+ </form>
477
+ </div>
 
 
 
includes/forms/query-selector.php CHANGED
@@ -6,12 +6,13 @@ if ( !defined( 'ABSPATH' ) ) exit;
6
 
7
  <div id="query_selector_options_panel"
8
  class="ctc-option-panel<?php echo 'query_selector_options' == $active_tab ? ' ctc-option-panel-active' : ''; ?>" <?php echo $hidechild; ?>>
 
9
  <form id="ctc_query_selector_form" method="post" action="?page=<?php echo $ctcpage; ?>">
10
  <?php wp_nonce_field( apply_filters( 'chld_thm_cfg_action', 'ctc_update' ) ); ?>
11
  <div class="ctc-input-row clearfix" id="input_row_query">
12
  <div class="ctc-input-cell"> <strong>
13
- <?php _e( 'Query', 'child-theme-configurator' ); ?>
14
- </strong> </div>
15
  <div class="ctc-input-cell" id="ctc_sel_ovrd_query_selected">&nbsp;</div>
16
  <div class="ctc-input-cell">
17
  <div class="ui-widget">
@@ -37,7 +38,7 @@ if ( !defined( 'ABSPATH' ) ) exit;
37
  <?php _e( 'Sample', 'child-theme-configurator' ); ?>
38
  </strong></div>
39
  <div class="ctc-input-cell clearfix" style="max-height:150px;overflow:hidden">
40
- <div class="ctc-swatch" id="ctc_child_all_0_swatch"><?php echo $this->ctc()->swatch_text; ?></div>
41
  </div>
42
  <div id="ctc_status_sel_val"></div>
43
  <div class="ctc-input-cell ctc-button-cell" id="ctc_save_query_selector_cell">
@@ -53,7 +54,7 @@ if ( !defined( 'ABSPATH' ) ) exit;
53
  <?php _e( 'Property', 'child-theme-configurator' ); ?>
54
  </strong> </div>
55
  <div class="ctc-input-cell"> <strong>
56
- <?php _e( 'Parent Value', 'child-theme-configurator' ); ?>
57
  </strong> </div>
58
  <div class="ctc-input-cell"> <strong>
59
  <?php _e( 'Child Value', 'child-theme-configurator' ); ?>
6
 
7
  <div id="query_selector_options_panel"
8
  class="ctc-option-panel<?php echo 'query_selector_options' == $active_tab ? ' ctc-option-panel-active' : ''; ?>" <?php echo $hidechild; ?>>
9
+ <p class="howto"><?php _e( 'To find and edit specific selectors within @media query blocks, first choose the query, then the selector. Use the "base" query to edit all other selectors.', 'child-theme-configurator' ); ?></p>
10
  <form id="ctc_query_selector_form" method="post" action="?page=<?php echo $ctcpage; ?>">
11
  <?php wp_nonce_field( apply_filters( 'chld_thm_cfg_action', 'ctc_update' ) ); ?>
12
  <div class="ctc-input-row clearfix" id="input_row_query">
13
  <div class="ctc-input-cell"> <strong>
14
+ <?php _e( '@media Query', 'child-theme-configurator' ); ?>
15
+ </strong> <?php _e( '( or "base" )', 'child-theme-configurator' ); ?></div>
16
  <div class="ctc-input-cell" id="ctc_sel_ovrd_query_selected">&nbsp;</div>
17
  <div class="ctc-input-cell">
18
  <div class="ui-widget">
38
  <?php _e( 'Sample', 'child-theme-configurator' ); ?>
39
  </strong></div>
40
  <div class="ctc-input-cell clearfix" style="max-height:150px;overflow:hidden">
41
+ <div class="ctc-swatch" id="ctc_child_all_0_swatch"><?php echo $this->swatch_txt; ?></div>
42
  </div>
43
  <div id="ctc_status_sel_val"></div>
44
  <div class="ctc-input-cell ctc-button-cell" id="ctc_save_query_selector_cell">
54
  <?php _e( 'Property', 'child-theme-configurator' ); ?>
55
  </strong> </div>
56
  <div class="ctc-input-cell"> <strong>
57
+ <?php _e( 'Baseline Value', 'child-theme-configurator' ); ?>
58
  </strong> </div>
59
  <div class="ctc-input-cell"> <strong>
60
  <?php _e( 'Child Value', 'child-theme-configurator' ); ?>
includes/forms/related.php CHANGED
@@ -1 +1 @@
1
- <span style="float:right;margin-left:2em;margin-top:-6px;text-shadow:1px 2px 0 #fff"><strong><?php _e( 'New user?','child-theme-configurator' ); ?> <span style="color:#F1823B"><?php _e( 'Click help', 'child-theme-configurator' ); ?></span></strong> <i class="dashicons dashicons-arrow-right-alt" style="color:#F1823B"></i></span><a href="<?php echo CHLD_THM_CFG_DOCS_URL; ?>/child-theme-configurator-pro/" target="_blank" title="<?php _e( 'Get CTC Pro and other tools', 'child-theme-configurator' ); ?>" style="float:right"><img src="<?php echo CHLD_THM_CFG_URL; ?>css/lilaea-logo.png" height="36" width="145" alt="<?php _e( 'Lilaea Media - Responsive Tools for a Mobile World', 'child-theme-configurator' ); ?>" /></a>
1
+ <span style="float:right;margin-left:2em;margin-top:-6px;text-shadow:1px 2px 0 #fff"><strong><?php _e( 'New user?', 'child-theme-configurator' ); ?> <span style="color:#F1823B"><?php _e( 'Click help', 'child-theme-configurator' ); ?></span></strong> <i class="dashicons dashicons-arrow-right-alt" style="color:#F1823B"></i></span><a href="<?php echo CHLD_THM_CFG_DOCS_URL; ?>/child-theme-configurator-pro/" target="_blank" title="<?php _e( 'Get CTC Pro and other tools', 'child-theme-configurator' ); ?>" style="float:right"><img src="<?php echo CHLD_THM_CFG_URL; ?>css/lilaea-logo.png" height="36" width="145" alt="<?php _e( 'Lilaea Media - Responsive Tools for a Mobile World', 'child-theme-configurator' ); ?>" /></a>
includes/forms/rule-value.php CHANGED
@@ -6,6 +6,7 @@ if ( !defined( 'ABSPATH' ) ) exit;
6
 
7
  <div id="rule_value_options_panel"
8
  class="ctc-option-panel<?php echo 'rule_value_options' == $active_tab ? ' ctc-option-panel-active' : ''; ?>" <?php echo $hidechild; ?>>
 
9
  <form id="ctc_rule_value_form" method="post" action="?page=<?php echo $ctcpage; ?>">
10
  <?php wp_nonce_field( apply_filters( 'chld_thm_cfg_action', 'ctc_update' ) ); ?>
11
  <div class="ctc-input-row clearfix" id="ctc_input_row_rule_menu">
6
 
7
  <div id="rule_value_options_panel"
8
  class="ctc-option-panel<?php echo 'rule_value_options' == $active_tab ? ' ctc-option-panel-active' : ''; ?>" <?php echo $hidechild; ?>>
9
+ <p class="howto"><?php _e( 'To find and edit selectors containing specific values for a given property, first choose the property (e.g., "color"), then click "Selectors" for any resulting value. A dialog panel will open with the corresponding selectors, grouped by media query.', 'child-theme-configurator' ); ?></p>
10
  <form id="ctc_rule_value_form" method="post" action="?page=<?php echo $ctcpage; ?>">
11
  <?php wp_nonce_field( apply_filters( 'chld_thm_cfg_action', 'ctc_update' ) ); ?>
12
  <div class="ctc-input-row clearfix" id="ctc_input_row_rule_menu">
includes/forms/settings-errors.php ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Exit if accessed directly
3
+ if ( !defined( 'ABSPATH' ) ) exit;
4
+ if ( count( $this->ctc()->errors ) ): ?>
5
+
6
+ <div class="error notice is-dismissible">
7
+ <ul>
8
+ <?php
9
+ foreach ( $this->ctc()->errors as $err ):
10
+ echo '<li>' . $err . '</li>' . LF;
11
+ endforeach; ?>
12
+ </ul>
13
+ </div>
14
+ <?php
15
+ elseif ( isset( $_GET[ 'updated' ] ) ):
16
+ $child_theme = wp_get_theme( $this->ctc()->get( 'child' ) ); ?>
17
+ <div class="updated notice is-dismissible">
18
+ <?php
19
+ if ( 4 == $_GET[ 'updated' ] ): ?>
20
+ <p> <?php printf( __( 'Child Theme <strong>%s</strong> has been reset. Please configure it using the settings below.', 'child-theme-configurator' ), $child_theme->Name ); ?> </p>
21
+ <?php
22
+ elseif ( 7 == $_GET[ 'updated' ] ): ?>
23
+ <p>
24
+ <?php _e( 'Update Key saved successfully.', 'child-theme-configurator' ); ?>
25
+ </p>
26
+ <?php
27
+ elseif ( 8 == $_GET[ 'updated' ] ): ?>
28
+ <p>
29
+ <?php _e( 'Child Theme files modified successfully.', 'child-theme-configurator' ); ?>
30
+ </p>
31
+ <?php else: ?>
32
+ <p class="ctc-success-response"><?php echo apply_filters( 'chld_thm_cfg_update_msg', sprintf( __( 'Child Theme <strong>%s</strong> has been generated successfully.', 'child-theme-configurator' ), $child_theme->Name ), $this->ctc() ); ?>
33
+ <?php
34
+ if ( $this->ctc()->is_theme() ): ?>
35
+ <strong>
36
+ <?php _e( 'IMPORTANT:', 'child-theme-configurator' ); ?>
37
+ <?php
38
+ if ( is_multisite() && !$child_theme->is_allowed() ):
39
+ printf( __( 'You must %sNetwork enable%s your child theme.', 'child-theme-configurator' ),
40
+ sprintf( '<a href="%s" title="%s" class="ctc-live-preview">',
41
+ network_admin_url( '/themes.php' ),
42
+ __( 'Go to Themes', 'child-theme-configurator' ) ),
43
+ '</a>'
44
+ );
45
+ else:
46
+ printf( __( '%sPreview your child theme%s before activating.', 'child-theme-configurator' ),
47
+ sprintf( '<a href="%s" title="%s" class="ctc-live-preview">',
48
+ admin_url( '/customize.php?theme=' . $this->ctc()->css->get_prop( 'child' ) ),
49
+ __( 'Live Preview', 'child-theme-configurator' ) ),
50
+ '</a>'
51
+ );
52
+ endif; ?>
53
+ </strong></p>
54
+ <?php
55
+ endif;
56
+ endif; ?>
57
+ </div>
58
+ <?php
59
+ endif;
60
+
includes/forms/tabs.php CHANGED
@@ -8,34 +8,32 @@ $active_tab = isset( $_GET[ 'tab' ] ) ? $_GET[ 'tab' ] : 'parent_child_options';
8
  <h2 class="nav-tab-wrapper clearfix">
9
  <a id="parent_child_options" href=""
10
  class="nav-tab<?php echo 'parent_child_options' == $active_tab ? ' nav-tab-active' : ''; ?>">
11
- <?php _e( 'Parent/Child', 'child-theme-configurator' ); ?>
12
- </a>
13
- <?php if ( $enqueueset ): ?>
14
- <!----><a id="query_selector_options" href=""
15
  class="nav-tab<?php echo 'query_selector_options' == $active_tab ? ' nav-tab-active' : ''; ?>" <?php echo $hidechild; ?>>
16
- <?php _e( 'Query/Selector', 'child-theme-configurator' ); ?>
17
- </a><!----><a id="rule_value_options" href=""
18
  class="nav-tab<?php echo 'rule_value_options' == $active_tab ? ' nav-tab-active' : ''; ?>" <?php echo $hidechild; ?>>
19
- <?php _e( 'Property/Value', 'child-theme-configurator' ); ?>
20
- </a><!----><a id="import_options" href=""
 
 
21
  class="nav-tab<?php echo 'import_options' == $active_tab ? ' nav-tab-active' : ''; ?>" <?php echo $hidechild; ?>>
22
  <?php _e( 'Web Fonts', 'child-theme-configurator' ); ?>
23
- </a><!----><a id="view_child_options" href=""
24
- class="nav-tab<?php echo 'view_child_options' == $active_tab ? ' nav-tab-active' : ''; ?>" <?php echo $hidechild; ?>>
25
- <?php _e( 'Child CSS', 'child-theme-configurator' ); ?>
26
- </a><!----><a id="view_parnt_options" href=""
27
  class="nav-tab<?php echo 'view_parnt_options' == $active_tab ? ' nav-tab-active' : ''; ?>" <?php echo $hidechild; ?>>
28
- <?php _e( 'Parent CSS', 'child-theme-configurator' ); ?>
29
- </a>
30
- <?php
31
- if ( '' == $hidechild ):
32
- ?>
33
- <a id="file_options" href="" class="nav-tab<?php echo 'file_options' == $active_tab ? ' nav-tab-active' : ''; ?>" <?php echo $hidechild; ?>>
 
34
  <?php _e( 'Files', 'child-theme-configurator' ); ?>
35
- </a>
36
- <?php
37
  endif;
38
- do_action( 'chld_thm_cfg_tabs', $this->ctc(), $active_tab, $hidechild );
39
  endif; ?>
40
  <i id="ctc_status_preview"></i>
41
  </h2>
8
  <h2 class="nav-tab-wrapper clearfix">
9
  <a id="parent_child_options" href=""
10
  class="nav-tab<?php echo 'parent_child_options' == $active_tab ? ' nav-tab-active' : ''; ?>">
11
+ <?php _e( 'Parent/ Child', 'child-theme-configurator' ); ?>
12
+ </a><?php if ( $enqueueset ): ?><a id="query_selector_options" href=""
 
 
13
  class="nav-tab<?php echo 'query_selector_options' == $active_tab ? ' nav-tab-active' : ''; ?>" <?php echo $hidechild; ?>>
14
+ <?php _e( 'Query/ Selector', 'child-theme-configurator' ); ?>
15
+ </a><a id="rule_value_options" href=""
16
  class="nav-tab<?php echo 'rule_value_options' == $active_tab ? ' nav-tab-active' : ''; ?>" <?php echo $hidechild; ?>>
17
+ <?php _e( 'Property/ Value', 'child-theme-configurator' ); ?>
18
+ </a><?php
19
+ if ( $this->ctc()->is_theme() ):
20
+ ?><a id="import_options" href=""
21
  class="nav-tab<?php echo 'import_options' == $active_tab ? ' nav-tab-active' : ''; ?>" <?php echo $hidechild; ?>>
22
  <?php _e( 'Web Fonts', 'child-theme-configurator' ); ?>
23
+ </a><?php
24
+ endif; ?><a id="view_parnt_options" href=""
 
 
25
  class="nav-tab<?php echo 'view_parnt_options' == $active_tab ? ' nav-tab-active' : ''; ?>" <?php echo $hidechild; ?>>
26
+ <?php _e( 'Baseline Styles', 'child-theme-configurator' ); ?>
27
+ </a><a id="view_child_options" href=""
28
+ class="nav-tab<?php echo 'view_child_options' == $active_tab ? ' nav-tab-active' : ''; ?>" <?php echo $hidechild; ?>>
29
+ <?php _e( 'Child Styles', 'child-theme-configurator' ); ?>
30
+ </a><?php
31
+ if ( '' == $hidechild && $this->ctc()->is_theme() ):
32
+ ?><a id="file_options" href="" class="nav-tab<?php echo 'file_options' == $active_tab ? ' nav-tab-active' : ''; ?>" <?php echo $hidechild; ?>>
33
  <?php _e( 'Files', 'child-theme-configurator' ); ?>
34
+ </a><?php
 
35
  endif;
36
+ do_action( 'chld_thm_cfg_tabs', $active_tab, $hidechild );
37
  endif; ?>
38
  <i id="ctc_status_preview"></i>
39
  </h2>
includes/forms/theme-menu.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Exit if accessed directly
3
+ if ( !defined( 'ABSPATH' ) ) exit;
4
+ ?>
5
+
6
+ <select class="ctc-select" id="ctc_theme_<?php echo $template; ?>" name="ctc_theme_<?php echo $template; ?>"
7
+ style="visibility:hidden" <?php echo $this->ctc()->is_theme() ? '' : ' disabled '; ?> autocomplete="off" >
8
+ <?php
9
+ uasort( $this->ctc()->themes[ $template ], array( $this, 'cmp_theme' ) );
10
+ foreach ( $this->ctc()->themes[ $template ] as $slug => $theme )
11
+ echo '<option value="' . $slug . '"' . ( $slug == $selected ? ' selected' : '' ) . '>'
12
+ . esc_attr( $theme[ 'Name' ] ) . '</option>' . LF;
13
+ ?>
14
+ </select>
15
+ <div style="display:none">
16
+ <?php
17
+ foreach ( $this->ctc()->themes[ $template ] as $slug => $theme )
18
+ include ( CHLD_THM_CFG_DIR . '/includes/forms/themepreview.php' ); ?>
19
+ </div>
includes/forms/zipform.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( !defined( 'ABSPATH' ) ) exit;
3
+ ?>
4
+ <form id="ctc_export_theme_form" method="post" action="?page=<?php echo CHLD_THM_CFG_MENU; ?>">
5
+ <?php wp_nonce_field( apply_filters( 'chld_thm_cfg_action', 'ctc_update' ) ); ?>
6
+ <input class="ctc_submit button button-primary" name="ctc_export_child_zip" type="submit" value="<?php _e( 'Export Child Theme', 'child-theme-configurator' ); ?>" />
7
+ <input type="hidden" id="ctc_export_theme" name="ctc_export_theme" value="" />
8
+ </form>
9
+
includes/help/de_DE.php CHANGED
@@ -3,77 +3,70 @@ if ( !defined( 'ABSPATH' ) ) exit;
3
  // Help Content
4
  ?>
5
  <!-- BEGIN tab -->
6
- <h3 id="ctc_getting_started">Hier beginnen</h3>
7
- <p><strong style="font-size:large">10 einfache Schritte zur Erstellung eines Kind-Themas:</strong></p>
8
- <ol>
9
- <li><strong>Thema zum Konfigurieren auswählen</strong> aus dem &quot;Eltern-Thema&quot; Menü.</li>
10
- <li><strong>Wählen Sie &quot;neues&quot; oder &quot;existierendes&quot;.</strong>
11
- <ul>
12
- <li>Wenn keine Kind-Themen verfügbar sind, werden das &quot;Kind-Thema&quot; und &quot;Kind-Thema-Name&quot; automatisch basierend auf dem ausgewählten Eltern-Thema eingefügt. Sie können diese bei Bedarf ändern, aber es darf nicht gleich wie ein bestehendes lauten.</li>
13
- <li>Wenn bestehende Kind-Themen verfügbar sind, gibt es ein zusätzliches Menü bezeichnet mit &quot;Benutze bestehende Kind-Themen&quot; von diesen können Sie auswählen, oder einen neuen Wert zum Neu-Erstellen eingeben.</li>
14
- </ul>
15
- </li>
16
- <li><strong>Optional: Eingabe von Themen-Name, Themen-Webseite, Autor, Autor-Webseite, Beschreibung, Schlagwörtern und Version</strong> für das Kind-Thema. Wird ein bestehendes Kind-Thema benutzt, werden die Werte automatisch basierend auf dem ausgewählten Kind-Thema eingefügt.</li>
17
- <li><strong>Wählen Sie, wie Wordpress die Eltern-Formatvorlage behandeln soll:</strong>
18
- <ul>
19
- <li><strong>Keine (vom Thema behandelt)</strong>
20
- Diese Option auswählen, wenn alle Formatvorlagen für Kind-Themen korrekt eingebunden werden. Wenn Stile nicht korrekt angewendet werden, benutzen Sie eine andere Option</li>
21
- <li><strong>Eltern-Formatvorlage einbinden (Standard)</strong>
22
- Diese Option auswählen, wenn das Thema die aktive Formatvorlage einbindet (enqueued), aber keine Sonderbehandlung für Kind-Themen hat. Bei Unsicherheit mit dieser Option beginnen..</li>
23
- <li><strong>Kind-Formatvorlage einbinden</strong>
24
- Diese Option auswählen, wenn das Thema die Eltern-Formatvorlage einbindet (enqueued), aber die Kind-Formatvorlage überhaupt nicht einbindet. Dies kann passieren, wenn <code>get_template()</code> oder <code>get_template_directory_uri()</code> zum Verknüpfen von Formatvorlagen benutzt wird.</li>
25
- <li><strong>Eltern- und Kind-Formatvorlage einbinden</strong>
26
- Diese Option auswählen, wenn Formatvorlagen-Linktags im Header-Template fix codiert sind (normalerweise in älteren Themen). Dies aktiviert die Übersteuerung der Eltern-Formatvorlage durch die Kind-Formatvorlage ohne das Benutzen von <code>@import</code>.</li>
27
- <li><strong><code>@import</code> der Eltern-Formatvorlage</strong>
28
- Diese Option importiert die Eltern-Formatvorlage aus der Kind-Formatvorlage. Das erlaubt der Kind-Formatvorlage die Übersteuerung der Eltern-Formatvorlage, jedoch ist das Benutzen von <code>@import</code> nicht mehr empfohlen.</li>
29
- </ul></li>
30
- <li><strong>Benutzen der Eltern-Optionen(optional)</strong> Wenn Sie die gleichen Optionen wie im Eltern-Thema verwenden wollen, wählen Sie "Kopieren Eltern-Thema-Menüs, Widgets und andere Optionen". Abhängig vom Thema müssen eventuell einige Optionen separat eingestellt werden. <strong>HINWEIS: Dies wird die Kind-Thema-Optionen überschreiben, die Sie vielleicht schon gesetzt haben.</strong></li>
31
- <li><strong>Backup sichern (optional)</strong> Bei einem bestehenden Kind-Thema können Sie "Backup Formatvorlage" auswählen, um eine Sicherung Ihrer Kind-Formatvorlage im Themen-Verzeichnis zu erstellen.</li>
32
- <li><strong>Wiederherstellen von Sicherung (optional - neu in Version 1.6.0):</strong> Bei einem bestehenden Kind-Thema können Sie wählen, die Kind-Formatvorlage neu zu laden (unverändert lassen), alle Werte zurückzusetzen, oder es aus der Sicherung wiederherzustellen. Wenn Sicherungsdateien vorhanden sind, erscheinen entsprechende Auswahlknöpfe.</li>
33
- <li><strong>Zusätzliche Formatvorlagen auswählen</strong> Benutzt ihr Thema zusätzliche Formatvorlagen, können Sie &quot;Zusätzliche Formatvorlagen auslesen&quot öffnen; umschalten und sie erscheinen als Auswahlkästchen. Formatvorlagen in Gebrauch des Eltern-Themas sollten automatisch für Sie ausgewählt werden. Wählen Sie nur Formatvorlagen aus, die Sie ändern wollen, um eine unnötige Last zu vermeiden. <strong>HINWEIS: Benutzt das Eltern-Thema Bootstrap-Formatvorlagen, werden Sie automatisch ausgewählt.</strong> Sie können Bootstrap-Formatvorlagen manuell auswählen, wenn Sie sie anpassen müssen, aber in den meisten Fällen erzeugt es nur unnötige Mehrbelastung.</li>
34
- <li><strong>Klicken Sie auf "Erstellen/Neuaufbau Kind-Thema-Dateien."</strong></li>
35
- <li><strong>WICHTIG: <a target="_blank" href="<?php echo CHLD_THM_CFG_DOCS_URL; ?>/how-to-use/#preview_activate" title="Testen Sie Ihr Kind-Thema vor der Aktivierung!">Testen Sie das Kind-Thema immer mit der Live-Vorschau vor der Aktivierung!</a></strong></li>
36
  </ol>
37
  <!-- END tab -->
38
  <!-- BEGIN tab -->
39
- <h3 id="ctc_tutorial">Tutorial-Videos</h3>
40
- <p>Wir betten aus Performance-Gründen nicht mehr länger Tutorial-Videos ein. <a href="http://www.childthemeconfigurator.com/tutorial-videos" target="_blank">Hier klicken, um Videos anzuschauen.</a></p><!-- END tab -->
41
- <!-- BEGIN tab -->
42
- <h3 id="ctc_query_selector">Abfrage/Selektor-Reiter</h3>
43
- <p>Es gibt zwei Wege, Eltern-Stile zu identifizieren und zu übersteuern. Der Child Theme Configurator lässt Sie Stile suchen nach <strong>Selektor</strong> oder nach <strong>Eigenschaft</strong>. Wenn Sie einen bestimmten Selektor ändern wollen (z.Bsp. h1), benutzen Sie den "Abfrage/Selektor"-Reiter. Wenn Sie einen Wert Webseiten-weit ändern wollen (z.Bsp. die Farbe des Typs), benutzen Sie den "Eigenschaften/Wert"-Reiter.</p>
44
- <p>Der Abfrage/Selektor-Reiter lässt Sie bestimmte Selektoren finden und bearbeiten. Zuerst finden Sie die Abfrage, die den gesuchten Selektor enthält, indem Sie in die <strong>Abfrage</strong> Autoauswahl-Box schreiben. Wählen Sie durch Mausklick oder "Eingabe"- bzw. "Tabulator"-Tasten. Selektoren sind in der <strong>Basis</strong> Abfrage standardmäßig.</p>
45
  <p>Dann finden Sie den mit der Eingabe in der <strong>Selektor</strong> Autoauswahl-Box. Wählen Sie aus mit Mausklick oder der "Eingabe"- bzw. den "Tabulator"-Tasten.</p>
46
  <p>Dies lädt alle Eigenschaften für diesen Selektor mit den Eltern-Werten auf der linken und den Kind-Werten auf der rechten Seite. Alle bestehenden Kind-Werte werden automatisch abgefüllt. Es gibt auch eine Musteransicht, welches die Kombination der Eltern- und Kindwerte Übersteuerungen anzeigt. Beachten Sie, dass der <strong>Rahmen</strong> und <strong>Hintergrundbild</strong> speziell behandelt werden.</p>
47
- <p>Das "Reihenfolge"-Feld enthält die Original-Reihenfolge des Selektors der Eltern-Formatvorlage. Sie können die Selektor-Reihenfolge ändern, indem Sie eine tiefere/höhere Zahl im Reihenfolge-Feld eingeben. Sie können auch Stil-Übersteuerungen forcieren (!important-Schalter), indem Sie das "!" Kästchen neben der Eingabe anwählen. Benutzen Sie es massvoll.</p>
 
48
  <p>Klicken Sie auf "Sichern" um die Kind-Formatvorlage zu aktualisieren und die Änderungen im Wordpress-Admin zu speichern.</p>
49
  <!-- END tab -->
50
  <!-- BEGIN tab -->
51
- <h3 id="ctc_new_styles">Neue Stile hinzufügen</h3>
52
- <p>Wenn Sie einem Selektor zusätzliche Eigenschaften hinzufügen wollen, laden Sie zuerst den Selektor mittels des "Abfrage/Selektor-Reiters. Dann finden Sie die Eigenschaft, welche Sie übersteuern wollen, indem Sie sie in der <strong>Neue Eigenschaft</strong> Autoauswahl-Box eingeben. Wählen Sie durch Mausklick oder "Eingabe"- bzw. "Tabulator"-Tasten. Dies fügt eine neue Eingabezeile zur Selektoren-Eingabe hinzu.</p>
53
- <p>Wenn Sie komplett neue Selektoren hinzufügen möchten, oder gar @media Abfragen, können Sie beliebiges CSS im Kasten "Rohes CSS" eingeben. Achten Sie auf absolut korrekte Syntax (z.Bsp. ausgeglichene geschweifte Klammerpaare etc.) für den Parser, um die neuen Stile zu laden. Ein rotes "X" erscheint, wenn die Syntax ungültig ist.</p>
54
- <p>Wenn Sie Shorthand-Syntax für die Eigenschaften/Werte bevorzugen (anstatt der zur Verfügung gestellten Eingaben des Child Theme Configurator), können Sie diese hier auch eingeben. Der Parser wird Ihre Eingaben automatisch in normalisiertes CSS umwandeln.</p>
55
  <!-- END tab -->
56
  <!-- BEGIN tab -->
57
- <h3 id="ctc_property_value">Eigenschaften/Wert-Reiter</h3>
58
- <p>Es gibt zwei Wege, Eltern-Stile zu identifizieren und zu übersteuern. Der Child Theme Configurator lässt Sie Stile suchen nach <strong>Selektor</strong> oder nach <strong>Eigenschaft</strong>. Wenn Sie einen bestimmten Selektor ändern wollen (z.Bsp. h1), benutzen Sie den "Abfrage/Selektor"-Reiter. Wenn Sie einen Wert Webseiten-weit ändern wollen (z.Bsp. die Farbe des Typs), benutzen Sie den "Eigenschaften/Wert"-Reiter.</p>There are two ways to identify and override parent styles. The Child Theme Configurator lets you search styles by <strong>selector</strong> and by <strong>property</strong>. If you wish to change a specific selector (e.g., h1), use the "Query/Selector" tab. If you have a specific value you wish to change site-wide (e.g., the color of the type), use the "Property/Value" tab.</p>
59
- <p>Der Eigenschaften/Wert-Reiter lässt Sie bestimmte Werte für eine gewisse Eigenschaft finden und ermöglicht dann das Bearbeiten für individuelle Selektoren, welche diese Eigenschaft-/Wert-Kombination benutzen. Zuerst finden Sie die Eigenschaft, die Sie übersteuern möchten, indem Sie diese in der <strong>Eigenschaft</strong> Autoauswahl-Box eingeben. Wählen Sie durch Mausklick oder "Eingabe"- bzw. "Tabulator"-Tasten.</p>
60
  <p>Dies lädt alle einzigartigen Werte dieser Eigenschaft in der Eltern-Formatvorlage mit einer Mustervorschau für diese Werte. Wenn Werte in der Kind-Formatvorlage existieren, die nicht in der Eltern-Formatvorlage enthalten sind, werden diese ebenfalls angezeigt.</p>
61
  <p>Für jeden einzigartigen Wert, klicken Sie auf die "Selektoren"-Verknüpfung, um eine Liste der Selektoren mit dieser Eigenschaften-/Wert-Kombination anzuzeigen, nach Abfrage gruppiert mit einer Muster-Vorschau der Werte und Eingaben für die Kind-Werte. Alle bestehenden Kind-Werte werden automatisch abgefüllt.</p>
62
  <p>Klicken Sie auf "Sichern" um die Kind-Formatvorlage zu aktualisieren und die Änderungen im Wordpress-Admin zu speichern.</p>
63
  <!-- END tab -->
64
  <!-- BEGIN tab -->
65
- <h3 id="ctc_imports">Webschriftarten-Reiter</h3>
66
- <p>Sie können zusätzliche Formatvorlagen und Webschriftarten verknüpfen, indem Sie @import Regeln in das Textfeld auf dem Webschriftarten-Reiter eingeben.</p>
67
  <p><strong>Hinweis:</strong> Child Theme Configurator schreibt nicht mehr länger @import Regeln in die Formatvorlage. Stattdessen benutzt es das @import Schlüsselwort und stellt sie in die Warteschlange. WordPress wandelt sie dann um in &lt;link&gt; Tags im verarbeiteten HTML.</p>
68
- <p>Wichtig: importieren Sie die Eltern-Formatvorlage nicht hier. Benutzen Sie die "Eltern-Formatvorlage-Behandlung"-Option auf dem Eltern/Kind-Reiter.</p>
69
- <p>Wenn Sie eine Formatvorlage unter "Zusätzliche Formatvorlegen auslesen" gewählt haben, als Sie das Kind-Thema erstellt haben, werden diese Stile für Übersteuerungen in der Kind-Formatvorlage zur Verfügung stehen.</p>
70
  <p>WordPress lädt automatisch zusätzliche Formatvorlagen, wenn es das Eltern-Thema lädt, also müssen Sie @import rules dafür hier nicht hinzufügen.</p>
71
- <p>Unten ist ein Beispiel, welche eine lokale angepasste Formatvorlage lädt (Sie müssen das "fonts" Verzeichnis und die Formatvorlage hinzufügen), sowie die Schriftart "Open Sans" von Google Web Fonts:</p>
72
- <blockquote><pre><code>&#64;import url(fonts/stylesheet.css);
73
  &#64;import url(http://fonts.googleapis.com/css?family=Open+Sans:400,400italic,700,700italic);</code></pre></blockquote>
74
  <!-- END tab -->
75
  <!-- BEGIN tab -->
76
- <h3 id="ctc_files">Dateien-Reiter</h3>
77
  <h5>Eltern-Vorlagen</h5>
78
  <p>Kopieren von PHP-Vorlagendateien des Eltern-Themes, indem Sie die Kästchen auswählen und "Auswahl zu gewählten Kind-Themen kopieren", und die Vorlage wird zum Kind-Themenverzeichnis hinzugefügt.</p>
79
  <p><strong>ACHTUNG: Wenn Ihr Kind-Thema aktiv ist, wird nach dem Kopiervorgang sofort die Kind-Thema-Version der Datei anstatt der Eltern-Datei benutzt.</strong></p>
@@ -85,7 +78,7 @@ Diese Option importiert die Eltern-Formatvorlage aus der Kind-Formatvorlage. Das
85
  <p>Diese Bilder befinden sich unter dem <code>Images</code>-Verzeichnis in Ihrem Kind-Thema-Verzeichnis und sind nur für Formatvorlagen vorgesehen. Benutzen Sie die Medienbibliothek für Inhaltsbilder.</p>
86
  <p>Sie können neue Bilder mittels des "Bild hochladen"-Formulars hochladen. Löschen Sie Bilder durch die Auswahl der Kästchen und dem Klicken auf "Auswahl löschen".</p>
87
  <h5>Kind-Thema Screenshot</h5>
88
- <p>Sie können einen speziellen Screenshot für das Kind-Thema hier hochladen.</p>
89
  <p>Der Themen-Screenshot sollte ein 4:3-Verhältnis aufweisen (z.Bsp, 880px x 660px) JPG, PNG oder GIF. Es wird in <code>screenshot</code> umbenannt.</p>
90
  <h5>Kind-Thema als ZIP-Archiv exportieren </h5>
91
  <p>Sie können Ihr Kind-Thema für den Gebrauch auf einer anderen Wordpress-Webseite herunterladen, indem Sie auf "Export" klicken.</p>
@@ -94,16 +87,16 @@ Diese Option importiert die Eltern-Formatvorlage aus der Kind-Formatvorlage. Das
94
  <h3 id="ctc_preview">Vorschau und Aktivierung</h3>
95
  <p><strong>WICHTIG: <a target="_blank" href="<?php echo CHLD_THM_CFG_DOCS_URL; ?>/how-to-use/#preview_activate" title="Testen Sie Ihr Kind-Thema vor der Aktivierung!">Testen Sie Ihr Kind-Thema vor der Aktivierung!</a></strong> Einige Themen (hauptsächlich kommerzielle Themen) laden Eltern-Formatvorlagen nicht korrekt oder laden Kind-Formatvorlagen automatisch oder PHP-Dateien. <strong>Im schlimmsten Fall wird bei Aktivierung Ihre Webseite unbrauchbar.</strong></p>
96
  <ol>
97
- <li>Navigieren Sie zu Design > Themen im Wordpress-Admin. Sie werden nun die neuen Kind-Themen als eine der installierten sehen.</li>
98
  <li>Klicken Sie auf "Live-Vorschau" unterhalb des Kind-Themas, um es in Aktion zu sehen.</li>
99
- <li>Wenn Sie das Kind-Thema nun live nehmen wollen, klicken Sie auf "Aktivieren."</li>
100
  </ol>
101
  <p><strong>MULTISITE NUTZER:</strong> Sie müssen Ihr Thema Netzwerk-aktivieren, um es in der Live-Vorschau zu sehen. Gehen Sie zu 'Themen' in der Netzwerk-Administration.</p>
102
  <!-- END tab -->
103
  <!-- BEGIN tab -->
104
  <h3 id="ctc_permissions">Dateiberechtigungen</h3>
105
  <p>Wordpress wurde für verschiedene Serverkonfigurationen entwickelt. Child Theme Configurator benutzt die WordPress Filesystem API, um Webseiten das Bearbeiten von Dateien zu ermöglichen, die Nutzerberechtigungen benötigen.</p>
106
- <p>Allerdings, weil die meiste Funktionalität mittels AJAX(Hintergrund)-Anfragen passiert, muss die Kind-Formatvorlage auf dem Server schreibbar sein.</p>
107
  <p>Das Plugin erkennt automatisch Ihre Konfiguration und liefert eine Anzahl von Optionen, um diese Anforderung zu lösen. Benutzen Sie die zur Verfügung gestellten Verknüpfungen, um mehr zu erfahren, beispielsweise:</p>
108
  <ol>
109
  <li>Die Formatvorlage mithilfe des Plugins vorübergehend schreibbar machen.</li>
@@ -114,7 +107,7 @@ Diese Option importiert die Eltern-Formatvorlage aus der Kind-Formatvorlage. Das
114
  <!-- END tab -->
115
  <!-- BEGIN tab -->
116
  <h3 id="ctc_faq">FAQs</h3>
117
- <h5 id="broken_theme">HILFE! Ich habe eine Datei geändert und kann nun über nicht mehr über wp-admin einloggen, um es zu reparieren!</h5>
118
  <p>Um aus einem defekten Thema herauszukommen, müssen Sie das problematische Themen-Verzeichnis umbenennen (via FTP, SSH oder Ihrem Webhoster-Kontrollpanel bzw. Dateimanager), so dass Wordpress es nicht mehr finden kann. WordPress wird dann einen Fehler generieren und zum Standard-Thema zurückkehren (aktuell Twenty-Fourteen).</p>
119
 
120
  <p>Das Kind-Thema ist normalerweise in Ihrem Themen-Verzeichnis</p>
@@ -130,88 +123,93 @@ Diese Option importiert die Eltern-Formatvorlage aus der Kind-Formatvorlage. Das
130
  <h5 id="options_broken">Wieso verschwinden meine Themen-Optionen, wenn ich das Kind-Thema aktiviere?</h5>
131
  <p>Diese Optionen sind für jedes Thema spezifisch und werden getrennt in der Datenbank gespeichert. Beim Erstellen eines neuen Kind-Themas sind diese Optionen leer.</p>
132
 
133
- <p><strong>Viele dieser Optionen können in das Kind-Thema kopiert werden, indem man das Kästchen "Kopieren Eltern-Theme-Menüs, Widgets und andere Design-Optionen" anklickt, wenn Sie die Kind-Thema-Dateien auf dem Eltern/Kind-Reiter erstellen.</strong></p>
134
 
135
  <p>Wenn Sie andere Optionen setzen wollen, können Sie diese nach dem Aktivieren des Kind-Themas aktivieren, oder mittels der Live-Vorschau unter Design > Themen.</p>
136
  <ul class="instructions">
137
- <li><strong>Menüs: </strong> Gehen Sie zu Design > Menüs und klicken Sie den "Position"-Reiter. Standardmäßig wird das Primärmenü die Verknüpfungen automatisch aus den bestehenden Seiten erstellen. Wählen Sie Ihr angepasstes Menü aus der Auswahlliste und klicken Sie "Neues Menü benutzen". Dies ersetzt das Standardmenü und Sie sehen die korrekten Verknüpfungen.</li>
138
 
139
- <li><strong>Header (Kopf): </strong> Gehen Sie zu Design > Header. Einige Themen zeigen standardmäßig den Titel und die Tagline Ihrer "Allgemeinen Einstellungen". Wählen Sie "Bild auswählen" und finden Sie einen "Kopf" aus der Medienbibliothek oder mittels Hochladen. Dies ersetzt den Standard mit dem angepassten Bild.</li>
140
 
141
- <li><strong>Hintergrund: </strong> Gehen Sie zu Design > Hintergrund und wählen Sie ein neues Hintergrundbild oder eine Farbe.</li>
142
 
143
- <li><strong>Optionen: </strong> Jedes Thema behandelt Optionen speziell. Meistens erstellen Sie einen Satz Optionen und speichern ihn in der Wordpress-Datenbank. Einige Optionen sind spezifisch für das aktive Thema (oder Kind-Thema), und einige nur für das Eltern-Thema bestimmt (d.h. das Kind-Thema kann sie NICHT übersteuern). Sie müssen sich beim Themen-Autor erkundigen, welche auf welche Art funktionieren.</li>
144
  </ul>
145
  </p>
146
  <h5 id="existing_parent">Wie verschiebe ich bereits gemachte Änderungen an meinem Thema in mein Kind-Thema?</h5>
147
  <p><a href="<?php echo CHLD_THM_CFG_DOCS_URL; ?>/how-to-use/#child_from_modified_parent" class="scroll-to">Folgen Sie diesen Schritten</a>. </p>
148
  <h5 id="web_fonts">Wie füge ich Webschriftarten hinzu?</h5>
149
- <p>Die einfachste Methode ist das Einfügen des @import code, geliefert von <a href="http://www.google.com/fonts" title="Google Fonts">Google</a>, <a href="http://www.fontsquirrel.com/" title="Font Squirrel">Font Squirrel</a> oder jeder anderen Schriftartenseite auf dem Schriftarten-Reiter. Die Schriftarten werden dann zum Gebrauch als Wert der <strong>font-family</strong> Eigenschaft zur Verfügung stehen. Stellen Sie sicher, dass Sie die Lizenz zum Gebrauch der Webschriftarten verstehen. </p>
150
- <p>Sie können auch eine sekundäre Formatvorlage erstellen, welche die @font-face Regeln enthält, und diese auf dem Webschriftarten-Reiter importieren. </p>
151
  <h5 id="plugin">Funktionert das mit Plugins?</h5>
152
  <p>Wir bieten eine Premium-Erweiterung an, die Sie Stile für jedes auf der Webseite installierte Plugin einfach verändern lässt. Der Child Theme Configurator Plugin Extension scannt Ihre Plugins und erlaubt die Erstellung von angepassten Formatvorlagen in Ihrem Kind-Thema. <a href="<?php echo CHLD_THM_CFG_DOCS_URL; ?>/child-theme-configurator-pro/" title="Die Kontrolle über Ihre Plugin-Stile mit der Child Theme Configurator Plugin Erweiterung für WordPress übernehmen">Mehr erfahren <i class="genericon genericon-next"></i></a>
153
  <h5 id="doesnt_work">Wieso funktioniert das in meinem (Hersteller des Themas hier einfügen) Thema nicht?</h5>
154
  <p>Einige Themen (hauptsächlich kommerzielle Themen) laden die Eltern-Vorlagen-Dateien nicht korrekt oder laden Kind-Thema-Formatvorlagen oder PHP-Dateien automatisch.</p><p>Das ist unglücklich, weil es im besten Fall den Webmaster daran hindert, Anpassungen vorzunehmen (abgesehen von solchen durch die Themen-Optionen), die einen Upgrade überleben. <strong>Im schlimmsten Fall jedoch wird Ihre Webseite unbrauchbar, wenn Sie das Kind-Thema aktivieren.</strong> </p>
155
  <p>Kontaktieren Sie direkt den Hersteller, um diese Kern-Funktionalität zu verlangen. Unserer Meinung nach sollten ALLE Themen (vor allem kommerzielle) die von Wordpress.org beschriebenen Themen-Tests erfüllen. </p>
156
  <h5 id="missing_parent">Wieso hat das Eltern-Thema keine Stile, wenn ich auf "Eltern-CSS anzeigen" gehe?</h5>
157
- <p>Ihr Eltern-Thema benutzt für die Formatvorlagen womöglich einen getrennten Ort. Wählen Sie individuelle Formatvorlagen aus dem "Zusätzliche Formatvorlagen auslesen"-Abschnitt des Eltern/Kind-Reiters und klicken Sie erneut auf "Neuaufbau Kind-Thema-Dateien". </p>
158
  <h5 id="performance">Wird das meine Webseite verlangsamen?</h5>
159
  Sobald die Kind-Formatvorlage erstellt ist, fügt CTC im Frontend nur ein wenig Zusatzlast hinzu, da die ganze Funktionalität im Admin enthalten ist.
160
 
161
- Das Plugin lädt den Hauptteil des Codes im Admin nur, wenn Sie das Tool benutzen. Die größte Performance-Einbusse geschieht, wenn Sie die Kind-Themen-Dateien auf dem Eltern/Kind-Reiter erstellen. </p>
162
  <h5 id="where_are_styles">Wo sind die Stile? Der Konfigurator zeigt nichts an!</h5>
163
  <p>Alle Stile werden dynamisch geladen. Sie müssen in den Textfelder etwas eingeben, um die Stile zum Bearbeiten auszuwählen.</p>
164
  <p>"Base" ist die Abfragegruppe, die mit keiner bestimmten at-Regel verbunden sind.</p>
165
- <p>Beginnen Sie mit einem Klick auf den "Abfage/Selektor"-Reiter und der Eingabe von "base" in der ersten Box. In der zweiten Box können Sie dann mit der Eingabe beginnen, um die Stil-Selektoren zum Bearbeiten zu holen. </p>
166
- <h5 id="preview-not-loading">Wieso zeigen die Vorschau-Reiter "Formatvorlage kann nicht angezeigt werden"?</h5>
167
- <p>Sie müssen ein Kind-Thema auf dem Eltern/Kind-Reiter für die Ansicht der Vorschau laden. Das kann auch passieren, wenn Ihre WP_CONTENT_URL sich von $bloginfo('site_url') unterscheidet. Ajax kann keine domänenübergreifenden Abfagen machen. Überprüfen Sie, ob der Einstellungen > Allgemein > "WordPress Adresse (URL)"-Wert korrekt ist. (Oft fehlt das "www"" in der Domäne.) </p>
168
  <h5 id="edit_manually">Kann ich das Kind-Thema manuell offline bearbeiten (oder mithilfe des Editors), oder muss ich unbedingt den Konfigurator benutzen?</h5>
169
  <p>Sie können jede gewünschte Änderung an der Formatvorlage vornehmen. Stellen Sie nur sicher, die geänderte Formatvorlage mittels des Eltern/Kind-Panels zu importieren, ansonsten wird der Konfigurator Ihre Änderungen beim nächsten Gebrauch überschreiben. Folgen Sie den üblichen Schritten, aber wählen Sie die Auswahloption "Bestehendes Kind-Thema benutzen" als Kind-Thema-Option. Der Konfigurator wird die internen Daten aus der neuen Formatvorlage automatisch aktualisieren. </p>
170
  <h5 id="update_child">Wenn das Eltern-Thema geändert wird (z.Bsp. Upgrade), muss ich das Kind-Thema aktualisieren?</h5>
171
  <p>Nein. Das ist der Zweck von Kind-Themen. Änderungen am Eltern-Thema werden vom Kind-Thema automatisch geerbt.</p>
172
  <p>Ein Kind-Thema ist keine Kopie eines Eltern-Themas. Es ist eine besondere Funktion von WordPress, die Sie bestimmte Stile und Funktionen übersteuern lässt, während der Rest intakt bleibt. Das einzige Mal, dass Sie nach einem Upgrade Änderungen machen müssen ist, wenn das Eltern-Thema Stile oder Funktionsnamen ändert oder entfernt. Qualitäts-Themen sollten alle veralteten Funktionen oder Stile in den Upgrade-Hinweisen erwähnen, so dass Nutzer von Kind-Themen die entsprechenden Anpassungen vornehmen können. </p>
173
  <h5 id="functions">Wo sind die .PHP-Dateien?</h5>
174
- <p>Der Konfigurator fügt dem Kind-Themenverzeichnis automatisch eine leere functions.php-Datei hinzu. Sie können Dateien des Eltern-Themas mittels des "Dateien"-Reiters kopieren. Wenn Sie neue Vorlagen und Verzeichnisse erstellen möchten, müssen Sie diese manuell via FTP oder SSH hochladen. Beachten Sie, dass ein Kind-Thema die Eltern-Vorlagen automatisch erbt, es sei denn, sie bestehen bereits im Kind-Thema-Verzeichnis. Kopieren Sie nur Vorlagen, die Sie auch wirklich anpassen möchten.</p>
175
  <h5 id="specific_color">Wie ändere ich eine(n) bestimmte Farbe/Schriftarttyp/Hintergrund?</h5>
176
- <p>Sie können einen bestimmten Wert global mittels des Eigenschaften/Wert-Reiters übersteuern. Siehe Eigenschaften/Werte, oben.</p>
177
  <h5 id="add_styles">Wie füge ich Stile hinzu, die nicht im Eltern-Thema enthalten sind?</h5>
178
- <p>Sie können Abfragen und Selektoren mittels des "Rohes CSS"-Textfelds auf dem Abfrage/Selektor-Reiter hinzufügen. Siehe Abfrage/Selektor, oben. </p>
179
  <h5 id="add_styles">Wie entferne ich Stile aus dem Eltern-Thema?</h5>
180
  <p>Sie sollten eigentlich Stile aus dem Eltern-Thema nicht entfernen. Sie können allerdings die Eigenschaft auf "Erben"," "Keine," oder Null setzen (abhängig von der Eigenschaft). Das wird den Eltern-Wert negieren. Ein wenig Probieren wird nötig sein.</p>
181
  <h5 id="remove_styles">Wie entferne ich einen Stil aus einem Kind-Thema?</h5>
182
  <p>Löschen Sie den Wert aus der Eingabe der Eigenschaft, die sie entfernen möchten. Der Child Theme Configurator fügt Übersteuerungen nur für Eigenschaften mit Werten hinzu. </p>
183
  <h5 id="important_flag">Wie setze ich den !important-Schalter?</h5>
184
  <p>Wir empfehlen immer ein gutes, verschachteltes Design, anstatt auf globale Übersteuerungen zu vertrauen. Dazu haben Sie die Möglichkeit, die Lade-Reihenfolge von Kind-Formatvorlagen zu ändern, indem Sie einen Wert im "Reihenfolge"-Feld eingeben. Sie können Eigenschaften als wichtig setzen, indem Sie das Kästchen mit dem "!" neben jeder Eingabe setzen. Benutzen Sie es massvoll. </p>
185
- <h5 id="gradients">Wie erstelle ich browser-unabhängige Verläufe?</h5>
186
  <p>Der Child Theme Configurator benutzt eine standarisierte Syntax für Farbverläufe und unterstützt nur zweifarbige Verläufe ohne Zwischenstopps. Die Eingaben bestehen aus dem Startpunkt (z.Bsp. top, left, 135deg, etc.), der Startfarbe und der Endfarbe. Browser-spezifische Syntax wird automatisch erstellt, wenn Sie diese Werte speichern. Siehe Tricks/Fallen, unten, für weitere Informationen. </p>
187
  <h5 id="responsive">Wie mache ich das Thema responsive?</h5>
188
  <p>Die kurze Antwort ist, ein responsives Eltern-Thema zu benutzen. Einige übliche Methoden für responsives Design sind:
189
  <ul class="instructions"><li>Vermeiden von festen Breiten und Höhen. Der Gebrauch von max- and min-height Werten und Prozenten sind Wege, das Design dem Browser des Benutzers anzupassen.</li>
190
  <li>Die Kombination von floats und clears mit inline und relative-Positionen erlaubt den Elementen, sich der umgebenden Behälterbreite fließend anzupassen.</li>
191
- <li>Anzeigen und Verbergen von Inhalt mittels JavaScript.</li></ul>
192
  <!-- END tab -->
193
  <!-- BEGIN tab -->
194
  <h3 id="ctc_glossary">Glossar</h3>
195
  <ul>
196
  <li id="parent_theme"><strong>Eltern-Thema</strong> Das Wordpress-Thema, welches Sie bearbeiten möchten. Wordpress lädt zuerst das Kind-Thema, dann das Eltern-Thema. Wenn ein Stil im Kind-Thema enthalten ist, übersteuert es das Eltern-Thema.</li>
197
  <li id="child_theme"><strong>Kind-Thema</strong> Neues Thema, basierend auf einem Eltern-Thema. Sie können eine beliebige Anzahl von Kind-Themen von einem einzigen Eltern-Thema erstellen.</li>
198
- <li id="class"><strong>Klasse</strong> Ein Begriff, der zum Organisieren von Objekten benutzt wird. Zum Beispiel, ein &lt;div&gt; könnte die "blue-text"-Klasse zugewiesen sein. Die Formatvorlage weist dann Mitgliedern der "blue-text"-Klasse den Wert "color: blue;" zu. Somit würde &lt;div&gt; als blauer Text im Browser dargestellt.</li>
199
- <li id="selector"><strong>Selektor</strong> Eines oder mehrere Elemente, Klassen, IDs oder andere Begriffe zum Identifizieren von Objektgruppen.</li>
 
 
200
  <li id="property"><strong>Eigenschaft</strong> Einer von vielen standardisierten Begriffen, die dem Browser mitteilen, wie Objekte mit einem bestimmten Selektor anzuzeigen sind. Beispiele sind <strong>color</strong>, <strong>background-image</strong> und <strong>font-size</strong>.</li>
 
201
  <li id="at-rule"><strong>At-Regel</strong> Ein CSS-Browser-Befehl, um die Standard-Funktionalität zu erweitern. Der Child Theme Configurator unterstützt zwei At-Regeln:
202
  <ul>
203
- <li id="import"><strong>@import</strong> Weist den Browser an, zusätzliche CSS-Informationen aus einer externen Quelle zu laden.</li>
204
- <li id="query"><strong>@media (Media Query)</strong> Identifiziert Stilblöcke, die nur benutzt werden, wenn gewisse Browser-Eigenschaften zutreffen. Beispiele sind max-width, screen und print.</li>
205
  </ul>
206
  </li>
207
- <li id="override"><strong>Übersteuerung</strong> Wenn ein Selektor in Eltern- und Kind-Thema existiert, hat das Kind-Thema Priorität über das Eltern-Thema. Hier zeigt sich die Stärke des Child Theme Configurator: es hilfe Ihnen, <strong>genaue Übersteuerungen</strong> von Selektoren des Eltern-Themas zu erstellen, und eliminiert damit Stunden des Herumprobierens.</li>
 
 
208
  </ul>
209
  <!-- END tab -->
210
  <!-- BEGIN sidebar -->
211
- <h4>Unser Plugin wird Sie nicht mit Spendeneinblendungen nerven...</h4>
212
  <span style="font-size:smaller">...aber wir LIEBEN Empfehlungen.</span><br/><a href="http://wordpress.org/support/view/plugin-reviews/child-theme-configurator?rate=5#postform">Geben Sie uns 5 Sterne</a>
213
- <h4>Vorstellung von CTC Pro</h4>
214
- <a href="<?php echo CHLD_THM_CFG_DOCS_URL; ?>/child-theme-configurator-pro/" title="<?php _e( 'Learn more about CTC Pro', 'chld_thm_cfg' ); ?>"><img src="<?php echo CHLD_THM_CFG_URL . 'css/pro-banner.jpg'; ?>" width="150" height="48" /></a>
215
  <p style="font-size:smaller">Von Wordpress-Entwicklern entworfen, die es jeden Tag benutzen. CTC Pro stellt Plugin-Formatvorlagen und andere Funktionen zur Verfügung, die Ihre Arbeit schneller und einfacher machen. Das ist ein kostenloses Upgrade für Nutzer, die die Plugin-Erweiterung erworben haben. <a href="<?php echo CHLD_THM_CFG_DOCS_URL; ?>/child-theme-configurator-pro/" title="Child Theme Configurator Pro">Mehr erfahren</a></p>
216
  <h4 id="ctc_help_sidebar">Links/Verknüpfungen</h4>
217
  <ul>
3
  // Help Content
4
  ?>
5
  <!-- BEGIN tab -->
6
+ <h3 id="ctc_tutorial">Hier starten: Anleitungs-Videos</h3>
7
+ <!-- p><iframe width="560" height="315" src="https://www.youtube.com/embed/xL0YmieF6d0?rel=0&modestbranding=1" frameborder="0" allowfullscreen></iframe></p>
8
+ <p><iframe width="560" height="315" src="https://www.youtube.com/embed/vhQ5oi20rYE?rel=0&modestbranding=1" frameborder="0" allowfullscreen></iframe></p -->
9
+ <p>Wir betten aus Leistungsgründen keine Anleitungsvideos mehr ein. <a href="http://www.childthemeconfigurator.com/tutorial-videos" target="_blank">Hier klicken, um die Videos anzuschauen.</a></p><!-- END tab -->
10
+ <!-- BEGIN tab -->
11
+ <h3 id="ctc_getting_started">Eltern/Kind-Tab</h3>
12
+ <ol><li><strong>Eine Aktion auswählen:</strong>
13
+ <ul><li><strong>Neues Kind-Thema ERZEUGEN</strong> - Installiere ein neues anpassbares Kind-Thema mit einem installierten Thema als Eltern.</li>
14
+ <li><strong>Bestehendes Kind-Thema ANPASSEN</strong> - Aufsetzen eines vorher installierten Kindthemas für den Konfigurator oder zum Ändern der aktuellen Einstellungen.</li>
15
+ <li><strong>Bestehendes Kind-Thema DUPLIZIEREN</strong> - Eine vollständige Kopie eines Kindthemas in ein neues Verzeichnis erstellen, inkl. Menüs, Widgets und anderer Einstellungen. Die Option zum Kopieren der Eltern-Einstellungen (Schritt 8 unten) ist mit dieser Aktion deaktiviert.</li>
16
+ <li><strong>Bestehendes Kind-Thema ZURÜCKSETZEN</strong> (dies wird all Ihre Arbeit im Konfigurator überschreiben) - Kind-Thema-Formatvorlage und Funktionsdateien auf ihren ursprünglichen Zustand setzen (vor der Initial-Konfiguration oder dem letzten Zurücksetzen).</li></ul></li>
17
+ <li><strong>Eltern-Thema auswählen</strong> falls Sie ein neues Kind-Thema erstellen; ein Kind-Thema auswählen, falls Sie anpassen, duplizieren, oder zurücksetzen möchten.</li>
18
+ <li><strong>Analysiere Kind-Thema</strong> - "Analysieren" klicken, um Formatvorlage-Abhängigkeiten und andere mögliche Probleme zu erkennen.</li>
19
+ <li><strong>Neues Verzeichnis benennen</strong> beim Erstellen eines neuen Kindthemas; ansonsten prüft es, ob das Verzeichnis korrekt ist. - Dies ist NICHT der Name des Kindthemas. Sie können den Namen, die Beschreibung etc. in Schritt 7 unten anpassen.</li>
20
+ <li><strong>Speicherort der neuen Stile auswählen:</strong><ul>
21
+ <li><strong>Primäre Formatvorlage (style.css)</strong> - Sichere neue angepasste Stile direkt in die primäre Formatvorlage des Kindthemas (ersetze vorhandene Werte). Die primäre Formatvorlage wird in der vom Thema definierten Reihenfolge geladen.</li>
22
+ <li><strong>Separate Formatvorlage</strong> - Sichere neue angepasste Stile in separate Formatvorlage und verwende bestehende Kindthemen-Stile als Basis. Diese Option wählen, wenn Sie die Original-Kindthemen-Stile behalten wollen (statt zu überschreiben). Diese Option erlaubt es Ihnen, nach der primären Formatvorlage geladene Formatvorlagen anzupassen.</li></ul></li>
23
+ <li><strong>Elternthema-Formatvorlage Behandlung auswählen:</strong><ul>
24
+ <li><strong>Benutze die WordPress Stil-Warteschlange.</strong> - Den Konfigurator die richtigen Aktionen und Abhängigkeiten auswählen lassen und Funktionendateien automatisch aktualisieren.</li>
25
+ <li><strong>Benutze @import</strong> in der Kind-Thema-Formatvorlage. - Diese Option nur benutzen, wenn die Eltern-Formatvorlage nicht mit der WordPress-Warteschlange geladen werden kann. Die Benutzung von <code>@import</code> ist nicht länger empfohlen.</li>
26
+ <li><strong>Keine zusätzliche Eltern-Formatvorlage-Behandlung hinzufügen.</strong> - Diese Option auswählen, wenn dieses Thema die Elternthema-Formatvorlage schon behandelt oder die Eltern-Thema <code>style.css</code>-Datei für die Darstellung/Anzeige nicht benutzt wird.</li></ul></li>
27
+ <li><strong>Kind-Thema-Name, Beschreibung, Autor, Version etc. anpassen</strong></li>
28
+ <li><strong>Kopieren der Elternthema-Menüs, Widgets und anderer Einstellungen in das Kind-Thema.</strong> - HINWEIS: Dies überschreibt alle im Kind-Thema vorgenommenen Änderungen und Einstellungen.</li>
29
+ <li><strong>Klicken Sie auf die Schaltfläche</strong> um den Konfigurator zu starten.</li>
30
+ <li><strong>WICHTIG: <a target="_blank" href="<?php echo CHLD_THM_CFG_DOCS_URL; ?>/how-to-use/#preview_activate" title="Testen Sie Ihr Kind-Thema vor der Aktivierung!">Testen Sie Ihr Kind-Thema immer mit der Live-Vorschau (Themen-Konfigurator) vor der Aktivierung!</a></strong></li>
 
 
 
 
 
31
  </ol>
32
  <!-- END tab -->
33
  <!-- BEGIN tab -->
34
+ <h3 id="ctc_query_selector">Abfrage/Selektor-Tab</h3>
35
+ <p>Es gibt zwei Wege, Eltern-Stile (Basiswerte) zu identifizieren und zu übersteuern. Der Child Theme Configurator lässt Sie Stile suchen nach <strong>Selektor</strong> oder nach <strong>Eigenschaft</strong>. Wenn Sie einen bestimmten Selektor ändern wollen (z.Bsp. h1), benutzen Sie den "Abfrage/Selektor"-Tab. Wenn Sie einen Wert Webseiten-weit ändern wollen (z.Bsp. die Farbe des Typs), benutzen Sie den "Eigenschaften/Wert"-Tab.</p>
36
+ <p>Der Abfrage/Selektor-Tab lässt Sie bestimmte Selektoren finden und bearbeiten. Zuerst finden Sie die Abfrage, die den gesuchten Selektor enthält, indem Sie in die <strong>Abfrage</strong> Autoauswahl-Box schreiben. Wählen Sie durch Mausklick oder "Eingabe"- bzw. "Tabulator"-Tasten. Selektoren sind in der <strong>Basis</strong> Abfrage standardmäßig.</p>
 
 
 
37
  <p>Dann finden Sie den mit der Eingabe in der <strong>Selektor</strong> Autoauswahl-Box. Wählen Sie aus mit Mausklick oder der "Eingabe"- bzw. den "Tabulator"-Tasten.</p>
38
  <p>Dies lädt alle Eigenschaften für diesen Selektor mit den Eltern-Werten auf der linken und den Kind-Werten auf der rechten Seite. Alle bestehenden Kind-Werte werden automatisch abgefüllt. Es gibt auch eine Musteransicht, welches die Kombination der Eltern- und Kindwerte Übersteuerungen anzeigt. Beachten Sie, dass der <strong>Rahmen</strong> und <strong>Hintergrundbild</strong> speziell behandelt werden.</p>
39
+ <p>Wenn Sie zusätzliche Eigenschaften zu einem bestehenden Selektor hinzufügen wollen, laden Sie zuerst den Selektor mit dem Abfrage/Selektor-Tab. Dann finden Sie die zu übersteuernde Eigenschaft mit der Eingabe in die <strong>Neue Eigenschaft</strong>-Auswahlbox. Wählen Sie mit einem Mausklick oder der Eingabe der ENTER- oder TAB-Taste. Dies wird der Auswahl eine neue Eingabezeile hinzufügen.</p>
40
+ <p>Das "Reihenfolge"-Feld enthält die Original-Reihenfolge des Selektors der Eltern-Formatvorlage. Sie können die Selektor-Reihenfolge ändern, indem Sie eine tiefere/höhere Zahl im Reihenfolge-Feld eingeben. Sie können auch Stil-Übersteuerungen forcieren (sogenannter !important-Schalter), indem Sie das "!" Kästchen neben der Eingabe anwählen. Benutzen Sie es nicht zu oft.</p>
41
  <p>Klicken Sie auf "Sichern" um die Kind-Formatvorlage zu aktualisieren und die Änderungen im Wordpress-Admin zu speichern.</p>
42
  <!-- END tab -->
43
  <!-- BEGIN tab -->
44
+ <h3 id="ctc_new_styles">Rohes CSS hinzufügen</h3>
45
+ <p>Wenn Sie komplett neue Selektoren oder sogar @media-Queries hinzufügen wollen, können Sie formloses CSS im Textfeld "Rohes CSS" eingeben. Achten Sie auf eine korrekte Syntax (bspw. passende geschweifte Klammern etc.), damit der Parser die neuen Stile laden kann. Sie erkennen Fehler an einem roten "X", welches neben der Sichern-Schaltfläche erscheint.</p>
46
+ <p>Wenn Sie die Shorthand-Syntax für Eigenschaften und Werte bevorzugen (anstatt der Vorgaben durch den Kind-Thema-Konfigurator), können Sie diese hier auch eingeben. Der Parser wir diese Eingaben automatisch in normalisierten CSS-Code konvertieren.</p>
47
+ <p>Wenn Sie zusätzliche Eigenschaften zu einem bestehenden Selektor hinzufügen möchten, laden Sie zuerst den Selektor mit dem Abfrage/Selektor-Tab. Dann suchen Sie die Eigenschaft zum Übersteuern, indem Sie in die <strong>Neue Eigenschaft</strong>-Box schreiben. Wählen Sie mit einem Mausklick oder der Eingabe der ENTER- oder TAB-Taste. Dies wird der Auswahl eine neue Eingabezeile hinzufügen.</p>
48
  <!-- END tab -->
49
  <!-- BEGIN tab -->
50
+ <h3 id="ctc_property_value">Eigenschaften/Wert-Tab</h3>
51
+ <p>Es gibt zwei Wege, Eltern-Stile (Basiswerte) zu identifizieren und zu übersteuern. Der Child Theme Configurator lässt Sie Stile suchen nach <strong>Selektor</strong> oder nach <strong>Eigenschaft</strong>. Wenn Sie einen bestimmten Selektor ändern wollen (z.Bsp. h1), benutzen Sie den "Abfrage/Selektor"-Tab. Wenn Sie einen Wert Webseiten-weit ändern wollen (z.Bsp. die Farbe des Typs), benutzen Sie den "Eigenschaften/Wert"-Tab.</p>
52
+ <p>Der Eigenschaften/Wert-Tab lässt Sie bestimmte Werte für eine gewisse Eigenschaft finden und ermöglicht dann das Bearbeiten für individuelle Selektoren, welche diese Eigenschaft-/Wert-Kombination benutzen. Zuerst finden Sie die Eigenschaft, die Sie übersteuern möchten, indem Sie diese in der <strong>Eigenschaft</strong> Autoauswahl-Box eingeben. Wählen Sie durch Mausklick oder "Eingabe"- bzw. "Tabulator"-Tasten.</p>
53
  <p>Dies lädt alle einzigartigen Werte dieser Eigenschaft in der Eltern-Formatvorlage mit einer Mustervorschau für diese Werte. Wenn Werte in der Kind-Formatvorlage existieren, die nicht in der Eltern-Formatvorlage enthalten sind, werden diese ebenfalls angezeigt.</p>
54
  <p>Für jeden einzigartigen Wert, klicken Sie auf die "Selektoren"-Verknüpfung, um eine Liste der Selektoren mit dieser Eigenschaften-/Wert-Kombination anzuzeigen, nach Abfrage gruppiert mit einer Muster-Vorschau der Werte und Eingaben für die Kind-Werte. Alle bestehenden Kind-Werte werden automatisch abgefüllt.</p>
55
  <p>Klicken Sie auf "Sichern" um die Kind-Formatvorlage zu aktualisieren und die Änderungen im Wordpress-Admin zu speichern.</p>
56
  <!-- END tab -->
57
  <!-- BEGIN tab -->
58
+ <h3 id="ctc_imports">Webschriftarten-Tab</h3>
59
+ <p>Sie können zusätzliche Formatvorlagen und Webschriftarten verknüpfen, indem Sie @import Regeln in das Textfeld auf dem Webschriftarten-Tab eingeben.</p>
60
  <p><strong>Hinweis:</strong> Child Theme Configurator schreibt nicht mehr länger @import Regeln in die Formatvorlage. Stattdessen benutzt es das @import Schlüsselwort und stellt sie in die Warteschlange. WordPress wandelt sie dann um in &lt;link&gt; Tags im verarbeiteten HTML.</p>
61
+ <p>Wichtig: importieren Sie die Eltern-Formatvorlage nicht hier. Benutzen Sie die "Eltern-Formatvorlage-Behandlung"-Option auf dem Eltern/Kind-Tab.</p>
62
+ <p>Wenn Sie eine Formatvorlage unter "Zusätzliche Formatvorlegen einlesen" gewählt haben, als Sie das Kind-Thema erstellt haben, werden diese Stile für Übersteuerungen in der Kind-Formatvorlage zur Verfügung stehen.</p>
63
  <p>WordPress lädt automatisch zusätzliche Formatvorlagen, wenn es das Eltern-Thema lädt, also müssen Sie @import rules dafür hier nicht hinzufügen.</p>
64
+ <p>Unten ist ein Beispiel, welche eine lokale angepasste Formatvorlage lädt (Sie müssen das "fonts"-Verzeichnis und die Formatvorlage hinzufügen), sowie die Schriftart "Open Sans" von Google Web Fonts:</p>
65
+ <blockquote><pre><code>&#64;import url(fonts/Formatvorlage.css);
66
  &#64;import url(http://fonts.googleapis.com/css?family=Open+Sans:400,400italic,700,700italic);</code></pre></blockquote>
67
  <!-- END tab -->
68
  <!-- BEGIN tab -->
69
+ <h3 id="ctc_files">Dateien-Tab</h3>
70
  <h5>Eltern-Vorlagen</h5>
71
  <p>Kopieren von PHP-Vorlagendateien des Eltern-Themes, indem Sie die Kästchen auswählen und "Auswahl zu gewählten Kind-Themen kopieren", und die Vorlage wird zum Kind-Themenverzeichnis hinzugefügt.</p>
72
  <p><strong>ACHTUNG: Wenn Ihr Kind-Thema aktiv ist, wird nach dem Kopiervorgang sofort die Kind-Thema-Version der Datei anstatt der Eltern-Datei benutzt.</strong></p>
78
  <p>Diese Bilder befinden sich unter dem <code>Images</code>-Verzeichnis in Ihrem Kind-Thema-Verzeichnis und sind nur für Formatvorlagen vorgesehen. Benutzen Sie die Medienbibliothek für Inhaltsbilder.</p>
79
  <p>Sie können neue Bilder mittels des "Bild hochladen"-Formulars hochladen. Löschen Sie Bilder durch die Auswahl der Kästchen und dem Klicken auf "Auswahl löschen".</p>
80
  <h5>Kind-Thema Screenshot</h5>
81
+ <p>Sie können hier einen speziellen/angepassten Screenshot für das Kind-Thema hochladen.</p>
82
  <p>Der Themen-Screenshot sollte ein 4:3-Verhältnis aufweisen (z.Bsp, 880px x 660px) JPG, PNG oder GIF. Es wird in <code>screenshot</code> umbenannt.</p>
83
  <h5>Kind-Thema als ZIP-Archiv exportieren </h5>
84
  <p>Sie können Ihr Kind-Thema für den Gebrauch auf einer anderen Wordpress-Webseite herunterladen, indem Sie auf "Export" klicken.</p>
87
  <h3 id="ctc_preview">Vorschau und Aktivierung</h3>
88
  <p><strong>WICHTIG: <a target="_blank" href="<?php echo CHLD_THM_CFG_DOCS_URL; ?>/how-to-use/#preview_activate" title="Testen Sie Ihr Kind-Thema vor der Aktivierung!">Testen Sie Ihr Kind-Thema vor der Aktivierung!</a></strong> Einige Themen (hauptsächlich kommerzielle Themen) laden Eltern-Formatvorlagen nicht korrekt oder laden Kind-Formatvorlagen automatisch oder PHP-Dateien. <strong>Im schlimmsten Fall wird bei Aktivierung Ihre Webseite unbrauchbar.</strong></p>
89
  <ol>
90
+ <li>Navigieren Sie zu Design > Themen im Wordpress-Admin. Sie werden nun die neuen Kind-Themen als eine der installierten Themen sehen.</li>
91
  <li>Klicken Sie auf "Live-Vorschau" unterhalb des Kind-Themas, um es in Aktion zu sehen.</li>
92
+ <li>Wenn Sie das Kind-Thema nun live schalten wollen, klicken Sie auf "Aktivieren."</li>
93
  </ol>
94
  <p><strong>MULTISITE NUTZER:</strong> Sie müssen Ihr Thema Netzwerk-aktivieren, um es in der Live-Vorschau zu sehen. Gehen Sie zu 'Themen' in der Netzwerk-Administration.</p>
95
  <!-- END tab -->
96
  <!-- BEGIN tab -->
97
  <h3 id="ctc_permissions">Dateiberechtigungen</h3>
98
  <p>Wordpress wurde für verschiedene Serverkonfigurationen entwickelt. Child Theme Configurator benutzt die WordPress Filesystem API, um Webseiten das Bearbeiten von Dateien zu ermöglichen, die Nutzerberechtigungen benötigen.</p>
99
+ <p>Allerdings, weil die meiste Funktionalität mittels AJAX(Hintergrund)-Anfragen passiert, muss die Kind-Formatvorlage auf dem Server beschreibbar sein.</p>
100
  <p>Das Plugin erkennt automatisch Ihre Konfiguration und liefert eine Anzahl von Optionen, um diese Anforderung zu lösen. Benutzen Sie die zur Verfügung gestellten Verknüpfungen, um mehr zu erfahren, beispielsweise:</p>
101
  <ol>
102
  <li>Die Formatvorlage mithilfe des Plugins vorübergehend schreibbar machen.</li>
107
  <!-- END tab -->
108
  <!-- BEGIN tab -->
109
  <h3 id="ctc_faq">FAQs</h3>
110
+ <<h5 id="broken_theme">HILFE! Ich habe eine Datei geändert und kann nun über nicht mehr über wp-admin einloggen, um es zu reparieren!</h5>
111
  <p>Um aus einem defekten Thema herauszukommen, müssen Sie das problematische Themen-Verzeichnis umbenennen (via FTP, SSH oder Ihrem Webhoster-Kontrollpanel bzw. Dateimanager), so dass Wordpress es nicht mehr finden kann. WordPress wird dann einen Fehler generieren und zum Standard-Thema zurückkehren (aktuell Twenty-Fourteen).</p>
112
 
113
  <p>Das Kind-Thema ist normalerweise in Ihrem Themen-Verzeichnis</p>
123
  <h5 id="options_broken">Wieso verschwinden meine Themen-Optionen, wenn ich das Kind-Thema aktiviere?</h5>
124
  <p>Diese Optionen sind für jedes Thema spezifisch und werden getrennt in der Datenbank gespeichert. Beim Erstellen eines neuen Kind-Themas sind diese Optionen leer.</p>
125
 
126
+ <p><strong>Viele dieser Optionen können in das Kind-Thema kopiert werden, indem man das Kästchen "Kopieren Eltern-Theme-Menüs, Widgets und andere Design-Optionen" anklickt, wenn Sie die Kind-Thema-Dateien auf dem Eltern/Kind-Tab erstellen.</strong></p>
127
 
128
  <p>Wenn Sie andere Optionen setzen wollen, können Sie diese nach dem Aktivieren des Kind-Themas aktivieren, oder mittels der Live-Vorschau unter Design > Themen.</p>
129
  <ul class="instructions">
130
+ <li><strong>Menüs: </strong> Gehen Sie zu Design > Menüs und klicken Sie den "Position"-Tab. Standardmäßig wird das Primärmenü die Verknüpfungen automatisch aus den bestehenden Seiten erstellen. Wählen Sie Ihr angepasstes Menü aus der Auswahlliste und klicken Sie "Neues Menü benutzen". Dies ersetzt das Standardmenü und Sie sehen die korrekten Verknüpfungen.</li>
131
 
132
+ <li><strong>Header (Kopf): </strong> Gehen Sie zu Design > Header. Einige Themen zeigen standardmäßig den Titel und die Tagline Ihrer "Allgemeinen Einstellungen". Wählen Sie "Bild auswählen" und finden Sie einen "Kopf" aus der Medienbibliothek oder mittels Hochladen. Dies ersetzt den Standard mit dem angepassten Bild.</li>
133
 
134
+ <li><strong>Hintergrund: </strong> Gehen Sie zu Design > Hintergrund und wählen Sie ein neues Hintergrundbild oder eine Farbe.</li>
135
 
136
+ <li><strong>Optionen: </strong> Jedes Thema behandelt Optionen speziell/anders. Meistens erstellen Sie einen Satz Optionen und speichern ihn in der Wordpress-Datenbank. Einige Optionen sind spezifisch für das aktive Thema (oder Kind-Thema), und einige nur für das Eltern-Thema bestimmt (d.h. das Kind-Thema kann sie NICHT übersteuern). Sie müssen sich beim Themen-Autor erkundigen, welche auf welche Art funktionieren.</li>
137
  </ul>
138
  </p>
139
  <h5 id="existing_parent">Wie verschiebe ich bereits gemachte Änderungen an meinem Thema in mein Kind-Thema?</h5>
140
  <p><a href="<?php echo CHLD_THM_CFG_DOCS_URL; ?>/how-to-use/#child_from_modified_parent" class="scroll-to">Folgen Sie diesen Schritten</a>. </p>
141
  <h5 id="web_fonts">Wie füge ich Webschriftarten hinzu?</h5>
142
+ <p>Die einfachste Methode ist das Einfügen des @import code, geliefert von <a href="http://www.google.com/fonts" title="Google Fonts">Google</a>, <a href="http://www.fontsquirrel.com/" title="Font Squirrel">Font Squirrel</a> oder jeder anderen Schriftartenseite auf dem Schriftarten-Tab. Die Schriftarten werden dann zum Gebrauch als Wert der <strong>font-family</strong> Eigenschaft zur Verfügung stehen. Stellen Sie sicher, dass Sie die Lizenz zum Gebrauch der Webschriftarten verstehen. </p>
143
+ <p>Sie können auch eine sekundäre Formatvorlage erstellen, welche die @font-face Regeln enthält, und diese auf dem Webschriftarten-Tab importieren. </p>
144
  <h5 id="plugin">Funktionert das mit Plugins?</h5>
145
  <p>Wir bieten eine Premium-Erweiterung an, die Sie Stile für jedes auf der Webseite installierte Plugin einfach verändern lässt. Der Child Theme Configurator Plugin Extension scannt Ihre Plugins und erlaubt die Erstellung von angepassten Formatvorlagen in Ihrem Kind-Thema. <a href="<?php echo CHLD_THM_CFG_DOCS_URL; ?>/child-theme-configurator-pro/" title="Die Kontrolle über Ihre Plugin-Stile mit der Child Theme Configurator Plugin Erweiterung für WordPress übernehmen">Mehr erfahren <i class="genericon genericon-next"></i></a>
146
  <h5 id="doesnt_work">Wieso funktioniert das in meinem (Hersteller des Themas hier einfügen) Thema nicht?</h5>
147
  <p>Einige Themen (hauptsächlich kommerzielle Themen) laden die Eltern-Vorlagen-Dateien nicht korrekt oder laden Kind-Thema-Formatvorlagen oder PHP-Dateien automatisch.</p><p>Das ist unglücklich, weil es im besten Fall den Webmaster daran hindert, Anpassungen vorzunehmen (abgesehen von solchen durch die Themen-Optionen), die einen Upgrade überleben. <strong>Im schlimmsten Fall jedoch wird Ihre Webseite unbrauchbar, wenn Sie das Kind-Thema aktivieren.</strong> </p>
148
  <p>Kontaktieren Sie direkt den Hersteller, um diese Kern-Funktionalität zu verlangen. Unserer Meinung nach sollten ALLE Themen (vor allem kommerzielle) die von Wordpress.org beschriebenen Themen-Tests erfüllen. </p>
149
  <h5 id="missing_parent">Wieso hat das Eltern-Thema keine Stile, wenn ich auf "Eltern-CSS anzeigen" gehe?</h5>
150
+ <p>Ihr Eltern-Thema benutzt für die Formatvorlagen womöglich einen getrennten Ort. Wählen Sie individuelle Formatvorlagen aus dem "Zusätzliche Formatvorlagen auslesen"-Abschnitt des Eltern/Kind-Tabs und klicken Sie erneut auf "Neuaufbau Kind-Thema-Dateien". </p>
151
  <h5 id="performance">Wird das meine Webseite verlangsamen?</h5>
152
  Sobald die Kind-Formatvorlage erstellt ist, fügt CTC im Frontend nur ein wenig Zusatzlast hinzu, da die ganze Funktionalität im Admin enthalten ist.
153
 
154
+ Das Plugin lädt den Hauptteil des Codes im Admin nur, wenn Sie das Tool benutzen. Die größte Performance-Einbuße geschieht, wenn Sie die Kind-Themen-Dateien auf dem Eltern/Kind-Tab erstellen. </p>
155
  <h5 id="where_are_styles">Wo sind die Stile? Der Konfigurator zeigt nichts an!</h5>
156
  <p>Alle Stile werden dynamisch geladen. Sie müssen in den Textfelder etwas eingeben, um die Stile zum Bearbeiten auszuwählen.</p>
157
  <p>"Base" ist die Abfragegruppe, die mit keiner bestimmten at-Regel verbunden sind.</p>
158
+ <p>Beginnen Sie mit einem Klick auf den "Abfage/Selektor"-Tab und der Eingabe von "base" in der ersten Box. In der zweiten Box können Sie dann mit der Eingabe beginnen, um die Stil-Selektoren zum Bearbeiten zu holen. </p>
159
+ <h5 id="preview-not-loading">Wieso zeigen die Vorschau-Tab "Formatvorlage kann nicht angezeigt werden"?</h5>
160
+ <p>Sie müssen ein Kind-Thema auf dem Eltern/Kind-Tab für die Ansicht der Vorschau laden. Das kann auch passieren, wenn Ihre WP_CONTENT_URL sich von $bloginfo('site_url') unterscheidet. Ajax kann keine domänenübergreifenden Abfagen machen. Überprüfen Sie, ob der Einstellungen > Allgemein > "WordPress Adresse (URL)"-Wert korrekt ist. (Oft fehlt das "www"" in der Domäne.) </p>
161
  <h5 id="edit_manually">Kann ich das Kind-Thema manuell offline bearbeiten (oder mithilfe des Editors), oder muss ich unbedingt den Konfigurator benutzen?</h5>
162
  <p>Sie können jede gewünschte Änderung an der Formatvorlage vornehmen. Stellen Sie nur sicher, die geänderte Formatvorlage mittels des Eltern/Kind-Panels zu importieren, ansonsten wird der Konfigurator Ihre Änderungen beim nächsten Gebrauch überschreiben. Folgen Sie den üblichen Schritten, aber wählen Sie die Auswahloption "Bestehendes Kind-Thema benutzen" als Kind-Thema-Option. Der Konfigurator wird die internen Daten aus der neuen Formatvorlage automatisch aktualisieren. </p>
163
  <h5 id="update_child">Wenn das Eltern-Thema geändert wird (z.Bsp. Upgrade), muss ich das Kind-Thema aktualisieren?</h5>
164
  <p>Nein. Das ist der Zweck von Kind-Themen. Änderungen am Eltern-Thema werden vom Kind-Thema automatisch geerbt.</p>
165
  <p>Ein Kind-Thema ist keine Kopie eines Eltern-Themas. Es ist eine besondere Funktion von WordPress, die Sie bestimmte Stile und Funktionen übersteuern lässt, während der Rest intakt bleibt. Das einzige Mal, dass Sie nach einem Upgrade Änderungen machen müssen ist, wenn das Eltern-Thema Stile oder Funktionsnamen ändert oder entfernt. Qualitäts-Themen sollten alle veralteten Funktionen oder Stile in den Upgrade-Hinweisen erwähnen, so dass Nutzer von Kind-Themen die entsprechenden Anpassungen vornehmen können. </p>
166
  <h5 id="functions">Wo sind die .PHP-Dateien?</h5>
167
+ <p>Der Konfigurator fügt dem Kind-Themenverzeichnis automatisch eine leere functions.php-Datei hinzu. Sie können Dateien des Eltern-Themas mittels des "Dateien"-Tabs kopieren. Wenn Sie neue Vorlagen und Verzeichnisse erstellen möchten, müssen Sie diese manuell via FTP oder SSH hochladen. Beachten Sie, dass ein Kind-Thema die Eltern-Vorlagen automatisch erbt, es sei denn, sie bestehen bereits im Kind-Thema-Verzeichnis. Kopieren Sie nur Vorlagen, die Sie auch wirklich anpassen möchten.</p>
168
  <h5 id="specific_color">Wie ändere ich eine(n) bestimmte Farbe/Schriftarttyp/Hintergrund?</h5>
169
+ <p>Sie können einen bestimmten Wert global mittels des Eigenschaften/Wert-Tabs übersteuern. Siehe Eigenschaften/Werte, oben.</p>
170
  <h5 id="add_styles">Wie füge ich Stile hinzu, die nicht im Eltern-Thema enthalten sind?</h5>
171
+ <p>Sie können Abfragen und Selektoren mittels des "Rohes CSS"-Textfelds auf dem Abfrage/Selektor-Tab hinzufügen. Siehe Abfrage/Selektor, oben. </p>
172
  <h5 id="add_styles">Wie entferne ich Stile aus dem Eltern-Thema?</h5>
173
  <p>Sie sollten eigentlich Stile aus dem Eltern-Thema nicht entfernen. Sie können allerdings die Eigenschaft auf "Erben"," "Keine," oder Null setzen (abhängig von der Eigenschaft). Das wird den Eltern-Wert negieren. Ein wenig Probieren wird nötig sein.</p>
174
  <h5 id="remove_styles">Wie entferne ich einen Stil aus einem Kind-Thema?</h5>
175
  <p>Löschen Sie den Wert aus der Eingabe der Eigenschaft, die sie entfernen möchten. Der Child Theme Configurator fügt Übersteuerungen nur für Eigenschaften mit Werten hinzu. </p>
176
  <h5 id="important_flag">Wie setze ich den !important-Schalter?</h5>
177
  <p>Wir empfehlen immer ein gutes, verschachteltes Design, anstatt auf globale Übersteuerungen zu vertrauen. Dazu haben Sie die Möglichkeit, die Lade-Reihenfolge von Kind-Formatvorlagen zu ändern, indem Sie einen Wert im "Reihenfolge"-Feld eingeben. Sie können Eigenschaften als wichtig setzen, indem Sie das Kästchen mit dem "!" neben jeder Eingabe setzen. Benutzen Sie es massvoll. </p>
178
+ <h5 id="gradients">Wie erstelle ich browser-unabhängige Farbverläufe?</h5>
179
  <p>Der Child Theme Configurator benutzt eine standarisierte Syntax für Farbverläufe und unterstützt nur zweifarbige Verläufe ohne Zwischenstopps. Die Eingaben bestehen aus dem Startpunkt (z.Bsp. top, left, 135deg, etc.), der Startfarbe und der Endfarbe. Browser-spezifische Syntax wird automatisch erstellt, wenn Sie diese Werte speichern. Siehe Tricks/Fallen, unten, für weitere Informationen. </p>
180
  <h5 id="responsive">Wie mache ich das Thema responsive?</h5>
181
  <p>Die kurze Antwort ist, ein responsives Eltern-Thema zu benutzen. Einige übliche Methoden für responsives Design sind:
182
  <ul class="instructions"><li>Vermeiden von festen Breiten und Höhen. Der Gebrauch von max- and min-height Werten und Prozenten sind Wege, das Design dem Browser des Benutzers anzupassen.</li>
183
  <li>Die Kombination von floats und clears mit inline und relative-Positionen erlaubt den Elementen, sich der umgebenden Behälterbreite fließend anzupassen.</li>
184
+ <li>Anzeigen und Verbergen von Inhalt mittels JavaScript.</li></ul>
185
  <!-- END tab -->
186
  <!-- BEGIN tab -->
187
  <h3 id="ctc_glossary">Glossar</h3>
188
  <ul>
189
  <li id="parent_theme"><strong>Eltern-Thema</strong> Das Wordpress-Thema, welches Sie bearbeiten möchten. Wordpress lädt zuerst das Kind-Thema, dann das Eltern-Thema. Wenn ein Stil im Kind-Thema enthalten ist, übersteuert es das Eltern-Thema.</li>
190
  <li id="child_theme"><strong>Kind-Thema</strong> Neues Thema, basierend auf einem Eltern-Thema. Sie können eine beliebige Anzahl von Kind-Themen von einem einzigen Eltern-Thema erstellen.</li>
191
+ <li id="class"><strong>Klasse</strong> Ein Begriff, der zum Organisieren von Objekten benutzt wird. Zum Beispiel, ein &lt;div&gt; könnte die "blue-text"-Klasse zugewiesen sein. Die Formatvorlage weist dann Mitgliedern der "blue-text"-Klasse den Wert "color: blue;" zu. Somit würde &lt;div&gt; als blauer Text im Browser dargestellt. Klassen-Selektoren beginnen mit einem Punkt.</li>
192
+ <li id="class"><strong>ID</strong> Eine einzigartige Zeichenkette, die ein bestimmtes Element bezeichnet. ID-Selektoren beginnen mit einem Hashtag (#).</li>
193
+ <li id="selector"><strong>Abfrage</strong> @media-Query-Anweisungen (siehe At-Regel unten).</li>
194
+ <li id="query"><strong>Selektor</strong> Kombination eines oder mehrere Elemente, Klassen, IDs oder andere Begriffe zum Identifizieren von Objektgruppen.</li>
195
  <li id="property"><strong>Eigenschaft</strong> Einer von vielen standardisierten Begriffen, die dem Browser mitteilen, wie Objekte mit einem bestimmten Selektor anzuzeigen sind. Beispiele sind <strong>color</strong>, <strong>background-image</strong> und <strong>font-size</strong>.</li>
196
+ <li id="value"><strong>Wert</strong> Daten, die mit einer Eigenschaft korrespondieren.</li>
197
  <li id="at-rule"><strong>At-Regel</strong> Ein CSS-Browser-Befehl, um die Standard-Funktionalität zu erweitern. Der Child Theme Configurator unterstützt zwei At-Regeln:
198
  <ul>
199
+ <li id="at_import"><strong>@import</strong> Weist den Browser an, zusätzliche CSS-Informationen aus einer externen Quelle zu laden.</li>
200
+ <li id="at_media"><strong>@media (Media Query)</strong> Identifiziert Stilblöcke, die nur benutzt werden, wenn gewisse Browser-Eigenschaften zutreffen. Beispiele sind max-width, screen und print.</li>
201
  </ul>
202
  </li>
203
+ <li id="child_theme"><strong>Basis-Stil</strong> Ein Stil einer beliebigen Kind- oder Eltern-Vorlage, der durch die Formatvorlage des Kind-Themas übersteuert werden kann. Meistens stammen diese aus der Formatvorlage des Eltern-Themas.</li>
204
+ <li id="override"><strong>Übersteuerung</strong> Wenn ein Selektor in Kind- und Eltern-Thema besteht, bekommt derjenige aus dem Kind-Thema Priorität. Das ist eines der besonderen Merkmale des Kind-Thema-Konfigurators: es hilft dabei, <strong>exakte Übersteuerungen</strong> von Selektoren des Eltern-Themas zu erstellen, und eliminiert viele Stunden des mühsamen Versuchens.</li>
205
+ <li id="child_theme"><strong>Themenvorlage</strong> Eine PHP-Datei eines Themas ohne Funktionen und Klassen. Andere PHP-Dateien können nicht ohne Weiteres sicher überschrieben werden.</li>
206
  </ul>
207
  <!-- END tab -->
208
  <!-- BEGIN sidebar -->
209
+ <h4>Unsere Plugins werden Sie nicht mit Spendeneinblendungen nerven...</h4>
210
  <span style="font-size:smaller">...aber wir LIEBEN Empfehlungen.</span><br/><a href="http://wordpress.org/support/view/plugin-reviews/child-theme-configurator?rate=5#postform">Geben Sie uns 5 Sterne</a>
211
+ <h4>Wir stellen CTC Pro vor</h4>
212
+ <a href="<?php echo CHLD_THM_CFG_DOCS_URL; ?>/child-theme-configurator-pro/" title="Erfahren Sie mehr über CTC Pro"><img src="<?php echo CHLD_THM_CFG_URL . 'css/pro-banner.jpg'; ?>" width="150" height="48" /></a>
213
  <p style="font-size:smaller">Von Wordpress-Entwicklern entworfen, die es jeden Tag benutzen. CTC Pro stellt Plugin-Formatvorlagen und andere Funktionen zur Verfügung, die Ihre Arbeit schneller und einfacher machen. Das ist ein kostenloses Upgrade für Nutzer, die die Plugin-Erweiterung erworben haben. <a href="<?php echo CHLD_THM_CFG_DOCS_URL; ?>/child-theme-configurator-pro/" title="Child Theme Configurator Pro">Mehr erfahren</a></p>
214
  <h4 id="ctc_help_sidebar">Links/Verknüpfungen</h4>
215
  <ul>
includes/help/en_US.php CHANGED
@@ -3,62 +3,55 @@ if ( !defined( 'ABSPATH' ) ) exit;
3
  // Help Content
4
  ?>
5
  <!-- BEGIN tab -->
6
- <h3 id="ctc_getting_started">Start Here</h3>
7
- <p><strong style="font-size:large">10 Easy Steps to Create a Child Theme:</strong></p>
8
- <ol>
9
- <li><strong>Select the theme</strong> you want to configure from the &quot;Parent Theme&quot; menu.</li>
10
- <li><strong>Select &quot;new&quot; or &quot;existing&quot;.</strong>
11
- <ul>
12
- <li>If there are currently no child themes available, the &quot;Child Theme&quot; and &quot;Child Theme Names&quot; will be entered for you automatically based on the parent theme selected. You may edit these if you like, but they cannot be the same as an existing theme.</li>
13
- <li>If there are existing child themes available, there will be an additional menu labeled &quot;Use Existing Child Theme&quot; from which you can select, or enter a new value in the input box to create a new one.</li>
14
- </ul>
15
- </li>
16
- <li><strong>Optional: Enter a Theme Name, Theme Website, Author, Author Website, Descriptiont, Tags and Version</strong> for the child theme. If using an existing child theme, they will be entered automatically based on the child theme selected.</li>
17
- <li><strong>Choose how WordPress should handle the parent theme stylesheet:</strong>
18
- <ul>
19
- <li><strong>None (handled by theme)</strong>
20
- Select this option if all stylesheets are correctly enqueued for child themes. If you find that styles are not being applied correctly, use a different option.</li>
21
- <li><strong>Enqueue parent stylesheet (default)</strong>
22
- Select this option if the theme enqueues the active stylesheet but has no special handling for child themes. Start with this option if unsure.</li>
23
- <li><strong>Enqueue child stylesheet</strong>
24
- Select this option if the theme enqueues the parent stylesheet but does not enqueue the child stylesheet at all. This can happen if <code>get_template()</code> or <code>get_template_directory_uri()</code> is used to link the stylesheet.</li>
25
- <li><strong>Enqueue both parent and child stylesheets</strong>
26
- Select this option if stylesheet link tags are hard-coded into the header template (common in older themes). This enables the child stylesheet to override the parent stylesheet without using <code>@import.</code></li>
27
- <li><strong><code>@import</code> parent stylesheet</strong>
28
- This option imports the parent stylesheet from the child stylesheet. This enables the child stylesheet to override the parent stylesheet, but using <code>@import</code> is no longer recommended.</li>
29
- </ul></li>
30
- <li><strong>Use Parent Options (optional)</strong> If you want to maintain the same theme options as the parent theme, check "Copy Parent Theme Menus, Widgets and other Options". Depending on the theme, some options may need to be applied using separate theme option controls. <strong>NOTE: This will overwrite any child theme options you may have already set.</strong></li>
31
- <li><strong>Save Backup (optional)</strong> If using an existing child theme, you can check "Backup Stylesheet", to create a backup of the child theme stylesheet in the child theme directory.</li>
32
- <li><strong>Restore from backup (optional - new in version 1.6.0):</strong> If using an existing child theme, you can choose whether to reload the current child theme stylesheet (leave unchanged), reset all values, or restore it from a backup. If there are backup files available, they will appear as radio button options.</li>
33
- <li><strong>Choose additional stylesheets</strong> If your theme uses additional stylesheets, you can open the &quot;Parse Additional Stylesheets&quot; toggle and they will appear as checkbox options. Stylesheets that are being used by the parent theme should be automatically selected for you. Only select additional stylesheets you wish to customize to reduce overhead. <strong>NOTE: If the parent theme uses Bootstrap stylesheets, they will not be automatically selected.</strong> You can select Bootstrap stylesheets manually if you need to customize them, but in most cases they add unecessary overhead to the configuration data.</li>
34
- <li><strong>Click "Generate/Rebuild Child Theme Files."</strong></li>
35
- <li><strong>IMPORTANT: <a target="_blank" href="<?php echo CHLD_THM_CFG_DOCS_URL; ?>/how-to-use/#preview_activate" title="Test your child theme before activating!">Always test your child theme with Live Preview before activating!</a></strong></li>
36
  </ol>
37
  <!-- END tab -->
38
  <!-- BEGIN tab -->
39
- <h3 id="ctc_tutorial">Tutorial Videos</h3>
40
- <p>We are no longer embedding videos for performance reasons. <a href="http://www.childthemeconfigurator.com/tutorial-videos" target="_blank">Click here to view videos.</a></p><!-- END tab -->
41
- <!-- BEGIN tab -->
42
  <h3 id="ctc_query_selector">Query/Selector Tab</h3>
43
- <p>There are two ways to identify and override parent styles. The Child Theme Configurator lets you search styles by <strong>selector</strong> and by <strong>property</strong>. If you wish to change a specific selector (e.g., h1), use the "Query/Selector" tab. If you have a specific value you wish to change site-wide (e.g., the color of the type), use the "Property/Value" tab.</p>
44
  <p>The Query/Selector tab lets you find specific selectors and edit them. First, find the query that contains the selector you wish to edit by typing in the <strong>Query</strong> autoselect box. Select by clicking with the mouse or by pressing the "Enter" or "Tab" keys. Selectors are in the <strong>base</strong> query by default.</p>
45
  <p>Next, find the selector by typing in the <strong>Selector</strong> autoselect box. Select by clicking with the mouse or by pressing the "Enter" or "Tab" keys.</p>
46
- <p>This will load all of the properties for that selector with the Parent values on the left and the Child values inputs on the right. Any existing child values will be automatically populated. There is also a Sample preview that displays the combination of Parent and Child overrides. Note that the <strong>border</strong> and <strong>background-image</strong> get special treatment.</p>
 
47
  <p>The "Order" field contains the original sequence of the selector in the parent theme stylesheet. You can change the selector order sequence by entering a lower or higher number in the "Order" field. You can also force style overrides (so called "!important" flag) by checking the "!" box next to each input. Please use judiciously.</p>
48
  <p>Click "Save" to update the child stylesheet and save your changes to the WordPress admin.</p>
49
  <!-- END tab -->
50
  <!-- BEGIN tab -->
51
- <h3 id="ctc_new_styles">Adding New Styles</h3>
52
- <p>If you wish to add additional properties to a given selector, first load the selector using the Query/Selector tab. Then find the property you wish to override by typing in the <strong>New Property</strong> autoselect box. Select by clicking with the mouse or by pressing the "Enter" or "Tab" keys. This will add a new input row to the selector inputs.</p>
53
  <p>If you wish to add completely new selectors, or even new @media queries, you can enter free-form CSS in the "Raw CSS" textarea. Be aware that your syntax must be correct (i.e., balanced curly braces, etc.) for the parser to load the new styles. You will know it is invalid because a red "X" will appear next to the save button.</p>
54
  <p>If you prefer to use shorthand syntax for properties and values instead of the inputs provided by the Child Theme Configurator, you can enter them here as well. The parser will convert your input into normalized CSS code automatically.</p>
 
55
  <!-- END tab -->
56
  <!-- BEGIN tab -->
57
  <h3 id="ctc_property_value">Property/Value Tab</h3>
58
- <p>There are two ways to identify and override parent styles. The Child Theme Configurator lets you search styles by <strong>selector</strong> and by <strong>property</strong>. If you wish to change a specific selector (e.g., h1), use the "Query/Selector" tab. If you have a specific value you wish to change site-wide (e.g., the color of the type), use the "Property/Value" tab.</p>
59
  <p>The Property/Value tab lets you find specific values for a given property and then edit that value for individual selectors that use that property/value combination. First, find the property you wish to override by typing in the <strong>Property</strong> autoselect box. Select by clicking with the mouse or by pressing the "Enter" or "Tab" keys.</p>
60
  <p>This will load all of the unique values that exist for that property in the parent stylesheet with a Sample preview for that value. If there are values that exist in the child stylesheet that do not exist in the parent stylesheet, they will be displayed as well.</p>
61
- <p>For each unique value, click the "Selectors" link to view a list of selectors that use that property/value combination, grouped by query with a Sample preview of the value and inputs for the child value. Any existing child values will be automatically populated.</p>
62
  <p>Click "Save" to update the child stylesheet and save your changes to the WordPress admin.</p>
63
  <!-- END tab -->
64
  <!-- BEGIN tab -->
@@ -92,7 +85,7 @@ This option imports the parent stylesheet from the child stylesheet. This enable
92
  <!-- END tab -->
93
  <!-- BEGIN tab -->
94
  <h3 id="ctc_preview">Preview and Activate</h3>
95
- <p><strong>IMPORTANT: <a target="_blank" href="<?php echo CHLD_THM_CFG_DOCS_URL; ?>/how-to-use/#preview_activate" title="Test your child theme before activating!">Test your child theme before activating!</a></strong> Some themes (particularly commercial themes) do not correctly load parent template files or automatically load child theme stylesheets or php files. <strong>In the worst cases they will break your website when you activate the child theme.</strong></p>
96
  <ol>
97
  <li>Navigate to Appearance > Themes in the WordPress Admin. You will now see the new Child Theme as one of the installed Themes.</li>
98
  <li>Click "Live Preview" below the new Child Theme to see it in action.</li>
@@ -134,13 +127,13 @@ This option imports the parent stylesheet from the child stylesheet. This enable
134
 
135
  <p>If you want to set different options you can either apply them after you activate the child theme, or by using the "Live Preview" under Appearance > Themes.</p>
136
  <ul class="instructions">
137
- <li><strong>Menus: </strong> Go to Appearance > Menus and click the "Locations" tab. By default, the primary menu will generate the links automatically from the existing pages. Select your customized Menu from the dropdown and click "Use New Menu." This will replace the default menu and you will see the correct links.</li>
138
 
139
- <li><strong>Header: </strong> Go to Appearance > Header. Some themes will show the "Title" and "Tagline" from your "General Settings" by default. Click "Choose Image" and find the header from the Media Library or upload a new image. This will replace default with your custom image.</li>
140
 
141
- <li><strong>Background: </strong> Go to Appearance > Background and choose a new background color or image.</li>
142
 
143
- <li><strong>Options: </strong> Every theme handles options in its own way. Most often, they will create a set of options and store them in the WordPress database. Some options are specific to the active theme (or child theme), and some are specific to the parent theme only (meaning the child theme CANNOT override them). You will have to find out from the theme author which are which.</li>
144
  </ul>
145
  </p>
146
  <h5 id="existing_parent">How do I move changes I have already made to my theme into a Child Theme?</h5>
@@ -177,7 +170,7 @@ The plugin only loads the bulk of the code in the admin when you are using the t
177
  <h5 id="add_styles">How do I add styles that aren't in the Parent Theme?</h5>
178
  <p>You can add queries and selectors using the "Raw CSS" textarea on the Query/Selector tab. See Query/Selector, above. </p>
179
  <h5 id="add_styles">How do I remove a style from the Parent Theme?</h5>
180
- <p>You shouldn't really "remove" a style from the Parent. You can, however, set the property to "inherit," "none," or zero (depending on the property). This will negate the Parent value. Some experimentation may be necessary.</p>
181
  <h5 id="remove_styles">How do I remove a style from the Child Theme?</h5>
182
  <p>Delete the value from the input for the property you wish to remove. The Child Theme Configurator only adds overrides for properties that contain values. </p>
183
  <h5 id="important_flag">How do I set the !important flag?</h5>
@@ -195,28 +188,33 @@ The plugin only loads the bulk of the code in the admin when you are using the t
195
  <ul>
196
  <li id="parent_theme"><strong>Parent Theme</strong> The WordPress Theme you wish to edit. WordPress first loads the Child Theme, then loads the Parent Theme. If a style exists in the Child Theme, it overrides the Parent Theme.</li>
197
  <li id="child_theme"><strong>Child Theme</strong> New Theme based on Parent Theme. You can create any number of Child Themes from a single Parent Theme.</li>
198
- <li id="class"><strong>Class</strong> A term used to organize objects. For example, a &lt;div&gt; might be assigned the "blue-text" class. The stylesheet might then assign "color: blue;" to members of the "blue-text" class. Thus, the &lt;div&gt; would display text as blue in the browser.</li>
199
- <li id="selector"><strong>Selector</strong> One or more html elements, classes, ids or other terms used to identify groups of objects.</li>
 
 
200
  <li id="property"><strong>Property</strong> One of many standardized terms used to tell the browser how to display objects matching a given selector. Examples are <strong>color</strong>, <strong>background-image</strong> and <strong>font-size</strong>.</li>
 
201
  <li id="at-rule"><strong>At-rule</strong> CSS browser instruction to extend default functionality. The Child Theme Configurator supports two At-rules:
202
  <ul>
203
- <li id="import"><strong>@import</strong> Instructs the browser to load additional CSS information from an external source.</li>
204
- <li id="query"><strong>@media (Media Query)</strong> Identifies blocks of styles that are used only when certain browser characteristics are true. Examples are max-width, screen and print.</li>
205
  </ul>
206
  </li>
 
207
  <li id="override"><strong>Override</strong> When a selector exists in both the Child Theme and the Parent Theme, the Child Theme takes priority over the Parent theme. This is where the Child Theme Configurator stands out: it helps you create <strong>exact overrides</strong> of selectors from the Parent Theme, eliminating hours of trial and error.</li>
 
208
  </ul>
209
  <!-- END tab -->
210
  <!-- BEGIN sidebar -->
211
  <h4>Our plugins will not nag you for donations...</h4>
212
  <span style="font-size:smaller">...but we LOVE referrals.</span><br/><a href="http://wordpress.org/support/view/plugin-reviews/child-theme-configurator?rate=5#postform">Give Us 5 Stars</a>
213
  <h4>Introducing CTC Pro</h4>
214
- <a href="<?php echo CHLD_THM_CFG_DOCS_URL; ?>/child-theme-configurator-pro/" title="<?php _e( 'Learn more about CTC Pro', 'child-theme-configurator' ); ?>"><img src="<?php echo CHLD_THM_CFG_URL . 'css/pro-banner.jpg'; ?>" width="150" height="48" /></a>
215
  <p style="font-size:smaller">Designed by WordPress developers who use it every day, CTC Pro adds plugin stylesheets and other features to make design work quicker and easier. This is a free upgrade for users that purchased the Plugins Extension. <a href="<?php echo CHLD_THM_CFG_DOCS_URL; ?>/child-theme-configurator-pro/" title="Child Theme Configurator Pro">Learn more</a></p>
216
  <h4 id="ctc_help_sidebar">Links</h4>
217
  <ul>
218
- <li><a href="http://www.lilaeamedia.com/about/contact/">Contact us</a></li>
219
- <li><a href="http://www.childthemeconfigurator.com/">Plugin Website</a></li>
220
  <li><a href="http://codex.wordpress.org/Child_Themes">WordPress Codex</a></li>
221
  <li><a href="http://wordpress.stackexchange.com/">WordPress Development (StackExchange)</a></li>
222
  </ul>
3
  // Help Content
4
  ?>
5
  <!-- BEGIN tab -->
6
+ <h3 id="ctc_tutorial">Start Here: Tutorial Videos</h3>
7
+ <!--p><iframe width="560" height="315" src="https://www.youtube.com/embed/xL0YmieF6d0?rel=0&modestbranding=1" frameborder="0" allowfullscreen></iframe></p>
8
+ <p><iframe width="560" height="315" src="https://www.youtube.com/embed/vhQ5oi20rYE?rel=0&modestbranding=1" frameborder="0" allowfullscreen></iframe></p -->
9
+ <p><a href="<?php echo CHLD_THM_CFG_DOCS_URL; ?>/tutorial-videos" target="_blank">Click here to view videos.</a></p><!-- END tab -->
10
+ <!-- BEGIN tab -->
11
+ <h3 id="ctc_getting_started">Parent/Child Tab</h3>
12
+ <ol><li><strong>Select an action:</strong>
13
+ <ul><li><strong>CREATE a new Child Theme</strong> - Install a new customizable child theme using an installed theme as a parent.</li>
14
+ <li><strong>CONFIGURE an existing Child Theme</strong> - Set up a previously installed child theme for use with the Configurator or to modify current settings.</li>
15
+ <li><strong>DUPLICATE an existing Child Theme</strong> - Make a complete copy of an existing Child Theme in a new directory, including any menus, widgets and other Customizer settings. The option to copy the Parent Theme settings (step 8, below) is disabled with this action.</li>
16
+ <li><strong>RESET an existing Child Theme</strong> (this will destroy any work you have done in the Configurator) - Revert the Child theme stylesheet and functions files to their state before the initial configuration or last reset.</li></ul></li>
17
+ <li><strong>Select a Parent Theme</strong> if creating a new Child Theme; select a Child Theme if configuring, duplicating or resetting.</li>
18
+ <li><strong>Analyze Child Theme</strong> - Click "Analyze" to determine stylesheet dependencies and other potential issues.</li>
19
+ <li><strong>Name the new theme directory</strong> if creating a new Child Theme; otherwise verify it the directory is correct. - This is NOT the name of the Child Theme. You can customize the name, description, etc. in step 7, below.</li>
20
+ <li><strong>Select where to save new styles:</strong><ul>
21
+ <li><strong>Primary Stylesheet (style.css)</strong> - Save new custom styles directly to the Child Theme primary stylesheet, replacing the existing values. The primary stylesheet will load in the order set by the theme.</li>
22
+ <li><strong>Separate Stylesheet</strong> - Save new custom styles to a separate stylesheet and use any existing child theme styles as a baseline. Select this option if you want to preserve the original child theme styles instead of overwriting them. This option also allows you to customize stylesheets that load after the primary stylesheet.</li></ul></li>
23
+ <li><strong>Select Parent Theme stylesheet handling:</strong><ul>
24
+ <li><strong>Use the WordPress style queue.</strong> - Let the Configurator determine the appropriate actions and dependencies and update the functions file automatically.</li>
25
+ <li><strong>Use @import</strong> in the child theme stylesheet. - Only use this option if the parent stylesheet cannot be loaded using the WordPress style queue. Using @import is not recommended.</li>
26
+ <li><strong>Do not add any parent stylesheet handling.</strong> - Select this option if this theme already handles the parent theme stylesheet or if the parent theme's style.css file is not used for its appearance.</li></ul></li>
27
+ <li><strong>Customize the Child Theme Name, Description, Author, Version, etc.</strong></li>
28
+ <li><strong>Copy Parent Theme Menus, Widgets and other Customizer Settings to Child Theme.</strong> - NOTE: This will overwrite any child theme options you may have already set.</li>
29
+ <li><strong>Click the button</strong> to run the Configurator.</li>
30
+ <li><strong>IMPORTANT: <a target="_blank" href="<?php echo CHLD_THM_CFG_DOCS_URL; ?>/how-to-use/#preview_activate" title="Preview your child theme before activating!">Always test your child theme with Live Preview (theme customizer) before activating!</a></strong></li>
 
 
 
 
 
31
  </ol>
32
  <!-- END tab -->
33
  <!-- BEGIN tab -->
 
 
 
34
  <h3 id="ctc_query_selector">Query/Selector Tab</h3>
35
+ <p>There are two ways to identify and override baseline (parent) styles. The Child Theme Configurator lets you search styles by <strong>selector</strong> and by <strong>property</strong>. If you wish to change a specific selector (e.g., h1), use the "Query/Selector" tab. If you have a specific value you wish to change site-wide (e.g., the color of the type), use the "Property/Value" tab.</p>
36
  <p>The Query/Selector tab lets you find specific selectors and edit them. First, find the query that contains the selector you wish to edit by typing in the <strong>Query</strong> autoselect box. Select by clicking with the mouse or by pressing the "Enter" or "Tab" keys. Selectors are in the <strong>base</strong> query by default.</p>
37
  <p>Next, find the selector by typing in the <strong>Selector</strong> autoselect box. Select by clicking with the mouse or by pressing the "Enter" or "Tab" keys.</p>
38
+ <p>This will load all of the properties for that selector with the Original values on the left and the New values inputs on the right. Any existing new values will be automatically populated. There is also a Sample preview that displays the combination of Parent and Child overrides. Note that the <strong>border</strong> and <strong>background-image</strong> get special treatment.</p>
39
+ <p>If you wish to add additional properties to an existing selector, first load the selector using the Query/Selector tab. Then find the property you wish to override by typing in the <strong>New Property</strong> autoselect box. Select by clicking with the mouse or by pressing the "Enter" or "Tab" keys. This will add a new input row to the selector inputs.</p>
40
  <p>The "Order" field contains the original sequence of the selector in the parent theme stylesheet. You can change the selector order sequence by entering a lower or higher number in the "Order" field. You can also force style overrides (so called "!important" flag) by checking the "!" box next to each input. Please use judiciously.</p>
41
  <p>Click "Save" to update the child stylesheet and save your changes to the WordPress admin.</p>
42
  <!-- END tab -->
43
  <!-- BEGIN tab -->
44
+ <h3 id="ctc_new_styles">Adding Raw CSS</h3>
 
45
  <p>If you wish to add completely new selectors, or even new @media queries, you can enter free-form CSS in the "Raw CSS" textarea. Be aware that your syntax must be correct (i.e., balanced curly braces, etc.) for the parser to load the new styles. You will know it is invalid because a red "X" will appear next to the save button.</p>
46
  <p>If you prefer to use shorthand syntax for properties and values instead of the inputs provided by the Child Theme Configurator, you can enter them here as well. The parser will convert your input into normalized CSS code automatically.</p>
47
+ <p>If you wish to add additional properties to an existing selector, first load the selector using the Query/Selector tab. Then find the property you wish to override by typing in the <strong>New Property</strong> autoselect box. Select by clicking with the mouse or by pressing the "Enter" or "Tab" keys. This will add a new input row to the selector inputs.</p>
48
  <!-- END tab -->
49
  <!-- BEGIN tab -->
50
  <h3 id="ctc_property_value">Property/Value Tab</h3>
51
+ <p>There are two ways to identify and override baseline (parent) styles. The Child Theme Configurator lets you search styles by <strong>selector</strong> and by <strong>property</strong>. If you wish to change a specific selector (e.g., h1), use the "Query/Selector" tab. If you have a specific value you wish to change site-wide (e.g., the color of the type), use the "Property/Value" tab.</p>
52
  <p>The Property/Value tab lets you find specific values for a given property and then edit that value for individual selectors that use that property/value combination. First, find the property you wish to override by typing in the <strong>Property</strong> autoselect box. Select by clicking with the mouse or by pressing the "Enter" or "Tab" keys.</p>
53
  <p>This will load all of the unique values that exist for that property in the parent stylesheet with a Sample preview for that value. If there are values that exist in the child stylesheet that do not exist in the parent stylesheet, they will be displayed as well.</p>
54
+ <p>For each unique value, click the "Selectors" link to view a list of selectors that use that property/value combination, grouped by query with a Sample preview of the value and inputs for the new value. Any existing new values will be automatically populated.</p>
55
  <p>Click "Save" to update the child stylesheet and save your changes to the WordPress admin.</p>
56
  <!-- END tab -->
57
  <!-- BEGIN tab -->
85
  <!-- END tab -->
86
  <!-- BEGIN tab -->
87
  <h3 id="ctc_preview">Preview and Activate</h3>
88
+ <p><strong>IMPORTANT: <a target="_blank" href="<?php echo CHLD_THM_CFG_DOCS_URL; ?>/how-to-use/#preview_activate" title="Preview your child theme before activating!">Preview your child theme before activating!</a></strong> Some themes (particularly commercial themes) do not correctly load parent template files or automatically load child theme stylesheets or php files. <strong>In the worst cases they will break your website when you activate the child theme.</strong></p>
89
  <ol>
90
  <li>Navigate to Appearance > Themes in the WordPress Admin. You will now see the new Child Theme as one of the installed Themes.</li>
91
  <li>Click "Live Preview" below the new Child Theme to see it in action.</li>
127
 
128
  <p>If you want to set different options you can either apply them after you activate the child theme, or by using the "Live Preview" under Appearance > Themes.</p>
129
  <ul class="instructions">
130
+ <li><strong>Menus: </strong> Go to Appearance > Menus and click the "Locations" tab. By default, the primary menu will generate the links automatically from the existing pages. Select your customized Menu from the dropdown and click "Use New Menu." This will replace the default menu and you will see the correct links.</li>
131
 
132
+ <li><strong>Header: </strong> Go to Appearance > Header. Some themes will show the "Title" and "Tagline" from your "General Settings" by default. Click "Choose Image" and find the header from the Media Library or upload a new image. This will replace default with your custom image.</li>
133
 
134
+ <li><strong>Background: </strong> Go to Appearance > Background and choose a new background color or image.</li>
135
 
136
+ <li><strong>Options: </strong> Every theme handles options in its own way. Most often, they will create a set of options and store them in the WordPress database. Some options are specific to the active theme (or child theme), and some are specific to the parent theme only (meaning the child theme CANNOT override them). You will have to find out from the theme author which are which.</li>
137
  </ul>
138
  </p>
139
  <h5 id="existing_parent">How do I move changes I have already made to my theme into a Child Theme?</h5>
170
  <h5 id="add_styles">How do I add styles that aren't in the Parent Theme?</h5>
171
  <p>You can add queries and selectors using the "Raw CSS" textarea on the Query/Selector tab. See Query/Selector, above. </p>
172
  <h5 id="add_styles">How do I remove a style from the Parent Theme?</h5>
173
+ <p>You shouldn't really "remove" a style from the Parent. You can, however, set the property to "inherit," "none," or zero (depending on the property). This will negate the Original value. Some experimentation may be necessary.</p>
174
  <h5 id="remove_styles">How do I remove a style from the Child Theme?</h5>
175
  <p>Delete the value from the input for the property you wish to remove. The Child Theme Configurator only adds overrides for properties that contain values. </p>
176
  <h5 id="important_flag">How do I set the !important flag?</h5>
188
  <ul>
189
  <li id="parent_theme"><strong>Parent Theme</strong> The WordPress Theme you wish to edit. WordPress first loads the Child Theme, then loads the Parent Theme. If a style exists in the Child Theme, it overrides the Parent Theme.</li>
190
  <li id="child_theme"><strong>Child Theme</strong> New Theme based on Parent Theme. You can create any number of Child Themes from a single Parent Theme.</li>
191
+ <li id="class"><strong>Class</strong> A term used to organize objects. For example, a &lt;div&gt; might be assigned the "blue-text" class. The stylesheet might then assign "color: blue;" to members of the "blue-text" class. Thus, the &lt;div&gt; would display text as blue in the browser. Class selectors begin with a period (.).</li>
192
+ <li id="class"><strong>ID</strong> A unique string used to identify a specific element. ID selectors begin with a hash (#).</li>
193
+ <li id="selector"><strong>Query</strong> @media query instruction (see At-rule, below).</li>
194
+ <li id="query"><strong>Selector</strong> Combination of html tag names, ids and classes used to identify objects or groups of objects.</li>
195
  <li id="property"><strong>Property</strong> One of many standardized terms used to tell the browser how to display objects matching a given selector. Examples are <strong>color</strong>, <strong>background-image</strong> and <strong>font-size</strong>.</li>
196
+ <li id="value"><strong>Value</strong> Data corresponding to a Property.</li>
197
  <li id="at-rule"><strong>At-rule</strong> CSS browser instruction to extend default functionality. The Child Theme Configurator supports two At-rules:
198
  <ul>
199
+ <li id="at_import"><strong>@import</strong> Instructs the browser to load additional CSS information from an external source.</li>
200
+ <li id="at_media"><strong>@media (Media Query)</strong> Identifies blocks of styles that are used only when certain browser characteristics are true. Examples are max-width, screen and print.</li>
201
  </ul>
202
  </li>
203
+ <li id="child_theme"><strong>Baseline Style</strong> A style from any existing Parent Theme or Child Theme stylesheet that can be overridden by the Child Theme custom stylesheet. Most of the time these will come from the Parent Theme's stylesheets.</li>
204
  <li id="override"><strong>Override</strong> When a selector exists in both the Child Theme and the Parent Theme, the Child Theme takes priority over the Parent theme. This is where the Child Theme Configurator stands out: it helps you create <strong>exact overrides</strong> of selectors from the Parent Theme, eliminating hours of trial and error.</li>
205
+ <li id="child_theme"><strong>Theme Template</strong> A Theme PHP file having no PHP functions or classes. Other PHP files cannot be safely overridden by a child theme.</li>
206
  </ul>
207
  <!-- END tab -->
208
  <!-- BEGIN sidebar -->
209
  <h4>Our plugins will not nag you for donations...</h4>
210
  <span style="font-size:smaller">...but we LOVE referrals.</span><br/><a href="http://wordpress.org/support/view/plugin-reviews/child-theme-configurator?rate=5#postform">Give Us 5 Stars</a>
211
  <h4>Introducing CTC Pro</h4>
212
+ <a href="<?php echo CHLD_THM_CFG_DOCS_URL; ?>/child-theme-configurator-pro/" title="Learn more about CTC Pro"><img src="<?php echo CHLD_THM_CFG_URL . 'css/pro-banner.jpg'; ?>" width="150" height="48" /></a>
213
  <p style="font-size:smaller">Designed by WordPress developers who use it every day, CTC Pro adds plugin stylesheets and other features to make design work quicker and easier. This is a free upgrade for users that purchased the Plugins Extension. <a href="<?php echo CHLD_THM_CFG_DOCS_URL; ?>/child-theme-configurator-pro/" title="Child Theme Configurator Pro">Learn more</a></p>
214
  <h4 id="ctc_help_sidebar">Links</h4>
215
  <ul>
216
+ <li><a href="<?php echo LILAEAMEDIA_URL; ?>/contact/">Contact us</a></li>
217
+ <li><a href="<?php echo CHLD_THM_CFG_DOCS_URL; ?>">Plugin Website</a></li>
218
  <li><a href="http://codex.wordpress.org/Child_Themes">WordPress Codex</a></li>
219
  <li><a href="http://wordpress.stackexchange.com/">WordPress Development (StackExchange)</a></li>
220
  </ul>
js/chld-thm-cfg.js DELETED
@@ -1,1540 +0,0 @@
1
- /*!
2
- * Script: chld-thm-cfg.js
3
- * Plugin URI: http://www.childthemeconfigurator.com/
4
- * Description: Handles jQuery, AJAX and other UI
5
- * Version: 1.7.9
6
- * Author: Lilaea Media
7
- * Author URI: http://www.lilaeamedia.com/
8
- * License: GPLv2
9
- * Copyright (C) 2014-2015 Lilaea Media
10
- */
11
-
12
- // ** for muliple property values: **
13
- // make sure sequence is passed with rule/val updates
14
- // determine sequence based on sequence of value array
15
- // add sequence to input name
16
-
17
- ( function( $ ) {
18
- $.chldthmcfg = {
19
- //console.log( 'executing main function' );
20
- esc_quot: function( str ) {
21
- var self = this;
22
- return self.is_empty( str ) ? str : str.toString().replace( /"/g, '&quot;' );
23
- },
24
-
25
- getxt: function( key ){
26
- return ( text = ctcAjax[ key + '_txt' ] ) ? text : '';
27
- },
28
-
29
- from_ascii: function( str ) {
30
- var ascii = parseInt( str ),
31
- chr = String.fromCharCode( ascii )
32
- return chr;
33
- },
34
-
35
- to_ascii: function( str ) {
36
- var ascii = str.charCodeAt( 0 );
37
- return ascii;
38
- },
39
-
40
- /**
41
- * is_empty
42
- * return true if value evaluates to false, null, null string,
43
- * empty array, empty object or undefined
44
- * but NOT 0 ( zero returns false )
45
- */
46
- is_empty: function( obj ) {
47
- // first bail when definitely empty or undefined ( true ) NOTE: numeric zero returns false !
48
- if ( 'undefined' == typeof obj || false === obj || null === obj || '' === obj ) { return true; }
49
- // then, if this is bool, string or number it must not be empty ( false )
50
- if ( true === obj || "string" === typeof obj || "number" === typeof obj ) { return false; }
51
- // check for object type to be safe
52
- if ( "object" === typeof obj ) {
53
- // Use a standard for in loop
54
- for ( var x in obj ) {
55
- // A for in will iterate over members on the prototype
56
- // chain as well, but Object.getOwnPropertyNames returns
57
- // only those directly on the object, so use hasOwnProperty.
58
- if ( obj.hasOwnProperty( x ) ) {
59
- // any value means not empty ( false )
60
- return false;
61
- }
62
- }
63
- // no properties, so return empty ( true )
64
- return true;
65
- }
66
- // this must be an unsupported datatype, so return not empty
67
- return false;
68
- },
69
-
70
- /**
71
- * theme_exists
72
- * returns true if theme is already present for type
73
- */
74
- theme_exists: function( testslug, testtype ) {
75
- var exists = false;
76
- $.each( ctcAjax.themes, function( type, theme ) {
77
- $.each( theme, function( slug, data ) {
78
- if ( slug.toLowerCase() === testslug.toLowerCase() && ( 'parnt' == type || 'new' == testtype ) ) {
79
- exists = true;
80
- return false;
81
- }
82
- } );
83
- if ( exists ) return false;
84
- } );
85
- return exists;
86
- },
87
-
88
- validate: function() {
89
- var self = this,
90
- regex = /[^\w\-]/,
91
- newslug = $( '#ctc_child_template' ).length ? $( '#ctc_child_template' )
92
- .val().toString().replace( regex ) : '',
93
- slug = $( '#ctc_theme_child' ).length ? $( '#ctc_theme_child' )
94
- .val().toString().replace( regex ) : newslug,
95
- type = $( 'input[name=ctc_child_type]:checked' ).val(),
96
- errors = [];
97
- if ( 'new' == type ) slug = newslug;
98
- if ( self.theme_exists( slug, type ) ) {
99
- errors.push( self.getxt( 'theme_exists' ).toString().replace( /%s/, slug ) );
100
- }
101
- if ( '' === slug ) {
102
- errors.push( self.getxt( 'inval_theme' ) );
103
- }
104
- if ( '' === $( '#ctc_child_name' ).val() ) {
105
- errors.push( self.getxt( 'inval_name' ) );
106
- }
107
- if ( errors.length ) {
108
- self.set_notice( { 'error': errors } );
109
- return false;
110
- }
111
- return true;
112
- },
113
-
114
- autogen_slugs: function() {
115
- if ( $( '#ctc_theme_parnt' ).length ) {
116
- var self = this,
117
- parent = $( '#ctc_theme_parnt' ).val(),
118
- slug = slugbase = parent + '-child',
119
- name = ctcAjax.themes.parnt[ parent ].Name + ' Child',
120
- suffix = '',
121
- padded = '',
122
- pad = '00';
123
- while ( self.theme_exists( slug, 'new' ) ) {
124
- suffix = ( '' == suffix ? 2 : suffix + 1 );
125
- padded = pad.substring( 0, pad.length - suffix.toString().length ) + suffix.toString();
126
- slug = slugbase + padded;
127
- }
128
- self.testslug = slug;
129
- self.testname = name + ( padded.length ? ' ' + padded : '' );
130
- }
131
- },
132
-
133
- focus_panel: function( id ) {
134
- var panelid = id + '_panel';
135
- $( '.nav-tab' ).removeClass( 'nav-tab-active' );
136
- $( '.ctc-option-panel' ).removeClass( 'ctc-option-panel-active' );
137
- //$( '.ctc-selector-container' ).hide();
138
- $( id ).addClass( 'nav-tab-active' );
139
- $( '.ctc-option-panel-container' ).scrollTop( 0 );
140
- $( panelid ).addClass( 'ctc-option-panel-active' );
141
- },
142
-
143
- selector_input_toggle: function( obj ) {
144
- //console.log( 'selector_input_toggle: ' + obj );
145
- var self = this,
146
- origval;
147
- if ( $( '#ctc_rewrite_selector' ).length ) {
148
- origval = $( '#ctc_rewrite_selector_orig' ).val();
149
- $( '#ctc_sel_ovrd_selector_selected' ).text( origval );
150
- $( obj ).text( self.getxt( 'rename' ) );
151
- } else {
152
- origval = $( '#ctc_sel_ovrd_selector_selected' ).text();
153
- $( '#ctc_sel_ovrd_selector_selected' ).html(
154
- '<textarea id="ctc_rewrite_selector"'
155
- + ' name="ctc_rewrite_selector" autocomplete="off"></textarea>'
156
- + '<input id="ctc_rewrite_selector_orig" name="ctc_rewrite_selector_orig"'
157
- + ' type="hidden" value="' + self.esc_quot( origval ) + '"/>' );
158
- $( '#ctc_rewrite_selector' ).val( origval );
159
- $( obj ).text( self.getxt( 'cancel' ) );
160
- }
161
- },
162
-
163
- fade_update_notice: function() {
164
- $( '.updated, .error' ).slideUp( 'slow', function() { $( '.updated' ).remove(); } );
165
- },
166
-
167
- coalesce_inputs: function( obj ) {
168
- //**console.log( 'coalesce_inputs ' + $( obj ).attr( 'id' ) );
169
- var self = this,
170
- id = $( obj ).attr( 'id' ),
171
- regex = /^(ctc_(ovrd|\d+)_(parent|child)_([0-9a-z\-]+)_(\d+?)(_(\d+))?)(_\w+)?$/,
172
- container = $( obj ).parents( '.ctc-selector-row, .ctc-parent-row' ).first(),
173
- swatch = container.find( '.ctc-swatch' ).first(),
174
- cssrules = { 'parent': {}, 'child': {} },
175
- gradient = {
176
- 'parent': {
177
- 'origin': '',
178
- 'start': '',
179
- 'end': ''
180
- },
181
- 'child': {
182
- 'origin': '',
183
- 'start': '',
184
- 'end': ''
185
- }
186
- },
187
- has_gradient = { 'child': false, 'parent': false },
188
- postdata = {};
189
- // set up objects for all neighboring inputs
190
- container.find( '.ctc-parent-value, .ctc-child-value' ).each( function() {
191
- var inputid = $( this ).attr( 'id' ),
192
- inputparts = inputid.toString().match( regex ),
193
- inputseq = inputparts[ 2 ],
194
- inputtheme = inputparts[ 3 ],
195
- inputrule = ( 'undefined' == typeof inputparts[ 4 ] ? '' : inputparts[ 4 ] ),
196
- rulevalid = inputparts[ 7 ],
197
- qsid = inputparts[ 5 ],
198
- rulepart = ( 'undefined' == typeof inputparts[ 7 ] ? '' : inputparts[ 8 ] ),
199
- value = ( 'parent' == inputtheme ? $( this ).text().replace( /!$/, '' ) :
200
- ( 'seq' != inputrule && 'ctc_delete_query_selector' == id ? '' : $( this ).val() ) ), // clear values if delete was clicked
201
- important = ( 'seq' == inputrule ? false : 'ctc_' + inputseq + '_child_' + inputrule + '_i_' + qsid + '_' + rulevalid ),
202
- parts, subparts;
203
- //**console.log( inputparts );
204
- //**console.log( 'value: ' + value );
205
- if ( 'child' == inputtheme ) {
206
- if ( !self.is_empty( $( this ).data( 'color' ) ) ) {
207
- value = self.color_text( $( this ).data( 'color' ) );
208
- $( this ).data( 'color', null );
209
- }
210
- postdata[ inputid ] = value;
211
- if ( important )
212
- postdata[ important ] = ( $( '#' + important ).is( ':checked' ) ) ? 1 : 0;
213
- }
214
- if ( '' !== value ) {
215
- // handle specific inputs
216
- if ( !self.is_empty( rulepart ) ) {
217
- switch( rulepart ) {
218
- case '_border_width':
219
- cssrules[ inputtheme ][ inputrule + '-width' ] = ( 'none' == value ? 0 : value );
220
- break;
221
- case '_border_style':
222
- cssrules[ inputtheme ][ inputrule + '-style' ] = value;
223
- break;
224
- case '_border_color':
225
- cssrules[ inputtheme ][ inputrule + '-color' ] = value;
226
- break;
227
- case '_background_url':
228
- cssrules[ inputtheme ][ 'background-image' ] = self.image_url( inputtheme, value );
229
- break;
230
- case '_background_color':
231
- cssrules[ inputtheme ][ 'background-color' ] = value; // was obj.value ???
232
- break;
233
- case '_background_color1':
234
- gradient[ inputtheme ].start = value;
235
- has_gradient[ inputtheme ] = true;
236
- break;
237
- case '_background_color2':
238
- gradient[ inputtheme ].end = value;
239
- has_gradient[ inputtheme ] = true;
240
- break;
241
- case '_background_origin':
242
- gradient[ inputtheme ].origin = value;
243
- has_gradient[ inputtheme ] = true;
244
- break;
245
- }
246
- } else {
247
- // handle borders
248
- if ( parts = inputrule.toString().match( /^border(\-(top|right|bottom|left))?$/ ) && !value.match( /none/ ) ) {
249
- var borderregx = new RegExp( self.border_regx + self.color_regx, 'i' ),
250
- subparts = value.toString().match( borderregx );
251
- //**console.log( 'border after regex: ');
252
- //**console.log( value );
253
- //**console.log( borderregx );
254
- //**console.log( subparts );
255
- if ( !self.is_empty( subparts ) ) {
256
- subparts.shift();
257
- cssrules[ inputtheme ][ inputrule + '-width' ] = subparts.shift() || '';
258
- subparts.shift();
259
- cssrules[ inputtheme ][ inputrule + '-style' ] = subparts.shift() || '';
260
- cssrules[ inputtheme ][ inputrule + '-color' ] = subparts.shift() || '';
261
- }
262
- // handle background images
263
- } else if ( 'background-image' == inputrule && !value.match( /none/ ) ) {
264
- if ( value.toString().match( /url\(/ ) ) {
265
- cssrules[ inputtheme ][ 'background-image' ] = self.image_url( inputtheme, value );
266
- } else {
267
- var gradregex = new RegExp( self.grad_regx + self.color_regx + self.color_regx, 'i' ),
268
- subparts = value.toString().match( gradregex );
269
- //**console.log( 'background-image after regex: ');
270
- //**console.log( value );
271
- //**console.log( gradregex );
272
- //**console.log( subparts );
273
- if ( !self.is_empty( subparts ) && subparts.length > 2 ) {
274
- subparts.shift();
275
- gradient[ inputtheme ].origin = subparts.shift() || 'top';
276
- gradient[ inputtheme ].start = subparts.shift() || 'transparent';
277
- gradient[ inputtheme ].end = subparts.shift() || 'transparent';
278
- has_gradient[ inputtheme ] = true;
279
- } else {
280
- cssrules[ inputtheme ][ 'background-image' ] = value;
281
- }
282
- }
283
- } else if ( 'seq' != inputrule ) {
284
- cssrules[ inputtheme ][ inputrule ] = value;
285
- }
286
- }
287
- }
288
- } );
289
- // update swatch
290
- if ( 'undefined' != typeof swatch && !self.is_empty( swatch.attr( 'id' ) ) ) {
291
- swatch.removeAttr( 'style' );
292
- if ( has_gradient.parent ) {
293
- swatch.ctcgrad( gradient.parent.origin, [ gradient.parent.start, gradient.parent.end ] );
294
- }
295
- //**console.log( 'combined css rules' );
296
- //**console.log( cssrules );
297
- swatch.css( cssrules.parent );
298
- if ( !( swatch.attr( 'id' ).toString().match( /parent/ ) ) ) {
299
- if ( has_gradient.child ) {
300
- swatch.ctcgrad( gradient.child.origin, [ gradient.child.start, gradient.child.end ] );
301
- }
302
- //console.log( cssrules.child );
303
- swatch.css( cssrules.child );
304
- }
305
- swatch.css( {'z-index':-1} );
306
- }
307
- return postdata;
308
- },
309
-
310
- decode_value: function( rule, value ) {
311
- //**console.log( 'in decode_value ( ' + rule + ' ...' );
312
- value = ( 'undefined' == typeof value ? '' : value );
313
- var self = this,
314
- obj = {
315
- 'orig': value,
316
- 'names': [ '' ],
317
- 'values': [ value ]
318
- };
319
- if ( rule.toString().match( /^border(\-(top|right|bottom|left))?$/ ) ) {
320
- var regex = new RegExp( self.border_regx + '(' + self.color_regx + ')?', 'i' ),
321
- params = value.toString().match( regex );
322
- if ( self.is_empty( params ) ) params = [];
323
- obj.names = [
324
- '_border_width',
325
- '_border_style',
326
- '_border_color',
327
- ];
328
- orig = params.shift();
329
- //**console.log( value );
330
- //**console.log( regex );
331
- //**console.log( params );
332
- obj.values[ 0 ] = params.shift() || '';
333
- params.shift();
334
- obj.values[ 1 ] = params.shift() || '';
335
- params.shift();
336
- obj.values[ 2 ] = params.shift() || '';
337
- } else if ( rule.toString().match( /^background\-image/ ) ) {
338
- obj.names = [
339
- '_background_url',
340
- '_background_origin',
341
- '_background_color1',
342
- '_background_color2'
343
- ];
344
- obj.values = [ '', '', '', '' ];
345
- if ( !self.is_empty( value ) && !( value.toString().match( /(url|none)/ ) ) ) {
346
- var params = value.toString().split( /:/ ),
347
- stop1, stop2;
348
- //**console.log( value );
349
- //**console.log( params );
350
- obj.values[ 1 ] = params.shift() || '';
351
- obj.values[ 2 ] = params.shift() || '';
352
- stop1 = params.shift() || '';
353
- obj.values[ 3 ] = params.shift() || '';
354
- stop2 = params.shift() || '';
355
- obj.orig = [
356
- obj.values[ 1 ],
357
- obj.values[ 2 ],
358
- obj.values[ 3 ]
359
- ].join( ' ' );
360
- } else {
361
- obj.values[ 0 ] = value;
362
- }
363
- }
364
- //**console.log( obj );
365
- return obj;
366
- },
367
-
368
- image_url: function( theme, value ) {
369
- var self = this,
370
- parts = value.toString().match( /url\(['" ]*(.+?)['" ]*\)/ ),
371
- path = self.is_empty( parts ) ? null : parts[ 1 ],
372
- url = ctcAjax.theme_uri + '/' + ( 'parent' == theme ? ctcAjax.parnt : ctcAjax.child ) + '/',
373
- image_url;
374
- if ( !path ) {
375
- return false;
376
- } else if ( path.toString().match( /^(data:|https?:|\/)/ ) ) {
377
- image_url = value;
378
- } else {
379
- image_url = 'url(' + url + path + ')';
380
- }
381
- return image_url;
382
- },
383
-
384
- setup_menus: function() {
385
- var self = this;
386
- //console.log( 'setup_menus' );
387
- self.setup_query_menu();
388
- self.setup_selector_menu();
389
- self.setup_rule_menu();
390
- self.setup_new_rule_menu();
391
- self.load_queries();
392
- self.load_rules();
393
- // selectors will be loaded after query selected
394
- self.set_query( self.current_query );
395
- },
396
-
397
- load_queries: function() {
398
- var self = this;
399
- //console.log( 'load_queries' );
400
- // retrieve unique media queries
401
- self.query_css( 'queries', null );
402
- },
403
-
404
- load_selectors: function() {
405
- var self = this;
406
- //console.log( 'load_selectors' );
407
- // retrieve unique selectors from query value
408
- self.query_css( 'selectors', self.current_query );
409
- },
410
-
411
- load_rules: function() {
412
- var self = this;
413
- //console.log( 'load_rules' );
414
- // retrieve all unique rules
415
- self.query_css( 'rules', null );
416
- },
417
-
418
- load_selector_values: function() {
419
- var self = this;
420
- //console.log( 'load_selector_values: ' + self.current_qsid );
421
- // retrieve individual values from qsid
422
- self.query_css( 'qsid', self.current_qsid );
423
- },
424
-
425
- get_queries: function( request, response ) {
426
- //console.log( 'get_queries' );
427
- //console.log( this );
428
- var self = this,
429
- arr = [],
430
- matcher = new RegExp( $.ui.autocomplete.escapeRegex( request.term ), "i" );
431
- if ( $.chldthmcfg.is_empty( this.element.data( 'menu' ) ) ) {
432
- arr.push( { 'label': ctcAjax.nosels_txt, 'value': null } );
433
- } else {
434
- // note: key = ndx, value = query name
435
- $.each( this.element.data( 'menu' ), function( key, val ) {
436
- if ( matcher.test( val ) ) {
437
- arr.push( { 'label': val, 'value': val } );
438
- }
439
- } );
440
- }
441
- response( arr );
442
- },
443
-
444
- get_selectors: function( request, response ) {
445
- //console.log( 'get_selectors' );
446
- var self = this,
447
- arr = [],
448
- matcher = new RegExp( $.ui.autocomplete.escapeRegex( request.term ), "i" );
449
- if ( $.chldthmcfg.is_empty( this.element.data( 'menu' ) ) ) {
450
- arr.push( { 'label': ctcAjax.nosels_txt, 'value': null } );
451
- } else {
452
- // note: key = selector name, value = qsid
453
- $.each( this.element.data( 'menu' ), function( key, val ) {
454
- if ( matcher.test( key ) ) {
455
- arr.push( { 'label': key, 'value': val } );
456
- }
457
- } );
458
- }
459
- response( arr );
460
- },
461
-
462
- get_rules: function( request, response ) {
463
- //console.log( 'get_rules' );
464
- var self = this,
465
- arr = [],
466
- matcher = new RegExp( $.ui.autocomplete.escapeRegex( request.term ), "i" );
467
- if ( $.chldthmcfg.is_empty( this.element.data( 'menu' ) ) ) {
468
- arr.push( { 'label': ctcAjax.nosels_txt, 'value': null } );
469
- } else {
470
- // note: key = ruleid, value = rule name
471
- $.each( this.element.data( 'menu' ), function( key, val ) {
472
- if ( matcher.test( key ) ) {
473
- arr.push( { 'label': key, 'value': val } );
474
- }
475
- } );
476
- }
477
- response( arr );
478
- },
479
-
480
- get_filtered_rules: function( request, response ) {
481
- //console.log( 'get_filtered_rules' );
482
- var self = this,
483
- arr = [],
484
- matcher = new RegExp( $.ui.autocomplete.escapeRegex( request.term ), "i" ); //,
485
- if ( $.chldthmcfg.is_empty( this.element.data( 'menu' ) ) ) {
486
- arr.push( { 'label': ctcAjax.nosels_txt, 'value': null } );
487
- } else {
488
- $.each( $( '#ctc_rule_menu' ).data( 'menu' ), function( key, val ) {
489
- //multiple versions of rule ok
490
- if ( matcher.test( key ) ) {
491
- arr.push( { 'label': key, 'value': val } );
492
- }
493
- } );
494
- }
495
- response( arr );
496
- },
497
-
498
- /**
499
- * parent and child values are stored in separate arrays
500
- * this function puts them into parent/child columns by rulevalid
501
- */
502
- merge_ruleval_arrays: function( rule, value, isnew ) {
503
- //**console.log( 'merge_ruleval_arrays' );
504
- var self = this,
505
- valarr = {};
506
- nextval = isnew ? value.child.pop() : null; // if new rule, pop off the top before counting
507
- //**console.log( value );
508
- $.each( [ 'parnt', 'child' ], function( ndx, template ) {
509
- // iterate through parent and child val arrays and populate new assoc array with parent/child for each rulevalid
510
- if ( !self.is_empty( value[ template ] ) ) {
511
- $.each( value[ template ], function( ndx2, val ) {
512
- if ( isnew ) {
513
- // if new rule, increment new rulevalid but do not add to parent/child assoc array
514
- if ( parseInt( val[ 2 ] ) >= parseInt( nextval[ 2 ] ) ) nextval[ 2 ] = parseInt( val[ 2 ] ) + 1;
515
- } else {
516
- // add to parent/child assoc array with rulevalid as key
517
- if ( self.is_empty( valarr[ val[ 2 ] ] ) ) valarr[ val[ 2 ] ] = {};
518
- valarr[ val[ 2 ] ][ template ] = val;
519
- }
520
- } );
521
- }
522
- } );
523
- // if new rule, create new parent child assoc array element with new rulevalid as key
524
- if ( isnew ) {
525
- valarr[ nextval[ 2 ] ] = {
526
- parnt: [],
527
- child: nextval
528
- };
529
- }
530
- return valarr;
531
- },
532
-
533
- /**
534
- * input_row
535
- * render individual row of inputs for a given selector/rule combination
536
- * qsid query/selector id
537
- * rule css property
538
- * seq panel id from rule/value tab
539
- * data contains all rules/values for selector
540
- * isnew is passed true when new rule is selected from menu
541
- */
542
- input_row: function( qsid, rule, seq, data, isnew ) {
543
- //console.log( 'in input_row' );
544
- var self = this,
545
- html = '';
546
- if ( !self.is_empty( data ) && !self.is_empty( data.value ) && !self.is_empty( data.value[ rule ] ) ) {
547
- var value = data.value[ rule ],
548
- valarr = self.merge_ruleval_arrays( rule, value, isnew );
549
- $.each( valarr, function( ndx, val ) {
550
- var pval = self.decode_value( rule, self.is_empty( val.parnt ) ? '' : val.parnt[ 0 ] ),
551
- pimp = self.is_empty( val.parnt ) || 0 == val.parnt[ 1 ] ? 0 : 1,
552
- cval = self.decode_value( rule, self.is_empty( val.child ) ? '' : val.child[ 0 ] ),
553
- cimp = self.is_empty( val.child ) || 0 == val.child[ 1 ] ? 0 : 1;
554
- html += '<div class="ctc-' + ( 'ovrd' == seq ? 'input' : 'selector' ) + '-row clearfix"><div class="ctc-input-cell">';
555
- if ( 'ovrd' == seq ) {
556
- html += rule.replace( /\d+/g, self.from_ascii );
557
- } else {
558
- html += data.selector + '<br/><a href="#" class="ctc-selector-edit"'
559
- + ' id="ctc_selector_edit_' + qsid + '" >' + self.getxt( 'edit' ) + '</a> '
560
- + ( self.is_empty( pval.orig ) ? self.getxt( 'child_only' ) : '' );
561
- }
562
- html += '</div><div class="ctc-parent-value ctc-input-cell"' + ( 'ovrd' != seq ? ' style="display:none"' : '' )
563
- + ' id="ctc_' + seq + '_parent_' + rule + '_' + qsid + '_' + ndx + '">'
564
- + ( self.is_empty( pval.orig ) ? '[no value]' : pval.orig + ( pimp ? self.getxt( 'important' ) : '' ) )
565
- + '</div><div class="ctc-input-cell">';
566
- if ( !self.is_empty( pval.names ) ) {
567
- $.each( pval.names, function( namendx, newname ) {
568
- newname = ( self.is_empty( newname ) ? '' : newname );
569
- html += '<div class="ctc-child-input-cell clear">';
570
- var id = 'ctc_' + seq + '_child_' + rule + '_' + qsid + '_' + ndx + newname,
571
- newval;
572
- if ( false === ( newval = cval.values.shift() ) ) {
573
- newval = '';
574
- }
575
-
576
- html += ( self.is_empty( newname ) ? '' : self.getxt( newname ) + ':<br/>' )
577
- + '<input type="text" id="' + id + '" name="' + id + '" class="ctc-child-value'
578
- + ( ( newname + rule ).toString().match( /color/ ) ? ' color-picker' : '' )
579
- + ( ( newname ).toString().match( /url/ ) ? ' ctc-input-wide' : '' )
580
- + '" value="' + self.esc_quot( newval ) + '" /></div>';
581
- } );
582
- var impid = 'ctc_' + seq + '_child_' + rule + '_i_' + qsid + '_' + ndx;
583
- html += '<label for="' + impid + '"><input type="checkbox"'
584
- + ' id="' + impid + '" name="' + impid + '" value="1" '
585
- + ( cimp ? 'checked' : '' ) + ' />'
586
- + self.getxt( 'important' ) + '</label>';
587
- }
588
- html += '</div>';
589
- if ( 'ovrd' != seq ) {
590
- html += '<div class="ctc-swatch ctc-specific"'
591
- + ' id="ctc_child_' + rule + '_' + qsid + '_' + ndx + '_swatch">'
592
- + self.getxt( 'swatch' ) + '</div>'
593
- + '<div class="ctc-child-input-cell ctc-button-cell"'
594
- + ' id="ctc_save_' + rule + '_' + qsid + '_' + ndx + '_cell">'
595
- + '<input type="button" class="button ctc-save-input"'
596
- + ' id="ctc_save_' + rule + '_' + qsid + '_' + ndx + '"'
597
- + ' name="ctc_save_' + rule + '_' + qsid + '_' + ndx + '"'
598
- + ' value="Save" /></div>';
599
- }
600
- html += '</div><!-- end input row -->' + "\n";
601
- } );
602
- }
603
- return html;
604
- },
605
-
606
- scrolltop: function() {
607
- $('html, body, .ctc-option-panel-container').animate( { scrollTop: 0 } );
608
- },
609
-
610
- css_preview: function( theme ) {
611
- var self = this,
612
- theme;
613
- //console.log( 'css_preview: ' + theme );
614
- if ( !( theme = theme.match( /(child|parnt)/ )[ 1 ] ) ) {
615
- theme = 'child';
616
- }
617
- // retrieve raw stylesheet ( parent or child )
618
- self.query_css( 'preview', theme );
619
- },
620
-
621
- /**
622
- * The "setup" functions initialize jQuery UI widgets
623
- */
624
- setup_iris: function( obj ) {
625
- // deprecated: using spectrum for alpha support
626
- var self = this;
627
- self.setup_spectrum( obj );
628
- },
629
-
630
- setup_spectrum: function( obj ) {
631
- var self = this,
632
- colortxt = $( obj ).attr( 'id' ) + '_colortxt',
633
- palette = !self.is_empty( ctcAjax.palette );
634
- try {
635
- $( obj ).spectrum( {
636
- showInput: true,
637
- allowEmpty: true,
638
- showAlpha: true,
639
- showInitial: true,
640
- preferredFormat: "hex", // 'name', //
641
- clickoutFiresChange: true,
642
- move: function( color ) {
643
- $( obj ).data( 'color', color );
644
- self.coalesce_inputs( obj );
645
- },
646
- showPalette: palette ? true : false,
647
- showSelectionPalette: palette ? true : false,
648
- palette: [ ],
649
- maxSelectionSize: 36,
650
- localStorageKey: "ctc-palette." + ctcAjax.child,
651
- hideAfterPaletteSelect: true,
652
- } ).on( 'change', function( e ){
653
- var color = $( this ).spectrum( 'get' );
654
- //console.log( 'color change: ' + color );
655
- self.coalesce_inputs( this );
656
- } ).on( 'keyup', function( e ) {
657
- // update spectrum ui to match text input after half-second delay
658
- var $this = this,
659
- $val = $( this ).val();
660
- clearTimeout( $( this ).data( 'spectrumTimer' ) );
661
- $( this ).data( 'spectrumTimer', setTimeout(
662
- function() {
663
- self.coalesce_inputs( $this );
664
- $( $this ).spectrum( 'set', $val );
665
-
666
- },
667
- 500
668
- ) );
669
- } );
670
-
671
- } catch ( exn ) {
672
- self.jquery_exception( exn, 'Spectrum Color Picker' );
673
- }
674
- },
675
-
676
- color_text: function( color ) {
677
- var self = this;
678
- if ( self.is_empty( color ) ) {
679
- return '';
680
- } else if ( color.getAlpha() < 1 ) {
681
- return color.toRgbString();
682
- } else {
683
- return color.toHexString();
684
- }
685
- },
686
-
687
- setup_query_menu: function() {
688
- var self = this;
689
- //console.log( 'setup_query_menu' );
690
- try {
691
- $( '#ctc_sel_ovrd_query' ).autocomplete( {
692
- source: self.get_queries,
693
- minLength: 0,
694
- selectFirst: true,
695
- autoFocus: true,
696
- select: function( e, ui ) {
697
- self.set_query( ui.item.value );
698
- return false;
699
- },
700
- focus: function( e ) {
701
- e.preventDefault();
702
- }
703
- } ).data( 'menu' , {} );
704
- } catch ( exn ) {
705
- self.jquery_exception( exn, 'Query Menu' );
706
- }
707
- },
708
-
709
- setup_selector_menu: function() {
710
- var self = this;
711
- //console.log( 'setup_selector_menu' );
712
- try {
713
- $( '#ctc_sel_ovrd_selector' ).autocomplete( {
714
- source: self.get_selectors,
715
- selectFirst: true,
716
- autoFocus: true,
717
- select: function( e, ui ) {
718
- self.set_selector( ui.item.value, ui.item.label );
719
- return false;
720
- },
721
- focus: function( e ) {
722
- e.preventDefault();
723
- }
724
- } ).data( 'menu' , {} );
725
- } catch ( exn ) {
726
- self.jquery_exception( exn, 'Selector Menu' );
727
- }
728
- },
729
-
730
- setup_rule_menu: function() {
731
- var self = this;
732
- //console.log( 'setup_rule_menu' );
733
- try {
734
- $( '#ctc_rule_menu' ).autocomplete( {
735
- source: self.get_rules,
736
- //minLength: 0,
737
- selectFirst: true,
738
- autoFocus: true,
739
- select: function( e, ui ) {
740
- self.set_rule( ui.item.value, ui.item.label );
741
- return false;
742
- },
743
- focus: function( e ) {
744
- e.preventDefault();
745
- }
746
- } ).data( 'menu' , {} );
747
- } catch ( exn ) {
748
- self.jquery_exception( exn, 'Property Menu' );
749
- }
750
- },
751
-
752
- setup_new_rule_menu: function() {
753
- var self = this;
754
- try {
755
- $( '#ctc_new_rule_menu' ).autocomplete( {
756
- source: self.get_filtered_rules,
757
- //minLength: 0,
758
- selectFirst: true,
759
- autoFocus: true,
760
- select: function( e, ui ) {
761
- //console.log( 'new rule selected' );
762
- e.preventDefault();
763
- var newrule = ui.item.label.replace( /[^\w\-]/g, self.to_ascii ),
764
- n = 1,
765
- row,
766
- first;
767
- //console.log( 'current qsdata before:' );
768
- //console.log( self.current_qsdata );
769
- if ( self.is_empty( self.current_qsdata.value ) ) {
770
- self.current_qsdata.value = {};
771
- }
772
- if ( self.is_empty( self.current_qsdata.value[ ui.item.label ] ) ) {
773
- self.current_qsdata.value[ ui.item.label ] = {};
774
- }
775
- if ( self.is_empty( self.current_qsdata.value[ ui.item.label ].child ) ) {
776
- self.current_qsdata.value[ ui.item.label ].child = [];
777
- }
778
- //console.log( 'current qsdata after:' );
779
- //console.log( self.current_qsdata );
780
- // seed current qsdata with new blank value with id 1
781
- // this will be modified during input_row function to be next id in order
782
- self.current_qsdata.value[ ui.item.label ].child.push( [ '', 0, 1, 1 ] );
783
- row = $( self.input_row( self.current_qsid, newrule, 'ovrd', self.current_qsdata, true ) );
784
- $( '#ctc_sel_ovrd_rule_inputs' ).append( row );
785
- $( '#ctc_new_rule_menu' ).val( '' );
786
-
787
- row.find( 'input[type="text"]' ).each( function( ndx, el ) {
788
- if (! first) first = el;
789
- if ( $( el ).hasClass( 'color-picker' ) )
790
- self.setup_spectrum( el );
791
- } );
792
- if ( first )
793
- $( first ).focus();
794
- if ( self.jquery_err.length )
795
- self.jquery_notice( 'setup_new_rule_menu' );
796
- return false;
797
- },
798
- focus: function( e ) {
799
- e.preventDefault();
800
- }
801
- } ).data( 'menu' , {} );
802
- } catch ( exn ) {
803
- self.jquery_exception( exn, 'New Property Menu' );
804
- }
805
- },
806
-
807
- set_existing: function() {
808
- var self = this;
809
- if ( $( '#ctc_theme_child' ).length && $( '#ctc_child_type_existing' ).is( ':checked' ) ) {
810
- var child = $( '#ctc_theme_child' ).val();
811
- if ( !self.is_empty( child ) ) {
812
- $( '#ctc_child_name' ).val( ctcAjax.themes.child[ child ].Name );
813
- $( '#ctc_child_author' ).val( ctcAjax.themes.child[ child ].Author );
814
- $( '#ctc_child_version' ).val( ctcAjax.themes.child[ child ].Version );
815
- $( '#ctc_child_authoruri' ).val( ctcAjax.themes.child[ child ].AuthorURI );
816
- $( '#ctc_child_themeuri' ).val( ctcAjax.themes.child[ child ].ThemeURI );
817
- $( '#ctc_child_descr' ).val( ctcAjax.themes.child[ child ].Descr );
818
- $( '#ctc_child_tags' ).val( ctcAjax.themes.child[ child ].Tags );
819
- $( '#ctc_duplicate_theme' ).prop( 'checked', false );
820
- $( '#ctc_duplicate_theme_slug' ).val( '' );
821
- $( '#input_row_duplicate_theme' ).show();
822
- }
823
- }
824
- },
825
-
826
- set_notice: function( noticearr ) {
827
- var self = this,
828
- errorHtml = '';
829
- if ( !self.is_empty( noticearr ) ) {
830
- $.each( noticearr, function( type, list ) {
831
- errorHtml += '<div class="' + type + '"><ul>' + "\n";
832
- $( list ).each( function( ndx, el ) {
833
- errorHtml += '<li>' + el.toString() + '</li>' + "\n";
834
- } );
835
- errorHtml += '</ul></div>';
836
- } );
837
- }
838
- $( '#ctc_error_notice' ).html( errorHtml );
839
- $( 'html, body' ).animate( { scrollTop: 0 }, 'slow' );
840
- },
841
-
842
- set_parent_menu: function( obj ) {
843
- $( '#ctc_theme_parnt' ).parents( '.ctc-input-row' ).first()
844
- .append( '<span class="ctc-status-icon spinner"></span>' );
845
- $( '.spinner' ).show();
846
- document.location='?page=' + ctcAjax.page + '&ctc_parent=' + obj.value;
847
- },
848
-
849
- set_child_menu: function( obj ) {
850
- var self = this,
851
- template,
852
- parent;
853
- if ( !self.is_empty( ctcAjax.themes.child[ obj.value ] ) ) {
854
- template = ctcAjax.themes.child[ obj.value ].Template,
855
- parent = $( '#ctc_theme_parnt' ).val();
856
- //console.log( 'template: ' + template + ' parent: ' + parent );
857
- if ( template == parent ) {
858
- $( '#ctc_child_name' ).val( ctcAjax.themes.child[ obj.value ].Name );
859
- $( '#ctc_child_author' ).val( ctcAjax.themes.child[ obj.value ].Author );
860
- $( '#ctc_child_version' ).val( ctcAjax.themes.child[ obj.value ].Version );
861
- } else {
862
- $( '#ctc_theme_child' ).parents( '.ctc-input-row' ).first()
863
- .append( '<span class="ctc-status-icon spinner"></span>' );
864
- $( '.spinner' ).show();
865
- document.location='?page=' + ctcAjax.page + '&ctc_parent=' + template + '&ctc_child=' + obj.value;
866
- }
867
- }
868
- },
869
-
870
- set_query: function( value ) {
871
- var self = this;
872
- if ( self.is_empty( value ) ) return false;
873
- //console.log( 'set_query: ' + value );
874
- self.current_query = value;
875
- $( '#ctc_sel_ovrd_query' ).val( '' );
876
- $( '#ctc_sel_ovrd_query_selected' ).text( value );
877
- $( '#ctc_sel_ovrd_selector' ).val( '' );
878
- $( '#ctc_sel_ovrd_selector_selected' ).html( '&nbsp;' );
879
- //$( '#ctc_sel_ovrd_rule_inputs' ).html( '' );
880
- self.load_selectors();
881
- self.scrolltop();
882
- },
883
-
884
- set_selector: function( value, label ) {
885
- var self = this;
886
- if ( self.is_empty( value ) ) return false;
887
- //console.log( 'set_selector: ' + value + ' label: ' + label );
888
- $( '#ctc_sel_ovrd_selector' ).val( '' );
889
- self.current_qsid = value;
890
- self.reload_menus = false;
891
- self.load_selector_values();
892
- self.scrolltop();
893
- },
894
-
895
- set_rule: function( value, label ) {
896
- //console.log( 'set_rule: ' + value + ' label: ' + label );
897
- var self = this;
898
- if ( self.is_empty( value ) ) return false;
899
- $( '#ctc_rule_menu' ).val( '' );
900
- $( '#ctc_rule_menu_selected' ).text( label );
901
- $( '.ctc-rewrite-toggle' ).text( self.getxt( 'rename' ) );
902
- $( '#ctc_rule_value_inputs, #ctc_input_row_rule_header' ).show();
903
- // retrieve unique values by rule
904
- self.query_css( 'rule_val', value );
905
- self.scrolltop();
906
- },
907
-
908
- set_qsid: function( obj ) {
909
- var self = this;
910
- //console.log( 'set_qsid: ' + $( obj ).attr( 'id' ) );
911
- self.current_qsid = $( obj ).attr( 'id' ).match( /_(\d+)$/ )[ 1 ];
912
- self.focus_panel( '#query_selector_options' );
913
- self.reload_menus = true;
914
- self.load_selector_values();
915
- },
916
-
917
- /**
918
- * slurp website home page and parse header for linked stylesheets
919
- * set these to be parsed as "default" stylesheets
920
- */
921
- set_addl_css: function() {
922
- //console.log( 'set_addl_css' );
923
- var self = this,
924
- template = $( '#ctc_theme_parnt' ).val(),
925
- theme_uri = ctcAjax.theme_uri.replace( /^https?:\/\//, '' ),
926
- homeurl = ctcAjax.homeurl.replace( /^https?/, ctcAjax.ssl ? 'https' : 'http' ),
927
- url = homeurl + '&template=' + template + '&stylesheet=' + template,
928
- regex = new RegExp( "<link rel=[\"']stylesheet[\"'][^>]+?"
929
- + theme_uri + '/' + template + '/(.+?\\.css)[^>]+?>', 'g' ),
930
- additional;
931
- if ( self.is_empty( template ) ) return;
932
- //console.log( template );
933
- if ( template != ctcAjax.parnt ) {
934
- $.get( url, function( data ) {
935
- //console.log( data );
936
- while ( additional = regex.exec( data ) ) {
937
- //console.log( additional );
938
- if ( 'style.css' == additional[ 1 ] ) break; // bail after main stylesheet
939
- if ( additional[ 1 ].match( /bootstrap/ ) ) continue; // don't autoselect Bootstrap stylesheets
940
- $( '.ctc_checkbox' ).each( function( ndx, el ) {
941
- if ( $( this ).val() == additional[ 1 ] ) $( this ).prop( 'checked', true );
942
- } );
943
- }
944
- data = null; // send page to garbage
945
- } );
946
- } else {
947
- //console.log('existing... using addl_css array');
948
- $( ctcAjax.addl_css ).each( function( ndx, el ) {
949
- $( '#ctc_stylesheet_files .ctc_checkbox' ).each( function( index, elem ) {
950
- if ( $( this ).val() == el ) $( this ).prop( 'checked', true );
951
- } );
952
- } );
953
- }
954
- },
955
-
956
- /**
957
- * Retrieve data from server and execute callback on completion
958
- */
959
- query_css: function( obj, key, params ) {
960
- //console.log( 'query_css: ' + obj + ' key: ' + key );
961
- var self = this,
962
- postdata = { 'ctc_query_obj' : obj, 'ctc_query_key': key },
963
- status_sel = '#ctc_status_' + obj + ( 'val_qry' == obj ? '_' + key : '' );
964
-
965
- if ( 'object' === typeof params ) {
966
- $.each( params, function( key, val ) {
967
- postdata[ 'ctc_query_' + key ] = val;
968
- } );
969
- }
970
- $( '.query-icon,.ctc-status-icon' ).remove();
971
- //console.log( status_sel + ' ' + $( status_sel ).length );
972
- $( status_sel + ' .ctc-status-icon' ).remove();
973
- $( status_sel ).append( '<span class="ctc-status-icon spinner query-icon"></span>' );
974
- $( '.spinner' ).show();
975
- // add wp ajax action to array
976
- //console.log( $( '#ctc_action' ).val() );
977
- postdata[ 'action' ] = ( !self.is_empty( $( '#ctc_action' ).val() )
978
- && 'plugin' == $( '#ctc_action' ).val() ) ?
979
- 'ctc_plgqry' : 'ctc_query';
980
- postdata[ '_wpnonce' ] = $( '#_wpnonce' ).val();
981
- // ajax post input data
982
- //console.log( 'query_css postdata:' );
983
- //console.log( postdata );
984
- self.ajax_post( obj, postdata );
985
- },
986
- /**
987
- * Post data to server for saving and execute callback on completion
988
- */
989
- save: function( obj ) {
990
- //console.log( 'save: ' + $( obj ).attr( 'id' ) );
991
- var self = this,
992
- url = ctcAjax.ajaxurl, // get ajax url from localized object
993
- postdata = {},
994
- $selector, $query, $imports, $rule,
995
- id = $( obj ).attr( 'id' ), newsel, origsel;
996
-
997
- // disable the button until ajax returns
998
- $( obj ).prop( 'disabled', true );
999
- // clear previous success/fail icons
1000
- $( '.ctc-query-icon,.ctc-status-icon' ).remove();
1001
- // show spinner
1002
- $( obj ).parent( '.ctc-textarea-button-cell, .ctc-button-cell' )
1003
- .append( '<span class="ctc-status-icon spinner save-icon"></span>' );
1004
- if ( id.match( /ctc_configtype/ ) ) {
1005
- $( obj ).parents( '.ctc-input-row' ).first()
1006
- .append( '<span class="ctc-status-icon spinner save-icon"></span>' );
1007
- postdata[ 'ctc_configtype' ] = $( obj ).val();
1008
- } else if ( ( $selector = $( '#ctc_new_selectors' ) )
1009
- && 'ctc_save_new_selectors' == $( obj ).attr( 'id' ) ) {
1010
- postdata[ 'ctc_new_selectors' ] = $selector.val();
1011
- if ( $query = $( '#ctc_sel_ovrd_query_selected' ) ) {
1012
- postdata[ 'ctc_sel_ovrd_query' ] = $query.text();
1013
- }
1014
- self.reload_menus = true;
1015
- } else if ( ( $imports = $( '#ctc_child_imports' ) )
1016
- && 'ctc_save_imports' == id ) {
1017
- postdata[ 'ctc_child_imports' ] = $imports.val();
1018
- } else if ( 'ctc_is_debug' == id ) {
1019
- postdata[ 'ctc_is_debug' ] = $( '#ctc_is_debug' ).is( ':checked' ) ? 1 : 0;
1020
- } else {
1021
- // coalesce inputs
1022
- postdata = self.coalesce_inputs( obj );
1023
- }
1024
- $( '.save-icon' ).show();
1025
- // add rename selector value if it exists
1026
- $( '#ctc_sel_ovrd_selector_selected' )
1027
- .find( '#ctc_rewrite_selector' ).each( function() {
1028
- newsel = $( '#ctc_rewrite_selector' ).val();
1029
- origsel = $( '#ctc_rewrite_selector_orig' ).val();
1030
- if ( self.is_empty( newsel ) || !newsel.toString().match( /\w/ ) ) {
1031
- newsel = origsel;
1032
- } else {
1033
- postdata[ 'ctc_rewrite_selector' ] = newsel;
1034
- self.reload_menus = true;
1035
- }
1036
- $( '.ctc-rewrite-toggle' ).text( self.getxt( 'rename' ) );
1037
- $( '#ctc_sel_ovrd_selector_selected' ).html( newsel );
1038
- } );
1039
- // add wp ajax action to array
1040
- //console.log( $( '#ctc_action' ).val() );
1041
- postdata[ 'action' ] = ( !self.is_empty( $( '#ctc_action' ).val() )
1042
- && 'plugin' == $( '#ctc_action' ).val() ) ?
1043
- 'ctc_plugin' : 'ctc_update';
1044
- postdata[ '_wpnonce' ] = $( '#_wpnonce' ).val();
1045
- //console.log( postdata );
1046
- // ajax post input data
1047
- self.ajax_post( 'qsid', postdata );
1048
- },
1049
-
1050
- ajax_post: function( obj, data, datatype ) {
1051
- var self = this,
1052
- url = ctcAjax.ajaxurl;
1053
- //console.log( 'ajax_post: ' + obj );
1054
- //console.log( data );
1055
- // get ajax url from localized object
1056
- $.ajax( {
1057
- url: url,
1058
- data: data,
1059
- dataType: ( self.is_empty( datatype ) ? 'json' : datatype ),
1060
- // 'ctc_update' == data.action && // 'rule_val' == obj ? 'text' : // 'qsid' == obj ? 'text' :
1061
- // 'ctc_update' == data.action && 'qsid' == obj ? 'text' :
1062
- type: 'POST'
1063
- } ).done( function( response ) {
1064
- //console.log( response );
1065
- self.handle_success( obj, response );
1066
- } ).fail( function() {
1067
- self.handle_failure( obj );
1068
- } );
1069
- },
1070
-
1071
- handle_failure: function( obj ) {
1072
- var self = this;
1073
- //console.log( 'handle_failure: ' + obj );
1074
- $( '.query-icon, .save-icon' ).removeClass( 'spinner' ).addClass( 'failure' );
1075
- $( 'input[type=submit], input[type=button], input[type=checkbox],.ctc-delete-input' ).prop( 'disabled', false );
1076
- $( '.ajax-pending' ).removeClass( 'ajax-pending' );
1077
- //FIXME: return fail text in ajax response
1078
- if ( 'preview' == obj )
1079
- $( '#view_parnt_options_panel,#view_child_options_panel' )
1080
- .text( self.getxt( 'css_fail' ) );
1081
- },
1082
-
1083
- handle_success: function( obj, response ) {
1084
- var self = this;
1085
- // query response
1086
- //console.log( 'handle_success: ' + obj );
1087
- //console.log( response );
1088
- // hide spinner
1089
- $( '.query-icon, .save-icon' ).removeClass( 'spinner' );
1090
- $( '.ajax-pending' ).removeClass( 'ajax-pending' );
1091
- // hide spinner
1092
- if ( self.is_empty( response ) ) {
1093
- self.handle_failure( obj );
1094
- } else {
1095
- $( '#ctc_new_selectors' ).val( '' );
1096
- // update data objects
1097
- // show check mark
1098
- // FIXME: distinction between save and query, update specific status icon
1099
- $( '.query-icon, .save-icon' ).addClass( 'success' );
1100
- $( 'input[type=submit], input[type=button], input[type=checkbox],.ctc-delete-input' ).prop( 'disabled', false );
1101
- // update ui from each response object
1102
- $( response ).each( function() {
1103
- if ( 'function' == typeof self.update[ this.obj ] ) {
1104
- //console.log( 'executing method update.' + this.obj );
1105
- self.update[ this.obj ].call( self, this );
1106
- } else {
1107
- //console.log( 'Fail: no method update.' + this.obj );
1108
- }
1109
- } );
1110
- }
1111
- },
1112
-
1113
- jquery_exception: function( exn, type ) {
1114
- var self = this,
1115
- ln = self.is_empty( exn.lineNumber ) ? '' : ' line: ' + exn.lineNumber,
1116
- fn = self.is_empty( exn.fileName ) ? '' : ' ' + exn.fileName.split( /\?/ )[ 0 ];
1117
- self.jquery_err.push( '<code><small>' + type + ': ' + exn.message + fn + ln + '</small></code>' );
1118
- },
1119
-
1120
- jquery_notice: function( fn ) {
1121
- //console.log( fn );
1122
- var self = this,
1123
- culprits = [],
1124
- errors = [];
1125
- // disable form submits
1126
- $( 'input[type=submit], input[type=button]' ).prop( 'disabled', true );
1127
- $( 'script' ).each( function( ndx,el ){
1128
- var url = $( this ).prop( 'src' );
1129
- if ( !self.is_empty( url ) && url.match( /jquery(\.min|\.js|\-?ui)/i )
1130
- && ! url.match( /load\-scripts.php/ ) ) {
1131
- culprits.push( '<code><small>' + url.split( /\?/ )[ 0 ] + '</small></code>' );
1132
- }
1133
- } );
1134
- errors.push( '<strong>' + self.getxt( 'js' ) + '</strong> ' + self.getxt( 'contact' ) );
1135
- //if ( 1 == ctcAjax.is_debug ) {
1136
- errors.push( self.jquery_err.join( '<br/>' ) );
1137
- //}
1138
- if ( culprits.length ) {
1139
- errors.push( self.getxt( 'jquery' ) + '<br/>' + culprits.join( '<br/>' ) );
1140
- }
1141
- errors.push( self.getxt( 'plugin' ) );
1142
- self.set_notice( { 'error': errors } );
1143
- },
1144
-
1145
- update: {
1146
- // render individual selector inputs on Query/Selector tab
1147
- qsid: function( res ) {
1148
- //console.log( res );
1149
- var self = this,
1150
- id, html, val, selector, empty;
1151
- self.current_qsid = res.key;
1152
- self.current_qsdata = res.data;
1153
- //console.log( 'update.qsid: ' + self.current_qsid );
1154
- $( '#ctc_sel_ovrd_qsid' ).val( self.current_qsid );
1155
- if ( self.is_empty( self.current_qsdata.seq ) ) {
1156
- $( '#ctc_child_load_order_container' ).empty();
1157
- } else {
1158
- id = 'ctc_ovrd_child_seq_' + self.current_qsid;
1159
- val = parseInt( self.current_qsdata.seq );
1160
- html = '<input type="text" id="' + id + '" name="' + id + '"'
1161
- + ' class="ctc-child-value" value="' + val + '" />';
1162
- $( '#ctc_child_load_order_container' ).html( html );
1163
- }
1164
- if ( self.is_empty( self.current_qsdata.value ) ) {
1165
- //console.log( 'qsdata is empty' );
1166
- empty = true;
1167
- $( '#ctc_sel_ovrd_rule_inputs' ).empty();
1168
- } else {
1169
- //console.log( 'qsdata NOT empty' );
1170
- empty = false;
1171
- html = '';
1172
- $.each( self.current_qsdata.value, function( rule, value ) {
1173
- html += self.input_row( self.current_qsid, rule, 'ovrd', self.current_qsdata );
1174
- } );
1175
- $( '#ctc_sel_ovrd_rule_inputs' ).html( html ).find( '.color-picker' ).each( function() {
1176
- self.setup_spectrum( this );
1177
- } );
1178
- self.coalesce_inputs( '#ctc_child_all_0_swatch' );
1179
- }
1180
- if ( self.jquery_err.length ) {
1181
- self.jquery_notice( 'update.qsid' );
1182
- } else {
1183
- //console.log( 'reload menus: ' + ( self.reload_menus ? 'true' : 'false' ) );
1184
- if ( self.reload_menus ) {
1185
- self.load_queries();
1186
- self.set_query( self.current_qsdata.query );
1187
- self.load_rules();
1188
- }
1189
- $( '#ctc_sel_ovrd_selector_selected' ).text( self.current_qsdata.selector );
1190
- $( '.ctc-rewrite-toggle' ).text( self.getxt( 'rename' ) );
1191
- $( '.ctc-rewrite-toggle' ).show();
1192
- if ( !empty ){
1193
- $( '#ctc_sel_ovrd_rule_header,'
1194
- + '#ctc_sel_ovrd_new_rule,'
1195
- + '#ctc_sel_ovrd_rule_inputs_container,'
1196
- + '#ctc_sel_ovrd_rule_inputs' ).show();
1197
- } else {
1198
- $( '#ctc_sel_ovrd_rule_header,'
1199
- + '#ctc_sel_ovrd_new_rule,'
1200
- + '#ctc_sel_ovrd_rule_inputs_container,'
1201
- + '#ctc_sel_ovrd_rule_inputs' ).hide();
1202
- }
1203
- //self.scrolltop();
1204
- }
1205
- },
1206
- // render list of unique values for given rule on Property/Value tab
1207
- rule_val: function( res ) {
1208
- //console.log( 'update.rule_val: ' + res.key );
1209
- //console.log( res.data );
1210
- var self = this,
1211
- rule = $( '#ctc_rule_menu_selected' ).text(),
1212
- html = '<div class="ctc-input-row clearfix" id="ctc_rule_row_' + rule + '">' + "\n";
1213
- //console.log( 'rule: ' + rule );
1214
- if ( !self.is_empty( res.data ) ) {
1215
- $.each( res.data, function( valid, value ) {
1216
- var parentObj = self.decode_value( rule, value );
1217
- html += '<div class="ctc-parent-row clearfix"'
1218
- + ' id="ctc_rule_row_' + rule + '_' + valid + '">' + "\n"
1219
- + '<div class="ctc-input-cell ctc-parent-value"'
1220
- + ' id="ctc_' + valid + '_parent_' + rule + '_' + valid + '">'
1221
- + parentObj.orig + '</div>' + "\n"
1222
- + '<div class="ctc-input-cell">' + "\n"
1223
- + '<div class="ctc-swatch ctc-specific"'
1224
- + ' id="ctc_' + valid + '_parent_' + rule + '_' + valid + '_swatch">'
1225
- + self.getxt( 'swatch' ) + '</div></div>' + "\n"
1226
- + '<div class="ctc-input-cell">'
1227
- + '<a href="#" class="ctc-selector-handle"'
1228
- + ' id="ctc_selector_' + rule + '_' + valid + '">'
1229
- + self.getxt( 'selector' ) + '</a></div>' + "\n"
1230
- + '<div id="ctc_selector_' + rule + '_' + valid + '_container"'
1231
- + ' class="ctc-selector-container">' + "\n"
1232
- + '<a href="#" id="ctc_selector_' + rule + '_' + valid + '_close"'
1233
- + ' class="ctc-selector-handle ctc-exit" title="'
1234
- + self.getxt( 'close' ) + '"></a>'
1235
- + '<div id="ctc_selector_' + rule + '_' + valid + '_inner_container"'
1236
- + ' class="ctc-selector-inner-container clearfix">' + "\n"
1237
- + '<div id="ctc_status_val_qry_' + valid + '"></div>' + "\n"
1238
- + '<div id="ctc_selector_' + rule + '_' + valid + '_rows"></div>' + "\n"
1239
- + '</div></div></div>' + "\n";
1240
- } );
1241
- html += '</div>' + "\n";
1242
- }
1243
- $( '#ctc_rule_value_inputs' ).html( html ).find( '.ctc-swatch' ).each( function() {
1244
- self.coalesce_inputs( this );
1245
- } );
1246
- },
1247
- // render list of selectors grouped by query for given value on Property/Value Tab
1248
- val_qry: function( res ) {
1249
- var self = this,
1250
- html = '';
1251
- if ( !self.is_empty( res.data ) ) {
1252
- $.each( res.data, function( rule, queries ) {
1253
- page_rule = rule;
1254
- $.each( queries, function( query, selectors ) {
1255
- html += '<h4 class="ctc-query-heading">' + query + '</h4>' + "\n";
1256
- if ( !self.is_empty( selectors ) ) {
1257
- $.each( selectors, function( qsid, qsdata ) {
1258
- html += self.input_row( qsid, rule, res.key, qsdata );
1259
- } );
1260
- }
1261
- } );
1262
- } );
1263
- }
1264
- selector = '#ctc_selector_' + rule + '_' + res.key + '_rows';
1265
- $( selector ).html( html ).find( '.color-picker' ).each( function() {
1266
- self.setup_spectrum( this );
1267
- } );
1268
- $( selector ).find( '.ctc-swatch' ).each( function() {
1269
- self.coalesce_inputs( this );
1270
- } );
1271
- if ( self.jquery_err.length ) self.jquery_notice( 'val_qry' );
1272
- },
1273
- // populate list of queries and attach to query input element
1274
- queries: function( res ) {
1275
- $( '#ctc_sel_ovrd_query' ).data( 'menu', res.data );
1276
- },
1277
- // populate list of selectors and attach to selector input element
1278
- selectors: function( res ) {
1279
- $( '#ctc_sel_ovrd_selector' ).data( 'menu', res.data );
1280
- },
1281
- // populate list of rules and attach to rule input element
1282
- rules: function( res ) {
1283
- $( '#ctc_rule_menu' ).data( 'menu', res.data );
1284
- },
1285
- // render debug output
1286
- debug: function( res ) {
1287
- $( '#ctc_debug_container' ).html( res.data );
1288
- //console.log( 'debug:' );
1289
- //console.log( res.data );
1290
- },
1291
- // render stylesheet preview on child or parent css tab
1292
- preview: function( res ) {
1293
- $( '#view_' + res.key + '_options_panel' ).text( res.data );
1294
- }
1295
-
1296
- },
1297
-
1298
- // initialize object vars, bind event listeners to elements, load menus and start plugin
1299
- init: function() {
1300
- //console.log( 'initializing...' )
1301
- var self = this;
1302
- // auto populate parent/child tab values
1303
- self.autogen_slugs();
1304
- self.set_existing();
1305
- // initialize theme menus
1306
- if ( !$( '#ctc_theme_parnt' ).is( 'input' ) ) {
1307
- //console.log( 'initializing theme select menus...' )
1308
- try {
1309
- $.widget( 'ctc.themeMenu', $.ui.selectmenu, {
1310
- _renderItem: function( ul, item ) {
1311
- var li = $( "<li>" ),
1312
- sel = item.value.replace( /[^\w\-]/, '' );
1313
- $( '#ctc_theme_option_' + sel )
1314
- .detach().appendTo( li );
1315
- return li.appendTo( ul );
1316
- }
1317
- } );
1318
- } catch( exn ) {
1319
- self.jquery_exception( exn, 'Theme Menu' );
1320
- }
1321
- try {
1322
- $( '#ctc_theme_parnt' ).themeMenu( {
1323
- select: function( event, ui ) {
1324
- self.set_parent_menu( ui.item );
1325
- }
1326
- } );
1327
- } catch( exn ) {
1328
- if ( 'function' == typeof themeMenu )
1329
- $( '#ctc_theme_parnt' ).themeMenu( 'destroy' );
1330
- else $( '#ctc_theme_parnt-button' ).remove();
1331
- self.jquery_exception( exn, 'Parent Theme Menu' );
1332
- }
1333
- if ( self.is_empty( ctcAjax.themes.child ) ) {
1334
- if ( $( '#ctc_child_name' ).length ) {
1335
- $( '#ctc_child_name' ).val( self.testname );
1336
- $( '#ctc_child_template' ).val( self.testslug );
1337
- }
1338
- } else {
1339
- try {
1340
- $( '#ctc_theme_child' ).themeMenu( {
1341
- select: function( event, ui ) {
1342
- self.set_child_menu( ui.item );
1343
- }
1344
- } );
1345
- } catch( exn ) {
1346
- if ( 'function' == typeof themeMenu )
1347
- $( '#ctc_theme_child' ).themeMenu( 'destroy' );
1348
- else $( '#ctc_theme_child-button' ).remove();
1349
- self.jquery_exception( exn, 'Child Theme Menu' );
1350
- }
1351
- }
1352
- }
1353
- if ( self.is_empty( self.jquery_err ) ){
1354
- //console.log( 'delegating event bindings...' )
1355
- $( '#ctc_main' ).on( 'click', '.ctc-selector-handle', function( e ) {
1356
- //'.ctc-option-panel-container'
1357
- e.preventDefault();
1358
- if ( $( this ).hasClass( 'ajax-pending' ) ) return false;
1359
- $( this ).addClass( 'ajax-pending' );
1360
- //set_notice( '' );
1361
- var id = $( this ).attr( 'id' ).toString().replace( '_close', '' ),
1362
- parts = id.toString().match( /_([^_]+)_(\d+)$/ );
1363
- if ( $( '#' + id + '_container' ).is( ':hidden' ) ) {
1364
- if ( !self.is_empty( parts[ 1 ] ) && !self.is_empty( parts[ 2 ] ) ) {
1365
- rule = parts[ 1 ];
1366
- valid = parts[ 2 ];
1367
- // retrieve selectors / values for individual value
1368
- self.query_css( 'val_qry', valid, { 'rule': rule } );
1369
- }
1370
- }
1371
- $( '#' + id + '_container' ).fadeToggle( 'fast' );
1372
- $( '.ctc-selector-container' ).not( '#' + id + '_container' ).fadeOut( 'fast' );
1373
- } );
1374
- $( '#ctc_main' ).on( 'click', '.ctc-save-input[type=button], .ctc-delete-input', function( e ) {
1375
- e.preventDefault();
1376
- if ( $( this ).hasClass( 'ajax-pending' ) ) return false;
1377
- $( this ).addClass( 'ajax-pending' );
1378
- self.save( this ); // refresh menus after updating data
1379
- return false;
1380
- } );
1381
- $( '#ctc_main' ).on( 'keydown', '.ctc-selector-container .ctc-child-value[type=text]', function( e ) {
1382
- if ( 13 === e.which ) {
1383
- //console.log( 'return key pressed' );
1384
- var $obj = $( this ).parents( '.ctc-selector-row' ).find( '.ctc-save-input[type=button]' ).first();
1385
- if ( $obj.length ) {
1386
- e.preventDefault();
1387
- //console.log( $obj.attr( 'id' ) );
1388
- if ( $obj.hasClass( 'ajax-pending' ) ) return false;
1389
- $obj.addClass( 'ajax-pending' );
1390
- self.save( $obj );
1391
- return false;
1392
- }
1393
- }
1394
- } );
1395
- $( '#ctc_main' ).on( 'click', '.ctc-selector-edit', function( e ) {
1396
- e.preventDefault();
1397
- if ( $( this ).hasClass( 'ajax-pending' ) ) return false;
1398
- $( this ).addClass( 'ajax-pending' );
1399
- self.set_qsid( this );
1400
- } );
1401
- $( '#ctc_main' ).on( 'click', '.ctc-rewrite-toggle', function( e ) {
1402
- e.preventDefault();
1403
- self.selector_input_toggle( this );
1404
- } );
1405
- $( '#ctc_main' ).on( 'click', '#ctc_copy_selector', function( e ) {
1406
- var txt = $( '#ctc_sel_ovrd_selector_selected' ).text().trim();
1407
- if ( !self.is_empty( txt ) )
1408
- $( '#ctc_new_selectors' ).val( $( '#ctc_new_selectors' ).val() + "\n" + txt + " {\n\n}" );
1409
- } );
1410
- $( '#ctc_configtype' ).on( 'change', function( e ) {
1411
- var val = $( this ).val();
1412
- if ( self.is_empty( val ) || 'theme' == val ) {
1413
- $( '.ctc-theme-only, .ctc-themeonly-container' ).removeClass( 'ctc-disabled' );
1414
- $( '.ctc-theme-only, .ctc-themeonly-container input' ).prop( 'disabled', false );
1415
- try {
1416
- $( '#ctc_theme_parnt, #ctc_theme_child' ).themeMenu( 'enable' );
1417
- } catch ( exn ) {
1418
- self.jquery_exception( exn, 'Theme Menu' );
1419
- }
1420
- } else {
1421
- $( '.ctc-theme-only, .ctc-themeonly-container' ).addClass( 'ctc-disabled' );
1422
- $( '.ctc-theme-only, .ctc-themeonly-container input' ).prop( 'disabled', true );
1423
- try {
1424
- $( '#ctc_theme_parnt, #ctc_theme_child' ).themeMenu( 'disable' );
1425
- } catch ( exn ) {
1426
- self.jquery_exception( exn, 'Theme Menu' );
1427
- }
1428
- }
1429
- } );
1430
- // these elements are not replaced so use direct selector events
1431
- $( '.nav-tab' ).on( 'click', function( e ) {
1432
- e.preventDefault();
1433
- // clear the notice box
1434
- //set_notice( '' );
1435
- $( '.ctc-query-icon,.ctc-status-icon' ).remove();
1436
- var id = '#' + $( this ).attr( 'id' );
1437
- self.focus_panel( id );
1438
- } );
1439
- $( '.ctc-section-toggle' ).on( 'click', function( e ) {
1440
- e.preventDefault();
1441
- $( this ).parents( '.ctc-input-row, .update-nag' ).first().find( '.ctc-section-toggle' )
1442
- .each( function() {
1443
- $( this ).toggleClass( 'open' );
1444
- } );
1445
- var id = $( this ).attr( 'id' ).replace(/\d$/, '') + '_content';
1446
- $( '#' + id ).stop().slideToggle( 'fast' );
1447
- return false;
1448
- } );
1449
- $( '#view_child_options, #view_parnt_options' ).on( 'click', function( e ){
1450
- if ( $( this ).hasClass( 'ajax-pending' ) ) return false;
1451
- $( this ).addClass( 'ajax-pending' );
1452
- self.css_preview( $( this ).attr( 'id' ) );
1453
- } );
1454
- $( '#ctc_load_form' ).on( 'submit', function() {
1455
- return ( self.validate() ); //&& confirm( self.getxt( 'load' ) ) ) ;
1456
- } );
1457
- $( '#ctc_query_selector_form' ).on( 'submit', function( e ) {
1458
- e.preventDefault();
1459
- $this = $( '#ctc_save_query_selector' );
1460
- if ( $this.hasClass( 'ajax-pending' ) ) return false;
1461
- $this.addClass( 'ajax-pending' );
1462
- self.save( $this ); // refresh menus after updating data
1463
- return false;
1464
- } );
1465
- $( '#ctc_rule_value_form' ).on( 'submit', function( e ) {
1466
- //console.log( 'rule value empty submit' );
1467
- e.preventDefault();
1468
- return false;
1469
- } );
1470
- $( '#ctc_theme_child, #ctc_theme_child-button, #ctc_child_type_existing' )
1471
- .on( 'focus click', function() {
1472
- // change the inputs to use existing child theme
1473
- $( '#ctc_child_type_existing' ).prop( 'checked', true );
1474
- $( '#ctc_child_type_new' ).prop( 'checked', false );
1475
- $( '#ctc_child_template' ).val( '' );
1476
- self.set_existing();
1477
- } );
1478
- $( '#ctc_duplicate_theme' ).on( 'click', function() {
1479
- if ( $( '#ctc_duplicate_theme' ).is( ':checked' ) ) {
1480
- $( '#ctc_child_name' ).val( self.testname );
1481
- $( '#ctc_duplicate_theme_slug' ).val( self.testslug );
1482
- } else {
1483
- self.set_existing();
1484
- }
1485
- } );
1486
- $( '#ctc_child_type_new, #ctc_child_template' ).on( 'focus click', function() {
1487
- // change the inputs to use new child theme
1488
- $( '#ctc_child_type_existing' ).prop( 'checked', false );
1489
- $( '#ctc_duplicate_theme' ).prop( 'checked', false );
1490
- $( '#ctc_duplicate_theme_slug' ).val( '' );
1491
- $( '#ctc_child_type_new' ).prop( 'checked', true );
1492
- $( '#input_row_duplicate_theme' ).hide();
1493
- $( '#ctc_child_name' ).val( self.testname );
1494
- $( '#ctc_child_template' ).val( self.testslug );
1495
- } );
1496
- $( '#ctc_is_debug' ).on( 'change', function( e ) {
1497
- self.save( this );
1498
- } );
1499
- $( '.ctc-live-preview' ).on( 'click', function( e ) {
1500
- e.stopImmediatePropagation();
1501
- e.preventDefault();
1502
- document.location = $( this ).prop( 'href' );
1503
- return false;
1504
- } );
1505
- //console.log( 'loading autoselect menus...' )
1506
- // initialize autoselect menus
1507
- self.setup_menus();
1508
- //console.log( 'checking for additional stylesheets...' )
1509
- // mark additional linked stylesheets for parsing
1510
- self.set_addl_css();
1511
- // show last 25 selectors edited
1512
- // render_recent();
1513
- // turn on submit buttons (disabled until everything is loaded to prevent errors)
1514
- //console.log( 'releasing submit buttons...' )
1515
- $( 'input[type=submit], input[type=button]' ).prop( 'disabled', false );
1516
- self.scrolltop();
1517
- //console.log( 'Ready.' )
1518
- // disappear any notices after 20 seconds
1519
- setTimeout( self.fade_update_notice, 20000 );
1520
- } else {
1521
- //$( '.ctc-select' ).css( { 'visibility': 'visible' } ).show();
1522
- self.jquery_notice( 'init' );
1523
- }
1524
- },
1525
- // object properties
1526
- testslug: '',
1527
- testname: '',
1528
- reload_menus: false,
1529
- current_query: 'base',
1530
- current_qsid: null,
1531
- current_qsdata: {},
1532
- jquery_err: [],
1533
- color_regx: '\\s+(\\#[a-f0-9]{3,6}|rgba?\\([\\d., ]+?\\)|hsla?\\([\\d%., ]+?\\)|[a-z]+)',
1534
- border_regx: '(\\w+)(\\s+(\\w+))?',
1535
- grad_regx: '(\\w+)'
1536
-
1537
- };
1538
- //console.log( 'creating new chldthmcfg object ...' );
1539
- $.chldthmcfg.init();
1540
- } ( jQuery ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/chld-thm-cfg.min.js DELETED
@@ -1 +0,0 @@
1
- !function(e){e.chldthmcfg={esc_quot:function(e){var t=this;return t.is_empty(e)?e:e.toString().replace(/"/g,"&quot;")},getxt:function(e){return(text=ctcAjax[e+"_txt"])?text:""},from_ascii:function(e){var t=parseInt(e),c=String.fromCharCode(t);return c},to_ascii:function(e){var t=e.charCodeAt(0);return t},is_empty:function(e){if("undefined"==typeof e||!1===e||null===e||""===e)return!0;if(!0===e||"string"==typeof e||"number"==typeof e)return!1;if("object"==typeof e){for(var t in e)if(e.hasOwnProperty(t))return!1;return!0}return!1},theme_exists:function(t,c){var n=!1;return e.each(ctcAjax.themes,function(i,a){return e.each(a,function(e,a){return e.toLowerCase()!==t.toLowerCase()||"parnt"!=i&&"new"!=c?void 0:(n=!0,!1)}),n?!1:void 0}),n},validate:function(){var t=this,c=/[^\w\-]/,n=e("#ctc_child_template").length?e("#ctc_child_template").val().toString().replace(c):"",i=e("#ctc_theme_child").length?e("#ctc_theme_child").val().toString().replace(c):n,a=e("input[name=ctc_child_type]:checked").val(),r=[];return"new"==a&&(i=n),t.theme_exists(i,a)&&r.push(t.getxt("theme_exists").toString().replace(/%s/,i)),""===i&&r.push(t.getxt("inval_theme")),""===e("#ctc_child_name").val()&&r.push(t.getxt("inval_name")),r.length?(t.set_notice({error:r}),!1):!0},autogen_slugs:function(){if(e("#ctc_theme_parnt").length){for(var t=this,c=e("#ctc_theme_parnt").val(),n=slugbase=c+"-child",i=ctcAjax.themes.parnt[c].Name+" Child",a="",r="",s="00";t.theme_exists(n,"new");)a=""==a?2:a+1,r=s.substring(0,s.length-a.toString().length)+a.toString(),n=slugbase+r;t.testslug=n,t.testname=i+(r.length?" "+r:"")}},focus_panel:function(t){var c=t+"_panel";e(".nav-tab").removeClass("nav-tab-active"),e(".ctc-option-panel").removeClass("ctc-option-panel-active"),e(t).addClass("nav-tab-active"),e(".ctc-option-panel-container").scrollTop(0),e(c).addClass("ctc-option-panel-active")},selector_input_toggle:function(t){var c,n=this;e("#ctc_rewrite_selector").length?(c=e("#ctc_rewrite_selector_orig").val(),e("#ctc_sel_ovrd_selector_selected").text(c),e(t).text(n.getxt("rename"))):(c=e("#ctc_sel_ovrd_selector_selected").text(),e("#ctc_sel_ovrd_selector_selected").html('<textarea id="ctc_rewrite_selector" name="ctc_rewrite_selector" autocomplete="off"></textarea><input id="ctc_rewrite_selector_orig" name="ctc_rewrite_selector_orig" type="hidden" value="'+n.esc_quot(c)+'"/>'),e("#ctc_rewrite_selector").val(c),e(t).text(n.getxt("cancel")))},fade_update_notice:function(){e(".updated, .error").slideUp("slow",function(){e(".updated").remove()})},coalesce_inputs:function(t){var c=this,n=e(t).attr("id"),i=/^(ctc_(ovrd|\d+)_(parent|child)_([0-9a-z\-]+)_(\d+?)(_(\d+))?)(_\w+)?$/,a=e(t).parents(".ctc-selector-row, .ctc-parent-row").first(),r=a.find(".ctc-swatch").first(),s={parent:{},child:{}},l={parent:{origin:"",start:"",end:""},child:{origin:"",start:"",end:""}},_={child:!1,parent:!1},o={};return a.find(".ctc-parent-value, .ctc-child-value").each(function(){var t,a,r=e(this).attr("id"),u=r.toString().match(i),d=u[2],p=u[3],h="undefined"==typeof u[4]?"":u[4],m=u[7],v=u[5],f="undefined"==typeof u[7]?"":u[8],g="parent"==p?e(this).text().replace(/!$/,""):"seq"!=h&&"ctc_delete_query_selector"==n?"":e(this).val(),y="seq"==h?!1:"ctc_"+d+"_child_"+h+"_i_"+v+"_"+m;if("child"==p&&(c.is_empty(e(this).data("color"))||(g=c.color_text(e(this).data("color")),e(this).data("color",null)),o[r]=g,y&&(o[y]=e("#"+y).is(":checked")?1:0)),""!==g)if(c.is_empty(f))if(t=h.toString().match(/^border(\-(top|right|bottom|left))?$/)&&!g.match(/none/)){var x=new RegExp(c.border_regx+c.color_regx,"i"),a=g.toString().match(x);c.is_empty(a)||(a.shift(),s[p][h+"-width"]=a.shift()||"",a.shift(),s[p][h+"-style"]=a.shift()||"",s[p][h+"-color"]=a.shift()||"")}else if("background-image"!=h||g.match(/none/))"seq"!=h&&(s[p][h]=g);else if(g.toString().match(/url\(/))s[p]["background-image"]=c.image_url(p,g);else{var w=new RegExp(c.grad_regx+c.color_regx+c.color_regx,"i"),a=g.toString().match(w);!c.is_empty(a)&&a.length>2?(a.shift(),l[p].origin=a.shift()||"top",l[p].start=a.shift()||"transparent",l[p].end=a.shift()||"transparent",_[p]=!0):s[p]["background-image"]=g}else switch(f){case"_border_width":s[p][h+"-width"]="none"==g?0:g;break;case"_border_style":s[p][h+"-style"]=g;break;case"_border_color":s[p][h+"-color"]=g;break;case"_background_url":s[p]["background-image"]=c.image_url(p,g);break;case"_background_color":s[p]["background-color"]=g;break;case"_background_color1":l[p].start=g,_[p]=!0;break;case"_background_color2":l[p].end=g,_[p]=!0;break;case"_background_origin":l[p].origin=g,_[p]=!0}}),"undefined"==typeof r||c.is_empty(r.attr("id"))||(r.removeAttr("style"),_.parent&&r.ctcgrad(l.parent.origin,[l.parent.start,l.parent.end]),r.css(s.parent),r.attr("id").toString().match(/parent/)||(_.child&&r.ctcgrad(l.child.origin,[l.child.start,l.child.end]),r.css(s.child)),r.css({"z-index":-1})),o},decode_value:function(e,t){t="undefined"==typeof t?"":t;var c=this,n={orig:t,names:[""],values:[t]};if(e.toString().match(/^border(\-(top|right|bottom|left))?$/)){var i=new RegExp(c.border_regx+"("+c.color_regx+")?","i"),a=t.toString().match(i);c.is_empty(a)&&(a=[]),n.names=["_border_width","_border_style","_border_color"],orig=a.shift(),n.values[0]=a.shift()||"",a.shift(),n.values[1]=a.shift()||"",a.shift(),n.values[2]=a.shift()||""}else if(e.toString().match(/^background\-image/))if(n.names=["_background_url","_background_origin","_background_color1","_background_color2"],n.values=["","","",""],c.is_empty(t)||t.toString().match(/(url|none)/))n.values[0]=t;else{var r,s,a=t.toString().split(/:/);n.values[1]=a.shift()||"",n.values[2]=a.shift()||"",r=a.shift()||"",n.values[3]=a.shift()||"",s=a.shift()||"",n.orig=[n.values[1],n.values[2],n.values[3]].join(" ")}return n},image_url:function(e,t){var c,n=this,i=t.toString().match(/url\(['" ]*(.+?)['" ]*\)/),a=n.is_empty(i)?null:i[1],r=ctcAjax.theme_uri+"/"+("parent"==e?ctcAjax.parnt:ctcAjax.child)+"/";return a?c=a.toString().match(/^(data:|https?:|\/)/)?t:"url("+r+a+")":!1},setup_menus:function(){var e=this;e.setup_query_menu(),e.setup_selector_menu(),e.setup_rule_menu(),e.setup_new_rule_menu(),e.load_queries(),e.load_rules(),e.set_query(e.current_query)},load_queries:function(){var e=this;e.query_css("queries",null)},load_selectors:function(){var e=this;e.query_css("selectors",e.current_query)},load_rules:function(){var e=this;e.query_css("rules",null)},load_selector_values:function(){var e=this;e.query_css("qsid",e.current_qsid)},get_queries:function(t,c){var n=[],i=new RegExp(e.ui.autocomplete.escapeRegex(t.term),"i");e.chldthmcfg.is_empty(this.element.data("menu"))?n.push({label:ctcAjax.nosels_txt,value:null}):e.each(this.element.data("menu"),function(e,t){i.test(t)&&n.push({label:t,value:t})}),c(n)},get_selectors:function(t,c){var n=[],i=new RegExp(e.ui.autocomplete.escapeRegex(t.term),"i");e.chldthmcfg.is_empty(this.element.data("menu"))?n.push({label:ctcAjax.nosels_txt,value:null}):e.each(this.element.data("menu"),function(e,t){i.test(e)&&n.push({label:e,value:t})}),c(n)},get_rules:function(t,c){var n=[],i=new RegExp(e.ui.autocomplete.escapeRegex(t.term),"i");e.chldthmcfg.is_empty(this.element.data("menu"))?n.push({label:ctcAjax.nosels_txt,value:null}):e.each(this.element.data("menu"),function(e,t){i.test(e)&&n.push({label:e,value:t})}),c(n)},get_filtered_rules:function(t,c){var n=[],i=new RegExp(e.ui.autocomplete.escapeRegex(t.term),"i");e.chldthmcfg.is_empty(this.element.data("menu"))?n.push({label:ctcAjax.nosels_txt,value:null}):e.each(e("#ctc_rule_menu").data("menu"),function(e,t){i.test(e)&&n.push({label:e,value:t})}),c(n)},merge_ruleval_arrays:function(t,c,n){var i=this,a={};return nextval=n?c.child.pop():null,e.each(["parnt","child"],function(t,r){i.is_empty(c[r])||e.each(c[r],function(e,t){n?parseInt(t[2])>=parseInt(nextval[2])&&(nextval[2]=parseInt(t[2])+1):(i.is_empty(a[t[2]])&&(a[t[2]]={}),a[t[2]][r]=t)})}),n&&(a[nextval[2]]={parnt:[],child:nextval}),a},input_row:function(t,c,n,i,a){var r=this,s="";if(!r.is_empty(i)&&!r.is_empty(i.value)&&!r.is_empty(i.value[c])){var l=i.value[c],_=r.merge_ruleval_arrays(c,l,a);e.each(_,function(a,l){var _=r.decode_value(c,r.is_empty(l.parnt)?"":l.parnt[0]),o=r.is_empty(l.parnt)||0==l.parnt[1]?0:1,u=r.decode_value(c,r.is_empty(l.child)?"":l.child[0]),d=r.is_empty(l.child)||0==l.child[1]?0:1;if(s+='<div class="ctc-'+("ovrd"==n?"input":"selector")+'-row clearfix"><div class="ctc-input-cell">',s+="ovrd"==n?c.replace(/\d+/g,r.from_ascii):i.selector+'<br/><a href="#" class="ctc-selector-edit" id="ctc_selector_edit_'+t+'" >'+r.getxt("edit")+"</a> "+(r.is_empty(_.orig)?r.getxt("child_only"):""),s+='</div><div class="ctc-parent-value ctc-input-cell"'+("ovrd"!=n?' style="display:none"':"")+' id="ctc_'+n+"_parent_"+c+"_"+t+"_"+a+'">'+(r.is_empty(_.orig)?"[no value]":_.orig+(o?r.getxt("important"):""))+'</div><div class="ctc-input-cell">',!r.is_empty(_.names)){e.each(_.names,function(e,i){i=r.is_empty(i)?"":i,s+='<div class="ctc-child-input-cell clear">';var l,_="ctc_"+n+"_child_"+c+"_"+t+"_"+a+i;!1===(l=u.values.shift())&&(l=""),s+=(r.is_empty(i)?"":r.getxt(i)+":<br/>")+'<input type="text" id="'+_+'" name="'+_+'" class="ctc-child-value'+((i+c).toString().match(/color/)?" color-picker":"")+(i.toString().match(/url/)?" ctc-input-wide":"")+'" value="'+r.esc_quot(l)+'" /></div>'});var p="ctc_"+n+"_child_"+c+"_i_"+t+"_"+a;s+='<label for="'+p+'"><input type="checkbox" id="'+p+'" name="'+p+'" value="1" '+(d?"checked":"")+" />"+r.getxt("important")+"</label>"}s+="</div>","ovrd"!=n&&(s+='<div class="ctc-swatch ctc-specific" id="ctc_child_'+c+"_"+t+"_"+a+'_swatch">'+r.getxt("swatch")+'</div><div class="ctc-child-input-cell ctc-button-cell" id="ctc_save_'+c+"_"+t+"_"+a+'_cell"><input type="button" class="button ctc-save-input" id="ctc_save_'+c+"_"+t+"_"+a+'" name="ctc_save_'+c+"_"+t+"_"+a+'" value="Save" /></div>'),s+="</div><!-- end input row -->\n"})}return s},scrolltop:function(){e("html, body, .ctc-option-panel-container").animate({scrollTop:0})},css_preview:function(e){var e,t=this;(e=e.match(/(child|parnt)/)[1])||(e="child"),t.query_css("preview",e)},setup_iris:function(e){var t=this;t.setup_spectrum(e)},setup_spectrum:function(t){var c=this,n=(e(t).attr("id")+"_colortxt",!c.is_empty(ctcAjax.palette));try{e(t).spectrum({showInput:!0,allowEmpty:!0,showAlpha:!0,showInitial:!0,preferredFormat:"hex",clickoutFiresChange:!0,move:function(n){e(t).data("color",n),c.coalesce_inputs(t)},showPalette:n?!0:!1,showSelectionPalette:n?!0:!1,palette:[],maxSelectionSize:36,localStorageKey:"ctc-palette."+ctcAjax.child,hideAfterPaletteSelect:!0}).on("change",function(t){e(this).spectrum("get");c.coalesce_inputs(this)}).on("keyup",function(t){var n=this,i=e(this).val();clearTimeout(e(this).data("spectrumTimer")),e(this).data("spectrumTimer",setTimeout(function(){c.coalesce_inputs(n),e(n).spectrum("set",i)},500))})}catch(i){c.jquery_exception(i,"Spectrum Color Picker")}},color_text:function(e){var t=this;return t.is_empty(e)?"":e.getAlpha()<1?e.toRgbString():e.toHexString()},setup_query_menu:function(){var t=this;try{e("#ctc_sel_ovrd_query").autocomplete({source:t.get_queries,minLength:0,selectFirst:!0,autoFocus:!0,select:function(e,c){return t.set_query(c.item.value),!1},focus:function(e){e.preventDefault()}}).data("menu",{})}catch(c){t.jquery_exception(c,"Query Menu")}},setup_selector_menu:function(){var t=this;try{e("#ctc_sel_ovrd_selector").autocomplete({source:t.get_selectors,selectFirst:!0,autoFocus:!0,select:function(e,c){return t.set_selector(c.item.value,c.item.label),!1},focus:function(e){e.preventDefault()}}).data("menu",{})}catch(c){t.jquery_exception(c,"Selector Menu")}},setup_rule_menu:function(){var t=this;try{e("#ctc_rule_menu").autocomplete({source:t.get_rules,selectFirst:!0,autoFocus:!0,select:function(e,c){return t.set_rule(c.item.value,c.item.label),!1},focus:function(e){e.preventDefault()}}).data("menu",{})}catch(c){t.jquery_exception(c,"Property Menu")}},setup_new_rule_menu:function(){var t=this;try{e("#ctc_new_rule_menu").autocomplete({source:t.get_filtered_rules,selectFirst:!0,autoFocus:!0,select:function(c,n){c.preventDefault();var i,a,r=n.item.label.replace(/[^\w\-]/g,t.to_ascii);return t.is_empty(t.current_qsdata.value)&&(t.current_qsdata.value={}),t.is_empty(t.current_qsdata.value[n.item.label])&&(t.current_qsdata.value[n.item.label]={}),t.is_empty(t.current_qsdata.value[n.item.label].child)&&(t.current_qsdata.value[n.item.label].child=[]),t.current_qsdata.value[n.item.label].child.push(["",0,1,1]),i=e(t.input_row(t.current_qsid,r,"ovrd",t.current_qsdata,!0)),e("#ctc_sel_ovrd_rule_inputs").append(i),e("#ctc_new_rule_menu").val(""),i.find('input[type="text"]').each(function(c,n){a||(a=n),e(n).hasClass("color-picker")&&t.setup_spectrum(n)}),a&&e(a).focus(),t.jquery_err.length&&t.jquery_notice("setup_new_rule_menu"),!1},focus:function(e){e.preventDefault()}}).data("menu",{})}catch(c){t.jquery_exception(c,"New Property Menu")}},set_existing:function(){var t=this;if(e("#ctc_theme_child").length&&e("#ctc_child_type_existing").is(":checked")){var c=e("#ctc_theme_child").val();t.is_empty(c)||(e("#ctc_child_name").val(ctcAjax.themes.child[c].Name),e("#ctc_child_author").val(ctcAjax.themes.child[c].Author),e("#ctc_child_version").val(ctcAjax.themes.child[c].Version),e("#ctc_child_authoruri").val(ctcAjax.themes.child[c].AuthorURI),e("#ctc_child_themeuri").val(ctcAjax.themes.child[c].ThemeURI),e("#ctc_child_descr").val(ctcAjax.themes.child[c].Descr),e("#ctc_child_tags").val(ctcAjax.themes.child[c].Tags),e("#ctc_duplicate_theme").prop("checked",!1),e("#ctc_duplicate_theme_slug").val(""),e("#input_row_duplicate_theme").show())}},set_notice:function(t){var c=this,n="";c.is_empty(t)||e.each(t,function(t,c){n+='<div class="'+t+'"><ul>\n',e(c).each(function(e,t){n+="<li>"+t.toString()+"</li>\n"}),n+="</ul></div>"}),e("#ctc_error_notice").html(n),e("html, body").animate({scrollTop:0},"slow")},set_parent_menu:function(t){e("#ctc_theme_parnt").parents(".ctc-input-row").first().append('<span class="ctc-status-icon spinner"></span>'),e(".spinner").show(),document.location="?page="+ctcAjax.page+"&ctc_parent="+t.value},set_child_menu:function(t){var c,n,i=this;i.is_empty(ctcAjax.themes.child[t.value])||(c=ctcAjax.themes.child[t.value].Template,n=e("#ctc_theme_parnt").val(),c==n?(e("#ctc_child_name").val(ctcAjax.themes.child[t.value].Name),e("#ctc_child_author").val(ctcAjax.themes.child[t.value].Author),e("#ctc_child_version").val(ctcAjax.themes.child[t.value].Version)):(e("#ctc_theme_child").parents(".ctc-input-row").first().append('<span class="ctc-status-icon spinner"></span>'),e(".spinner").show(),document.location="?page="+ctcAjax.page+"&ctc_parent="+c+"&ctc_child="+t.value))},set_query:function(t){var c=this;return c.is_empty(t)?!1:(c.current_query=t,e("#ctc_sel_ovrd_query").val(""),e("#ctc_sel_ovrd_query_selected").text(t),e("#ctc_sel_ovrd_selector").val(""),e("#ctc_sel_ovrd_selector_selected").html("&nbsp;"),c.load_selectors(),void c.scrolltop())},set_selector:function(t,c){var n=this;return n.is_empty(t)?!1:(e("#ctc_sel_ovrd_selector").val(""),n.current_qsid=t,n.reload_menus=!1,n.load_selector_values(),void n.scrolltop())},set_rule:function(t,c){var n=this;return n.is_empty(t)?!1:(e("#ctc_rule_menu").val(""),e("#ctc_rule_menu_selected").text(c),e(".ctc-rewrite-toggle").text(n.getxt("rename")),e("#ctc_rule_value_inputs, #ctc_input_row_rule_header").show(),n.query_css("rule_val",t),void n.scrolltop())},set_qsid:function(t){var c=this;c.current_qsid=e(t).attr("id").match(/_(\d+)$/)[1],c.focus_panel("#query_selector_options"),c.reload_menus=!0,c.load_selector_values()},set_addl_css:function(){var t,c=this,n=e("#ctc_theme_parnt").val(),i=ctcAjax.theme_uri.replace(/^https?:\/\//,""),a=ctcAjax.homeurl.replace(/^https?/,ctcAjax.ssl?"https":"http"),r=a+"&template="+n+"&stylesheet="+n,s=new RegExp("<link rel=[\"']stylesheet[\"'][^>]+?"+i+"/"+n+"/(.+?\\.css)[^>]+?>","g");c.is_empty(n)||(n!=ctcAjax.parnt?e.get(r,function(c){for(;(t=s.exec(c))&&"style.css"!=t[1];)t[1].match(/bootstrap/)||e(".ctc_checkbox").each(function(c,n){e(this).val()==t[1]&&e(this).prop("checked",!0)});c=null}):e(ctcAjax.addl_css).each(function(t,c){e("#ctc_stylesheet_files .ctc_checkbox").each(function(t,n){e(this).val()==c&&e(this).prop("checked",!0)})}))},query_css:function(t,c,n){var i=this,a={ctc_query_obj:t,ctc_query_key:c},r="#ctc_status_"+t+("val_qry"==t?"_"+c:"");"object"==typeof n&&e.each(n,function(e,t){a["ctc_query_"+e]=t}),e(".query-icon,.ctc-status-icon").remove(),e(r+" .ctc-status-icon").remove(),e(r).append('<span class="ctc-status-icon spinner query-icon"></span>'),e(".spinner").show(),a.action=i.is_empty(e("#ctc_action").val())||"plugin"!=e("#ctc_action").val()?"ctc_query":"ctc_plgqry",a._wpnonce=e("#_wpnonce").val(),i.ajax_post(t,a)},save:function(t){var c,n,i,a,r,s=this,l=(ctcAjax.ajaxurl,{}),_=e(t).attr("id");e(t).prop("disabled",!0),e(".ctc-query-icon,.ctc-status-icon").remove(),e(t).parent(".ctc-textarea-button-cell, .ctc-button-cell").append('<span class="ctc-status-icon spinner save-icon"></span>'),_.match(/ctc_configtype/)?(e(t).parents(".ctc-input-row").first().append('<span class="ctc-status-icon spinner save-icon"></span>'),l.ctc_configtype=e(t).val()):(c=e("#ctc_new_selectors"))&&"ctc_save_new_selectors"==e(t).attr("id")?(l.ctc_new_selectors=c.val(),(n=e("#ctc_sel_ovrd_query_selected"))&&(l.ctc_sel_ovrd_query=n.text()),s.reload_menus=!0):(i=e("#ctc_child_imports"))&&"ctc_save_imports"==_?l.ctc_child_imports=i.val():"ctc_is_debug"==_?l.ctc_is_debug=e("#ctc_is_debug").is(":checked")?1:0:l=s.coalesce_inputs(t),e(".save-icon").show(),e("#ctc_sel_ovrd_selector_selected").find("#ctc_rewrite_selector").each(function(){a=e("#ctc_rewrite_selector").val(),r=e("#ctc_rewrite_selector_orig").val(),s.is_empty(a)||!a.toString().match(/\w/)?a=r:(l.ctc_rewrite_selector=a,s.reload_menus=!0),e(".ctc-rewrite-toggle").text(s.getxt("rename")),e("#ctc_sel_ovrd_selector_selected").html(a)}),l.action=s.is_empty(e("#ctc_action").val())||"plugin"!=e("#ctc_action").val()?"ctc_update":"ctc_plugin",l._wpnonce=e("#_wpnonce").val(),s.ajax_post("qsid",l)},ajax_post:function(t,c,n){var i=this,a=ctcAjax.ajaxurl;e.ajax({url:a,data:c,dataType:i.is_empty(n)?"json":n,type:"POST"}).done(function(e){i.handle_success(t,e)}).fail(function(){i.handle_failure(t)})},handle_failure:function(t){var c=this;e(".query-icon, .save-icon").removeClass("spinner").addClass("failure"),e("input[type=submit], input[type=button], input[type=checkbox],.ctc-delete-input").prop("disabled",!1),e(".ajax-pending").removeClass("ajax-pending"),"preview"==t&&e("#view_parnt_options_panel,#view_child_options_panel").text(c.getxt("css_fail"))},handle_success:function(t,c){var n=this;e(".query-icon, .save-icon").removeClass("spinner"),e(".ajax-pending").removeClass("ajax-pending"),n.is_empty(c)?n.handle_failure(t):(e("#ctc_new_selectors").val(""),e(".query-icon, .save-icon").addClass("success"),e("input[type=submit], input[type=button], input[type=checkbox],.ctc-delete-input").prop("disabled",!1),e(c).each(function(){"function"==typeof n.update[this.obj]&&n.update[this.obj].call(n,this)}))},jquery_exception:function(e,t){var c=this,n=c.is_empty(e.lineNumber)?"":" line: "+e.lineNumber,i=c.is_empty(e.fileName)?"":" "+e.fileName.split(/\?/)[0];c.jquery_err.push("<code><small>"+t+": "+e.message+i+n+"</small></code>")},jquery_notice:function(t){var c=this,n=[],i=[];e("input[type=submit], input[type=button]").prop("disabled",!0),e("script").each(function(t,i){var a=e(this).prop("src");c.is_empty(a)||!a.match(/jquery(\.min|\.js|\-?ui)/i)||a.match(/load\-scripts.php/)||n.push("<code><small>"+a.split(/\?/)[0]+"</small></code>")}),i.push("<strong>"+c.getxt("js")+"</strong> "+c.getxt("contact")),i.push(c.jquery_err.join("<br/>")),n.length&&i.push(c.getxt("jquery")+"<br/>"+n.join("<br/>")),i.push(c.getxt("plugin")),c.set_notice({error:i})},update:{qsid:function(t){var c,n,i,a,r=this;r.current_qsid=t.key,r.current_qsdata=t.data,e("#ctc_sel_ovrd_qsid").val(r.current_qsid),r.is_empty(r.current_qsdata.seq)?e("#ctc_child_load_order_container").empty():(c="ctc_ovrd_child_seq_"+r.current_qsid,i=parseInt(r.current_qsdata.seq),n='<input type="text" id="'+c+'" name="'+c+'" class="ctc-child-value" value="'+i+'" />',e("#ctc_child_load_order_container").html(n)),r.is_empty(r.current_qsdata.value)?(a=!0,e("#ctc_sel_ovrd_rule_inputs").empty()):(a=!1,n="",e.each(r.current_qsdata.value,function(e,t){n+=r.input_row(r.current_qsid,e,"ovrd",r.current_qsdata)}),e("#ctc_sel_ovrd_rule_inputs").html(n).find(".color-picker").each(function(){r.setup_spectrum(this)}),r.coalesce_inputs("#ctc_child_all_0_swatch")),r.jquery_err.length?r.jquery_notice("update.qsid"):(r.reload_menus&&(r.load_queries(),r.set_query(r.current_qsdata.query),r.load_rules()),e("#ctc_sel_ovrd_selector_selected").text(r.current_qsdata.selector),e(".ctc-rewrite-toggle").text(r.getxt("rename")),e(".ctc-rewrite-toggle").show(),a?e("#ctc_sel_ovrd_rule_header,#ctc_sel_ovrd_new_rule,#ctc_sel_ovrd_rule_inputs_container,#ctc_sel_ovrd_rule_inputs").hide():e("#ctc_sel_ovrd_rule_header,#ctc_sel_ovrd_new_rule,#ctc_sel_ovrd_rule_inputs_container,#ctc_sel_ovrd_rule_inputs").show())},rule_val:function(t){var c=this,n=e("#ctc_rule_menu_selected").text(),i='<div class="ctc-input-row clearfix" id="ctc_rule_row_'+n+'">\n';c.is_empty(t.data)||(e.each(t.data,function(e,t){var a=c.decode_value(n,t);i+='<div class="ctc-parent-row clearfix" id="ctc_rule_row_'+n+"_"+e+'">\n<div class="ctc-input-cell ctc-parent-value" id="ctc_'+e+"_parent_"+n+"_"+e+'">'+a.orig+'</div>\n<div class="ctc-input-cell">\n<div class="ctc-swatch ctc-specific" id="ctc_'+e+"_parent_"+n+"_"+e+'_swatch">'+c.getxt("swatch")+'</div></div>\n<div class="ctc-input-cell"><a href="#" class="ctc-selector-handle" id="ctc_selector_'+n+"_"+e+'">'+c.getxt("selector")+'</a></div>\n<div id="ctc_selector_'+n+"_"+e+'_container" class="ctc-selector-container">\n<a href="#" id="ctc_selector_'+n+"_"+e+'_close" class="ctc-selector-handle ctc-exit" title="'+c.getxt("close")+'"></a><div id="ctc_selector_'+n+"_"+e+'_inner_container" class="ctc-selector-inner-container clearfix">\n<div id="ctc_status_val_qry_'+e+'"></div>\n<div id="ctc_selector_'+n+"_"+e+'_rows"></div>\n</div></div></div>\n'}),i+="</div>\n"),e("#ctc_rule_value_inputs").html(i).find(".ctc-swatch").each(function(){c.coalesce_inputs(this)})},val_qry:function(t){var c=this,n="";c.is_empty(t.data)||e.each(t.data,function(i,a){page_rule=i,e.each(a,function(a,r){n+='<h4 class="ctc-query-heading">'+a+"</h4>\n",c.is_empty(r)||e.each(r,function(e,a){n+=c.input_row(e,i,t.key,a)})})}),selector="#ctc_selector_"+rule+"_"+t.key+"_rows",e(selector).html(n).find(".color-picker").each(function(){c.setup_spectrum(this)}),e(selector).find(".ctc-swatch").each(function(){c.coalesce_inputs(this)}),c.jquery_err.length&&c.jquery_notice("val_qry")},queries:function(t){e("#ctc_sel_ovrd_query").data("menu",t.data)},selectors:function(t){e("#ctc_sel_ovrd_selector").data("menu",t.data)},rules:function(t){e("#ctc_rule_menu").data("menu",t.data)},debug:function(t){e("#ctc_debug_container").html(t.data)},preview:function(t){e("#view_"+t.key+"_options_panel").text(t.data)}},init:function(){var t=this;if(t.autogen_slugs(),t.set_existing(),!e("#ctc_theme_parnt").is("input")){try{e.widget("ctc.themeMenu",e.ui.selectmenu,{_renderItem:function(t,c){var n=e("<li>"),i=c.value.replace(/[^\w\-]/,"");return e("#ctc_theme_option_"+i).detach().appendTo(n),n.appendTo(t)}})}catch(c){t.jquery_exception(c,"Theme Menu")}try{e("#ctc_theme_parnt").themeMenu({select:function(e,c){t.set_parent_menu(c.item)}})}catch(c){"function"==typeof themeMenu?e("#ctc_theme_parnt").themeMenu("destroy"):e("#ctc_theme_parnt-button").remove(),t.jquery_exception(c,"Parent Theme Menu")}if(t.is_empty(ctcAjax.themes.child))e("#ctc_child_name").length&&(e("#ctc_child_name").val(t.testname),e("#ctc_child_template").val(t.testslug));else try{e("#ctc_theme_child").themeMenu({select:function(e,c){t.set_child_menu(c.item)}})}catch(c){"function"==typeof themeMenu?e("#ctc_theme_child").themeMenu("destroy"):e("#ctc_theme_child-button").remove(),t.jquery_exception(c,"Child Theme Menu")}}t.is_empty(t.jquery_err)?(e("#ctc_main").on("click",".ctc-selector-handle",function(c){if(c.preventDefault(),e(this).hasClass("ajax-pending"))return!1;e(this).addClass("ajax-pending");var n=e(this).attr("id").toString().replace("_close",""),i=n.toString().match(/_([^_]+)_(\d+)$/);e("#"+n+"_container").is(":hidden")&&(t.is_empty(i[1])||t.is_empty(i[2])||(rule=i[1],valid=i[2],t.query_css("val_qry",valid,{rule:rule}))),e("#"+n+"_container").fadeToggle("fast"),e(".ctc-selector-container").not("#"+n+"_container").fadeOut("fast")}),e("#ctc_main").on("click",".ctc-save-input[type=button], .ctc-delete-input",function(c){return c.preventDefault(),e(this).hasClass("ajax-pending")?!1:(e(this).addClass("ajax-pending"),t.save(this),!1)}),e("#ctc_main").on("keydown",".ctc-selector-container .ctc-child-value[type=text]",function(c){if(13===c.which){var n=e(this).parents(".ctc-selector-row").find(".ctc-save-input[type=button]").first();if(n.length)return c.preventDefault(),n.hasClass("ajax-pending")?!1:(n.addClass("ajax-pending"),t.save(n),!1)}}),e("#ctc_main").on("click",".ctc-selector-edit",function(c){return c.preventDefault(),e(this).hasClass("ajax-pending")?!1:(e(this).addClass("ajax-pending"),void t.set_qsid(this))}),e("#ctc_main").on("click",".ctc-rewrite-toggle",function(e){e.preventDefault(),t.selector_input_toggle(this)}),e("#ctc_main").on("click","#ctc_copy_selector",function(c){var n=e("#ctc_sel_ovrd_selector_selected").text().trim();t.is_empty(n)||e("#ctc_new_selectors").val(e("#ctc_new_selectors").val()+"\n"+n+" {\n\n}")}),e("#ctc_configtype").on("change",function(c){var n=e(this).val();if(t.is_empty(n)||"theme"==n){e(".ctc-theme-only, .ctc-themeonly-container").removeClass("ctc-disabled"),e(".ctc-theme-only, .ctc-themeonly-container input").prop("disabled",!1);try{e("#ctc_theme_parnt, #ctc_theme_child").themeMenu("enable")}catch(i){t.jquery_exception(i,"Theme Menu")}}else{e(".ctc-theme-only, .ctc-themeonly-container").addClass("ctc-disabled"),e(".ctc-theme-only, .ctc-themeonly-container input").prop("disabled",!0);try{e("#ctc_theme_parnt, #ctc_theme_child").themeMenu("disable")}catch(i){t.jquery_exception(i,"Theme Menu")}}}),e(".nav-tab").on("click",function(c){c.preventDefault(),e(".ctc-query-icon,.ctc-status-icon").remove();var n="#"+e(this).attr("id");t.focus_panel(n)}),e(".ctc-section-toggle").on("click",function(t){t.preventDefault(),e(this).parents(".ctc-input-row, .update-nag").first().find(".ctc-section-toggle").each(function(){e(this).toggleClass("open")});var c=e(this).attr("id").replace(/\d$/,"")+"_content";return e("#"+c).stop().slideToggle("fast"),!1}),e("#view_child_options, #view_parnt_options").on("click",function(c){return e(this).hasClass("ajax-pending")?!1:(e(this).addClass("ajax-pending"),void t.css_preview(e(this).attr("id")))}),e("#ctc_load_form").on("submit",function(){return t.validate()}),e("#ctc_query_selector_form").on("submit",function(c){return c.preventDefault(),$this=e("#ctc_save_query_selector"),$this.hasClass("ajax-pending")?!1:($this.addClass("ajax-pending"),t.save($this),!1)}),e("#ctc_rule_value_form").on("submit",function(e){return e.preventDefault(),!1}),e("#ctc_theme_child, #ctc_theme_child-button, #ctc_child_type_existing").on("focus click",function(){e("#ctc_child_type_existing").prop("checked",!0),e("#ctc_child_type_new").prop("checked",!1),e("#ctc_child_template").val(""),t.set_existing()}),e("#ctc_duplicate_theme").on("click",function(){e("#ctc_duplicate_theme").is(":checked")?(e("#ctc_child_name").val(t.testname),e("#ctc_duplicate_theme_slug").val(t.testslug)):t.set_existing()}),e("#ctc_child_type_new, #ctc_child_template").on("focus click",function(){e("#ctc_child_type_existing").prop("checked",!1),e("#ctc_duplicate_theme").prop("checked",!1),e("#ctc_duplicate_theme_slug").val(""),e("#ctc_child_type_new").prop("checked",!0),e("#input_row_duplicate_theme").hide(),e("#ctc_child_name").val(t.testname),e("#ctc_child_template").val(t.testslug)}),e("#ctc_is_debug").on("change",function(e){t.save(this)}),e(".ctc-live-preview").on("click",function(t){return t.stopImmediatePropagation(),t.preventDefault(),document.location=e(this).prop("href"),!1}),t.setup_menus(),t.set_addl_css(),e("input[type=submit], input[type=button]").prop("disabled",!1),t.scrolltop(),setTimeout(t.fade_update_notice,2e4)):t.jquery_notice("init")},testslug:"",testname:"",reload_menus:!1,current_query:"base",current_qsid:null,current_qsdata:{},jquery_err:[],color_regx:"\\s+(\\#[a-f0-9]{3,6}|rgba?\\([\\d., ]+?\\)|hsla?\\([\\d%., ]+?\\)|[a-z]+)",border_regx:"(\\w+)(\\s+(\\w+))?",grad_regx:"(\\w+)"},e.chldthmcfg.init()}(jQuery);
 
js/chldthmcfg.js ADDED
@@ -0,0 +1,2165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Script: chldthmcfg.js
3
+ * Plugin URI: http://www.childthemeconfigurator.com/
4
+ * Description: Handles jQuery, AJAX and other UI
5
+ * Version: 2.2.0
6
+ * Author: Lilaea Media
7
+ * Author URI: http://www.lilaeamedia.com/
8
+ * License: GPLv2
9
+ * Copyright (C) 2014-2016 Lilaea Media
10
+ */
11
+
12
+ // ** for muliple property values: **
13
+ // make sure sequence is passed with rule/val updates
14
+ // determine sequence based on sequence of value array
15
+ // add sequence to input name
16
+
17
+ ( function( $ ) {
18
+ 'use strict';
19
+ $.chldthmcfg = {
20
+ //console.log( 'executing main function' );
21
+ escquo: function( str ) {
22
+ var self = this;
23
+ return self.is_empty( str ) ? str : str.toString().replace( /"/g, '"' );
24
+ },
25
+
26
+ getxt: function( key, merge ){
27
+ var text = window.ctcAjax[ key + '_txt' ];
28
+ if ( text ) {
29
+ if ( merge ) {
30
+ text = text.replace( /%s/, merge );
31
+ }
32
+ return text;
33
+ }
34
+ return '';
35
+ },
36
+
37
+ getname: function( themetype ){
38
+ var stylesheet = ( 'child' === themetype ? $.chldthmcfg.currchild : $.chldthmcfg.currparnt );
39
+ return window.ctcAjax.themes[ themetype ][ stylesheet ].Name;
40
+ },
41
+
42
+ frascii: function( str ) {
43
+ var ascii = parseInt( str ),
44
+ chr = String.fromCharCode( ascii );
45
+ return chr;
46
+ },
47
+
48
+ toascii: function( str ) {
49
+ var ascii = str.charCodeAt( 0 );
50
+ return ascii;
51
+ },
52
+
53
+ /**
54
+ * is_empty
55
+ * return true if value evaluates to false, null, null string,
56
+ * empty array, empty object or undefined
57
+ * but NOT 0 ( zero returns false ) unless zero flag is passed
58
+ */
59
+ is_empty: function( obj, zeros ) {
60
+ // first bail when definitely empty or undefined ( true ) NOTE: numeric zero returns false !
61
+ if ( 'undefined' === typeof obj || false === obj || null === obj || '' === obj ) {
62
+ // console.log( 'matched empty' );
63
+ return true;
64
+ }
65
+ // if zeros flag is set, return true for 0 or '0'
66
+ if ( 'undefined' !== typeof zeros && '0' === obj || 0 === obj ) {
67
+ // console.log( 'matched zero literal:' + obj );
68
+ return true;
69
+ }
70
+ // then, if this is bool, string or number it must not be empty ( false )
71
+ if ( true === obj || "string" === typeof obj || "number" === typeof obj ) {
72
+ return false;
73
+ }
74
+ // check for object type to be safe
75
+ if ( "object" === typeof obj ) {
76
+ // Use a standard for in loop
77
+ for ( var x in obj ) {
78
+ // for in will iterate over members on the prototype
79
+ // chain as well, but Object.getOwnPropertyNames returns
80
+ // only those directly on the object, so use hasOwnProperty.
81
+ if ( obj.hasOwnProperty( x ) ) {
82
+ // any value means not empty ( false )
83
+ return false;
84
+ }
85
+ }
86
+ // no properties, so return empty ( true )
87
+ return true;
88
+ }
89
+ // this must be an unsupported datatype, so return not empty
90
+ return false;
91
+ },
92
+
93
+ /**
94
+ * theme_exists
95
+ * returns true if theme is already present for type
96
+ */
97
+ theme_exists: function( testslug, testtype ) {
98
+ var exists = false;
99
+ $.each( window.ctcAjax.themes, function( type, theme ) {
100
+ $.each( theme, function( slug, data ) {
101
+ data = null;
102
+ if ( slug.toLowerCase() === testslug.toLowerCase() && ( 'parnt' === type || 'new' === testtype ) ) {
103
+ exists = true; // no need to continue testing
104
+ return false; // in this context "return false" means "break"
105
+ }
106
+ } );
107
+ if ( exists ) { // no need to continue testing
108
+ return false; // in this context "return false" means "break"
109
+ }
110
+ } );
111
+ return exists;
112
+ },
113
+
114
+ validate: function() {
115
+ var self = this,
116
+ regex = /[^\w\-]/,
117
+ newslug = $( '#ctc_child_template' ).length ? $( '#ctc_child_template' )
118
+ .val().toString().replace( regex ) : '',
119
+ slug = $( '#ctc_theme_child' ).length ? $( '#ctc_theme_child' )
120
+ .val().toString().replace( regex ) : newslug,
121
+ type = $( 'input[name=ctc_child_type]:checked' ).val(),
122
+ errors = [];
123
+ if ( 'new' === type ) {
124
+ slug = newslug;
125
+ }
126
+ if ( self.theme_exists( slug, type ) ) {
127
+ errors.push( self.getxt( 'theme_exists' ).toString().replace( /%s/, slug ) );
128
+ }
129
+ if ( self.is_empty( slug ) ) {
130
+ errors.push( self.getxt( 'inval_theme' ) );
131
+ }
132
+ //if ( self.is_empty( $( '#ctc_child_name' ).val() ) ) {
133
+ // errors.push( self.getxt( 'inval_name' ) );
134
+ //}
135
+ if ( errors.length ) {
136
+ self.set_notice( { 'error': errors } );
137
+ return false;
138
+ }
139
+ if ( 'reset' === type ) {
140
+ if ( confirm( self.getxt( 'load' ) ) ) {
141
+ return true;
142
+ }
143
+ return false;
144
+ }
145
+ return true;
146
+ },
147
+
148
+ autogen_slugs: function() {
149
+ if ( $( '#ctc_theme_parnt' ).length ) {
150
+ var self = this,
151
+ parent = $( '#ctc_theme_parnt' ).val(),
152
+ child = $( '#ctc_theme_child' ).length ? $( '#ctc_theme_child' ).val() : '',
153
+ slugbase= ( '' !== child && $( '#ctc_child_type_duplicate' ).is( ':checked' ) ) ? child : parent + '-child',
154
+ slug = slugbase,
155
+ name = ( '' !== child && $( '#ctc_child_type_duplicate' ).is( ':checked' ) ) ? $.chldthmcfg.getname( 'child' ) : $.chldthmcfg.getname( 'parnt' ) + ' Child',
156
+ suffix = '',
157
+ padded = '',
158
+ pad = '00';
159
+ while ( self.theme_exists( slug, 'new' ) ) {
160
+ suffix = ( self.is_empty( suffix ) ? 2 : suffix + 1 );
161
+ padded = pad.substring( 0, pad.length - suffix.toString().length ) + suffix.toString();
162
+ slug = slugbase + padded;
163
+ }
164
+ self.testslug = slug;
165
+ self.testname = name + ( padded.length ? ' ' + padded : '' );
166
+ //console.log( 'autogen_slugs: parent: ' + parent + ' slug: ' + slug );
167
+ }
168
+ },
169
+
170
+ focus_panel: function( id ) {
171
+ var panelid = id + '_panel';
172
+ $( '.nav-tab' ).removeClass( 'nav-tab-active' );
173
+ $( '.ctc-option-panel' ).removeClass( 'ctc-option-panel-active' );
174
+ //$( '.ctc-selector-container' ).hide();
175
+ $( id ).addClass( 'nav-tab-active' );
176
+ $( '.ctc-option-panel-container' ).scrollTop( 0 );
177
+ $( panelid ).addClass( 'ctc-option-panel-active' );
178
+ },
179
+
180
+ selector_input_toggle: function( obj ) {
181
+ //console.log( 'selector_input_toggle: ' + obj );
182
+ var self = this,
183
+ origval;
184
+ if ( $( '#ctc_rewrite_selector' ).length ) {
185
+ origval = $( '#ctc_rewrite_selector_orig' ).val();
186
+ $( '#ctc_sel_ovrd_selector_selected' ).text( origval );
187
+ $( obj ).text( self.getxt( 'rename' ) );
188
+ } else {
189
+ origval = $( '#ctc_sel_ovrd_selector_selected' ).text();
190
+ $( '#ctc_sel_ovrd_selector_selected' ).html(
191
+ '<textarea id="ctc_rewrite_selector"' +
192
+ ' name="ctc_rewrite_selector" autocomplete="off"></textarea>' +
193
+ '<input id="ctc_rewrite_selector_orig" name="ctc_rewrite_selector_orig"' +
194
+ ' type="hidden" value="' + self.escquo( origval ) + '"/>' );
195
+ $( '#ctc_rewrite_selector' ).val( origval );
196
+ $( obj ).text( self.getxt( 'cancel' ) );
197
+ }
198
+ },
199
+
200
+ coalesce_inputs: function( obj ) {
201
+ //**console.log( 'coalesce_inputs ' + $( obj ).attr( 'id' ) );
202
+ var self = this,
203
+ id = $( obj ).attr( 'id' ),
204
+ regex = /^(ctc_(ovrd|\d+)_(parent|child)_([0-9a-z\-]+)_(\d+?)(_(\d+))?)(_\w+)?$/,
205
+ container = $( obj ).parents( '.ctc-selector-row, .ctc-parent-row' ).first(),
206
+ swatch = container.find( '.ctc-swatch' ).first(),
207
+ cssrules = { 'parent': {}, 'child': {} },
208
+ gradient = {
209
+ 'parent': {
210
+ 'origin': '',
211
+ 'start': '',
212
+ 'end': ''
213
+ },
214
+ 'child': {
215
+ 'origin': '',
216
+ 'start': '',
217
+ 'end': ''
218
+ }
219
+ },
220
+ has_gradient = { 'child': false, 'parent': false },
221
+ postdata = {};
222
+ // set up objects for all neighboring inputs
223
+ container.find( '.ctc-parent-value, .ctc-child-value' ).each( function() {
224
+ var inputid = $( this ).attr( 'id' ),
225
+ inputparts = inputid.toString().match( regex ),
226
+ inputseq = inputparts[ 2 ],
227
+ inputtheme = inputparts[ 3 ],
228
+ inputrule = ( 'undefined' === typeof inputparts[ 4 ] ? '' : inputparts[ 4 ] ),
229
+ rulevalid = inputparts[ 7 ],
230
+ qsid = inputparts[ 5 ],
231
+ rulepart = ( 'undefined' === typeof inputparts[ 7 ] ? '' : inputparts[ 8 ] ),
232
+ value = ( 'parent' === inputtheme ? $( this ).text().replace( /!$/, '' ) :
233
+ ( 'seq' !== inputrule && 'ctc_delete_query_selector' === id ? '' :
234
+ $( this ).val() ) ), // clear values if delete was clicked
235
+ important = ( 'seq' === inputrule ? false : 'ctc_' + inputseq + '_child_' + inputrule + '_i_' + qsid + '_' + rulevalid ),
236
+ parts, subparts;
237
+ //**console.log( inputparts );
238
+ //**console.log( 'value: ' + value );
239
+ if ( 'child' === inputtheme ) {
240
+ if ( !self.is_empty( $( this ).data( 'color' ) ) ) {
241
+ value = self.color_text( $( this ).data( 'color' ) );
242
+ $( this ).data( 'color', null );
243
+ }
244
+ postdata[ inputid ] = value;
245
+ if ( important ) {
246
+ postdata[ important ] = ( $( '#' + important ).is( ':checked' ) ) ? 1 : 0;
247
+ }
248
+ }
249
+ if ( '' !== value ) {
250
+ // handle specific inputs
251
+ if ( !self.is_empty( rulepart ) ) {
252
+ switch( rulepart ) {
253
+ case '_border_width':
254
+ cssrules[ inputtheme ][ inputrule + '-width' ] = ( 'none' === value ? 0 : value );
255
+ break;
256
+ case '_border_style':
257
+ cssrules[ inputtheme ][ inputrule + '-style' ] = value;
258
+ break;
259
+ case '_border_color':
260
+ cssrules[ inputtheme ][ inputrule + '-color' ] = value;
261
+ break;
262
+ case '_background_url':
263
+ cssrules[ inputtheme ][ 'background-image' ] = self.image_url( inputtheme, value );
264
+ break;
265
+ case '_background_color':
266
+ cssrules[ inputtheme ][ 'background-color' ] = value; // was obj.value ???
267
+ break;
268
+ case '_background_color1':
269
+ gradient[ inputtheme ].start = value;
270
+ has_gradient[ inputtheme ] = true;
271
+ break;
272
+ case '_background_color2':
273
+ gradient[ inputtheme ].end = value;
274
+ has_gradient[ inputtheme ] = true;
275
+ break;
276
+ case '_background_origin':
277
+ gradient[ inputtheme ].origin = value;
278
+ has_gradient[ inputtheme ] = true;
279
+ break;
280
+ }
281
+ } else {
282
+ // handle borders
283
+ if ( ( parts = inputrule.toString().match( /^border(\-(top|right|bottom|left))?$/ ) && !value.match( /none/ ) ) ) {
284
+ var borderregx = new RegExp( self.border_regx + self.color_regx, 'i' );
285
+ subparts = value.toString().match( borderregx );
286
+ //**console.log( 'border after regex: ');
287
+ //**console.log( value );
288
+ //**console.log( borderregx );
289
+ //**console.log( subparts );
290
+ if ( !self.is_empty( subparts ) ) {
291
+ subparts.shift();
292
+ cssrules[ inputtheme ][ inputrule + '-width' ] = subparts.shift() || '';
293
+ subparts.shift();
294
+ cssrules[ inputtheme ][ inputrule + '-style' ] = subparts.shift() || '';
295
+ cssrules[ inputtheme ][ inputrule + '-color' ] = subparts.shift() || '';
296
+ }
297
+ // handle background images
298
+ } else if ( 'background-image' === inputrule && !value.match( /none/ ) ) {
299
+ if ( value.toString().match( /url\(/ ) ) {
300
+ cssrules[ inputtheme ][ 'background-image' ] = self.image_url( inputtheme, value );
301
+ } else {
302
+ var gradregex = new RegExp( self.grad_regx + self.color_regx + self.color_regx, 'i' );
303
+ subparts = value.toString().match( gradregex );
304
+ //**console.log( 'background-image after regex: ');
305
+ //**console.log( value );
306
+ //**console.log( gradregex );
307
+ //**console.log( subparts );
308
+ if ( !self.is_empty( subparts ) && subparts.length > 2 ) {
309
+ subparts.shift();
310
+ gradient[ inputtheme ].origin = subparts.shift() || 'top';
311
+ gradient[ inputtheme ].start = subparts.shift() || 'transparent';
312
+ gradient[ inputtheme ].end = subparts.shift() || 'transparent';
313
+ has_gradient[ inputtheme ] = true;
314
+ } else {
315
+ cssrules[ inputtheme ][ 'background-image' ] = value;
316
+ }
317
+ }
318
+ } else if ( 'seq' !== inputrule ) {
319
+ cssrules[ inputtheme ][ inputrule ] = value;
320
+ }
321
+ }
322
+ }
323
+ } );
324
+ // update swatch
325
+ if ( 'undefined' !== typeof swatch && !self.is_empty( swatch.attr( 'id' ) ) ) {
326
+ swatch.removeAttr( 'style' );
327
+ if ( has_gradient.parent ) {
328
+ swatch.ctcgrad( gradient.parent.origin, [ gradient.parent.start, gradient.parent.end ] );
329
+ }
330
+ //**console.log( 'combined css rules' );
331
+ //**console.log( cssrules );
332
+ swatch.css( cssrules.parent );
333
+ if ( !( swatch.attr( 'id' ).toString().match( /parent/ ) ) ) {
334
+ if ( has_gradient.child ) {
335
+ swatch.ctcgrad( gradient.child.origin, [ gradient.child.start, gradient.child.end ] );
336
+ }
337
+ //console.log( cssrules.child );
338
+ swatch.css( cssrules.child );
339
+ }
340
+ swatch.css( {'z-index':-1} );
341
+ }
342
+ return postdata;
343
+ },
344
+
345
+ decode_value: function( rule, value ) {
346
+ //**console.log( 'in decode_value ( ' + rule + ' ...' );
347
+ value = ( 'undefined' === typeof value ? '' : value );
348
+ var self = this,
349
+ obj = {
350
+ 'orig': value,
351
+ 'names': [ '' ],
352
+ 'values': [ value ]
353
+ },
354
+ params;
355
+ if ( rule.toString().match( /^border(\-(top|right|bottom|left))?$/ ) ) {
356
+ var regex = new RegExp( self.border_regx + '(' + self.color_regx + ')?', 'i' ),
357
+ orig;
358
+ params = value.toString().match( regex );
359
+ if ( self.is_empty( params ) ) {
360
+ params = [];
361
+ }
362
+ obj.names = [
363
+ '_border_width',
364
+ '_border_style',
365
+ '_border_color',
366
+ ];
367
+ orig = params.shift();
368
+ //**console.log( value );
369
+ //**console.log( regex );
370
+ //**console.log( params );
371
+ obj.values[ 0 ] = params.shift() || '';
372
+ params.shift();
373
+ obj.values[ 1 ] = params.shift() || '';
374
+ params.shift();
375
+ obj.values[ 2 ] = params.shift() || '';
376
+ } else if ( rule.toString().match( /^background\-image/ ) ) {
377
+ obj.names = [
378
+ '_background_url',
379
+ '_background_origin',
380
+ '_background_color1',
381
+ '_background_color2'
382
+ ];
383
+ obj.values = [ '', '', '', '' ];
384
+ if ( !self.is_empty( value ) && !( value.toString().match( /(url|none)/ ) ) ) {
385
+ var stop1, stop2;
386
+ params = value.toString().split( /:/ );
387
+ //**console.log( value );
388
+ //**console.log( params );
389
+ obj.values[ 1 ] = params.shift() || '';
390
+ obj.values[ 2 ] = params.shift() || '';
391
+ stop1 = params.shift() || '';
392
+ obj.values[ 3 ] = params.shift() || '';
393
+ stop2 = params.shift() || '';
394
+ obj.orig = [
395
+ obj.values[ 1 ],
396
+ obj.values[ 2 ],
397
+ obj.values[ 3 ]
398
+ ].join( ' ' );
399
+ } else {
400
+ obj.values[ 0 ] = value;
401
+ }
402
+ }
403
+ //**console.log( obj );
404
+ return obj;
405
+ },
406
+
407
+ image_url: function( theme, value ) {
408
+ var self = this,
409
+ parts = value.toString().match( /url\(['" ]*(.+?)['" ]*\)/ ),
410
+ path = self.is_empty( parts ) ? null : parts[ 1 ],
411
+ url = window.ctcAjax.theme_uri + '/' + ( 'parent' === theme ? window.ctcAjax.parnt : window.ctcAjax.child ) + '/',
412
+ image_url;
413
+ if ( !path ) {
414
+ return false;
415
+ } else if ( path.toString().match( /^(data:|https?:|\/)/ ) ) {
416
+ image_url = value;
417
+ } else {
418
+ image_url = 'url(' + url + path + ')';
419
+ }
420
+ return image_url;
421
+ },
422
+
423
+ setup_menus: function() {
424
+ var self = this;
425
+ //console.log( 'setup_menus' );
426
+ self.setup_query_menu();
427
+ self.setup_selector_menu();
428
+ self.setup_rule_menu();
429
+ self.setup_new_rule_menu();
430
+ self.load_queries();
431
+ self.load_rules();
432
+ // selectors will be loaded after query selected
433
+ self.set_query( self.currquery );
434
+ },
435
+
436
+ load_queries: function() {
437
+ var self = this;
438
+ //console.log( 'load_queries' );
439
+ // retrieve unique media queries
440
+ self.query_css( 'queries', null );
441
+ },
442
+
443
+ load_selectors: function() {
444
+ var self = this;
445
+ //console.log( 'load_selectors' );
446
+ // retrieve unique selectors from query value
447
+ self.query_css( 'selectors', self.currquery );
448
+ },
449
+
450
+ load_rules: function() {
451
+ var self = this;
452
+ //console.log( 'load_rules' );
453
+ // retrieve all unique rules
454
+ self.query_css( 'rules', null );
455
+ },
456
+
457
+ load_selector_values: function() {
458
+ var self = this;
459
+ //console.log( 'load_selector_values: ' + self.currqsid );
460
+ // retrieve individual values from qsid
461
+ self.query_css( 'qsid', self.currqsid );
462
+ },
463
+
464
+ get_queries: function( request, response ) {
465
+ //console.log( 'get_queries' );
466
+ //console.log( this );
467
+ var //self = this,
468
+ arr = [],
469
+ matcher = new RegExp( $.ui.autocomplete.escapeRegex( request.term ), "i" );
470
+ if ( $.chldthmcfg.is_empty( this.element.data( 'menu' ) ) ) {
471
+ arr.push( { 'label': window.ctcAjax.nosels_txt, 'value': null } );
472
+ } else {
473
+ // note: key = ndx, value = query name
474
+ $.each( this.element.data( 'menu' ), function( key, val ) {
475
+ if ( matcher.test( val ) ) {
476
+ arr.push( { 'label': val, 'value': val } );
477
+ }
478
+ } );
479
+ }
480
+ response( arr );
481
+ },
482
+
483
+ get_selectors: function( request, response ) {
484
+ //console.log( 'get_selectors' );
485
+ var //self = this,
486
+ arr = [],
487
+ matcher = new RegExp( $.ui.autocomplete.escapeRegex( request.term ), "i" );
488
+ if ( $.chldthmcfg.is_empty( this.element.data( 'menu' ) ) ) {
489
+ arr.push( { 'label': window.ctcAjax.nosels_txt, 'value': null } );
490
+ } else {
491
+ // note: key = selector name, value = qsid
492
+ $.each( this.element.data( 'menu' ), function( key, val ) {
493
+ if ( matcher.test( key ) ) {
494
+ arr.push( { 'label': key, 'value': val } );
495
+ }
496
+ } );
497
+ }
498
+ response( arr );
499
+ },
500
+
501
+ get_rules: function( request, response ) {
502
+ //console.log( 'get_rules' );
503
+ var //self = this,
504
+ arr = [],
505
+ matcher = new RegExp( $.ui.autocomplete.escapeRegex( request.term ), "i" );
506
+ if ( $.chldthmcfg.is_empty( this.element.data( 'menu' ) ) ) {
507
+ arr.push( { 'label': window.ctcAjax.nosels_txt, 'value': null } );
508
+ } else {
509
+ // note: key = ruleid, value = rule name
510
+ $.each( this.element.data( 'menu' ), function( key, val ) {
511
+ if ( matcher.test( key ) ) {
512
+ arr.push( { 'label': key, 'value': val } );
513
+ }
514
+ } );
515
+ }
516
+ response( arr );
517
+ },
518
+
519
+ get_filtered_rules: function( request, response ) {
520
+ //console.log( 'get_filtered_rules' );
521
+ var arr = [],
522
+ matcher = new RegExp( $.ui.autocomplete.escapeRegex( request.term ), "i" ); //,
523
+ $.each( $( '#ctc_rule_menu' ).data( 'menu' ), function( key, val ) {
524
+ //multiple versions of rule ok
525
+ if ( matcher.test( key ) ) {
526
+ arr.push( { 'label': key, 'value': val } );
527
+ }
528
+ } );
529
+ response( arr );
530
+ },
531
+
532
+ /**
533
+ * parent and new values are stored in separate arrays
534
+ * this function puts them into parent/child columns by rulevalid
535
+ */
536
+ merge_ruleval_arrays: function( rule, value, isnew ) {
537
+ //**console.log( 'merge_ruleval_arrays' );
538
+ var self = this,
539
+ valarr = {},
540
+ nextval = isnew ? value.child.pop() : null; // if new rule, pop off the top before counting
541
+ //**console.log( value );
542
+ $.each( [ 'parnt', 'child' ], function( ndx, themetype ) {
543
+ // iterate through parent and child val arrays and populate new assoc array with parent/child for each rulevalid
544
+ if ( !self.is_empty( value[ themetype ] ) ) {
545
+ $.each( value[ themetype ], function( ndx2, val ) {
546
+ if ( isnew ) {
547
+ // if new rule, increment new rulevalid but do not add to parent/child assoc array
548
+ if ( parseInt( val[ 2 ] ) >= parseInt( nextval[ 2 ] ) ) {
549
+ nextval[ 2 ] = parseInt( val[ 2 ] ) + 1;
550
+ }
551
+ } else {
552
+ // add to parent/child assoc array with rulevalid as key
553
+ if ( self.is_empty( valarr[ val[ 2 ] ] ) ) {
554
+ valarr[ val[ 2 ] ] = {};
555
+ }
556
+ valarr[ val[ 2 ] ][ themetype ] = val;
557
+ }
558
+ } );
559
+ }
560
+ } );
561
+ // if new rule, create new parent child assoc array element with new rulevalid as key
562
+ if ( isnew ) {
563
+ valarr[ nextval[ 2 ] ] = {
564
+ parnt: [],
565
+ child: nextval
566
+ };
567
+ }
568
+ return valarr;
569
+ },
570
+
571
+ /**
572
+ * input_row
573
+ * render individual row of inputs for a given selector/rule combination
574
+ * qsid query/selector id
575
+ * rule css property
576
+ * seq panel id from rule/value tab
577
+ * data contains all rules/values for selector
578
+ * isnew is passed true when new rule is selected from menu
579
+ */
580
+ input_row: function( qsid, rule, seq, data, isnew ) {
581
+ //console.log( 'in input_row' );
582
+ var self = this,
583
+ html = '';
584
+ if ( !self.is_empty( data ) && !self.is_empty( data.value ) && !self.is_empty( data.value[ rule ] ) ) {
585
+ var value = data.value[ rule ],
586
+ valarr = self.merge_ruleval_arrays( rule, value, isnew );
587
+ $.each( valarr, function( ndx, val ) {
588
+ var pval = self.decode_value( rule, self.is_empty( val.parnt ) ? '' : val.parnt[ 0 ] ),
589
+ pimp = self.is_empty( val.parnt ) || self.is_empty( val.parnt[ 1 ], 1 ) ? 0 : 1,
590
+ cval = self.decode_value( rule, self.is_empty( val.child ) ? '' : val.child[ 0 ] ),
591
+ cimp = self.is_empty( val.child ) || self.is_empty( val.child[ 1 ], 1 ) ? 0 : 1;
592
+ html += '<div class="ctc-' + ( 'ovrd' === seq ? 'input' : 'selector' ) + '-row clearfix"><div class="ctc-input-cell">';
593
+ if ( 'ovrd' === seq ) {
594
+ html += rule.replace( /\d+/g, self.frascii );
595
+ } else {
596
+ html += data.selector + '<br/><a href="#" class="ctc-selector-edit"' +
597
+ ' id="ctc_selector_edit_' + qsid + '" >' + self.getxt( 'edit' ) + '</a> ' +
598
+ ( self.is_empty( pval.orig ) ? self.getxt( 'child_only' ) : '' );
599
+ }
600
+ html += '</div><div class="ctc-parent-value ctc-input-cell"' + ( 'ovrd' !== seq ? ' style="display:none"' : '' ) +
601
+ ' id="ctc_' + seq + '_parent_' + rule + '_' + qsid + '_' + ndx + '">' +
602
+ ( self.is_empty( pval.orig ) ? '[no value]' : pval.orig + ( pimp ? self.getxt( 'important' ) : '' ) ) +
603
+ '</div><div class="ctc-input-cell">';
604
+ if ( !self.is_empty( pval.names ) ) {
605
+ $.each( pval.names, function( namendx, newname ) {
606
+ newname = ( self.is_empty( newname ) ? '' : newname );
607
+ html += '<div class="ctc-child-input-cell clear">';
608
+ var id = 'ctc_' + seq + '_child_' + rule + '_' + qsid + '_' + ndx + newname,
609
+ newval;
610
+ if ( false === ( newval = cval.values.shift() ) ) {
611
+ newval = '';
612
+ }
613
+
614
+ html += ( self.is_empty( newname ) ? '' : self.getxt( newname ) + ':<br/>' ) +
615
+ '<input type="text" id="' + id + '" name="' + id + '" class="ctc-child-value' +
616
+ ( ( newname + rule ).toString().match( /color/ ) ? ' color-picker' : '' ) +
617
+ ( ( newname ).toString().match( /url/ ) ? ' ctc-input-wide' : '' ) +
618
+ '" value="' + self.escquo( newval ) + '" /></div>';
619
+ } );
620
+ var impid = 'ctc_' + seq + '_child_' + rule + '_i_' + qsid + '_' + ndx;
621
+ html += '<label for="' + impid + '"><input type="checkbox"' +
622
+ ' id="' + impid + '" name="' + impid + '" value="1" ' +
623
+ ( cimp ? 'checked' : '' ) + ' />' +
624
+ self.getxt( 'important' ) + '</label>';
625
+ }
626
+ html += '</div>';
627
+ if ( 'ovrd' !== seq ) {
628
+ html += '<div class="ctc-swatch ctc-specific"' +
629
+ ' id="ctc_child_' + rule + '_' + qsid + '_' + ndx + '_swatch">' +
630
+ self.getxt( 'swatch' ) + '</div>' +
631
+ '<div class="ctc-child-input-cell ctc-button-cell"' +
632
+ ' id="ctc_save_' + rule + '_' + qsid + '_' + ndx + '_cell">' +
633
+ '<input type="button" class="button ctc-save-input"' +
634
+ ' id="ctc_save_' + rule + '_' + qsid + '_' + ndx + '"' +
635
+ ' name="ctc_save_' + rule + '_' + qsid + '_' + ndx + '"' +
636
+ ' value="Save" /></div>';
637
+ }
638
+ html += '</div><!-- end input row -->' + "\n";
639
+ } );
640
+ }
641
+ return html;
642
+ },
643
+
644
+ scrolltop: function() {
645
+ $('html, body, .ctc-option-panel-container').animate( { scrollTop: 0 } );
646
+ },
647
+
648
+ css_preview: function( theme ) {
649
+ var self = this;
650
+ //console.log( 'css_preview: ' + theme );
651
+ if ( !( theme = theme.match( /(child|parnt)/ )[ 1 ] ) ) {
652
+ theme = 'child';
653
+ }
654
+ //console.log( 'css_preview: ' + theme );
655
+ // retrieve raw stylesheet ( parent or child )
656
+ self.query_css( 'preview', theme );
657
+ },
658
+
659
+ /**
660
+ * The "setup" functions initialize jQuery UI widgets
661
+ */
662
+ setup_iris: function( obj ) {
663
+ // deprecated: using spectrum for alpha support
664
+ var self = this;
665
+ self.setup_spectrum( obj );
666
+ },
667
+
668
+ setup_spectrum: function( obj ) {
669
+ var self = this,
670
+ //colortxt = $( obj ).attr( 'id' ) + '_colortxt',
671
+ palette = !self.is_empty( window.ctcAjax.palette );
672
+ try {
673
+ $( obj ).spectrum( {
674
+ showInput: true,
675
+ allowEmpty: true,
676
+ showAlpha: true,
677
+ showInitial: true,
678
+ preferredFormat: "hex", // 'name', //
679
+ clickoutFiresChange: true,
680
+ move: function( color ) {
681
+ $( obj ).data( 'color', color );
682
+ self.coalesce_inputs( obj );
683
+ },
684
+ showPalette: palette ? true : false,
685
+ showSelectionPalette: palette ? true : false,
686
+ palette: [ ],
687
+ maxSelectionSize: 36,
688
+ localStorageKey: "ctc-palette." + window.ctcAjax.child,
689
+ hideAfterPaletteSelect: true,
690
+ } ).on( 'change', function( ){
691
+ //var color = $( this ).spectrum( 'get' );
692
+ //console.log( 'color change: ' + color );
693
+ self.coalesce_inputs( this );
694
+ } ).on( 'keyup', function( ) {
695
+ // update spectrum ui to match text input after half-second delay
696
+ var $this = this,
697
+ $val = self.addhash( $( this ).val() );
698
+ $( $this ).val( $val );
699
+ clearTimeout( $( this ).data( 'spectrumTimer' ) );
700
+ $( this ).data( 'spectrumTimer', setTimeout(
701
+ function() {
702
+ self.coalesce_inputs( $this );
703
+ $( $this ).spectrum( 'set', $val );
704
+ },
705
+ 500
706
+ ) );
707
+ } );
708
+
709
+ } catch ( exn ) {
710
+ self.jquery_exception( exn, 'Spectrum Color Picker' );
711
+ }
712
+ },
713
+ addhash: function( color ) {
714
+ return color.replace( /^#?([a-f0-9]{3,6}.*)/, "#$1" );
715
+ },
716
+ color_text: function( color ) {
717
+ var self = this;
718
+ if ( self.is_empty( color ) ) {
719
+ return '';
720
+ } else if ( color.getAlpha() < 1 ) {
721
+ return color.toRgbString();
722
+ } else {
723
+ return color.toHexString();
724
+ }
725
+ },
726
+
727
+ setup_query_menu: function() {
728
+ var self = this;
729
+ //console.log( 'setup_query_menu' );
730
+ try {
731
+ $( '#ctc_sel_ovrd_query' ).autocomplete( {
732
+ source: self.get_queries,
733
+ minLength: 0,
734
+ selectFirst: true,
735
+ autoFocus: true,
736
+ select: function( e, ui ) {
737
+ self.set_query( ui.item.value );
738
+ return false;
739
+ },
740
+ focus: function( e ) {
741
+ e.preventDefault();
742
+ }
743
+ } ).data( 'menu' , {} );
744
+ } catch ( exn ) {
745
+ self.jquery_exception( exn, 'Query Menu' );
746
+ }
747
+ },
748
+
749
+ setup_selector_menu: function() {
750
+ var self = this;
751
+ //console.log( 'setup_selector_menu' );
752
+ try {
753
+ $( '#ctc_sel_ovrd_selector' ).autocomplete( {
754
+ source: self.get_selectors,
755
+ selectFirst: true,
756
+ autoFocus: true,
757
+ select: function( e, ui ) {
758
+ self.set_selector( ui.item.value, ui.item.label );
759
+ return false;
760
+ },
761
+ focus: function( e ) {
762
+ e.preventDefault();
763
+ }
764
+ } ).data( 'menu' , {} );
765
+ } catch ( exn ) {
766
+ self.jquery_exception( exn, 'Selector Menu' );
767
+ }
768
+ },
769
+
770
+ setup_rule_menu: function() {
771
+ var self = this;
772
+ //console.log( 'setup_rule_menu' );
773
+ try {
774
+ $( '#ctc_rule_menu' ).autocomplete( {
775
+ source: self.get_rules,
776
+ //minLength: 0,
777
+ selectFirst: true,
778
+ autoFocus: true,
779
+ select: function( e, ui ) {
780
+ self.set_rule( ui.item.value, ui.item.label );
781
+ return false;
782
+ },
783
+ focus: function( e ) {
784
+ e.preventDefault();
785
+ }
786
+ } ).data( 'menu' , {} );
787
+ } catch ( exn ) {
788
+ self.jquery_exception( exn, 'Property Menu' );
789
+ }
790
+ },
791
+
792
+ setup_new_rule_menu: function() {
793
+ var self = this;
794
+ try {
795
+ $( '#ctc_new_rule_menu' ).autocomplete( {
796
+ source: self.get_filtered_rules,
797
+ //minLength: 0,
798
+ selectFirst: true,
799
+ autoFocus: true,
800
+ select: function( e, ui ) {
801
+ //console.log( 'new rule selected' );
802
+ e.preventDefault();
803
+ var newrule = ui.item.label.replace( /[^\w\-]/g, self.toascii ),
804
+ row,
805
+ first;
806
+ //console.log( 'current qsdata before:' );
807
+ //console.log( self.currdata );
808
+ if ( self.is_empty( self.currdata.value ) ) {
809
+ self.currdata.value = {};
810
+ }
811
+ if ( self.is_empty( self.currdata.value[ ui.item.label ] ) ) {
812
+ self.currdata.value[ ui.item.label ] = {};
813
+ }
814
+ if ( self.is_empty( self.currdata.value[ ui.item.label ].child ) ) {
815
+ self.currdata.value[ ui.item.label ].child = [];
816
+ }
817
+ //console.log( 'current qsdata after:' );
818
+ //console.log( self.currdata );
819
+ // seed current qsdata with new blank value with id 1
820
+ // this will be modified during input_row function to be next id in order
821
+ self.currdata.value[ ui.item.label ].child.push( [ '', 0, 1, 1 ] );
822
+ row = $( self.input_row( self.currqsid, newrule, 'ovrd', self.currdata, true ) );
823
+ $( '#ctc_sel_ovrd_rule_inputs' ).append( row );
824
+ $( '#ctc_new_rule_menu' ).val( '' );
825
+
826
+ row.find( 'input[type="text"]' ).each( function( ndx, el ) {
827
+ if (! first) {
828
+ first = el;
829
+ }
830
+ if ( $( el ).hasClass( 'color-picker' ) ){
831
+ self.setup_spectrum( el );
832
+ }
833
+ } );
834
+ if ( first ){
835
+ $( first ).focus();
836
+ }
837
+ // if ( self.jqueryerr.length ) {
838
+ // self.jquery_notice( 'setup_new_rule_menu' );
839
+ // }
840
+ return false;
841
+ },
842
+ focus: function( e ) {
843
+ e.preventDefault();
844
+ }
845
+ } ).data( 'menu' , {} );
846
+ } catch ( exn ) {
847
+ self.jquery_exception( exn, 'New Property Menu' );
848
+ }
849
+ },
850
+ set_theme_params: function( themetype, themedir ) {
851
+ $( '#ctc_child_author' ).val( window.ctcAjax.themes[ themetype ][ themedir ].Author );
852
+ $( '#ctc_child_version' ).val( window.ctcAjax.themes[ themetype ][ themedir ].Version );
853
+ $( '#ctc_child_authoruri' ).val( window.ctcAjax.themes[ themetype ][ themedir ].AuthorURI );
854
+ $( '#ctc_child_themeuri' ).val( window.ctcAjax.themes[ themetype ][ themedir ].ThemeURI );
855
+ $( '#ctc_child_descr' ).val( window.ctcAjax.themes[ themetype ][ themedir ].Descr );
856
+ $( '#ctc_child_tags' ).val( window.ctcAjax.themes[ themetype ][ themedir ].Tags );
857
+ },
858
+ update_form: function() {
859
+ var self = this,
860
+ themedir;
861
+ $( '#input_row_stylesheet_handling_container,#input_row_parent_handling_container,#ctc_additional_css_files_container,#input_row_new_theme_slug,#input_row_duplicate_theme_slug,#ctc_copy_theme_mods,#ctc_child_header_parameters,#ctc_configure_submit,#input_row_theme_slug' ).slideUp( 'fast' );
862
+ $( '#ctc_configure_submit .ctc-step' ).text( '9' );
863
+ if ( $( '#ctc_theme_child' ).length && !$( '#ctc_child_type_new' ).is( ':checked' ) ) {
864
+ themedir = $( '#ctc_theme_child' ).val();
865
+ //console.log( 'update_form (existing) ... ' + themedir );
866
+ self.existing = 1;
867
+ self.currparnt = window.ctcAjax.themes.child[ themedir ].Template;
868
+ self.autogen_slugs();
869
+ $( '#ctc_theme_parnt' ).val( self.currparnt );
870
+ $( '#ctc_theme_parnt-button .ui-selectmenu-text' ).text( self.getname( 'parnt' ) );
871
+ self.set_theme_params( 'child', themedir );
872
+ //self.set_child_menu( document.getElementById( 'ctc_theme_child' ) );
873
+ if ( $( '#ctc_child_type_duplicate' ).is( ':checked' ) ) {
874
+ $( '#ctc_child_template' ).val( self.testslug );
875
+ $( '#ctc_child_name' ).val( self.testname );
876
+ $( '.ctc-analyze-theme, .ctc-analyze-howto' ).show();
877
+ $( '#ctc_load_styles' ).val( 'Duplicate Child Theme' );
878
+ } else if ( $( '#ctc_child_type_reset' ).is( ':checked' ) ) {
879
+ $( '#ctc_configure_submit .ctc-step' ).text( '3' );
880
+ $( '#ctc_configure_submit' ).slideDown( 'fast' );
881
+ $( '#theme_slug_container' ).text( themedir );
882
+ $( '.ctc-analyze-theme, .ctc-analyze-howto' ).hide();
883
+ //$( '#input_row_theme_slug' ).slideDown( 'fast' );
884
+ $( '#ctc_enqueue_none' ).prop( 'checked', true );
885
+ $( '#ctc_load_styles' ).val( 'Reset Child Theme to Previous State' );
886
+ } else {
887
+ $( '#ctc_child_template' ).val( '' );
888
+ $( '#theme_slug_container' ).text( themedir );
889
+ $( '.ctc-analyze-theme, .ctc-analyze-howto' ).show();
890
+ $( '#ctc_child_name' ).val( self.getname( 'child' ) );
891
+ $( '#ctc_load_styles' ).val( 'Configure Child Theme' );
892
+ }
893
+ $( '#input_row_existing_theme_option' ).slideDown( 'fast' );
894
+ $( '#input_row_new_theme_option' ).slideUp( 'fast' );
895
+ } else {
896
+ self.existing = 0;
897
+ self.autogen_slugs();
898
+ //themedir = $( '#ctc_theme_parnt' ).val();
899
+ $( '#ctc_theme_parnt' ).val( self.currparnt );
900
+ $( '#ctc_theme_parnt-button .ui-selectmenu-text' ).text( $.chldthmcfg.getname( 'parnt' ) );
901
+ //console.log( 'update_form (new) ... ' + self.currparnt );
902
+ //self.set_parent_menu( document.getElementById( 'ctc_theme_parnt' ) );
903
+ //console.log( 'setting to new...' + $( '#ctc_theme_parnt' ).val() );
904
+ self.set_theme_params( 'parnt', self.currparnt );
905
+ $( '#input_row_existing_theme_option,#input_row_duplicate_theme_container,#input_row_theme_slug' ).slideUp( 'fast' );
906
+ $( '#input_row_new_theme_option' ).slideDown( 'fast' );
907
+ $( '#ctc_child_name' ).val( self.testname );
908
+ $( '#ctc_child_template' ).val( self.testslug );
909
+ $( '.ctc-analyze-theme, .ctc-analyze-howto' ).show();
910
+ $( '#ctc_load_styles' ).val( 'Create New Child Theme' );
911
+ }
912
+ /* 2.0.0 maybe necessary?
913
+ // disable copy theme options if parent not allowed
914
+ // console.log( window.ctcAjax.themes );
915
+ // console.log( self.currparnt );
916
+ if ( window.ctcAjax.themes.parnt[ self.currparnt ].allowed ){
917
+ // console.log( 'allowed' );
918
+ $( '#ctc_copy_theme_mods' ).slideDown( 'fast' );
919
+ $( '#ctc_parent_mods' ).prop( 'disabled', false );
920
+
921
+ } else {
922
+ // console.log( 'not allowed' );
923
+ $( '#ctc_parent_mods' ).prop( 'disabled', true ).prop( 'checked', false );
924
+ $( '#ctc_copy_theme_mods' ).slideUp( 'fast' );
925
+ }
926
+ */
927
+
928
+ },
929
+ set_notice: function( noticearr ) {
930
+ var self = this,
931
+ errorHtml = '',
932
+ out;
933
+ if ( !self.is_empty( noticearr ) ) {
934
+ $.each( noticearr, function( type, list ) {
935
+ errorHtml += '<div class="' + type + ' notice is-dismissible dashicons-before"><ul>' + "\n";
936
+ $( list ).each( function( ndx, el ) {
937
+ errorHtml += '<li>' + el.toString() + '</li>' + "\n";
938
+ } );
939
+ errorHtml += '</ul></div>';
940
+ } );
941
+ }
942
+ out = $( errorHtml );
943
+ $( '#ctc_error_notice' ).html( out );
944
+ self.bind_dismiss( out );
945
+ $( 'html, body' ).animate( { scrollTop: 0 }, 'slow' );
946
+ },
947
+
948
+ set_parent_menu: function( obj ) {
949
+ // refresh page with current parent theme
950
+ var self = this;
951
+ self.currparnt = obj.value;
952
+ self.update_form();
953
+ //self.show_loading();
954
+ //document.location = '?page=' + window.ctcAjax.page + '&ctc_parent=' + obj.value;
955
+ },
956
+
957
+ set_child_menu: function( obj ) {
958
+ var self = this;
959
+ self.currchild = obj.value;
960
+ self.update_form();
961
+ },
962
+
963
+ set_query: function( value ) {
964
+ var self = this;
965
+ if ( self.is_empty( value ) ) {
966
+ return false;
967
+ }
968
+ //console.log( 'set_query: ' + value );
969
+ self.currquery = value;
970
+ $( '#ctc_sel_ovrd_query' ).val( '' );
971
+ $( '#ctc_sel_ovrd_query_selected' ).text( value );
972
+ $( '#ctc_sel_ovrd_selector' ).val( '' );
973
+ $( '#ctc_sel_ovrd_selector_selected' ).html( '&nbsp;' );
974
+ self.load_selectors();
975
+ self.scrolltop();
976
+ },
977
+
978
+ set_selector: function( value, label ) {
979
+ var self = this;
980
+ label = null;
981
+ if ( self.is_empty( value ) ) {
982
+ return false;
983
+ }
984
+ //console.log( 'set_selector: ' + value + ' label: ' + label );
985
+ $( '#ctc_sel_ovrd_selector' ).val( '' );
986
+ self.currqsid = value;
987
+ self.reload = false;
988
+ self.load_selector_values();
989
+ self.scrolltop();
990
+ },
991
+
992
+ set_rule: function( value, label ) {
993
+ //console.log( 'set_rule: ' + value + ' label: ' + label );
994
+ var self = this;
995
+ if ( self.is_empty( value ) ) {
996
+ return false;
997
+ }
998
+ $( '#ctc_rule_menu' ).val( '' );
999
+ $( '#ctc_rule_menu_selected' ).text( label );
1000
+ $( '.ctc-rewrite-toggle' ).text( self.getxt( 'rename' ) );
1001
+ $( '#ctc_rule_value_inputs, #ctc_input_row_rule_header' ).show();
1002
+ // retrieve unique values by rule
1003
+ self.query_css( 'rule_val', value );
1004
+ self.scrolltop();
1005
+ },
1006
+
1007
+ set_qsid: function( obj ) {
1008
+ var self = this;
1009
+ //console.log( 'set_qsid: ' + $( obj ).attr( 'id' ) );
1010
+ self.currqsid = $( obj ).attr( 'id' ).match( /_(\d+)$/ )[ 1 ];
1011
+ self.focus_panel( '#query_selector_options' );
1012
+ self.reload = true;
1013
+ self.load_selector_values();
1014
+ },
1015
+ /**
1016
+ * Retrieve data from server and execute callback on completion
1017
+ */
1018
+ query_css: function( obj, key, params ) {
1019
+ //console.log( 'query_css: ' + obj + ' key: ' + key );
1020
+ var self = this,
1021
+ postdata = { 'ctc_query_obj' : obj, 'ctc_query_key': key },
1022
+ status_sel = '#ctc_status_' + obj + ( 'val_qry' === obj ? '_' + key : '' );
1023
+
1024
+ if ( 'object' === typeof params ) {
1025
+ $.each( params, function( key, val ) {
1026
+ postdata[ 'ctc_query_' + key ] = val;
1027
+ } );
1028
+ }
1029
+ $( '.query-icon,.ctc-status-icon' ).remove();
1030
+ //console.log( status_sel + ' ' + $( status_sel ).length );
1031
+ $( status_sel + ' .ctc-status-icon' ).remove();
1032
+ $( status_sel ).append( '<span class="ctc-status-icon spinner is-active query-icon"></span>' );
1033
+ // add wp ajax action to array
1034
+ //console.log( $( '#ctc_action' ).val() );
1035
+ postdata.action = ( !self.is_empty( $( '#ctc_action' ).val() ) &&
1036
+ 'plugin' === $( '#ctc_action' ).val() ) ?
1037
+ 'ctc_plgqry' : 'ctc_query';
1038
+ postdata._wpnonce = $( '#_wpnonce' ).val();
1039
+ // ajax post input data
1040
+ //console.log( 'query_css postdata:' );
1041
+ //console.log( postdata );
1042
+ self.ajax_post( obj, postdata );
1043
+ },
1044
+ /**
1045
+ * Post data to server for saving and execute callback on completion
1046
+ */
1047
+ save: function( obj ) {
1048
+ //console.log( 'save: ' + $( obj ).attr( 'id' ) );
1049
+ var self = this,
1050
+ postdata = {},
1051
+ $selector,
1052
+ $query,
1053
+ $imports,
1054
+ id = $( obj ).attr( 'id' ),
1055
+ newsel,
1056
+ origsel;
1057
+
1058
+ // disable the button until ajax returns
1059
+ $( obj ).prop( 'disabled', true );
1060
+ // clear previous success/fail icons
1061
+ $( '.ctc-query-icon,.ctc-status-icon' ).remove();
1062
+ // show spinner
1063
+ $( obj ).parent( '.ctc-textarea-button-cell, .ctc-button-cell' )
1064
+ .append( '<span class="ctc-status-icon spinner save-icon"></span>' );
1065
+ if ( id.match( /ctc_configtype/ ) ) {
1066
+ $( obj ).parents( '.ctc-input-row' ).first()
1067
+ .append( '<span class="ctc-status-icon spinner save-icon"></span>' );
1068
+ postdata.ctc_configtype = $( obj ).val();
1069
+ } else if ( ( $selector = $( '#ctc_new_selectors' ) ) &&
1070
+ 'ctc_save_new_selectors' === $( obj ).attr( 'id' ) ) {
1071
+ postdata.ctc_new_selectors = $selector.val();
1072
+ if ( ( $query = $( '#ctc_sel_ovrd_query_selected' ) ) ) {
1073
+ postdata.ctc_sel_ovrd_query = $query.text();
1074
+ }
1075
+ self.reload = true;
1076
+ } else if ( ( $imports = $( '#ctc_child_imports' ) ) &&
1077
+ 'ctc_save_imports' === id ) {
1078
+ postdata.ctc_child_imports = $imports.val();
1079
+ } else if ( 'ctc_is_debug' === id ) {
1080
+ postdata.ctc_is_debug = $( '#ctc_is_debug' ).is( ':checked' ) ? 1 : 0;
1081
+ } else {
1082
+ // coalesce inputs
1083
+ postdata = self.coalesce_inputs( obj );
1084
+ }
1085
+ $( '.save-icon' ).addClass( 'is-active' );
1086
+ // add rename selector value if it exists
1087
+ $( '#ctc_sel_ovrd_selector_selected' )
1088
+ .find( '#ctc_rewrite_selector' ).each( function() {
1089
+ newsel = $( '#ctc_rewrite_selector' ).val();
1090
+ origsel = $( '#ctc_rewrite_selector_orig' ).val();
1091
+ if ( self.is_empty( newsel ) || !newsel.toString().match( /\w/ ) ) {
1092
+ newsel = origsel;
1093
+ } else {
1094
+ postdata.ctc_rewrite_selector = newsel;
1095
+ self.reload = true;
1096
+ }
1097
+ $( '.ctc-rewrite-toggle' ).text( self.getxt( 'rename' ) );
1098
+ $( '#ctc_sel_ovrd_selector_selected' ).html( newsel );
1099
+ } );
1100
+ // add wp ajax action to array
1101
+ //console.log( $( '#ctc_action' ).val() );
1102
+ postdata.action = ( !self.is_empty( $( '#ctc_action' ).val() ) &&
1103
+ 'plugin' === $( '#ctc_action' ).val() ) ?
1104
+ 'ctc_plugin' : 'ctc_update';
1105
+ postdata._wpnonce = $( '#_wpnonce' ).val();
1106
+ //console.log( postdata );
1107
+ // ajax post input data
1108
+ self.ajax_post( 'qsid', postdata );
1109
+ },
1110
+
1111
+ ajax_post: function( obj, data, datatype ) {
1112
+ var self = this;
1113
+ //console.log( 'ajax_post: ' + obj );
1114
+ //console.log( data );
1115
+ //console.log( window.ctcAjax.ajaxurl );
1116
+ //console.log( window.ctcAjax.ajaxurl );
1117
+ // get ajax url from localized object
1118
+ $.ajax( {
1119
+ url: window.ctcAjax.ajaxurl,
1120
+ data: data,
1121
+ dataType:
1122
+ //'ctc_update' === data.action && 'qsid' === obj ? 'text' :
1123
+ //'ctc_update' == data.action && //
1124
+ //'rule_val' === obj ? 'text' : // 'qsid' == obj ? 'text' :
1125
+ ( self.is_empty( datatype ) ? 'json' : datatype ),
1126
+ type: 'POST'
1127
+ } ).done( function( response ) {
1128
+ //console.log( response );
1129
+ self.handle_success( obj, response );
1130
+ } ).fail( function() { // jxr, status, err ) {
1131
+ //console.log( status );
1132
+ //console.log( err );
1133
+ self.handle_failure( obj );
1134
+ } ).always( function() {
1135
+ if ( self.jqueryerr.length ) {
1136
+ self.jquery_notice();
1137
+ }
1138
+ } );
1139
+ },
1140
+
1141
+ handle_failure: function( obj ) {
1142
+ var self = this;
1143
+ //console.log( 'handle_failure: ' + obj );
1144
+ $( '.query-icon, .save-icon' ).removeClass( 'spinner' ).addClass( 'failure' );
1145
+ $( 'input[type=submit], input[type=button], input[type=checkbox],.ctc-delete-input' ).prop( 'disabled', false );
1146
+ $( '.ajax-pending' ).removeClass( 'ajax-pending' );
1147
+ //FIXME: return fail text in ajax response
1148
+ if ( 'preview' === obj ) {
1149
+ $( '#view_parnt_options_panel,#view_child_options_panel' )
1150
+ .text( self.getxt( 'css_fail' ) );
1151
+ }
1152
+ },
1153
+
1154
+ handle_success: function( obj, response ) {
1155
+ var self = this;
1156
+ // query response
1157
+ //console.log( 'handle_success: ' + obj );
1158
+ //console.log( response );
1159
+ // hide spinner
1160
+ $( '.query-icon, .save-icon' ).removeClass( 'spinner' );
1161
+ $( '.ajax-pending' ).removeClass( 'ajax-pending' );
1162
+ // hide spinner
1163
+ if ( self.is_empty( response ) ) {
1164
+ self.handle_failure( obj );
1165
+ } else {
1166
+ $( '#ctc_new_selectors' ).val( '' );
1167
+ // update data objects
1168
+ // show check mark
1169
+ // FIXME: distinction between save and query, update specific status icon
1170
+ $( '.query-icon, .save-icon' ).addClass( 'success' );
1171
+ $( 'input[type=submit], input[type=button], input[type=checkbox],.ctc-delete-input' ).prop( 'disabled', false );
1172
+ // update ui from each response object
1173
+ $( response ).each( function() {
1174
+ if ( 'function' === typeof self.update[ this.obj ] ) {
1175
+ //console.log( 'executing method update.' + this.obj );
1176
+ self.update[ this.obj ].call( self, this );
1177
+ } else {
1178
+ //console.log( 'Fail: no method update.' + this.obj );
1179
+ }
1180
+ } );
1181
+ }
1182
+ },
1183
+
1184
+ jquery_exception: function( exn, type ) {
1185
+ var self = this,
1186
+ ln = self.is_empty( exn.lineNumber ) ? '' : ' line: ' + exn.lineNumber,
1187
+ fn = self.is_empty( exn.fileName ) ? '' : ' ' + exn.fileName.split( /\?/ )[ 0 ];
1188
+ self.jqueryerr.push( '<code><small>' + type + ': ' + exn.message + fn + ln + '</small></code>' );
1189
+ //console.log( 'jquery error detected' );
1190
+ },
1191
+
1192
+ jquery_notice: function( fn ) {
1193
+ //console.log( fn );
1194
+ fn = null;
1195
+ var self = this,
1196
+ culprits = [],
1197
+ errors = [];
1198
+ if ( self.jqueryerr.length ){
1199
+ // disable form submits
1200
+ $( 'input[type=submit], input[type=button]' ).prop( 'disabled', true );
1201
+ $( 'script' ).each( function(){
1202
+ var url = $( this ).prop( 'src' );
1203
+ if ( !self.is_empty( url ) && url.match( /jquery(\.min|\.js|\-?ui)/i ) &&
1204
+ ! url.match( /load\-scripts.php/ ) ) {
1205
+ culprits.push( '<code><small>' + url.split( /\?/ )[ 0 ] + '</small></code>' );
1206
+ }
1207
+ } );
1208
+ errors.push( '<strong>' + self.getxt( 'js' ) + '</strong> ' + self.getxt( 'contact' ) );
1209
+ //if ( 1 == window.ctcAjax.is_debug ) {
1210
+ errors.push( self.jqueryerr.join( '<br/>' ) );
1211
+ //}
1212
+ if ( culprits.length ) {
1213
+ errors.push( self.getxt( 'jquery' ) + '<br/>' + culprits.join( '<br/>' ) );
1214
+ }
1215
+ errors.push( self.getxt( 'plugin' ) );
1216
+ }
1217
+ //return errors;
1218
+ self.set_notice( { 'error': errors } );
1219
+ },
1220
+ /*
1221
+ // test for jquery issues
1222
+
1223
+ $.each( jqueryerr, function( index, err ) {
1224
+ notice.hasnotice = 1;
1225
+ notice.style = 'error';
1226
+ notice.jquery += err;
1227
+ } );
1228
+ */
1229
+
1230
+
1231
+ update: {
1232
+ // render individual selector inputs on Query/Selector tab
1233
+ qsid: function( res ) {
1234
+ //console.log( res );
1235
+ var self = this,
1236
+ id, html, val, empty;
1237
+ self.currqsid = res.key;
1238
+ self.currdata = res.data;
1239
+ //console.log( 'update.qsid: ' + self.currqsid );
1240
+ $( '#ctc_sel_ovrd_qsid' ).val( self.currqsid );
1241
+ if ( self.is_empty( self.currdata.seq ) ) {
1242
+ $( '#ctc_child_load_order_container' ).empty();
1243
+ } else {
1244
+ id = 'ctc_ovrd_child_seq_' + self.currqsid;
1245
+ val = parseInt( self.currdata.seq );
1246
+ html = '<input type="text" id="' + id + '" name="' + id + '"' +
1247
+ ' class="ctc-child-value" value="' + val + '" />';
1248
+ $( '#ctc_child_load_order_container' ).html( html );
1249
+ }
1250
+ if ( self.is_empty( self.currdata.value ) ) {
1251
+ //console.log( 'qsdata is empty' );
1252
+ empty = true;
1253
+ $( '#ctc_sel_ovrd_rule_inputs' ).empty();
1254
+ } else {
1255
+ //console.log( 'qsdata NOT empty' );
1256
+ empty = false;
1257
+ html = '';
1258
+ $.each( self.currdata.value, function( rule, value ) {
1259
+ value = null;
1260
+ html += self.input_row( self.currqsid, rule, 'ovrd', self.currdata );
1261
+ } );
1262
+ $( '#ctc_sel_ovrd_rule_inputs' ).html( html ).find( '.color-picker' ).each( function() {
1263
+ self.setup_spectrum( this );
1264
+ } );
1265
+ self.coalesce_inputs( '#ctc_child_all_0_swatch' );
1266
+ }
1267
+ // if ( self.jqueryerr.length ) {
1268
+ // self.jquery_notice( 'update.qsid' );
1269
+ // } else {
1270
+ //console.log( 'reload menus: ' + ( self.reload ? 'true' : 'false' ) );
1271
+ if ( self.reload ) {
1272
+ self.load_queries();
1273
+ self.set_query( self.currdata.query );
1274
+ self.load_rules();
1275
+ }
1276
+ $( '#ctc_sel_ovrd_selector_selected' ).text( self.currdata.selector );
1277
+ $( '.ctc-rewrite-toggle' ).text( self.getxt( 'rename' ) );
1278
+ $( '.ctc-rewrite-toggle' ).show();
1279
+ if ( !empty ){
1280
+ $( '#ctc_sel_ovrd_rule_header,' +
1281
+ '#ctc_sel_ovrd_new_rule,' +
1282
+ '#ctc_sel_ovrd_rule_inputs_container,' +
1283
+ '#ctc_sel_ovrd_rule_inputs' ).show();
1284
+ } else {
1285
+ $( '#ctc_sel_ovrd_rule_header,' +
1286
+ '#ctc_sel_ovrd_new_rule,' +
1287
+ '#ctc_sel_ovrd_rule_inputs_container,' +
1288
+ '#ctc_sel_ovrd_rule_inputs' ).hide();
1289
+ }
1290
+ //self.scrolltop();
1291
+ // }
1292
+ },
1293
+ // render list of unique values for given rule on Property/Value tab
1294
+ rule_val: function( res ) {
1295
+ //console.log( 'update.rule_val: ' + res.key );
1296
+ //console.log( res.data );
1297
+ var self = this,
1298
+ rule = $( '#ctc_rule_menu_selected' ).text(),
1299
+ html = '<div class="ctc-input-row clearfix" id="ctc_rule_row_' + rule + '">' + "\n";
1300
+ //console.log( 'rule: ' + rule );
1301
+ if ( !self.is_empty( res.data ) ) {
1302
+ $.each( res.data, function( valid, value ) {
1303
+ var parentObj = self.decode_value( rule, value );
1304
+ html += '<div class="ctc-parent-row clearfix"' +
1305
+ ' id="ctc_rule_row_' + rule + '_' + valid + '">' + "\n" +
1306
+ '<div class="ctc-input-cell ctc-parent-value"' +
1307
+ ' id="ctc_' + valid + '_parent_' + rule + '_' + valid + '">' +
1308
+ parentObj.orig + '</div>' + "\n" +
1309
+ '<div class="ctc-input-cell">' + "\n" +
1310
+ '<div class="ctc-swatch ctc-specific"' +
1311
+ ' id="ctc_' + valid + '_parent_' + rule + '_' + valid + '_swatch">' +
1312
+ self.getxt( 'swatch' ) + '</div></div>' + "\n" +
1313
+ '<div class="ctc-input-cell">' +
1314
+ '<a href="#" class="ctc-selector-handle"' +
1315
+ ' id="ctc_selector_' + rule + '_' + valid + '">' +
1316
+ self.getxt( 'selector' ) + '</a></div>' + "\n" +
1317
+ '<div id="ctc_selector_' + rule + '_' + valid + '_container"' +
1318
+ ' class="ctc-selector-container">' + "\n" +
1319
+ '<a href="#" id="ctc_selector_' + rule + '_' + valid + '_close"' +
1320
+ ' class="ctc-selector-handle ctc-exit" title="' +
1321
+ self.getxt( 'close' ) + '"></a>' +
1322
+ '<div id="ctc_selector_' + rule + '_' + valid + '_inner_container"' +
1323
+ ' class="ctc-selector-inner-container clearfix">' + "\n" +
1324
+ '<div id="ctc_status_val_qry_' + valid + '"></div>' + "\n" +
1325
+ '<div id="ctc_selector_' + rule + '_' + valid + '_rows"></div>' + "\n" +
1326
+ '</div></div></div>' + "\n";
1327
+ } );
1328
+ html += '</div>' + "\n";
1329
+ }
1330
+ $( '#ctc_rule_value_inputs' ).html( html ).find( '.ctc-swatch' ).each( function() {
1331
+ self.coalesce_inputs( this );
1332
+ } );
1333
+ },
1334
+ // render list of selectors grouped by query for given value on Property/Value Tab
1335
+ val_qry: function( res ) {
1336
+ //console.log( 'in val_qry' );
1337
+ //console.log( res );
1338
+ var self = this,
1339
+ html = '',
1340
+ page_rule,
1341
+ selector;
1342
+ if ( !self.is_empty( res.data ) ) {
1343
+ $.each( res.data, function( rule, queries ) {
1344
+ page_rule = rule;
1345
+ $.each( queries, function( query, selectors ) {
1346
+ html += '<h4 class="ctc-query-heading">' + query + '</h4>' + "\n";
1347
+ if ( !self.is_empty( selectors ) ) {
1348
+ $.each( selectors, function( qsid, qsdata ) {
1349
+ html += self.input_row( qsid, rule, res.key, qsdata );
1350
+ } );
1351
+ }
1352
+ } );
1353
+ } );
1354
+ }
1355
+ selector = '#ctc_selector_' + page_rule + '_' + res.key + '_rows';
1356
+ //console.log( selector );
1357
+
1358
+ $( selector ).html( html ).find( '.color-picker' ).each( function() {
1359
+ self.setup_spectrum( this );
1360
+ } );
1361
+ $( selector ).find( '.ctc-swatch' ).each( function() {
1362
+ self.coalesce_inputs( this );
1363
+ } );
1364
+ // if ( self.jqueryerr.length ) {
1365
+ // self.jquery_notice( 'val_qry' );
1366
+ // }
1367
+ },
1368
+ // populate list of queries and attach to query input element
1369
+ queries: function( res ) {
1370
+ $( '#ctc_sel_ovrd_query' ).data( 'menu', res.data );
1371
+ },
1372
+ // populate list of selectors and attach to selector input element
1373
+ selectors: function( res ) {
1374
+ $( '#ctc_sel_ovrd_selector' ).data( 'menu', res.data );
1375
+ },
1376
+ // populate list of rules and attach to rule input element
1377
+ rules: function( res ) {
1378
+ $( '#ctc_rule_menu' ).data( 'menu', res.data );
1379
+ },
1380
+ // render debug output
1381
+ debug: function( res ) {
1382
+ $( '#ctc_debug_box' ).val( $( '#ctc_debug_box' ).val() + res.data );
1383
+ //console.log( 'debug:' );
1384
+ //console.log( res.data );
1385
+ },
1386
+ // render stylesheet preview on child or parent css tab
1387
+ preview: function( res ) {
1388
+ $( '#view_' + res.key + '_options_panel' ).text( res.data );
1389
+ },
1390
+ dismiss: function() { // res ) {
1391
+ //console.log( 'dismiss came home!' );
1392
+ //console.log( res );
1393
+ //var self = this;
1394
+ //self.dismiss_notice();
1395
+ }
1396
+
1397
+ },
1398
+ // applies core dismiss behavior to injected elements
1399
+ bind_dismiss: function( el ) {
1400
+ //console.log( 'bind_dismiss' );
1401
+ var self = this,
1402
+ $this = $( el ),
1403
+ $button = $( '<button type="button" class="notice-dismiss"><span class="screen-reader-text"></span></button>' ),
1404
+ btnText = window.commonL10n.dismiss || '';
1405
+
1406
+ // Ensure plain text
1407
+ $button.find( '.screen-reader-text' ).text( btnText );
1408
+
1409
+ $this.append( $button );
1410
+
1411
+ $button.on( 'click.wp-dismiss-notice', function( event ) {
1412
+ event.preventDefault();
1413
+ self.dismiss_notice( el );
1414
+ });
1415
+ },
1416
+ dismiss_notice: function( el ) {
1417
+ $( el ).fadeTo( 100 , 0, function() {
1418
+ $( this ).slideUp( 100, function() {
1419
+ $( this ).remove();
1420
+ });
1421
+ });
1422
+ },
1423
+ reset_handling: function() {
1424
+ //console.log( '----> resetting form...' );
1425
+ $( '#parnt_analysis_notice .notice, #child_analysis_notice .notice' ).slideUp();
1426
+ $( '#ctc_enqueue_enqueue' ).prop( 'checked', true );
1427
+ $( '#ctc_handling_primary' ).prop( 'checked', true );
1428
+ $( '#ctc_ignoreparnt' ).prop( 'checked', false );
1429
+ $( '#ctc_repairheader' ).prop( 'checked', false );
1430
+ },
1431
+ // initialize object vars, bind event listeners to elements, load menus and start plugin
1432
+ init: function() {
1433
+ //console.log( 'initializing...' )
1434
+ var self = this;
1435
+ //self.jquery_exception( { 'message':'testing' }, 'Testing' );
1436
+ // try to initialize theme menus
1437
+ if ( !$( '#ctc_theme_parnt' ).is( 'input' ) ) {
1438
+ //console.log( 'initializing theme select menus...' );
1439
+ try {
1440
+ $.widget( 'ctc.themeMenu', $.ui.selectmenu, {
1441
+ _renderItem: function( ul, item ) {
1442
+ var li = $( "<li>" ),
1443
+ sel = item.value.replace( /[^\w\-]/, '' );
1444
+ $( '#ctc_theme_option_' + sel )
1445
+ .detach().appendTo( li );
1446
+ return li.appendTo( ul );
1447
+ }
1448
+ } );
1449
+ } catch( exn ) {
1450
+ self.jquery_exception( exn, 'Theme Menu' );
1451
+ }
1452
+ try {
1453
+ $( '#ctc_theme_parnt' ).themeMenu( {
1454
+ select: function( event, ui ) {
1455
+ self.reset_handling();
1456
+ self.set_parent_menu( ui.item );
1457
+ }
1458
+ } );
1459
+ } catch( exn ) {
1460
+ if ( 'function' === typeof themeMenu ) {
1461
+ $( '#ctc_theme_parnt' ).themeMenu( 'destroy' );
1462
+ } else {
1463
+ $( '#ctc_theme_parnt-button' ).remove();
1464
+ }
1465
+ self.jquery_exception( exn, 'Parent Theme Menu' );
1466
+ }
1467
+ if ( self.is_empty( window.ctcAjax.themes.child ) ) {
1468
+ if ( $( '#ctc_child_name' ).length ) {
1469
+ $( '#ctc_child_name' ).val( self.testname );
1470
+ $( '#ctc_child_template' ).val( self.testslug );
1471
+ }
1472
+ } else {
1473
+ try {
1474
+ $( '#ctc_theme_child' ).themeMenu( {
1475
+ select: function( event, ui ) {
1476
+ self.reset_handling();
1477
+ self.set_child_menu( ui.item );
1478
+ }
1479
+ } );
1480
+ } catch( exn ) {
1481
+ if ( 'function' === typeof themeMenu ) {
1482
+ $( '#ctc_theme_child' ).themeMenu( 'destroy' );
1483
+ } else {
1484
+ $( '#ctc_theme_child-button' ).remove();
1485
+ }
1486
+ self.jquery_exception( exn, 'Child Theme Menu' );
1487
+ }
1488
+ }
1489
+ }
1490
+
1491
+ // auto populate parent/child tab values
1492
+ self.currparnt = $( '#ctc_theme_parnt' ).val();
1493
+ self.currchild = $( '#ctc_theme_child' ).length ? $( '#ctc_theme_child' ).val() : '';
1494
+ $( '#ctc_main' ).on( 'click', '.ctc-section-toggle', function( e ) {
1495
+ e.preventDefault();
1496
+ $( this ).parents( '.ctc-input-row, .notice-warning, .updated, .error' ).first().find( '.ctc-section-toggle' )
1497
+ .each( function() {
1498
+ $( this ).toggleClass( 'open' );
1499
+ } );
1500
+ var id = $( this ).attr( 'id' ).replace(/\d$/, '') + '_content';
1501
+ $( '#' + id ).stop().slideToggle( 'fast' );
1502
+ return false;
1503
+ } );
1504
+
1505
+ $( '#ctc_main' ).on( 'click', '.ctc-upgrade-notice .notice-dismiss', function() { // e ) {
1506
+ //console.log( 'dismiss upgrade clicked!' );
1507
+ //e.preventDefault();
1508
+ var postdata = {
1509
+ 'action': 'ctc_dismiss',
1510
+ '_wpnonce': $( '#_wpnonce' ).val()
1511
+ };
1512
+ self.ajax_post( 'dismiss', postdata );
1513
+ } );
1514
+
1515
+ if ( self.is_empty( self.jqueryerr ) ){
1516
+ //console.log( 'delegating event bindings...' )
1517
+ $( '#ctc_main' ).on( 'click', '.ctc-selector-handle', function( e ) {
1518
+ //'.ctc-option-panel-container'
1519
+ e.preventDefault();
1520
+ if ( $( this ).hasClass( 'ajax-pending' ) ) {
1521
+ return false;
1522
+ }
1523
+ $( this ).addClass( 'ajax-pending' );
1524
+ //set_notice( '' );
1525
+ var id = $( this ).attr( 'id' ).toString().replace( '_close', '' ),
1526
+ parts = id.toString().match( /_([^_]+)_(\d+)$/ ),
1527
+ rule,
1528
+ valid;
1529
+ if ( $( '#' + id + '_container' ).is( ':hidden' ) ) {
1530
+ if ( !self.is_empty( parts[ 1 ] ) && !self.is_empty( parts[ 2 ] ) ) {
1531
+ rule = parts[ 1 ];
1532
+ valid = parts[ 2 ];
1533
+ // retrieve selectors / values for individual value
1534
+ self.query_css( 'val_qry', valid, { 'rule': rule } );
1535
+ }
1536
+ }
1537
+ $( '#' + id + '_container' ).fadeToggle( 'fast' );
1538
+ $( '.ctc-selector-container' ).not( '#' + id + '_container' ).fadeOut( 'fast' );
1539
+ } );
1540
+
1541
+ $( '#ctc_main' ).on( 'click', '.ctc-save-input[type=button], .ctc-delete-input', function( e ) {
1542
+ e.preventDefault();
1543
+ if ( $( this ).hasClass( 'ajax-pending' ) ) {
1544
+ return false;
1545
+ }
1546
+ $( this ).addClass( 'ajax-pending' );
1547
+ self.save( this ); // refresh menus after updating data
1548
+ return false;
1549
+ } );
1550
+
1551
+ $( '#ctc_main' ).on( 'keydown', '.ctc-selector-container .ctc-child-value[type=text]', function( e ) {
1552
+ if ( 13 === e.which ) {
1553
+ //console.log( 'return key pressed' );
1554
+ var $obj = $( this ).parents( '.ctc-selector-row' ).find( '.ctc-save-input[type=button]' ).first();
1555
+ if ( $obj.length ) {
1556
+ e.preventDefault();
1557
+ //console.log( $obj.attr( 'id' ) );
1558
+ if ( $obj.hasClass( 'ajax-pending' ) ) {
1559
+ return false;
1560
+ }
1561
+ $obj.addClass( 'ajax-pending' );
1562
+ self.save( $obj );
1563
+ return false;
1564
+ }
1565
+ }
1566
+ } );
1567
+
1568
+ $( '#ctc_main' ).on( 'click', '.ctc-selector-edit', function( e ) {
1569
+ e.preventDefault();
1570
+ if ( $( this ).hasClass( 'ajax-pending' ) ) {
1571
+ return false;
1572
+ }
1573
+ $( this ).addClass( 'ajax-pending' );
1574
+ self.set_qsid( this );
1575
+ } );
1576
+
1577
+ $( '#ctc_main' ).on( 'click', '.ctc-rewrite-toggle', function( e ) {
1578
+ e.preventDefault();
1579
+ self.selector_input_toggle( this );
1580
+ } );
1581
+
1582
+ $( '#ctc_main' ).on( 'click', '#ctc_copy_selector', function( ) {
1583
+ var txt = $( '#ctc_sel_ovrd_selector_selected' ).text().trim();
1584
+ if ( !self.is_empty( txt ) ){
1585
+ $( '#ctc_new_selectors' ).val( $( '#ctc_new_selectors' ).val() + "\n" + txt + " {\n\n}" );
1586
+ }
1587
+ } );
1588
+ // save theme as zip
1589
+ $( '#ctc_main' ).on( 'click', '.ctc-backup-theme', function( e ) {
1590
+ e.preventDefault();
1591
+ // copy selected theme to zip export form
1592
+ if ( self.existing ){
1593
+ $( '#ctc_export_theme' ).val( self.currchild );
1594
+ } else {
1595
+ $( '#ctc_export_theme' ).val( self.currparnt );
1596
+ }
1597
+ //console.log( 'backup clicked - theme: ' + $( '#ctc_export_theme' ).val() );
1598
+ // submit form
1599
+ $( '#ctc_export_theme_form' ).submit();
1600
+ // submit form
1601
+ } );
1602
+ $( '#ctc_configtype' ).on( 'change', function( ) {
1603
+ var val = $( this ).val();
1604
+ if ( self.is_empty( val ) || 'theme' === val ) {
1605
+ $( '.ctc-theme-only, .ctc-themeonly-container' ).removeClass( 'ctc-disabled' );
1606
+ $( '.ctc-theme-only, .ctc-themeonly-container input' ).prop( 'disabled', false );
1607
+ try {
1608
+ $( '#ctc_theme_parnt, #ctc_theme_child' ).themeMenu( 'enable' );
1609
+ } catch ( exn ) {
1610
+ self.jquery_exception( exn, 'Theme Menu' );
1611
+ }
1612
+ } else {
1613
+ $( '.ctc-theme-only, .ctc-themeonly-container' ).addClass( 'ctc-disabled' );
1614
+ $( '.ctc-theme-only, .ctc-themeonly-container input' ).prop( 'disabled', true );
1615
+ try {
1616
+ $( '#ctc_theme_parnt, #ctc_theme_child' ).themeMenu( 'disable' );
1617
+ } catch ( exn ) {
1618
+ self.jquery_exception( exn, 'Theme Menu' );
1619
+ }
1620
+ }
1621
+ } );
1622
+
1623
+ // these elements are not replaced so use direct selector events
1624
+ $( '.nav-tab' ).on( 'click', function( e ) {
1625
+ e.preventDefault();
1626
+ // clear the notice box
1627
+ //set_notice( '' );
1628
+ $( '.ctc-query-icon,.ctc-status-icon' ).remove();
1629
+ var id = '#' + $( this ).attr( 'id' );
1630
+ self.focus_panel( id );
1631
+ } );
1632
+
1633
+ $( '#view_child_options, #view_parnt_options' ).on( 'click', function( ){
1634
+ if ( $( this ).hasClass( 'ajax-pending' ) ) {
1635
+ return false;
1636
+ }
1637
+ $( this ).addClass( 'ajax-pending' );
1638
+ self.css_preview( $( this ).attr( 'id' ) );
1639
+ } );
1640
+
1641
+ $( '#ctc_load_form' ).on( 'submit', function() {
1642
+ return ( self.validate() );
1643
+ } );
1644
+
1645
+ $( '#ctc_query_selector_form' ).on( 'submit', function( e ) {
1646
+ e.preventDefault();
1647
+ var $this = $( '#ctc_save_query_selector' );
1648
+ if ( $this.hasClass( 'ajax-pending' ) ) {
1649
+ return false;
1650
+ }
1651
+ $this.addClass( 'ajax-pending' );
1652
+ self.save( $this ); // refresh menus after updating data
1653
+ return false;
1654
+ } );
1655
+
1656
+ $( '#ctc_rule_value_form' ).on( 'submit', function( e ) {
1657
+ //console.log( 'rule value empty submit' );
1658
+ e.preventDefault();
1659
+ return false;
1660
+ } );
1661
+
1662
+ // update interface for existing child theme
1663
+ $( '#ctc_child_type_new,#ctc_child_type_existing,#ctc_child_type_duplicate,#ctc_child_type_reset' )
1664
+ .on( 'focus click', function() {
1665
+ //console.log( 'child type clicked!' );
1666
+ self.reset_handling();
1667
+ self.update_form();
1668
+ } );
1669
+
1670
+ $( '#ctc_is_debug' ).on( 'change', function( ) {
1671
+ if ( $( this ).is( ':checked' ) ){
1672
+ if ( !$( '#ctc_debug_box' ).length ){
1673
+ $( '#ctc_debug_container' ).html( '<textarea id="ctc_debug_box"></textarea>' );
1674
+ }
1675
+ } else {
1676
+ $( '#ctc_debug_box' ).remove();
1677
+ }
1678
+ self.save( this );
1679
+ } );
1680
+
1681
+ $( '.ctc-live-preview' ).on( 'click', function( e ) {
1682
+ e.stopImmediatePropagation();
1683
+ e.preventDefault();
1684
+ document.location = $( this ).prop( 'href' );
1685
+ return false;
1686
+ } );
1687
+ //console.log( 'loading autoselect menus...' )
1688
+ // initialize autoselect menus
1689
+ self.setup_menus();
1690
+
1691
+ // turn on submit buttons (disabled until everything is loaded to prevent errors)
1692
+ //console.log( 'releasing submit buttons...' )
1693
+ $( 'input[type=submit], input[type=button]' ).prop( 'disabled', false );
1694
+ self.scrolltop();
1695
+ self.update_form();
1696
+ //console.log( 'Ready.' );
1697
+ }
1698
+ if ( self.jqueryerr.length ) {
1699
+ self.jquery_notice();
1700
+ }
1701
+ },
1702
+ // object properties
1703
+ testslug: '',
1704
+ testname: '',
1705
+ reload: false,
1706
+ currquery: 'base',
1707
+ currqsid: null,
1708
+ currdata: {},
1709
+ currparnt: '',
1710
+ currchild: '',
1711
+ existing: false,
1712
+ jqueryerr: [], // stores jquery exceptions thrown during init
1713
+ color_regx: '\\s+(\\#[a-f0-9]{3,6}|rgba?\\([\\d., ]+?\\)|hsla?\\([\\d%., ]+?\\)|[a-z]+)',
1714
+ border_regx: '(\\w+)(\\s+(\\w+))?',
1715
+ grad_regx: '(\\w+)'
1716
+
1717
+ };
1718
+ $.chldthmanalyze = {
1719
+
1720
+ show_loading: function( resubmit, text ) {
1721
+ var themetype = $.chldthmcfg.existing ? 'child' : 'parnt',
1722
+ name = text ? text : $.chldthmcfg.getname( themetype ),
1723
+ notice = '<strong class="ctc_analyze_loading"><span class="spinner is-active"></span>' +
1724
+ $.chldthmcfg.getxt( resubmit ? 'anlz1' : 'anlz2' ) + ' ' + name + '...</strong>';
1725
+ self.noticediv = ( 'child' === themetype ? '' : '' );
1726
+ $( '#' + themetype + '_analysis_notice' ).html( notice );
1727
+ //$( 'html, body' ).animate( { scrollTop: 0 }, 'slow' );
1728
+ },
1729
+ hide_loading: function() {
1730
+ $( '.ctc_analyze_loading' ).fadeTo( 200, 0, function(){ $( this ).slideUp( 200, function() { $( this ).remove(); } ); } );
1731
+ },
1732
+ /**
1733
+ * Fetch website home page and parse <head> for linked stylesheets
1734
+ * Use this to store dependencies and to mark them to be parsed as "default" stylesheets
1735
+ * Detects other signals for configuration heuristics during child theme setup.
1736
+ */
1737
+ analyze_theme: function( themetype ) {
1738
+ //console.log( 'analyze_theme' );
1739
+ var self = this,
1740
+ template = $.chldthmcfg.currparnt,
1741
+ stylesheet = ( 'child' === themetype ? $.chldthmcfg.currchild : $.chldthmcfg.currparnt );
1742
+
1743
+ //console.log( 'Fetching home page: ' + url );
1744
+
1745
+ $.ajax( {
1746
+ url: window.ctcAjax.ajaxurl,
1747
+ data: {
1748
+ action: 'ctc_analyze',
1749
+ stylesheet: stylesheet,
1750
+ template: template,
1751
+ _wpnonce: $( '#_wpnonce' ).val(),
1752
+ },
1753
+ dataType: 'json',
1754
+ type: 'POST'
1755
+ } ).done( function( data ) {
1756
+ // console.log( data );
1757
+ self.analysis[ themetype ] = data;
1758
+ $.each( data.dependencies, function( ndx, el ){
1759
+ self.dependencies[ ndx ] = el;
1760
+ });
1761
+ $( document ).trigger( 'analysisdone' );
1762
+ } ).fail( function( xhr, status, err ){
1763
+ //console.log( xhr );
1764
+ var analysis = {
1765
+ 'signals': {
1766
+ 'failure': 1,
1767
+ 'xhrerr': err
1768
+ }
1769
+ };
1770
+ self.analysis[ themetype ] = analysis;
1771
+ $( document ).trigger( 'analysisdone' );
1772
+ } );
1773
+ },
1774
+
1775
+ /**
1776
+ * Uses analysis data to auto configure form, pass parameters
1777
+ * for child theme setup and display results to user.
1778
+ */
1779
+ css_notice: function() {
1780
+ //console.log( 'in css_notice' );
1781
+ var self = this,
1782
+ themetype = $.chldthmcfg.existing ? 'child' : 'parnt',
1783
+ name = $.chldthmcfg.getname( themetype ),
1784
+ hidden = '',
1785
+ notice = {
1786
+ notices: [],
1787
+ },
1788
+ errnotice = {
1789
+ style: 'notice-warning',
1790
+ headline: $.chldthmcfg.getxt( 'anlz3', name ),
1791
+ errlist: ''
1792
+ },
1793
+ resubmit = 0,
1794
+ resubmitdata= {},
1795
+ anlz,
1796
+ debugtxt = '',
1797
+ dep_inputs;
1798
+
1799
+ if ( self.analysis[ themetype ].signals.failure ||
1800
+ ( self.analysis[ themetype ].signals.thm_noqueue && !self.phperr[ themetype ].length ) ) {
1801
+ if ( $( '#ctc_is_debug' ).is( ':checked' ) ) {
1802
+ debugtxt = $.chldthmcfg.getxt( 'anlz33' ).replace(/%1/, '<a href="' + self.analysis[ themetype ].url + '" target="_new">' ).replace( /%2/, '</a>' );
1803
+ }
1804
+ if ( $( '#ctc_is_debug' ).is( ':checked' ) ) {
1805
+ debugtxt = $.chldthmcfg.getxt( 'anlz33' ).replace(/%1/, '<a href="' + self.analysis[ template ].url + '" target="_new">' ).replace( /%2/, '</a>' );
1806
+ }
1807
+ notice.notices.push( {
1808
+ headline: $.chldthmcfg.getxt( 'anlz4', name ),
1809
+ msg: $.chldthmcfg.getxt( 'anlz5' ) + debugtxt, // + self.analysis[ themetype ].signals.xhrerr,
1810
+ style: 'notice-warning'
1811
+ } );
1812
+ } else {
1813
+ // test errors
1814
+ if ( self.analysis[ themetype ].errors.length ) {
1815
+ $.each( self.analysis[ themetype ].errors, function( index, err ) {
1816
+ if ( err.match( /Fatal error/i ) ) {
1817
+ errnotice.style = 'error';
1818
+ errnotice.headline = $.chldthmcfg.getxt( 'anlz8', name );
1819
+ }
1820
+ /*
1821
+ if ( $.chldthmcfg.existing && err.match( /(FileNotFoundException|Failed opening|failed to open stream)/i ) ) {
1822
+ //console.log( 'Probably using get_stylesheet_directory()' );
1823
+ notice.subhead = 'A file cannot be found in the Child Theme\'s directory.';
1824
+ }
1825
+ */
1826
+ errnotice.errlist += err + "\n";
1827
+ } );
1828
+ errnotice.msg = '<div style="background-color:#ffeebb;padding:6px">' +
1829
+ '<div class="ctc-section-toggle" id="ctc_analysis_errs">' +
1830
+ $.chldthmcfg.getxt( 'anlz6' ) + '</div>' +
1831
+ '<div id="ctc_analysis_errs_content" style="display:none"><textarea>' +
1832
+ errnotice.errlist + '</textarea></div></div>' +
1833
+ $.chldthmcfg.getxt( 'anlz7' );
1834
+ notice.notices.push( errnotice );
1835
+ }
1836
+ if ( self.analysis[ themetype ].signals.thm_past_wphead || self.analysis[ themetype ].signals.dep_past_wphead ) {
1837
+ // || self.analysis[ themetype ].signals.css_past_wphead ){
1838
+ notice.notices.push( {
1839
+ headline: $.chldthmcfg.getxt( 'anlz9' ),
1840
+ style: 'notice-warning',
1841
+ msg: $.chldthmcfg.getxt( 'anlz10' )
1842
+ } );
1843
+ $( '#ctc_repairheader' ).prop( 'checked', true );
1844
+ $( '#ctc_repairheader_container' ).show();
1845
+ }
1846
+ if ( self.analysis[ themetype ].signals.thm_unregistered ) {
1847
+ if (
1848
+ !self.analysis[ themetype ].signals.ctc_child_loaded &&
1849
+ !self.analysis[ themetype ].signals.ctc_sep_loaded ){
1850
+ // test for stylesheet enqueue issues
1851
+ notice.notices.push( {
1852
+ headline: $.chldthmcfg.getxt( 'anlz11' ),
1853
+ style: 'notice-warning',
1854
+ msg: $.chldthmcfg.getxt( 'anlz12' )
1855
+ } );
1856
+ $( '#ctc_repairheader_container' ).show();
1857
+ $( '#ctc_repairheader' ).prop( 'checked', true );
1858
+ }
1859
+ }
1860
+ if ( 'child' === themetype ) {
1861
+ if ( self.analysis.child.signals.ctc_parnt_reorder ) {
1862
+ //console.log( 'reorder flag detected, resubmitting.' );
1863
+ resubmit = 1;
1864
+ }
1865
+ if ( !self.analysis.child.signals.ctc_child_loaded &&
1866
+ !self.analysis.child.signals.ctc_sep_loaded &&
1867
+ !self.analysis.child.signals.thm_child_loaded ){
1868
+ notice.notices.push( {
1869
+ headline: $.chldthmcfg.getxt( 'anlz13' ),
1870
+ style: 'notice-warning',
1871
+ msg: $.chldthmcfg.getxt( 'anlz14' )
1872
+ } );
1873
+ resubmit = 1;
1874
+ }
1875
+ if ( self.analysis[ themetype ].signals.ctc_gen_loaded ) {
1876
+ notice.notices.push( {
1877
+ headline: $.chldthmcfg.getxt( 'anlz31' ),
1878
+ msg: $.chldthmcfg.getxt( 'anlz32' ),
1879
+ style: 'notice-warning'
1880
+ } );
1881
+ }
1882
+ if ( !self.analysis.parnt.signals.thm_no_styles &&
1883
+ !self.analysis.child.signals.ctc_gen_loaded &&
1884
+ !self.analysis.child.signals.thm_parnt_loaded &&
1885
+ !self.analysis.child.signals.ctc_parnt_loaded &&
1886
+ !self.analysis.child.signals.thm_ignoreparnt &&
1887
+ !self.analysis.child.signals.thm_has_import ){
1888
+ notice.notices.push( {
1889
+ headline: $.chldthmcfg.getxt( 'anlz15' ),
1890
+ style: 'notice-warning',
1891
+ msg: $.chldthmcfg.getxt( 'anlz16' )
1892
+ } );
1893
+ resubmit = 1;
1894
+ }
1895
+ if ( self.analysis.child.signals.thm_unregistered &&
1896
+ self.analysis.child.signals.thm_child_loaded &&
1897
+ 'thm_unregistered' === self.analysis.child.signals.thm_child_loaded &&
1898
+ self.analysis.child.signals.ctc_child_loaded &&
1899
+ self.analysis.child.signals.ctc_parnt_loaded ) {
1900
+ notice.notices.push( {
1901
+ headline: $.chldthmcfg.getxt( 'anlz28' ),
1902
+ style: 'notice-warning',
1903
+ msg: $.chldthmcfg.getxt( 'anlz29' )
1904
+ } );
1905
+ $( '#ctc_repairheader_container' ).show();
1906
+ $( '#ctc_repairheader' ).prop( 'checked', true );
1907
+ }
1908
+
1909
+ if ( !self.analysis.child.signals.thm_is_ctc &&
1910
+ !$( '#ctc_child_type_duplicate' ).is( ':checked' ) ) {
1911
+ notice.notices.push( {
1912
+ headline: $.chldthmcfg.getxt( 'anlz19' ),
1913
+ msg: $.chldthmcfg.getxt( 'anlz20' ),
1914
+ style: 'notice-warning'
1915
+ } );
1916
+ }
1917
+ }
1918
+ // automatically set form inputs based on current analysis
1919
+ if ( self.analysis[ themetype ].signals.ctc_sep_loaded || self.analysis[ themetype ].signals.ctc_gen_loaded ){
1920
+ //console.log( 'Separate stylesheet detected' );
1921
+ $( '#ctc_handling_separate' ).prop( 'checked', true );
1922
+ }
1923
+ if ( !notice.notices.length ) {
1924
+ notice.notices.push( {
1925
+ headline: '' + ( 'child' === themetype ? $.chldthmcfg.getxt( 'anlz17' ) : $.chldthmcfg.getxt( 'anlz18' ) ) + '',
1926
+ style: 'updated',
1927
+ msg: ''
1928
+ } );
1929
+ }
1930
+
1931
+ if ( 'child' === themetype && self.analysis.child.signals.thm_has_import ) {
1932
+ notice.notices.push( {
1933
+ headline: $.chldthmcfg.getxt( 'anlz21' ),
1934
+ msg: $.chldthmcfg.getxt( 'anlz22' ),
1935
+ style: 'notice-warning'
1936
+ } );
1937
+ //console.log( 'Import parent detected' );
1938
+ $( '#ctc_enqueue_import' ).prop( 'checked', true );
1939
+ }
1940
+ if ( self.analysis[ themetype ].signals.thm_ignoreparnt || self.analysis[ themetype ].signals.ctc_gen_loaded ){
1941
+ //console.log( 'Ignore parent detected' );
1942
+ $( '#ctc_ignoreparnt' ).prop( 'checked', true );
1943
+ if ( !$( '#ctc_enqueue_none' ).is( ':checked' ) ) {
1944
+ $( '#ctc_enqueue_none' ).prop( 'checked', true );
1945
+ resubmit = 1;
1946
+ resubmitdata.ctc_enqueue = 'none';
1947
+ }
1948
+ } else {
1949
+ $( '#ctc_ignoreparnt' ).prop( 'checked', false );
1950
+ }
1951
+ if ( !self.analysis[ themetype ].signals.ctc_sep_loaded &&
1952
+ !self.analysis[ themetype ].signals.ctc_gen_loaded &&
1953
+ !self.analysis[ themetype ].signals.ctc_child_loaded &&
1954
+ !self.analysis[ themetype ].signals.thm_unregistered &&
1955
+ !self.analysis[ themetype ].signals.thm_past_wphead &&
1956
+ self.analysis[ themetype ].deps[ 1 ].length ) {
1957
+ var sheets = '';
1958
+ $.each( self.analysis[ themetype ].deps[ 1 ], function( ndx, el ) {
1959
+ if ( el[ 1 ].match( /^style([\-\.]min)?\.css$/ ) ) { return; }
1960
+ sheets += '<li>' + el[ 1 ] + "</li>\n";
1961
+ } );
1962
+ if ( '' !== sheets ) {
1963
+ sheets = "<ul class='howto' style='padding-left:1em'>\n" + sheets + "</ul>\n";
1964
+ notice.notices.push( {
1965
+ headline: $.chldthmcfg.getxt( 'anlz23' ),
1966
+ msg: sheets + $.chldthmcfg.getxt( 'anlz24' ),
1967
+ style: 'updated'
1968
+ } );
1969
+ }
1970
+ }
1971
+ if ( 'child' === themetype && self.analysis[ themetype ].signals.thm_parnt_loaded ) {
1972
+ //if ( !$( '#ctc_enqueue_none' ).is( ':checked' ) ) {
1973
+ notice.notices.push( {
1974
+ headline: $.chldthmcfg.getxt( 'anlz25' ),
1975
+ msg: $.chldthmcfg.getxt( 'anlz26' ),
1976
+ style: 'updated'
1977
+ } );
1978
+ //}
1979
+ $( '#ctc_enqueue_none' ).prop( 'checked', true );
1980
+ resubmit = 1;
1981
+ resubmitdata.ctc_enqueue = 'none';
1982
+ }
1983
+ // if no parent styles, no need to enqueue
1984
+ if ( self.analysis.parnt.signals.thm_no_styles ) {
1985
+ //if ( !$( '#ctc_enqueue_none' ).is( ':checked' ) ) {
1986
+ notice.notices.push( {
1987
+ headline: $.chldthmcfg.getxt( 'anlz27' ),
1988
+ msg: $.chldthmcfg.getxt( 'anlz26' ),
1989
+ style: 'updated'
1990
+ } );
1991
+ //}
1992
+ $( '#ctc_enqueue_none' ).prop( 'checked', true );
1993
+ resubmit = 1;
1994
+ resubmitdata.ctc_enqueue = 'none';
1995
+ }
1996
+ }
1997
+
1998
+ /**
1999
+ * Auto-configure parameters
2000
+ * Some configuration must be done based on theme-specific signals
2001
+ * These are passed back as hidden inputs
2002
+ */
2003
+ // parent has styles
2004
+ hidden = encodeURIComponent( JSON.stringify( self.analysis ) );
2005
+
2006
+ $( 'input[name="ctc_analysis"]' ).val( hidden );
2007
+ resubmitdata.ctc_analysis = hidden;
2008
+ if ( self.is_success() && resubmit && !self.resubmitting ){
2009
+ self.resubmitting = 1;
2010
+ self.resubmit( resubmitdata );
2011
+ return;
2012
+ } else {
2013
+ self.resubmitting = 0;
2014
+ self.hide_loading();
2015
+ $.each( notice.notices, function( ndx, notice ){
2016
+ //console.log( notice );
2017
+ var $out = $( '<div class="' + notice.style + ' notice is-dismissible dashicons-before" >' +
2018
+ '<h4>' + notice.headline + '</h4>' +
2019
+ notice.msg +
2020
+ '</div>' );
2021
+ $.chldthmcfg.bind_dismiss( $out );
2022
+ $out.hide().appendTo( '#' + themetype + '_analysis_notice' ).slideDown();
2023
+ } );
2024
+
2025
+ if ( $( '#ctc_is_debug' ).is( ':checked' ) ) {
2026
+ anlz = '<div style="background-color:#ddd;padding:6px">' +
2027
+ '<div class="ctc-section-toggle" id="ctc_analysis_obj">' +
2028
+ $.chldthmcfg.getxt( 'anlz30' ) +
2029
+ '</div>' +
2030
+ '<div id="ctc_analysis_obj_content" style="display:none">' +
2031
+ '<textarea style="font-family:monospace;font-size:10px">' +
2032
+ JSON.stringify( self.analysis, null, 2 ) +
2033
+ '</textarea></div></div>';
2034
+
2035
+ $( anlz ).appendTo( '#' + themetype + '_analysis_notice' );
2036
+
2037
+ }
2038
+
2039
+ // v2.1.3 remove stylesheet dependencies
2040
+ dep_inputs = '';
2041
+ // console.log( self.dependencies );
2042
+ $.each( self.dependencies, function( ndx, el ){
2043
+ // console.log( 'setting dependecy: ' + ndx + ' ' + el );
2044
+ if ( el ) {
2045
+ dep_inputs += '<label><input class="ctc_checkbox ctc-themeonly" id="ctc_forcedep_' + ndx +
2046
+ '" name="ctc_forcedep[]" type="checkbox" value="' + ndx + '" autocomplete="off" ' +
2047
+ ( -1 !== $.inArray( ndx, window.ctcAjax.forcedep ) ? 'checked' : '' ) +
2048
+ ' />' + ndx + "</label><br/>\n";
2049
+ }
2050
+ });
2051
+ // console.log( 'dep_inputs: ' + dep_inputs.length );
2052
+ if ( dep_inputs.length ){
2053
+ $( '#ctc_dependencies' ).html( dep_inputs );
2054
+ $( '#ctc_dependencies_container' ).show();
2055
+ } else {
2056
+ $( '#ctc_dependencies' ).empty();
2057
+ $( '#ctc_dependencies_container' ).hide();
2058
+ }
2059
+
2060
+ if ( !$( '#ctc_child_type_reset' ).is( ':checked' ) ) {
2061
+ $( '#input_row_stylesheet_handling_container,#input_row_parent_handling_container,#ctc_child_header_parameters,#ctc_configure_submit' ).slideDown( 'fast' );
2062
+ if ( $( '#ctc_child_type_duplicate' ).is( ':checked' ) ) {
2063
+ $( '#ctc_configure_submit .ctc-step' ).text( '8' );
2064
+ $( '#ctc_copy_theme_mods' ).find( 'input' ).prop( 'checked', false );
2065
+ } else {
2066
+ $( '#ctc_configure_submit .ctc-step' ).text( '9' );
2067
+ $( '#ctc_copy_theme_mods' ).slideDown( 'fast' );
2068
+ }
2069
+ if ( $( '#ctc_child_type_duplicate' ).is( ':checked' ) || $( '#ctc_child_type_new' ).is( ':checked' ) ) {
2070
+ $( '#input_row_theme_slug' ).hide();
2071
+ $( '#input_row_new_theme_slug' ).slideDown( 'fast' );
2072
+ } else {
2073
+ $( '#input_row_new_theme_slug' ).hide();
2074
+ $( '#input_row_theme_slug' ).slideDown( 'fast' );
2075
+ }
2076
+ }
2077
+
2078
+ //console.log( 'end css_notice' );
2079
+ }
2080
+
2081
+ },
2082
+ resubmit: function( data ) {
2083
+ var self = this;
2084
+ self.hide_loading();
2085
+ self.show_loading( true );
2086
+ data.action = 'ctc_update';
2087
+ data._wpnonce = $( '#_wpnonce' ).val();
2088
+ //console.log( '=====>>> RESUBMIT CALLED! <<<=====' );
2089
+ //console.log( data );
2090
+ $.ajax( {
2091
+ url: window.ctcAjax.ajaxurl,
2092
+ data: data,
2093
+ //dataType: 'json',
2094
+ type: 'POST'
2095
+ } ).done( function() { // response ) {
2096
+ //console.log( 'resubmit done:' );
2097
+ //console.log( response );
2098
+ self.hide_loading();
2099
+ self.do_analysis();
2100
+ } ).fail( function() { // xhr, status, err ) {
2101
+ //self.do_analysis();
2102
+ self.hide_loading();
2103
+ //console.log( status + ' ' + err );
2104
+ // FIXME: handle failure
2105
+ } );
2106
+ },
2107
+ do_analysis: function() {
2108
+ var self = this;
2109
+ self.analysis = { parnt: {}, child: {} };
2110
+ self.phperr = { parnt: [], child: [] };
2111
+ self.dependencies = {};
2112
+ self.done = 0;
2113
+ self.show_loading( false );
2114
+ self.analyze_theme( 'parnt' );
2115
+ if ( $.chldthmcfg.existing ) {
2116
+ self.analyze_theme( 'child' );
2117
+ }
2118
+ //$( '#ctc_enqueue_enqueue' ).prop( 'checked', true );
2119
+ //$( '#ctc_handling_primary' ).prop( 'checked', true );
2120
+ //$( '#ctc_ignoreparent' ).prop( 'checked', false );
2121
+ },
2122
+ // initialize object vars, bind event listeners to elements, load menus and start plugin
2123
+ init: function() {
2124
+ //console.log( 'initializing...' )
2125
+ var self = this;
2126
+ // ajax request done
2127
+ $( document ).on( 'analysisdone', function(){
2128
+ self.done++;
2129
+ //console.log( 'analysis came home ' + self.done );
2130
+ //console.log( 'existing: ' + $.chldthmcfg.existing );
2131
+ //console.log( 'parent: ' + $( '#ctc_theme_parnt' ).val() );
2132
+ // all ajax requests done
2133
+ if ( self.done > $.chldthmcfg.existing ){
2134
+ //console.log( 'analysis complete!' );
2135
+ self.done = 0;
2136
+ self.css_notice();
2137
+ }
2138
+ } );
2139
+ // run analyzer on demand
2140
+ $( '#ctc_main' ).on( 'click', '.ctc-analyze-theme', function() {
2141
+ if ( self.is_success() ) {
2142
+ $.chldthmcfg.dismiss_notice( $( '.ctc-success-response' ).parent( '.notice' ) );
2143
+ }
2144
+ self.do_analysis();
2145
+ } );
2146
+ // if page is success response run the analyzer on load
2147
+ if ( self.is_success() && !window.ctcAjax.pluginmode ) {
2148
+ self.do_analysis();
2149
+ }
2150
+ },
2151
+ analysis: {}, // analysis signals object
2152
+ done: 0, // analysis semphore
2153
+ resubmitting: 0, // resubmit semaphore
2154
+ dependencies: {}, // addl stylesheets that may require dependencies
2155
+ is_success: function(){
2156
+ return $( '.ctc-success-response' ).length;
2157
+ }
2158
+ };
2159
+ // don't initialize if this is FTP request
2160
+ if (!$( '#request-filesystem-credentials-form' ).length ){
2161
+ $.chldthmcfg.init();
2162
+ $.chldthmanalyze.init();
2163
+ }
2164
+ } ( jQuery ) );
2165
+
js/chldthmcfg.min.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ !function(e){"use strict";e.chldthmcfg={escquo:function(e){var t=this;return t.is_empty(e)?e:e.toString().replace(/"/g,'"')},getxt:function(e,t){var c=window.ctcAjax[e+"_txt"];return c?(t&&(c=c.replace(/%s/,t)),c):""},getname:function(t){var c="child"===t?e.chldthmcfg.currchild:e.chldthmcfg.currparnt;return window.ctcAjax.themes[t][c].Name},frascii:function(e){var t=parseInt(e),c=String.fromCharCode(t);return c},toascii:function(e){var t=e.charCodeAt(0);return t},is_empty:function(e,t){if("undefined"==typeof e||!1===e||null===e||""===e)return!0;if("undefined"!=typeof t&&"0"===e||0===e)return!0;if(!0===e||"string"==typeof e||"number"==typeof e)return!1;if("object"==typeof e){for(var c in e)if(e.hasOwnProperty(c))return!1;return!0}return!1},theme_exists:function(t,c){var n=!1;return e.each(window.ctcAjax.themes,function(i,a){return e.each(a,function(e,a){return a=null,e.toLowerCase()!==t.toLowerCase()||"parnt"!==i&&"new"!==c?void 0:(n=!0,!1)}),n?!1:void 0}),n},validate:function(){var t=this,c=/[^\w\-]/,n=e("#ctc_child_template").length?e("#ctc_child_template").val().toString().replace(c):"",i=e("#ctc_theme_child").length?e("#ctc_theme_child").val().toString().replace(c):n,a=e("input[name=ctc_child_type]:checked").val(),s=[];return"new"===a&&(i=n),t.theme_exists(i,a)&&s.push(t.getxt("theme_exists").toString().replace(/%s/,i)),t.is_empty(i)&&s.push(t.getxt("inval_theme")),s.length?(t.set_notice({error:s}),!1):"reset"===a?!!confirm(t.getxt("load")):!0},autogen_slugs:function(){if(e("#ctc_theme_parnt").length){for(var t=this,c=e("#ctc_theme_parnt").val(),n=e("#ctc_theme_child").length?e("#ctc_theme_child").val():"",i=""!==n&&e("#ctc_child_type_duplicate").is(":checked")?n:c+"-child",a=i,s=""!==n&&e("#ctc_child_type_duplicate").is(":checked")?e.chldthmcfg.getname("child"):e.chldthmcfg.getname("parnt")+" Child",l="",r="",o="00";t.theme_exists(a,"new");)l=t.is_empty(l)?2:l+1,r=o.substring(0,o.length-l.toString().length)+l.toString(),a=i+r;t.testslug=a,t.testname=s+(r.length?" "+r:"")}},focus_panel:function(t){var c=t+"_panel";e(".nav-tab").removeClass("nav-tab-active"),e(".ctc-option-panel").removeClass("ctc-option-panel-active"),e(t).addClass("nav-tab-active"),e(".ctc-option-panel-container").scrollTop(0),e(c).addClass("ctc-option-panel-active")},selector_input_toggle:function(t){var c,n=this;e("#ctc_rewrite_selector").length?(c=e("#ctc_rewrite_selector_orig").val(),e("#ctc_sel_ovrd_selector_selected").text(c),e(t).text(n.getxt("rename"))):(c=e("#ctc_sel_ovrd_selector_selected").text(),e("#ctc_sel_ovrd_selector_selected").html('<textarea id="ctc_rewrite_selector" name="ctc_rewrite_selector" autocomplete="off"></textarea><input id="ctc_rewrite_selector_orig" name="ctc_rewrite_selector_orig" type="hidden" value="'+n.escquo(c)+'"/>'),e("#ctc_rewrite_selector").val(c),e(t).text(n.getxt("cancel")))},coalesce_inputs:function(t){var c=this,n=e(t).attr("id"),i=/^(ctc_(ovrd|\d+)_(parent|child)_([0-9a-z\-]+)_(\d+?)(_(\d+))?)(_\w+)?$/,a=e(t).parents(".ctc-selector-row, .ctc-parent-row").first(),s=a.find(".ctc-swatch").first(),l={parent:{},child:{}},r={parent:{origin:"",start:"",end:""},child:{origin:"",start:"",end:""}},o={child:!1,parent:!1},_={};return a.find(".ctc-parent-value, .ctc-child-value").each(function(){var t,a,s=e(this).attr("id"),d=s.toString().match(i),u=d[2],h=d[3],p="undefined"==typeof d[4]?"":d[4],m=d[7],g=d[5],f="undefined"==typeof d[7]?"":d[8],v="parent"===h?e(this).text().replace(/!$/,""):"seq"!==p&&"ctc_delete_query_selector"===n?"":e(this).val(),y="seq"===p?!1:"ctc_"+u+"_child_"+p+"_i_"+g+"_"+m;if("child"===h&&(c.is_empty(e(this).data("color"))||(v=c.color_text(e(this).data("color")),e(this).data("color",null)),_[s]=v,y&&(_[y]=e("#"+y).is(":checked")?1:0)),""!==v)if(c.is_empty(f))if(t=p.toString().match(/^border(\-(top|right|bottom|left))?$/)&&!v.match(/none/)){var w=new RegExp(c.border_regx+c.color_regx,"i");a=v.toString().match(w),c.is_empty(a)||(a.shift(),l[h][p+"-width"]=a.shift()||"",a.shift(),l[h][p+"-style"]=a.shift()||"",l[h][p+"-color"]=a.shift()||"")}else if("background-image"!==p||v.match(/none/))"seq"!==p&&(l[h][p]=v);else if(v.toString().match(/url\(/))l[h]["background-image"]=c.image_url(h,v);else{var x=new RegExp(c.grad_regx+c.color_regx+c.color_regx,"i");a=v.toString().match(x),!c.is_empty(a)&&a.length>2?(a.shift(),r[h].origin=a.shift()||"top",r[h].start=a.shift()||"transparent",r[h].end=a.shift()||"transparent",o[h]=!0):l[h]["background-image"]=v}else switch(f){case"_border_width":l[h][p+"-width"]="none"===v?0:v;break;case"_border_style":l[h][p+"-style"]=v;break;case"_border_color":l[h][p+"-color"]=v;break;case"_background_url":l[h]["background-image"]=c.image_url(h,v);break;case"_background_color":l[h]["background-color"]=v;break;case"_background_color1":r[h].start=v,o[h]=!0;break;case"_background_color2":r[h].end=v,o[h]=!0;break;case"_background_origin":r[h].origin=v,o[h]=!0}}),"undefined"==typeof s||c.is_empty(s.attr("id"))||(s.removeAttr("style"),o.parent&&s.ctcgrad(r.parent.origin,[r.parent.start,r.parent.end]),s.css(l.parent),s.attr("id").toString().match(/parent/)||(o.child&&s.ctcgrad(r.child.origin,[r.child.start,r.child.end]),s.css(l.child)),s.css({"z-index":-1})),_},decode_value:function(e,t){t="undefined"==typeof t?"":t;var c,n=this,i={orig:t,names:[""],values:[t]};if(e.toString().match(/^border(\-(top|right|bottom|left))?$/)){var a,s=new RegExp(n.border_regx+"("+n.color_regx+")?","i");c=t.toString().match(s),n.is_empty(c)&&(c=[]),i.names=["_border_width","_border_style","_border_color"],a=c.shift(),i.values[0]=c.shift()||"",c.shift(),i.values[1]=c.shift()||"",c.shift(),i.values[2]=c.shift()||""}else if(e.toString().match(/^background\-image/))if(i.names=["_background_url","_background_origin","_background_color1","_background_color2"],i.values=["","","",""],n.is_empty(t)||t.toString().match(/(url|none)/))i.values[0]=t;else{var l,r;c=t.toString().split(/:/),i.values[1]=c.shift()||"",i.values[2]=c.shift()||"",l=c.shift()||"",i.values[3]=c.shift()||"",r=c.shift()||"",i.orig=[i.values[1],i.values[2],i.values[3]].join(" ")}return i},image_url:function(e,t){var c,n=this,i=t.toString().match(/url\(['" ]*(.+?)['" ]*\)/),a=n.is_empty(i)?null:i[1],s=window.ctcAjax.theme_uri+"/"+("parent"===e?window.ctcAjax.parnt:window.ctcAjax.child)+"/";return a?c=a.toString().match(/^(data:|https?:|\/)/)?t:"url("+s+a+")":!1},setup_menus:function(){var e=this;e.setup_query_menu(),e.setup_selector_menu(),e.setup_rule_menu(),e.setup_new_rule_menu(),e.load_queries(),e.load_rules(),e.set_query(e.currquery)},load_queries:function(){var e=this;e.query_css("queries",null)},load_selectors:function(){var e=this;e.query_css("selectors",e.currquery)},load_rules:function(){var e=this;e.query_css("rules",null)},load_selector_values:function(){var e=this;e.query_css("qsid",e.currqsid)},get_queries:function(t,c){var n=[],i=new RegExp(e.ui.autocomplete.escapeRegex(t.term),"i");e.chldthmcfg.is_empty(this.element.data("menu"))?n.push({label:window.ctcAjax.nosels_txt,value:null}):e.each(this.element.data("menu"),function(e,t){i.test(t)&&n.push({label:t,value:t})}),c(n)},get_selectors:function(t,c){var n=[],i=new RegExp(e.ui.autocomplete.escapeRegex(t.term),"i");e.chldthmcfg.is_empty(this.element.data("menu"))?n.push({label:window.ctcAjax.nosels_txt,value:null}):e.each(this.element.data("menu"),function(e,t){i.test(e)&&n.push({label:e,value:t})}),c(n)},get_rules:function(t,c){var n=[],i=new RegExp(e.ui.autocomplete.escapeRegex(t.term),"i");e.chldthmcfg.is_empty(this.element.data("menu"))?n.push({label:window.ctcAjax.nosels_txt,value:null}):e.each(this.element.data("menu"),function(e,t){i.test(e)&&n.push({label:e,value:t})}),c(n)},get_filtered_rules:function(t,c){var n=[],i=new RegExp(e.ui.autocomplete.escapeRegex(t.term),"i");e.each(e("#ctc_rule_menu").data("menu"),function(e,t){i.test(e)&&n.push({label:e,value:t})}),c(n)},merge_ruleval_arrays:function(t,c,n){var i=this,a={},s=n?c.child.pop():null;return e.each(["parnt","child"],function(t,l){i.is_empty(c[l])||e.each(c[l],function(e,t){n?parseInt(t[2])>=parseInt(s[2])&&(s[2]=parseInt(t[2])+1):(i.is_empty(a[t[2]])&&(a[t[2]]={}),a[t[2]][l]=t)})}),n&&(a[s[2]]={parnt:[],child:s}),a},input_row:function(t,c,n,i,a){var s=this,l="";if(!s.is_empty(i)&&!s.is_empty(i.value)&&!s.is_empty(i.value[c])){var r=i.value[c],o=s.merge_ruleval_arrays(c,r,a);e.each(o,function(a,r){var o=s.decode_value(c,s.is_empty(r.parnt)?"":r.parnt[0]),_=s.is_empty(r.parnt)||s.is_empty(r.parnt[1],1)?0:1,d=s.decode_value(c,s.is_empty(r.child)?"":r.child[0]),u=s.is_empty(r.child)||s.is_empty(r.child[1],1)?0:1;if(l+='<div class="ctc-'+("ovrd"===n?"input":"selector")+'-row clearfix"><div class="ctc-input-cell">',l+="ovrd"===n?c.replace(/\d+/g,s.frascii):i.selector+'<br/><a href="#" class="ctc-selector-edit" id="ctc_selector_edit_'+t+'" >'+s.getxt("edit")+"</a> "+(s.is_empty(o.orig)?s.getxt("child_only"):""),l+='</div><div class="ctc-parent-value ctc-input-cell"'+("ovrd"!==n?' style="display:none"':"")+' id="ctc_'+n+"_parent_"+c+"_"+t+"_"+a+'">'+(s.is_empty(o.orig)?"[no value]":o.orig+(_?s.getxt("important"):""))+'</div><div class="ctc-input-cell">',!s.is_empty(o.names)){e.each(o.names,function(e,i){i=s.is_empty(i)?"":i,l+='<div class="ctc-child-input-cell clear">';var r,o="ctc_"+n+"_child_"+c+"_"+t+"_"+a+i;!1===(r=d.values.shift())&&(r=""),l+=(s.is_empty(i)?"":s.getxt(i)+":<br/>")+'<input type="text" id="'+o+'" name="'+o+'" class="ctc-child-value'+((i+c).toString().match(/color/)?" color-picker":"")+(i.toString().match(/url/)?" ctc-input-wide":"")+'" value="'+s.escquo(r)+'" /></div>'});var h="ctc_"+n+"_child_"+c+"_i_"+t+"_"+a;l+='<label for="'+h+'"><input type="checkbox" id="'+h+'" name="'+h+'" value="1" '+(u?"checked":"")+" />"+s.getxt("important")+"</label>"}l+="</div>","ovrd"!==n&&(l+='<div class="ctc-swatch ctc-specific" id="ctc_child_'+c+"_"+t+"_"+a+'_swatch">'+s.getxt("swatch")+'</div><div class="ctc-child-input-cell ctc-button-cell" id="ctc_save_'+c+"_"+t+"_"+a+'_cell"><input type="button" class="button ctc-save-input" id="ctc_save_'+c+"_"+t+"_"+a+'" name="ctc_save_'+c+"_"+t+"_"+a+'" value="Save" /></div>'),l+="</div><!-- end input row -->\n"})}return l},scrolltop:function(){e("html, body, .ctc-option-panel-container").animate({scrollTop:0})},css_preview:function(e){var t=this;(e=e.match(/(child|parnt)/)[1])||(e="child"),t.query_css("preview",e)},setup_iris:function(e){var t=this;t.setup_spectrum(e)},setup_spectrum:function(t){var c=this,n=!c.is_empty(window.ctcAjax.palette);try{e(t).spectrum({showInput:!0,allowEmpty:!0,showAlpha:!0,showInitial:!0,preferredFormat:"hex",clickoutFiresChange:!0,move:function(n){e(t).data("color",n),c.coalesce_inputs(t)},showPalette:!!n,showSelectionPalette:!!n,palette:[],maxSelectionSize:36,localStorageKey:"ctc-palette."+window.ctcAjax.child,hideAfterPaletteSelect:!0}).on("change",function(){c.coalesce_inputs(this)}).on("keyup",function(){var t=this,n=c.addhash(e(this).val());e(t).val(n),clearTimeout(e(this).data("spectrumTimer")),e(this).data("spectrumTimer",setTimeout(function(){c.coalesce_inputs(t),e(t).spectrum("set",n)},500))})}catch(i){c.jquery_exception(i,"Spectrum Color Picker")}},addhash:function(e){return e.replace(/^#?([a-f0-9]{3,6}.*)/,"#$1")},color_text:function(e){var t=this;return t.is_empty(e)?"":e.getAlpha()<1?e.toRgbString():e.toHexString()},setup_query_menu:function(){var t=this;try{e("#ctc_sel_ovrd_query").autocomplete({source:t.get_queries,minLength:0,selectFirst:!0,autoFocus:!0,select:function(e,c){return t.set_query(c.item.value),!1},focus:function(e){e.preventDefault()}}).data("menu",{})}catch(c){t.jquery_exception(c,"Query Menu")}},setup_selector_menu:function(){var t=this;try{e("#ctc_sel_ovrd_selector").autocomplete({source:t.get_selectors,selectFirst:!0,autoFocus:!0,select:function(e,c){return t.set_selector(c.item.value,c.item.label),!1},focus:function(e){e.preventDefault()}}).data("menu",{})}catch(c){t.jquery_exception(c,"Selector Menu")}},setup_rule_menu:function(){var t=this;try{e("#ctc_rule_menu").autocomplete({source:t.get_rules,selectFirst:!0,autoFocus:!0,select:function(e,c){return t.set_rule(c.item.value,c.item.label),!1},focus:function(e){e.preventDefault()}}).data("menu",{})}catch(c){t.jquery_exception(c,"Property Menu")}},setup_new_rule_menu:function(){var t=this;try{e("#ctc_new_rule_menu").autocomplete({source:t.get_filtered_rules,selectFirst:!0,autoFocus:!0,select:function(c,n){c.preventDefault();var i,a,s=n.item.label.replace(/[^\w\-]/g,t.toascii);return t.is_empty(t.currdata.value)&&(t.currdata.value={}),t.is_empty(t.currdata.value[n.item.label])&&(t.currdata.value[n.item.label]={}),t.is_empty(t.currdata.value[n.item.label].child)&&(t.currdata.value[n.item.label].child=[]),t.currdata.value[n.item.label].child.push(["",0,1,1]),i=e(t.input_row(t.currqsid,s,"ovrd",t.currdata,!0)),e("#ctc_sel_ovrd_rule_inputs").append(i),e("#ctc_new_rule_menu").val(""),i.find('input[type="text"]').each(function(c,n){a||(a=n),e(n).hasClass("color-picker")&&t.setup_spectrum(n)}),a&&e(a).focus(),!1},focus:function(e){e.preventDefault()}}).data("menu",{})}catch(c){t.jquery_exception(c,"New Property Menu")}},set_theme_params:function(t,c){e("#ctc_child_author").val(window.ctcAjax.themes[t][c].Author),e("#ctc_child_version").val(window.ctcAjax.themes[t][c].Version),e("#ctc_child_authoruri").val(window.ctcAjax.themes[t][c].AuthorURI),e("#ctc_child_themeuri").val(window.ctcAjax.themes[t][c].ThemeURI),e("#ctc_child_descr").val(window.ctcAjax.themes[t][c].Descr),e("#ctc_child_tags").val(window.ctcAjax.themes[t][c].Tags)},update_form:function(){var t,c=this;e("#input_row_stylesheet_handling_container,#input_row_parent_handling_container,#ctc_additional_css_files_container,#input_row_new_theme_slug,#input_row_duplicate_theme_slug,#ctc_copy_theme_mods,#ctc_child_header_parameters,#ctc_configure_submit,#input_row_theme_slug").slideUp("fast"),e("#ctc_configure_submit .ctc-step").text("9"),e("#ctc_theme_child").length&&!e("#ctc_child_type_new").is(":checked")?(t=e("#ctc_theme_child").val(),c.existing=1,c.currparnt=window.ctcAjax.themes.child[t].Template,c.autogen_slugs(),e("#ctc_theme_parnt").val(c.currparnt),e("#ctc_theme_parnt-button .ui-selectmenu-text").text(c.getname("parnt")),c.set_theme_params("child",t),e("#ctc_child_type_duplicate").is(":checked")?(e("#ctc_child_template").val(c.testslug),e("#ctc_child_name").val(c.testname),e(".ctc-analyze-theme, .ctc-analyze-howto").show(),e("#ctc_load_styles").val("Duplicate Child Theme")):e("#ctc_child_type_reset").is(":checked")?(e("#ctc_configure_submit .ctc-step").text("3"),e("#ctc_configure_submit").slideDown("fast"),e("#theme_slug_container").text(t),e(".ctc-analyze-theme, .ctc-analyze-howto").hide(),e("#ctc_enqueue_none").prop("checked",!0),e("#ctc_load_styles").val("Reset Child Theme to Previous State")):(e("#ctc_child_template").val(""),e("#theme_slug_container").text(t),e(".ctc-analyze-theme, .ctc-analyze-howto").show(),e("#ctc_child_name").val(c.getname("child")),e("#ctc_load_styles").val("Configure Child Theme")),e("#input_row_existing_theme_option").slideDown("fast"),e("#input_row_new_theme_option").slideUp("fast")):(c.existing=0,c.autogen_slugs(),e("#ctc_theme_parnt").val(c.currparnt),e("#ctc_theme_parnt-button .ui-selectmenu-text").text(e.chldthmcfg.getname("parnt")),c.set_theme_params("parnt",c.currparnt),e("#input_row_existing_theme_option,#input_row_duplicate_theme_container,#input_row_theme_slug").slideUp("fast"),e("#input_row_new_theme_option").slideDown("fast"),e("#ctc_child_name").val(c.testname),e("#ctc_child_template").val(c.testslug),e(".ctc-analyze-theme, .ctc-analyze-howto").show(),e("#ctc_load_styles").val("Create New Child Theme"))},set_notice:function(t){var c,n=this,i="";n.is_empty(t)||e.each(t,function(t,c){i+='<div class="'+t+' notice is-dismissible dashicons-before"><ul>\n',e(c).each(function(e,t){i+="<li>"+t.toString()+"</li>\n"}),i+="</ul></div>"}),c=e(i),e("#ctc_error_notice").html(c),n.bind_dismiss(c),e("html, body").animate({scrollTop:0},"slow")},set_parent_menu:function(e){var t=this;t.currparnt=e.value,t.update_form()},set_child_menu:function(e){var t=this;t.currchild=e.value,t.update_form()},set_query:function(t){var c=this;return c.is_empty(t)?!1:(c.currquery=t,e("#ctc_sel_ovrd_query").val(""),e("#ctc_sel_ovrd_query_selected").text(t),e("#ctc_sel_ovrd_selector").val(""),e("#ctc_sel_ovrd_selector_selected").html("&nbsp;"),c.load_selectors(),void c.scrolltop())},set_selector:function(t,c){var n=this;return c=null,n.is_empty(t)?!1:(e("#ctc_sel_ovrd_selector").val(""),n.currqsid=t,n.reload=!1,n.load_selector_values(),void n.scrolltop())},set_rule:function(t,c){var n=this;return n.is_empty(t)?!1:(e("#ctc_rule_menu").val(""),e("#ctc_rule_menu_selected").text(c),e(".ctc-rewrite-toggle").text(n.getxt("rename")),e("#ctc_rule_value_inputs, #ctc_input_row_rule_header").show(),n.query_css("rule_val",t),void n.scrolltop())},set_qsid:function(t){var c=this;c.currqsid=e(t).attr("id").match(/_(\d+)$/)[1],c.focus_panel("#query_selector_options"),c.reload=!0,c.load_selector_values()},query_css:function(t,c,n){var i=this,a={ctc_query_obj:t,ctc_query_key:c},s="#ctc_status_"+t+("val_qry"===t?"_"+c:"");"object"==typeof n&&e.each(n,function(e,t){a["ctc_query_"+e]=t}),e(".query-icon,.ctc-status-icon").remove(),e(s+" .ctc-status-icon").remove(),e(s).append('<span class="ctc-status-icon spinner is-active query-icon"></span>'),a.action=i.is_empty(e("#ctc_action").val())||"plugin"!==e("#ctc_action").val()?"ctc_query":"ctc_plgqry",a._wpnonce=e("#_wpnonce").val(),i.ajax_post(t,a)},save:function(t){var c,n,i,a,s,l=this,r={},o=e(t).attr("id");e(t).prop("disabled",!0),e(".ctc-query-icon,.ctc-status-icon").remove(),e(t).parent(".ctc-textarea-button-cell, .ctc-button-cell").append('<span class="ctc-status-icon spinner save-icon"></span>'),o.match(/ctc_configtype/)?(e(t).parents(".ctc-input-row").first().append('<span class="ctc-status-icon spinner save-icon"></span>'),r.ctc_configtype=e(t).val()):(c=e("#ctc_new_selectors"))&&"ctc_save_new_selectors"===e(t).attr("id")?(r.ctc_new_selectors=c.val(),(n=e("#ctc_sel_ovrd_query_selected"))&&(r.ctc_sel_ovrd_query=n.text()),l.reload=!0):(i=e("#ctc_child_imports"))&&"ctc_save_imports"===o?r.ctc_child_imports=i.val():"ctc_is_debug"===o?r.ctc_is_debug=e("#ctc_is_debug").is(":checked")?1:0:r=l.coalesce_inputs(t),e(".save-icon").addClass("is-active"),e("#ctc_sel_ovrd_selector_selected").find("#ctc_rewrite_selector").each(function(){a=e("#ctc_rewrite_selector").val(),s=e("#ctc_rewrite_selector_orig").val(),l.is_empty(a)||!a.toString().match(/\w/)?a=s:(r.ctc_rewrite_selector=a,l.reload=!0),e(".ctc-rewrite-toggle").text(l.getxt("rename")),e("#ctc_sel_ovrd_selector_selected").html(a)}),r.action=l.is_empty(e("#ctc_action").val())||"plugin"!==e("#ctc_action").val()?"ctc_update":"ctc_plugin",r._wpnonce=e("#_wpnonce").val(),l.ajax_post("qsid",r)},ajax_post:function(t,c,n){var i=this;e.ajax({url:window.ctcAjax.ajaxurl,data:c,dataType:i.is_empty(n)?"json":n,type:"POST"}).done(function(e){i.handle_success(t,e)}).fail(function(){i.handle_failure(t)}).always(function(){i.jqueryerr.length&&i.jquery_notice()})},handle_failure:function(t){var c=this;e(".query-icon, .save-icon").removeClass("spinner").addClass("failure"),e("input[type=submit], input[type=button], input[type=checkbox],.ctc-delete-input").prop("disabled",!1),e(".ajax-pending").removeClass("ajax-pending"),"preview"===t&&e("#view_parnt_options_panel,#view_child_options_panel").text(c.getxt("css_fail"))},handle_success:function(t,c){var n=this;e(".query-icon, .save-icon").removeClass("spinner"),e(".ajax-pending").removeClass("ajax-pending"),n.is_empty(c)?n.handle_failure(t):(e("#ctc_new_selectors").val(""),e(".query-icon, .save-icon").addClass("success"),e("input[type=submit], input[type=button], input[type=checkbox],.ctc-delete-input").prop("disabled",!1),e(c).each(function(){"function"==typeof n.update[this.obj]&&n.update[this.obj].call(n,this)}))},jquery_exception:function(e,t){var c=this,n=c.is_empty(e.lineNumber)?"":" line: "+e.lineNumber,i=c.is_empty(e.fileName)?"":" "+e.fileName.split(/\?/)[0];c.jqueryerr.push("<code><small>"+t+": "+e.message+i+n+"</small></code>")},jquery_notice:function(t){t=null;var c=this,n=[],i=[];c.jqueryerr.length&&(e("input[type=submit], input[type=button]").prop("disabled",!0),e("script").each(function(){var t=e(this).prop("src");c.is_empty(t)||!t.match(/jquery(\.min|\.js|\-?ui)/i)||t.match(/load\-scripts.php/)||n.push("<code><small>"+t.split(/\?/)[0]+"</small></code>")}),i.push("<strong>"+c.getxt("js")+"</strong> "+c.getxt("contact")),i.push(c.jqueryerr.join("<br/>")),n.length&&i.push(c.getxt("jquery")+"<br/>"+n.join("<br/>")),i.push(c.getxt("plugin"))),c.set_notice({error:i})},update:{qsid:function(t){var c,n,i,a,s=this;s.currqsid=t.key,s.currdata=t.data,e("#ctc_sel_ovrd_qsid").val(s.currqsid),s.is_empty(s.currdata.seq)?e("#ctc_child_load_order_container").empty():(c="ctc_ovrd_child_seq_"+s.currqsid,i=parseInt(s.currdata.seq),n='<input type="text" id="'+c+'" name="'+c+'" class="ctc-child-value" value="'+i+'" />',e("#ctc_child_load_order_container").html(n)),s.is_empty(s.currdata.value)?(a=!0,e("#ctc_sel_ovrd_rule_inputs").empty()):(a=!1,n="",e.each(s.currdata.value,function(e,t){t=null,n+=s.input_row(s.currqsid,e,"ovrd",s.currdata)}),e("#ctc_sel_ovrd_rule_inputs").html(n).find(".color-picker").each(function(){s.setup_spectrum(this)}),s.coalesce_inputs("#ctc_child_all_0_swatch")),s.reload&&(s.load_queries(),s.set_query(s.currdata.query),s.load_rules()),e("#ctc_sel_ovrd_selector_selected").text(s.currdata.selector),e(".ctc-rewrite-toggle").text(s.getxt("rename")),e(".ctc-rewrite-toggle").show(),a?e("#ctc_sel_ovrd_rule_header,#ctc_sel_ovrd_new_rule,#ctc_sel_ovrd_rule_inputs_container,#ctc_sel_ovrd_rule_inputs").hide():e("#ctc_sel_ovrd_rule_header,#ctc_sel_ovrd_new_rule,#ctc_sel_ovrd_rule_inputs_container,#ctc_sel_ovrd_rule_inputs").show()},rule_val:function(t){var c=this,n=e("#ctc_rule_menu_selected").text(),i='<div class="ctc-input-row clearfix" id="ctc_rule_row_'+n+'">\n';c.is_empty(t.data)||(e.each(t.data,function(e,t){var a=c.decode_value(n,t);i+='<div class="ctc-parent-row clearfix" id="ctc_rule_row_'+n+"_"+e+'">\n<div class="ctc-input-cell ctc-parent-value" id="ctc_'+e+"_parent_"+n+"_"+e+'">'+a.orig+'</div>\n<div class="ctc-input-cell">\n<div class="ctc-swatch ctc-specific" id="ctc_'+e+"_parent_"+n+"_"+e+'_swatch">'+c.getxt("swatch")+'</div></div>\n<div class="ctc-input-cell"><a href="#" class="ctc-selector-handle" id="ctc_selector_'+n+"_"+e+'">'+c.getxt("selector")+'</a></div>\n<div id="ctc_selector_'+n+"_"+e+'_container" class="ctc-selector-container">\n<a href="#" id="ctc_selector_'+n+"_"+e+'_close" class="ctc-selector-handle ctc-exit" title="'+c.getxt("close")+'"></a><div id="ctc_selector_'+n+"_"+e+'_inner_container" class="ctc-selector-inner-container clearfix">\n<div id="ctc_status_val_qry_'+e+'"></div>\n<div id="ctc_selector_'+n+"_"+e+'_rows"></div>\n</div></div></div>\n'}),i+="</div>\n"),e("#ctc_rule_value_inputs").html(i).find(".ctc-swatch").each(function(){c.coalesce_inputs(this)})},val_qry:function(t){var c,n,i=this,a="";i.is_empty(t.data)||e.each(t.data,function(n,s){c=n,e.each(s,function(c,s){a+='<h4 class="ctc-query-heading">'+c+"</h4>\n",i.is_empty(s)||e.each(s,function(e,c){a+=i.input_row(e,n,t.key,c)})})}),n="#ctc_selector_"+c+"_"+t.key+"_rows",e(n).html(a).find(".color-picker").each(function(){i.setup_spectrum(this)}),e(n).find(".ctc-swatch").each(function(){i.coalesce_inputs(this)})},queries:function(t){e("#ctc_sel_ovrd_query").data("menu",t.data)},selectors:function(t){e("#ctc_sel_ovrd_selector").data("menu",t.data)},rules:function(t){e("#ctc_rule_menu").data("menu",t.data)},debug:function(t){e("#ctc_debug_box").val(e("#ctc_debug_box").val()+t.data)},preview:function(t){e("#view_"+t.key+"_options_panel").text(t.data)},dismiss:function(){}},bind_dismiss:function(t){var c=this,n=e(t),i=e('<button type="button" class="notice-dismiss"><span class="screen-reader-text"></span></button>'),a=window.commonL10n.dismiss||"";i.find(".screen-reader-text").text(a),n.append(i),i.on("click.wp-dismiss-notice",function(e){e.preventDefault(),c.dismiss_notice(t)})},dismiss_notice:function(t){e(t).fadeTo(100,0,function(){e(this).slideUp(100,function(){e(this).remove()})})},reset_handling:function(){e("#parnt_analysis_notice .notice, #child_analysis_notice .notice").slideUp(),e("#ctc_enqueue_enqueue").prop("checked",!0),e("#ctc_handling_primary").prop("checked",!0),e("#ctc_ignoreparnt").prop("checked",!1),e("#ctc_repairheader").prop("checked",!1)},init:function(){var t=this;if(!e("#ctc_theme_parnt").is("input")){try{e.widget("ctc.themeMenu",e.ui.selectmenu,{_renderItem:function(t,c){var n=e("<li>"),i=c.value.replace(/[^\w\-]/,"");return e("#ctc_theme_option_"+i).detach().appendTo(n),n.appendTo(t)}})}catch(c){t.jquery_exception(c,"Theme Menu")}try{e("#ctc_theme_parnt").themeMenu({select:function(e,c){t.reset_handling(),t.set_parent_menu(c.item)}})}catch(c){"function"==typeof themeMenu?e("#ctc_theme_parnt").themeMenu("destroy"):e("#ctc_theme_parnt-button").remove(),t.jquery_exception(c,"Parent Theme Menu")}if(t.is_empty(window.ctcAjax.themes.child))e("#ctc_child_name").length&&(e("#ctc_child_name").val(t.testname),e("#ctc_child_template").val(t.testslug));else try{e("#ctc_theme_child").themeMenu({select:function(e,c){t.reset_handling(),t.set_child_menu(c.item)}})}catch(c){"function"==typeof themeMenu?e("#ctc_theme_child").themeMenu("destroy"):e("#ctc_theme_child-button").remove(),t.jquery_exception(c,"Child Theme Menu")}}t.currparnt=e("#ctc_theme_parnt").val(),t.currchild=e("#ctc_theme_child").length?e("#ctc_theme_child").val():"",e("#ctc_main").on("click",".ctc-section-toggle",function(t){t.preventDefault(),e(this).parents(".ctc-input-row, .notice-warning, .updated, .error").first().find(".ctc-section-toggle").each(function(){e(this).toggleClass("open")});var c=e(this).attr("id").replace(/\d$/,"")+"_content";return e("#"+c).stop().slideToggle("fast"),!1}),e("#ctc_main").on("click",".ctc-upgrade-notice .notice-dismiss",function(){var c={action:"ctc_dismiss",_wpnonce:e("#_wpnonce").val()};t.ajax_post("dismiss",c)}),t.is_empty(t.jqueryerr)&&(e("#ctc_main").on("click",".ctc-selector-handle",function(c){if(c.preventDefault(),e(this).hasClass("ajax-pending"))return!1;e(this).addClass("ajax-pending");var n,i,a=e(this).attr("id").toString().replace("_close",""),s=a.toString().match(/_([^_]+)_(\d+)$/);e("#"+a+"_container").is(":hidden")&&(t.is_empty(s[1])||t.is_empty(s[2])||(n=s[1],i=s[2],t.query_css("val_qry",i,{rule:n}))),e("#"+a+"_container").fadeToggle("fast"),e(".ctc-selector-container").not("#"+a+"_container").fadeOut("fast")}),e("#ctc_main").on("click",".ctc-save-input[type=button], .ctc-delete-input",function(c){return c.preventDefault(),e(this).hasClass("ajax-pending")?!1:(e(this).addClass("ajax-pending"),t.save(this),!1)}),e("#ctc_main").on("keydown",".ctc-selector-container .ctc-child-value[type=text]",function(c){if(13===c.which){var n=e(this).parents(".ctc-selector-row").find(".ctc-save-input[type=button]").first();if(n.length)return c.preventDefault(),n.hasClass("ajax-pending")?!1:(n.addClass("ajax-pending"),t.save(n),!1)}}),e("#ctc_main").on("click",".ctc-selector-edit",function(c){return c.preventDefault(),e(this).hasClass("ajax-pending")?!1:(e(this).addClass("ajax-pending"),void t.set_qsid(this))}),e("#ctc_main").on("click",".ctc-rewrite-toggle",function(e){e.preventDefault(),t.selector_input_toggle(this)}),e("#ctc_main").on("click","#ctc_copy_selector",function(){var c=e("#ctc_sel_ovrd_selector_selected").text().trim();t.is_empty(c)||e("#ctc_new_selectors").val(e("#ctc_new_selectors").val()+"\n"+c+" {\n\n}")}),e("#ctc_main").on("click",".ctc-backup-theme",function(c){c.preventDefault(),t.existing?e("#ctc_export_theme").val(t.currchild):e("#ctc_export_theme").val(t.currparnt),e("#ctc_export_theme_form").submit()}),e("#ctc_configtype").on("change",function(){var c=e(this).val();if(t.is_empty(c)||"theme"===c){e(".ctc-theme-only, .ctc-themeonly-container").removeClass("ctc-disabled"),e(".ctc-theme-only, .ctc-themeonly-container input").prop("disabled",!1);try{e("#ctc_theme_parnt, #ctc_theme_child").themeMenu("enable")}catch(n){t.jquery_exception(n,"Theme Menu")}}else{e(".ctc-theme-only, .ctc-themeonly-container").addClass("ctc-disabled"),e(".ctc-theme-only, .ctc-themeonly-container input").prop("disabled",!0);try{e("#ctc_theme_parnt, #ctc_theme_child").themeMenu("disable")}catch(n){t.jquery_exception(n,"Theme Menu")}}}),e(".nav-tab").on("click",function(c){c.preventDefault(),e(".ctc-query-icon,.ctc-status-icon").remove();var n="#"+e(this).attr("id");t.focus_panel(n)}),e("#view_child_options, #view_parnt_options").on("click",function(){return e(this).hasClass("ajax-pending")?!1:(e(this).addClass("ajax-pending"),void t.css_preview(e(this).attr("id")))}),e("#ctc_load_form").on("submit",function(){return t.validate()}),e("#ctc_query_selector_form").on("submit",function(c){c.preventDefault();var n=e("#ctc_save_query_selector");return n.hasClass("ajax-pending")?!1:(n.addClass("ajax-pending"),t.save(n),!1)}),e("#ctc_rule_value_form").on("submit",function(e){return e.preventDefault(),!1}),e("#ctc_child_type_new,#ctc_child_type_existing,#ctc_child_type_duplicate,#ctc_child_type_reset").on("focus click",function(){t.reset_handling(),t.update_form()}),e("#ctc_is_debug").on("change",function(){e(this).is(":checked")?e("#ctc_debug_box").length||e("#ctc_debug_container").html('<textarea id="ctc_debug_box"></textarea>'):e("#ctc_debug_box").remove(),t.save(this)}),e(".ctc-live-preview").on("click",function(t){return t.stopImmediatePropagation(),t.preventDefault(),document.location=e(this).prop("href"),!1}),t.setup_menus(),e("input[type=submit], input[type=button]").prop("disabled",!1),t.scrolltop(),t.update_form()),t.jqueryerr.length&&t.jquery_notice()},testslug:"",testname:"",reload:!1,currquery:"base",currqsid:null,currdata:{},currparnt:"",currchild:"",existing:!1,jqueryerr:[],color_regx:"\\s+(\\#[a-f0-9]{3,6}|rgba?\\([\\d., ]+?\\)|hsla?\\([\\d%., ]+?\\)|[a-z]+)",border_regx:"(\\w+)(\\s+(\\w+))?",grad_regx:"(\\w+)"},e.chldthmanalyze={show_loading:function(t,c){var n=e.chldthmcfg.existing?"child":"parnt",i=c?c:e.chldthmcfg.getname(n),a='<strong class="ctc_analyze_loading"><span class="spinner is-active"></span>'+e.chldthmcfg.getxt(t?"anlz1":"anlz2")+" "+i+"...</strong>";self.noticediv="",e("#"+n+"_analysis_notice").html(a)},hide_loading:function(){e(".ctc_analyze_loading").fadeTo(200,0,function(){e(this).slideUp(200,function(){e(this).remove()})})},analyze_theme:function(t){var c=this,n=e.chldthmcfg.currparnt,i="child"===t?e.chldthmcfg.currchild:e.chldthmcfg.currparnt;e.ajax({url:window.ctcAjax.ajaxurl,data:{action:"ctc_analyze",stylesheet:i,template:n,_wpnonce:e("#_wpnonce").val()},dataType:"json",type:"POST"}).done(function(n){c.analysis[t]=n,e.each(n.dependencies,function(e,t){c.dependencies[e]=t}),e(document).trigger("analysisdone")}).fail(function(n,i,a){var s={signals:{failure:1,xhrerr:a}};c.analysis[t]=s,e(document).trigger("analysisdone")})},css_notice:function(){var t,c,n=this,i=e.chldthmcfg.existing?"child":"parnt",a=e.chldthmcfg.getname(i),s="",l={notices:[]},r={style:"notice-warning",headline:e.chldthmcfg.getxt("anlz3",a),errlist:""},o=0,_={},d="";if(n.analysis[i].signals.failure||n.analysis[i].signals.thm_noqueue&&!n.phperr[i].length)e("#ctc_is_debug").is(":checked")&&(d=e.chldthmcfg.getxt("anlz33").replace(/%1/,'<a href="'+n.analysis[i].url+'" target="_new">').replace(/%2/,"</a>")),e("#ctc_is_debug").is(":checked")&&(d=e.chldthmcfg.getxt("anlz33").replace(/%1/,'<a href="'+n.analysis[template].url+'" target="_new">').replace(/%2/,"</a>")),l.notices.push({headline:e.chldthmcfg.getxt("anlz4",a),msg:e.chldthmcfg.getxt("anlz5")+d,style:"notice-warning"});else{if(n.analysis[i].errors.length&&(e.each(n.analysis[i].errors,function(t,c){c.match(/Fatal error/i)&&(r.style="error",r.headline=e.chldthmcfg.getxt("anlz8",a)),r.errlist+=c+"\n"}),r.msg='<div style="background-color:#ffeebb;padding:6px"><div class="ctc-section-toggle" id="ctc_analysis_errs">'+e.chldthmcfg.getxt("anlz6")+'</div><div id="ctc_analysis_errs_content" style="display:none"><textarea>'+r.errlist+"</textarea></div></div>"+e.chldthmcfg.getxt("anlz7"),
2
+ l.notices.push(r)),(n.analysis[i].signals.thm_past_wphead||n.analysis[i].signals.dep_past_wphead)&&(l.notices.push({headline:e.chldthmcfg.getxt("anlz9"),style:"notice-warning",msg:e.chldthmcfg.getxt("anlz10")}),e("#ctc_repairheader").prop("checked",!0),e("#ctc_repairheader_container").show()),n.analysis[i].signals.thm_unregistered&&(n.analysis[i].signals.ctc_child_loaded||n.analysis[i].signals.ctc_sep_loaded||(l.notices.push({headline:e.chldthmcfg.getxt("anlz11"),style:"notice-warning",msg:e.chldthmcfg.getxt("anlz12")}),e("#ctc_repairheader_container").show(),e("#ctc_repairheader").prop("checked",!0))),"child"===i&&(n.analysis.child.signals.ctc_parnt_reorder&&(o=1),n.analysis.child.signals.ctc_child_loaded||n.analysis.child.signals.ctc_sep_loaded||n.analysis.child.signals.thm_child_loaded||(l.notices.push({headline:e.chldthmcfg.getxt("anlz13"),style:"notice-warning",msg:e.chldthmcfg.getxt("anlz14")}),o=1),n.analysis[i].signals.ctc_gen_loaded&&l.notices.push({headline:e.chldthmcfg.getxt("anlz31"),msg:e.chldthmcfg.getxt("anlz32"),style:"notice-warning"}),n.analysis.parnt.signals.thm_no_styles||n.analysis.child.signals.ctc_gen_loaded||n.analysis.child.signals.thm_parnt_loaded||n.analysis.child.signals.ctc_parnt_loaded||n.analysis.child.signals.thm_ignoreparnt||n.analysis.child.signals.thm_has_import||(l.notices.push({headline:e.chldthmcfg.getxt("anlz15"),style:"notice-warning",msg:e.chldthmcfg.getxt("anlz16")}),o=1),n.analysis.child.signals.thm_unregistered&&n.analysis.child.signals.thm_child_loaded&&"thm_unregistered"===n.analysis.child.signals.thm_child_loaded&&n.analysis.child.signals.ctc_child_loaded&&n.analysis.child.signals.ctc_parnt_loaded&&(l.notices.push({headline:e.chldthmcfg.getxt("anlz28"),style:"notice-warning",msg:e.chldthmcfg.getxt("anlz29")}),e("#ctc_repairheader_container").show(),e("#ctc_repairheader").prop("checked",!0)),n.analysis.child.signals.thm_is_ctc||e("#ctc_child_type_duplicate").is(":checked")||l.notices.push({headline:e.chldthmcfg.getxt("anlz19"),msg:e.chldthmcfg.getxt("anlz20"),style:"notice-warning"})),(n.analysis[i].signals.ctc_sep_loaded||n.analysis[i].signals.ctc_gen_loaded)&&e("#ctc_handling_separate").prop("checked",!0),l.notices.length||l.notices.push({headline:""+("child"===i?e.chldthmcfg.getxt("anlz17"):e.chldthmcfg.getxt("anlz18")),style:"updated",msg:""}),"child"===i&&n.analysis.child.signals.thm_has_import&&(l.notices.push({headline:e.chldthmcfg.getxt("anlz21"),msg:e.chldthmcfg.getxt("anlz22"),style:"notice-warning"}),e("#ctc_enqueue_import").prop("checked",!0)),n.analysis[i].signals.thm_ignoreparnt||n.analysis[i].signals.ctc_gen_loaded?(e("#ctc_ignoreparnt").prop("checked",!0),e("#ctc_enqueue_none").is(":checked")||(e("#ctc_enqueue_none").prop("checked",!0),o=1,_.ctc_enqueue="none")):e("#ctc_ignoreparnt").prop("checked",!1),!n.analysis[i].signals.ctc_sep_loaded&&!n.analysis[i].signals.ctc_gen_loaded&&!n.analysis[i].signals.ctc_child_loaded&&!n.analysis[i].signals.thm_unregistered&&!n.analysis[i].signals.thm_past_wphead&&n.analysis[i].deps[1].length){var u="";e.each(n.analysis[i].deps[1],function(e,t){t[1].match(/^style([\-\.]min)?\.css$/)||(u+="<li>"+t[1]+"</li>\n")}),""!==u&&(u="<ul class='howto' style='padding-left:1em'>\n"+u+"</ul>\n",l.notices.push({headline:e.chldthmcfg.getxt("anlz23"),msg:u+e.chldthmcfg.getxt("anlz24"),style:"updated"}))}"child"===i&&n.analysis[i].signals.thm_parnt_loaded&&(l.notices.push({headline:e.chldthmcfg.getxt("anlz25"),msg:e.chldthmcfg.getxt("anlz26"),style:"updated"}),e("#ctc_enqueue_none").prop("checked",!0),o=1,_.ctc_enqueue="none"),n.analysis.parnt.signals.thm_no_styles&&(l.notices.push({headline:e.chldthmcfg.getxt("anlz27"),msg:e.chldthmcfg.getxt("anlz26"),style:"updated"}),e("#ctc_enqueue_none").prop("checked",!0),o=1,_.ctc_enqueue="none")}return s=encodeURIComponent(JSON.stringify(n.analysis)),e('input[name="ctc_analysis"]').val(s),_.ctc_analysis=s,n.is_success()&&o&&!n.resubmitting?(n.resubmitting=1,void n.resubmit(_)):(n.resubmitting=0,n.hide_loading(),e.each(l.notices,function(t,c){var n=e('<div class="'+c.style+' notice is-dismissible dashicons-before" ><h4>'+c.headline+"</h4>"+c.msg+"</div>");e.chldthmcfg.bind_dismiss(n),n.hide().appendTo("#"+i+"_analysis_notice").slideDown()}),e("#ctc_is_debug").is(":checked")&&(t='<div style="background-color:#ddd;padding:6px"><div class="ctc-section-toggle" id="ctc_analysis_obj">'+e.chldthmcfg.getxt("anlz30")+'</div><div id="ctc_analysis_obj_content" style="display:none"><textarea style="font-family:monospace;font-size:10px">'+JSON.stringify(n.analysis,null,2)+"</textarea></div></div>",e(t).appendTo("#"+i+"_analysis_notice")),c="",e.each(n.dependencies,function(t,n){n&&(c+='<label><input class="ctc_checkbox ctc-themeonly" id="ctc_forcedep_'+t+'" name="ctc_forcedep[]" type="checkbox" value="'+t+'" autocomplete="off" '+(-1!==e.inArray(t,window.ctcAjax.forcedep)?"checked":"")+" />"+t+"</label><br/>\n")}),c.length?(e("#ctc_dependencies").html(c),e("#ctc_dependencies_container").show()):(e("#ctc_dependencies").empty(),e("#ctc_dependencies_container").hide()),e("#ctc_child_type_reset").is(":checked")||(e("#input_row_stylesheet_handling_container,#input_row_parent_handling_container,#ctc_child_header_parameters,#ctc_configure_submit").slideDown("fast"),e("#ctc_child_type_duplicate").is(":checked")?(e("#ctc_configure_submit .ctc-step").text("8"),e("#ctc_copy_theme_mods").find("input").prop("checked",!1)):(e("#ctc_configure_submit .ctc-step").text("9"),e("#ctc_copy_theme_mods").slideDown("fast")),e("#ctc_child_type_duplicate").is(":checked")||e("#ctc_child_type_new").is(":checked")?(e("#input_row_theme_slug").hide(),e("#input_row_new_theme_slug").slideDown("fast")):(e("#input_row_new_theme_slug").hide(),e("#input_row_theme_slug").slideDown("fast"))),void 0)},resubmit:function(t){var c=this;c.hide_loading(),c.show_loading(!0),t.action="ctc_update",t._wpnonce=e("#_wpnonce").val(),e.ajax({url:window.ctcAjax.ajaxurl,data:t,type:"POST"}).done(function(){c.hide_loading(),c.do_analysis()}).fail(function(){c.hide_loading()})},do_analysis:function(){var t=this;t.analysis={parnt:{},child:{}},t.phperr={parnt:[],child:[]},t.dependencies={},t.done=0,t.show_loading(!1),t.analyze_theme("parnt"),e.chldthmcfg.existing&&t.analyze_theme("child")},init:function(){var t=this;e(document).on("analysisdone",function(){t.done++,t.done>e.chldthmcfg.existing&&(t.done=0,t.css_notice())}),e("#ctc_main").on("click",".ctc-analyze-theme",function(){t.is_success()&&e.chldthmcfg.dismiss_notice(e(".ctc-success-response").parent(".notice")),t.do_analysis()}),t.is_success()&&!window.ctcAjax.pluginmode&&t.do_analysis()},analysis:{},done:0,resubmitting:0,dependencies:{},is_success:function(){return e(".ctc-success-response").length}},e("#request-filesystem-credentials-form").length||(e.chldthmcfg.init(),e.chldthmanalyze.init())}(jQuery);
js/ctcgrad.js CHANGED
@@ -5,199 +5,199 @@
5
  * Licensed under the GPLv2 license.
6
  */
7
  (function( $, undef ){
8
- var _html, nonGradientIE, gradientType, vendorPrefixes, _css, Iris, UA, isIE, IEVersion;
9
- UA = navigator.userAgent.toLowerCase();
10
- isIE = navigator.appName === 'Microsoft Internet Explorer';
11
- IEVersion = isIE ? parseFloat( UA.match( /msie ([0-9]{1,}[\.0-9]{0,})/ )[1] ) : 0;
12
- nonGradientIE = ( isIE && IEVersion < 10 );
13
- // we don't bother with an unprefixed version, as it has a different syntax
14
- vendorPrefixes = ['-moz-', '-webkit-', '-o-', '-ms-' ];
15
- testGradientType();
16
-
17
- // Bail for IE <= 7
18
- if ( nonGradientIE && IEVersion <= 7 ) {
19
- $.fn.ctcgrad = $.noop;
20
- $.support.ctcgrad = false;
21
- return;
22
- }
23
-
24
- $.support.ctcgrad = true;
25
-
26
- function testGradientType() {
27
- var el, base;
28
- if ( nonGradientIE ) {
29
- gradientType = 'filter';
30
- }
31
- else {
32
- el = $('<div id="ctcgrad-gradtest" />');
33
- base = "linear-gradient(top,#fff,#000)";
34
- $.each( vendorPrefixes, function( i, val ){
35
- el.css( 'backgroundImage', val + base );
36
- if ( el.css( 'backgroundImage').match('gradient') ) {
37
- gradientType = i;
38
- return false;
39
- }
40
- });
41
- // check for legacy webkit gradient syntax
42
- if ( gradientType === false ) {
43
- el.css( 'background', '-webkit-gradient(linear,0% 0%,0% 100%,from(#fff),to(#000))' );
44
- if ( el.css( 'backgroundImage').match('gradient') )
45
- gradientType = 'webkit';
46
- }
47
- el.remove();
48
- }
49
-
50
- }
51
-
52
- /**
53
- * Only for CSS3 gradients. oldIE will use a separate function.
54
- *
55
- * Accepts as many color stops as necessary from 2nd arg on, or 2nd
56
- * arg can be an array of color stops
57
- *
58
- * @param {string} origin Gradient origin - top bottom left right (n)deg
59
- * @return {string} Appropriate CSS3 gradient string for use in
60
- */
61
- function createGradient( origin, stops ) {
62
- origin = ( origin.match(/(\d+deg|top|left|bottom|right)( (top|left|bottom|right))?/) ? origin : 'top');
63
- stops = $.isArray( stops ) ? stops : Array.prototype.slice.call(arguments, 1);
64
- if ( gradientType === 'webkit' )
65
- return legacyWebkitGradient( origin, stops );
66
- else
67
- return vendorPrefixes[gradientType] + 'linear-gradient(' + origin + ', ' + stops.join(', ') + ')';
68
- }
69
-
70
- /**
71
- * Stupid gradients for a stupid browser.
72
- */
73
- function stupidIEGradient( origin, stops ) {
74
- var type, self, lastIndex, filter, startPosProp, endPosProp, dimensionProp, template, html, filterVal;
75
-
76
- origin = ( origin === 'left' ) ? 'left' : 'top';
77
- stops = $.isArray( stops ) ? stops : Array.prototype.slice.call(arguments, 1);
78
- // 8 hex: AARRGGBB
79
- // GradientType: 0 vertical, 1 horizontal
80
- type = ( origin === 'top' ) ? 0 : 1;
81
- self = $( this );
82
- lastIndex = stops.length - 1;
83
- filter = 'filter';
84
- startPosProp = ( type === 1 ) ? 'left' : 'top';
85
- endPosProp = ( type === 1 ) ? 'right' : 'bottom';
86
- dimensionProp = ( type === 1 ) ? 'height' : 'width';
87
- // need a positioning context
88
- if ( self.css('position') === 'static' )
89
- self.css( {position: 'relative' } );
90
-
91
- stops = fillColorStops( stops );
92
- $.each(stops, function( i, startColor ) {
93
- var endColor, endStop;
94
-
95
- // we want two at a time. if we're on the last pair, bail.
96
- if ( i === lastIndex )
97
- return false;
98
-
99
- endColor = stops[ i + 1 ];
100
- //if our pairs are at the same color stop, moving along.
101
- if ( startColor.stop === endColor.stop )
102
- return;
103
-
104
- endStop = 100 - parseFloat( endColor.stop ) + '%';
105
- startColor.octoHex = new Color( startColor.color ).toIEOctoHex();
106
- endColor.octoHex = new Color( endColor.color ).toIEOctoHex();
107
-
108
- filterVal = "progid:DXImageTransform.Microsoft.Gradient(GradientType=" + type + ", StartColorStr='" + startColor.octoHex + "', EndColorStr='" + endColor.octoHex + "')";
109
- });
110
  return filterVal;
111
- }
112
-
113
- function legacyWebkitGradient( origin, colorList ) {
114
- var stops = [];
115
- origin = ( origin === 'top' ) ? '0% 0%,0% 100%,' : '0% 100%,100% 100%,';
116
- colorList = fillColorStops( colorList );
117
- $.each( colorList, function( i, val ){
118
- stops.push( 'color-stop(' + ( parseFloat( val.stop ) / 100 ) + ', ' + val.color + ')' );
119
- });
120
- return '-webkit-gradient(linear,' + origin + stops.join(',') + ')';
121
- }
122
-
123
- function fillColorStops( colorList ) {
124
- var colors = [],
125
- percs = [],
126
- newColorList = [],
127
- lastIndex = colorList.length - 1;
128
-
129
- $.each( colorList, function( index, val ) {
130
- var color = val,
131
- perc = false,
132
- match = val.match(/1?[0-9]{1,2}%$/);
133
-
134
- if ( match ) {
135
- color = val.replace(/\s?1?[0-9]{1,2}%$/, '');
136
- perc = match.shift();
137
- }
138
- colors.push( color );
139
- percs.push( perc );
140
- });
141
-
142
- // back fill first and last
143
- if ( percs[0] === false )
144
- percs[0] = '0%';
145
-
146
- if ( percs[lastIndex] === false )
147
- percs[lastIndex] = '100%';
148
-
149
- percs = backFillColorStops( percs );
150
-
151
- $.each( percs, function( i ){
152
- newColorList[i] = { color: colors[i], stop: percs[i] };
153
- });
154
- return newColorList;
155
- }
156
-
157
- function backFillColorStops( stops ) {
158
- var first = 0,
159
- last = stops.length - 1,
160
- i = 0,
161
- foundFirst = false,
162
- incr,
163
- steps,
164
- step,
165
- firstVal;
166
-
167
- if ( stops.length <= 2 || $.inArray( false, stops ) < 0 ) {
168
- return stops;
169
- }
170
- while ( i < stops.length - 1 ) {
171
- if ( ! foundFirst && stops[i] === false ) {
172
- first = i - 1;
173
- foundFirst = true;
174
- } else if ( foundFirst && stops[i] !== false ) {
175
- last = i;
176
- i = stops.length;
177
- }
178
- i++;
179
- }
180
- steps = last - first;
181
- firstVal = parseInt( stops[first].replace('%'), 10 );
182
- incr = ( parseFloat( stops[last].replace('%') ) - firstVal ) / steps;
183
- i = first + 1;
184
- step = 1;
185
- while ( i < last ) {
186
- stops[i] = ( firstVal + ( step * incr ) ) + '%';
187
- step++;
188
- i++;
189
- }
190
- return backFillColorStops( stops );
191
- }
192
-
193
- $.fn.ctcgrad = function( origin ) {
194
- var args = arguments;
195
- // this'll be oldishIE
196
- if ( nonGradientIE )
197
  $(this).css('filter',
198
- stupidIEGradient.apply( this, args ));
199
- else // new hotness
200
- $( this ).css( 'backgroundImage', createGradient.apply( this, args ) );
201
- };
202
 
203
  }( jQuery ));
5
  * Licensed under the GPLv2 license.
6
  */
7
  (function( $, undef ){
8
+ var _html, nonGradientIE, gradientType, vendorPrefixes, _css, Iris, UA, isIE, IEVersion;
9
+ UA = navigator.userAgent.toLowerCase();
10
+ isIE = navigator.appName === 'Microsoft Internet Explorer';
11
+ IEVersion = isIE ? parseFloat( UA.match( /msie ([0-9]{1,}[\.0-9]{0,})/ )[1] ) : 0;
12
+ nonGradientIE = ( isIE && IEVersion < 10 );
13
+ // we don't bother with an unprefixed version, as it has a different syntax
14
+ vendorPrefixes = ['-moz-', '-webkit-', '-o-', '-ms-' ];
15
+ testGradientType();
16
+
17
+ // Bail for IE <= 7
18
+ if ( nonGradientIE && IEVersion <= 7 ) {
19
+ $.fn.ctcgrad = $.noop;
20
+ $.support.ctcgrad = false;
21
+ return;
22
+ }
23
+
24
+ $.support.ctcgrad = true;
25
+
26
+ function testGradientType() {
27
+ var el, base;
28
+ if ( nonGradientIE ) {
29
+ gradientType = 'filter';
30
+ }
31
+ else {
32
+ el = $('<div id="ctcgrad-gradtest" />');
33
+ base = "linear-gradient(top,#fff,#000)";
34
+ $.each( vendorPrefixes, function( i, val ){
35
+ el.css( 'backgroundImage', val + base );
36
+ if ( el.css( 'backgroundImage').match('gradient') ) {
37
+ gradientType = i;
38
+ return false;
39
+ }
40
+ });
41
+ // check for legacy webkit gradient syntax
42
+ if ( gradientType === false ) {
43
+ el.css( 'background', '-webkit-gradient(linear,0% 0%,0% 100%,from(#fff),to(#000))' );
44
+ if ( el.css( 'backgroundImage').match('gradient') )
45
+ gradientType = 'webkit';
46
+ }
47
+ el.remove();
48
+ }
49
+
50
+ }
51
+
52
+ /**
53
+ * Only for CSS3 gradients. oldIE will use a separate function.
54
+ *
55
+ * Accepts as many color stops as necessary from 2nd arg on, or 2nd
56
+ * arg can be an array of color stops
57
+ *
58
+ * @param {string} origin Gradient origin - top bottom left right (n)deg
59
+ * @return {string} Appropriate CSS3 gradient string for use in
60
+ */
61
+ function createGradient( origin, stops ) {
62
+ origin = ( origin.match(/(\d+deg|top|left|bottom|right)( (top|left|bottom|right))?/) ? origin : 'top');
63
+ stops = $.isArray( stops ) ? stops : Array.prototype.slice.call(arguments, 1);
64
+ if ( gradientType === 'webkit' )
65
+ return legacyWebkitGradient( origin, stops );
66
+ else
67
+ return vendorPrefixes[gradientType] + 'linear-gradient(' + origin + ', ' + stops.join(', ') + ')';
68
+ }
69
+
70
+ /**
71
+ * Stupid gradients for a stupid browser.
72
+ */
73
+ function stupidIEGradient( origin, stops ) {
74
+ var type, self, lastIndex, filter, startPosProp, endPosProp, dimensionProp, template, html, filterVal;
75
+
76
+ origin = ( origin === 'left' ) ? 'left' : 'top';
77
+ stops = $.isArray( stops ) ? stops : Array.prototype.slice.call(arguments, 1);
78
+ // 8 hex: AARRGGBB
79
+ // GradientType: 0 vertical, 1 horizontal
80
+ type = ( origin === 'top' ) ? 0 : 1;
81
+ self = $( this );
82
+ lastIndex = stops.length - 1;
83
+ filter = 'filter';
84
+ startPosProp = ( type === 1 ) ? 'left' : 'top';
85
+ endPosProp = ( type === 1 ) ? 'right' : 'bottom';
86
+ dimensionProp = ( type === 1 ) ? 'height' : 'width';
87
+ // need a positioning context
88
+ if ( self.css('position') === 'static' )
89
+ self.css( {position: 'relative' } );
90
+
91
+ stops = fillColorStops( stops );
92
+ $.each(stops, function( i, startColor ) {
93
+ var endColor, endStop;
94
+
95
+ // we want two at a time. if we're on the last pair, bail.
96
+ if ( i === lastIndex )
97
+ return false;
98
+
99
+ endColor = stops[ i + 1 ];
100
+ //if our pairs are at the same color stop, moving along.
101
+ if ( startColor.stop === endColor.stop )
102
+ return;
103
+
104
+ endStop = 100 - parseFloat( endColor.stop ) + '%';
105
+ startColor.octoHex = new Color( startColor.color ).toIEOctoHex();
106
+ endColor.octoHex = new Color( endColor.color ).toIEOctoHex();
107
+
108
+ filterVal = "progid:DXImageTransform.Microsoft.Gradient(GradientType=" + type + ", StartColorStr='" + startColor.octoHex + "', EndColorStr='" + endColor.octoHex + "')";
109
+ });
110
  return filterVal;
111
+ }
112
+
113
+ function legacyWebkitGradient( origin, colorList ) {
114
+ var stops = [];
115
+ origin = ( origin === 'top' ) ? '0% 0%,0% 100%,' : '0% 100%,100% 100%,';
116
+ colorList = fillColorStops( colorList );
117
+ $.each( colorList, function( i, val ){
118
+ stops.push( 'color-stop(' + ( parseFloat( val.stop ) / 100 ) + ', ' + val.color + ')' );
119
+ });
120
+ return '-webkit-gradient(linear,' + origin + stops.join(',') + ')';
121
+ }
122
+
123
+ function fillColorStops( colorList ) {
124
+ var colors = [],
125
+ percs = [],
126
+ newColorList = [],
127
+ lastIndex = colorList.length - 1;
128
+
129
+ $.each( colorList, function( index, val ) {
130
+ var color = val,
131
+ perc = false,
132
+ match = val.match(/1?[0-9]{1,2}%$/);
133
+
134
+ if ( match ) {
135
+ color = val.replace(/\s?1?[0-9]{1,2}%$/, '');
136
+ perc = match.shift();
137
+ }
138
+ colors.push( color );
139
+ percs.push( perc );
140
+ });
141
+
142
+ // back fill first and last
143
+ if ( percs[0] === false )
144
+ percs[0] = '0%';
145
+
146
+ if ( percs[lastIndex] === false )
147
+ percs[lastIndex] = '100%';
148
+
149
+ percs = backFillColorStops( percs );
150
+
151
+ $.each( percs, function( i ){
152
+ newColorList[i] = { color: colors[i], stop: percs[i] };
153
+ });
154
+ return newColorList;
155
+ }
156
+
157
+ function backFillColorStops( stops ) {
158
+ var first = 0,
159
+ last = stops.length - 1,
160
+ i = 0,
161
+ foundFirst = false,
162
+ incr,
163
+ steps,
164
+ step,
165
+ firstVal;
166
+
167
+ if ( stops.length <= 2 || $.inArray( false, stops ) < 0 ) {
168
+ return stops;
169
+ }
170
+ while ( i < stops.length - 1 ) {
171
+ if ( ! foundFirst && stops[i] === false ) {
172
+ first = i - 1;
173
+ foundFirst = true;
174
+ } else if ( foundFirst && stops[i] !== false ) {
175
+ last = i;
176
+ i = stops.length;
177
+ }
178
+ i++;
179
+ }
180
+ steps = last - first;
181
+ firstVal = parseInt( stops[first].replace('%'), 10 );
182
+ incr = ( parseFloat( stops[last].replace('%') ) - firstVal ) / steps;
183
+ i = first + 1;
184
+ step = 1;
185
+ while ( i < last ) {
186
+ stops[i] = ( firstVal + ( step * incr ) ) + '%';
187
+ step++;
188
+ i++;
189
+ }
190
+ return backFillColorStops( stops );
191
+ }
192
+
193
+ $.fn.ctcgrad = function( origin ) {
194
+ var args = arguments;
195
+ // this'll be oldishIE
196
+ if ( nonGradientIE )
197
  $(this).css('filter',
198
+ stupidIEGradient.apply( this, args ));
199
+ else // new hotness
200
+ $( this ).css( 'backgroundImage', createGradient.apply( this, args ) );
201
+ };
202
 
203
  }( jQuery ));
js/jquery-ui-selectmenu.js CHANGED
@@ -4,15 +4,15 @@
4
  * Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */
5
 
6
  (function( factory ) {
7
- if ( typeof define === "function" && define.amd ) {
8
 
9
- // AMD. Register as an anonymous module.
10
- define([ "jquery" ], factory );
11
- } else {
12
 
13
- // Browser globals
14
- factory( jQuery );
15
- }
16
  }(function( $ ) {
17
 
18
 
@@ -29,219 +29,219 @@
29
 
30
 
31
  var widget_uuid = 0,
32
- widget_slice = Array.prototype.slice;
33
 
34
  $.cleanData = (function( orig ) {
35
- return function( elems ) {
36
- var events, elem, i;
37
- for ( i = 0; (elem = elems[i]) != null; i++ ) {
38
- try {
39
-
40
- // Only trigger remove when necessary to save time
41
- events = $._data( elem, "events" );
42
- if ( events && events.remove ) {
43
- $( elem ).triggerHandler( "remove" );
44
- }
45
-
46
- // http://bugs.jquery.com/ticket/8235
47
- } catch ( e ) {}
48
- }
49
- orig( elems );
50
- };
51
  })( $.cleanData );
52
 
53
  $.widget = function( name, base, prototype ) {
54
- var fullName, existingConstructor, constructor, basePrototype,
55
- // proxiedPrototype allows the provided prototype to remain unmodified
56
- // so that it can be used as a mixin for multiple widgets (#8876)
57
- proxiedPrototype = {},
58
- namespace = name.split( "." )[ 0 ];
59
-
60
- name = name.split( "." )[ 1 ];
61
- fullName = namespace + "-" + name;
62
-
63
- if ( !prototype ) {
64
- prototype = base;
65
- base = $.Widget;
66
- }
67
-
68
- // create selector for plugin
69
- $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
70
- return !!$.data( elem, fullName );
71
- };
72
-
73
- $[ namespace ] = $[ namespace ] || {};
74
- existingConstructor = $[ namespace ][ name ];
75
- constructor = $[ namespace ][ name ] = function( options, element ) {
76
- // allow instantiation without "new" keyword
77
- if ( !this._createWidget ) {
78
- return new constructor( options, element );
79
- }
80
-
81
- // allow instantiation without initializing for simple inheritance
82
- // must use "new" keyword (the code above always passes args)
83
- if ( arguments.length ) {
84
- this._createWidget( options, element );
85
- }
86
- };
87
- // extend with the existing constructor to carry over any static properties
88
- $.extend( constructor, existingConstructor, {
89
- version: prototype.version,
90
- // copy the object used to create the prototype in case we need to
91
- // redefine the widget later
92
- _proto: $.extend( {}, prototype ),
93
- // track widgets that inherit from this widget in case this widget is
94
- // redefined after a widget inherits from it
95
- _childConstructors: []
96
- });
97
-
98
- basePrototype = new base();
99
- // we need to make the options hash a property directly on the new instance
100
- // otherwise we'll modify the options hash on the prototype that we're
101
- // inheriting from
102
- basePrototype.options = $.widget.extend( {}, basePrototype.options );
103
- $.each( prototype, function( prop, value ) {
104
- if ( !$.isFunction( value ) ) {
105
- proxiedPrototype[ prop ] = value;
106
- return;
107
- }
108
- proxiedPrototype[ prop ] = (function() {
109
- var _super = function() {
110
- return base.prototype[ prop ].apply( this, arguments );
111
- },
112
- _superApply = function( args ) {
113
- return base.prototype[ prop ].apply( this, args );
114
- };
115
- return function() {
116
- var __super = this._super,
117
- __superApply = this._superApply,
118
- returnValue;
119
-
120
- this._super = _super;
121
- this._superApply = _superApply;
122
-
123
- returnValue = value.apply( this, arguments );
124
-
125
- this._super = __super;
126
- this._superApply = __superApply;
127
-
128
- return returnValue;
129
- };
130
- })();
131
- });
132
- constructor.prototype = $.widget.extend( basePrototype, {
133
- // TODO: remove support for widgetEventPrefix
134
- // always use the name + a colon as the prefix, e.g., draggable:start
135
- // don't prefix for widgets that aren't DOM-based
136
- widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name
137
- }, proxiedPrototype, {
138
- constructor: constructor,
139
- namespace: namespace,
140
- widgetName: name,
141
- widgetFullName: fullName
142
- });
143
-
144
- // If this widget is being redefined then we need to find all widgets that
145
- // are inheriting from it and redefine all of them so that they inherit from
146
- // the new version of this widget. We're essentially trying to replace one
147
- // level in the prototype chain.
148
- if ( existingConstructor ) {
149
- $.each( existingConstructor._childConstructors, function( i, child ) {
150
- var childPrototype = child.prototype;
151
-
152
- // redefine the child widget using the same prototype that was
153
- // originally used, but inherit from the new version of the base
154
- $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
155
- });
156
- // remove the list of existing child constructors from the old constructor
157
- // so the old child constructors can be garbage collected
158
- delete existingConstructor._childConstructors;
159
- } else {
160
- base._childConstructors.push( constructor );
161
- }
162
-
163
- $.widget.bridge( name, constructor );
164
-
165
- return constructor;
166
  };
167
 
168
  $.widget.extend = function( target ) {
169
- var input = widget_slice.call( arguments, 1 ),
170
- inputIndex = 0,
171
- inputLength = input.length,
172
- key,
173
- value;
174
- for ( ; inputIndex < inputLength; inputIndex++ ) {
175
- for ( key in input[ inputIndex ] ) {
176
- value = input[ inputIndex ][ key ];
177
- if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
178
- // Clone objects
179
- if ( $.isPlainObject( value ) ) {
180
- target[ key ] = $.isPlainObject( target[ key ] ) ?
181
- $.widget.extend( {}, target[ key ], value ) :
182
- // Don't extend strings, arrays, etc. with objects
183
- $.widget.extend( {}, value );
184
- // Copy everything else by reference
185
- } else {
186
- target[ key ] = value;
187
- }
188
- }
189
- }
190
- }
191
- return target;
192
  };
193
 
194
  $.widget.bridge = function( name, object ) {
195
- var fullName = object.prototype.widgetFullName || name;
196
- $.fn[ name ] = function( options ) {
197
- var isMethodCall = typeof options === "string",
198
- args = widget_slice.call( arguments, 1 ),
199
- returnValue = this;
200
-
201
- // allow multiple hashes to be passed on init
202
- options = !isMethodCall && args.length ?
203
- $.widget.extend.apply( null, [ options ].concat(args) ) :
204
- options;
205
-
206
- if ( isMethodCall ) {
207
- this.each(function() {
208
- var methodValue,
209
- instance = $.data( this, fullName );
210
- if ( options === "instance" ) {
211
- returnValue = instance;
212
- return false;
213
- }
214
- if ( !instance ) {
215
- return $.error( "cannot call methods on " + name + " prior to initialization; " +
216
- "attempted to call method '" + options + "'" );
217
- }
218
- if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
219
- return $.error( "no such method '" + options + "' for " + name + " widget instance" );
220
- }
221
- methodValue = instance[ options ].apply( instance, args );
222
- if ( methodValue !== instance && methodValue !== undefined ) {
223
- returnValue = methodValue && methodValue.jquery ?
224
- returnValue.pushStack( methodValue.get() ) :
225
- methodValue;
226
- return false;
227
- }
228
- });
229
- } else {
230
- this.each(function() {
231
- var instance = $.data( this, fullName );
232
- if ( instance ) {
233
- instance.option( options || {} );
234
- if ( instance._init ) {
235
- instance._init();
236
- }
237
- } else {
238
- $.data( this, fullName, new object( options, this ) );
239
- }
240
- });
241
- }
242
-
243
- return returnValue;
244
- };
245
  };
246
 
247
  $.Widget = function( /* options, element */ ) {};
@@ -250,316 +250,316 @@ $.Widget = function( /* options, element */ ) {};
250
  $.Widget._childConstructors = [];
251
 
252
  $.Widget.prototype = {
253
- widgetName: "widget",
254
- widgetEventPrefix: "",
255
- defaultElement: "<div>",
256
- options: {
257
- disabled: false,
258
-
259
- // callbacks
260
- create: null
261
- },
262
- _createWidget: function( options, element ) {
263
- element = $( element || this.defaultElement || this )[ 0 ];
264
- this.element = $( element );
265
- this.uuid = widget_uuid++;
266
- this.eventNamespace = "." + this.widgetName + this.uuid;
267
-
268
- this.bindings = $();
269
- this.hoverable = $();
270
- this.focusable = $();
271
-
272
- if ( element !== this ) {
273
- $.data( element, this.widgetFullName, this );
274
- this._on( true, this.element, {
275
- remove: function( event ) {
276
- if ( event.target === element ) {
277
- this.destroy();
278
- }
279
- }
280
- });
281
- this.document = $( element.style ?
282
- // element within the document
283
- element.ownerDocument :
284
- // element is window or document
285
- element.document || element );
286
- this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
287
- }
288
-
289
- this.options = $.widget.extend( {},
290
- this.options,
291
- this._getCreateOptions(),
292
- options );
293
-
294
- this._create();
295
- this._trigger( "create", null, this._getCreateEventData() );
296
- this._init();
297
- },
298
- _getCreateOptions: $.noop,
299
- _getCreateEventData: $.noop,
300
- _create: $.noop,
301
- _init: $.noop,
302
-
303
- destroy: function() {
304
- this._destroy();
305
- // we can probably remove the unbind calls in 2.0
306
- // all event bindings should go through this._on()
307
- this.element
308
- .unbind( this.eventNamespace )
309
- .removeData( this.widgetFullName )
310
- // support: jquery <1.6.4
311
- // http://bugs.jquery.com/ticket/9413
312
- .removeData( $.camelCase( this.widgetFullName ) );
313
- this.widget()
314
- .unbind( this.eventNamespace )
315
- .removeAttr( "aria-disabled" )
316
- .removeClass(
317
- this.widgetFullName + "-disabled " +
318
- "ui-state-disabled" );
319
-
320
- // clean up events and states
321
- this.bindings.unbind( this.eventNamespace );
322
- this.hoverable.removeClass( "ui-state-hover" );
323
- this.focusable.removeClass( "ui-state-focus" );
324
- },
325
- _destroy: $.noop,
326
-
327
- widget: function() {
328
- return this.element;
329
- },
330
-
331
- option: function( key, value ) {
332
- var options = key,
333
- parts,
334
- curOption,
335
- i;
336
-
337
- if ( arguments.length === 0 ) {
338
- // don't return a reference to the internal hash
339
- return $.widget.extend( {}, this.options );
340
- }
341
-
342
- if ( typeof key === "string" ) {
343
- // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
344
- options = {};
345
- parts = key.split( "." );
346
- key = parts.shift();
347
- if ( parts.length ) {
348
- curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
349
- for ( i = 0; i < parts.length - 1; i++ ) {
350
- curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
351
- curOption = curOption[ parts[ i ] ];
352
- }
353
- key = parts.pop();
354
- if ( arguments.length === 1 ) {
355
- return curOption[ key ] === undefined ? null : curOption[ key ];
356
- }
357
- curOption[ key ] = value;
358
- } else {
359
- if ( arguments.length === 1 ) {
360
- return this.options[ key ] === undefined ? null : this.options[ key ];
361
- }
362
- options[ key ] = value;
363
- }
364
- }
365
-
366
- this._setOptions( options );
367
-
368
- return this;
369
- },
370
- _setOptions: function( options ) {
371
- var key;
372
-
373
- for ( key in options ) {
374
- this._setOption( key, options[ key ] );
375
- }
376
-
377
- return this;
378
- },
379
- _setOption: function( key, value ) {
380
- this.options[ key ] = value;
381
-
382
- if ( key === "disabled" ) {
383
- this.widget()
384
- .toggleClass( this.widgetFullName + "-disabled", !!value );
385
-
386
- // If the widget is becoming disabled, then nothing is interactive
387
- if ( value ) {
388
- this.hoverable.removeClass( "ui-state-hover" );
389
- this.focusable.removeClass( "ui-state-focus" );
390
- }
391
- }
392
-
393
- return this;
394
- },
395
-
396
- enable: function() {
397
- return this._setOptions({ disabled: false });
398
- },
399
- disable: function() {
400
- return this._setOptions({ disabled: true });
401
- },
402
-
403
- _on: function( suppressDisabledCheck, element, handlers ) {
404
- var delegateElement,
405
- instance = this;
406
-
407
- // no suppressDisabledCheck flag, shuffle arguments
408
- if ( typeof suppressDisabledCheck !== "boolean" ) {
409
- handlers = element;
410
- element = suppressDisabledCheck;
411
- suppressDisabledCheck = false;
412
- }
413
-
414
- // no element argument, shuffle and use this.element
415
- if ( !handlers ) {
416
- handlers = element;
417
- element = this.element;
418
- delegateElement = this.widget();
419
- } else {
420
- element = delegateElement = $( element );
421
- this.bindings = this.bindings.add( element );
422
- }
423
-
424
- $.each( handlers, function( event, handler ) {
425
- function handlerProxy() {
426
- // allow widgets to customize the disabled handling
427
- // - disabled as an array instead of boolean
428
- // - disabled class as method for disabling individual parts
429
- if ( !suppressDisabledCheck &&
430
- ( instance.options.disabled === true ||
431
- $( this ).hasClass( "ui-state-disabled" ) ) ) {
432
- return;
433
- }
434
- return ( typeof handler === "string" ? instance[ handler ] : handler )
435
- .apply( instance, arguments );
436
- }
437
-
438
- // copy the guid so direct unbinding works
439
- if ( typeof handler !== "string" ) {
440
- handlerProxy.guid = handler.guid =
441
- handler.guid || handlerProxy.guid || $.guid++;
442
- }
443
-
444
- var match = event.match( /^([\w:-]*)\s*(.*)$/ ),
445
- eventName = match[1] + instance.eventNamespace,
446
- selector = match[2];
447
- if ( selector ) {
448
- delegateElement.delegate( selector, eventName, handlerProxy );
449
- } else {
450
- element.bind( eventName, handlerProxy );
451
- }
452
- });
453
- },
454
-
455
- _off: function( element, eventName ) {
456
- eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) +
457
- this.eventNamespace;
458
- element.unbind( eventName ).undelegate( eventName );
459
-
460
- // Clear the stack to avoid memory leaks (#10056)
461
- this.bindings = $( this.bindings.not( element ).get() );
462
- this.focusable = $( this.focusable.not( element ).get() );
463
- this.hoverable = $( this.hoverable.not( element ).get() );
464
- },
465
-
466
- _delay: function( handler, delay ) {
467
- function handlerProxy() {
468
- return ( typeof handler === "string" ? instance[ handler ] : handler )
469
- .apply( instance, arguments );
470
- }
471
- var instance = this;
472
- return setTimeout( handlerProxy, delay || 0 );
473
- },
474
-
475
- _hoverable: function( element ) {
476
- this.hoverable = this.hoverable.add( element );
477
- this._on( element, {
478
- mouseenter: function( event ) {
479
- $( event.currentTarget ).addClass( "ui-state-hover" );
480
- },
481
- mouseleave: function( event ) {
482
- $( event.currentTarget ).removeClass( "ui-state-hover" );
483
- }
484
- });
485
- },
486
-
487
- _focusable: function( element ) {
488
- this.focusable = this.focusable.add( element );
489
- this._on( element, {
490
- focusin: function( event ) {
491
- $( event.currentTarget ).addClass( "ui-state-focus" );
492
- },
493
- focusout: function( event ) {
494
- $( event.currentTarget ).removeClass( "ui-state-focus" );
495
- }
496
- });
497
- },
498
-
499
- _trigger: function( type, event, data ) {
500
- var prop, orig,
501
- callback = this.options[ type ];
502
-
503
- data = data || {};
504
- event = $.Event( event );
505
- event.type = ( type === this.widgetEventPrefix ?
506
- type :
507
- this.widgetEventPrefix + type ).toLowerCase();
508
- // the original event may come from any element
509
- // so we need to reset the target on the new event
510
- event.target = this.element[ 0 ];
511
-
512
- // copy original event properties over to the new event
513
- orig = event.originalEvent;
514
- if ( orig ) {
515
- for ( prop in orig ) {
516
- if ( !( prop in event ) ) {
517
- event[ prop ] = orig[ prop ];
518
- }
519
- }
520
- }
521
-
522
- this.element.trigger( event, data );
523
- return !( $.isFunction( callback ) &&
524
- callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
525
- event.isDefaultPrevented() );
526
- }
527
  };
528
 
529
  $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
530
- $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
531
- if ( typeof options === "string" ) {
532
- options = { effect: options };
533
- }
534
- var hasOptions,
535
- effectName = !options ?
536
- method :
537
- options === true || typeof options === "number" ?
538
- defaultEffect :
539
- options.effect || defaultEffect;
540
- options = options || {};
541
- if ( typeof options === "number" ) {
542
- options = { duration: options };
543
- }
544
- hasOptions = !$.isEmptyObject( options );
545
- options.complete = callback;
546
- if ( options.delay ) {
547
- element.delay( options.delay );
548
- }
549
- if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
550
- element[ method ]( options );
551
- } else if ( effectName !== method && element[ effectName ] ) {
552
- element[ effectName ]( options.duration, options.easing, callback );
553
- } else {
554
- element.queue(function( next ) {
555
- $( this )[ method ]();
556
- if ( callback ) {
557
- callback.call( element[ 0 ] );
558
- }
559
- next();
560
- });
561
- }
562
- };
563
  });
564
 
565
  var widget = $.widget;
@@ -580,621 +580,621 @@ var widget = $.widget;
580
 
581
 
582
  var menu = $.widget( "ui.menu", {
583
- version: "1.11.2",
584
- defaultElement: "<ul>",
585
- delay: 300,
586
- options: {
587
- icons: {
588
- submenu: "ui-icon-carat-1-e"
589
- },
590
- items: "> *",
591
- menus: "ul",
592
- position: {
593
- my: "left-1 top",
594
- at: "right top"
595
- },
596
- role: "menu",
597
-
598
- // callbacks
599
- blur: null,
600
- focus: null,
601
- select: null
602
- },
603
-
604
- _create: function() {
605
- this.activeMenu = this.element;
606
-
607
- // Flag used to prevent firing of the click handler
608
- // as the event bubbles up through nested menus
609
- this.mouseHandled = false;
610
- this.element
611
- .uniqueId()
612
- .addClass( "ui-menu ui-widget ui-widget-content" )
613
- .toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length )
614
- .attr({
615
- role: this.options.role,
616
- tabIndex: 0
617
- });
618
-
619
- if ( this.options.disabled ) {
620
- this.element
621
- .addClass( "ui-state-disabled" )
622
- .attr( "aria-disabled", "true" );
623
- }
624
-
625
- this._on({
626
- // Prevent focus from sticking to links inside menu after clicking
627
- // them (focus should always stay on UL during navigation).
628
- "mousedown .ui-menu-item": function( event ) {
629
- event.preventDefault();
630
- },
631
- "click .ui-menu-item": function( event ) {
632
- var target = $( event.target );
633
- if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
634
- this.select( event );
635
-
636
- // Only set the mouseHandled flag if the event will bubble, see #9469.
637
- if ( !event.isPropagationStopped() ) {
638
- this.mouseHandled = true;
639
- }
640
-
641
- // Open submenu on click
642
- if ( target.has( ".ui-menu" ).length ) {
643
- this.expand( event );
644
- } else if ( !this.element.is( ":focus" ) && $( this.document[ 0 ].activeElement ).closest( ".ui-menu" ).length ) {
645
-
646
- // Redirect focus to the menu
647
- this.element.trigger( "focus", [ true ] );
648
-
649
- // If the active item is on the top level, let it stay active.
650
- // Otherwise, blur the active item since it is no longer visible.
651
- if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
652
- clearTimeout( this.timer );
653
- }
654
- }
655
- }
656
- },
657
- "mouseenter .ui-menu-item": function( event ) {
658
- // Ignore mouse events while typeahead is active, see #10458.
659
- // Prevents focusing the wrong item when typeahead causes a scroll while the mouse
660
- // is over an item in the menu
661
- if ( this.previousFilter ) {
662
- return;
663
- }
664
- var target = $( event.currentTarget );
665
- // Remove ui-state-active class from siblings of the newly focused menu item
666
- // to avoid a jump caused by adjacent elements both having a class with a border
667
- target.siblings( ".ui-state-active" ).removeClass( "ui-state-active" );
668
- this.focus( event, target );
669
- },
670
- mouseleave: "collapseAll",
671
- "mouseleave .ui-menu": "collapseAll",
672
- focus: function( event, keepActiveItem ) {
673
- // If there's already an active item, keep it active
674
- // If not, activate the first item
675
- var item = this.active || this.element.find( this.options.items ).eq( 0 );
676
-
677
- if ( !keepActiveItem ) {
678
- this.focus( event, item );
679
- }
680
- },
681
- blur: function( event ) {
682
- this._delay(function() {
683
- if ( !$.contains( this.element[0], this.document[0].activeElement ) ) {
684
- this.collapseAll( event );
685
- }
686
- });
687
- },
688
- keydown: "_keydown"
689
- });
690
-
691
- this.refresh();
692
-
693
- // Clicks outside of a menu collapse any open menus
694
- this._on( this.document, {
695
- click: function( event ) {
696
- if ( this._closeOnDocumentClick( event ) ) {
697
- this.collapseAll( event );
698
- }
699
-
700
- // Reset the mouseHandled flag
701
- this.mouseHandled = false;
702
- }
703
- });
704
- },
705
-
706
- _destroy: function() {
707
- // Destroy (sub)menus
708
- this.element
709
- .removeAttr( "aria-activedescendant" )
710
- .find( ".ui-menu" ).addBack()
711
- .removeClass( "ui-menu ui-widget ui-widget-content ui-menu-icons ui-front" )
712
- .removeAttr( "role" )
713
- .removeAttr( "tabIndex" )
714
- .removeAttr( "aria-labelledby" )
715
- .removeAttr( "aria-expanded" )
716
- .removeAttr( "aria-hidden" )
717
- .removeAttr( "aria-disabled" )
718
- .removeUniqueId()
719
- .show();
720
-
721
- // Destroy menu items
722
- this.element.find( ".ui-menu-item" )
723
- .removeClass( "ui-menu-item" )
724
- .removeAttr( "role" )
725
- .removeAttr( "aria-disabled" )
726
- .removeUniqueId()
727
- .removeClass( "ui-state-hover" )
728
- .removeAttr( "tabIndex" )
729
- .removeAttr( "role" )
730
- .removeAttr( "aria-haspopup" )
731
- .children().each( function() {
732
- var elem = $( this );
733
- if ( elem.data( "ui-menu-submenu-carat" ) ) {
734
- elem.remove();
735
- }
736
- });
737
-
738
- // Destroy menu dividers
739
- this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" );
740
- },
741
-
742
- _keydown: function( event ) {
743
- var match, prev, character, skip,
744
- preventDefault = true;
745
-
746
- switch ( event.keyCode ) {
747
- case $.ui.keyCode.PAGE_UP:
748
- this.previousPage( event );
749
- break;
750
- case $.ui.keyCode.PAGE_DOWN:
751
- this.nextPage( event );
752
- break;
753
- case $.ui.keyCode.HOME:
754
- this._move( "first", "first", event );
755
- break;
756
- case $.ui.keyCode.END:
757
- this._move( "last", "last", event );
758
- break;
759
- case $.ui.keyCode.UP:
760
- this.previous( event );
761
- break;
762
- case $.ui.keyCode.DOWN:
763
- this.next( event );
764
- break;
765
- case $.ui.keyCode.LEFT:
766
- this.collapse( event );
767
- break;
768
- case $.ui.keyCode.RIGHT:
769
- if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
770
- this.expand( event );
771
- }
772
- break;
773
- case $.ui.keyCode.ENTER:
774
- case $.ui.keyCode.SPACE:
775
- this._activate( event );
776
- break;
777
- case $.ui.keyCode.ESCAPE:
778
- this.collapse( event );
779
- break;
780
- default:
781
- preventDefault = false;
782
- prev = this.previousFilter || "";
783
- character = String.fromCharCode( event.keyCode );
784
- skip = false;
785
-
786
- clearTimeout( this.filterTimer );
787
-
788
- if ( character === prev ) {
789
- skip = true;
790
- } else {
791
- character = prev + character;
792
- }
793
-
794
- match = this._filterMenuItems( character );
795
- match = skip && match.index( this.active.next() ) !== -1 ?
796
- this.active.nextAll( ".ui-menu-item" ) :
797
- match;
798
-
799
- // If no matches on the current filter, reset to the last character pressed
800
- // to move down the menu to the first item that starts with that character
801
- if ( !match.length ) {
802
- character = String.fromCharCode( event.keyCode );
803
- match = this._filterMenuItems( character );
804
- }
805
-
806
- if ( match.length ) {
807
- this.focus( event, match );
808
- this.previousFilter = character;
809
- this.filterTimer = this._delay(function() {
810
- delete this.previousFilter;
811
- }, 1000 );
812
- } else {
813
- delete this.previousFilter;
814
- }
815
- }
816
-
817
- if ( preventDefault ) {
818
- event.preventDefault();
819
- }
820
- },
821
-
822
- _activate: function( event ) {
823
- if ( !this.active.is( ".ui-state-disabled" ) ) {
824
- if ( this.active.is( "[aria-haspopup='true']" ) ) {
825
- this.expand( event );
826
- } else {
827
- this.select( event );
828
- }
829
- }
830
- },
831
-
832
- refresh: function() {
833
- var menus, items,
834
- that = this,
835
- icon = this.options.icons.submenu,
836
- submenus = this.element.find( this.options.menus );
837
-
838
- this.element.toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length );
839
-
840
- // Initialize nested menus
841
- submenus.filter( ":not(.ui-menu)" )
842
- .addClass( "ui-menu ui-widget ui-widget-content ui-front" )
843
- .hide()
844
- .attr({
845
- role: this.options.role,
846
- "aria-hidden": "true",
847
- "aria-expanded": "false"
848
- })
849
- .each(function() {
850
- var menu = $( this ),
851
- item = menu.parent(),
852
- submenuCarat = $( "<span>" )
853
- .addClass( "ui-menu-icon ui-icon " + icon )
854
- .data( "ui-menu-submenu-carat", true );
855
-
856
- item
857
- .attr( "aria-haspopup", "true" )
858
- .prepend( submenuCarat );
859
- menu.attr( "aria-labelledby", item.attr( "id" ) );
860
- });
861
-
862
- menus = submenus.add( this.element );
863
- items = menus.find( this.options.items );
864
-
865
- // Initialize menu-items containing spaces and/or dashes only as dividers
866
- items.not( ".ui-menu-item" ).each(function() {
867
- var item = $( this );
868
- if ( that._isDivider( item ) ) {
869
- item.addClass( "ui-widget-content ui-menu-divider" );
870
- }
871
- });
872
-
873
- // Don't refresh list items that are already adapted
874
- items.not( ".ui-menu-item, .ui-menu-divider" )
875
- .addClass( "ui-menu-item" )
876
- .uniqueId()
877
- .attr({
878
- tabIndex: -1,
879
- role: this._itemRole()
880
- });
881
-
882
- // Add aria-disabled attribute to any disabled menu item
883
- items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
884
-
885
- // If the active item has been removed, blur the menu
886
- if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
887
- this.blur();
888
- }
889
- },
890
-
891
- _itemRole: function() {
892
- return {
893
- menu: "menuitem",
894
- listbox: "option"
895
- }[ this.options.role ];
896
- },
897
-
898
- _setOption: function( key, value ) {
899
- if ( key === "icons" ) {
900
- this.element.find( ".ui-menu-icon" )
901
- .removeClass( this.options.icons.submenu )
902
- .addClass( value.submenu );
903
- }
904
- if ( key === "disabled" ) {
905
- this.element
906
- .toggleClass( "ui-state-disabled", !!value )
907
- .attr( "aria-disabled", value );
908
- }
909
- this._super( key, value );
910
- },
911
-
912
- focus: function( event, item ) {
913
- var nested, focused;
914
- this.blur( event, event && event.type === "focus" );
915
-
916
- this._scrollIntoView( item );
917
-
918
- this.active = item.first();
919
- focused = this.active.addClass( "ui-state-focus" ).removeClass( "ui-state-active" );
920
- // Only update aria-activedescendant if there's a role
921
- // otherwise we assume focus is managed elsewhere
922
- if ( this.options.role ) {
923
- this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
924
- }
925
-
926
- // Highlight active parent menu item, if any
927
- this.active
928
- .parent()
929
- .closest( ".ui-menu-item" )
930
- .addClass( "ui-state-active" );
931
-
932
- if ( event && event.type === "keydown" ) {
933
- this._close();
934
- } else {
935
- this.timer = this._delay(function() {
936
- this._close();
937
- }, this.delay );
938
- }
939
-
940
- nested = item.children( ".ui-menu" );
941
- if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {
942
- this._startOpening(nested);
943
- }
944
- this.activeMenu = item.parent();
945
-
946
- this._trigger( "focus", event, { item: item } );
947
- },
948
-
949
- _scrollIntoView: function( item ) {
950
- var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
951
- if ( this._hasScroll() ) {
952
- borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0;
953
- paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0;
954
- offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
955
- scroll = this.activeMenu.scrollTop();
956
- elementHeight = this.activeMenu.height();
957
- itemHeight = item.outerHeight();
958
-
959
- if ( offset < 0 ) {
960
- this.activeMenu.scrollTop( scroll + offset );
961
- } else if ( offset + itemHeight > elementHeight ) {
962
- this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
963
- }
964
- }
965
- },
966
-
967
- blur: function( event, fromFocus ) {
968
- if ( !fromFocus ) {
969
- clearTimeout( this.timer );
970
- }
971
-
972
- if ( !this.active ) {
973
- return;
974
- }
975
-
976
- this.active.removeClass( "ui-state-focus" );
977
- this.active = null;
978
-
979
- this._trigger( "blur", event, { item: this.active } );
980
- },
981
-
982
- _startOpening: function( submenu ) {
983
- clearTimeout( this.timer );
984
-
985
- // Don't open if already open fixes a Firefox bug that caused a .5 pixel
986
- // shift in the submenu position when mousing over the carat icon
987
- if ( submenu.attr( "aria-hidden" ) !== "true" ) {
988
- return;
989
- }
990
-
991
- this.timer = this._delay(function() {
992
- this._close();
993
- this._open( submenu );
994
- }, this.delay );
995
- },
996
-
997
- _open: function( submenu ) {
998
- var position = $.extend({
999
- of: this.active
1000
- }, this.options.position );
1001
-
1002
- clearTimeout( this.timer );
1003
- this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
1004
- .hide()
1005
- .attr( "aria-hidden", "true" );
1006
-
1007
- submenu
1008
- .show()
1009
- .removeAttr( "aria-hidden" )
1010
- .attr( "aria-expanded", "true" )
1011
- .position( position );
1012
- },
1013
-
1014
- collapseAll: function( event, all ) {
1015
- clearTimeout( this.timer );
1016
- this.timer = this._delay(function() {
1017
- // If we were passed an event, look for the submenu that contains the event
1018
- var currentMenu = all ? this.element :
1019
- $( event && event.target ).closest( this.element.find( ".ui-menu" ) );
1020
-
1021
- // If we found no valid submenu ancestor, use the main menu to close all sub menus anyway
1022
- if ( !currentMenu.length ) {
1023
- currentMenu = this.element;
1024
- }
1025
-
1026
- this._close( currentMenu );
1027
-
1028
- this.blur( event );
1029
- this.activeMenu = currentMenu;
1030
- }, this.delay );
1031
- },
1032
-
1033
- // With no arguments, closes the currently active menu - if nothing is active
1034
- // it closes all menus. If passed an argument, it will search for menus BELOW
1035
- _close: function( startMenu ) {
1036
- if ( !startMenu ) {
1037
- startMenu = this.active ? this.active.parent() : this.element;
1038
- }
1039
-
1040
- startMenu
1041
- .find( ".ui-menu" )
1042
- .hide()
1043
- .attr( "aria-hidden", "true" )
1044
- .attr( "aria-expanded", "false" )
1045
- .end()
1046
- .find( ".ui-state-active" ).not( ".ui-state-focus" )
1047
- .removeClass( "ui-state-active" );
1048
- },
1049
-
1050
- _closeOnDocumentClick: function( event ) {
1051
- return !$( event.target ).closest( ".ui-menu" ).length;
1052
- },
1053
-
1054
- _isDivider: function( item ) {
1055
-
1056
- // Match hyphen, em dash, en dash
1057
- return !/[^\-\u2014\u2013\s]/.test( item.text() );
1058
- },
1059
-
1060
- collapse: function( event ) {
1061
- var newItem = this.active &&
1062
- this.active.parent().closest( ".ui-menu-item", this.element );
1063
- if ( newItem && newItem.length ) {
1064
- this._close();
1065
- this.focus( event, newItem );
1066
- }
1067
- },
1068
-
1069
- expand: function( event ) {
1070
- var newItem = this.active &&
1071
- this.active
1072
- .children( ".ui-menu " )
1073
- .find( this.options.items )
1074
- .first();
1075
-
1076
- if ( newItem && newItem.length ) {
1077
- this._open( newItem.parent() );
1078
-
1079
- // Delay so Firefox will not hide activedescendant change in expanding submenu from AT
1080
- this._delay(function() {
1081
- this.focus( event, newItem );
1082
- });
1083
- }
1084
- },
1085
-
1086
- next: function( event ) {
1087
- this._move( "next", "first", event );
1088
- },
1089
-
1090
- previous: function( event ) {
1091
- this._move( "prev", "last", event );
1092
- },
1093
-
1094
- isFirstItem: function() {
1095
- return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
1096
- },
1097
-
1098
- isLastItem: function() {
1099
- return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
1100
- },
1101
-
1102
- _move: function( direction, filter, event ) {
1103
- var next;
1104
- if ( this.active ) {
1105
- if ( direction === "first" || direction === "last" ) {
1106
- next = this.active
1107
- [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
1108
- .eq( -1 );
1109
- } else {
1110
- next = this.active
1111
- [ direction + "All" ]( ".ui-menu-item" )
1112
- .eq( 0 );
1113
- }
1114
- }
1115
- if ( !next || !next.length || !this.active ) {
1116
- next = this.activeMenu.find( this.options.items )[ filter ]();
1117
- }
1118
-
1119
- this.focus( event, next );
1120
- },
1121
-
1122
- nextPage: function( event ) {
1123
- var item, base, height;
1124
-
1125
- if ( !this.active ) {
1126
- this.next( event );
1127
- return;
1128
- }
1129
- if ( this.isLastItem() ) {
1130
- return;
1131
- }
1132
- if ( this._hasScroll() ) {
1133
- base = this.active.offset().top;
1134
- height = this.element.height();
1135
- this.active.nextAll( ".ui-menu-item" ).each(function() {
1136
- item = $( this );
1137
- return item.offset().top - base - height < 0;
1138
- });
1139
-
1140
- this.focus( event, item );
1141
- } else {
1142
- this.focus( event, this.activeMenu.find( this.options.items )
1143
- [ !this.active ? "first" : "last" ]() );
1144
- }
1145
- },
1146
-
1147
- previousPage: function( event ) {
1148
- var item, base, height;
1149
- if ( !this.active ) {
1150
- this.next( event );
1151
- return;
1152
- }
1153
- if ( this.isFirstItem() ) {
1154
- return;
1155
- }
1156
- if ( this._hasScroll() ) {
1157
- base = this.active.offset().top;
1158
- height = this.element.height();
1159
- this.active.prevAll( ".ui-menu-item" ).each(function() {
1160
- item = $( this );
1161
- return item.offset().top - base + height > 0;
1162
- });
1163
-
1164
- this.focus( event, item );
1165
- } else {
1166
- this.focus( event, this.activeMenu.find( this.options.items ).first() );
1167
- }
1168
- },
1169
-
1170
- _hasScroll: function() {
1171
- return this.element.outerHeight() < this.element.prop( "scrollHeight" );
1172
- },
1173
-
1174
- select: function( event ) {
1175
- // TODO: It should never be possible to not have an active item at this
1176
- // point, but the tests don't trigger mouseenter before click.
1177
- this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
1178
- var ui = { item: this.active };
1179
- if ( !this.active.has( ".ui-menu" ).length ) {
1180
- this.collapseAll( event, true );
1181
- }
1182
- this._trigger( "select", event, ui );
1183
- },
1184
-
1185
- _filterMenuItems: function(character) {
1186
- var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ),
1187
- regex = new RegExp( "^" + escapedCharacter, "i" );
1188
-
1189
- return this.activeMenu
1190
- .find( this.options.items )
1191
-
1192
- // Only match on items, not dividers or other content (#10571)
1193
- .filter( ".ui-menu-item" )
1194
- .filter(function() {
1195
- return regex.test( $.trim( $( this ).text() ) );
1196
- });
1197
- }
1198
  });
1199
 
1200
 
@@ -1211,590 +1211,590 @@ var menu = $.widget( "ui.menu", {
1211
 
1212
 
1213
  var selectmenu = $.widget( "ui.selectmenu", {
1214
- version: "1.11.2",
1215
- defaultElement: "<select>",
1216
- options: {
1217
- appendTo: null,
1218
- disabled: null,
1219
- icons: {
1220
- button: "ui-icon-triangle-1-s"
1221
- },
1222
- position: {
1223
- my: "left top",
1224
- at: "left bottom",
1225
- collision: "none"
1226
- },
1227
- width: null,
1228
-
1229
- // callbacks
1230
- change: null,
1231
- close: null,
1232
- focus: null,
1233
- open: null,
1234
- select: null
1235
- },
1236
-
1237
- _create: function() {
1238
- var selectmenuId = this.element.uniqueId().attr( "id" );
1239
- this.ids = {
1240
- element: selectmenuId,
1241
- button: selectmenuId + "-button",
1242
- menu: selectmenuId + "-menu"
1243
- };
1244
-
1245
- this._drawButton();
1246
- this._drawMenu();
1247
-
1248
- if ( this.options.disabled ) {
1249
- this.disable();
1250
- }
1251
- },
1252
-
1253
- _drawButton: function() {
1254
- var that = this,
1255
- tabindex = this.element.attr( "tabindex" );
1256
-
1257
- // Associate existing label with the new button
1258
- this.label = $( "label[for='" + this.ids.element + "']" ).attr( "for", this.ids.button );
1259
- this._on( this.label, {
1260
- click: function( event ) {
1261
- this.button.focus();
1262
- event.preventDefault();
1263
- }
1264
- });
1265
-
1266
- // Hide original select element
1267
- this.element.hide();
1268
-
1269
- // Create button
1270
- this.button = $( "<span>", {
1271
- "class": "ui-selectmenu-button ui-widget ui-state-default ui-corner-all",
1272
- tabindex: tabindex || this.options.disabled ? -1 : 0,
1273
- id: this.ids.button,
1274
- role: "combobox",
1275
- "aria-expanded": "false",
1276
- "aria-autocomplete": "list",
1277
- "aria-owns": this.ids.menu,
1278
- "aria-haspopup": "true"
1279
- })
1280
- .insertAfter( this.element );
1281
-
1282
- $( "<span>", {
1283
- "class": "ui-icon " + this.options.icons.button
1284
- })
1285
- .prependTo( this.button );
1286
-
1287
- this.buttonText = $( "<span>", {
1288
- "class": "ui-selectmenu-text"
1289
- })
1290
- .appendTo( this.button );
1291
-
1292
- this._setText( this.buttonText, this.element.find( "option:selected" ).text() );
1293
- this._resizeButton();
1294
-
1295
- this._on( this.button, this._buttonEvents );
1296
- this.button.one( "focusin", function() {
1297
-
1298
- // Delay rendering the menu items until the button receives focus.
1299
- // The menu may have already been rendered via a programmatic open.
1300
- if ( !that.menuItems ) {
1301
- that._refreshMenu();
1302
- }
1303
- });
1304
- this._hoverable( this.button );
1305
- this._focusable( this.button );
1306
- },
1307
-
1308
- _drawMenu: function() {
1309
- var that = this;
1310
-
1311
- // Create menu
1312
- this.menu = $( "<ul>", {
1313
- "aria-hidden": "true",
1314
- "aria-labelledby": this.ids.button,
1315
- id: this.ids.menu
1316
- });
1317
-
1318
- // Wrap menu
1319
- this.menuWrap = $( "<div>", {
1320
- "class": "ui-selectmenu-menu ui-front"
1321
- })
1322
- .append( this.menu )
1323
- .appendTo( this._appendTo() );
1324
-
1325
- // Initialize menu widget
1326
- this.menuInstance = this.menu
1327
- .menu({
1328
- role: "listbox",
1329
- select: function( event, ui ) {
1330
- event.preventDefault();
1331
-
1332
- // support: IE8
1333
- // If the item was selected via a click, the text selection
1334
- // will be destroyed in IE
1335
- that._setSelection();
1336
-
1337
- that._select( ui.item.data( "ui-selectmenu-item" ), event );
1338
- },
1339
- focus: function( event, ui ) {
1340
- var item = ui.item.data( "ui-selectmenu-item" );
1341
-
1342
- // Prevent inital focus from firing and check if its a newly focused item
1343
- if ( that.focusIndex != null && item.index !== that.focusIndex ) {
1344
- that._trigger( "focus", event, { item: item } );
1345
- if ( !that.isOpen ) {
1346
- that._select( item, event );
1347
- }
1348
- }
1349
- that.focusIndex = item.index;
1350
-
1351
- that.button.attr( "aria-activedescendant",
1352
- that.menuItems.eq( item.index ).attr( "id" ) );
1353
- }
1354
- })
1355
- .menu( "instance" );
1356
-
1357
- // Adjust menu styles to dropdown
1358
- this.menu
1359
- .addClass( "ui-corner-bottom" )
1360
- .removeClass( "ui-corner-all" );
1361
-
1362
- // Don't close the menu on mouseleave
1363
- this.menuInstance._off( this.menu, "mouseleave" );
1364
-
1365
- // Cancel the menu's collapseAll on document click
1366
- this.menuInstance._closeOnDocumentClick = function() {
1367
- return false;
1368
- };
1369
-
1370
- // Selects often contain empty items, but never contain dividers
1371
- this.menuInstance._isDivider = function() {
1372
- return false;
1373
- };
1374
- },
1375
-
1376
- refresh: function() {
1377
- this._refreshMenu();
1378
- this._setText( this.buttonText, this._getSelectedItem().text() );
1379
- if ( !this.options.width ) {
1380
- this._resizeButton();
1381
- }
1382
- },
1383
-
1384
- _refreshMenu: function() {
1385
- this.menu.empty();
1386
-
1387
- var item,
1388
- options = this.element.find( "option" );
1389
-
1390
- if ( !options.length ) {
1391
- return;
1392
- }
1393
-
1394
- this._parseOptions( options );
1395
- this._renderMenu( this.menu, this.items );
1396
-
1397
- this.menuInstance.refresh();
1398
- this.menuItems = this.menu.find( "li" ).not( ".ui-selectmenu-optgroup" );
1399
-
1400
- item = this._getSelectedItem();
1401
-
1402
- // Update the menu to have the correct item focused
1403
- this.menuInstance.focus( null, item );
1404
- this._setAria( item.data( "ui-selectmenu-item" ) );
1405
-
1406
- // Set disabled state
1407
- this._setOption( "disabled", this.element.prop( "disabled" ) );
1408
- },
1409
-
1410
- open: function( event ) {
1411
- if ( this.options.disabled ) {
1412
- return;
1413
- }
1414
-
1415
- // If this is the first time the menu is being opened, render the items
1416
- if ( !this.menuItems ) {
1417
- this._refreshMenu();
1418
- } else {
1419
-
1420
- // Menu clears focus on close, reset focus to selected item
1421
- this.menu.find( ".ui-state-focus" ).removeClass( "ui-state-focus" );
1422
- this.menuInstance.focus( null, this._getSelectedItem() );
1423
- }
1424
-
1425
- this.isOpen = true;
1426
- this._toggleAttr();
1427
- this._resizeMenu();
1428
- this._position();
1429
-
1430
- this._on( this.document, this._documentClick );
1431
-
1432
- this._trigger( "open", event );
1433
- },
1434
-
1435
- _position: function() {
1436
- this.menuWrap.position( $.extend( { of: this.button }, this.options.position ) );
1437
- },
1438
-
1439
- close: function( event ) {
1440
- if ( !this.isOpen ) {
1441
- return;
1442
- }
1443
-
1444
- this.isOpen = false;
1445
- this._toggleAttr();
1446
-
1447
- this.range = null;
1448
- this._off( this.document );
1449
-
1450
- this._trigger( "close", event );
1451
- },
1452
-
1453
- widget: function() {
1454
- return this.button;
1455
- },
1456
-
1457
- menuWidget: function() {
1458
- return this.menu;
1459
- },
1460
-
1461
- _renderMenu: function( ul, items ) {
1462
- var that = this,
1463
- currentOptgroup = "";
1464
-
1465
- $.each( items, function( index, item ) {
1466
- if ( item.optgroup !== currentOptgroup ) {
1467
- $( "<li>", {
1468
- "class": "ui-selectmenu-optgroup ui-menu-divider" +
1469
- ( item.element.parent( "optgroup" ).prop( "disabled" ) ?
1470
- " ui-state-disabled" :
1471
- "" ),
1472
- text: item.optgroup
1473
- })
1474
- .appendTo( ul );
1475
-
1476
- currentOptgroup = item.optgroup;
1477
- }
1478
-
1479
- that._renderItemData( ul, item );
1480
- });
1481
- },
1482
-
1483
- _renderItemData: function( ul, item ) {
1484
- return this._renderItem( ul, item ).data( "ui-selectmenu-item", item );
1485
- },
1486
-
1487
- _renderItem: function( ul, item ) {
1488
- var li = $( "<li>" );
1489
-
1490
- if ( item.disabled ) {
1491
- li.addClass( "ui-state-disabled" );
1492
- }
1493
- this._setText( li, item.label );
1494
-
1495
- return li.appendTo( ul );
1496
- },
1497
-
1498
- _setText: function( element, value ) {
1499
- if ( value ) {
1500
- element.text( value );
1501
- } else {
1502
- element.html( "&#160;" );
1503
- }
1504
- },
1505
-
1506
- _move: function( direction, event ) {
1507
- var item, next,
1508
- filter = ".ui-menu-item";
1509
-
1510
- if ( this.isOpen ) {
1511
- item = this.menuItems.eq( this.focusIndex );
1512
- } else {
1513
- item = this.menuItems.eq( this.element[ 0 ].selectedIndex );
1514
- filter += ":not(.ui-state-disabled)";
1515
- }
1516
-
1517
- if ( direction === "first" || direction === "last" ) {
1518
- next = item[ direction === "first" ? "prevAll" : "nextAll" ]( filter ).eq( -1 );
1519
- } else {
1520
- next = item[ direction + "All" ]( filter ).eq( 0 );
1521
- }
1522
-
1523
- if ( next.length ) {
1524
- this.menuInstance.focus( event, next );
1525
- }
1526
- },
1527
-
1528
- _getSelectedItem: function() {
1529
- return this.menuItems.eq( this.element[ 0 ].selectedIndex );
1530
- },
1531
-
1532
- _toggle: function( event ) {
1533
- this[ this.isOpen ? "close" : "open" ]( event );
1534
- },
1535
-
1536
- _setSelection: function() {
1537
- var selection;
1538
-
1539
- if ( !this.range ) {
1540
- return;
1541
- }
1542
-
1543
- if ( window.getSelection ) {
1544
- selection = window.getSelection();
1545
- selection.removeAllRanges();
1546
- selection.addRange( this.range );
1547
-
1548
- // support: IE8
1549
- } else {
1550
- this.range.select();
1551
- }
1552
-
1553
- // support: IE
1554
- // Setting the text selection kills the button focus in IE, but
1555
- // restoring the focus doesn't kill the selection.
1556
- this.button.focus();
1557
- },
1558
-
1559
- _documentClick: {
1560
- mousedown: function( event ) {
1561
- if ( !this.isOpen ) {
1562
- return;
1563
- }
1564
-
1565
- if ( !$( event.target ).closest( ".ui-selectmenu-menu, #" + this.ids.button ).length ) {
1566
- this.close( event );
1567
- }
1568
- }
1569
- },
1570
-
1571
- _buttonEvents: {
1572
-
1573
- // Prevent text selection from being reset when interacting with the selectmenu (#10144)
1574
- mousedown: function() {
1575
- var selection;
1576
-
1577
- if ( window.getSelection ) {
1578
- selection = window.getSelection();
1579
- if ( selection.rangeCount ) {
1580
- this.range = selection.getRangeAt( 0 );
1581
- }
1582
-
1583
- // support: IE8
1584
- } else {
1585
- this.range = document.selection.createRange();
1586
- }
1587
- },
1588
-
1589
- click: function( event ) {
1590
- this._setSelection();
1591
- this._toggle( event );
1592
- },
1593
-
1594
- keydown: function( event ) {
1595
- var preventDefault = true;
1596
- switch ( event.keyCode ) {
1597
- case $.ui.keyCode.TAB:
1598
- case $.ui.keyCode.ESCAPE:
1599
- this.close( event );
1600
- preventDefault = false;
1601
- break;
1602
- case $.ui.keyCode.ENTER:
1603
- if ( this.isOpen ) {
1604
- this._selectFocusedItem( event );
1605
- }
1606
- break;
1607
- case $.ui.keyCode.UP:
1608
- if ( event.altKey ) {
1609
- this._toggle( event );
1610
- } else {
1611
- this._move( "prev", event );
1612
- }
1613
- break;
1614
- case $.ui.keyCode.DOWN:
1615
- if ( event.altKey ) {
1616
- this._toggle( event );
1617
- } else {
1618
- this._move( "next", event );
1619
- }
1620
- break;
1621
- case $.ui.keyCode.SPACE:
1622
- if ( this.isOpen ) {
1623
- this._selectFocusedItem( event );
1624
- } else {
1625
- this._toggle( event );
1626
- }
1627
- break;
1628
- case $.ui.keyCode.LEFT:
1629
- this._move( "prev", event );
1630
- break;
1631
- case $.ui.keyCode.RIGHT:
1632
- this._move( "next", event );
1633
- break;
1634
- case $.ui.keyCode.HOME:
1635
- case $.ui.keyCode.PAGE_UP:
1636
- this._move( "first", event );
1637
- break;
1638
- case $.ui.keyCode.END:
1639
- case $.ui.keyCode.PAGE_DOWN:
1640
- this._move( "last", event );
1641
- break;
1642
- default:
1643
- this.menu.trigger( event );
1644
- preventDefault = false;
1645
- }
1646
-
1647
- if ( preventDefault ) {
1648
- event.preventDefault();
1649
- }
1650
- }
1651
- },
1652
-
1653
- _selectFocusedItem: function( event ) {
1654
- var item = this.menuItems.eq( this.focusIndex );
1655
- if ( !item.hasClass( "ui-state-disabled" ) ) {
1656
- this._select( item.data( "ui-selectmenu-item" ), event );
1657
- }
1658
- },
1659
-
1660
- _select: function( item, event ) {
1661
- var oldIndex = this.element[ 0 ].selectedIndex;
1662
-
1663
- // Change native select element
1664
- this.element[ 0 ].selectedIndex = item.index;
1665
- this._setText( this.buttonText, item.label );
1666
- this._setAria( item );
1667
- this._trigger( "select", event, { item: item } );
1668
-
1669
- if ( item.index !== oldIndex ) {
1670
- this._trigger( "change", event, { item: item } );
1671
- }
1672
-
1673
- this.close( event );
1674
- },
1675
-
1676
- _setAria: function( item ) {
1677
- var id = this.menuItems.eq( item.index ).attr( "id" );
1678
-
1679
- this.button.attr({
1680
- "aria-labelledby": id,
1681
- "aria-activedescendant": id
1682
- });
1683
- this.menu.attr( "aria-activedescendant", id );
1684
- },
1685
-
1686
- _setOption: function( key, value ) {
1687
- if ( key === "icons" ) {
1688
- this.button.find( "span.ui-icon" )
1689
- .removeClass( this.options.icons.button )
1690
- .addClass( value.button );
1691
- }
1692
-
1693
- this._super( key, value );
1694
-
1695
- if ( key === "appendTo" ) {
1696
- this.menuWrap.appendTo( this._appendTo() );
1697
- }
1698
-
1699
- if ( key === "disabled" ) {
1700
- this.menuInstance.option( "disabled", value );
1701
- this.button
1702
- .toggleClass( "ui-state-disabled", value )
1703
- .attr( "aria-disabled", value );
1704
-
1705
- this.element.prop( "disabled", value );
1706
- if ( value ) {
1707
- this.button.attr( "tabindex", -1 );
1708
- this.close();
1709
- } else {
1710
- this.button.attr( "tabindex", 0 );
1711
- }
1712
- }
1713
-
1714
- if ( key === "width" ) {
1715
- this._resizeButton();
1716
- }
1717
- },
1718
-
1719
- _appendTo: function() {
1720
- var element = this.options.appendTo;
1721
-
1722
- if ( element ) {
1723
- element = element.jquery || element.nodeType ?
1724
- $( element ) :
1725
- this.document.find( element ).eq( 0 );
1726
- }
1727
-
1728
- if ( !element || !element[ 0 ] ) {
1729
- element = this.element.closest( ".ui-front" );
1730
- }
1731
-
1732
- if ( !element.length ) {
1733
- element = this.document[ 0 ].body;
1734
- }
1735
-
1736
- return element;
1737
- },
1738
-
1739
- _toggleAttr: function() {
1740
- this.button
1741
- .toggleClass( "ui-corner-top", this.isOpen )
1742
- .toggleClass( "ui-corner-all", !this.isOpen )
1743
- .attr( "aria-expanded", this.isOpen );
1744
- this.menuWrap.toggleClass( "ui-selectmenu-open", this.isOpen );
1745
- this.menu.attr( "aria-hidden", !this.isOpen );
1746
- },
1747
-
1748
- _resizeButton: function() {
1749
- var width = this.options.width;
1750
-
1751
- if ( !width ) {
1752
- width = this.element.show().outerWidth();
1753
- this.element.hide();
1754
- }
1755
-
1756
- this.button.outerWidth( width );
1757
- },
1758
-
1759
- _resizeMenu: function() {
1760
- this.menu.outerWidth( Math.max(
1761
- this.button.outerWidth(),
1762
-
1763
- // support: IE10
1764
- // IE10 wraps long text (possibly a rounding bug)
1765
- // so we add 1px to avoid the wrapping
1766
- this.menu.width( "" ).outerWidth() + 1
1767
- ) );
1768
- },
1769
-
1770
- _getCreateOptions: function() {
1771
- return { disabled: this.element.prop( "disabled" ) };
1772
- },
1773
-
1774
- _parseOptions: function( options ) {
1775
- var data = [];
1776
- options.each(function( index, item ) {
1777
- var option = $( item ),
1778
- optgroup = option.parent( "optgroup" );
1779
- data.push({
1780
- element: option,
1781
- index: index,
1782
- value: option.attr( "value" ),
1783
- label: option.text(),
1784
- optgroup: optgroup.attr( "label" ) || "",
1785
- disabled: optgroup.prop( "disabled" ) || option.prop( "disabled" )
1786
- });
1787
- });
1788
- this.items = data;
1789
- },
1790
-
1791
- _destroy: function() {
1792
- this.menuWrap.remove();
1793
- this.button.remove();
1794
- this.element.show();
1795
- this.element.removeUniqueId();
1796
- this.label.attr( "for", this.ids.element );
1797
- }
1798
  });
1799
 
1800
 
4
  * Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */
5
 
6
  (function( factory ) {
7
+ if ( typeof define === "function" && define.amd ) {
8
 
9
+ // AMD. Register as an anonymous module.
10
+ define([ "jquery" ], factory );
11
+ } else {
12
 
13
+ // Browser globals
14
+ factory( jQuery );
15
+ }
16
  }(function( $ ) {
17
 
18
 
29
 
30
 
31
  var widget_uuid = 0,
32
+ widget_slice = Array.prototype.slice;
33
 
34
  $.cleanData = (function( orig ) {
35
+ return function( elems ) {
36
+ var events, elem, i;
37
+ for ( i = 0; (elem = elems[i]) != null; i++ ) {
38
+ try {
39
+
40
+ // Only trigger remove when necessary to save time
41
+ events = $._data( elem, "events" );
42
+ if ( events && events.remove ) {
43
+ $( elem ).triggerHandler( "remove" );
44
+ }
45
+
46
+ // http://bugs.jquery.com/ticket/8235
47
+ } catch ( e ) {}
48
+ }
49
+ orig( elems );
50
+ };
51
  })( $.cleanData );
52
 
53
  $.widget = function( name, base, prototype ) {
54
+ var fullName, existingConstructor, constructor, basePrototype,
55
+ // proxiedPrototype allows the provided prototype to remain unmodified
56
+ // so that it can be used as a mixin for multiple widgets (#8876)
57
+ proxiedPrototype = {},
58
+ namespace = name.split( "." )[ 0 ];
59
+
60
+ name = name.split( "." )[ 1 ];
61
+ fullName = namespace + "-" + name;
62
+
63
+ if ( !prototype ) {
64
+ prototype = base;
65
+ base = $.Widget;
66
+ }
67
+
68
+ // create selector for plugin
69
+ $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
70
+ return !!$.data( elem, fullName );
71
+ };
72
+
73
+ $[ namespace ] = $[ namespace ] || {};
74
+ existingConstructor = $[ namespace ][ name ];
75
+ constructor = $[ namespace ][ name ] = function( options, element ) {
76
+ // allow instantiation without "new" keyword
77
+ if ( !this._createWidget ) {
78
+ return new constructor( options, element );
79
+ }
80
+
81
+ // allow instantiation without initializing for simple inheritance
82
+ // must use "new" keyword (the code above always passes args)
83
+ if ( arguments.length ) {
84
+ this._createWidget( options, element );
85
+ }
86
+ };
87
+ // extend with the existing constructor to carry over any static properties
88
+ $.extend( constructor, existingConstructor, {
89
+ version: prototype.version,
90
+ // copy the object used to create the prototype in case we need to
91
+ // redefine the widget later
92
+ _proto: $.extend( {}, prototype ),
93
+ // track widgets that inherit from this widget in case this widget is
94
+ // redefined after a widget inherits from it
95
+ _childConstructors: []
96
+ });
97
+
98
+ basePrototype = new base();
99
+ // we need to make the options hash a property directly on the new instance
100
+ // otherwise we'll modify the options hash on the prototype that we're
101
+ // inheriting from
102
+ basePrototype.options = $.widget.extend( {}, basePrototype.options );
103
+ $.each( prototype, function( prop, value ) {
104
+ if ( !$.isFunction( value ) ) {
105
+ proxiedPrototype[ prop ] = value;
106
+ return;
107
+ }
108
+ proxiedPrototype[ prop ] = (function() {
109
+ var _super = function() {
110
+ return base.prototype[ prop ].apply( this, arguments );
111
+ },
112
+ _superApply = function( args ) {
113
+ return base.prototype[ prop ].apply( this, args );
114
+ };
115
+ return function() {
116
+ var __super = this._super,
117
+ __superApply = this._superApply,
118
+ returnValue;
119
+
120
+ this._super = _super;
121
+ this._superApply = _superApply;
122
+
123
+ returnValue = value.apply( this, arguments );
124
+
125
+ this._super = __super;
126
+ this._superApply = __superApply;
127
+
128
+ return returnValue;
129
+ };
130
+ })();
131
+ });
132
+ constructor.prototype = $.widget.extend( basePrototype, {
133
+ // TODO: remove support for widgetEventPrefix
134
+ // always use the name + a colon as the prefix, e.g., draggable:start
135
+ // don't prefix for widgets that aren't DOM-based
136
+ widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name
137
+ }, proxiedPrototype, {
138
+ constructor: constructor,
139
+ namespace: namespace,
140
+ widgetName: name,
141
+ widgetFullName: fullName
142
+ });
143
+
144
+ // If this widget is being redefined then we need to find all widgets that
145
+ // are inheriting from it and redefine all of them so that they inherit from
146
+ // the new version of this widget. We're essentially trying to replace one
147
+ // level in the prototype chain.
148
+ if ( existingConstructor ) {
149
+ $.each( existingConstructor._childConstructors, function( i, child ) {
150
+ var childPrototype = child.prototype;
151
+
152
+ // redefine the child widget using the same prototype that was
153
+ // originally used, but inherit from the new version of the base
154
+ $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
155
+ });
156
+ // remove the list of existing child constructors from the old constructor
157
+ // so the old child constructors can be garbage collected
158
+ delete existingConstructor._childConstructors;
159
+ } else {
160
+ base._childConstructors.push( constructor );
161
+ }
162
+
163
+ $.widget.bridge( name, constructor );
164
+
165
+ return constructor;
166
  };
167
 
168
  $.widget.extend = function( target ) {
169
+ var input = widget_slice.call( arguments, 1 ),
170
+ inputIndex = 0,
171
+ inputLength = input.length,
172
+ key,
173
+ value;
174
+ for ( ; inputIndex < inputLength; inputIndex++ ) {
175
+ for ( key in input[ inputIndex ] ) {
176
+ value = input[ inputIndex ][ key ];
177
+ if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
178
+ // Clone objects
179
+ if ( $.isPlainObject( value ) ) {
180
+ target[ key ] = $.isPlainObject( target[ key ] ) ?
181
+ $.widget.extend( {}, target[ key ], value ) :
182
+ // Don't extend strings, arrays, etc. with objects
183
+ $.widget.extend( {}, value );
184
+ // Copy everything else by reference
185
+ } else {
186
+ target[ key ] = value;
187
+ }
188
+ }
189
+ }
190
+ }
191
+ return target;
192
  };
193
 
194
  $.widget.bridge = function( name, object ) {
195
+ var fullName = object.prototype.widgetFullName || name;
196
+ $.fn[ name ] = function( options ) {
197
+ var isMethodCall = typeof options === "string",
198
+ args = widget_slice.call( arguments, 1 ),
199
+ returnValue = this;
200
+
201
+ // allow multiple hashes to be passed on init
202
+ options = !isMethodCall && args.length ?
203
+ $.widget.extend.apply( null, [ options ].concat(args) ) :
204
+ options;
205
+
206
+ if ( isMethodCall ) {
207
+ this.each(function() {
208
+ var methodValue,
209
+ instance = $.data( this, fullName );
210
+ if ( options === "instance" ) {
211
+ returnValue = instance;
212
+ return false;
213
+ }
214
+ if ( !instance ) {
215
+ return $.error( "cannot call methods on " + name + " prior to initialization; " +
216
+ "attempted to call method '" + options + "'" );
217
+ }
218
+ if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
219
+ return $.error( "no such method '" + options + "' for " + name + " widget instance" );
220
+ }
221
+ methodValue = instance[ options ].apply( instance, args );
222
+ if ( methodValue !== instance && methodValue !== undefined ) {
223
+ returnValue = methodValue && methodValue.jquery ?
224
+ returnValue.pushStack( methodValue.get() ) :
225
+ methodValue;
226
+ return false;
227
+ }
228
+ });
229
+ } else {
230
+ this.each(function() {
231
+ var instance = $.data( this, fullName );
232
+ if ( instance ) {
233
+ instance.option( options || {} );
234
+ if ( instance._init ) {
235
+ instance._init();
236
+ }
237
+ } else {
238
+ $.data( this, fullName, new object( options, this ) );
239
+ }
240
+ });
241
+ }
242
+
243
+ return returnValue;
244
+ };
245
  };
246
 
247
  $.Widget = function( /* options, element */ ) {};
250
  $.Widget._childConstructors = [];
251
 
252
  $.Widget.prototype = {
253
+ widgetName: "widget",
254
+ widgetEventPrefix: "",
255
+ defaultElement: "<div>",
256
+ options: {
257
+ disabled: false,
258
+
259
+ // callbacks
260
+ create: null
261
+ },
262
+ _createWidget: function( options, element ) {
263
+ element = $( element || this.defaultElement || this )[ 0 ];
264
+ this.element = $( element );
265
+ this.uuid = widget_uuid++;
266
+ this.eventNamespace = "." + this.widgetName + this.uuid;
267
+
268
+ this.bindings = $();
269
+ this.hoverable = $();
270
+ this.focusable = $();
271
+
272
+ if ( element !== this ) {
273
+ $.data( element, this.widgetFullName, this );
274
+ this._on( true, this.element, {
275
+ remove: function( event ) {
276
+ if ( event.target === element ) {
277
+ this.destroy();
278
+ }
279
+ }
280
+ });
281
+ this.document = $( element.style ?
282
+ // element within the document
283
+ element.ownerDocument :
284
+ // element is window or document
285
+ element.document || element );
286
+ this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
287
+ }
288
+
289
+ this.options = $.widget.extend( {},
290
+ this.options,
291
+ this._getCreateOptions(),
292
+ options );
293
+
294
+ this._create();
295
+ this._trigger( "create", null, this._getCreateEventData() );
296
+ this._init();
297
+ },
298
+ _getCreateOptions: $.noop,
299
+ _getCreateEventData: $.noop,
300
+ _create: $.noop,
301
+ _init: $.noop,
302
+
303
+ destroy: function() {
304
+ this._destroy();
305
+ // we can probably remove the unbind calls in 2.0
306
+ // all event bindings should go through this._on()
307
+ this.element
308
+ .unbind( this.eventNamespace )
309
+ .removeData( this.widgetFullName )
310
+ // support: jquery <1.6.4
311
+ // http://bugs.jquery.com/ticket/9413
312
+ .removeData( $.camelCase( this.widgetFullName ) );
313
+ this.widget()
314
+ .unbind( this.eventNamespace )
315
+ .removeAttr( "aria-disabled" )
316
+ .removeClass(
317
+ this.widgetFullName + "-disabled " +
318
+ "ui-state-disabled" );
319
+
320
+ // clean up events and states
321
+ this.bindings.unbind( this.eventNamespace );
322
+ this.hoverable.removeClass( "ui-state-hover" );
323
+ this.focusable.removeClass( "ui-state-focus" );
324
+ },
325
+ _destroy: $.noop,
326
+
327
+ widget: function() {
328
+ return this.element;
329
+ },
330
+
331
+ option: function( key, value ) {
332
+ var options = key,
333
+ parts,
334
+ curOption,
335
+ i;
336
+
337
+ if ( arguments.length === 0 ) {
338
+ // don't return a reference to the internal hash
339
+ return $.widget.extend( {}, this.options );
340
+ }
341
+
342
+ if ( typeof key === "string" ) {
343
+ // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
344
+ options = {};
345
+ parts = key.split( "." );
346
+ key = parts.shift();
347
+ if ( parts.length ) {
348
+ curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
349
+ for ( i = 0; i < parts.length - 1; i++ ) {
350
+ curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
351
+ curOption = curOption[ parts[ i ] ];
352
+ }
353
+ key = parts.pop();
354
+ if ( arguments.length === 1 ) {
355
+ return curOption[ key ] === undefined ? null : curOption[ key ];
356
+ }
357
+ curOption[ key ] = value;
358
+ } else {
359
+ if ( arguments.length === 1 ) {
360
+ return this.options[ key ] === undefined ? null : this.options[ key ];
361
+ }
362
+ options[ key ] = value;
363
+ }
364
+ }
365
+
366
+ this._setOptions( options );
367
+
368
+ return this;
369
+ },
370
+ _setOptions: function( options ) {
371
+ var key;
372
+
373
+ for ( key in options ) {
374
+ this._setOption( key, options[ key ] );
375
+ }
376
+
377
+ return this;
378
+ },
379
+ _setOption: function( key, value ) {
380
+ this.options[ key ] = value;
381
+
382
+ if ( key === "disabled" ) {
383
+ this.widget()
384
+ .toggleClass( this.widgetFullName + "-disabled", !!value );
385
+
386
+ // If the widget is becoming disabled, then nothing is interactive
387
+ if ( value ) {
388
+ this.hoverable.removeClass( "ui-state-hover" );
389
+ this.focusable.removeClass( "ui-state-focus" );
390
+ }
391
+ }
392
+
393
+ return this;
394
+ },
395
+
396
+ enable: function() {
397
+ return this._setOptions({ disabled: false });
398
+ },
399
+ disable: function() {
400
+ return this._setOptions({ disabled: true });
401
+ },
402
+
403
+ _on: function( suppressDisabledCheck, element, handlers ) {
404
+ var delegateElement,
405
+ instance = this;
406
+
407
+ // no suppressDisabledCheck flag, shuffle arguments
408
+ if ( typeof suppressDisabledCheck !== "boolean" ) {
409
+ handlers = element;
410
+ element = suppressDisabledCheck;
411
+ suppressDisabledCheck = false;
412
+ }
413
+
414
+ // no element argument, shuffle and use this.element
415
+ if ( !handlers ) {
416
+ handlers = element;
417
+ element = this.element;
418
+ delegateElement = this.widget();
419
+ } else {
420
+ element = delegateElement = $( element );
421
+ this.bindings = this.bindings.add( element );
422
+ }
423
+
424
+ $.each( handlers, function( event, handler ) {
425
+ function handlerProxy() {
426
+ // allow widgets to customize the disabled handling
427
+ // - disabled as an array instead of boolean
428
+ // - disabled class as method for disabling individual parts
429
+ if ( !suppressDisabledCheck &&
430
+ ( instance.options.disabled === true ||
431
+ $( this ).hasClass( "ui-state-disabled" ) ) ) {
432
+ return;
433
+ }
434
+ return ( typeof handler === "string" ? instance[ handler ] : handler )
435
+ .apply( instance, arguments );
436
+ }
437
+
438
+ // copy the guid so direct unbinding works
439
+ if ( typeof handler !== "string" ) {
440
+ handlerProxy.guid = handler.guid =
441
+ handler.guid || handlerProxy.guid || $.guid++;
442
+ }
443
+
444
+ var match = event.match( /^([\w:-]*)\s*(.*)$/ ),
445
+ eventName = match[1] + instance.eventNamespace,
446
+ selector = match[2];
447
+ if ( selector ) {
448
+ delegateElement.delegate( selector, eventName, handlerProxy );
449
+ } else {
450
+ element.bind( eventName, handlerProxy );
451
+ }
452
+ });
453
+ },
454
+
455
+ _off: function( element, eventName ) {
456
+ eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) +
457
+ this.eventNamespace;
458
+ element.unbind( eventName ).undelegate( eventName );
459
+
460
+ // Clear the stack to avoid memory leaks (#10056)
461
+ this.bindings = $( this.bindings.not( element ).get() );
462
+ this.focusable = $( this.focusable.not( element ).get() );
463
+ this.hoverable = $( this.hoverable.not( element ).get() );
464
+ },
465
+
466
+ _delay: function( handler, delay ) {
467
+ function handlerProxy() {
468
+ return ( typeof handler === "string" ? instance[ handler ] : handler )
469
+ .apply( instance, arguments );
470
+ }
471
+ var instance = this;
472
+ return setTimeout( handlerProxy, delay || 0 );
473
+ },
474
+
475
+ _hoverable: function( element ) {
476
+ this.hoverable = this.hoverable.add( element );
477
+ this._on( element, {
478
+ mouseenter: function( event ) {
479
+ $( event.currentTarget ).addClass( "ui-state-hover" );
480
+ },
481
+ mouseleave: function( event ) {
482
+ $( event.currentTarget ).removeClass( "ui-state-hover" );
483
+ }
484
+ });
485
+ },
486
+
487
+ _focusable: function( element ) {
488
+ this.focusable = this.focusable.add( element );
489
+ this._on( element, {
490
+ focusin: function( event ) {
491
+ $( event.currentTarget ).addClass( "ui-state-focus" );
492
+ },
493
+ focusout: function( event ) {
494
+ $( event.currentTarget ).removeClass( "ui-state-focus" );
495
+ }
496
+ });
497
+ },
498
+
499
+ _trigger: function( type, event, data ) {
500
+ var prop, orig,
501
+ callback = this.options[ type ];
502
+
503
+ data = data || {};
504
+ event = $.Event( event );
505
+ event.type = ( type === this.widgetEventPrefix ?
506
+ type :
507
+ this.widgetEventPrefix + type ).toLowerCase();
508
+ // the original event may come from any element
509
+ // so we need to reset the target on the new event
510
+ event.target = this.element[ 0 ];
511
+
512
+ // copy original event properties over to the new event
513
+ orig = event.originalEvent;
514
+ if ( orig ) {
515
+ for ( prop in orig ) {
516
+ if ( !( prop in event ) ) {
517
+ event[ prop ] = orig[ prop ];
518
+ }
519
+ }
520
+ }
521
+
522
+ this.element.trigger( event, data );
523
+ return !( $.isFunction( callback ) &&
524
+ callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
525
+ event.isDefaultPrevented() );
526
+ }
527
  };
528
 
529
  $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
530
+ $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
531
+ if ( typeof options === "string" ) {
532
+ options = { effect: options };
533
+ }
534
+ var hasOptions,
535
+ effectName = !options ?
536
+ method :
537
+ options === true || typeof options === "number" ?
538
+ defaultEffect :
539
+ options.effect || defaultEffect;
540
+ options = options || {};
541
+ if ( typeof options === "number" ) {
542
+ options = { duration: options };
543
+ }
544
+ hasOptions = !$.isEmptyObject( options );
545
+ options.complete = callback;
546
+ if ( options.delay ) {
547
+ element.delay( options.delay );
548
+ }
549
+ if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
550
+ element[ method ]( options );
551
+ } else if ( effectName !== method && element[ effectName ] ) {
552
+ element[ effectName ]( options.duration, options.easing, callback );
553
+ } else {
554
+ element.queue(function( next ) {
555
+ $( this )[ method ]();
556
+ if ( callback ) {
557
+ callback.call( element[ 0 ] );
558
+ }
559
+ next();
560
+ });
561
+ }
562
+ };
563
  });
564
 
565
  var widget = $.widget;
580
 
581
 
582
  var menu = $.widget( "ui.menu", {
583
+ version: "1.11.2",
584
+ defaultElement: "<ul>",
585
+ delay: 300,
586
+ options: {
587
+ icons: {
588
+ submenu: "ui-icon-carat-1-e"
589
+ },
590
+ items: "> *",
591
+ menus: "ul",
592
+ position: {
593
+ my: "left-1 top",
594
+ at: "right top"
595
+ },
596
+ role: "menu",
597
+
598
+ // callbacks
599
+ blur: null,
600
+ focus: null,
601
+ select: null
602
+ },
603
+
604
+ _create: function() {
605
+ this.activeMenu = this.element;
606
+
607
+ // Flag used to prevent firing of the click handler
608
+ // as the event bubbles up through nested menus
609
+ this.mouseHandled = false;
610
+ this.element
611
+ .uniqueId()
612
+ .addClass( "ui-menu ui-widget ui-widget-content" )
613
+ .toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length )
614
+ .attr({
615
+ role: this.options.role,
616
+ tabIndex: 0
617
+ });
618
+
619
+ if ( this.options.disabled ) {
620
+ this.element
621
+ .addClass( "ui-state-disabled" )
622
+ .attr( "aria-disabled", "true" );
623
+ }
624
+
625
+ this._on({
626
+ // Prevent focus from sticking to links inside menu after clicking
627
+ // them (focus should always stay on UL during navigation).
628
+ "mousedown .ui-menu-item": function( event ) {
629
+ event.preventDefault();
630
+ },
631
+ "click .ui-menu-item": function( event ) {
632
+ var target = $( event.target );
633
+ if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
634
+ this.select( event );
635
+
636
+ // Only set the mouseHandled flag if the event will bubble, see #9469.
637
+ if ( !event.isPropagationStopped() ) {
638
+ this.mouseHandled = true;
639
+ }
640
+
641
+ // Open submenu on click
642
+ if ( target.has( ".ui-menu" ).length ) {
643
+ this.expand( event );
644
+ } else if ( !this.element.is( ":focus" ) && $( this.document[ 0 ].activeElement ).closest( ".ui-menu" ).length ) {
645
+
646
+ // Redirect focus to the menu
647
+ this.element.trigger( "focus", [ true ] );
648
+
649
+ // If the active item is on the top level, let it stay active.
650
+ // Otherwise, blur the active item since it is no longer visible.
651
+ if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
652
+ clearTimeout( this.timer );
653
+ }
654
+ }
655
+ }
656
+ },
657
+ "mouseenter .ui-menu-item": function( event ) {
658
+ // Ignore mouse events while typeahead is active, see #10458.
659
+ // Prevents focusing the wrong item when typeahead causes a scroll while the mouse
660
+ // is over an item in the menu
661
+ if ( this.previousFilter ) {
662
+ return;
663
+ }
664
+ var target = $( event.currentTarget );
665
+ // Remove ui-state-active class from siblings of the newly focused menu item
666
+ // to avoid a jump caused by adjacent elements both having a class with a border
667
+ target.siblings( ".ui-state-active" ).removeClass( "ui-state-active" );
668
+ this.focus( event, target );
669
+ },
670
+ mouseleave: "collapseAll",
671
+ "mouseleave .ui-menu": "collapseAll",
672
+ focus: function( event, keepActiveItem ) {
673
+ // If there's already an active item, keep it active
674
+ // If not, activate the first item
675
+ var item = this.active || this.element.find( this.options.items ).eq( 0 );
676
+
677
+ if ( !keepActiveItem ) {
678
+ this.focus( event, item );
679
+ }
680
+ },
681
+ blur: function( event ) {
682
+ this._delay(function() {
683
+ if ( !$.contains( this.element[0], this.document[0].activeElement ) ) {
684
+ this.collapseAll( event );
685
+ }
686
+ });
687
+ },
688
+ keydown: "_keydown"
689
+ });
690
+
691
+ this.refresh();
692
+
693
+ // Clicks outside of a menu collapse any open menus
694
+ this._on( this.document, {
695
+ click: function( event ) {
696
+ if ( this._closeOnDocumentClick( event ) ) {
697
+ this.collapseAll( event );
698
+ }
699
+
700
+ // Reset the mouseHandled flag
701
+ this.mouseHandled = false;
702
+ }
703
+ });
704
+ },
705
+
706
+ _destroy: function() {
707
+ // Destroy (sub)menus
708
+ this.element
709
+ .removeAttr( "aria-activedescendant" )
710
+ .find( ".ui-menu" ).addBack()
711
+ .removeClass( "ui-menu ui-widget ui-widget-content ui-menu-icons ui-front" )
712
+ .removeAttr( "role" )
713
+ .removeAttr( "tabIndex" )
714
+ .removeAttr( "aria-labelledby" )
715
+ .removeAttr( "aria-expanded" )
716
+ .removeAttr( "aria-hidden" )
717
+ .removeAttr( "aria-disabled" )
718
+ .removeUniqueId()
719
+ .show();
720
+
721
+ // Destroy menu items
722
+ this.element.find( ".ui-menu-item" )
723
+ .removeClass( "ui-menu-item" )
724
+ .removeAttr( "role" )
725
+ .removeAttr( "aria-disabled" )
726
+ .removeUniqueId()
727
+ .removeClass( "ui-state-hover" )
728
+ .removeAttr( "tabIndex" )
729
+ .removeAttr( "role" )
730
+ .removeAttr( "aria-haspopup" )
731
+ .children().each( function() {
732
+ var elem = $( this );
733
+ if ( elem.data( "ui-menu-submenu-carat" ) ) {
734
+ elem.remove();
735
+ }
736
+ });
737
+
738
+ // Destroy menu dividers
739
+ this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" );
740
+ },
741
+
742
+ _keydown: function( event ) {
743
+ var match, prev, character, skip,
744
+ preventDefault = true;
745
+
746
+ switch ( event.keyCode ) {
747
+ case $.ui.keyCode.PAGE_UP:
748
+ this.previousPage( event );
749
+ break;
750
+ case $.ui.keyCode.PAGE_DOWN:
751
+ this.nextPage( event );
752
+ break;
753
+ case $.ui.keyCode.HOME:
754
+ this._move( "first", "first", event );
755
+ break;
756
+ case $.ui.keyCode.END:
757
+ this._move( "last", "last", event );
758
+ break;
759
+ case $.ui.keyCode.UP:
760
+ this.previous( event );
761
+ break;
762
+ case $.ui.keyCode.DOWN:
763
+ this.next( event );
764
+ break;
765
+ case $.ui.keyCode.LEFT:
766
+ this.collapse( event );
767
+ break;
768
+ case $.ui.keyCode.RIGHT:
769
+ if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
770
+ this.expand( event );
771
+ }
772
+ break;
773
+ case $.ui.keyCode.ENTER:
774
+ case $.ui.keyCode.SPACE:
775
+ this._activate( event );
776
+ break;
777
+ case $.ui.keyCode.ESCAPE:
778
+ this.collapse( event );
779
+ break;
780
+ default:
781
+ preventDefault = false;
782
+ prev = this.previousFilter || "";
783
+ character = String.fromCharCode( event.keyCode );
784
+ skip = false;
785
+
786
+ clearTimeout( this.filterTimer );
787
+
788
+ if ( character === prev ) {
789
+ skip = true;
790
+ } else {
791
+ character = prev + character;
792
+ }
793
+
794
+ match = this._filterMenuItems( character );
795
+ match = skip && match.index( this.active.next() ) !== -1 ?
796
+ this.active.nextAll( ".ui-menu-item" ) :
797
+ match;
798
+
799
+ // If no matches on the current filter, reset to the last character pressed
800
+ // to move down the menu to the first item that starts with that character
801
+ if ( !match.length ) {
802
+ character = String.fromCharCode( event.keyCode );
803
+ match = this._filterMenuItems( character );
804
+ }
805
+
806
+ if ( match.length ) {
807
+ this.focus( event, match );
808
+ this.previousFilter = character;
809
+ this.filterTimer = this._delay(function() {
810
+ delete this.previousFilter;
811
+ }, 1000 );
812
+ } else {
813
+ delete this.previousFilter;
814
+ }
815
+ }
816
+
817
+ if ( preventDefault ) {
818
+ event.preventDefault();
819
+ }
820
+ },
821
+
822
+ _activate: function( event ) {
823
+ if ( !this.active.is( ".ui-state-disabled" ) ) {
824
+ if ( this.active.is( "[aria-haspopup='true']" ) ) {
825
+ this.expand( event );
826
+ } else {
827
+ this.select( event );
828
+ }
829
+ }
830
+ },
831
+
832
+ refresh: function() {
833
+ var menus, items,
834
+ that = this,
835
+ icon = this.options.icons.submenu,
836
+ submenus = this.element.find( this.options.menus );
837
+
838
+ this.element.toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length );
839
+
840
+ // Initialize nested menus
841
+ submenus.filter( ":not(.ui-menu)" )
842
+ .addClass( "ui-menu ui-widget ui-widget-content ui-front" )
843
+ .hide()
844
+ .attr({
845
+ role: this.options.role,
846
+ "aria-hidden": "true",
847
+ "aria-expanded": "false"
848
+ })
849
+ .each(function() {
850
+ var menu = $( this ),
851
+ item = menu.parent(),
852
+ submenuCarat = $( "<span>" )
853
+ .addClass( "ui-menu-icon ui-icon " + icon )
854
+ .data( "ui-menu-submenu-carat", true );
855
+
856
+ item
857
+ .attr( "aria-haspopup", "true" )
858
+ .prepend( submenuCarat );
859
+ menu.attr( "aria-labelledby", item.attr( "id" ) );
860
+ });
861
+
862
+ menus = submenus.add( this.element );
863
+ items = menus.find( this.options.items );
864
+
865
+ // Initialize menu-items containing spaces and/or dashes only as dividers
866
+ items.not( ".ui-menu-item" ).each(function() {
867
+ var item = $( this );
868
+ if ( that._isDivider( item ) ) {
869
+ item.addClass( "ui-widget-content ui-menu-divider" );
870
+ }
871
+ });
872
+
873
+ // Don't refresh list items that are already adapted
874
+ items.not( ".ui-menu-item, .ui-menu-divider" )
875
+ .addClass( "ui-menu-item" )
876
+ .uniqueId()
877
+ .attr({
878
+ tabIndex: -1,
879
+ role: this._itemRole()
880
+ });
881
+
882
+ // Add aria-disabled attribute to any disabled menu item
883
+ items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
884
+
885
+ // If the active item has been removed, blur the menu
886
+ if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
887
+ this.blur();
888
+ }
889
+ },
890
+
891
+ _itemRole: function() {
892
+ return {
893
+ menu: "menuitem",
894
+ listbox: "option"
895
+ }[ this.options.role ];
896
+ },
897
+
898
+ _setOption: function( key, value ) {
899
+ if ( key === "icons" ) {
900
+ this.element.find( ".ui-menu-icon" )
901
+ .removeClass( this.options.icons.submenu )
902
+ .addClass( value.submenu );
903
+ }
904
+ if ( key === "disabled" ) {
905
+ this.element
906
+ .toggleClass( "ui-state-disabled", !!value )
907
+ .attr( "aria-disabled", value );
908
+ }
909
+ this._super( key, value );
910
+ },
911
+
912
+ focus: function( event, item ) {
913
+ var nested, focused;
914
+ this.blur( event, event && event.type === "focus" );
915
+
916
+ this._scrollIntoView( item );
917
+
918
+ this.active = item.first();
919
+ focused = this.active.addClass( "ui-state-focus" ).removeClass( "ui-state-active" );
920
+ // Only update aria-activedescendant if there's a role
921
+ // otherwise we assume focus is managed elsewhere
922
+ if ( this.options.role ) {
923
+ this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
924
+ }
925
+
926
+ // Highlight active parent menu item, if any
927
+ this.active
928
+ .parent()
929
+ .closest( ".ui-menu-item" )
930
+ .addClass( "ui-state-active" );
931
+
932
+ if ( event && event.type === "keydown" ) {
933
+ this._close();
934
+ } else {
935
+ this.timer = this._delay(function() {
936
+ this._close();
937
+ }, this.delay );
938
+ }
939
+
940
+ nested = item.children( ".ui-menu" );
941
+ if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {
942
+ this._startOpening(nested);
943
+ }
944
+ this.activeMenu = item.parent();
945
+
946
+ this._trigger( "focus", event, { item: item } );
947
+ },
948
+
949
+ _scrollIntoView: function( item ) {
950
+ var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
951
+ if ( this._hasScroll() ) {
952
+ borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0;
953
+ paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0;
954
+ offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
955
+ scroll = this.activeMenu.scrollTop();
956
+ elementHeight = this.activeMenu.height();
957
+ itemHeight = item.outerHeight();
958
+
959
+ if ( offset < 0 ) {
960
+ this.activeMenu.scrollTop( scroll + offset );
961
+ } else if ( offset + itemHeight > elementHeight ) {
962
+ this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
963
+ }
964
+ }
965
+ },
966
+
967
+ blur: function( event, fromFocus ) {
968
+ if ( !fromFocus ) {
969
+ clearTimeout( this.timer );
970
+ }
971
+
972
+ if ( !this.active ) {
973
+ return;
974
+ }
975
+
976
+ this.active.removeClass( "ui-state-focus" );
977
+ this.active = null;
978
+
979
+ this._trigger( "blur", event, { item: this.active } );
980
+ },
981
+
982
+ _startOpening: function( submenu ) {
983
+ clearTimeout( this.timer );
984
+
985
+ // Don't open if already open fixes a Firefox bug that caused a .5 pixel
986
+ // shift in the submenu position when mousing over the carat icon
987
+ if ( submenu.attr( "aria-hidden" ) !== "true" ) {
988
+ return;
989
+ }
990
+
991
+ this.timer = this._delay(function() {
992
+ this._close();
993
+ this._open( submenu );
994
+ }, this.delay );
995
+ },
996
+
997
+ _open: function( submenu ) {
998
+ var position = $.extend({
999
+ of: this.active
1000
+ }, this.options.position );
1001
+
1002
+ clearTimeout( this.timer );
1003
+ this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
1004
+ .hide()
1005
+ .attr( "aria-hidden", "true" );
1006
+
1007
+ submenu
1008
+ .show()
1009
+ .removeAttr( "aria-hidden" )
1010
+ .attr( "aria-expanded", "true" )
1011
+ .position( position );
1012
+ },
1013
+
1014
+ collapseAll: function( event, all ) {
1015
+ clearTimeout( this.timer );
1016
+ this.timer = this._delay(function() {
1017
+ // If we were passed an event, look for the submenu that contains the event
1018
+ var currentMenu = all ? this.element :
1019
+ $( event && event.target ).closest( this.element.find( ".ui-menu" ) );
1020
+
1021
+ // If we found no valid submenu ancestor, use the main menu to close all sub menus anyway
1022
+ if ( !currentMenu.length ) {
1023
+ currentMenu = this.element;
1024
+ }
1025
+
1026
+ this._close( currentMenu );
1027
+
1028
+ this.blur( event );
1029
+ this.activeMenu = currentMenu;
1030
+ }, this.delay );
1031
+ },
1032
+
1033
+ // With no arguments, closes the currently active menu - if nothing is active
1034
+ // it closes all menus. If passed an argument, it will search for menus BELOW
1035
+ _close: function( startMenu ) {
1036
+ if ( !startMenu ) {
1037
+ startMenu = this.active ? this.active.parent() : this.element;
1038
+ }
1039
+
1040
+ startMenu
1041
+ .find( ".ui-menu" )
1042
+ .hide()
1043
+ .attr( "aria-hidden", "true" )
1044
+ .attr( "aria-expanded", "false" )
1045
+ .end()
1046
+ .find( ".ui-state-active" ).not( ".ui-state-focus" )
1047
+ .removeClass( "ui-state-active" );
1048
+ },
1049
+
1050
+ _closeOnDocumentClick: function( event ) {
1051
+ return !$( event.target ).closest( ".ui-menu" ).length;
1052
+ },
1053
+
1054
+ _isDivider: function( item ) {
1055
+
1056
+ // Match hyphen, em dash, en dash
1057
+ return !/[^\-\u2014\u2013\s]/.test( item.text() );
1058
+ },
1059
+
1060
+ collapse: function( event ) {
1061
+ var newItem = this.active &&
1062
+ this.active.parent().closest( ".ui-menu-item", this.element );
1063
+ if ( newItem && newItem.length ) {
1064
+ this._close();
1065
+ this.focus( event, newItem );
1066
+ }
1067
+ },
1068
+
1069
+ expand: function( event ) {
1070
+ var newItem = this.active &&
1071
+ this.active
1072
+ .children( ".ui-menu " )
1073
+ .find( this.options.items )
1074
+ .first();
1075
+
1076
+ if ( newItem && newItem.length ) {
1077
+ this._open( newItem.parent() );
1078
+
1079
+ // Delay so Firefox will not hide activedescendant change in expanding submenu from AT
1080
+ this._delay(function() {
1081
+ this.focus( event, newItem );
1082
+ });
1083
+ }
1084
+ },
1085
+
1086
+ next: function( event ) {
1087
+ this._move( "next", "first", event );
1088
+ },
1089
+
1090
+ previous: function( event ) {
1091
+ this._move( "prev", "last", event );
1092
+ },
1093
+
1094
+ isFirstItem: function() {
1095
+ return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
1096
+ },
1097
+
1098
+ isLastItem: function() {
1099
+ return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
1100
+ },
1101
+
1102
+ _move: function( direction, filter, event ) {
1103
+ var next;
1104
+ if ( this.active ) {
1105
+ if ( direction === "first" || direction === "last" ) {
1106
+ next = this.active
1107
+ [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
1108
+ .eq( -1 );
1109
+ } else {
1110
+ next = this.active
1111
+ [ direction + "All" ]( ".ui-menu-item" )
1112
+ .eq( 0 );
1113
+ }
1114
+ }
1115
+ if ( !next || !next.length || !this.active ) {
1116
+ next = this.activeMenu.find( this.options.items )[ filter ]();
1117
+ }
1118
+
1119
+ this.focus( event, next );
1120
+ },
1121
+
1122
+ nextPage: function( event ) {
1123
+ var item, base, height;
1124
+
1125
+ if ( !this.active ) {
1126
+ this.next( event );
1127
+ return;
1128
+ }
1129
+ if ( this.isLastItem() ) {
1130
+ return;
1131
+ }
1132
+ if ( this._hasScroll() ) {
1133
+ base = this.active.offset().top;
1134
+ height = this.element.height();
1135
+ this.active.nextAll( ".ui-menu-item" ).each(function() {
1136
+ item = $( this );
1137
+ return item.offset().top - base - height < 0;
1138
+ });
1139
+
1140
+ this.focus( event, item );
1141
+ } else {
1142
+ this.focus( event, this.activeMenu.find( this.options.items )
1143
+ [ !this.active ? "first" : "last" ]() );
1144
+ }
1145
+ },
1146
+
1147
+ previousPage: function( event ) {
1148
+ var item, base, height;
1149
+ if ( !this.active ) {
1150
+ this.next( event );
1151
+ return;
1152
+ }
1153
+ if ( this.isFirstItem() ) {
1154
+ return;
1155
+ }
1156
+ if ( this._hasScroll() ) {
1157
+ base = this.active.offset().top;
1158
+ height = this.element.height();
1159
+ this.active.prevAll( ".ui-menu-item" ).each(function() {
1160
+ item = $( this );
1161
+ return item.offset().top - base + height > 0;
1162
+ });
1163
+
1164
+ this.focus( event, item );
1165
+ } else {
1166
+ this.focus( event, this.activeMenu.find( this.options.items ).first() );
1167
+ }
1168
+ },
1169
+
1170
+ _hasScroll: function() {
1171
+ return this.element.outerHeight() < this.element.prop( "scrollHeight" );
1172
+ },
1173
+
1174
+ select: function( event ) {
1175
+ // TODO: It should never be possible to not have an active item at this
1176
+ // point, but the tests don't trigger mouseenter before click.
1177
+ this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
1178
+ var ui = { item: this.active };
1179
+ if ( !this.active.has( ".ui-menu" ).length ) {
1180
+ this.collapseAll( event, true );
1181
+ }
1182
+ this._trigger( "select", event, ui );
1183
+ },
1184
+
1185
+ _filterMenuItems: function(character) {
1186
+ var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ),
1187
+ regex = new RegExp( "^" + escapedCharacter, "i" );
1188
+
1189
+ return this.activeMenu
1190
+ .find( this.options.items )
1191
+
1192
+ // Only match on items, not dividers or other content (#10571)
1193
+ .filter( ".ui-menu-item" )
1194
+ .filter(function() {
1195
+ return regex.test( $.trim( $( this ).text() ) );
1196
+ });
1197
+ }
1198
  });
1199
 
1200
 
1211
 
1212
 
1213
  var selectmenu = $.widget( "ui.selectmenu", {
1214
+ version: "1.11.2",
1215
+ defaultElement: "<select>",
1216
+ options: {
1217
+ appendTo: null,
1218
+ disabled: null,
1219
+ icons: {
1220
+ button: "ui-icon-triangle-1-s"
1221
+ },
1222
+ position: {
1223
+ my: "left top",
1224
+ at: "left bottom",
1225
+ collision: "none"
1226
+ },
1227
+ width: null,
1228
+
1229
+ // callbacks
1230
+ change: null,
1231
+ close: null,
1232
+ focus: null,
1233
+ open: null,
1234
+ select: null
1235
+ },
1236
+
1237
+ _create: function() {
1238
+ var selectmenuId = this.element.uniqueId().attr( "id" );
1239
+ this.ids = {
1240
+ element: selectmenuId,
1241
+ button: selectmenuId + "-button",
1242
+ menu: selectmenuId + "-menu"
1243
+ };
1244
+
1245
+ this._drawButton();
1246
+ this._drawMenu();
1247
+
1248
+ if ( this.options.disabled ) {
1249
+ this.disable();
1250
+ }
1251
+ },
1252
+
1253
+ _drawButton: function() {
1254
+ var that = this,
1255
+ tabindex = this.element.attr( "tabindex" );
1256
+
1257
+ // Associate existing label with the new button
1258
+ this.label = $( "label[for='" + this.ids.element + "']" ).attr( "for", this.ids.button );
1259
+ this._on( this.label, {
1260
+ click: function( event ) {
1261
+ this.button.focus();
1262
+ event.preventDefault();
1263
+ }
1264
+ });
1265
+
1266
+ // Hide original select element
1267
+ this.element.hide();
1268
+
1269
+ // Create button
1270
+ this.button = $( "<span>", {
1271
+ "class": "ui-selectmenu-button ui-widget ui-state-default ui-corner-all",
1272
+ tabindex: tabindex || this.options.disabled ? -1 : 0,
1273
+ id: this.ids.button,
1274
+ role: "combobox",
1275
+ "aria-expanded": "false",
1276
+ "aria-autocomplete": "list",
1277
+ "aria-owns": this.ids.menu,
1278
+ "aria-haspopup": "true"
1279
+ })
1280
+ .insertAfter( this.element );
1281
+
1282
+ $( "<span>", {
1283
+ "class": "ui-icon " + this.options.icons.button
1284
+ })
1285
+ .prependTo( this.button );
1286
+
1287
+ this.buttonText = $( "<span>", {
1288
+ "class": "ui-selectmenu-text"
1289
+ })
1290
+ .appendTo( this.button );
1291
+
1292
+ this._setText( this.buttonText, this.element.find( "option:selected" ).text() );
1293
+ this._resizeButton();
1294
+
1295
+ this._on( this.button, this._buttonEvents );
1296
+ this.button.one( "focusin", function() {
1297
+
1298
+ // Delay rendering the menu items until the button receives focus.
1299
+ // The menu may have already been rendered via a programmatic open.
1300
+ if ( !that.menuItems ) {
1301
+ that._refreshMenu();
1302
+ }
1303
+ });
1304
+ this._hoverable( this.button );
1305
+ this._focusable( this.button );
1306
+ },
1307
+
1308
+ _drawMenu: function() {
1309
+ var that = this;
1310
+
1311
+ // Create menu
1312
+ this.menu = $( "<ul>", {
1313
+ "aria-hidden": "true",
1314
+ "aria-labelledby": this.ids.button,
1315
+ id: this.ids.menu
1316
+ });
1317
+
1318
+ // Wrap menu
1319
+ this.menuWrap = $( "<div>", {
1320
+ "class": "ui-selectmenu-menu ui-front"
1321
+ })
1322
+ .append( this.menu )
1323
+ .appendTo( this._appendTo() );
1324
+
1325
+ // Initialize menu widget
1326
+ this.menuInstance = this.menu
1327
+ .menu({
1328
+ role: "listbox",
1329
+ select: function( event, ui ) {
1330
+ event.preventDefault();
1331
+
1332
+ // support: IE8
1333
+ // If the item was selected via a click, the text selection
1334
+ // will be destroyed in IE
1335
+ that._setSelection();
1336
+
1337
+ that._select( ui.item.data( "ui-selectmenu-item" ), event );
1338
+ },
1339
+ focus: function( event, ui ) {
1340
+ var item = ui.item.data( "ui-selectmenu-item" );
1341
+
1342
+ // Prevent inital focus from firing and check if its a newly focused item
1343
+ if ( that.focusIndex != null && item.index !== that.focusIndex ) {
1344
+ that._trigger( "focus", event, { item: item } );
1345
+ if ( !that.isOpen ) {
1346
+ that._select( item, event );
1347
+ }
1348
+ }
1349
+ that.focusIndex = item.index;
1350
+
1351
+ that.button.attr( "aria-activedescendant",
1352
+ that.menuItems.eq( item.index ).attr( "id" ) );
1353
+ }
1354
+ })
1355
+ .menu( "instance" );
1356
+
1357
+ // Adjust menu styles to dropdown
1358
+ this.menu
1359
+ .addClass( "ui-corner-bottom" )
1360
+ .removeClass( "ui-corner-all" );
1361
+
1362
+ // Don't close the menu on mouseleave
1363
+ this.menuInstance._off( this.menu, "mouseleave" );
1364
+
1365
+ // Cancel the menu's collapseAll on document click
1366
+ this.menuInstance._closeOnDocumentClick = function() {
1367
+ return false;
1368
+ };
1369
+
1370
+ // Selects often contain empty items, but never contain dividers
1371
+ this.menuInstance._isDivider = function() {
1372
+ return false;
1373
+ };
1374
+ },
1375
+
1376
+ refresh: function() {
1377
+ this._refreshMenu();
1378
+ this._setText( this.buttonText, this._getSelectedItem().text() );
1379
+ if ( !this.options.width ) {
1380
+ this._resizeButton();
1381
+ }
1382
+ },
1383
+
1384
+ _refreshMenu: function() {
1385
+ this.menu.empty();
1386
+
1387
+ var item,
1388
+ options = this.element.find( "option" );
1389
+
1390
+ if ( !options.length ) {
1391
+ return;
1392
+ }
1393
+
1394
+ this._parseOptions( options );
1395
+ this._renderMenu( this.menu, this.items );
1396
+
1397
+ this.menuInstance.refresh();
1398
+ this.menuItems = this.menu.find( "li" ).not( ".ui-selectmenu-optgroup" );
1399
+
1400
+ item = this._getSelectedItem();
1401
+
1402
+ // Update the menu to have the correct item focused
1403
+ this.menuInstance.focus( null, item );
1404
+ this._setAria( item.data( "ui-selectmenu-item" ) );
1405
+
1406
+ // Set disabled state
1407
+ this._setOption( "disabled", this.element.prop( "disabled" ) );
1408
+ },
1409
+
1410
+ open: function( event ) {
1411
+ if ( this.options.disabled ) {
1412
+ return;
1413
+ }
1414
+
1415
+ // If this is the first time the menu is being opened, render the items
1416
+ if ( !this.menuItems ) {
1417
+ this._refreshMenu();
1418
+ } else {
1419
+
1420
+ // Menu clears focus on close, reset focus to selected item
1421
+ this.menu.find( ".ui-state-focus" ).removeClass( "ui-state-focus" );
1422
+ this.menuInstance.focus( null, this._getSelectedItem() );
1423
+ }
1424
+
1425
+ this.isOpen = true;
1426
+ this._toggleAttr();
1427
+ this._resizeMenu();
1428
+ this._position();
1429
+
1430
+ this._on( this.document, this._documentClick );
1431
+
1432
+ this._trigger( "open", event );
1433
+ },
1434
+
1435
+ _position: function() {
1436
+ this.menuWrap.position( $.extend( { of: this.button }, this.options.position ) );
1437
+ },
1438
+
1439
+ close: function( event ) {
1440
+ if ( !this.isOpen ) {
1441
+ return;
1442
+ }
1443
+
1444
+ this.isOpen = false;
1445
+ this._toggleAttr();
1446
+
1447
+ this.range = null;
1448
+ this._off( this.document );
1449
+
1450
+ this._trigger( "close", event );
1451
+ },
1452
+
1453
+ widget: function() {
1454
+ return this.button;
1455
+ },
1456
+
1457
+ menuWidget: function() {
1458
+ return this.menu;
1459
+ },
1460
+
1461
+ _renderMenu: function( ul, items ) {
1462
+ var that = this,
1463
+ currentOptgroup = "";
1464
+
1465
+ $.each( items, function( index, item ) {
1466
+ if ( item.optgroup !== currentOptgroup ) {
1467
+ $( "<li>", {
1468
+ "class": "ui-selectmenu-optgroup ui-menu-divider" +
1469
+ ( item.element.parent( "optgroup" ).prop( "disabled" ) ?
1470
+ " ui-state-disabled" :
1471
+ "" ),
1472
+ text: item.optgroup
1473
+ })
1474
+ .appendTo( ul );
1475
+
1476
+ currentOptgroup = item.optgroup;
1477
+ }
1478
+
1479
+ that._renderItemData( ul, item );
1480
+ });
1481
+ },
1482
+
1483
+ _renderItemData: function( ul, item ) {
1484
+ return this._renderItem( ul, item ).data( "ui-selectmenu-item", item );
1485
+ },
1486
+
1487
+ _renderItem: function( ul, item ) {
1488
+ var li = $( "<li>" );
1489
+
1490
+ if ( item.disabled ) {
1491
+ li.addClass( "ui-state-disabled" );
1492
+ }
1493
+ this._setText( li, item.label );
1494
+
1495
+ return li.appendTo( ul );
1496
+ },
1497
+
1498
+ _setText: function( element, value ) {
1499
+ if ( value ) {
1500
+ element.text( value );
1501
+ } else {
1502
+ element.html( "&#160;" );
1503
+ }
1504
+ },
1505
+
1506
+ _move: function( direction, event ) {
1507
+ var item, next,
1508
+ filter = ".ui-menu-item";
1509
+
1510
+ if ( this.isOpen ) {
1511
+ item = this.menuItems.eq( this.focusIndex );
1512
+ } else {
1513
+ item = this.menuItems.eq( this.element[ 0 ].selectedIndex );
1514
+ filter += ":not(.ui-state-disabled)";
1515
+ }
1516
+
1517
+ if ( direction === "first" || direction === "last" ) {
1518
+ next = item[ direction === "first" ? "prevAll" : "nextAll" ]( filter ).eq( -1 );
1519
+ } else {
1520
+ next = item[ direction + "All" ]( filter ).eq( 0 );
1521
+ }
1522
+
1523
+ if ( next.length ) {
1524
+ this.menuInstance.focus( event, next );
1525
+ }
1526
+ },
1527
+
1528
+ _getSelectedItem: function() {
1529
+ return this.menuItems.eq( this.element[ 0 ].selectedIndex );
1530
+ },
1531
+
1532
+ _toggle: function( event ) {
1533
+ this[ this.isOpen ? "close" : "open" ]( event );
1534
+ },
1535
+
1536
+ _setSelection: function() {
1537
+ var selection;
1538
+
1539
+ if ( !this.range ) {
1540
+ return;
1541
+ }
1542
+
1543
+ if ( window.getSelection ) {
1544
+ selection = window.getSelection();
1545
+ selection.removeAllRanges();
1546
+ selection.addRange( this.range );
1547
+
1548
+ // support: IE8
1549
+ } else {
1550
+ this.range.select();
1551
+ }
1552
+
1553
+ // support: IE
1554
+ // Setting the text selection kills the button focus in IE, but
1555
+ // restoring the focus doesn't kill the selection.
1556
+ this.button.focus();
1557
+ },
1558
+
1559
+ _documentClick: {
1560
+ mousedown: function( event ) {
1561
+ if ( !this.isOpen ) {
1562
+ return;
1563
+ }
1564
+
1565
+ if ( !$( event.target ).closest( ".ui-selectmenu-menu, #" + this.ids.button ).length ) {
1566
+ this.close( event );
1567
+ }
1568
+ }
1569
+ },
1570
+
1571
+ _buttonEvents: {
1572
+
1573
+ // Prevent text selection from being reset when interacting with the selectmenu (#10144)
1574
+ mousedown: function() {
1575
+ var selection;
1576
+
1577
+ if ( window.getSelection ) {
1578
+ selection = window.getSelection();
1579
+ if ( selection.rangeCount ) {
1580
+ this.range = selection.getRangeAt( 0 );
1581
+ }
1582
+
1583
+ // support: IE8
1584
+ } else {
1585
+ this.range = document.selection.createRange();
1586
+ }
1587
+ },
1588
+
1589
+ click: function( event ) {
1590
+ this._setSelection();
1591
+ this._toggle( event );
1592
+ },
1593
+
1594
+ keydown: function( event ) {
1595
+ var preventDefault = true;
1596
+ switch ( event.keyCode ) {
1597
+ case $.ui.keyCode.TAB:
1598
+ case $.ui.keyCode.ESCAPE:
1599
+ this.close( event );
1600
+ preventDefault = false;
1601
+ break;
1602
+ case $.ui.keyCode.ENTER:
1603
+ if ( this.isOpen ) {
1604
+ this._selectFocusedItem( event );
1605
+ }
1606
+ break;
1607
+ case $.ui.keyCode.UP:
1608
+ if ( event.altKey ) {
1609
+ this._toggle( event );
1610
+ } else {
1611
+ this._move( "prev", event );
1612
+ }
1613
+ break;
1614
+ case $.ui.keyCode.DOWN:
1615
+ if ( event.altKey ) {
1616
+ this._toggle( event );
1617
+ } else {
1618
+ this._move( "next", event );
1619
+ }
1620
+ break;
1621
+ case $.ui.keyCode.SPACE:
1622
+ if ( this.isOpen ) {
1623
+ this._selectFocusedItem( event );
1624
+ } else {
1625
+ this._toggle( event );
1626
+ }
1627
+ break;
1628
+ case $.ui.keyCode.LEFT:
1629
+ this._move( "prev", event );
1630
+ break;
1631
+ case $.ui.keyCode.RIGHT:
1632
+ this._move( "next", event );
1633
+ break;
1634
+ case $.ui.keyCode.HOME:
1635
+ case $.ui.keyCode.PAGE_UP:
1636
+ this._move( "first", event );
1637
+ break;
1638
+ case $.ui.keyCode.END:
1639
+ case $.ui.keyCode.PAGE_DOWN:
1640
+ this._move( "last", event );
1641
+ break;
1642
+ default:
1643
+ this.menu.trigger( event );
1644
+ preventDefault = false;
1645
+ }
1646
+
1647
+ if ( preventDefault ) {
1648
+ event.preventDefault();
1649
+ }
1650
+ }
1651
+ },
1652
+
1653
+ _selectFocusedItem: function( event ) {
1654
+ var item = this.menuItems.eq( this.focusIndex );
1655
+ if ( !item.hasClass( "ui-state-disabled" ) ) {
1656
+ this._select( item.data( "ui-selectmenu-item" ), event );
1657
+ }
1658
+ },
1659
+
1660
+ _select: function( item, event ) {
1661
+ var oldIndex = this.element[ 0 ].selectedIndex;
1662
+
1663
+ // Change native select element
1664
+ this.element[ 0 ].selectedIndex = item.index;
1665
+ this._setText( this.buttonText, item.label );
1666
+ this._setAria( item );
1667
+ this._trigger( "select", event, { item: item } );
1668
+
1669
+ if ( item.index !== oldIndex ) {
1670
+ this._trigger( "change", event, { item: item } );
1671
+ }
1672
+
1673
+ this.close( event );
1674
+ },
1675
+
1676
+ _setAria: function( item ) {
1677
+ var id = this.menuItems.eq( item.index ).attr( "id" );
1678
+
1679
+ this.button.attr({
1680
+ "aria-labelledby": id,
1681
+ "aria-activedescendant": id
1682
+ });
1683
+ this.menu.attr( "aria-activedescendant", id );
1684
+ },
1685
+
1686
+ _setOption: function( key, value ) {
1687
+ if ( key === "icons" ) {
1688
+ this.button.find( "span.ui-icon" )
1689
+ .removeClass( this.options.icons.button )
1690
+ .addClass( value.button );
1691
+ }
1692
+
1693
+ this._super( key, value );
1694
+
1695
+ if ( key === "appendTo" ) {
1696
+ this.menuWrap.appendTo( this._appendTo() );
1697
+ }
1698
+
1699
+ if ( key === "disabled" ) {
1700
+ this.menuInstance.option( "disabled", value );
1701
+ this.button
1702
+ .toggleClass( "ui-state-disabled", value )
1703
+ .attr( "aria-disabled", value );
1704
+
1705
+ this.element.prop( "disabled", value );
1706
+ if ( value ) {
1707
+ this.button.attr( "tabindex", -1 );
1708
+ this.close();
1709
+ } else {
1710
+ this.button.attr( "tabindex", 0 );
1711
+ }
1712
+ }
1713
+
1714
+ if ( key === "width" ) {
1715
+ this._resizeButton();
1716
+ }
1717
+ },
1718
+
1719
+ _appendTo: function() {
1720
+ var element = this.options.appendTo;
1721
+
1722
+ if ( element ) {
1723
+ element = element.jquery || element.nodeType ?
1724
+ $( element ) :
1725
+ this.document.find( element ).eq( 0 );
1726
+ }
1727
+
1728
+ if ( !element || !element[ 0 ] ) {
1729
+ element = this.element.closest( ".ui-front" );
1730
+ }
1731
+
1732
+ if ( !element.length ) {
1733
+ element = this.document[ 0 ].body;
1734
+ }
1735
+
1736
+ return element;
1737
+ },
1738
+
1739
+ _toggleAttr: function() {
1740
+ this.button
1741
+ .toggleClass( "ui-corner-top", this.isOpen )
1742
+ .toggleClass( "ui-corner-all", !this.isOpen )
1743
+ .attr( "aria-expanded", this.isOpen );
1744
+ this.menuWrap.toggleClass( "ui-selectmenu-open", this.isOpen );
1745
+ this.menu.attr( "aria-hidden", !this.isOpen );
1746
+ },
1747
+
1748
+ _resizeButton: function() {
1749
+ var width = this.options.width;
1750
+
1751
+ if ( !width ) {
1752
+ width = this.element.show().outerWidth();
1753
+ this.element.hide();
1754
+ }
1755
+
1756
+ this.button.outerWidth( width );
1757
+ },
1758
+
1759
+ _resizeMenu: function() {
1760
+ this.menu.outerWidth( Math.max(
1761
+ this.button.outerWidth(),
1762
+
1763
+ // support: IE10
1764
+ // IE10 wraps long text (possibly a rounding bug)
1765
+ // so we add 1px to avoid the wrapping
1766
+ this.menu.width( "" ).outerWidth() + 1
1767
+ ) );
1768
+ },
1769
+
1770
+ _getCreateOptions: function() {
1771
+ return { disabled: this.element.prop( "disabled" ) };
1772
+ },
1773
+
1774
+ _parseOptions: function( options ) {
1775
+ var data = [];
1776
+ options.each(function( index, item ) {
1777
+ var option = $( item ),
1778
+ optgroup = option.parent( "optgroup" );
1779
+ data.push({
1780
+ element: option,
1781
+ index: index,
1782
+ value: option.attr( "value" ),
1783
+ label: option.text(),
1784
+ optgroup: optgroup.attr( "label" ) || "",
1785
+ disabled: optgroup.prop( "disabled" ) || option.prop( "disabled" )
1786
+ });
1787
+ });
1788
+ this.items = data;
1789
+ },
1790
+
1791
+ _destroy: function() {
1792
+ this.menuWrap.remove();
1793
+ this.button.remove();
1794
+ this.element.show();
1795
+ this.element.removeUniqueId();
1796
+ this.label.attr( "for", this.ids.element );
1797
+ }
1798
  });
1799
 
1800
 
js/spectrum.js CHANGED
@@ -2,7 +2,7 @@
2
  // https://github.com/bgrins/spectrum
3
  // Author: Brian Grinstead
4
  // License: MIT
5
- // Modifications for CTC (c) 2015 LIlaea Media LLC
6
 
7
  (function (factory) {
8
  "use strict";
2
  // https://github.com/bgrins/spectrum
3
  // Author: Brian Grinstead
4
  // License: MIT
5
+ // Modifications for CTC (c) 2016 Lilaea Media LLC
6
 
7
  (function (factory) {
8
  "use strict";
lang/child-theme-configurator-de_DE.mo CHANGED
Binary file
lang/child-theme-configurator-de_DE.po CHANGED
@@ -1,376 +1,646 @@
1
- # Copyright (C) 2015 Child Theme Configurator
2
  # This file is distributed under the same license as the Child Theme Configurator package.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: Child Theme Configurator 1.7.8\n"
6
  "Report-Msgid-Bugs-To: http://wordpress.org/tag/child-theme-configurator\n"
7
- "POT-Creation-Date: 2015-09-24 16:44+0200\n"
 
 
 
 
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
11
- "PO-Revision-Date: 2015-09-25 11:09+0200\n"
12
- "Language-Team: \n"
13
- "X-Generator: Poedit 1.8.5\n"
14
- "Last-Translator: \n"
15
  "Plural-Forms: nplurals=2; plural=(n != 1);\n"
16
- "Language: de_DE\n"
17
 
18
- #. Plugin Name of the plugin/theme
19
- #: child-theme-configurator.php:78 child-theme-configurator.php:88
20
- #: includes/forms/main.php:23
21
- msgid "Child Theme Configurator"
22
- msgstr "Child Theme Configurator"
23
 
24
- #: child-theme-configurator.php:79 child-theme-configurator.php:89
25
- #: child-theme-configurator.php:99
26
- msgid "Child Themes"
27
- msgstr "Kind-Themen"
28
 
29
- #: child-theme-configurator.php:114
30
- msgid "Child Theme Configurator requires WordPress version %s or later."
31
- msgstr "Child Theme Configurator benötigt WordPress Version %s oder neuer."
32
 
33
- #: includes/class-ctc-ui.php:52
34
- msgid "A stylesheet link tag is hard-coded into the header template."
35
- msgstr "Ein Formatvorlage-Verknüpfungstag ist fix in das 'header template' codiert."
 
 
 
 
 
 
 
 
36
 
37
- #: includes/class-ctc-ui.php:53
38
- msgid "<code>wp_enqueue_style()</code> called from the header template."
39
- msgstr "<code>wp_enqueue_style()</code> aufgerufen vom 'header template'."
40
 
41
- #: includes/class-ctc-ui.php:55
42
  msgid ""
43
- "Code exists between the <code>wp_head()</code> function and the closing <code>&lt;/"
44
- "head&gt;</code> tag."
45
  msgstr ""
46
- "Code existiert zwischen der <code>wp_head()</code> Funktion und dem schließenden "
47
- "<code>&lt;/head&gt;</code> Tag."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
 
49
- #: includes/class-ctc-ui.php:162
 
 
 
 
 
 
 
 
50
  msgid "Child Theme files modified successfully."
51
- msgstr "Kind-Thema-Dateien erfolgreich geändert."
52
 
53
- #: includes/class-ctc-ui.php:165
54
  msgid ""
55
- "Child Theme <strong>%s</strong> has been generated successfully.\n"
56
- " "
57
  msgstr ""
58
- "Kind-Thema <strong>%s</strong> wurde erfolgreich erstellt.\n"
59
- " "
60
 
61
- #: includes/class-ctc-ui.php:168
 
 
 
 
62
  msgid "IMPORTANT:"
63
  msgstr "WICHTIG:"
64
 
65
- #: includes/class-ctc-ui.php:170 includes/forms/themepreview.php:20
66
  msgid "Go to Themes"
67
  msgstr "Gehe zu Themen"
68
 
69
- #: includes/class-ctc-ui.php:170
70
  msgid "Network enable"
71
- msgstr "Netzwerk-aktivieren"
72
 
73
- #: includes/class-ctc-ui.php:170
74
  msgid "your child theme."
75
- msgstr "Ihr Kind-Thema."
76
 
77
- #: includes/class-ctc-ui.php:172 includes/forms/themepreview.php:18
78
  msgid "Live Preview"
79
  msgstr "Live-Vorschau"
80
 
81
- #: includes/class-ctc-ui.php:172
82
- msgid "Test your child theme"
83
- msgstr "Testen Sie Ihr Kind-Thema"
84
 
85
- #: includes/class-ctc-ui.php:172
86
  msgid "before activating."
87
  msgstr "vor der Aktivierung."
88
 
89
- #: includes/class-ctc.php:144
90
  msgid "URL/None"
91
- msgstr "URL/Kein(e)"
92
 
93
- #: includes/class-ctc.php:145
94
  msgid "Origin"
95
  msgstr "Quelle"
96
 
97
- #: includes/class-ctc.php:146
98
  msgid "Color 1"
99
  msgstr "Farbe 1"
100
 
101
- #: includes/class-ctc.php:147
102
  msgid "Color 2"
103
  msgstr "Farbe 2"
104
 
105
- #: includes/class-ctc.php:148
106
  msgid "Width/None"
107
  msgstr "Breite/Keine"
108
 
109
- #: includes/class-ctc.php:149
110
  msgid "Style"
111
  msgstr "Stil"
112
 
113
- #: includes/class-ctc.php:150
114
  msgid "Color"
115
  msgstr "Farbe"
116
 
117
- #: includes/class-ctc.php:152
118
- msgid "Are you sure? This will replace your current settings."
119
- msgstr "Sind Sie sicher? Dies überschreibt alle aktuellen Einstellungen."
 
 
 
 
120
 
121
- #: includes/class-ctc.php:153
122
  msgid "<span style=\"font-size:10px\">!</span>"
123
  msgstr "<span style=\"font-size:10px\">!</span>"
124
 
125
- #: includes/class-ctc.php:154 includes/forms/rule-value.php:32
126
  msgid "Selectors"
127
  msgstr "Selektoren"
128
 
129
- #: includes/class-ctc.php:155
130
  msgid "Close"
131
  msgstr "Schließen"
132
 
133
- #: includes/class-ctc.php:156
134
  msgid "Edit Selector"
135
- msgstr "Selektor bearbeiten"
136
 
137
- #: includes/class-ctc.php:157
138
  msgid "Cancel"
139
  msgstr "Abbrechen"
140
 
141
- #: includes/class-ctc.php:158
142
  msgid "Rename"
143
- msgstr "Umbenennen"
144
 
145
- #: includes/class-ctc.php:159
146
  msgid "The stylesheet cannot be displayed."
147
  msgstr "Die Formatvorlage kann nicht angezeigt werden."
148
 
149
- #: includes/class-ctc.php:160
150
  msgid "(Child Only)"
151
  msgstr "(Nur Kind)"
152
 
153
- #: includes/class-ctc.php:161
154
  msgid "Please enter a valid Child Theme."
155
- msgstr "Bitte ein gültiges Kind-Thema eingeben."
156
 
157
- #: includes/class-ctc.php:162
158
  msgid "Please enter a valid Child Theme name."
159
- msgstr "Bitte einen gültigen Namen eines Kind-Themes eingeben."
160
 
161
- #: includes/class-ctc.php:163
162
  msgid "<strong>%s</strong> exists. Please enter a different Child Theme"
163
- msgstr "<strong>%s</strong> existiert. Bitte anderes Kind-Thema eingeben"
164
 
165
- #: includes/class-ctc.php:164
166
  msgid "The page could not be loaded correctly."
167
  msgstr "Die Seite konnte nicht korrekt geladen werden."
168
 
169
- #: includes/class-ctc.php:166
170
- msgid "Conflicting or out-of-date jQuery libraries were loaded by another plugin:"
 
171
  msgstr ""
172
- "Nicht mehr aktuelle oder in Konflikt stehende jQuery-Bibliotheken von anderem Plugin "
173
- "geladen:"
174
 
175
- #: includes/class-ctc.php:168
176
  msgid "Deactivating or replacing plugins may resolve this issue."
177
- msgstr "Das Deaktivieren oder Ersetzen des Plugins könnte dieses Problem lösen."
178
 
179
- #: includes/class-ctc.php:169
180
  msgid "%sWhy am I seeing this?%s"
181
  msgstr "%sWieso sehe ich das?%s"
182
 
183
- #: includes/class-ctc.php:392
184
- msgid "Zip file creation failed."
185
- msgstr "ZIP-Dateierstellung fehlgeschlagen."
186
 
187
- #: includes/class-ctc.php:428
188
- msgid "The Functions file is required and cannot be deleted."
189
- msgstr "Die Funktionen-Datei wird benötigt und kann nicht entfernt werden."
190
 
191
- #: includes/class-ctc.php:510
192
- msgid "You do not have permission to configure child themes."
193
- msgstr "Sie haben nicht die Berechtigung zur Konfiguration von Kind-Themen."
194
 
195
- #: includes/class-ctc.php:557
196
- msgid "%s does not exist. Please select a valid Parent Theme."
197
- msgstr "%s existiert nicht. Bitte wählen Sie ein gültiges Eltern-Theme."
198
 
199
- #: includes/class-ctc.php:561
200
- msgid "Please select a valid Parent Theme."
201
- msgstr "Bitte wählen Sie ein gültiges Eltern-Theme."
202
 
203
- #: includes/class-ctc.php:564
204
- msgid "Please enter a valid Child Theme directory."
205
- msgstr "Bitte geben Sie ein gültiges Kind-Thema-Verzeichnis ein."
206
 
207
- #: includes/class-ctc.php:572 includes/class-ctc.php:587
208
- msgid "Please enter a valid Child Theme template name."
209
- msgstr "Bitte geben Sie eine gültige Kind-Thema-Vorlagennamen ein."
210
 
211
- #: includes/class-ctc.php:577 includes/class-ctc.php:591
212
- msgid "<strong>%s</strong> exists. Please enter a different Child Theme template name."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
213
  msgstr ""
214
- "<strong>%s</strong> existiert. Bitte einen anderen Kind-Thema-Vorlagennamen eingeben."
 
 
215
 
216
- #: includes/class-ctc.php:604
217
- msgid "Your theme directories are not writable."
218
- msgstr "Ihr Theme-Verzeichnis ist schreibgeschützt."
 
 
 
 
219
 
220
- #: includes/class-ctc.php:682
221
- msgid "Your stylesheet is not writable."
222
- msgstr "Ihre Formatvorlage kann nicht überschrieben werden."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
223
 
224
- #: includes/class-ctc.php:959
225
  msgid ""
226
- "A closing PHP tag was detected in Child theme functions file so \"Parent Stylesheet "
227
- "Handling\" option was not configured. Closing PHP at the end of the file is discouraged "
228
- "as it can cause premature HTTP headers. Please edit <code>functions.php</code> to "
229
- "remove the final <code>?&gt;</code> tag and click \"Generate/Rebuild Child Theme Files"
230
- "\" again."
231
  msgstr ""
232
- "Ein schließendes PHP-Tag wurde in der Kind-Thema Funktions-Datei gefunden, die \"Eltern "
233
- "Formatvorlage-Behandlung\"-Option wurde nicht konfiguriert. Schließendes PHP am Ende "
234
- "der Datei ist nicht empfohlen, da es zu frühe HTTP-Header verursachen kann. Bitte "
235
- "bearbeiten Sie <code>functions.php</code> um den abschließenden <code>?&gt;</code> Tag "
236
- "zu entfernen und klicken Sie erneut auf \"Erzeugen/Neuaufbauen Kind-Thema-Dateien\"."
237
 
238
- #: includes/class-ctc.php:1060
239
- msgid "Could not delete file."
240
- msgstr "Konnte Dateien nicht löschen."
 
 
 
 
241
 
242
- #: includes/class-ctc.php:1139
243
- msgid "Could not set write permissions."
244
- msgstr "Konnte Schreibberechtigung nicht setzen."
245
 
246
- #: includes/class-ctc.php:1240
247
- msgid "There were errors while resetting permissions."
248
- msgstr "Es traten beim Zurücksetzen der Berechtigungen Fehler auf."
249
 
250
- #: includes/class-ctc.php:1282
251
- msgid "Could not upload file."
252
- msgstr "Konnte Datei nicht hochladen."
253
 
254
- #: includes/class-ctc.php:1365
255
  msgid ""
256
- "The child theme is in read-only mode and Child Theme Configurator cannot apply changes. "
257
- "Click to see options"
 
 
258
  msgstr ""
259
- "Das Kind-Thema ist im Nur-Lese-Modus und der Child Theme Configurator kann die "
260
- "Änderungen nicht anwenden. Klicken Sie für Optionen"
 
 
261
 
262
- #: includes/class-ctc.php:1368
263
  msgid ""
264
- "<li>Temporarily set write permissions by clicking the button below. When you are "
265
- "finished editing, revert to read-only by clicking \"Make read-only\" under the \"Files"
266
- "\" tab.</li>"
267
  msgstr ""
268
- "<li>Schreibberechtigung vorübergehend setzen mittels Klicken auf die untenstehende "
269
- "Schaltfläche. Wenn Sie die Bearbeitung beendet haben, wieder auf \"Nur-Lesen-Modus\" "
270
- "zurück mittels Klicken auf \"Nur-Lesen setzen\" auf dem \"Dateien\"-Reiter.</li>"
271
 
272
- #: includes/class-ctc.php:1371
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
273
  msgid "Make files writable"
274
- msgstr "Mache Dateien schreibbar"
275
 
276
- #: includes/class-ctc.php:1372
277
  msgid ""
278
- "<li><a target=\"_blank\" href=\"http://codex.wordpress.org/Editing_wp-config."
279
- "php#WordPress_Upgrade_Constants\" title=\"Editin wp-config.php\">Add your FTP/SSH "
280
- "credentials to the WordPress config file</a>.</li>"
281
  msgstr ""
282
- "<li><a target=\"_blank\" href=\"http://codex.wordpress.org/Editing_wp-config."
283
- "php#WordPress_Upgrade_Constants\" title=\"Editin wp-config.php\">Hinzufügen von FTP/SSH-"
284
- "Berechtigungen zur Wordpress-Konfigurationsdatei</a>.</li>"
285
 
286
- #: includes/class-ctc.php:1374
287
  msgid ""
288
- "<li><a target=\"_blank\" href=\"http://technet.microsoft.com/en-us/library/cc771170\" "
289
- "title=\"Setting Application Pool Identity\">Assign WordPress to an application pool "
290
- "that has write permissions</a> (Windows IIS systems).</li>"
 
291
  msgstr ""
292
- "<li><a target=\"_blank\" href=\"http://technet.microsoft.com/en-us/library/cc771170\" "
293
- "title=\"Setting Application Pool Identity\">WordPress zu einem Applikations-Pool mit "
294
- "Schreibberechtigung zuweisen</a> (Windows IIS-Systeme).</li>"
 
295
 
296
- #: includes/class-ctc.php:1375
297
  msgid ""
298
- "<li><a target=\"_blank\" href=\"http://codex.wordpress.org/Changing_File_Permissions\" "
299
- "title=\"Changing File Permissions\">Set write permissions on the server manually</a> "
300
- "(not recommended).</li>"
301
  msgstr ""
302
- "<li><a target=\"_blank\" href=\"http://codex.wordpress.org/Changing_File_Permissions\" "
303
- "title=\"Changing File Permissions\">Auf einem Server Schreibberechtigung manuell "
304
- "setzen</a> (nicht empfohlen).</li>"
305
 
306
- #: includes/class-ctc.php:1377
307
  msgid "<li>Run PHP under Apache with suEXEC (contact your web host).</li>"
308
- msgstr "<li>PHP unter Apache mit suEXEC ausführen (bitte Webprovider kontaktieren).</li>"
 
 
309
 
310
- #: includes/class-ctc.php:1388
311
  msgid ""
312
- "This Child Theme is not owned by your website account. It may have been created by a "
313
- "prior version of this plugin or by another program. Moving forward, it must be owned by "
314
- "your website account to make changes. Child Theme Configurator will attempt to correct "
315
- "this when you click the button below."
 
316
  msgstr ""
317
- "Dieses Kind-Thema ist nicht im Besitz Ihres Webseiten-Kontos. Es könnte von einer "
318
- "älteren Version dieses Plugins oder einem anderen Programm erstellt worden sein. Um "
319
- "fortzufahren, muss es im Besitz Ihrer Webseite sein, um Änderungen vorzunehmen. Child "
320
- "Theme Configurator versucht dies zu korrigieren, wenn Sie auf den Knopf unten klicken."
 
321
 
322
- #: includes/class-ctc.php:1391
323
- msgid "Correct Child Theme Permissions"
324
- msgstr "Kind-Thema-Berechtigungen korrigieren"
 
 
 
 
 
 
325
 
326
- #: includes/class-ctc.php:1398
327
  msgid ""
328
- "Child Theme Configurator needs to update its interal data. Please set your preferences "
329
- "below and click \"Generate Child Theme Files\" to update your configuration."
 
330
  msgstr ""
331
- "Child Theme Configurator muss seine internen Daten aktualisieren. Bitte setzen Sie "
332
- "unten Ihre Voreinstellungen und klicken Sie auf \"Erzeugen Kind-Thema-Dateien\", um "
333
- "Ihre Konfiguration zu aktualisieren."
 
334
 
335
- #: includes/class-ctc.php:1404
336
  msgid ""
337
- "<strong>However, some styles could not be parsed due to memory limits.</strong> Try "
338
- "deselecting \"Additional Stylesheets\" below and click \"Generate/Rebuild Child Theme "
339
- "Files\". %sWhy am I seeing this?%s"
340
  msgstr ""
341
- "<strong>Allerdings konnten einige Stile wegen Speicherlimiten nicht ausgelesen werden</"
342
- "strong> Versuchen Sie es mit der Deaktivierung von \"Zusätzliche Formatvorlagen\" unten "
343
- "und klicken Sie auf \"Erstellen/Neuaufbau Kind-Thema-Dateien\". %sWieso sehe ich das?%s"
344
 
345
- #: includes/class-ctc.php:1413
346
  msgid ""
347
- "Child Theme Configurator did not detect any configuration data because a previously "
348
- "configured Child Theme has been removed. Please set your preferences below and click "
349
- "\"Generate Child Theme Files\"."
350
  msgstr ""
351
- "Child Theme Configurator entdeckte keine Konfigurationsdaten, weil ein vorher "
352
- "konfiguriertes Kind-Thema entfernt wurde. Bitte setzen Sie Ihre Voreinstellungen unten "
353
- "und klicken Sie auf \"Erstellen Kind-Thema-Dateien\"."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
354
 
355
  #: includes/forms/addl_css.php:7
356
  msgid "Parse additional stylesheets:"
357
- msgstr "Zusätzliche Formatvorlagen auslesen:"
358
 
359
- #: includes/forms/addl_css.php:11 includes/forms/parent-child.php:270
360
  msgid ""
361
- "Stylesheets that are currently being loaded by the parent theme are automatically "
362
- "selected below (except for Bootstrap stylesheets which add a large amount data to the "
363
- "configuration). To further reduce overhead, select only the additional stylesheets you "
364
- "wish to customize."
365
  msgstr ""
366
- "Formatvorlagen, die zurzeit vom Eltern-Theme geladen werden, sind unten automatisch "
367
- "ausgewählt (ausgenommen für Bootstrap-Formatvorlagen welche eine große Datenmenge zur "
368
- "Konfiguration hinzufügen). Um weitere Überlastung zu vermindern, wählen Sie nur "
369
- "Formatvorlagen, die Sie anpassen wollen."
370
 
371
  #: includes/forms/addl_panels.php:9 includes/forms/addl_panels.php:39
372
  msgid "Use coupon code"
373
- msgstr "Coupon-Code benutzen"
374
 
375
  #: includes/forms/addl_panels.php:9 includes/forms/addl_panels.php:39
376
  msgid "wordpress-org"
@@ -378,7 +648,7 @@ msgstr "wordpress-org"
378
 
379
  #: includes/forms/addl_panels.php:9 includes/forms/addl_panels.php:39
380
  msgid "and get <strong>20% off entire order</strong>."
381
- msgstr "und erhalte <strong>20% Rabatt auf die ganze Bestellung</strong>."
382
 
383
  #: includes/forms/addl_panels.php:10 includes/forms/addl_panels.php:40
384
  msgid "Order Now"
@@ -386,22 +656,23 @@ msgstr "Jetzt bestellen"
386
 
387
  #: includes/forms/addl_panels.php:10 includes/forms/addl_panels.php:40
388
  msgid "*Prices and offers subject to change."
389
- msgstr "*Preise und Angebote ohne Gewähr."
390
 
391
  #: includes/forms/addl_panels.php:11 includes/forms/addl_panels.php:12
392
  msgid "Learn more about IntelliWidget"
393
- msgstr "Erfahren Sie mehr über IntelliWidget"
394
 
395
  #: includes/forms/addl_panels.php:12
396
  msgid ""
397
- "IntelliWidget is a versatile widget manager that does the work of multiple plugins by "
398
- "combining custom page menus, featured posts, sliders and other dynamic content features "
399
- "into a single plugin that can display on a per-page or site-wide basis."
 
400
  msgstr ""
401
- "IntelliWidget ist ein ausgefeilter Widget-Manager, der die Arbeit vieler Plugins "
402
- "erledigt, indem es Seitenmenüs, Beliebte Beiträge (Featured Posts), Slider und anderen "
403
- "dynamischen Inhalt in ein einzelnes Plugin kombiniert, welches die Anzeige auf Seiten- "
404
- "oder Webseiten-Basis ermöglicht."
405
 
406
  #: includes/forms/addl_panels.php:13 includes/forms/addl_panels.php:16
407
  msgid "Learn more"
@@ -413,42 +684,43 @@ msgstr "Mehr über IW Responsive Menu erfahren"
413
 
414
  #: includes/forms/addl_panels.php:15
415
  msgid ""
416
- "IntelliWidget Responsive Menu lets you break free from your theme’s built-in responsive "
417
- "menu options and gives you complete control over the user experience."
 
418
  msgstr ""
419
- "IntelliWidget Responsive Menu ermöglicht Ihnen das Ausbrechen aus den starren, "
420
- "eingebauten Theme-Menüoptionen und gibt Ihnen vollständige Kontrolle über die "
421
- "Nutzererfahrung."
422
 
423
- #: includes/forms/addl_panels.php:19 includes/help/help_en_US.php:215
424
  msgid "Learn more about CTC Pro"
425
  msgstr "Mehr über CTC Pro erfahren"
426
 
427
  #: includes/forms/addl_panels.php:20
428
  msgid "Customizing WordPress just got even easier."
429
- msgstr "Es ist jetzt noch einfacher, WordPress anzupassen."
430
 
431
  #: includes/forms/addl_panels.php:21
432
  msgid ""
433
- "Thousands of users have already seen the benefits of using Child Theme Configurator. If "
434
- "you spend any amount of time customizing WordPress, CTC Pro will help maximize your "
435
- "productivity."
436
  msgstr ""
437
- "Tausende Benutzer haben schon die Vorteile des Child Theme Configurator erkannt. Wenn "
438
- "Sie Zeit für die Anpassung von WordPress aufwenden, wird CTC Pro Ihre Produktivität "
439
- "maximieren."
440
 
441
  #: includes/forms/addl_panels.php:22
442
  msgid "Designed by Developers Who Use It Every Day."
443
- msgstr "Entworfen von Entwicklern, die es täglich verwenden."
444
 
445
  #: includes/forms/addl_panels.php:23
446
  msgid ""
447
- "We've packed in more features to make design work quicker and easier with <strong>Child "
448
- "Theme Configurator Pro.</strong>"
449
  msgstr ""
450
- "Wir haben noch mehr Funktionen hineingepackt, um die Entwurfs-Arbeit noch schneller und "
451
- "einfacher zu gestalten mit <strong>Child Theme Configurator Pro.<strong>"
452
 
453
  #: includes/forms/addl_panels.php:25
454
  msgid "Customize Plugin Stylesheets"
@@ -456,20 +728,20 @@ msgstr "Plugin-Formatvorlagen anpassen"
456
 
457
  #: includes/forms/addl_panels.php:26
458
  msgid ""
459
- "Apply the power of CTC's top-rated interface to your site's plugin styles. All new "
460
- "design makes it much easier to get the results you want."
461
  msgstr ""
462
- "Wende die Macht der ausgezeichnet bewerteten Schnittstelle von CTC für deine Plugin-"
463
- "Stile an. Alle neuen Designs machen es noch einfacher, die gewünschten Resultate zu "
464
- "erhalten."
465
 
466
  #: includes/forms/addl_panels.php:27
467
  msgid "Quick Preview"
468
- msgstr "Schnell-Vorschau"
469
 
470
  #: includes/forms/addl_panels.php:27
471
- msgid "Test your child theme with a single click."
472
- msgstr "Testen Sie Ihr Kind-Thema mit einem einzigen Klick."
473
 
474
  #: includes/forms/addl_panels.php:28
475
  msgid "Color Palettes"
@@ -477,21 +749,22 @@ msgstr "Farbpaletten"
477
 
478
  #: includes/forms/addl_panels.php:28
479
  msgid ""
480
- "Keep the colors you select just a click away. No more searching for hex codes and RGB "
481
- "values."
482
  msgstr ""
483
- "Behalten Sie die Farben nur einen Klick entfernt weg. Kein umständliches Suchen für Hex-"
484
- "Codes und RGB-Werte."
485
 
486
  #: includes/forms/addl_panels.php:29
487
  msgid "Find related styles"
488
- msgstr "Finde ähnliche Stile"
489
 
490
  #: includes/forms/addl_panels.php:29
491
  msgid ""
492
- "Use the \"All Styles\" panel to edit groups of selectors from a single combined list."
 
493
  msgstr ""
494
- "Nutzen Sie das \"Alle Stile\"-Bedienungsfeld, um Gruppen von Selektoren aus einer "
495
  "einzigen kombinierten Liste zu bearbeiten."
496
 
497
  #: includes/forms/addl_panels.php:30
@@ -500,7 +773,7 @@ msgstr "Finde Stile mittels Nav-Menü"
500
 
501
  #: includes/forms/addl_panels.php:30
502
  msgid "Tweak menus quickly and easily."
503
- msgstr "Passe Menüs schnell und einfach an."
504
 
505
  #: includes/forms/addl_panels.php:31
506
  msgid "Most recent edits"
@@ -509,7 +782,8 @@ msgstr "Letzte Bearbeitungen"
509
  #: includes/forms/addl_panels.php:31
510
  msgid "Return to recently edited selectors from a toggleable sidebar."
511
  msgstr ""
512
- "Zurückkehren zu kürzlich bearbeiteten Selektoren mittels umschaltbarer Seitenleiste."
 
513
 
514
  #: includes/forms/addl_panels.php:32
515
  msgid "Genesis Framework Support"
@@ -517,10 +791,11 @@ msgstr "Genesis Framework Support"
517
 
518
  #: includes/forms/addl_panels.php:33
519
  msgid ""
520
- "Automatically detects and configures Genesis Child Themes with more frameworks on the "
521
- "way."
522
  msgstr ""
523
- "Entdeckt und konfiguriert nebenbei automatisch Genesis Kind-Themen mit mehr Frameworks."
 
524
 
525
  #: includes/forms/addl_panels.php:34
526
  msgid "Top-rated Online Support"
@@ -532,28 +807,31 @@ msgstr "Online-Dokumentation"
532
 
533
  #: includes/forms/addl_panels.php:36
534
  msgid "Tutorial Videos"
535
- msgstr "Tutorial-Videos"
536
 
537
  #: includes/forms/addl_tabs.php:8
538
  msgid "Upgrade"
539
- msgstr "Aktualisieren"
540
 
541
  #: includes/forms/backup.php:8
542
  msgid "Backup"
543
- msgstr "Sicherung"
544
 
545
- #: includes/forms/backups.php:10 includes/forms/parent-child.php:253
546
  msgid "Restore backup from"
547
- msgstr "Sicherung wiederherstellen von"
548
 
549
  #: includes/forms/fileform.php:8
550
- msgid "The Theme editor has been disabled. Template files must be edited offline."
 
551
  msgstr ""
552
- "Der Themen-Editor wurde deaktiviert. Vorlagendateien müssen offline bearbeitet werden."
 
553
 
554
  #: includes/forms/fileform.php:12
555
  msgid "Click here to edit template files using the Theme Editor"
556
- msgstr "Hier klicken, um Vorlagendateien mit dem Themen-Editor zu bearbeiten"
 
557
 
558
  #: includes/forms/fileform.php:23
559
  msgid "Parent Templates"
@@ -561,44 +839,51 @@ msgstr "Eltern-Vorlagen"
561
 
562
  #: includes/forms/fileform.php:23
563
  msgid "Child Theme Files"
564
- msgstr "Kind-Thema-Dateien"
565
 
566
  #: includes/forms/fileform.php:28
567
- msgid "Copy PHP template files from the parent theme by selecting them here."
 
 
 
568
  msgstr ""
569
- "Kopieren von PHP-Vorlagendateien des Eltern-Themes, indem Sie diese hier auswählen."
 
 
 
570
 
571
  #: includes/forms/fileform.php:31
572
  msgid ""
573
- "CAUTION: If your child theme is active, the child theme version of the file will be "
574
- "used instead of the parent immediately after it is copied."
575
  msgstr ""
576
- "ACHTUNG: Wenn Ihr Kind-Thema aktiv ist, wird nach dem Kopiervorgang sofort die Kind-"
577
- "Thema-Version der Datei anstatt der Eltern-Datei benutzt."
578
 
579
  #: includes/forms/fileform.php:33
580
  msgid "The %s file is generated separately and cannot be copied here."
581
- msgstr "Die %s Datei wird getrennt erstellt und kann nicht hierher kopiert werden."
582
 
583
  #: includes/forms/fileform.php:43
584
  msgid "Delete child theme templates by selecting them here."
585
- msgstr "Löschen von Kind-Thema-Vorlagen, indem Sie sie hier auswählen."
586
 
587
  #: includes/forms/fileform.php:44
588
  msgid ""
589
- "Delete child theme templates or make them writable by selecting them here. Writable "
590
- "files are displayed in <span style=\"color:red\">red</span>."
591
  msgstr ""
592
- "Löschen Sie Kind-Thema-Vorlagen oder setzen Sie sie schreibbar, indem Sie sie hier "
593
- "auswählen. Schreibbare Dateien sind in <span style=\"color:red\">red</span> angezeigt."
 
594
 
595
  #: includes/forms/fileform.php:57
596
  msgid "Make Selected Writable"
597
- msgstr "Auswahl schreibbar setzen"
598
 
599
  #: includes/forms/fileform.php:61
600
  msgid "Copy Selected to Child Theme"
601
- msgstr "Ausgewähltes Kind-Thema kopieren"
602
 
603
  #: includes/forms/fileform.php:61 includes/forms/images.php:21
604
  msgid "Delete Selected"
@@ -606,15 +891,16 @@ msgstr "Auswahl löschen"
606
 
607
  #: includes/forms/files.php:15
608
  msgid "Upload New Child Theme Image"
609
- msgstr "Neues Kind-Thema-Bild hochladen"
610
 
611
  #: includes/forms/files.php:18
612
  msgid ""
613
- "Theme images reside under the <code>images</code> directory in your child theme and are "
614
- "meant for stylesheet use only. Use the Media Library for content images."
 
615
  msgstr ""
616
- "Diese Bilder befinden sich unter dem <code>Images</code>-Verzeichnis in Ihrem Kind-"
617
- "Thema-Verzeichnis und sind nur für Formatvorlagen vorgesehen. Benutzen Sie die "
618
  "Medienbibliothek für Inhaltsbilder."
619
 
620
  #: includes/forms/files.php:25 includes/forms/files.php:51
@@ -623,311 +909,390 @@ msgstr "Hochladen"
623
 
624
  #: includes/forms/files.php:32
625
  msgid "Child Theme Screenshot"
626
- msgstr "Kind-Thema Screenshot"
627
 
628
  #: includes/forms/files.php:41
629
  msgid "Upload New Screenshot"
630
- msgstr "Neuen Screenshot hochladen"
631
 
632
  #: includes/forms/files.php:44
633
  msgid ""
634
- "The theme screenshot should be a 4:3 ratio (e.g., 880px x 660px) JPG, PNG or GIF. It "
635
- "will be renamed <code>screenshot</code>."
636
  msgstr ""
637
- "Der Theme-Screenshot sollte ein 4:3-Verhältnis aufweisen (z.Bsp, 880px x 660px) JPG, "
638
- "PNG oder GIF. Es wird in <code>screenshot</code> umbenannt."
639
 
640
- #: includes/forms/files.php:59
641
  msgid "Export Child Theme as Zip Archive"
642
- msgstr "Kind-Thema als ZIP-Archiv exportieren"
643
-
644
- #: includes/forms/files.php:64
645
- msgid "Export"
646
- msgstr "Export"
647
 
648
- #: includes/forms/files.php:73
649
  msgid "Secure Child Theme"
650
- msgstr "Kind-Thema sichern"
651
 
652
- #: includes/forms/files.php:76
653
- msgid "Attempt to reset child theme permissions to user ownership and read-only access."
 
 
654
  msgstr ""
655
- "Versuchen Sie, die Kind-Thema-Berechtigungen auf Besitz und Lese-Modus-Zugriff "
656
- "zurückzusetzen."
657
 
658
- #: includes/forms/files.php:82
659
  msgid "Make read-only"
660
- msgstr "Nur-Lesen setzen"
661
 
662
  #: includes/forms/images.php:10
663
  msgid "Child Theme Images"
664
- msgstr "Kind-Thema-Bilder"
665
 
666
  #: includes/forms/images.php:13
667
  msgid "Delete child theme images by selecting them here."
668
- msgstr "Löschen Sie Kind-Thema-Bilder, indem Sie sie hier auswählen."
669
 
670
- #: includes/forms/main.php:23
671
  msgid "version"
672
- msgstr "version"
673
 
674
- #: includes/forms/parent-child.php:17
675
- msgid "Parent Theme"
676
- msgstr "Eltern-Theme"
677
 
678
- #: includes/forms/parent-child.php:25
679
- msgid "Child Theme"
680
- msgstr "Kind-Thema"
681
 
682
- #: includes/forms/parent-child.php:27
683
- msgid "(click to edit additional fields)"
684
- msgstr "(klicken, um mehr Felder zu bearbeiten)"
685
 
686
- #: includes/forms/parent-child.php:34
687
- msgid "Create New Child Theme"
688
- msgstr "Neues Kind-Thema erstellen"
 
 
 
 
 
 
 
689
 
690
  #: includes/forms/parent-child.php:43
691
- msgid "Use Existing Child Theme"
692
- msgstr "Bestehendes Kind-Thema benutzen"
693
 
694
- #: includes/forms/parent-child.php:48
695
- msgid "New Child Theme Slug"
696
- msgstr "Neuer Kind-Thema-Slug"
 
 
 
 
697
 
698
- #: includes/forms/parent-child.php:59
699
- msgid "Child Theme Name"
700
- msgstr "Kind-Thema-Name"
701
 
702
- #: includes/forms/parent-child.php:63
703
- msgid "Theme Name"
704
- msgstr "Themen-Name"
 
 
 
 
 
 
 
705
 
706
- #: includes/forms/parent-child.php:66 includes/forms/parent-child.php:70
707
- msgid "Theme Website"
708
- msgstr "Themen-Webseite"
 
 
 
 
709
 
710
- #: includes/forms/parent-child.php:73 includes/forms/parent-child.php:77
711
- msgid "Author"
712
- msgstr "Autor"
 
 
 
 
 
 
 
713
 
714
- #: includes/forms/parent-child.php:81 includes/forms/parent-child.php:85
715
- msgid "Author Website"
716
- msgstr "Autor-Webseite"
717
 
718
- #: includes/forms/parent-child.php:88
719
- msgid "Theme Description"
720
- msgstr "Themen-Beschreibung"
721
 
722
- #: includes/forms/parent-child.php:91
723
- msgid "Description"
724
- msgstr "Beschreibung"
725
 
726
- #: includes/forms/parent-child.php:94
727
- msgid "Theme Tags"
728
- msgstr "Themen-Schlagwörter"
 
 
 
 
729
 
730
- #: includes/forms/parent-child.php:97
731
- msgid "Tags"
732
- msgstr "Schlagwörter"
733
 
734
- #: includes/forms/parent-child.php:100 includes/forms/parent-child.php:104
735
- msgid "Version"
736
- msgstr "Version"
737
 
738
- #: includes/forms/parent-child.php:109
739
- msgid "Duplicate Existing Child Theme"
740
- msgstr "Bestehendes Kind-Thema duplizieren"
741
 
742
- #: includes/forms/parent-child.php:115
743
- msgid "Duplicate Theme Slug"
744
- msgstr "Themen-Slug duplizieren"
745
 
746
- #: includes/forms/parent-child.php:118 includes/forms/parent-child.php:212
747
- #: includes/forms/parent-child.php:227
748
  msgid "NOTE:"
749
  msgstr "HINWEIS:"
750
 
751
- #: includes/forms/parent-child.php:120
752
- msgid "This will copy all child theme files and apply changes to new version."
 
 
753
  msgstr ""
754
- "Dies kopiert alle Dateien des Kind-Themas und wendet bei der neuen Version die "
755
- "Änderungen an."
756
 
757
- #: includes/forms/parent-child.php:126
758
- msgid "Debug"
759
- msgstr "Fehlerverfolgung"
760
-
761
- #: includes/forms/parent-child.php:134
762
- msgid "Check the box to enable debugging output."
763
- msgstr "Kästchen auswählen, um Fehlerverfolgung-Ausgabe zu aktivieren."
764
-
765
- #: includes/forms/parent-child.php:141
766
- msgid "Stylesheet handling"
767
- msgstr "Formatvorlage-Behandlung"
768
-
769
- #: includes/forms/parent-child.php:142
770
- msgid "(click to view options)"
771
- msgstr "(klicken für Optionen)"
772
 
773
- #: includes/forms/parent-child.php:144
774
- msgid "This theme may not apply child theme styles correctly with the current settings:"
 
 
775
  msgstr ""
776
- "Dieses Thema wird die Kind-Thema-Stile eventuell nicht richtig anwenden (mit den "
777
- "aktuellen Einstellungen):"
778
 
779
- #: includes/forms/parent-child.php:146
780
- msgid "Don't show again."
781
- msgstr "Nicht mehr anzeigen."
782
 
783
- #: includes/forms/parent-child.php:146
784
- msgid "View options"
785
- msgstr "Optionen anzeigen"
786
 
787
- #: includes/forms/parent-child.php:149
788
- msgid "Which option should I use?"
789
- msgstr "Welche Option soll ich benutzen?"
790
 
791
- #: includes/forms/parent-child.php:154
792
- msgid "None (handled by theme)"
793
- msgstr "Keine (vom Thema abgewickelt)"
794
-
795
- #: includes/forms/parent-child.php:158
796
  msgid ""
797
- "Select this option if all stylesheets are correctly enqueued for child themes. If you "
798
- "find that styles are not being applied correctly, use a different option."
 
799
  msgstr ""
800
- "Diese Option auswählen, wenn alle Formatvorlagen richtig eingebunden (enqueued) werden. "
801
- "Sollten die Stile nicht richtig angewendet werden, benutzen Sie eine andere Option."
 
802
 
803
- #: includes/forms/parent-child.php:165
804
- msgid "Enqueue parent stylesheet (default)"
805
- msgstr "Eltern-Formatvorlage einbinden (Standard)"
806
 
807
- #: includes/forms/parent-child.php:168
808
  msgid ""
809
- "Select this option if the theme enqueues the active stylesheet but has no special "
810
- "handling for child themes. Start with this option if unsure."
 
 
811
  msgstr ""
812
- "Diese Option auswählen, wenn das Thema die aktive Formatvorlage einbindet (enqueued), "
813
- "aber keine Sonderbehandlung für Kind-Themen hat. Bei Unsicherheit mit dieser Option "
814
- "beginnen."
 
 
815
 
816
- #: includes/forms/parent-child.php:175
817
- msgid "Enqueue child stylesheet"
818
- msgstr "Kind-Formatvorlage einbinden"
819
 
820
- #: includes/forms/parent-child.php:178
 
 
 
 
821
  msgid ""
822
- "Select this option if the theme enqueues the parent stylesheet but does not enqueue the "
823
- "child stylesheet at all. This can happen if <code>get_template()</code> or "
824
- "<code>get_template_directory_uri()</code> is used to link the stylesheet."
825
  msgstr ""
826
- "Diese Option auswählen, wenn das Thema die Eltern-Formatvorlage einbindet (enqueued), "
827
- "aber die Kind-Formatvorlage überhaupt nicht aufruft. Dies kann passieren, wenn "
828
- "<code>get_template()</code> oder <code>get_template_directory_uri()</code> zum "
829
- "Verknüpfen von Formatvorlagen benutzt wird."
830
-
831
- #: includes/forms/parent-child.php:181
832
- msgid "Recommended for this theme:"
833
- msgstr "Empfohlen für dieses Thema:"
834
 
835
- #: includes/forms/parent-child.php:187
836
- msgid "Enqueue both parent and child stylesheets"
837
- msgstr "Eltern- und Kind-Formatvorlagen einbinden (enqueue)"
838
 
839
- #: includes/forms/parent-child.php:190
840
  msgid ""
841
- "Select this option if stylesheet link tags are hard-coded into the header template "
842
- "(common in older themes). This enables the child stylesheet to override the parent "
843
- "stylesheet without using <code>@import</code>."
844
  msgstr ""
845
- "Diese Option auswählen, wenn Formatvorlagen-Linktags im Header-Template fix codiert "
846
- "sind (normalerweise in älteren Themen). Dies aktiviert die Übersteuerung der Eltern-"
847
- "Formatvorlage durch die Kind-Formatvorlage ohne das Benutzen von <code>@import</code>."
848
 
849
- #: includes/forms/parent-child.php:197
850
- msgid "<code>@import</code> parent stylesheet"
851
- msgstr "<code>@import</code> parent stylesheet"
852
 
853
- #: includes/forms/parent-child.php:200
854
  msgid ""
855
- "This option imports the parent stylesheet from the child stylesheet. This enables the "
856
- "child stylesheet to override the parent stylesheet, but using <code>@import</code> is "
857
- "no longer recommended."
858
  msgstr ""
859
- "Diese Option importiert die Eltern-Formatvorlage aus der Kind-Formatvorlage. Das "
860
- "erlaubt der Kind-Formatvorlage die Übersteuerung der Eltern-Formatvorlage, aber das "
861
- "Benutzen von <code>@import</code> ist nicht mehr empfohlen."
862
 
863
  #: includes/forms/parent-child.php:205
864
- msgid "Copy Parent Theme Menus, Widgets and other Customizer Options"
865
- msgstr "Kopieren Eltern-Theme-Menüs, Widgets und andere Design-Optionen"
866
 
867
- #: includes/forms/parent-child.php:214
868
- msgid "This will overwrite child theme options you may have already set."
 
 
 
 
 
 
 
869
  msgstr ""
870
- "Dies wird die Kind-Thema-Optionen überschreiben, die Sie vielleicht schon gesetzt haben."
 
 
871
 
872
- #: includes/forms/parent-child.php:220
873
- msgid "Backup current stylesheet"
874
- msgstr "Aktuelle Formatvorlage sichern"
875
 
876
- #: includes/forms/parent-child.php:229
877
  msgid ""
878
- "This creates a copy of the current stylesheet before applying changes. You can remove "
879
- "old backup files using the Files tab."
880
  msgstr ""
881
- "Dies erstellt eine Kopie der aktuellen Formatvorlage, bevor die Änderungen angewendet "
882
- "werden. Sie können alte Sicherungsdateien mittels des Dateien-Reiters löschen."
 
 
 
 
 
 
 
 
 
 
 
 
883
 
884
  #: includes/forms/parent-child.php:234
885
- msgid "Reset/Restore from backup"
886
- msgstr "Zurücksetzen/Wiederherstellen aus Backup"
887
 
888
- #: includes/forms/parent-child.php:240
889
- msgid "Leave unchanged"
890
- msgstr "Unverändert lassen"
891
 
892
- #: includes/forms/parent-child.php:246
893
- msgid "Reset all"
894
- msgstr "Alles zurücksetzen"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
895
 
896
- #: includes/forms/parent-child.php:266
897
- msgid "Parse additional stylesheets"
898
- msgstr "Zusätzliche Formatvorlagen auslesen"
899
 
900
- #: includes/forms/parent-child.php:290
901
- msgid "Please read before you click:"
902
- msgstr "Bitte vor dem Klicken durchlesen."
903
 
904
- #: includes/forms/parent-child.php:291
905
  msgid ""
906
- "This plugin makes significant modifications to your child theme, to include changing "
907
- "CSS, removing comments and adding php functions."
908
  msgstr ""
909
- "Dieses Plugin führt signifikante Änderungen an Ihrem Kind-Thema durch, z.Bsp. CSS-"
910
- "Änderungen, Entfernen von Kommentaren und dem Hinzufügen von PHP-Funktionen."
911
 
912
- #: includes/forms/parent-child.php:292
913
- msgid "If you are using an existing Child Theme,"
914
- msgstr "Wenn Sie ein bestehendes Kind-Thema benutzen,"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
915
 
916
- #: includes/forms/parent-child.php:292
917
- msgid "please consider using the Duplicate Child Theme option"
918
- msgstr "bitte ziehen Sie die 'Kind-Thema Duplizieren'-Option in Betracht"
919
 
920
- #: includes/forms/parent-child.php:292
921
- msgid "before proceeding."
922
- msgstr "vor dem Fortfahren."
923
 
924
- #: includes/forms/parent-child.php:298
925
- msgid "Generate/Rebuild Child Theme Files"
926
- msgstr "Erstellen/Neuaufbau Kind-Thema-Dateien"
927
 
928
  #: includes/forms/query-selector.php:13
929
- msgid "Query"
930
- msgstr "Abfrage"
 
 
 
 
931
 
932
  #: includes/forms/query-selector.php:24
933
  msgid "Selector"
@@ -939,23 +1304,23 @@ msgstr "Muster"
939
 
940
  #: includes/forms/query-selector.php:45
941
  msgid "Save Child Values"
942
- msgstr "Sichern Kind-Werte"
943
 
944
  #: includes/forms/query-selector.php:46
945
  msgid "Delete Child Values"
946
- msgstr "Löschen Kind-Werte"
947
 
948
  #: includes/forms/query-selector.php:53 includes/forms/rule-value.php:13
949
  msgid "Property"
950
  msgstr "Eigenschaft"
951
 
952
  #: includes/forms/query-selector.php:56
953
- msgid "Parent Value"
954
- msgstr "Eltern-Wert"
955
 
956
  #: includes/forms/query-selector.php:59
957
  msgid "Child Value"
958
- msgstr "Kind-Wert"
959
 
960
  #: includes/forms/query-selector.php:65
961
  msgid "New Property"
@@ -967,7 +1332,7 @@ msgstr "Reihenfolge"
967
 
968
  #: includes/forms/query-selector.php:84
969
  msgid "Copy Selector"
970
- msgstr "Kopieren Selektor"
971
 
972
  #: includes/forms/query-selector.php:86 includes/forms/webfonts.php:15
973
  msgid "Save"
@@ -980,15 +1345,16 @@ msgstr "Rohes CSS"
980
  #: includes/forms/query-selector.php:91
981
  msgid "Use to enter shorthand CSS or new @media queries and selectors."
982
  msgstr ""
983
- "Benutzen, um 'Shorthand-CSS' einzugeben, oder neue @media-Abfragen bzw. Selektoren."
 
984
 
985
  #: includes/forms/query-selector.php:91
986
  msgid ""
987
- "Values entered here are merged into existing child styles or added to the child "
988
- "stylesheet if they do not exist in the parent."
989
  msgstr ""
990
- "Hier eingegebene Werte werden mit bestehenden Kind-Stilen zusammengeführt oder der Kind-"
991
- "Formatvorlage hinzugefügt, wenn sie in der Elternvorlage nicht vorkommen."
992
 
993
  #: includes/forms/related.php:1
994
  msgid "New user?"
@@ -996,7 +1362,7 @@ msgstr "Neuer Benutzer?"
996
 
997
  #: includes/forms/related.php:1
998
  msgid "Click help"
999
- msgstr "Auf Hilfe klicken"
1000
 
1001
  #: includes/forms/related.php:1
1002
  msgid "Get CTC Pro and other tools"
@@ -1004,7 +1370,7 @@ msgstr "CTC Pro und andere Tools erhalten"
1004
 
1005
  #: includes/forms/related.php:1
1006
  msgid "Lilaea Media - Responsive Tools for a Mobile World"
1007
- msgstr "Lilaea Media - Responsive Tools für eine Mobile Welt"
1008
 
1009
  #: includes/forms/rule-value.php:26
1010
  msgid "Value"
@@ -1014,27 +1380,27 @@ msgstr "Wert"
1014
  msgid "Parent/Child"
1015
  msgstr "Eltern/Kind"
1016
 
1017
- #: includes/forms/tabs.php:16
1018
  msgid "Query/Selector"
1019
  msgstr "Abfrage/Selektor"
1020
 
1021
- #: includes/forms/tabs.php:19
1022
  msgid "Property/Value"
1023
  msgstr "Eigenschaft/Wert"
1024
 
1025
- #: includes/forms/tabs.php:22
1026
  msgid "Web Fonts"
1027
  msgstr "Webschriftarten"
1028
 
1029
- #: includes/forms/tabs.php:25
1030
- msgid "Child CSS"
1031
- msgstr "Kind-CSS"
1032
 
1033
- #: includes/forms/tabs.php:28
1034
- msgid "Parent CSS"
1035
- msgstr "Eltern-CSS"
1036
 
1037
- #: includes/forms/tabs.php:34
1038
  msgid "Files"
1039
  msgstr "Dateien"
1040
 
@@ -1052,7 +1418,7 @@ msgstr "Vorschau"
1052
 
1053
  #: includes/forms/themepreview.php:17
1054
  msgid " in default Site"
1055
- msgstr " auf Standard-Webseite"
1056
 
1057
  #: includes/forms/themepreview.php:21
1058
  msgid "Not Network Enabled"
@@ -1064,14 +1430,19 @@ msgstr "Verknüpfte Formatvorlagen"
1064
 
1065
  #: includes/forms/webfonts.php:20
1066
  msgid ""
1067
- "Use <code>@import url( [path] );</code> to link additional stylesheets. Child Theme "
1068
- "Configurator uses the <code>@import</code> keyword to identify them and convert them to "
1069
- "<code>&lt;link&gt;</code> tags. <strong>Example:</strong>"
 
1070
  msgstr ""
1071
- "Benutzen Sie <code>@import url( [path] );</code>, um mehr Formatvorlagen zu verknüpfen. "
1072
- "Child Theme Configurator benutzt das <code>@import</code> Schlüsselwort um sie zu "
1073
- "identifizieren und zu konvertieren in <code>&lt;link&gt;</code> Tags. <strong>Beispiel:"
1074
- "</strong>"
 
 
 
 
1075
 
1076
  #. Plugin URI of the plugin/theme
1077
  msgid "http://www.childthemeconfigurator.com"
@@ -1079,12 +1450,11 @@ msgstr "http://www.childthemeconfigurator.com"
1079
 
1080
  #. Description of the plugin/theme
1081
  msgid ""
1082
- "Create child themes and customize styles, templates and functions. Enqueues stylesheets "
1083
- "and web fonts. Handles rgba, vendor-prefixes and more."
1084
  msgstr ""
1085
- "Erstellen Sie Kind-Themen und passen Sie Stile, Vorlagen und Funktionen an. Bindet "
1086
- "Formatvorlagen und Webschriftarten ein (Enqueue). Behandelt RGBA, Hersteller-Präfixe "
1087
- "und mehr."
1088
 
1089
  #. Author of the plugin/theme
1090
  msgid "Lilaea Media"
@@ -1093,3 +1463,47 @@ msgstr "Lilaea Media"
1093
  #. Author URI of the plugin/theme
1094
  msgid "http://www.lilaeamedia.com"
1095
  msgstr "http://www.lilaeamedia.com"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (C) 2016 Child Theme Configurator
2
  # This file is distributed under the same license as the Child Theme Configurator package.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: Child Theme Configurator 2.0.0\n"
6
  "Report-Msgid-Bugs-To: http://wordpress.org/tag/child-theme-configurator\n"
7
+ "POT-Creation-Date: 2016-03-29 17:45+0200\n"
8
+ "PO-Revision-Date: 2016-03-29 19:31+0200\n"
9
+ "Last-Translator: \n"
10
+ "Language-Team: \n"
11
+ "Language: de_DE\n"
12
  "MIME-Version: 1.0\n"
13
  "Content-Type: text/plain; charset=UTF-8\n"
14
  "Content-Transfer-Encoding: 8bit\n"
15
+ "X-Generator: Poedit 1.8.6\n"
 
 
 
16
  "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
17
 
18
+ #: includes/class-ctc-admin.php:373
19
+ msgid "Zip file creation failed."
20
+ msgstr "ZIP-Dateierstellung fehlgeschlagen."
 
 
21
 
22
+ #: includes/class-ctc-admin.php:409
23
+ msgid "The Functions file is required and cannot be deleted."
24
+ msgstr "Die Funktionendatei wird benötigt und kann nicht gelöscht werden."
 
25
 
26
+ #: includes/class-ctc-admin.php:493
27
+ msgid "You do not have permission to configure child themes."
28
+ msgstr "Sie haben keine Berechtigung, Kindthemen zu konfigurieren."
29
 
30
+ #: includes/class-ctc-admin.php:522
31
+ msgid "%s does not exist. Please select a valid Parent Theme."
32
+ msgstr "%s existiert nicht. Bitte wählen Sie ein gültiges Elternthema."
33
+
34
+ #: includes/class-ctc-admin.php:525
35
+ msgid "Please select a valid Parent Theme."
36
+ msgstr "Bitte wählen Sie ein gültiges Elternthema."
37
+
38
+ #: includes/class-ctc-admin.php:530
39
+ msgid "Please select a valid Child Theme."
40
+ msgstr "Bitte wählen Sie ein gültiges Kindthema."
41
 
42
+ #: includes/class-ctc-admin.php:534
43
+ msgid "Please enter a valid Child Theme directory name."
44
+ msgstr "Bitte geben Sie ein gültiges Kindthema-Verzeichnis ein."
45
 
46
+ #: includes/class-ctc-admin.php:539
47
  msgid ""
48
+ "<strong>%s</strong> exists. Please enter a different Child Theme template "
49
+ "name."
50
  msgstr ""
51
+ "<strong>%s</strong> existiert. Bitte geben Sie einen anderen Kindthema-"
52
+ "Vorlagennamen ein."
53
+
54
+ #: includes/class-ctc-admin.php:558
55
+ msgid "Your theme directories are not writable."
56
+ msgstr "Ihr Themenverzeichnis ist schreibgeschützt."
57
+
58
+ #: includes/class-ctc-admin.php:632
59
+ msgid "Could not upgrade child theme"
60
+ msgstr "Konnte das Kindthema nicht aktualisieren"
61
+
62
+ #: includes/class-ctc-admin.php:722
63
+ msgid "Your stylesheet is not writable."
64
+ msgstr "Ihre Formatvorlage ist schreibgeschützt."
65
+
66
+ #: includes/class-ctc-admin.php:1283
67
+ msgid "Could not set write permissions."
68
+ msgstr "Konnte Schreibberechtigungen nicht setzen."
69
+
70
+ #: includes/class-ctc-admin.php:1384
71
+ msgid "There were errors while resetting permissions."
72
+ msgstr "Beim Zurücksetzen der Berechtigungen traten Fehler auf."
73
 
74
+ #: includes/class-ctc-admin.php:1426
75
+ msgid "Could not upload file."
76
+ msgstr "Konnte Datei nicht hochladen."
77
+
78
+ #: includes/class-ctc-ui.php:35
79
+ msgid "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
80
+ msgstr "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
81
+
82
+ #: includes/class-ctc-ui.php:166
83
  msgid "Child Theme files modified successfully."
84
+ msgstr "Kindthema-Dateien erfolgreich geändert."
85
 
86
+ #: includes/class-ctc-ui.php:168
87
  msgid ""
88
+ "Child Theme <strong>%s</strong> has been reset. Please configure it using "
89
+ "the settings below."
90
  msgstr ""
91
+ "Kindthema <strong>%s</strong> zurückgesetzt. Bitte mit den Einstellungen "
92
+ "unten konfigurieren."
93
 
94
+ #: includes/class-ctc-ui.php:170
95
+ msgid "Child Theme <strong>%s</strong> has been generated successfully."
96
+ msgstr "Kindthema <strong>%s</strong> wurde erfolgreich erstellt."
97
+
98
+ #: includes/class-ctc-ui.php:172
99
  msgid "IMPORTANT:"
100
  msgstr "WICHTIG:"
101
 
102
+ #: includes/class-ctc-ui.php:174 includes/forms/themepreview.php:20
103
  msgid "Go to Themes"
104
  msgstr "Gehe zu Themen"
105
 
106
+ #: includes/class-ctc-ui.php:174
107
  msgid "Network enable"
108
+ msgstr "Netzwerkfähig machen"
109
 
110
+ #: includes/class-ctc-ui.php:174
111
  msgid "your child theme."
112
+ msgstr "Ihr Kindthema"
113
 
114
+ #: includes/class-ctc-ui.php:176 includes/forms/themepreview.php:18
115
  msgid "Live Preview"
116
  msgstr "Live-Vorschau"
117
 
118
+ #: includes/class-ctc-ui.php:176
119
+ msgid "Preview your child theme"
120
+ msgstr "Vorschau Ihres Kindthemas"
121
 
122
+ #: includes/class-ctc-ui.php:176
123
  msgid "before activating."
124
  msgstr "vor der Aktivierung."
125
 
126
+ #: includes/class-ctc-ui.php:284
127
  msgid "URL/None"
128
+ msgstr "URL/Keine"
129
 
130
+ #: includes/class-ctc-ui.php:285
131
  msgid "Origin"
132
  msgstr "Quelle"
133
 
134
+ #: includes/class-ctc-ui.php:286
135
  msgid "Color 1"
136
  msgstr "Farbe 1"
137
 
138
+ #: includes/class-ctc-ui.php:287
139
  msgid "Color 2"
140
  msgstr "Farbe 2"
141
 
142
+ #: includes/class-ctc-ui.php:288
143
  msgid "Width/None"
144
  msgstr "Breite/Keine"
145
 
146
+ #: includes/class-ctc-ui.php:289
147
  msgid "Style"
148
  msgstr "Stil"
149
 
150
+ #: includes/class-ctc-ui.php:290
151
  msgid "Color"
152
  msgstr "Farbe"
153
 
154
+ #: includes/class-ctc-ui.php:292
155
+ msgid ""
156
+ "Are you sure you wish to RESET? This will destroy any work you have done in "
157
+ "the Configurator."
158
+ msgstr ""
159
+ "Möchten Sie wirklich zurücksetzen? Dies wird jegliche Arbeit im Konfigurator "
160
+ "überschreiben."
161
 
162
+ #: includes/class-ctc-ui.php:293
163
  msgid "<span style=\"font-size:10px\">!</span>"
164
  msgstr "<span style=\"font-size:10px\">!</span>"
165
 
166
+ #: includes/class-ctc-ui.php:294 includes/forms/rule-value.php:32
167
  msgid "Selectors"
168
  msgstr "Selektoren"
169
 
170
+ #: includes/class-ctc-ui.php:295
171
  msgid "Close"
172
  msgstr "Schließen"
173
 
174
+ #: includes/class-ctc-ui.php:296
175
  msgid "Edit Selector"
176
+ msgstr "Selektor wählen"
177
 
178
+ #: includes/class-ctc-ui.php:297
179
  msgid "Cancel"
180
  msgstr "Abbrechen"
181
 
182
+ #: includes/class-ctc-ui.php:298
183
  msgid "Rename"
184
+ msgstr "Umbennen"
185
 
186
+ #: includes/class-ctc-ui.php:299
187
  msgid "The stylesheet cannot be displayed."
188
  msgstr "Die Formatvorlage kann nicht angezeigt werden."
189
 
190
+ #: includes/class-ctc-ui.php:300
191
  msgid "(Child Only)"
192
  msgstr "(Nur Kind)"
193
 
194
+ #: includes/class-ctc-ui.php:301
195
  msgid "Please enter a valid Child Theme."
196
+ msgstr "Bitte gültiges Kindthema eingeben."
197
 
198
+ #: includes/class-ctc-ui.php:302
199
  msgid "Please enter a valid Child Theme name."
200
+ msgstr "Bitte gültigen Kindthema-Namen eingeben."
201
 
202
+ #: includes/class-ctc-ui.php:303
203
  msgid "<strong>%s</strong> exists. Please enter a different Child Theme"
204
+ msgstr "<strong>%s</strong> existiert. Bitte anderen Kindthema-Namen eingeben"
205
 
206
+ #: includes/class-ctc-ui.php:304
207
  msgid "The page could not be loaded correctly."
208
  msgstr "Die Seite konnte nicht korrekt geladen werden."
209
 
210
+ #: includes/class-ctc-ui.php:305
211
+ msgid ""
212
+ "Conflicting or out-of-date jQuery libraries were loaded by another plugin:"
213
  msgstr ""
214
+ "jQuery-Bibliotheken-Konflikt oder veraltete wurden von anderem Plugin "
215
+ "geladen."
216
 
217
+ #: includes/class-ctc-ui.php:306
218
  msgid "Deactivating or replacing plugins may resolve this issue."
219
+ msgstr "Deaktivieren oder Ersetzen von Plugins könnte das Problem lösen."
220
 
221
+ #: includes/class-ctc-ui.php:307
222
  msgid "%sWhy am I seeing this?%s"
223
  msgstr "%sWieso sehe ich das?%s"
224
 
225
+ #: includes/class-ctc-ui.php:310
226
+ msgid "No Styles Available. Check Parent/Child settings."
227
+ msgstr "Keine Stile verfügbar. Prüfen Sie Eltern/Kind-Einstellungen."
228
 
229
+ #: includes/class-ctc-ui.php:311
230
+ msgid "Updating"
231
+ msgstr "Aktualisiere"
232
 
233
+ #: includes/class-ctc-ui.php:312
234
+ msgid "Checking"
235
+ msgstr "Prüfe"
236
 
237
+ #: includes/class-ctc-ui.php:313
238
+ msgid "The theme \"%s\" generated unexpected PHP debug output."
239
+ msgstr "Das Thema \"%s\" erzeugte unerwartete PHP-Debug-Ausgabe."
240
 
241
+ #: includes/class-ctc-ui.php:314
242
+ msgid "The theme \"%s\" could not be loaded."
243
+ msgstr "Das Thema \"%s\" konnte nicht geladen werden."
244
 
245
+ #: includes/class-ctc-ui.php:315
246
+ msgid "<p>Please verify the theme has been installed correctly.</p>"
247
+ msgstr "<p>Bitte prüfen Sie, ob das Thema korrekt installiert wurde.</p>"
248
 
249
+ #: includes/class-ctc-ui.php:316
250
+ msgid "Show Debug Output"
251
+ msgstr "Zeige Debug-Ausgabe"
252
 
253
+ #: includes/class-ctc-ui.php:317
254
+ msgid ""
255
+ "<p>You may not be able to use this Theme as a Child Theme while these "
256
+ "conditions exist.</p><p>It is possible that this theme has specific "
257
+ "requirements to work correctly as a child theme. Check your theme's "
258
+ "documentation for more information.</p><p>Please make sure you are using the "
259
+ "latest version of this theme. If so, please contact this Theme's author and "
260
+ "report the error list above.</p>"
261
+ msgstr ""
262
+ "<p>Sie können dieses Thema unter diesen Bedingungen vielleicht nicht "
263
+ "benutzen.</p><p>Möglicherweise braucht das Thema spezielle Anforderungen, um "
264
+ "korrekt als Kindthema zu funktionieren. Prüfen Sie die Themen-Dokumentation "
265
+ "für weitere Infos.</p>Bitte stellen Sie sicher, die neueste Version dieses "
266
+ "Themas zu benutzen. Falls ja, kontaktieren Sie den Themenautor und melden "
267
+ "Sie den obigen Fehler.</p>"
268
+
269
+ #: includes/class-ctc-ui.php:318
270
+ msgid "Do Not Activate \"%s\"! A PHP FATAL ERROR has been detected."
271
+ msgstr "Aktivieren Sie nicht \"%s\"! Ein PHP FATAL ERROR wurde entdeckt."
272
+
273
+ #: includes/class-ctc-ui.php:319
274
+ msgid "This theme loads stylesheets after the wp_styles queue."
275
+ msgstr "Dieses Thema lädt Formatvorlagen nach der wp_styles Warteschlange."
276
+
277
+ #: includes/class-ctc-ui.php:320
278
+ msgid ""
279
+ "<p>This makes it difficult for plugins to override these styles. You can try "
280
+ "to resolve this using the \"Repair header template\" option (Step 6, "
281
+ "\"Additional handling options\", below).</p>"
282
  msgstr ""
283
+ "<p>Dies macht es schwierig für Plugins, diese Stile zu übersteuern. Sie "
284
+ "können dies eventuell mit der \"Reparieren Header-Vorlage\"-Option beheben "
285
+ "(Schritt 6, \"Zusätzliche Behandlungsoptionen\", unten)</p>"
286
 
287
+ #: includes/class-ctc-ui.php:321
288
+ msgid ""
289
+ "This theme loads the parent theme's <code>style.css</code> file outside the "
290
+ "wp_styles queue."
291
+ msgstr ""
292
+ "Dieses Thema lädt die Elternthema <code>style.css</code>-Datei außerhalb der "
293
+ "wp_styles-Warteschlange."
294
 
295
+ #: includes/class-ctc-ui.php:322
296
+ msgid ""
297
+ "<p>This is common with older themes but requires the use of <code>@import</"
298
+ "code>, which is no longer recommended. You can try to resolve this using the "
299
+ "\"Repair header template\" option (see step 6, \"Additional handling options"
300
+ "\", below).</p>"
301
+ msgstr ""
302
+ "<p>Dies ist üblich bei älteren Themen, benötigt aber den Gebrauch von "
303
+ "<code>@import</code> (nicht mehr empfohlen). Sie können dies eventuell mit "
304
+ "der \"Reparieren Header-Vorlage\"-Option beheben (Schritt 6, \"Zusätzliche "
305
+ "Behandlungsoptionen\", unten)</p>"
306
+
307
+ #: includes/class-ctc-ui.php:323
308
+ msgid "This child theme does not load a Configurator stylesheet."
309
+ msgstr "Dieses Kindthema lädt keine Konfigurator-Formatvorlage."
310
+
311
+ #: includes/class-ctc-ui.php:324
312
+ msgid ""
313
+ "<p>If you want to customize styles using this plugin, please click "
314
+ "\"Configure Child Theme\" again to add this to the settings.</p>"
315
+ msgstr ""
316
+ "<p>Wenn Sie Stile mit diesem Plugin anpassen wollen, bitte klicken Sie "
317
+ "erneut \"Kindthema konfigurieren\", um dies zu den Einstellungen "
318
+ "hinzuzufügen.</p>"
319
 
320
+ #: includes/class-ctc-ui.php:325
321
  msgid ""
322
+ "This child theme uses the parent stylesheet but does not load the parent "
323
+ "theme's <code>style.css</code> file."
 
 
 
324
  msgstr ""
325
+ "Dieses Kindthema benutzt die Eltern-Formatvorlage, aber lädt nicht die "
326
+ "Elternthema <code>style.css</code>-Datei."
 
 
 
327
 
328
+ #: includes/class-ctc-ui.php:326
329
+ msgid ""
330
+ "<p>Please select a stylesheet handling method or check \"Ignore parent theme "
331
+ "stylesheets\" (see step 6, below).</p>"
332
+ msgstr ""
333
+ "<p>Bitte wählen Sie eine Formatvorlage-Behandlungsmethode oder kreuzen Sie "
334
+ "\"Elternthema-Formatvorlagen ignorieren\" an (siehe Schritt 6 unten).</p>"
335
 
336
+ #: includes/class-ctc-ui.php:327
337
+ msgid "This child theme appears to be functioning correctly."
338
+ msgstr "Dieses Kindthema scheint korrekt zu funktionieren."
339
 
340
+ #: includes/class-ctc-ui.php:328
341
+ msgid "This theme appears OK to use as a Child theme."
342
+ msgstr "Dieses Thema scheint als Kindthema OK zu sein."
343
 
344
+ #: includes/class-ctc-ui.php:329
345
+ msgid "This Child Theme has not been configured for this plugin."
346
+ msgstr "Dieses Kindthema wurde für dieses Plugin nicht konfiguriert."
347
 
348
+ #: includes/class-ctc-ui.php:330
349
  msgid ""
350
+ "<p>The Configurator makes significant modifications to the child theme, "
351
+ "including stylesheet changes and additional php functions. Please consider "
352
+ "using the DUPLICATE child theme option (see step 1, above) and keeping the "
353
+ "original as a backup.</p>"
354
  msgstr ""
355
+ "<p>Der Konfigurator macht umfangreiche Änderungen am Kindthema, inklusive "
356
+ "Formatvorlage-Änderungen und zusätzlichen PHP-Funktionen. Bitte ziehen Sie "
357
+ "die DUPLIZIEREN-Option für Kindthemen in Betracht (siehe Schritt 1 oben), um "
358
+ "das Original als Backup zu behalten.</p>"
359
 
360
+ #: includes/class-ctc-ui.php:331
361
  msgid ""
362
+ "This child theme uses <code>@import</code> to load the parent theme's "
363
+ "<code>style.css</code> file."
 
364
  msgstr ""
365
+ "Dieses Thema benutzt das Elternthema <code>@import</code>, um die Eltern "
366
+ "<code>style.css</code>-Datei zu laden."
 
367
 
368
+ #: includes/class-ctc-ui.php:332
369
+ msgid ""
370
+ "<p>Please consider selecting \"Use the WordPress style queue\" for the "
371
+ "parent stylesheet handling option (see step 6, below).</p>"
372
+ msgstr ""
373
+ "<p>Ziehen Sie bitte die Option \"Benutzen Sie die Wordpress Stil-"
374
+ "Warteschlange\" in Betracht für die Formatvorlage-Behandlung (siehe Schritt "
375
+ "6 unten)</p>"
376
+
377
+ #: includes/class-ctc-ui.php:333
378
+ msgid ""
379
+ "This theme loads additional stylesheets after the <code>style.css</code> "
380
+ "file:"
381
+ msgstr ""
382
+ "Dieses Thema lädt zusätzliche Formatvorlagen nach der <code>style.css</code>-"
383
+ "Datei."
384
+
385
+ #: includes/class-ctc-ui.php:334
386
+ msgid ""
387
+ "<p>Consider saving new custom styles to a \"Separate stylesheet\" (see step "
388
+ "5, below) so that you can customize these styles.</p>"
389
+ msgstr ""
390
+ "<p>Ziehen Sie in Betracht, neue Stile in eine separate Formatvorlage zu "
391
+ "sichern (siehe Schritt 5 unten), so dass Sie die Stile anpassen können.</p>"
392
+
393
+ #: includes/class-ctc-ui.php:335
394
+ msgid ""
395
+ "The parent theme's <code>style.css</code> file is being loaded automatically."
396
+ msgstr ""
397
+ "Die Elternthema-Datei <code>style.css</code> wird automatisch geladen."
398
+
399
+ #: includes/class-ctc-ui.php:336
400
+ msgid ""
401
+ "<p>The Configurator has been selected \"Do not add any parent stylesheet "
402
+ "handling\" for the \"Parent stylesheet handling\" option (see step 6, below)."
403
+ "</p>"
404
+ msgstr ""
405
+ "<p> Im Konfigurator wurde für \"Eltern-Formatvorlagen-Behandlung\" "
406
+ "ausgewählt \"Keine Eltern-Formatvorlagen-Behandlung hinzufügen\" (siehe "
407
+ "Schritt 6 unten).</p>"
408
+
409
+ #: includes/class-ctc-ui.php:337
410
+ msgid ""
411
+ "This theme does not require the parent theme's <code>style.css</code> file "
412
+ "for its appearance."
413
+ msgstr ""
414
+ "Dieses Thema benötigt die <code>style.css</code>-Datei des Elternthemas "
415
+ "nicht für die Anzeige."
416
+
417
+ #: includes/class-ctc-ui.php:338
418
+ msgid "This Child Theme was configured with an earlier version."
419
+ msgstr "Dieses Kindthema wurde mit einer früheren Version konfiguriert."
420
+
421
+ #: includes/class-ctc-ui.php:339
422
+ msgid ""
423
+ "<p>The selected stylesheet handling method is no longer used. Please update "
424
+ "the configuration using the \"Repair header template\" option (see step 6, "
425
+ "\"Additional handling options\", below).</p>"
426
+ msgstr ""
427
+ "<p>Die ausgewählte Formatvorlage-Behandlungsmethode wird nicht mehr benutzt. "
428
+ "Bitte aktualisieren Sie die Konfiguration mit der \"Reparieren Header-Vorlage"
429
+ "\"-Option (siehe Schritt 6 unten, \"Zusätzliche Behandlungsoptionen\").</p>"
430
+
431
+ #: includes/class-ctc-ui.php:340
432
+ msgid "Show Analysis Object"
433
+ msgstr "Zeige Analyse von Objekt"
434
+
435
+ #: includes/class-ctc-ui.php:341
436
+ msgid ""
437
+ "This child theme was configured using the CTC Pro \"Genesis stylesheet "
438
+ "handling\" method."
439
+ msgstr ""
440
+ "Dieses Kindthema wurde mit der CTC Pro \"Genesis Formatvorlagen Behandlungs"
441
+ "\"-Methode konfiguriert."
442
+
443
+ #: includes/class-ctc-ui.php:342
444
+ msgid ""
445
+ "<p>This method has been replaced by the \"Separate stylesheet\" and \"Ignore "
446
+ "Parent Theme\" options ( selected below ) for broader framework "
447
+ "compatability.</p>"
448
+ msgstr ""
449
+ "<p>Diese Methode wurde für breitere Kompatibilität durch die \"Separate "
450
+ "Formatvorlage\" und \"Ignorieren Elternthema\"-Optionen ersetzt (unten "
451
+ "ausgewählt)</p>."
452
+
453
+ #: includes/class-ctc-ui.php:362
454
+ msgid ""
455
+ "The child theme is in read-only mode and Child Theme Configurator cannot "
456
+ "apply changes. Click to see options"
457
+ msgstr ""
458
+ "Dieses Kindthema ist im Nur-Lese-Modus und der Kindthemen-Konfigurator kann "
459
+ "die Änderungen nicht anwenden. Klicken Sie für Optionen"
460
+
461
+ #: includes/class-ctc-ui.php:365
462
+ msgid ""
463
+ "<li>Temporarily set write permissions by clicking the button below. When you "
464
+ "are finished editing, revert to read-only by clicking \"Make read-only\" "
465
+ "under the \"Files\" tab.</li>"
466
+ msgstr ""
467
+ "<li>Temporär die Schreibberechtigungen setzen (mit dem Klicken der "
468
+ "Schaltfläche). Wenn Sie mit der Bearbeitung fertig sind, können Sie \"Nur "
469
+ "lesbar\" klicken (Dateien-Tab), um zum alten Zustand zurück zu kehren.</li>"
470
+
471
+ #: includes/class-ctc-ui.php:368
472
  msgid "Make files writable"
473
+ msgstr "Dateien beschreibbar machen"
474
 
475
+ #: includes/class-ctc-ui.php:369
476
  msgid ""
477
+ "<li><a target=\"_blank\" href=\"http://codex.wordpress.org/Editing_wp-"
478
+ "config.php#WordPress_Upgrade_Constants\" title=\"Editin wp-config.php\">Add "
479
+ "your FTP/SSH credentials to the WordPress config file</a>.</li>"
480
  msgstr ""
481
+ "<li><a target=\"_blank\" href=\"http://codex.wordpress.org/Editing_wp-"
482
+ "config.php#WordPress_Upgrade_Constants\" title=\"Editin wp-config.php\">Add "
483
+ "your FTP/SSH credentials to the WordPress config file</a>.</li>"
484
 
485
+ #: includes/class-ctc-ui.php:371
486
  msgid ""
487
+ "<li><a target=\"_blank\" href=\"http://technet.microsoft.com/en-us/library/"
488
+ "cc771170\" title=\"Setting Application Pool Identity\">Assign WordPress to "
489
+ "an application pool that has write permissions</a> (Windows IIS systems).</"
490
+ "li>"
491
  msgstr ""
492
+ "<li><a target=\"_blank\" href=\"http://technet.microsoft.com/en-us/library/"
493
+ "cc771170\" title=\"Setting Application Pool Identity\">Assign WordPress to "
494
+ "an application pool that has write permissions</a> (Windows IIS systems).</"
495
+ "li>"
496
 
497
+ #: includes/class-ctc-ui.php:372
498
  msgid ""
499
+ "<li><a target=\"_blank\" href=\"http://codex.wordpress.org/"
500
+ "Changing_File_Permissions\" title=\"Changing File Permissions\">Set write "
501
+ "permissions on the server manually</a> (not recommended).</li>"
502
  msgstr ""
503
+ "<li><a target=\"_blank\" href=\"http://codex.wordpress.org/"
504
+ "Changing_File_Permissions\" title=\"Changing File Permissions\">Set write "
505
+ "permissions on the server manually</a> (not recommended).</li>"
506
 
507
+ #: includes/class-ctc-ui.php:374
508
  msgid "<li>Run PHP under Apache with suEXEC (contact your web host).</li>"
509
+ msgstr ""
510
+ "<li>PHP unter Apache mit suEXEC laufen lassen (kontaktieren Sie Ihren "
511
+ "Provider).</li>"
512
 
513
+ #: includes/class-ctc-ui.php:383
514
  msgid ""
515
+ "This Child Theme is not owned by your website account. It may have been "
516
+ "created by a prior version of this plugin or by another program. Moving "
517
+ "forward, it must be owned by your website account to make changes. Child "
518
+ "Theme Configurator will attempt to correct this when you click the button "
519
+ "below."
520
  msgstr ""
521
+ "Dieses Kindthema gehört nicht Ihrem Webseiten-Konto. Es könnte von einer "
522
+ "früheren Version dieses Plugins oder einem anderen Programm erstellt worden "
523
+ "sein. Um fortzufahren und Änderungen zu machen, müssen Sie es besitzen. Der "
524
+ "Kindthema-Konfigurator wird versuchen, dies zu korrigieren, wenn Sie die "
525
+ "Schaltfläche unten klicken."
526
 
527
+ #: includes/class-ctc-ui.php:391
528
+ msgid ""
529
+ "Child Theme Configurator needs to update its internal data. Please set your "
530
+ "preferences below and click \"Generate Child Theme Files\" to update your "
531
+ "configuration."
532
+ msgstr ""
533
+ "Der Kindthema-Konfigurator muss interne Daten aktualisieren. Bitte setzen "
534
+ "Sie Ihre Voreinstellungen unten und klicken Sie auf \"Erzeuge Kindthemen-"
535
+ "Dateien\", um die Konfiguration zu aktualisieren."
536
 
537
+ #: includes/class-ctc-ui.php:397
538
  msgid ""
539
+ "<strong>However, some styles could not be parsed due to memory limits.</"
540
+ "strong> Try deselecting \"Additional Stylesheets\" below and click "
541
+ "\"Generate/Rebuild Child Theme Files\". %sWhy am I seeing this?%s"
542
  msgstr ""
543
+ "<strong>Einige Stile konnten jedoch wegen Speicherlimiten nicht gelesen "
544
+ "werden.</strong> Versuchen Sie die Deselektion von \"Zusätzliche "
545
+ "Formatvorlagen\" unten und klicken Sie auf \"Erzeugen/Neuaufbau Kindthemen-"
546
+ "Dateien\". %sWieso sehe ich das?%s"
547
 
548
+ #: includes/class-ctc-ui.php:405
549
  msgid ""
550
+ "Child Theme Configurator did not detect any configuration data because a "
551
+ "previously configured Child Theme has been removed. Please follow the steps "
552
+ "for \"CONFIGURE an existing Child Theme\" under the \"Parent/Child\" Tab."
553
  msgstr ""
554
+ "Der Kindthema-Konfigurator fand keinerlei Konfigurationsdaten, da ein früher "
555
+ "konfiguriertes Kindthema entfernt wurde. Bitte folgen Sie den Schritten für "
556
+ "\"KONFIGURIERE ein bestehendes Kindthema\" unter dem \"Eltern/Kind\"-Tab."
557
 
558
+ #: includes/class-ctc-ui.php:411
559
  msgid ""
560
+ "Your stylesheet has changed since the last time you used the Configurator. "
561
+ "Please follow the steps for \"CONFIGURE an existing Child Theme\" under the "
562
+ "\"Parent/Child\" Tab or you will lose these changes."
563
  msgstr ""
564
+ "Ihre Formatvorlage hat sich seit der letzten Benutzung des Konfigurators "
565
+ "verändert. Bitte folgen Sie den Schritten für \"KONFIGURIERE ein bestehendes "
566
+ "Kindthema\" unter dem \"Eltern/Kind\"-Tab oder Sie werden diese Änderungen "
567
+ "verlieren."
568
+
569
+ #: includes/class-ctc-ui.php:423
570
+ msgid "This version of Child Theme Configurator includes significant updates."
571
+ msgstr ""
572
+ "Diese Version des Kindthema-Konfigurators enthält umfangreiche Updates."
573
+
574
+ #: includes/class-ctc-ui.php:424
575
+ msgid ""
576
+ "A lot of time and testing has gone into this release but there are always "
577
+ "edge cases. If you have any questions, please"
578
+ msgstr ""
579
+ "Viel Zeit und Testen wurde in diese Veröffentlichung gesteckt, aber es gibt "
580
+ "immer Sonderfälle. Wenn Sie Fragen haben sollten, bitte"
581
+
582
+ #: includes/class-ctc-ui.php:424
583
+ msgid "Contact Us."
584
+ msgstr "Kontaktieren Sie uns."
585
+
586
+ #: includes/class-ctc-ui.php:425
587
+ msgid "For more information, please open the Help tab at the top right or "
588
+ msgstr ""
589
+ "Für weitere Informationen, bitte öffnen Sie oben rechts den Hilfe-Tab oder "
590
+
591
+ #: includes/class-ctc-ui.php:425
592
+ msgid "click here to view the latest videos."
593
+ msgstr "klicken Sie hier für die neuesten Videos."
594
+
595
+ #: includes/class-ctc-ui.php:427
596
+ msgid ""
597
+ "It is a good idea to save a Zip Archive of your Child Theme before using "
598
+ "this version for the first time (click the button to the right to download). "
599
+ "Remember you can always export your child themes from the \"Files\" Tab."
600
+ msgstr ""
601
+ "Es ist eine gute Idee, ein ZIP-Archiv Ihres Kindthemas zu speichern, bevor "
602
+ "Sie diese Version erstmalig benutzen (klicken Sie die Schaltfläche rechts "
603
+ "zum Herunterladen). Bedenken Sie, Sie können Ihr Kindthema immer mit dem "
604
+ "\"Dateien\"-Tab exportieren."
605
+
606
+ #: includes/class-ctc-ui.php:429
607
+ msgid "Backup Child Theme"
608
+ msgstr "Kindthema sichern"
609
+
610
+ #. Plugin Name of the plugin/theme
611
+ #: includes/class-ctc.php:50 includes/class-ctc.php:60
612
+ #: includes/forms/main.php:34
613
+ msgid "Child Theme Configurator"
614
+ msgstr "Kindthema-Konfigurator"
615
+
616
+ #: includes/class-ctc.php:51 includes/class-ctc.php:61
617
+ #: includes/class-ctc.php:71
618
+ msgid "Child Themes"
619
+ msgstr "Kindthemen"
620
+
621
+ #: includes/class-ctc.php:86
622
+ msgid "Child Theme Configurator requires WordPress version %s or later."
623
+ msgstr "Kindthema-Konfigurator benötigt WordPress-Version %s oder neuer."
624
 
625
  #: includes/forms/addl_css.php:7
626
  msgid "Parse additional stylesheets:"
627
+ msgstr "Zusätzliche Formatvorlagen einlesen:"
628
 
629
+ #: includes/forms/addl_css.php:11
630
  msgid ""
631
+ "Stylesheets that are currently being loaded by the parent theme are "
632
+ "automatically selected below (except for Bootstrap stylesheets which add a "
633
+ "large amount data to the configuration). To further reduce overhead, select "
634
+ "only the additional stylesheets you wish to customize."
635
  msgstr ""
636
+ "Aktuell geladene Formatvorlagen vom Elternthema werden unten automatisch "
637
+ "ausgewählt (ausgenommen Bootstrap-Stylesheets, welche der Konfiguration eine "
638
+ "enorme Datenmenge hinzufügen). Um weiteren Overhead zu vermeiden, wählen Sie "
639
+ "nur die Stylesheets aus, die Sie auch anpassen möchten."
640
 
641
  #: includes/forms/addl_panels.php:9 includes/forms/addl_panels.php:39
642
  msgid "Use coupon code"
643
+ msgstr "Gutschein-Code benutzen"
644
 
645
  #: includes/forms/addl_panels.php:9 includes/forms/addl_panels.php:39
646
  msgid "wordpress-org"
648
 
649
  #: includes/forms/addl_panels.php:9 includes/forms/addl_panels.php:39
650
  msgid "and get <strong>20% off entire order</strong>."
651
+ msgstr "und erhalten Sie <strong> 20% auf die ganze Bestellung</strong>."
652
 
653
  #: includes/forms/addl_panels.php:10 includes/forms/addl_panels.php:40
654
  msgid "Order Now"
656
 
657
  #: includes/forms/addl_panels.php:10 includes/forms/addl_panels.php:40
658
  msgid "*Prices and offers subject to change."
659
+ msgstr "*Preise und Angebote können sich ändern."
660
 
661
  #: includes/forms/addl_panels.php:11 includes/forms/addl_panels.php:12
662
  msgid "Learn more about IntelliWidget"
663
+ msgstr "Mehr über IntelliWidget erfahren"
664
 
665
  #: includes/forms/addl_panels.php:12
666
  msgid ""
667
+ "IntelliWidget is a versatile widget manager that does the work of multiple "
668
+ "plugins by combining custom page menus, featured posts, sliders and other "
669
+ "dynamic content features into a single plugin that can display on a per-page "
670
+ "or site-wide basis."
671
  msgstr ""
672
+ "IntelliWidget ist ein cleverer Widget-Manager, der die Arbeit von mehreren "
673
+ "Plugins erledigt, indem er Seitenmenüs, angesagte Beiträge, Slider und "
674
+ "anderen dynamischen Inhalt in ein einzelnes Plugin kombiniert, welche pro "
675
+ "Seite oder Site angezeigt werden können."
676
 
677
  #: includes/forms/addl_panels.php:13 includes/forms/addl_panels.php:16
678
  msgid "Learn more"
684
 
685
  #: includes/forms/addl_panels.php:15
686
  msgid ""
687
+ "IntelliWidget Responsive Menu lets you break free from your theme’s built-in "
688
+ "responsive menu options and gives you complete control over the user "
689
+ "experience."
690
  msgstr ""
691
+ "IntelliWidget Responsive Menu lässt Sie aus den eingebauten Themen-"
692
+ "Menüoptionen ausbrechen und gibt Ihnen komplette Kontrolle über die "
693
+ "Benutzererfahrung."
694
 
695
+ #: includes/forms/addl_panels.php:19
696
  msgid "Learn more about CTC Pro"
697
  msgstr "Mehr über CTC Pro erfahren"
698
 
699
  #: includes/forms/addl_panels.php:20
700
  msgid "Customizing WordPress just got even easier."
701
+ msgstr "WordPress anzupassen ist jetzt noch einfacher."
702
 
703
  #: includes/forms/addl_panels.php:21
704
  msgid ""
705
+ "Thousands of users have already seen the benefits of using Child Theme "
706
+ "Configurator. If you spend any amount of time customizing WordPress, CTC Pro "
707
+ "will help maximize your productivity."
708
  msgstr ""
709
+ "Tausende von Benutzern haben die Vorteile des Kindthema-Konfigurators (CTC) "
710
+ "schon gesehen. Wenn Sie Zeit mit der Anpassung von WordPress verwenden, holt "
711
+ "CTC Pro das Maximum an Produktivität heraus."
712
 
713
  #: includes/forms/addl_panels.php:22
714
  msgid "Designed by Developers Who Use It Every Day."
715
+ msgstr "Von Entwicklern kreiert, die es jeden Tag benutzen."
716
 
717
  #: includes/forms/addl_panels.php:23
718
  msgid ""
719
+ "We've packed in more features to make design work quicker and easier with "
720
+ "<strong>Child Theme Configurator Pro.</strong>"
721
  msgstr ""
722
+ "Wir haben noch mehr Funktionen hineingepackt, um das Designen schneller und "
723
+ "einfacher zu machen mit <strong>Child Theme Configurator Pro.</strong>"
724
 
725
  #: includes/forms/addl_panels.php:25
726
  msgid "Customize Plugin Stylesheets"
728
 
729
  #: includes/forms/addl_panels.php:26
730
  msgid ""
731
+ "Apply the power of CTC's top-rated interface to your site's plugin styles. "
732
+ "All new design makes it much easier to get the results you want."
733
  msgstr ""
734
+ "Wenden Sie die Macht von CTC's top-bewerteter Schnittstelle für Ihre Plugin-"
735
+ "Stile an. Das ganz neue Design macht es noch einfacher, die gewünschten "
736
+ "Resultate zu erhalten."
737
 
738
  #: includes/forms/addl_panels.php:27
739
  msgid "Quick Preview"
740
+ msgstr "Schnelle Vorschau"
741
 
742
  #: includes/forms/addl_panels.php:27
743
+ msgid "Preview your child theme with a single click."
744
+ msgstr "Vorschau Ihres Kindthemas mit nur einem Klick."
745
 
746
  #: includes/forms/addl_panels.php:28
747
  msgid "Color Palettes"
749
 
750
  #: includes/forms/addl_panels.php:28
751
  msgid ""
752
+ "Keep the colors you select just a click away. No more searching for hex "
753
+ "codes and RGB values."
754
  msgstr ""
755
+ "Die gewünschten Farben nur einen Klick entfernt. Kein umständliches Suchen "
756
+ "nach Hex-Codes und RGB-Werten."
757
 
758
  #: includes/forms/addl_panels.php:29
759
  msgid "Find related styles"
760
+ msgstr "Finde verwandte Stile"
761
 
762
  #: includes/forms/addl_panels.php:29
763
  msgid ""
764
+ "Use the \"All Styles\" panel to edit groups of selectors from a single "
765
+ "combined list."
766
  msgstr ""
767
+ "Benutze Sie das \"Alle Stile\"-Werkzeug, um Gruppen von Selektoren in einer "
768
  "einzigen kombinierten Liste zu bearbeiten."
769
 
770
  #: includes/forms/addl_panels.php:30
773
 
774
  #: includes/forms/addl_panels.php:30
775
  msgid "Tweak menus quickly and easily."
776
+ msgstr "Menüs einfach und schnell anpassen."
777
 
778
  #: includes/forms/addl_panels.php:31
779
  msgid "Most recent edits"
782
  #: includes/forms/addl_panels.php:31
783
  msgid "Return to recently edited selectors from a toggleable sidebar."
784
  msgstr ""
785
+ "Zu den kürzlich bearbeiteten Selektoren mittels Umschalt-Seitenleiste "
786
+ "zurückkehren."
787
 
788
  #: includes/forms/addl_panels.php:32
789
  msgid "Genesis Framework Support"
791
 
792
  #: includes/forms/addl_panels.php:33
793
  msgid ""
794
+ "Automatically detects and configures Genesis Child Themes with more "
795
+ "frameworks on the way."
796
  msgstr ""
797
+ "Entdeckt und konfiguriert automatisch Genesis-Kindthemen (mehr Frameworks "
798
+ "werden folgen)."
799
 
800
  #: includes/forms/addl_panels.php:34
801
  msgid "Top-rated Online Support"
807
 
808
  #: includes/forms/addl_panels.php:36
809
  msgid "Tutorial Videos"
810
+ msgstr "Anleitungs-Videos"
811
 
812
  #: includes/forms/addl_tabs.php:8
813
  msgid "Upgrade"
814
+ msgstr "Upgrade"
815
 
816
  #: includes/forms/backup.php:8
817
  msgid "Backup"
818
+ msgstr "Backup"
819
 
820
+ #: includes/forms/backups.php:10
821
  msgid "Restore backup from"
822
+ msgstr "Backup wiederherstellen vom"
823
 
824
  #: includes/forms/fileform.php:8
825
+ msgid ""
826
+ "The Theme editor has been disabled. Template files must be edited offline."
827
  msgstr ""
828
+ "Der Themeneditor wurde deaktiviert. Vorlagendateien müssen offline "
829
+ "bearbeitet werden."
830
 
831
  #: includes/forms/fileform.php:12
832
  msgid "Click here to edit template files using the Theme Editor"
833
+ msgstr ""
834
+ "Hier klicken, um die Vorlagendateien mit dem Themeneditor zu bearbeiten"
835
 
836
  #: includes/forms/fileform.php:23
837
  msgid "Parent Templates"
839
 
840
  #: includes/forms/fileform.php:23
841
  msgid "Child Theme Files"
842
+ msgstr "Kindthemen-Dateien"
843
 
844
  #: includes/forms/fileform.php:28
845
+ msgid ""
846
+ "Copy PHP templates from the parent theme by selecting them here. The "
847
+ "Configurator defines a template as a Theme PHP file having no PHP functions "
848
+ "or classes. Other PHP files cannot be safely overridden by a child theme."
849
  msgstr ""
850
+ "PHP-Vorlagendateien des Elternthemas kopieren, indem Sie sie hier auswählen. "
851
+ "Der Konfigurator definiert eine Vorlage als eine PHP-Datei ohne Klassen bzw. "
852
+ "Funktionen. Andere PHP-Dateien können vom Kindthema nicht sicher "
853
+ "überschrieben werden."
854
 
855
  #: includes/forms/fileform.php:31
856
  msgid ""
857
+ "CAUTION: If your child theme is active, the child theme version of the file "
858
+ "will be used instead of the parent immediately after it is copied."
859
  msgstr ""
860
+ "WARNUNG: Wenn Ihr Kindthema aktiv ist, wird sofort die Kindthema-Version der "
861
+ "Datei anstelle der Eltern-Version benutzt, nachdem sie kopiert wurde."
862
 
863
  #: includes/forms/fileform.php:33
864
  msgid "The %s file is generated separately and cannot be copied here."
865
+ msgstr "Die %s-Datei wird separat erzeugt und kann hier nicht kopiert werden."
866
 
867
  #: includes/forms/fileform.php:43
868
  msgid "Delete child theme templates by selecting them here."
869
+ msgstr "Kindthema-Vorlagen löschen, indem Sie sie hier auswählen."
870
 
871
  #: includes/forms/fileform.php:44
872
  msgid ""
873
+ "Delete child theme templates or make them writable by selecting them here. "
874
+ "Writable files are displayed in <span style=\"color:red\">red</span>."
875
  msgstr ""
876
+ "Kindthema-Vorlagen löschen oder beschreibbar machen, indem Sie sie hier "
877
+ "auswählen. Beschreibbare Dateien sind in <span style=\"color:red\">rot</"
878
+ "span> angezeigt."
879
 
880
  #: includes/forms/fileform.php:57
881
  msgid "Make Selected Writable"
882
+ msgstr "Auswahl beschreibbar machen"
883
 
884
  #: includes/forms/fileform.php:61
885
  msgid "Copy Selected to Child Theme"
886
+ msgstr "In gewähltes Kindthema kopieren"
887
 
888
  #: includes/forms/fileform.php:61 includes/forms/images.php:21
889
  msgid "Delete Selected"
891
 
892
  #: includes/forms/files.php:15
893
  msgid "Upload New Child Theme Image"
894
+ msgstr "Neues Kindthema-Abbild (Image) hochladen"
895
 
896
  #: includes/forms/files.php:18
897
  msgid ""
898
+ "Theme images reside under the <code>images</code> directory in your child "
899
+ "theme and are meant for stylesheet use only. Use the Media Library for "
900
+ "content images."
901
  msgstr ""
902
+ "Themenbilder befinden sich unter dem <code>images</code>-Verzeichnis in "
903
+ "Ihrem Kindthema und sind nur für Formatvorlagen gedacht. Nutzen Sie die "
904
  "Medienbibliothek für Inhaltsbilder."
905
 
906
  #: includes/forms/files.php:25 includes/forms/files.php:51
909
 
910
  #: includes/forms/files.php:32
911
  msgid "Child Theme Screenshot"
912
+ msgstr "Kindthema-Screenshot"
913
 
914
  #: includes/forms/files.php:41
915
  msgid "Upload New Screenshot"
916
+ msgstr "Neuer Kindthema-Screenshot"
917
 
918
  #: includes/forms/files.php:44
919
  msgid ""
920
+ "The theme screenshot should be a 4:3 ratio (e.g., 880px x 660px) JPG, PNG or "
921
+ "GIF. It will be renamed <code>screenshot</code>."
922
  msgstr ""
923
+ "Der Themen-Screenshot sollte das Format 4:3 haben (bspw. 880px x 660px) JPG, "
924
+ "PNG oder GIF. Es wird umbenannt zu <code>screenshot</code>."
925
 
926
+ #: includes/forms/files.php:57
927
  msgid "Export Child Theme as Zip Archive"
928
+ msgstr "Kindthema als ZIP-Archiv exportieren"
 
 
 
 
929
 
930
+ #: includes/forms/files.php:68
931
  msgid "Secure Child Theme"
932
+ msgstr "Kindthema absichern"
933
 
934
+ #: includes/forms/files.php:71
935
+ msgid ""
936
+ "Attempt to reset child theme permissions to user ownership and read-only "
937
+ "access."
938
  msgstr ""
939
+ "Versuche, die Kindthema-Berechtigungen zurückzusetzen (auf Nur-Lese-Zugriff "
940
+ "und Benutzerbesitz)."
941
 
942
+ #: includes/forms/files.php:77
943
  msgid "Make read-only"
944
+ msgstr "Nur-Lesbar machen"
945
 
946
  #: includes/forms/images.php:10
947
  msgid "Child Theme Images"
948
+ msgstr "Kindthemen-Bilder"
949
 
950
  #: includes/forms/images.php:13
951
  msgid "Delete child theme images by selecting them here."
952
+ msgstr "Auswahl der Kindthemen-Bilder zum Löschen."
953
 
954
+ #: includes/forms/main.php:34
955
  msgid "version"
956
+ msgstr "Version"
957
 
958
+ #: includes/forms/main.php:38
959
+ msgid "Debug"
960
+ msgstr "Debug"
961
 
962
+ #: includes/forms/main.php:41
963
+ msgid "Currently Loaded"
964
+ msgstr "Aktuell geladen"
965
 
966
+ #: includes/forms/parent-child.php:22
967
+ msgid "Select an action:"
968
+ msgstr "Aktion auswählen:"
969
 
970
+ #: includes/forms/parent-child.php:29
971
+ msgid "CREATE a new Child Theme"
972
+ msgstr "ERZEUGE ein neues Kindthema"
973
+
974
+ #: includes/forms/parent-child.php:32
975
+ msgid ""
976
+ "Install a new customizable child theme using an installed theme as a parent."
977
+ msgstr ""
978
+ "Ein neues anpassbares Kindthema mittels installiertem Thema als Elternthema "
979
+ "installieren."
980
 
981
  #: includes/forms/parent-child.php:43
982
+ msgid "CONFIGURE an existing Child Theme"
983
+ msgstr "Bestehendes Kindthema ANPASSEN"
984
 
985
+ #: includes/forms/parent-child.php:46
986
+ msgid ""
987
+ "Set up a previously installed child theme for use with the Configurator or "
988
+ "to modify current settings."
989
+ msgstr ""
990
+ "Ein vorher installiertes Kindthema aufsetzen, um es mit dem Konfigurator "
991
+ "bearbeiten zu können."
992
 
993
+ #: includes/forms/parent-child.php:55
994
+ msgid "DUPLICATE an existing Child Theme"
995
+ msgstr "Bestehenes Kindthema DUPLIZIEREN"
996
 
997
+ #: includes/forms/parent-child.php:58
998
+ msgid ""
999
+ "Make a complete copy of an existing Child Theme in a new directory, "
1000
+ "including any menus, widgets and other Customizer settings. The option to "
1001
+ "copy the Parent Theme settings (step 8, below) is disabled with this action."
1002
+ msgstr ""
1003
+ "Eine vollständige Kopie eines bestehenden Kindthemas in neuem Verzeichnis "
1004
+ "erstellen, inkl. Menüs, Widgets und andere Einstellungen. Die Option zum "
1005
+ "Kopieren der Elternthema-Einstellungen (Schritt 8 unten) ist mit dieser "
1006
+ "Aktion deaktiviert."
1007
 
1008
+ #: includes/forms/parent-child.php:67
1009
+ msgid ""
1010
+ "RESET an existing Child Theme (this will destroy any work you have done in "
1011
+ "the Configurator)"
1012
+ msgstr ""
1013
+ "Ein bestehendes Kindthema ZURÜCKSETZEN (zerstört all Ihre bisherige Arbeit "
1014
+ "mit dem Konfigurator)"
1015
 
1016
+ #: includes/forms/parent-child.php:70
1017
+ msgid ""
1018
+ "Revert the Child theme stylesheet and functions files to their state before "
1019
+ "the initial configuration or last reset. Additional child theme files will "
1020
+ "not be removed, but you can delete them under the Files tab."
1021
+ msgstr ""
1022
+ "Kindthema-Formatvorlage und Funktionsdateien auf ihren ursprünglichen "
1023
+ "Zustand setzen (vor der Initial-Konfiguration oder dem letzten "
1024
+ "Zurücksetzen). Zusätzliche Kindthemen-Dateien werden belassen, aber sie "
1025
+ "können mittels \"Dateien\"-Tab gelöscht werden."
1026
 
1027
+ #: includes/forms/parent-child.php:79
1028
+ msgid "Select a Parent Theme:"
1029
+ msgstr "Elternthema auswählen:"
1030
 
1031
+ #: includes/forms/parent-child.php:83 includes/forms/parent-child.php:96
1032
+ msgid "Analyze"
1033
+ msgstr "Analysieren"
1034
 
1035
+ #: includes/forms/parent-child.php:85
1036
+ msgid "Analyze Parent Theme"
1037
+ msgstr "Analysiere Elternthema"
1038
 
1039
+ #: includes/forms/parent-child.php:85 includes/forms/parent-child.php:98
1040
+ msgid ""
1041
+ "Click \"Analyze\" to determine stylesheet dependencies and other potential "
1042
+ "issues."
1043
+ msgstr ""
1044
+ "\"Analysieren\" klicken, um Formatvorlage-Abhängigkeiten und andere mögliche "
1045
+ "Probleme zu erkennen."
1046
 
1047
+ #: includes/forms/parent-child.php:92
1048
+ msgid "Select a Child Theme:"
1049
+ msgstr "Kindthema auswählen:"
1050
 
1051
+ #: includes/forms/parent-child.php:98
1052
+ msgid "Analyze Child Theme"
1053
+ msgstr "Kindthema analysieren"
1054
 
1055
+ #: includes/forms/parent-child.php:106
1056
+ msgid "Name the new theme directory:"
1057
+ msgstr "Neues Verzeichnis benennen:"
1058
 
1059
+ #: includes/forms/parent-child.php:109
1060
+ msgid "Directory Name"
1061
+ msgstr "Verzeichnisname"
1062
 
1063
+ #: includes/forms/parent-child.php:113 includes/forms/parent-child.php:307
 
1064
  msgid "NOTE:"
1065
  msgstr "HINWEIS:"
1066
 
1067
+ #: includes/forms/parent-child.php:115
1068
+ msgid ""
1069
+ "This is NOT the name of the Child Theme. You can customize the name, "
1070
+ "description, etc. in step 7, below."
1071
  msgstr ""
1072
+ "Dies ist NICHT der Name des Kindthemas. Sie können Name, Beschreibung etc. "
1073
+ "in Schritt 7 unten anpassen."
1074
 
1075
+ #: includes/forms/parent-child.php:119
1076
+ msgid "Verify Child Theme directory:"
1077
+ msgstr "Kindthema-Verzeichnis prüfen:"
 
 
 
 
 
 
 
 
 
 
 
 
1078
 
1079
+ #: includes/forms/parent-child.php:125
1080
+ msgid ""
1081
+ "For verification only (you cannot modify the directory of an existing Child "
1082
+ "Theme)."
1083
  msgstr ""
1084
+ "Nur zur Überprüfung (Sie können das Verzeichnis eines Kindthemas nicht "
1085
+ "verändern)."
1086
 
1087
+ #: includes/forms/parent-child.php:135 includes/forms/parent-child.php:165
1088
+ msgid "Click to expand"
1089
+ msgstr "Zum Erweitern klicken"
1090
 
1091
+ #: includes/forms/parent-child.php:136
1092
+ msgid "Select where to save new styles:"
1093
+ msgstr "Speicherort der neuen Stile auswählen:"
1094
 
1095
+ #: includes/forms/parent-child.php:143
1096
+ msgid "Primary Stylesheet (style.css)"
1097
+ msgstr "Primäre Formatvorlage (style.css)"
1098
 
1099
+ #: includes/forms/parent-child.php:146
 
 
 
 
1100
  msgid ""
1101
+ "Save new custom styles directly to the Child Theme primary stylesheet, "
1102
+ "replacing the existing values. The primary stylesheet will load in the order "
1103
+ "set by the theme."
1104
  msgstr ""
1105
+ "Sichere neue angepasste Stile direkt in das primäre Formatvorlage des "
1106
+ "Kindthemas (ersetze vorhandene Werte). Die primäre Formatvorlage wird in "
1107
+ "definierter Reihenfolge geladen."
1108
 
1109
+ #: includes/forms/parent-child.php:156
1110
+ msgid "Separate Stylesheet"
1111
+ msgstr "Separate Formatvorlage"
1112
 
1113
+ #: includes/forms/parent-child.php:159
1114
  msgid ""
1115
+ "Save new custom styles to a separate stylesheet and use any existing child "
1116
+ "theme styles as a baseline. Select this option if you want to preserve the "
1117
+ "original child theme styles instead of overwriting them. This option also "
1118
+ "allows you to customize stylesheets that load after the primary stylesheet."
1119
  msgstr ""
1120
+ "Sichere neue angepasste Stile in separates Formatvorlage und verwende "
1121
+ "bestehende Kindthemen-Stile als Basis. Diese Option wählen, wenn Sie die "
1122
+ "Original-Kindthemen-Stile behalten wollen (statt zu überschreiben). Diese "
1123
+ "Option erlaubt Ihnen, nach der primären Formatvorlage geladene "
1124
+ "Formatvorlagen anzupassen."
1125
 
1126
+ #: includes/forms/parent-child.php:166
1127
+ msgid "Select Parent Theme stylesheet handling:"
1128
+ msgstr "Elternthema-Formatvorlage Behandlung auswählen:"
1129
 
1130
+ #: includes/forms/parent-child.php:179
1131
+ msgid "Use the WordPress style queue."
1132
+ msgstr "Benutze die WordPress Stil-Warteschlange."
1133
+
1134
+ #: includes/forms/parent-child.php:183
1135
  msgid ""
1136
+ "Let the Configurator determine the appropriate actions and dependencies and "
1137
+ "update the functions file automatically."
 
1138
  msgstr ""
1139
+ "Den Konfigurator die richtigen Aktionen und Abhängigkeiten auswählen lassen "
1140
+ "und Funktionendateien automatisch aktualisieren."
 
 
 
 
 
 
1141
 
1142
+ #: includes/forms/parent-child.php:189
1143
+ msgid "Use <code>@import</code> in the child theme stylesheet."
1144
+ msgstr "Benutze <code>@import</code> in der Kindthema-Formatvorlage."
1145
 
1146
+ #: includes/forms/parent-child.php:193
1147
  msgid ""
1148
+ "Only use this option if the parent stylesheet cannot be loaded using the "
1149
+ "WordPress style queue. Using <code>@import</code> is not recommended."
 
1150
  msgstr ""
1151
+ "Diese Option nur benutzen, wenn die Eltern-Formatvorlage nicht mit der "
1152
+ "WordPress-Warteschlange geladen werden kann. Benutzung von <code>@import</"
1153
+ "code> ist nicht länger empfohlen."
1154
 
1155
+ #: includes/forms/parent-child.php:199
1156
+ msgid "Do not add any parent stylesheet handling."
1157
+ msgstr "Keine zusätzliche Eltern-Formatvorlage-Behandlung hinzufügen."
1158
 
1159
+ #: includes/forms/parent-child.php:202
1160
  msgid ""
1161
+ "Select this option if this theme already handles the parent theme stylesheet "
1162
+ "or if the parent theme's <code>style.css</code> file is not used for its "
1163
+ "appearance."
1164
  msgstr ""
1165
+ "Diese Option wählen, wenn dieses Thema die Elternthema-Formatvorlage schon "
1166
+ "behandelt oder die Eltern-Thema <code>style.css</code>-Datei für die Anzeige "
1167
+ "nicht benutzt wird."
1168
 
1169
  #: includes/forms/parent-child.php:205
1170
+ msgid "Additional handling options"
1171
+ msgstr "Zusätzliche Behandlungs-Optionen"
1172
 
1173
+ #: includes/forms/parent-child.php:212
1174
+ msgid "Ignore parent theme stylesheets."
1175
+ msgstr "Elternthema-Formatvorlagen ignorieren."
1176
+
1177
+ #: includes/forms/parent-child.php:213
1178
+ msgid ""
1179
+ "Do not load or parse the parent theme styles. Only use this option if the "
1180
+ "Child Theme uses a Framework like Genesis and only uses child theme "
1181
+ "stylesheets for its appearance."
1182
  msgstr ""
1183
+ "Elternthema-Stile nicht laden oder auslesen. Diese Option nur benutzen, "
1184
+ "falls das Kindthema ein Framework wie Genesis nutzt und Kindthemen-"
1185
+ "Formatvorlagen für die Anzeige benutzt."
1186
 
1187
+ #: includes/forms/parent-child.php:222
1188
+ msgid "Repair the header template in the child theme."
1189
+ msgstr "Den Header der Vorlage im Kindthema reparieren."
1190
 
1191
+ #: includes/forms/parent-child.php:223
1192
  msgid ""
1193
+ "Let the Configurator (try to) resolve any stylesheet issues listed above. "
1194
+ "This can fix many, but not all, common problems."
1195
  msgstr ""
1196
+ "Den Konfigurator die obigen Probleme mit Formatvorlagen selber lösen lassen. "
1197
+ "Dies kann viele, aber nicht alle der üblichen Probleme lösen."
1198
+
1199
+ #: includes/forms/parent-child.php:228
1200
+ msgid "Click to toggle form"
1201
+ msgstr "Klicken um Formular umzuschalten"
1202
+
1203
+ #: includes/forms/parent-child.php:229
1204
+ msgid "Customize the Child Theme Name, Description, Author, Version, etc.:"
1205
+ msgstr "Kindthema-Name, Beschreibung, Autor, Version etc. anpassen"
1206
+
1207
+ #: includes/forms/parent-child.php:230
1208
+ msgid "(Click to toggle form)"
1209
+ msgstr "(Klicken um Formular umzuschalten)"
1210
 
1211
  #: includes/forms/parent-child.php:234
1212
+ msgid "Child Theme Name"
1213
+ msgstr "Name des Kindthemas"
1214
 
1215
+ #: includes/forms/parent-child.php:238
1216
+ msgid "Theme Name"
1217
+ msgstr "Themenname"
1218
 
1219
+ #: includes/forms/parent-child.php:243 includes/forms/parent-child.php:247
1220
+ msgid "Theme Website"
1221
+ msgstr "Themenwebseite"
1222
+
1223
+ #: includes/forms/parent-child.php:252 includes/forms/parent-child.php:256
1224
+ msgid "Author"
1225
+ msgstr "Autor"
1226
+
1227
+ #: includes/forms/parent-child.php:261 includes/forms/parent-child.php:265
1228
+ msgid "Author Website"
1229
+ msgstr "Autoren-Webseite"
1230
+
1231
+ #: includes/forms/parent-child.php:270
1232
+ msgid "Theme Description"
1233
+ msgstr "Themen-Beschreibung"
1234
+
1235
+ #: includes/forms/parent-child.php:273
1236
+ msgid "Description"
1237
+ msgstr "Beschreibung"
1238
+
1239
+ #: includes/forms/parent-child.php:278
1240
+ msgid "Theme Tags"
1241
+ msgstr "Themen-Schlagwörter"
1242
 
1243
+ #: includes/forms/parent-child.php:281
1244
+ msgid "Tags"
1245
+ msgstr "Schlagwörter"
1246
 
1247
+ #: includes/forms/parent-child.php:286 includes/forms/parent-child.php:290
1248
+ msgid "Version"
1249
+ msgstr "Version"
1250
 
1251
+ #: includes/forms/parent-child.php:299
1252
  msgid ""
1253
+ "Copy Menus, Widgets and other Customizer Settings from the Parent Theme to "
1254
+ "the Child Theme:"
1255
  msgstr ""
1256
+ "Kopiere Menüs, Widgets, und andere Customizer-Einstellungen vom Elternthema "
1257
+ "in das Kindthema:"
1258
 
1259
+ #: includes/forms/parent-child.php:309
1260
+ msgid ""
1261
+ "This option replaces the Child Theme's existing Menus, Widgets and other "
1262
+ "Customizer Settings with those from the Parent Theme. You should only need "
1263
+ "to use this option the first time you configure a Child Theme."
1264
+ msgstr ""
1265
+ "Diese Option ersetzt bestehende Menüs, Widgets und andere Customizer-"
1266
+ "Einstellungen des Kindthemas mit denen des Elternthemas. Sie sollten diese "
1267
+ "Option nur bei der ersten Konfiguration eines Kindthemas verwenden."
1268
+
1269
+ #: includes/forms/parent-child.php:316 includes/forms/parent-child.php:353
1270
+ msgid "Click to run the Configurator:"
1271
+ msgstr "Klicken, um den Konfigurator laufen zu lassen:"
1272
+
1273
+ #: includes/forms/parent-child.php:319
1274
+ msgid "Configure Child Theme"
1275
+ msgstr "Kindthema konfigurieren"
1276
 
1277
+ #: includes/forms/parent-child.php:337
1278
+ msgid "Parse Plugin stylesheets:"
1279
+ msgstr "Plugin-Formatvorlagen einlesen"
1280
 
1281
+ #: includes/forms/parent-child.php:341
1282
+ msgid "Select the plugin stylesheets you wish to customize below."
1283
+ msgstr "Plugin-Formatvorlagen zum Anpassen unten auswählen"
1284
 
1285
+ #: includes/forms/parent-child.php:356
1286
+ msgid "Configure Plugin Styles"
1287
+ msgstr "Plugin-Stile konfigurieren"
1288
 
1289
  #: includes/forms/query-selector.php:13
1290
+ msgid "@media Query"
1291
+ msgstr "@media Query"
1292
+
1293
+ #: includes/forms/query-selector.php:14
1294
+ msgid "( or \"base\" )"
1295
+ msgstr "( oder \"base\" )"
1296
 
1297
  #: includes/forms/query-selector.php:24
1298
  msgid "Selector"
1304
 
1305
  #: includes/forms/query-selector.php:45
1306
  msgid "Save Child Values"
1307
+ msgstr "Kindwerte schreiben"
1308
 
1309
  #: includes/forms/query-selector.php:46
1310
  msgid "Delete Child Values"
1311
+ msgstr "Kindwerte löschen"
1312
 
1313
  #: includes/forms/query-selector.php:53 includes/forms/rule-value.php:13
1314
  msgid "Property"
1315
  msgstr "Eigenschaft"
1316
 
1317
  #: includes/forms/query-selector.php:56
1318
+ msgid "Baseline Value"
1319
+ msgstr "Basiswert"
1320
 
1321
  #: includes/forms/query-selector.php:59
1322
  msgid "Child Value"
1323
+ msgstr "Kindwert"
1324
 
1325
  #: includes/forms/query-selector.php:65
1326
  msgid "New Property"
1332
 
1333
  #: includes/forms/query-selector.php:84
1334
  msgid "Copy Selector"
1335
+ msgstr "Selektor kopieren"
1336
 
1337
  #: includes/forms/query-selector.php:86 includes/forms/webfonts.php:15
1338
  msgid "Save"
1345
  #: includes/forms/query-selector.php:91
1346
  msgid "Use to enter shorthand CSS or new @media queries and selectors."
1347
  msgstr ""
1348
+ "Benutzen, um Shorthand-CSS oder neue @media-Queries und Selektoren "
1349
+ "einzugeben."
1350
 
1351
  #: includes/forms/query-selector.php:91
1352
  msgid ""
1353
+ "Values entered here are merged into existing child styles or added to the "
1354
+ "child stylesheet if they do not exist in the parent."
1355
  msgstr ""
1356
+ "Hier eingegebene Werte werden in bestehende Kind-Stile eingefügt oder "
1357
+ "hinzugefügt, falls sie im Eltern-Stil nicht bestehen sollten."
1358
 
1359
  #: includes/forms/related.php:1
1360
  msgid "New user?"
1362
 
1363
  #: includes/forms/related.php:1
1364
  msgid "Click help"
1365
+ msgstr "Klicken Sie auf Hilfe"
1366
 
1367
  #: includes/forms/related.php:1
1368
  msgid "Get CTC Pro and other tools"
1370
 
1371
  #: includes/forms/related.php:1
1372
  msgid "Lilaea Media - Responsive Tools for a Mobile World"
1373
+ msgstr "Klicken um Formular umzuschalten"
1374
 
1375
  #: includes/forms/rule-value.php:26
1376
  msgid "Value"
1380
  msgid "Parent/Child"
1381
  msgstr "Eltern/Kind"
1382
 
1383
+ #: includes/forms/tabs.php:14
1384
  msgid "Query/Selector"
1385
  msgstr "Abfrage/Selektor"
1386
 
1387
+ #: includes/forms/tabs.php:17
1388
  msgid "Property/Value"
1389
  msgstr "Eigenschaft/Wert"
1390
 
1391
+ #: includes/forms/tabs.php:20
1392
  msgid "Web Fonts"
1393
  msgstr "Webschriftarten"
1394
 
1395
+ #: includes/forms/tabs.php:23
1396
+ msgid "Baseline Styles"
1397
+ msgstr "Basis-Stile"
1398
 
1399
+ #: includes/forms/tabs.php:26
1400
+ msgid "Child Styles"
1401
+ msgstr "Kind-Stile"
1402
 
1403
+ #: includes/forms/tabs.php:30
1404
  msgid "Files"
1405
  msgstr "Dateien"
1406
 
1418
 
1419
  #: includes/forms/themepreview.php:17
1420
  msgid " in default Site"
1421
+ msgstr " in Standard-Seite"
1422
 
1423
  #: includes/forms/themepreview.php:21
1424
  msgid "Not Network Enabled"
1430
 
1431
  #: includes/forms/webfonts.php:20
1432
  msgid ""
1433
+ "Use <code>@import url( [path] );</code> to link additional stylesheets. "
1434
+ "Child Theme Configurator uses the <code>@import</code> keyword to identify "
1435
+ "them and convert them to <code>&lt;link&gt;</code> tags. <strong>Example:</"
1436
+ "strong>"
1437
  msgstr ""
1438
+ "Benutze <code>@import url( [path] );</code>, um zusätzliche Formatvorlagen "
1439
+ "zu verknüpfen. CTC benutzt das <code>@import</code> Schlüsselwort, um sie zu "
1440
+ "identifizieren und sie in <code>&lt;link&gt;</code> Tags zu konvertieren. "
1441
+ "<strong>Beispiel:</strong>"
1442
+
1443
+ #: includes/forms/zipform.php:8
1444
+ msgid "Export Zip"
1445
+ msgstr "ZIP-Export"
1446
 
1447
  #. Plugin URI of the plugin/theme
1448
  msgid "http://www.childthemeconfigurator.com"
1450
 
1451
  #. Description of the plugin/theme
1452
  msgid ""
1453
+ "When using the Customizer is not enough - Create child themes and customize "
1454
+ "styles, templates, functions and more."
1455
  msgstr ""
1456
+ "Wenn der Customizer nicht genug sein sollte - Erzeugen Sie Kindthemen und "
1457
+ "passen Sie Stile, Vorlagen, Funktionen und mehr an."
 
1458
 
1459
  #. Author of the plugin/theme
1460
  msgid "Lilaea Media"
1463
  #. Author URI of the plugin/theme
1464
  msgid "http://www.lilaeamedia.com"
1465
  msgstr "http://www.lilaeamedia.com"
1466
+
1467
+ #~ msgid "Could not copy file"
1468
+ #~ msgstr "Konnte Datei nicht kopieren"
1469
+
1470
+ #~ msgid ""
1471
+ #~ "<p>\"Do not add any parent stylesheet handling\" has been selected for "
1472
+ #~ "\"Parent stylesheet handling\" (see step 6, below).</p>"
1473
+ #~ msgstr ""
1474
+ #~ "<p>\"Elternthema-Behandlung nicht hinzufügen\" wurde ausgewählt für "
1475
+ #~ "\"Elternthema-Behandlung\" (siehe Schritt 6 unten).</p>"
1476
+
1477
+ #~ msgid ""
1478
+ #~ "Child Theme Configurator did not detect any configuration data because a "
1479
+ #~ "previously configured Child Theme has been removed. Please set your "
1480
+ #~ "preferences below and click \"Generate Child Theme Files\"."
1481
+ #~ msgstr ""
1482
+ #~ "Der Kindthema-Konfigurator enteckte keine Konfigurationsdaten, weil ein "
1483
+ #~ "früher konfiguriertes Kindthema entfernt wurde. Bitte setzen Sie Ihre "
1484
+ #~ "Voreinstellungen unten und klicken Sie auf \"Erzeugen Kindthema-Dateien\"."
1485
+
1486
+ #~ msgid "Export"
1487
+ #~ msgstr "Exportieren"
1488
+
1489
+ #~ msgid ""
1490
+ #~ "Copy Parent Theme Menus, Widgets and other Customizer Settings to Child "
1491
+ #~ "Theme:"
1492
+ #~ msgstr ""
1493
+ #~ "Kopieren der Elternthema-Menüs, Widgets und anderer Einstellungen in das "
1494
+ #~ "Kindthema:"
1495
+
1496
+ #~ msgid ""
1497
+ #~ "This will overwrite any child theme options you may have already set."
1498
+ #~ msgstr ""
1499
+ #~ "Dies überschreibt alle Werte des Kindthemas, die allenfalls schon gesetzt "
1500
+ #~ "sind."
1501
+
1502
+ #~ msgid ""
1503
+ #~ "Create child themes and customize styles, templates and functions. "
1504
+ #~ "Enqueues stylesheets and web fonts. Handles rgba, vendor-prefixes and "
1505
+ #~ "more."
1506
+ #~ msgstr ""
1507
+ #~ "Benutze Kindthemen und passe Stile, Vorlagen und Funktionen an. Behandelt "
1508
+ #~ "Formatvorlagen und Webschriftarten sowie RGBA, Hersteller-Präfixe und "
1509
+ #~ "mehr."
lang/child-theme-configurator.pot CHANGED
@@ -1,327 +1,447 @@
1
- # Copyright (C) 2015 Child Theme Configurator
2
  # This file is distributed under the same license as the Child Theme Configurator package.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: Child Theme Configurator 1.7.8\n"
6
  "Report-Msgid-Bugs-To: http://wordpress.org/tag/child-theme-configurator\n"
7
- "POT-Creation-Date: 2015-09-24 00:16:38+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
11
- "PO-Revision-Date: 2015-MO-DA HO:MI+ZONE\n"
12
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13
  "Language-Team: LANGUAGE <LL@li.org>\n"
14
 
15
- #. #-#-#-#-# chld_thm_cfg.pot (Child Theme Configurator 1.7.8) #-#-#-#-#
16
- #. Plugin Name of the plugin/theme
17
- #: child-theme-configurator.php:78 child-theme-configurator.php:88
18
- #: includes/forms/main.php:23
19
- msgid "Child Theme Configurator"
20
  msgstr ""
21
 
22
- #: child-theme-configurator.php:79 child-theme-configurator.php:89
23
- #: child-theme-configurator.php:99
24
- msgid "Child Themes"
25
  msgstr ""
26
 
27
- #: child-theme-configurator.php:114
28
- msgid "Child Theme Configurator requires WordPress version %s or later."
29
  msgstr ""
30
 
31
- #: includes/class-ctc-ui.php:52
32
- msgid "A stylesheet link tag is hard-coded into the header template."
33
  msgstr ""
34
 
35
- #: includes/class-ctc-ui.php:53
36
- msgid "<code>wp_enqueue_style()</code> called from the header template."
37
  msgstr ""
38
 
39
- #: includes/class-ctc-ui.php:55
40
- msgid ""
41
- "Code exists between the <code>wp_head()</code> function and the closing "
42
- "<code>&lt;/head&gt;</code> tag."
43
  msgstr ""
44
 
45
- #: includes/class-ctc-ui.php:162
46
- msgid "Child Theme files modified successfully."
47
  msgstr ""
48
 
49
- #: includes/class-ctc-ui.php:165
50
  msgid ""
51
- "Child Theme <strong>%s</strong> has been generated successfully.\n"
52
- " "
53
  msgstr ""
54
 
55
- #: includes/class-ctc-ui.php:168
56
- msgid "IMPORTANT:"
57
  msgstr ""
58
 
59
- #: includes/class-ctc-ui.php:170 includes/forms/themepreview.php:20
60
- msgid "Go to Themes"
61
  msgstr ""
62
 
63
- #: includes/class-ctc-ui.php:170
64
- msgid "Network enable"
65
  msgstr ""
66
 
67
- #: includes/class-ctc-ui.php:170
68
- msgid "your child theme."
69
  msgstr ""
70
 
71
- #: includes/class-ctc-ui.php:172 includes/forms/themepreview.php:18
72
- msgid "Live Preview"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  msgstr ""
74
 
75
- #: includes/class-ctc-ui.php:172
76
- msgid "Test your child theme"
 
77
  msgstr ""
78
 
79
- #: includes/class-ctc-ui.php:172
80
- msgid "before activating."
81
  msgstr ""
82
 
83
- #: includes/class-ctc.php:144
84
  msgid "URL/None"
85
  msgstr ""
86
 
87
- #: includes/class-ctc.php:145
88
  msgid "Origin"
89
  msgstr ""
90
 
91
- #: includes/class-ctc.php:146
92
  msgid "Color 1"
93
  msgstr ""
94
 
95
- #: includes/class-ctc.php:147
96
  msgid "Color 2"
97
  msgstr ""
98
 
99
- #: includes/class-ctc.php:148
100
  msgid "Width/None"
101
  msgstr ""
102
 
103
- #: includes/class-ctc.php:149
104
  msgid "Style"
105
  msgstr ""
106
 
107
- #: includes/class-ctc.php:150
108
  msgid "Color"
109
  msgstr ""
110
 
111
- #: includes/class-ctc.php:152
112
- msgid "Are you sure? This will replace your current settings."
 
 
113
  msgstr ""
114
 
115
- #: includes/class-ctc.php:153
116
  msgid "<span style=\"font-size:10px\">!</span>"
117
  msgstr ""
118
 
119
- #: includes/class-ctc.php:154 includes/forms/rule-value.php:32
120
  msgid "Selectors"
121
  msgstr ""
122
 
123
- #: includes/class-ctc.php:155
124
  msgid "Close"
125
  msgstr ""
126
 
127
- #: includes/class-ctc.php:156
128
  msgid "Edit Selector"
129
  msgstr ""
130
 
131
- #: includes/class-ctc.php:157
132
  msgid "Cancel"
133
  msgstr ""
134
 
135
- #: includes/class-ctc.php:158
136
  msgid "Rename"
137
  msgstr ""
138
 
139
- #: includes/class-ctc.php:159
140
  msgid "The stylesheet cannot be displayed."
141
  msgstr ""
142
 
143
- #: includes/class-ctc.php:160
144
  msgid "(Child Only)"
145
  msgstr ""
146
 
147
- #: includes/class-ctc.php:161
148
  msgid "Please enter a valid Child Theme."
149
  msgstr ""
150
 
151
- #: includes/class-ctc.php:162
152
  msgid "Please enter a valid Child Theme name."
153
  msgstr ""
154
 
155
- #: includes/class-ctc.php:163
156
  msgid "<strong>%s</strong> exists. Please enter a different Child Theme"
157
  msgstr ""
158
 
159
- #: includes/class-ctc.php:164
160
  msgid "The page could not be loaded correctly."
161
  msgstr ""
162
 
163
- #: includes/class-ctc.php:166
164
  msgid ""
165
  "Conflicting or out-of-date jQuery libraries were loaded by another plugin:"
166
  msgstr ""
167
 
168
- #: includes/class-ctc.php:168
169
  msgid "Deactivating or replacing plugins may resolve this issue."
170
  msgstr ""
171
 
172
- #: includes/class-ctc.php:169
173
  msgid "%sWhy am I seeing this?%s"
174
  msgstr ""
175
 
176
- #: includes/class-ctc.php:392
177
- msgid "Zip file creation failed."
178
  msgstr ""
179
 
180
- #: includes/class-ctc.php:428
181
- msgid "The Functions file is required and cannot be deleted."
182
  msgstr ""
183
 
184
- #: includes/class-ctc.php:510
185
- msgid "You do not have permission to configure child themes."
186
  msgstr ""
187
 
188
- #: includes/class-ctc.php:557
189
- msgid "%s does not exist. Please select a valid Parent Theme."
190
  msgstr ""
191
 
192
- #: includes/class-ctc.php:561
193
- msgid "Please select a valid Parent Theme."
 
 
194
  msgstr ""
195
 
196
- #: includes/class-ctc.php:564
197
- msgid "Please enter a valid Child Theme directory."
 
 
 
 
198
  msgstr ""
199
 
200
- #: includes/class-ctc.php:572 includes/class-ctc.php:587
201
- msgid "Please enter a valid Child Theme template name."
202
  msgstr ""
203
 
204
- #: inclu
1
+ # Copyright (C) 2016 Child Theme Configurator
2
  # This file is distributed under the same license as the Child Theme Configurator package.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: Child Theme Configurator 2.2.0\n"
6
  "Report-Msgid-Bugs-To: http://wordpress.org/tag/child-theme-configurator\n"
7
+ "POT-Creation-Date: 2016-12-24 14:59:49+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
11
+ "PO-Revision-Date: 2016-MO-DA HO:MI+ZONE\n"
12
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13
  "Language-Team: LANGUAGE <LL@li.org>\n"
14
 
15
+ #: includes/classes/Admin.php:395
16
+ msgid "Zip file creation failed."
 
 
 
17
  msgstr ""
18
 
19
+ #: includes/classes/Admin.php:421
20
+ msgid "The Functions file is required and cannot be deleted."
 
21
  msgstr ""
22
 
23
+ #: includes/classes/Admin.php:501
24
+ msgid "You do not have permission to configure child themes."
25
  msgstr ""
26
 
27
+ #: includes/classes/Admin.php:534
28
+ msgid "%s does not exist. Please select a valid Parent Theme."
29
  msgstr ""
30
 
31
+ #: includes/classes/Admin.php:537
32
+ msgid "Please select a valid Parent Theme."
33
  msgstr ""
34
 
35
+ #: includes/classes/Admin.php:542
36
+ msgid "Please select a valid Child Theme."
 
 
37
  msgstr ""
38
 
39
+ #: includes/classes/Admin.php:546
40
+ msgid "Please enter a valid Child Theme directory name."
41
  msgstr ""
42
 
43
+ #: includes/classes/Admin.php:551
44
  msgid ""
45
+ "<strong>%s</strong> exists. Please enter a different Child Theme template "
46
+ "name."
47
  msgstr ""
48
 
49
+ #: includes/classes/Admin.php:570
50
+ msgid "Your theme directories are not writable."
51
  msgstr ""
52
 
53
+ #: includes/classes/Admin.php:651
54
+ msgid "Could not upgrade child theme"
55
  msgstr ""
56
 
57
+ #: includes/classes/Admin.php:733
58
+ msgid "Your stylesheet is not writable."
59
  msgstr ""
60
 
61
+ #: includes/classes/Admin.php:1317
62
+ msgid "Could not set write permissions."
63
  msgstr ""
64
 
65
+ #: includes/classes/Admin.php:1418
66
+ msgid "There were errors while resetting permissions."
67
+ msgstr ""
68
+
69
+ #: includes/classes/Admin.php:1492
70
+ msgid "Could not upload file."
71
+ msgstr ""
72
+
73
+ #: includes/classes/Admin.php:1518
74
+ msgid "Invalid theme root directory."
75
+ msgstr ""
76
+
77
+ #: includes/classes/Admin.php:1530
78
+ msgid "No writable temp directory."
79
+ msgstr ""
80
+
81
+ #: includes/classes/Admin.php:1560
82
+ msgid "PclZip returned zero bytes."
83
+ msgstr ""
84
+
85
+ #. #-#-#-#-# chldthmcfg.pot (Child Theme Configurator 2.2.0) #-#-#-#-#
86
+ #. Plugin Name of the plugin/theme
87
+ #: includes/classes/Core.php:94 includes/classes/Core.php:105
88
+ #: includes/forms/main.php:35
89
+ msgid "Child Theme Configurator"
90
+ msgstr ""
91
+
92
+ #: includes/classes/Core.php:95 includes/classes/Core.php:106
93
+ #: includes/classes/Core.php:117
94
+ msgid "Child Themes"
95
+ msgstr ""
96
+
97
+ #: includes/classes/Core.php:135
98
+ msgid "Child Theme Configurator requires WordPress version %s or later."
99
+ msgstr ""
100
+
101
+ #: includes/classes/UI.php:35
102
+ msgid "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
103
  msgstr ""
104
 
105
+ #: includes/classes/UI.php:98
106
+ msgid ""
107
+ "The Theme editor has been disabled. Template files must be edited offline."
108
  msgstr ""
109
 
110
+ #: includes/classes/UI.php:102
111
+ msgid "Click here to edit template files using the Theme Editor"
112
  msgstr ""
113
 
114
+ #: includes/classes/UI.php:270
115
  msgid "URL/None"
116
  msgstr ""
117
 
118
+ #: includes/classes/UI.php:271
119
  msgid "Origin"
120
  msgstr ""
121
 
122
+ #: includes/classes/UI.php:272
123
  msgid "Color 1"
124
  msgstr ""
125
 
126
+ #: includes/classes/UI.php:273
127
  msgid "Color 2"
128
  msgstr ""
129
 
130
+ #: includes/classes/UI.php:274
131
  msgid "Width/None"
132
  msgstr ""
133
 
134
+ #: includes/classes/UI.php:275
135
  msgid "Style"
136
  msgstr ""
137
 
138
+ #: includes/classes/UI.php:276
139
  msgid "Color"
140
  msgstr ""
141
 
142
+ #: includes/classes/UI.php:278
143
+ msgid ""
144
+ "Are you sure you wish to RESET? This will destroy any work you have done in "
145
+ "the Configurator."
146
  msgstr ""
147
 
148
+ #: includes/classes/UI.php:279
149
  msgid "<span style=\"font-size:10px\">!</span>"
150
  msgstr ""
151
 
152
+ #: includes/classes/UI.php:280 includes/forms/rule-value.php:33
153
  msgid "Selectors"
154
  msgstr ""
155
 
156
+ #: includes/classes/UI.php:281
157
  msgid "Close"
158
  msgstr ""
159
 
160
+ #: includes/classes/UI.php:282
161
  msgid "Edit Selector"
162
  msgstr ""
163
 
164
+ #: includes/classes/UI.php:283
165
  msgid "Cancel"
166
  msgstr ""
167
 
168
+ #: includes/classes/UI.php:284
169
  msgid "Rename"
170
  msgstr ""
171
 
172
+ #: includes/classes/UI.php:285
173
  msgid "The stylesheet cannot be displayed."
174
  msgstr ""
175
 
176
+ #: includes/classes/UI.php:286
177
  msgid "(Child Only)"
178
  msgstr ""
179
 
180
+ #: includes/classes/UI.php:287
181
  msgid "Please enter a valid Child Theme."
182
  msgstr ""
183
 
184
+ #: includes/classes/UI.php:288
185
  msgid "Please enter a valid Child Theme name."
186
  msgstr ""
187
 
188
+ #: includes/classes/UI.php:289
189
  msgid "<strong>%s</strong> exists. Please enter a different Child Theme"
190
  msgstr ""
191
 
192
+ #: includes/classes/UI.php:290
193
  msgid "The page could not be loaded correctly."
194
  msgstr ""
195
 
196
+ #: includes/classes/UI.php:291
197
  msgid ""
198
  "Conflicting or out-of-date jQuery libraries were loaded by another plugin:"
199
  msgstr ""
200
 
201
+ #: includes/classes/UI.php:292
202
  msgid "Deactivating or replacing plugins may resolve this issue."
203
  msgstr ""
204
 
205
+ #: includes/classes/UI.php:293
206
  msgid "%sWhy am I seeing this?%s"
207
  msgstr ""
208
 
209
+ #: includes/classes/UI.php:296
210
+ msgid "No Styles Available. Check Parent/Child settings."
211
  msgstr ""
212
 
213
+ #: includes/classes/UI.php:297
214
+ msgid "Updating"
215
  msgstr ""
216
 
217
+ #: includes/classes/UI.php:298
218
+ msgid "Checking"
219
  msgstr ""
220
 
221
+ #: includes/classes/UI.php:299
222
+ msgid "The theme \"%s\" generated unexpected PHP debug output."
223
  msgstr ""
224
 
225
+ #: includes/classes/UI.php:300
226
+ msgid ""
227
+ "The theme \"%s\" could not be analyzed because the preview did not render "
228
+ "correctly."
229
  msgstr ""
230
 
231
+ #: includes/classes/UI.php:301
232
+ msgid ""
233
+ "<p>First, verify you can <a href=\"%s\">preview your home page with the "
234
+ "Customizer</a> and try analyzing again.</p><p>If that does not work, try "
235
+ "temporarily disabling plugins that <strong>minify CSS</strong> or that "
236
+ "<strong>force redirects between HTTP and HTTPS</strong>.</p>"
237
  msgstr ""
238
 
239
+ #: includes/classes/UI.php:302
240
+ msgid "Click to show/hide PHP debug output"
241
  msgstr ""
242