Child Theme Configurator - Version 1.1.0

Version Description

  • Corrected parsing for certain backgrounds and gradients (e.g., supports hsla color syntax)
  • Handle empty selectors
  • Ajax load for menus and updates
  • Clean up Parent/Child form UI and validation
  • Streamlined UI overall
Download this release

Release Info

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

Version 1.1.0

child-theme-configurator.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Exit if accessed directly
3
+ if ( !defined('ABSPATH')) exit;
4
+
5
+ /*
6
+ Plugin Name: Child Theme Configurator
7
+ Plugin URI: http://www.lilaeamedia.com/plugins/child-theme-configurator/
8
+ Description: Create Child Theme from any Theme or Stylesheet
9
+ Version: 1.1.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) 2013 Lilaea Media
16
+ */
17
+
18
+ defined('LF') or define('LF', "\n");
19
+
20
+ require_once( 'includes/class-ctc.php' );
21
+ global $chld_thm_cfg;
22
+ $chld_thm_cfg = new Child_Theme_Configurator( __FILE__ );
23
+
24
+ register_uninstall_hook( __FILE__ , 'child_theme_configurator_delete_plugin');
25
+ function child_theme_configurator_delete_plugin() {
26
+ global $chld_thm_cfg;
27
+ delete_option($chld_thm_cfg->optionsName);
28
+ }
29
+
30
+
css/chld-thm-cfg.css ADDED
@@ -0,0 +1,164 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .nav-tab, .nav-tab:focus, .nav-tab:active {
2
+ outline: none;
3
+ }
4
+ .nav-tab-active {
5
+ /*background-color:#f9f9f9;*/
6
+ }
7
+ .ctc-option-panel-container {
8
+ position:relative;
9
+ min-height:600px;
10
+ max-height:800px;
11
+ overflow:auto;
12
+ }
13
+ #view_child_options_panel, #view_parnt_options_panel {
14
+ white-space:pre;
15
+ overflow:auto;
16
+ font-family:monospace;
17
+ word-wrap:normal;
18
+ }
19
+ .ctc-option-panel {
20
+ visibility: hidden;
21
+ position:absolute;
22
+ width:96%;
23
+ top:0;
24
+ left:0;
25
+ padding:10px 2%;
26
+ }
27
+ .ctc-option-panel-active {
28
+ visibility: visible;
29
+ }
30
+ .ctc-swatch {
31
+ display:block;
32
+ float:left;
33
+ font-size:16px;
34
+ padding:0;
35
+ line-height:1;
36
+ overflow: hidden;
37
+ }
38
+ .ctc-hidden {
39
+ display:none;
40
+ }
41
+ .ctc-swatch.ctc-specific {
42
+ min-height:60px;
43
+ max-height:100px;
44
+ max-width:100px;
45
+ margin:0 2% 0 0;
46
+ /*color:#7f7f7f;
47
+ border: 1px solid #ddd;*/
48
+ }
49
+ .ctc-parent-row {
50
+ clear:both;
51
+ position:relative;
52
+ margin:4px 0;
53
+ }
54
+ .ctc-parent-value {
55
+ }
56
+ .ctc-input-cell {
57
+ display:block;
58
+ float:left;
59
+ width:25%;
60
+ max-width:250px;
61
+ margin-right:2.13%;
62
+ }
63
+ .ctc-input-cell-wide {
64
+ display:block;
65
+ float:left;
66
+ width:70%;
67
+ margin-right:2.13%;
68
+ }
69
+ .ctc-input-cell-wide textarea {
70
+ width:100%;
71
+ height:200px;
72
+ white-space:pre;
73
+ overflow:auto;
74
+ font-family:monospace;
75
+ word-wrap:normal;
76
+ }
77
+ .ctc-save-input {
78
+ }
79
+ .ctc-button-cell, .ctc-input-cell.ctc-button-cell {
80
+ width:85px;
81
+ }
82
+ .ctc-textarea-button-cell {
83
+ margin:15px 0;
84
+ width:85px;
85
+ }
86
+ .ctc-selector-link {
87
+ }
88
+ .ctc-selector-handle {
89
+ }
90
+ .ctc-selector-container {
91
+ clear:both;
92
+ background:#f9f9f9;
93
+ border:1px solid #ddd;
94
+ padding:10px;
95
+ min-height:300px;
96
+ max-height:500px;
97
+ position:absolute;
98
+ width:90%;
99
+ overflow: auto;
100
+ left:0;
101
+ top:30px;
102
+ display:none;
103
+ z-index:99999;
104
+ }
105
+ .ctc-query-heading {
106
+ }
107
+ .ctc-selector-row {
108
+ clear:both;
109
+ margin: 0;
110
+ padding:8px 0;
111
+ border-top: 1px solid #ddd;
112
+ border-bottom: 1px solid #fff;
113
+ }
114
+ .ctc-input-row {
115
+ clear:both;
116
+ margin:4px 0;
117
+ padding:4px 0;
118
+ border-bottom: 1px solid #ddd;
119
+ }
120
+ .ctc-selector-value {
121
+ }
122
+ .ctc-selector-cell {
123
+ float:left;
124
+ width:30%;
125
+ margin-right:2%;
126
+ }
127
+ .ctc-child-input-cell {
128
+ display:block;
129
+ float:left;
130
+ margin-right:2.13%;
131
+
132
+ }
133
+ .ctc-child-input-cell-container {
134
+ float:left;
135
+ width:40%;
136
+ margin-right:2%;
137
+ }
138
+ .ctc-child-input-cell-container label {
139
+ float:left;
140
+ clear:both;
141
+ width:100px;
142
+ margin-right:2%;
143
+ }
144
+ .ctc-child-input-cell input[type="text"] {
145
+ width:60px;
146
+ }
147
+ .ctc-child-input-cell input[type="text"].ctc-input-wide {
148
+ width:200px;
149
+ }
150
+ .clearfix:after, .clearfix:before {
151
+ content: ' ';
152
+ display: table;
153
+ margin: 0;
154
+ padding: 0;
155
+ }
156
+
157
+ .clearfix:after {
158
+ clear: both;
159
+ }
160
+
161
+ .ie7 .clearfix {
162
+ zoom: 1;
163
+ }
164
+
includes/class-ctc-css.php ADDED
@@ -0,0 +1,813 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Exit if accessed directly
3
+ if ( !defined('ABSPATH')) exit;
4
+
5
+ /*
6
+ Class: Child_Theme_Configurator_CSS
7
+ Plugin URI: http://www.lilaeamedia.com/plugins/child-theme-configurator/
8
+ Description: Handles all CSS output, parsing, normalization
9
+ Version: 1.1.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) 2013 Lilaea Media
16
+ */
17
+ class Child_Theme_Configurator_CSS {
18
+ var $version;
19
+ // data dictionaries
20
+ var $dict_query; // @media queries and 'base'
21
+ var $dict_sel; // selectors
22
+ var $dict_qs; // query/selector lookup
23
+ var $dict_rule; // css rules
24
+ var $dict_val; // css values
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
30
+ var $querykey; // counter for dict_query
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 $updates; // temporary update cache
37
+ var $child; // child theme slug
38
+ var $parnt; // parent theme slug
39
+ var $child_name; // child theme name
40
+ var $child_author; // stylesheet author
41
+ var $child_version; // stylesheet version
42
+
43
+ function __construct() {
44
+ // scalars
45
+ $this->version = '1.1.0';
46
+ $this->querykey = 0;
47
+ $this->selkey = 0;
48
+ $this->qskey = 0;
49
+ $this->rulekey = 0;
50
+ $this->valkey = 0;
51
+ $this->child = '';
52
+ $this->parnt = '';
53
+ $this->child_name = '';
54
+ $this->child_author = 'Child Theme Configurator by Lilaea Media';
55
+ $this->child_version = '1.0';
56
+ // multi-dim arrays
57
+ $this->dict_qs = array();
58
+ $this->dict_sel = array();
59
+ $this->dict_query = array();
60
+ $this->dict_rule = array();
61
+ $this->dict_val = array();
62
+ $this->sel_ndx = array();
63
+ $this->val_ndx = array();
64
+ $this->imports = array('child' => '', 'parnt' => '');
65
+ $this->updates = array();
66
+ }
67
+
68
+ /*
69
+ * set_property
70
+ * Setter interface (scalar values only)
71
+ */
72
+ function set_property($prop, $value) {
73
+ if (is_scalar($this->{$prop}))
74
+ $this->{$prop} = $value;
75
+ else return false;
76
+ }
77
+
78
+ /*
79
+ * get_property
80
+ * Getter interface (data sliced different ways depending on objname)
81
+ */
82
+ function get_property($objname, $params = null) {
83
+ switch ($objname):
84
+ case 'updates':
85
+ return $this->obj_to_utf8($this->updates);
86
+ case 'imports':
87
+ return $this->obj_to_utf8($this->imports['child']);
88
+ case 'sel_ndx':
89
+ return $this->obj_to_utf8($this->denorm_sel_ndx(empty($params['key'])?null:$params['key']));
90
+ case 'rule_val':
91
+ return empty($params['key']) ? array() : $this->denorm_rule_val($params['key']);
92
+ case 'val_qry':
93
+ if (isset($params['rule']) && isset($this->dict_rule[$params['rule']])):
94
+ return empty($params['key']) ?
95
+ array() : $this->denorm_val_query($params['key'], $params['rule']);
96
+ endif;
97
+ case 'sel_val':
98
+ return empty($params['key']) ?
99
+ array() : $this->denorm_sel_val($params['key']);
100
+ case 'rule':
101
+ return $this->obj_to_utf8(array_flip($this->dict_rule));
102
+ case 'child':
103
+ return $this->child;
104
+ case 'parnt':
105
+ return $this->parnt;
106
+ case 'child_name':
107
+ return $this->child_name;
108
+ case 'author':
109
+ return $this->child_author;
110
+ case 'version':
111
+ return $this->child_version;
112
+ endswitch;
113
+ return false;
114
+ }
115
+
116
+ /*
117
+ * obj_to_utf8
118
+ * sets object data to UTF8
119
+ * and stringifies NULLs
120
+ */
121
+ function obj_to_utf8($data) {
122
+
123
+ if (is_object($data)) {
124
+ $data = get_object_vars($data);
125
+ }
126
+ if (is_array($data)) {
127
+ return array_map(array(&$this, __FUNCTION__), $data);
128
+ }
129
+ else {
130
+ return is_null( $data ) ? '' : utf8_encode($data);
131
+ }
132
+ }
133
+
134
+ /*
135
+ * normalize_background
136
+ * parses background shorthand value and returns
137
+ * normalized rule/value pairs for each property
138
+ */
139
+ function normalize_background($value, &$rules, &$values){
140
+ if (false !== strpos($value, 'gradient')):
141
+ // only supporting linear syntax
142
+ if (preg_match('#(linear\-|Microsoft\.)#', $value)):
143
+ $values[] = $value;
144
+ $rules[] = 'background-image';
145
+ endif;
146
+ else:
147
+ $regex = '#(url *\([^\)]+\))#';
148
+ if (preg_match($regex, $value, $matches)) $url = $matches[1];
149
+ $parts = preg_split($regex, $value);
150
+
151
+ if (count($parts) == 1):
152
+ // this is a named color or single hex color or none
153
+ $part = str_replace(' ', '', $parts[0]);
154
+ $rules[] = 'none' == $part ? 'background' : 'background-color';
155
+ $values[] = $part;
156
+ else:
157
+ $rules[] = 'background-image';
158
+ $values[] = $url;
159
+ if (!empty($parts[0]) && '' != $parts[0]):
160
+ $rules[] = 'background-color';
161
+ $values[] = trim($parts[0]);
162
+ endif;
163
+ $position = array();
164
+ foreach(preg_split('/ +/', trim($parts[1])) as $part):
165
+ if (empty($part) || '' == $part) continue;
166
+ if (false === strpos($part, 'repeat')):
167
+ $position[] = $part;
168
+ else:
169
+ $rules[] = 'background-repeat';
170
+ $values[] = $part;
171
+ endif;
172
+ endforeach;
173
+ if (count($position)):
174
+ $rules[] = 'background-position';
175
+ $values[] = implode(' ', $position);
176
+ endif;
177
+ endif;
178
+ endif;
179
+ }
180
+
181
+ /*
182
+ * normalize_font
183
+ * parses font shorthand value and returns
184
+ * normalized rule/value pairs for each property
185
+ */
186
+ function normalize_font($value, &$rules, &$values) {
187
+ $regex = '#^((\d+|bold|normal) )?((italic|normal) )?(([\d\.]+(px|r?em|%))[\/ ])?(([\d\.]+(px|r?em|%)?) )?(.+)$#is';
188
+ preg_match($regex, $value, $parts);
189
+ if (!empty($parts[2])):
190
+ $rules[] = 'font-weight';
191
+ $values[] = $parts[2];
192
+ endif;
193
+ if (!empty($parts[4])):
194
+ $rules[] = 'font-style';
195
+ $values[] = $parts[4];
196
+ endif;
197
+ if (!empty($parts[6])):
198
+ $rules[] = 'font-size';
199
+ $values[] = $parts[6];
200
+ endif;
201
+ if (!empty($parts[9])):
202
+ $rules[] = 'line-height';
203
+ $values[] = $parts[9];
204
+ endif;
205
+ if (!empty($parts[11])):
206
+ $rules[] = 'font-family';
207
+ $values[] = $parts[11];
208
+ endif;
209
+ }
210
+
211
+ /*
212
+ * normalize_margin_padding
213
+ * parses margin or padding shorthand value and returns
214
+ * normalized rule/value pairs for each property
215
+ * TODO: reassemble into shorthand when writing CSS file
216
+ */
217
+ function normalize_margin_padding($rule, $value, &$rules, &$values) {
218
+ $parts = preg_split("/ +/", trim($value));
219
+ if (!isset($parts[1])) $parts[1] = $parts[0];
220
+ if (!isset($parts[2])) $parts[2] = $parts[0];
221
+ if (!isset($parts[3])) $parts[3] = $parts[1];
222
+ $rules[0] = $rule . '-top';
223
+ $values[0] = $parts[0];
224
+ $rules[1] = $rule . '-right';
225
+ $values[1] = $parts[1];
226
+ $rules[2] = $rule . '-bottom';
227
+ $values[2] = $parts[2];
228
+ $rules[3] = $rule . '-left';
229
+ $values[3] = $parts[3];
230
+ }
231
+
232
+ /*
233
+ * parse_css_file
234
+ * reads stylesheet to get WordPress meta data and passes rest to parse_css
235
+ */
236
+ function parse_css_file($template) {
237
+ if (empty($this->{$template}) || !is_scalar($this->{$template})) return false;
238
+ $stylesheet = get_theme_root() . '/' . $this->{$template} . '/style.css';
239
+ // read parnt stylesheet
240
+ if (!is_file($stylesheet)) return false;
241
+ $styles = file_get_contents($stylesheet);
242
+ // get theme name
243
+ $regex = '#Theme Name:\s*(.+?)\n#i';
244
+ preg_match($regex, $styles, $matches);
245
+ if (empty($matches[1])) return false;
246
+ if ('child' == $template && empty($this->child_name)) $this->set_property('child_name', $matches[1]);
247
+ $this->parse_css($template, $styles);
248
+ }
249
+
250
+ /*
251
+ * reset_updates
252
+ * clears temporary update cache
253
+ */
254
+ function reset_updates() {
255
+ $this->updates = array();
256
+ }
257
+
258
+ /*
259
+ * update_arrays
260
+ * accepts CSS properties as raw strings and normilizes into
261
+ * CTC object arrays, creating update cache in the process.
262
+ * Update cache is returned to UI via AJAX to refresh page
263
+ */
264
+ function update_arrays($template, $query, $sel, $rule = null, $value = null, $important = null) {
265
+ // add selector and query to index
266
+ if (!isset($this->dict_query[$query])) $this->dict_query[$query] = ++$this->querykey;
267
+ if (!isset($this->dict_sel[$sel])) $this->dict_sel[$sel] = ++$this->selkey;
268
+ if (!isset($this->sel_ndx[$this->dict_query[$query]][$this->dict_sel[$sel]])):
269
+ // increment key number
270
+ $this->sel_ndx[$this->dict_query[$query]][$this->dict_sel[$sel]] = ++$this->qskey;
271
+ $this->dict_qs[$this->qskey]['s'] = $this->dict_sel[$sel];
272
+ $this->dict_qs[$this->qskey]['q'] = $this->dict_query[$query];
273
+ // tell the UI to update a single cached query/selector lookup by passing 'qsid' as the key
274
+ // (normally the entire array is replaced):
275
+ $this->updates[] = array(
276
+ 'obj' => 'sel_ndx',
277
+ 'key' => 'qsid',
278
+ 'data' => array(
279
+ 'query' => $query,
280
+ 'selector' => $sel,
281
+ 'qsid' => $this->qskey,
282
+ ),
283
+ );
284
+ endif;
285
+ // set data and value
286
+ if ($rule):
287
+ if (!isset($this->dict_rule[$rule])):
288
+ $this->dict_rule[$rule] = ++$this->rulekey;
289
+ // tell the UI to update a single cached rule:
290
+ $this->updates[] = array(
291
+ 'obj' => 'rule',
292
+ 'key' => $this->rulekey,
293
+ 'data' => $rule,
294
+ );
295
+ endif;
296
+ $qsid = $this->sel_ndx[$this->dict_query[$query]][$this->dict_sel[$sel]];
297
+ $ruleid = $this->dict_rule[$rule];
298
+ //$important = $this->is_important($value);
299
+ if (!isset($this->dict_val[$value])):
300
+ $this->dict_val[$value] = ++$this->valkey;
301
+ endif;
302
+ $this->val_ndx[$qsid][$ruleid][$template] = $this->dict_val[$value];
303
+ $this->val_ndx[$qsid][$ruleid]['i'] = $important;
304
+ // tell the UI to add a single cached query/selector data array:
305
+ $this->updates[] = array(
306
+ 'obj' => 'sel_val',
307
+ 'key' => $qsid,
308
+ 'data' => $this->denorm_sel_val($qsid),
309
+ );
310
+ endif;
311
+ }
312
+
313
+ /*
314
+ * parse_css
315
+ * accepts raw CSS as text and parses into separate properties
316
+ */
317
+ function parse_css($template, $styles, $basequery = null, $parse_imports = true) {
318
+ if (false === strpos($basequery, '@')):
319
+ $basequery = 'base';
320
+ endif;
321
+ $ruleset = array();
322
+ // ignore commented code
323
+ $styles = preg_replace('#\/\*.*?\*\/#s', '', $styles);
324
+ // space brace to ensure correct matching
325
+ $styles = preg_replace('#(\{\s*)#', "$1\n", $styles);
326
+ // get all imports
327
+ if ($parse_imports):
328
+ $regex = '#(\@import.+?);#';
329
+ preg_match_all($regex, $styles, $matches);
330
+ $this->imports[$template] = preg_grep('#style\.css#', $matches[1], PREG_GREP_INVERT);
331
+ $this->updates[] = array(
332
+ 'obj' => 'imports',
333
+ 'data' => $this->imports[$template],
334
+ );
335
+ endif;
336
+ // break into @ segments
337
+ $regex = '#(\@media.+?)\{(.*?\})\s*\}#s';
338
+ preg_match_all($regex, $styles, $matches);
339
+ foreach ($matches[1] as $segment):
340
+ $ruleset[trim($segment)] = array_shift($matches[2]);
341
+ endforeach;
342
+ // remove rulesets from styles
343
+ $ruleset[$basequery] = preg_replace($regex, '', $styles);
344
+ foreach ($ruleset as $query => $segment):
345
+ // make sure there is semicolon before closing brace
346
+ $segment = preg_replace('#(\})#', ";$1", $segment);
347
+ $regex = '#\s([\.\#\:\w][\w\-\s\[\]\'\*\.\#\+:,"=>]+?)\s*\{(.*?)\}#s';
348
+ preg_match_all($regex, $segment, $matches);
349
+ foreach($matches[1] as $sel):
350
+ $stuff = array_shift($matches[2]);
351
+ // normalize selector styling
352
+ $sel = implode(', ', preg_split('#\s*,\s*#s', trim($sel)));
353
+ $this->update_arrays($template, $query, $sel);
354
+ foreach (explode(';', $stuff) as $ruleval):
355
+ if (false === strpos($ruleval, ':')) continue;
356
+ list($rule, $value) = explode(':', $ruleval, 2);
357
+ $rule = trim($rule);
358
+ $value = trim($value);
359
+
360
+ $rules = $values = array();
361
+ // save important flag
362
+ $important = $this->is_important($value);
363
+ // normalize font
364
+ if ('font' == $rule):
365
+ $this->normalize_font($value, $rules, $values);
366
+ // normalize background
367
+ elseif('background' == $rule):
368
+ $this->normalize_background($value, $rules, $values);
369
+ // normalize margin/padding
370
+ elseif ('margin' == $rule || 'padding' == $rule):
371
+ $this->normalize_margin_padding($rule, $value, $rules, $values);
372
+ else:
373
+ $rules[] = $rule;
374
+ $values[] = $value;
375
+ endif;
376
+ foreach ($rules as $rule):
377
+ $value = trim(array_shift($values));
378
+ // normalize zero values
379
+ $value = preg_replace('#([: ])0(px|r?em)#', "$1\0", $value);
380
+ // normalize gradients
381
+ if (false !== strpos($value, 'gradient')):
382
+ if (false !== strpos($rule, 'filter')):
383
+ $rule = 'background-image';
384
+ continue; // treat as background-image, we'll add filter rule later
385
+ endif;
386
+ if (false !== strpos($value, 'webkit-gradient')) continue; // bail on legacy webkit, we'll add it later
387
+ $value = $this->encode_gradient($value);
388
+ endif;
389
+ // normalize common vendor prefixes
390
+ $rule = preg_replace('#(\-(o|ms|moz|webkit)\-)?(box\-sizing|font\-smoothing|border\-radius|box\-shadow|transition)#', "$3", $rule);
391
+ $this->update_arrays($template, $query, $sel, $rule, $value, $important);
392
+ endforeach;
393
+ endforeach;
394
+ endforeach;
395
+ endforeach;
396
+ }
397
+
398
+ /*
399
+ * write_css
400
+ * converts normalized CSS object data into stylesheet.
401
+ * Preserves selector sequence and !important flags of parent stylesheet.
402
+ * @media query blocks are sorted using internal heuristics (see sort_queries)
403
+ * New selectors are appended to the end of each media query block.
404
+ * TODO: allow user to modify selector sequence, !important flags and @media sort
405
+ */
406
+ function write_css() {
407
+ // write new stylesheet
408
+ $output = '/*' . LF;
409
+ $output .= 'Theme Name: ' . $this->child_name . LF;
410
+ $output .= 'Template: ' . $this->parnt . LF;
411
+ $output .= 'Author: ' . $this->child_author . LF;
412
+ $output .= 'Version: 1.0' . LF;
413
+ $output .= 'Updated: ' . current_time('mysql') . LF;
414
+ $output .= '*/' . LF . LF;
415
+ $output .= '@charset "UTF-8";' . LF;
416
+ $output .= '@import url(\'../' . $this->parnt . '/style.css\');' . LF;
417
+ if (!empty($this->imports['child'])):
418
+ foreach ($this->imports['child'] as $import):
419
+ $output .= $import . ';' . LF;
420
+ endforeach;
421
+ endif;
422
+ $output .= LF;
423
+ // turn the dictionaries into indexes:
424
+ $rulearr = array_flip($this->dict_rule);
425
+ $valarr = array_flip($this->dict_val);
426
+ $selarr = array_flip($this->dict_sel);
427
+ foreach ($this->sort_queries() as $query => $sort_order):
428
+ $selectors = $this->sel_ndx[$this->dict_query[$query]];
429
+ asort($selectors);
430
+ $has_selector = 0;
431
+ $sel_output = '';
432
+ if ('base' != $query) $sel_output .= $query . ' {' . LF;
433
+ foreach ($selectors as $selid => $qsid):
434
+ $has_value = 0;
435
+ $sel = $selarr[$selid];
436
+ if (!empty($this->val_ndx[$qsid])):
437
+ foreach ($this->val_ndx[$qsid] as $ruleid => $valid):
438
+ if (isset($valid['child']) && isset($valarr[$valid['child']]) && '' != $valarr[$valid['child']]):
439
+ if (! $has_value):
440
+ $sel_output .= $sel . ' {' . LF;
441
+ $has_value = 1;
442
+ $has_selector = 1;
443
+ endif;
444
+ $sel_output .= $this->add_vendor_rules($rulearr[$ruleid], $valarr[$valid['child']]);
445
+ endif;
446
+ endforeach;
447
+ if ($has_value):
448
+ $sel_output .= '}' . LF;
449
+ endif;
450
+ endif;
451
+ endforeach;
452
+ if ('base' != $query) $sel_output .= '}' . LF;
453
+ if ($has_selector) $output .= $sel_output;
454
+ endforeach;
455
+ $themedir = get_theme_root() . '/' . $this->child;
456
+
457
+ $stylesheet = $themedir . '/style.css';
458
+ if (!is_dir($themedir)):
459
+ mkdir($themedir, 0755);
460
+ endif;
461
+ // backup current stylesheet if no backup exists
462
+ if (is_file($stylesheet) && !is_file($stylesheet . '.bak')):
463
+ file_put_contents($stylesheet . '.bak', file_get_contents($stylesheet));
464
+ endif;
465
+ // write new stylesheet
466
+ file_put_contents($stylesheet, $output);
467
+ }
468
+
469
+ /*
470
+ * add_vendor_rules
471
+ * Applies vendor prefixes to rules/values
472
+ * These are based on commonly used practices and not all vendor prefixed are supported
473
+ * TODO: verify this logic against vendor and W3C documentation
474
+ */
475
+ function add_vendor_rules($rule, $value) {
476
+ $rules = '';
477
+ if (preg_match("/^(box\-sizing|font\-smoothing|border\-radius|box\-shadow|transition)$/", $rule)):
478
+ foreach(array('moz', 'webkit', 'o') as $prefix):
479
+ $rules .= ' -' . $prefix . '-' . $rule . ': ' . $value . ';' . LF;
480
+ endforeach;
481
+ $rules .= ' ' . $rule . ': ' . $value . ';' . LF;
482
+ elseif ('background-image' == $rule):
483
+ // gradient?
484
+ if ($gradient = $this->decode_gradient($value)):
485
+ // standard gradient
486
+ foreach(array('moz', 'webkit', 'o', 'ms') as $prefix):
487
+ $rules .= ' background-image: -' . $prefix . '-' . 'linear-gradient(' . $gradient['origin'] . ', '
488
+ . $gradient['color1'] . ', ' . $gradient['color2'] . ');' . LF;
489
+ endforeach;
490
+ // W3C standard gradient
491
+ // rotate origin 90 degrees
492
+ if (preg_match('/(\d+)deg/', $gradient['origin'], $matches)):
493
+ $org = (90 - $matches[1]) . 'deg';
494
+ else:
495
+ foreach (preg_split("/\s+/", $gradient['origin']) as $dir):
496
+ $dir = strtolower($dir);
497
+ $dirs[] = ('top' == $dir ? 'bottom' : ('bottom' == $dir ? 'top' : ('left' == $dir ? 'right' : ('right' == $dir ? 'left' : $dir))));
498
+ endforeach;
499
+ $org = 'to ' . implode(' ', $dirs);
500
+ endif;
501
+ $rules .= ' background-image: linear-gradient(' . $org . ', '
502
+ . $gradient['color1'] . ', ' . $gradient['color2'] . ');' . LF;
503
+
504
+ // legacy webkit gradient - we'll add if there is demand
505
+ // '-webkit-gradient(linear,' .$origin . ', ' . $color1 . ', '. $color2 . ')';
506
+
507
+ // MS filter gradient
508
+ $type = (in_array($gradient['origin'], array('left', 'right', '0deg', '180deg')) ? 1 : 0);
509
+ $color1 = preg_replace("/^#/", '#00', $gradient['color1']);
510
+ $rules .= ' filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=' . $type . ', StartColorStr="'
511
+ . strtoupper($color1) . '", EndColorStr="' . strtoupper($gradient['color2']) . '");' . LF;
512
+ else:
513
+ // url or other value
514
+ $rules .= ' ' . $rule . ': ' . $value . ';' . LF;
515
+ endif;
516
+ else:
517
+ $rules .= ' ' . $rule . ': ' . $value . ';' . LF;
518
+ endif;
519
+ return $rules;
520
+ }
521
+
522
+ /*
523
+ * encode_gradient
524
+ * Normalize linear gradients from a bazillion formats into standard CTC syntax:
525
+ * Currently only supports two-color linear gradients with no inner stops.
526
+ * TODO: legacy webkit? more gradients?
527
+ */
528
+ function encode_gradient($value) {
529
+ $regex = '#gradient[^\)]*?\((((top|bottom|left|right)?( (top|bottom|left|right))?|\d+deg),)?([^\)]*[\'"]?(\#\w{3,8}|rgba?\([\d, ]+?\)|hsla?\([\d%, ]+?\))( \d+%)?)([^\)]*[\'"]?(\#\w{3,8}|rgba?\([\d, ]+?\)|hsla?\([\d%, ]+?\))( \d+%)?)([^\)]*gradienttype=[\'"]?(\d)[\'"]?)?[^\)]*\)#i';
530
+ $param = $parts = array();
531
+ preg_match($regex, $value, $parts);
532
+ if (empty($parts[13])):
533
+ if (empty($parts[2])):
534
+ $param[0] = 'top';
535
+ else:
536
+ $param[0] = trim($parts[2]);
537
+ endif;
538
+ if (empty($parts[8])):
539
+ $param[2] = '0%';
540
+ else:
541
+ $param[2] = trim($parts[8]);
542
+ endif;
543
+ if (empty($parts[11])):
544
+ $param[4] = '100%';
545
+ else:
546
+ $param[4] = trim($parts[11]);
547
+ endif;
548
+ elseif('0' == $parts[13]):
549
+ $param[0] = 'top';
550
+ $param[2] = '0%';
551
+ $param[4] = '100%';
552
+ elseif ('1' == $parts[13]):
553
+ $param[0] = 'left';
554
+ $param[2] = '0%';
555
+ $param[4] = '100%';
556
+ endif;
557
+ $param[1] = $parts[7];
558
+ $param[3] = $parts[10];
559
+ ksort($param);
560
+ return implode(':', $param);
561
+ }
562
+
563
+ /*
564
+ * decode_border
565
+ * De-normalize CTC border syntax into separate properties.
566
+ */
567
+ function decode_border($value) {
568
+ if (preg_match('#^(0|none)#i', $value)):
569
+ $parts[0] = $value;
570
+ $parts[1] = $parts[2] = '';
571
+ else:
572
+ $parts = preg_split('#\s+#', $value, 3);
573
+ endif;
574
+ return array(
575
+ 'width' => empty($parts[0])?'':$parts[0],
576
+ 'style' => empty($parts[1])?'':$parts[1],
577
+ 'color' => empty($parts[2])?'':$parts[2],
578
+ );
579
+ }
580
+
581
+ /*
582
+ * decode_gradient
583
+ * De-normalize CTC gradient syntax into separate properties.
584
+ */
585
+ function decode_gradient($value) {
586
+ $parts = explode(':', $value, 5);
587
+ if (count($parts) == 5):
588
+ return array(
589
+ 'origin' => empty($parts[0])?'':$parts[0],
590
+ 'color1' => empty($parts[1])?'':$parts[1],
591
+ 'stop1' => empty($parts[2])?'':$parts[2],
592
+ 'color2' => empty($parts[3])?'':$parts[3],
593
+ 'stop2' => empty($parts[4])?'':$parts[4],
594
+ );
595
+ else:
596
+ return false;
597
+ endif;
598
+ }
599
+
600
+ /*
601
+ * parse_css_input
602
+ * Normalize raw user CSS input so that the parser can read it.
603
+ */
604
+ function parse_css_input($styles) {
605
+ return $styles;
606
+ }
607
+
608
+ /*
609
+ * parse_post_data
610
+ * Parse user form input into separate properties and pass to update_arrays
611
+ */
612
+ function parse_post_data() {
613
+ if (isset($_POST['ctc_new_selectors'])):
614
+
615
+ $this->parse_css('child', LF . $this->parse_css_input($_POST['ctc_new_selectors']),
616
+ (isset($_POST['ctc_sel_ovrd_query'])?trim($_POST['ctc_sel_ovrd_query']):null), false);
617
+ elseif (isset($_POST['ctc_child_imports'])):
618
+ $this->parse_css('child', $_POST['ctc_child_imports']);
619
+ else:
620
+ $parts = array();
621
+ foreach (preg_grep('#^ctc_(ovrd_)?child#', array_keys($_POST)) as $post_key):
622
+ if (preg_match('#^ctc_(ovrd_)?child_([\w\-]+?)_(\d+?)(_(.+))?$#', $post_key, $matches)):
623
+ $rule = $matches[2];
624
+ if (null == $rule || !isset($this->dict_rule[$rule])) continue;
625
+ $ruleid = $this->dict_rule[$rule];
626
+ $qsid = $matches[3];
627
+ $value = sanitize_text_field($_POST[$post_key]);
628
+ if (isset($this->val_ndx[$qsid][$ruleid]) && isset($this->val_ndx[$qsid][$ruleid]['child'])):
629
+ $child_value = $this->val_ndx[$qsid][$ruleid]['child'];
630
+ else:
631
+ $child_value = $this->val_ndx[$qsid][$ruleid]['child'] = '';
632
+ endif;
633
+ if (isset($this->val_ndx[$qsid][$ruleid]['parnt'])):
634
+ $parent_value = $this->val_ndx[$qsid][$ruleid]['parnt'];
635
+ else:
636
+ $parent_value = $this->val_ndx[$qsid][$ruleid]['parnt'] = '';
637
+ endif;
638
+ $important = $this->val_ndx[$qsid][$ruleid]['i'];
639
+
640
+ $selarr = $this->denorm_query_sel($qsid);
641
+ if (!empty($matches[5])):
642
+ $parts[$qsid][$rule][$matches[5]] = $value;
643
+ $parts[$qsid][$rule]['important'] = $important;
644
+ $parts[$qsid][$rule]['query'] = $selarr['query'];
645
+ $parts[$qsid][$rule]['selector'] = $selarr['selector'];
646
+ else:
647
+ $this->update_arrays('child', $selarr['query'], $selarr['selector'],
648
+ $rule, $value, $important);
649
+ endif;
650
+ endif;
651
+ endforeach;
652
+ foreach ($parts as $qsid => $rule_arr):
653
+ foreach ($rule_arr as $rule => $rule_part):
654
+ if ('background' == $rule):
655
+ $value = $rule_part['background_url'];
656
+ elseif ('background-image' == $rule):
657
+ if (empty($rule_part['background_url'])):
658
+ if (empty($rule_part['background_color2'])):
659
+ $value = '';
660
+ else:
661
+ $value = implode(':', array(
662
+ $rule_part['background_origin'],
663
+ $rule_part['background_color1'], '0%',
664
+ $rule_part['background_color2'], '100%'
665
+ ));
666
+ endif;
667
+ else:
668
+ $value = $rule_part['background_url'];
669
+ endif;
670
+ elseif (preg_match('#^border(\-(top|right|bottom|left))?$#', $rule)):
671
+ $value = implode(' ', array(
672
+ $rule_part['border_width'],
673
+ $rule_part['border_style'],
674
+ $rule_part['border_color']
675
+ ));
676
+ else:
677
+ $value = '';
678
+ endif;
679
+ $this->update_arrays('child', $rule_part['query'], $rule_part['selector'],
680
+ $rule, $value, $rule_part['important']);
681
+ endforeach;
682
+ endforeach;
683
+ endif;
684
+ }
685
+
686
+ /*
687
+ * is_important
688
+ * Strip important flag from value ref and return boolean
689
+ * Value is updated because it is a ref
690
+ */
691
+ function is_important(&$value) {
692
+ $important = 0;
693
+ $value = trim(str_replace('!important', '', $value, $important));
694
+ return $important;
695
+ }
696
+
697
+ /*
698
+ * sort_queries
699
+ * De-normalize query data and return array sorted as follows:
700
+ * base
701
+ * @media max-width queries in descending order
702
+ * other @media queries in no particular order
703
+ * @media min-width queries in ascending order
704
+ */
705
+ function sort_queries() {
706
+ $queries = array();
707
+ $queryarr = array_flip($this->dict_query);
708
+ foreach (array_keys($this->sel_ndx) as $queryid):
709
+ $query = $queryarr[$queryid];
710
+ if ('base' == $query):
711
+ $queries['base'] = -999999;
712
+ continue;
713
+ endif;
714
+ if (preg_match("/((min|max)(\-device)?\-width)\s*:\s*(\d+)/", $query, $matches)):
715
+ $queries[$query] = 'min-width' == $matches[1] ? $matches[4] : -$matches[4];
716
+ else:
717
+ $queries[$query] = $queryid - 10000;
718
+ endif;
719
+ endforeach;
720
+ asort($queries);
721
+ return $queries;
722
+ }
723
+
724
+ /*
725
+ * denorm_rule_val
726
+ * Return array of unique values corresponding to specific rule
727
+ */
728
+ function denorm_rule_val($ruleid) {
729
+ $rule_sel_arr = array();
730
+ $val_arr = array_flip($this->dict_val);
731
+ foreach ($this->val_ndx as $selid => $rules):
732
+ if (!isset($rules[$ruleid])) continue;
733
+ foreach ($rules[$ruleid] as $theme => $val):
734
+ if (!isset($val_arr[$val]) || '' == $val_arr[$val]) continue;
735
+ $rule_sel_arr[$val] = $val_arr[$val];
736
+ endforeach;
737
+ endforeach;
738
+ return $rule_sel_arr;
739
+ }
740
+
741
+ /*
742
+ * denorm_val_query
743
+ * Return array of queries, selectors, rules, and values corresponding to
744
+ * specific rule/value combo grouped by query, selector
745
+ */
746
+ function denorm_val_query($valid, $rule) {
747
+ $value_query_arr = array();
748
+ foreach ($this->val_ndx as $qsid => $rules):
749
+ foreach ($rules as $ruleid => $values):
750
+ if ($ruleid != $this->dict_rule[$rule]) continue;
751
+ foreach ($values as $name => $val):
752
+ if ('i' == $name || $val != $valid) continue;
753
+ $selarr = $this->denorm_query_sel($qsid);
754
+ $valarr = $this->denorm_sel_val($qsid);
755
+ $value_query_arr[$rule][$selarr['query']][$qsid] = $valarr;
756
+ endforeach;
757
+ endforeach;
758
+ endforeach;
759
+ return $value_query_arr;
760
+ }
761
+
762
+ /*
763
+ * denorm_query_sel
764
+ * Return id, query and selector values of a specific qsid (query-selector ID)
765
+ */
766
+ function denorm_query_sel($qsid) {
767
+ $queryarr = array_flip($this->dict_query);
768
+ $selarr = array_flip($this->dict_sel);
769
+
770
+ return array(
771
+ 'id' => $qsid,
772
+ 'query' => $queryarr[$this->dict_qs[$qsid]['q']],
773
+ 'selector' => $selarr[$this->dict_qs[$qsid]['s']],
774
+ );
775
+ }
776
+
777
+ /*
778
+ * denorm_sel_val
779
+ * Return array of rules, and values matching specific qsid (query-selector ID)
780
+ * grouped by query, selector
781
+ */
782
+ function denorm_sel_val($qsid) {
783
+ $selarr = $this->denorm_query_sel($qsid);
784
+ $valarr = array_flip($this->dict_val);
785
+ $rulearr = array_flip($this->dict_rule);
786
+ if (isset($this->val_ndx[$qsid]) && is_array($this->val_ndx[$qsid])):
787
+ foreach ($this->val_ndx[$qsid] as $ruleid => $values):
788
+ foreach ($values as $name => $val):
789
+ if ('i' == $name || !isset($valarr[$val]) || '' == $valarr[$val]) continue;
790
+ $selarr['value'][$rulearr[$ruleid]][$name] = $valarr[$val];
791
+ endforeach;
792
+ endforeach;
793
+ endif;
794
+ return $selarr;
795
+ }
796
+
797
+ /*
798
+ * denorm_sel_ndx
799
+ * Return denormalized array containing query and selector heirarchy
800
+ */
801
+ function denorm_sel_ndx($query = null) {
802
+ $sel_ndx_norm = array();
803
+ $queryarr = array_flip($this->dict_query);
804
+ $selarr = array_flip($this->dict_sel);
805
+ foreach($this->sel_ndx as $queryid => $sel):
806
+ foreach($sel as $selid => $qsid):
807
+ $sel_ndx_norm[$queryarr[$queryid]][$selarr[$selid]] = $qsid;
808
+ endforeach;
809
+ endforeach;
810
+ return empty($query) ? $sel_ndx_norm : $sel_ndx_norm[$query];
811
+ }
812
+ }
813
+ ?>
includes/class-ctc-ui.php ADDED
@@ -0,0 +1,490 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Exit if accessed directly
3
+ if ( !defined('ABSPATH')) exit;
4
+ /*
5
+ Class: Child_Theme_Configurator_UI
6
+ Plugin URI: http://www.lilaeamedia.com/plugins/child-theme-configurator/
7
+ Description: Handles the plugin User Interface
8
+ Version: 1.1.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) 2013 Lilaea Media
15
+ */
16
+ class Child_Theme_Configurator_UI {
17
+ var $swatch_text;
18
+ var $themes;
19
+
20
+ function __construct() {
21
+ $this->swatch_text = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
22
+ }
23
+
24
+ function render_options() {
25
+ global $chld_thm_cfg;
26
+ $css = $chld_thm_cfg->css;
27
+ $themes = $chld_thm_cfg->themes;
28
+ $parent = $css->get_property('parnt');
29
+ $child = $css->get_property('child');
30
+ $hidechild = (count($themes['child']) ? '' : 'style="display:none"');
31
+ $imports = $css->get_property('imports');
32
+ $id = 0;
33
+ ?>
34
+
35
+ <div class="wrap">
36
+ <div id="icon-tools" class="icon32"></div>
37
+ <h2><?php echo $chld_thm_cfg->pluginName; ?></h2>
38
+ <div id="ctc_error_notice">
39
+ <?php $this->settings_errors(); ?>
40
+ </div>
41
+ <?php
42
+ $active_tab = isset( $_GET[ 'tab' ] ) ? $_GET[ 'tab' ] : 'parent_child_options';
43
+ ?>
44
+ <h2 class="nav-tab-wrapper"> <a id="parent_child_options" href="?page=<?php echo $chld_thm_cfg->menuName; ?>&amp;tab=parent_child_options"
45
+ class="nav-tab<?php echo 'parent_child_options' == $active_tab ? ' nav-tab-active' : ''; ?>">
46
+ <?php _e('Parent/Child', 'chld_thm_cfg'); ?>
47
+ </a> <a id="query_selector_options" href="?page=<?php echo $chld_thm_cfg->menuName; ?>&amp;tab=query_selector_options"
48
+ class="nav-tab<?php echo 'query_selector_options' == $active_tab ? ' nav-tab-active' : ''; ?>" <?php echo $hidechild; ?>>
49
+ <?php _e('Query/Selector', 'chld_thm_cfg'); ?>
50
+ </a> <a id="rule_value_options" href="?page=<?php echo $chld_thm_cfg->menuName; ?>&amp;tab=rule_value_options"
51
+ class="nav-tab<?php echo 'rule_value_options' == $active_tab ? ' nav-tab-active' : ''; ?>" <?php echo $hidechild; ?>>
52
+ <?php _e('Rule/Value', 'chld_thm_cfg'); ?>
53
+ </a> <a id="import_options" href="?page=<?php echo $chld_thm_cfg->menuName; ?>&amp;tab=import_options"
54
+ class="nav-tab<?php echo 'import_options' == $active_tab ? ' nav-tab-active' : ''; ?>" <?php echo $hidechild; ?>>
55
+ <?php _e('@import', 'chld_thm_cfg'); ?>
56
+ </a> <a id="view_child_options" href="?page=<?php echo $chld_thm_cfg->menuName; ?>&amp;tab=view_child_options"
57
+ class="nav-tab<?php echo 'view_child_options' == $active_tab ? ' nav-tab-active' : ''; ?>" <?php echo $hidechild; ?>>
58
+ <?php _e('View Child CSS', 'chld_thm_cfg'); ?>
59
+ </a> <a id="view_parnt_options" href="?page=<?php echo $chld_thm_cfg->menuName; ?>&amp;tab=view_parnt_options"
60
+ class="nav-tab<?php echo 'view_parnt_options' == $active_tab ? ' nav-tab-active' : ''; ?>">
61
+ <?php _e('View Parent CSS', 'chld_thm_cfg'); ?>
62
+ </a> </h2>
63
+ <div class="ctc-option-panel-container">
64
+ <div id="parent_child_options_panel" class="ctc-option-panel<?php echo 'parent_child_options' == $active_tab ? ' ctc-option-panel-active' : ''; ?>">
65
+ <form id="ctc_load_form" method="post" action="">
66
+ <?php wp_nonce_field( 'ctc_update' ); ?>
67
+ <div class="ctc-input-row clearfix" id="input_row_parnt">
68
+ <div class="ctc-input-cell">
69
+ <label>
70
+ <?php _e('Parent Theme', 'chld_thm_cfg'); ?>
71
+ </label>
72
+ </div>
73
+ <div class="ctc-input-cell">
74
+ <select class="ctc-select" id="ctc_theme_parnt" name="ctc_theme_parnt">
75
+ <?php echo $chld_thm_cfg->render_menu('parnt', $parent); ?>
76
+ </select>
77
+ </div>
78
+ </div>
79
+ <div class="ctc-input-row clearfix" id="input_row_child">
80
+ <div class="ctc-input-cell">
81
+ <label>
82
+ <?php _e('Child Theme', 'chld_thm_cfg'); ?>
83
+ </label>
84
+ </div>
85
+ <div class="ctc-input-cell">
86
+ <input class="ctc-radio" id="ctc_child_type_new" name="ctc_child_type" type="radio" value="new"
87
+ <? echo (!empty($hidechild) ? 'checked' : ''); ?>
88
+ <?php echo $hidechild;?> />
89
+ <label for="ctc_child_type_new">
90
+ <?php _e('Create New Child Theme', 'chld_thm_cfg'); ?>
91
+ </label>
92
+ </div>
93
+ <div class="ctc-input-cell">
94
+ <input class="ctc-radio" id="ctc_child_type_existing" name="ctc_child_type" type="radio" value="existing"
95
+ <? echo (empty($hidechild) ? 'checked' : ''); ?>
96
+ <?php echo $hidechild; ?>/>
97
+ &nbsp;
98
+ <label for="ctc_child_type_existing" <?php echo $hidechild;?>>
99
+ <?php _e('Use Existing Child Theme', 'chld_thm_cfg'); ?>
100
+ </label>
101
+ </div>
102
+ <div class="ctc-input-cell" style="clear:both">
103
+ <label>&nbsp;</label>
104
+ </div>
105
+ <div class="ctc-input-cell" >
106
+ <input class="ctc_text" id="ctc_child_template" name="ctc_child_template" type="text" placeholder="theme slug" autocomplete="off"/>
107
+ </div>
108
+ <div class="ctc-input-cell">
109
+ <select class="ctc-select" id="ctc_theme_child" name="ctc_theme_child" <?php echo $hidechild; ?>>
110
+ <?php echo $chld_thm_cfg->render_menu('child', $child); ?>
111
+ </select>
112
+ </div>
113
+ </div>
114
+ <div class="ctc-input-row clearfix" id="input_row_child_name">
115
+ <div class="ctc-input-cell">
116
+ <label>
117
+ <?php _e('Child Theme Name', 'chld_thm_cfg'); ?>
118
+ </label>
119
+ </div>
120
+ <div class="ctc-input-cell">
121
+ <input class="ctc_text" id="ctc_child_name" name="ctc_child_name" type="text"
122
+ value="<? echo esc_attr($css->get_property('child_name')); ?>" placeholder="theme name" autocomplete="off" />
123
+ </div>
124
+ </div>
125
+ <div class="ctc-input-row clearfix" id="input_row_child_template">
126
+ <div class="ctc-input-cell">
127
+ <label>
128
+ <?php _e('Author', 'chld_thm_cfg'); ?>
129
+ </label>
130
+ </div>
131
+ <div class="ctc-input-cell">
132
+ <input class="ctc_text" id="ctc_child_author" name="ctc_child_author" type="text"
133
+ value="<? echo esc_attr($css->get_property('author')); ?>" placeholder="author" autocomplete="off" />
134
+ </div>
135
+ </div>
136
+ <div class="ctc-input-row clearfix" id="input_row_child_template">
137
+ <div class="ctc-input-cell">
138
+ <label>
139
+ <?php _e('Version', 'chld_thm_cfg'); ?>
140
+ </label>
141
+ </div>
142
+ <div class="ctc-input-cell">
143
+ <input class="ctc_text" id="ctc_child_version" name="ctc_child_version" type="text"
144
+ value="<? echo esc_attr($css->get_property('version')); ?>" placeholder="version" autocomplete="off" />
145
+ </div>
146
+ </div>
147
+ <div class="ctc-input-row clearfix" id="input_row_child_template">
148
+ <div class="ctc-input-cell">
149
+ <label>&nbsp;</label>
150
+ </div>
151
+ <div class="ctc-input-cell">
152
+ <input class="ctc_submit button button-primary" id="ctc_load_styles" name="ctc_load_styles" type="submit"
153
+ value="<?php _e('Generate Child Theme', 'chld_thm_cfg'); ?>" disabled />
154
+ </div>
155
+ </div>
156
+ </form>
157
+ </div>
158
+ <div id="rule_value_options_panel"
159
+ class="ctc-option-panel<?php echo 'rule_value_options' == $active_tab ? ' ctc-option-panel-active' : ''; ?>" <?php echo $hidechild; ?>>
160
+ <form id="ctc_rule_value_form" method="post" action="">
161
+ <?php wp_nonce_field( 'ctc_update' ); ?>
162
+ <div class="ctc-input-row clearfix" id="ctc_input_row_rule_menu">
163
+ <div class="ctc-input-cell"> <strong>
164
+ <?php _e('Rule', 'chld_thm_cfg'); ?>
165
+ </strong> </div>
166
+ <div class="ctc-input-cell" id="ctc_rule_menu_selected">&nbsp;</div>
167
+ <div id="ctc_status_rule_val"></div>
168
+ <div class="ctc-input-cell">
169
+ <div class="ui-widget">
170
+ <input id="ctc_rule_menu"/>
171
+ <div id="ctc_status_rule"></div>
172
+ </div>
173
+ </div>
174
+ </div>
175
+ <div class="ctc-input-row clearfix" id="ctc_input_row_rule_header" style="display:none">
176
+ <div class="ctc-input-cell"> <strong>
177
+ <?php _e('Value', 'chld_thm_cfg'); ?>
178
+ </strong> </div>
179
+ <div class="ctc-input-cell"> <strong>
180
+ <?php _e('Sample', 'chld_thm_cfg'); ?>
181
+ </strong> </div>
182
+ <div class="ctc-input-cell"> <strong>
183
+ <?php _e('Selectors', 'chld_thm_cfg'); ?>
184
+ </strong> </div>
185
+ </div>
186
+ <div class="ctc-rule-value-input-container clearfix" id="ctc_rule_value_inputs" style="display:none"> </div>
187
+ </form>
188
+ </div>
189
+ <div id="query_selector_options_panel"
190
+ class="ctc-option-panel<?php echo 'query_selector_options' == $active_tab ? ' ctc-option-panel-active' : ''; ?>" <?php echo $hidechild; ?>>
191
+ <form id="ctc_query_selector_form" method="post" action="">
192
+ <div class="ctc-input-row clearfix" id="input_row_query">
193
+ <div class="ctc-input-cell"> <strong>
194
+ <?php _e('Query', 'chld_thm_cfg'); ?>
195
+ </strong> </div>
196
+ <div class="ctc-input-cell" id="ctc_sel_ovrd_query_selected">&nbsp;</div>
197
+ <div class="ctc-input-cell">
198
+ <div class="ui-widget">
199
+ <input id="ctc_sel_ovrd_query"/>
200
+ </div>
201
+ </div>
202
+ </div>
203
+ <div class="ctc-input-row clearfix" id="input_row_selector">
204
+ <div class="ctc-input-cell"> <strong>
205
+ <?php _e('Selector', 'chld_thm_cfg'); ?>
206
+ </strong> </div>
207
+ <div class="ctc-input-cell" id="ctc_sel_ovrd_selector_selected">&nbsp;</div>
208
+ <div class="ctc-input-cell">
209
+ <div class="ui-widget">
210
+ <input id="ctc_sel_ovrd_selector"/>
211
+ <div id="ctc_status_sel_ndx"></div>
212
+ </div>
213
+ </div>
214
+ </div>
215
+ <div class="ctc-selector-row clearfix" id="ctc_sel_ovrd_rule_inputs_container" style="display:none">
216
+ <div class="ctc-input-row clearfix">
217
+ <div class="ctc-input-cell"><strong>
218
+ <?php _e('Sample', 'chld_thm_cfg'); ?>
219
+ </strong></div>
220
+ <div id="ctc_status_sel_val"></div>
221
+ <div class="ctc-input-cell clearfix" style="max-height:150px;overflow:hidden">
222
+ <div class="ctc-swatch" id="ctc_child_all_0_swatch"><?php echo $this->swatch_text; ?></div>
223
+ </div>
224
+ <div class="ctc-input-cell ctc-button-cell" id="ctc_save_query_selector_cell">
225
+ <input type="button" class="button ctc-save-input" id="ctc_save_query_selector"
226
+ name="ctc_save_query_selector" value="Save" disabled />
227
+ <input type="hidden" id="ctc_sel_ovrd_qsid"
228
+ name="ctc_sel_ovrd_qsid" value="" />
229
+ </div>
230
+ </div>
231
+ <div class="ctc-input-row clearfix" id="ctc_sel_ovrd_rule_header" style="display:none">
232
+ <div class="ctc-input-cell"> <strong>
233
+ <?php _e('Rule', 'chld_thm_cfg'); ?>
234
+ </strong> </div>
235
+ <div class="ctc-input-cell"> <strong>
236
+ <?php _e('Parent Value', 'chld_thm_cfg'); ?>
237
+ </strong> </div>
238
+ <div class="ctc-input-cell"> <strong>
239
+ <?php _e('Child Value', 'chld_thm_cfg'); ?>
240
+ </strong> </div>
241
+ </div>
242
+ <div id="ctc_sel_ovrd_rule_inputs" style="display:none"> </div>
243
+ <div class="ctc-input-row clearfix" id="ctc_sel_ovrd_new_rule" style="display:none">
244
+ <div class="ctc-input-cell"> <strong>
245
+ <?php _e('New Rule', 'chld_thm_cfg'); ?>
246
+ </strong> </div>
247
+ <div class="ctc-input-cell">
248
+ <div class="ui-widget">
249
+ <input id="ctc_new_rule_menu"/>
250
+ </div>
251
+ </div>
252
+ </div>
253
+ </div>
254
+ <div class="ctc-selector-row clearfix" id="ctc_new_selector_row">
255
+ <div class="ctc-input-cell"> <strong>
256
+ <?php _e('New Selector(s)', 'chld_thm_cfg'); ?>
257
+ </strong>
258
+ <div class="ctc-textarea-button-cell" id="ctc_save_query_selector_cell">
259
+ <input type="button" class="button ctc-save-input" id="ctc_save_new_selectors"
260
+ name="ctc_save_new_selectors" value="Save" disabled />
261
+ </div>
262
+ </div>
263
+ <div class="ctc-input-cell-wide">
264
+ <textarea id="ctc_new_selectors" name="ctc_new_selectors" wrap="off"></textarea>
265
+ </div>
266
+ </div>
267
+ </form>
268
+ </div>
269
+ <div id="import_options_panel"
270
+ class="ctc-option-panel<?php echo 'import_options' == $active_tab ? ' ctc-option-panel-active' : ''; ?>" <?php echo $hidechild; ?>>
271
+ <form id="ctc_import_form" method="post" action="">
272
+ <?php wp_nonce_field( 'ctc_update' ); ?>
273
+ <div class="ctc-input-row clearfix" id="ctc_child_imports_row">
274
+ <div class="ctc-input-cell"> <strong>
275
+ <?php _e('@import Statements', 'chld_thm_cfg'); ?>
276
+ </strong>
277
+ <div class="ctc-textarea-button-cell" id="ctc_save_imports_cell">
278
+ <input type="button" class="button ctc-save-input" id="ctc_save_imports"
279
+ name="ctc_save_imports" value="Save" disabled />
280
+ </div>
281
+ </div>
282
+ <div class="ctc-input-cell-wide">
283
+ <textarea id="ctc_child_imports" name="ctc_child_imports" wrap="off">
284
+ <?php if (!empty($imports)):
285
+ foreach ($imports as $import):
286
+ echo esc_textarea($import . ';' . LF);
287
+ endforeach; endif;?>
288
+ </textarea>
289
+ </div>
290
+ </div>
291
+ </form>
292
+ </div>
293
+ <div id="view_child_options_panel"
294
+ class="ctc-option-panel<?php echo 'view_child_options' == $active_tab ? ' ctc-option-panel-active' : ''; ?>" <?php echo $hidechild; ?>> </div>
295
+ <div id="view_parnt_options_panel" class="ctc-option-panel<?php echo 'view_parnt_options' == $active_tab ? ' ctc-option-panel-active' : ''; ?>"> </div>
296
+ </div>
297
+ </div>
298
+ <style type="text/css">
299
+ .ctc-status-icon.success {
300
+ display: block;
301
+ float:right;
302
+ position: relative;
303
+ height: 16px;
304
+ width: 16px;
305
+ margin:4px;
306
+ background:url(<?php echo admin_url( 'images/yes.png' ); ?>) no-repeat;
307
+ }
308
+ .ctc-status-icon.failure {
309
+ display: block;
310
+ float:right;
311
+ position: relative;
312
+ height: 16px;
313
+ width: 16px;
314
+ margin:4px;
315
+ background:url(<?php echo admin_url( 'images/no.png') ; ?>) no-repeat;
316
+ }
317
+ </style>
318
+ <?php
319
+ }
320
+
321
+ function settings_errors() {
322
+ global $chld_thm_cfg;
323
+ if (count($chld_thm_cfg->errors)):
324
+ echo '<div class="error"><ul>' . LF;
325
+ foreach ($chld_thm_cfg->errors as $err):
326
+ echo '<li>' . $err . '</li>' . LF;
327
+ endforeach;
328
+ echo '</ul></div>' . LF;
329
+ elseif (isset($_GET['updated'])):
330
+ echo '<div class="updated"><p>' . LF
331
+ . sprintf(__('Child Theme <strong>%s</strong> has been generated successfully.', 'chld_thm_cfg'),
332
+ $chld_thm_cfg->css->get_property('child_name')) . LF
333
+ . '</p></div>' . LF;
334
+ endif;
335
+ }
336
+
337
+ function render_help_tabs() {
338
+ global $wp_version, $chld_thm_cfg;
339
+ if ( version_compare( $wp_version, '3.3') >= 0 ) {
340
+
341
+ $screen = get_current_screen();
342
+
343
+ if ( $screen->id != $chld_thm_cfg->hook )
344
+ return;
345
+ // Add help tabs
346
+ $screen->add_help_tab( array(
347
+ 'id' => 'ctc_getting_started',
348
+ 'title' => __( 'Start Here', 'chld_thm_cfg' ),
349
+ 'content' => __( '
350
+ <p>The first step is to create a child theme and import your parent theme styles into the configurator.</p>
351
+ <ol><li>Select an existing parent theme from the menu.</li>
352
+ <li>Select "New" or "Existing" child theme.
353
+ <ul><li>If creating a new theme, enter a "slug" (lower case, no spaces). This is used to name the theme directory and identify the theme to WordPress.</li>
354
+ <li>If using an existing theme, select a child theme from the menu.</li></ul></li>
355
+ <li>Enter a Name for the child theme.</li>
356
+ <li>Enter an author for the child theme.</li>
357
+ <li>Enter the child theme version number.</li>
358
+ <li>Click "Generate Child Theme." If you are loading an existing child theme, The Child Theme Configurator will create a backup of your existing stylesheet in the theme directory.</li></ol>
359
+ ', 'chld_thm_cfg'
360
+ ),
361
+ ) );
362
+
363
+ $screen->add_help_tab( array(
364
+ 'id' => 'ctc_query_selector',
365
+ 'title' => __( 'Query/Selector', 'chld_thm_cfg' ),
366
+ 'content' => __( '
367
+ <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>rule</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 "Rule/Value" tab.</p>
368
+ <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>
369
+ <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>
370
+ <p>This will load all of the rules 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>
371
+ <p>Click "Save" to update the child stylesheet and save your changes to the WordPress admin.</p>
372
+ ', 'chld_thm_cfg'
373
+ ),
374
+ ) );
375
+
376
+ $screen->add_help_tab( array(
377
+ 'id' => 'ctc_rule_value',
378
+ 'title' => __( 'Rule/Value', 'chld_thm_cfg' ),
379
+ 'content' => __( '
380
+ <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>rule</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 "Rule/Value" tab.</p>
381
+ <p>The Rule/Value tab lets you find specific values for a given rule and then edit that value for individual selectors that use that rule/value combination. First, find the rule you wish to override by typing in the <strong>Rule</strong> autoselect box. Select by clicking with the mouse or by pressing the "Enter" or "Tab" keys.</p>
382
+ <p>This will load all of the unique values that exist for that rule 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>
383
+ <p>For each unique value, click the "Selectors" link to view a list of selectors that use that rule/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>
384
+ <p>Click "Save" to update the child stylesheet and save your changes to the WordPress admin.</p>
385
+ ', 'chld_thm_cfg'
386
+ ),
387
+ ) );
388
+
389
+ $screen->add_help_tab( array(
390
+ 'id' => 'ctc_new_styles',
391
+ 'title' => __( 'Add New Styles', 'chld_thm_cfg' ),
392
+ 'content' => __( '
393
+ <p>If you wish to add additional rules to a given selector, first load the selector using the Query/Selector tab. Then find the rule you wish to override by typing in the <strong>New Rule</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>
394
+ <p>If you wish to add completely new selectors, or even new @media queries, you can enter free-form CSS in the "New Selector" 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>
395
+ <p>If you prefer to use shorthand syntax for rules 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>
396
+ ', 'chld_thm_cfg'
397
+ ),
398
+ ) );
399
+
400
+ $screen->add_help_tab( array(
401
+ 'id' => 'ctc_imports',
402
+ 'title' => __( '@imports', 'chld_thm_cfg' ),
403
+ 'content' => __( '
404
+ <p>You can add additional stylesheets and web fonts by typing @import rules into the textarea on the @import tab. <strong>Important: The Child Theme Configurator adds the @import rule that loads the Parent Theme\'s stylesheet automatically. Do not need to add it here.</strong></p>
405
+ <p>Below is an example that loads a local custom stylesheet (you would have to add the "fonts" directory and stylesheet) as well as the web font "Open Sans" from Google Web Fonts:</p>
406
+ <blockquote><pre><code>
407
+ @import url(fonts/stylesheet.css);
408
+ @import url(http://fonts.googleapis.com/css?family=Open+Sans:400,400italic,700,700italic);
409
+ </code></pre></blockquote>
410
+ ', 'chld_thm_cfg'
411
+ ),
412
+ ) );
413
+
414
+ $screen->add_help_tab( array(
415
+ 'id' => 'ctc_preview',
416
+ 'title' => __( 'Preview and Activate', 'chld_thm_cfg' ),
417
+ 'content' => __( '
418
+ <p>Click the View Child or Parent CSS tab to reference the stylesheet code. To preview the stylesheet as a WordPress theme follow these steps:</p>
419
+ <ol><li>Navigate to Appearance > Themes in the WordPress Admin. You will now see the new Child Theme as one of the installed Themes.</li>
420
+ <li>Click "Live Preview" below the new Child Theme to see it in action.</li>
421
+ <li>When you are ready to take the Child Theme live, click "Activate."</li></ol>
422
+ ', 'chld_thm_cfg'
423
+ ),
424
+ ) );
425
+
426
+ $screen->add_help_tab( array(
427
+ 'id' => 'ctc_faq',
428
+ 'title' => __( 'FAQs', 'chld_thm_cfg' ),
429
+ 'content' => __( '
430
+ <h5 id="specific_color">How do I change a specific color/font style/background?</h5>
431
+ <p>You can override a specific value globally using the Rule/Value tab. See Rule/Value, above.</p>
432
+ <h5 id="add_styles">How do I add styles that aren\'t in the Parent Theme?</h5>
433
+ <p>You can add queries and selectors using the "New Selector(s)" textarea on the Query/Selector tab. See Query/Selector, above.</p>
434
+ <h5 id="add_styles">How do I remove a style from the Parent Theme?</h5>
435
+ <p>You shouldn\'t really "remove" a style from the Parent. You can, however, set the rule to "inherit," "none," or zero (depending on the rule). This will negate the Parent value. Some experimentation may be necessary.</p>
436
+ <h5 id="remove_styles">How do I remove a style from the Child Theme?</h5>
437
+ <p>Delete the value from the input for the rule you wish to remove. The Child Theme Configurator only adds overrides for rules that contain values.</p>
438
+ <h5 id="gradients">How do I create cross-browser gradients?</h5>
439
+ <p>The Child Theme Configurator automatically generates the vendor prefixes and filters to display gradients across most browsers. It uses a normalized syntax and only supports two colors without intermediate stops. The inputs consist of origin (e.g., top, left, 135deg, etc.), start color and end color. The browser-specific syntax is generated automatically when you save these values. <strong>Note:</strong> For Internet Explorer, a filter rule approximates the gradient but can only be horizontal (origin top) or vertical (origin left). The legacy webkit-gradient syntax is not supported.</p>
440
+ <h5 id="responsive">How do I make my Theme responsive?</h5>
441
+ <p>This topic is beyond the scope of this document. The short answer is to use a responsive Parent Theme. Some common characteristics of responsive design are:
442
+ <ul><li>Avoiding fixed width and height values. Using max- and min-height values and percentages are ways to make your designs respond to the viewer\'s browser size.</li>
443
+ <li>Combining floats and clears with inline and relative positions allow the elements to adjust gracefully to their container\'s width.</li>
444
+ <li>Showing and hiding content with Javascript.</li></ul>
445
+ <h5 id="web_fonts">How do I add Web Fonts?</h5>
446
+ <p>The easiest method is to paste the @import code provided by Google, Font Squirrel or any other Web Font site into the @import tab. The fonts will then be available to use as a value of the <strong>font-family</strong> rule. Be sure you understand the license for any embedded fonts.</p>
447
+ <p>You can also create a secondary stylesheet that contains @font-face rules and import it using the @import tab. <strong>Note:</strong> Currently the Child Theme Configurator does not generate previews of imported web fonts, but will in a later release.</p>
448
+ <h5 id="functions_file">Where is the functions.php file?</h5>
449
+ <p>You can add your own functions.php file, and any other files and directories you need for your Child Theme. The Child Theme Configurator helps you identify and override the Parent stylesheet without touching the other files.</p>
450
+ ', 'chld_thm_cfg'
451
+ ),
452
+ ) );
453
+
454
+ $screen->add_help_tab( array(
455
+ 'id' => 'ctc_glossary',
456
+ 'title' => __( 'Glossary', 'chld_thm_cfg' ),
457
+ 'content' => __( '
458
+ <h3 id="terms">Glossary</h3>
459
+ <ul><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>
460
+ <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>
461
+ <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 the "color: blue;" rule to members of the "blue-text" class. Thus, the &lt;div&gt; would display text as blue in the browser.</li>
462
+ <li id="selector"><strong>Selector</strong> One or more html elements, classes, ids or other terms used to identify groups of objects.</li>
463
+ <li id="rule"><strong>Rule</strong> One of many standardized attributes 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>
464
+ <li id="at-rule"><strong>At-rule</strong> CSS browser instruction to extend default functionality. The Child Theme Configurator supports two At-rules:
465
+ <ul> <li id="import"><strong>@import</strong> Instructs the browser to load additional CSS information from an external source.</li>
466
+ <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>
467
+ </ul></li>
468
+ <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>
469
+ </ul>
470
+ ', 'chld_thm_cfg'
471
+ ),
472
+ ) );
473
+
474
+ // Set help sidebar
475
+ $screen->set_help_sidebar(
476
+ '
477
+ <ul>
478
+ <li><a href="http://www.lilaeamedia.com/about/contact/">' . __( 'Contact us', 'chld_thm_cfg' ) . '</a></li>
479
+ <li><a href="http://www.lilaeamedia.com/plugins/child-theme-configurator">' . __( 'Plugin Website', 'chld_thm_cfg' ) . '</a></li>
480
+ <li><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=8QE5YJ8WE96AJ">' . __( 'Donate', 'chld_thm_cfg' ) . '</a></li>
481
+ <li><a href="http://wordpress.org/support/view/plugin-reviews/child-theme-configurator?rate=5#postform">' . __( 'Give Us 5 Stars', 'chld_thm_cfg' ) . '</a></li>
482
+ <li><a href="http://codex.wordpress.org/Child_Themes">' . __( 'WordPress Codex', 'chld_thm_cfg' ) . '</a></li>
483
+ <li><a href="http://wordpress.stackexchange.com/">' . __( 'WordPress Answers', 'chld_thm_cfg' ) . '</a></li>
484
+ </ul>
485
+ '
486
+ );
487
+ }
488
+ }
489
+ }
490
+ ?>
includes/class-ctc.php ADDED
@@ -0,0 +1,261 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Exit if accessed directly
3
+ if ( !defined('ABSPATH')) exit;
4
+
5
+ /*
6
+ Class: Child_Theme_Configurator
7
+ Plugin URI: http://www.lilaeamedia.com/plugins/child-theme-configurator/
8
+ Description: Main Controller Class
9
+ Version: 1.1.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) 2013 Lilaea Media
16
+ */
17
+ require_once('class-ctc-ui.php');
18
+ require_once('class-ctc-css.php');
19
+ class Child_Theme_Configurator {
20
+
21
+ var $version = '1.1.0';
22
+ var $css;
23
+ var $optionsName;
24
+ var $menuName;
25
+ var $langName;
26
+ var $pluginName;
27
+ var $shortName;
28
+ var $ns;
29
+ var $ui;
30
+ var $themes;
31
+ var $errors;
32
+ var $hook;
33
+ var $is_ajax;
34
+ var $updated;
35
+
36
+ function __construct($file) {
37
+ $this->dir = dirname( $file );
38
+ $this->optionsName = 'chld_thm_cfg_options';
39
+ $this->menuName = 'chld_thm_cfg_menu';
40
+ $lang_dir = $this->dir . '/lang';
41
+ load_plugin_textdomain('chld_thm_cfg', false, $lang_dir, $lang_dir);
42
+
43
+ $this->pluginName = __('Child Theme Configurator', 'chld_thm_cfg');
44
+ $this->shortName = __('Child Themes', 'chld_thm_cfg');
45
+ $this->pluginPath = $this->dir . '/';
46
+ $this->pluginURL = plugin_dir_url($file);
47
+
48
+ // setup plugin hooks
49
+ add_action('admin_menu', array(&$this, 'admin_menu'));
50
+ add_action('admin_enqueue_scripts', array(&$this, 'enqueue_scripts'));
51
+ add_action('wp_ajax_ctc_update', array(&$this, 'ajax_save_postdata' ));
52
+ add_action('wp_ajax_ctc_query', array(&$this, 'ajax_query_css' ));
53
+ add_action('update_option_' . $this->optionsName, array(&$this, 'update_redirect'), 10);
54
+ }
55
+
56
+ function admin_menu() {
57
+ $this->hook = add_management_page($this->pluginName, $this->shortName, 'edit_theme_options', $this->menuName, array(&$this, 'options_panel') );
58
+ // only load plugin-specific data
59
+ // when ctc page is loaded
60
+ add_action( 'load-' . $this->hook, array(&$this, 'ctc_page_init') );
61
+ }
62
+
63
+ function enqueue_scripts($hook) {
64
+ if ($this->hook == $hook):
65
+ wp_enqueue_style('chld-thm-cfg-admin', $this->pluginURL . 'css/chld-thm-cfg.css');
66
+ wp_enqueue_script('iris');
67
+ wp_enqueue_script('ctc-thm-cfg-ctcgrad', $this->pluginURL . 'js/ctcgrad.min.js', array('iris'), '1.0');
68
+ wp_enqueue_script('chld-thm-cfg-admin', $this->pluginURL . 'js/chld-thm-cfg.min.js', //'js/chld-thm-cfg.js',
69
+ array('jquery-ui-autocomplete'), '1.0', true);
70
+ wp_localize_script( 'chld-thm-cfg-admin', 'ctcAjax',
71
+ apply_filters('ctc_localize_script', array(
72
+ 'ajaxurl' => admin_url( 'admin-ajax.php' ),
73
+ 'theme_uri' => get_theme_root_uri(),
74
+ 'themes' => $this->themes,
75
+ 'parnt' => $this->css->get_property('parnt'),
76
+ 'child' => $this->css->get_property('child'),
77
+ 'imports' => $this->css->get_property('imports'),
78
+ 'rule' => $this->css->get_property('rule'),
79
+ 'sel_ndx' => $this->css->get_property('sel_ndx'),
80
+ 'val_qry' => array(),
81
+ 'rule_val' => array(),
82
+ 'sel_val' => array(),
83
+ 'field_labels' => array(
84
+ '_background_url' => __('URL/None', 'chld_thm_cfg'),
85
+ '_background_origin' => __('Origin', 'chld_thm_cfg'),
86
+ '_background_color1' => __('Color 1', 'chld_thm_cfg'),
87
+ '_background_color2' => __('Color 2', 'chld_thm_cfg'),
88
+ '_border_width' => __('Width', 'chld_thm_cfg'),
89
+ '_border_style' => __('Style', 'chld_thm_cfg'),
90
+ '_border_color' => __('Color', 'chld_thm_cfg'),
91
+ ),
92
+ 'load_txt' => __('Are you sure? This will replace your current settings.', 'chld_thm_cfg'),
93
+ 'swatch_txt' => $this->ui->swatch_text,
94
+ 'swatch_label' => __('Sample', 'chld_thm_cfg'),
95
+ 'selector_txt' => __('Selectors', 'chld_thm_cfg'),
96
+ 'close_txt' => __('Close', 'chld_thm_cfg'),
97
+ 'css_fail_txt' => __('The stylesheet cannot be displayed.', 'chld_thm_cfg'),
98
+ 'child_only_txt' => __('(Child Only)', 'chld_thm_cfg'),
99
+ 'inval_theme_txt' => __('Please enter a valid Child Theme', 'chld_thm_cfg'),
100
+ 'inval_name_txt' => __('Please enter a valid Child Theme name', 'chld_thm_cfg'),
101
+ 'theme_exists_txt' => __('<strong>%s</strong> exists. Please enter a different Child Theme', 'chld_thm_cfg'),
102
+ )));
103
+ endif;
104
+ }
105
+
106
+ function options_panel() {
107
+ $this->ui->render_options();
108
+ }
109
+
110
+ function ctc_page_init () {
111
+ $this->get_themes();
112
+ $this->load_css();
113
+ $this->generate_stylesheet();
114
+ $this->ui = new Child_Theme_Configurator_UI();
115
+ $this->ui->render_help_tabs();
116
+ }
117
+
118
+ function get_themes() {
119
+ $this->themes = array('child' => array(), 'parnt' => array());
120
+ foreach (wp_get_themes() as $theme):
121
+ $parent = $theme->parent();
122
+ if (empty($parent)):
123
+ $slug = $theme->get_template();
124
+ $this->themes['parnt'][$slug] = array('Name' => $theme->get('Name'));
125
+ else:
126
+ $slug = $theme->get_stylesheet();
127
+ $this->themes['child'][$slug] = array('Name' => $theme->get('Name'), 'Author' => $theme->get('Author'), 'Version' => $theme->get('Version'));
128
+ endif;
129
+ endforeach;
130
+ }
131
+
132
+ function load_css() {
133
+ if (!($this->css = get_option($this->optionsName))
134
+ || !is_object($this->css)
135
+ // upgrade to v.1.1.0
136
+ || !($version = $this->css->get_property('version')))
137
+
138
+ $this->css = new Child_Theme_Configurator_CSS();
139
+ }
140
+
141
+ function validate_post() {
142
+ return ('POST' == $_SERVER['REQUEST_METHOD']
143
+ && current_user_can('edit_theme_options')
144
+ && ($this->is_ajax ? check_ajax_referer( 'ctc_update', '_wpnonce', false ) : check_admin_referer( 'ctc_update', '_wpnonce', false )));
145
+ }
146
+
147
+ function ajax_save_postdata() {
148
+ $this->is_ajax = true;
149
+ if ($this->validate_post()):
150
+ $this->load_css();
151
+ $this->css->parse_post_data();
152
+ $this->css->write_css();
153
+ $result = $this->css->get_property('updates');
154
+ $this->css->reset_updates();
155
+ update_option($this->optionsName, $this->css);
156
+ die(json_encode($result));
157
+ else:
158
+ die(0);
159
+ endif;
160
+ }
161
+
162
+ function ajax_query_css() {
163
+ $this->is_ajax = true;
164
+ if ($this->validate_post()):
165
+ $this->load_css();
166
+ $regex = "/^ctc_query_/";
167
+ foreach(preg_grep($regex, array_keys($_POST)) as $key):
168
+ $name = preg_replace($regex, '', $key);
169
+ $param[$name] = sanitize_text_field($_POST[$key]);
170
+ endforeach;
171
+ if (!empty($param['obj'])):
172
+ $result = array(
173
+ array(
174
+ 'key' => isset($param['key'])?$param['key']:'',
175
+ 'obj' => $param['obj'],
176
+ 'data' => $this->css->get_property($param['obj'], $param),
177
+ ),
178
+ );
179
+ die(json_encode($result));
180
+ endif;
181
+ endif;
182
+ die(0);
183
+ }
184
+
185
+ function generate_stylesheet() {
186
+ if (empty($_POST['ctc_load_styles'])) return;
187
+ $this->errors = array();
188
+ if (current_user_can('install_themes') && $this->validate_post()):
189
+ foreach (array(
190
+ 'ctc_theme_parnt',
191
+ 'ctc_child_type',
192
+ 'ctc_theme_child',
193
+ 'ctc_child_name',
194
+ 'ctc_child_template',
195
+ 'ctc_child_author',
196
+ 'ctc_child_version') as $postfield):
197
+ $varparts = explode('_', $postfield);
198
+ $varname = end($varparts);
199
+ ${$varname} = empty($_POST[$postfield])?'':sanitize_text_field($_POST[$postfield]);
200
+ endforeach;
201
+ if ($parnt):
202
+ if (! $this->check_theme_exists($parnt)):
203
+ $this->errors[] = sprintf(__('%s does not exist. Please select a valid Parent Theme', 'chld_thm_cfg'), $parnt);
204
+ endif;
205
+ else:
206
+ $this->errors[] = __('Please select a valid Parent Theme', 'chld_thm_cfg');
207
+ endif;
208
+ if ('new' == $type):
209
+ $child = strtolower(preg_replace("%[^\w\-]%", '', $template));
210
+ if ($this->check_theme_exists($child)):
211
+ $this->errors[] = sprintf(__('<strong>%s</strong> exists. Please enter a different Child Theme template name', 'chld_thm_cfg'), $child);
212
+ endif;
213
+ endif;
214
+ if (empty($child) || preg_match("%^[^a-z]%", $child)):
215
+ $this->errors[] = __('Please enter a valid Child Theme template name', 'chld_thm_cfg');
216
+ endif;
217
+ if (empty($name)):
218
+ $this->errors[] = __('Please enter a valid Child Theme name', 'chld_thm_cfg');
219
+ endif;
220
+ else:
221
+ $this->errors[] = __('You do not have permission to configure child themes.', 'chld_thm_cfg');
222
+ endif;
223
+ if (empty($this->errors)):
224
+ $this->css = new Child_Theme_Configurator_CSS();
225
+ $this->css->set_property('parnt', $parnt);
226
+ $this->css->set_property('child', $child);
227
+ $this->css->set_property('child_name', $name);
228
+ $this->css->set_property('child_author', $author);
229
+ $this->css->set_property('child_version', $version);
230
+ $this->css->parse_css_file('parnt');
231
+ $this->css->parse_css_file('child');
232
+ $this->css->write_css();
233
+ update_option($this->optionsName, $this->css);
234
+ endif;
235
+ }
236
+
237
+ function render_menu($template = 'child', $selected = null) {
238
+ $menu = '<option value="">Select</option>' . LF;
239
+ foreach ($this->themes[$template] as $slug => $theme):
240
+ $menu .= '<option value="' . $slug . '"' . ($slug == $selected ? ' selected' : '') . '>'
241
+ . $slug . ' - "' . $theme['Name'] . '"' . '</option>' . LF;
242
+ endforeach;
243
+ return $menu;
244
+ }
245
+
246
+ function check_theme_exists($theme) {
247
+ return in_array(strtolower($theme), array_keys(wp_get_themes()));
248
+ }
249
+
250
+ function sanitize_options($input) {
251
+ return $input;
252
+ }
253
+
254
+ function update_redirect() {
255
+ if (empty($this->is_ajax)):
256
+ wp_safe_redirect(admin_url('tools.php?page=' . $this->menuName . '&updated=true'));
257
+ die();
258
+ endif;
259
+ }
260
+
261
+ }
js/chld-thm-cfg.js ADDED
@@ -0,0 +1,838 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Script: chld-thm-cfg.js
3
+ * Plugin URI: http://www.lilaeamedia.com/plugins/child-theme-configurator/
4
+ * Description: Handles jQuery, AJAX and other UI
5
+ * Version: 1.1.0
6
+ * Author: Lilaea Media
7
+ * Author URI: http://www.lilaeamedia.com/
8
+ * License: GPLv2
9
+ * Copyright (C) 2013 Lilaea Media
10
+ */
11
+ jQuery(document).ready(function($){
12
+
13
+ var lf = "\n",
14
+
15
+ // initialize functions
16
+ ctc_setup_iris = function(obj) {
17
+ $(obj).iris({
18
+ change: function() {
19
+ ctc_coalesce_inputs(obj);
20
+ }
21
+ });
22
+ },
23
+
24
+ ctc_coalesce_inputs = function(obj) {
25
+ var regex = /^(ctc_(ovrd_)?(parent|child)_([a-z\-]+)_(\d+))(_\w+)?$/,
26
+ $container = $(obj).parents('.ctc-selector-row, .ctc-parent-row').first(),
27
+ $swatch = $container.find('.ctc-swatch').first(),
28
+ cssrules = { 'parent': {}, 'child': {} },
29
+ gradient = {
30
+ 'parent': {
31
+ 'origin': '',
32
+ 'start': '',
33
+ 'end': ''
34
+ },
35
+ 'child': {
36
+ 'origin': '',
37
+ 'start': '',
38
+ 'end': ''
39
+ }
40
+ },
41
+ has_gradient = { 'child': false, 'parent': false },
42
+ postdata = {};
43
+ // set up objects for all neighboring inputs
44
+ $container.find('.ctc-parent-value, .ctc-child-value').each(function(){
45
+ var inputid = $(this).attr('id'),
46
+ inputparts = inputid.match(regex),
47
+ inputtheme = inputparts[3],
48
+ inputrule = ('undefined' == typeof inputparts[4] ? '' : inputparts[4]),
49
+ qsid = inputparts[5],
50
+ rulepart = ('undefined' == typeof inputparts[6] ? '' : inputparts[6]),
51
+ value = ('parent' == inputtheme ? $(this).text() : $(this).val()),
52
+ parts, subparts;
53
+ if ('child' == inputtheme) {
54
+ postdata[inputid] = value;
55
+ }
56
+ if (ctc_is_empty(value)) return;
57
+ // handle specific inputs
58
+ if (false === ctc_is_empty(rulepart)) {
59
+ switch(rulepart) {
60
+ case '_border_width':
61
+ cssrules[inputtheme][inputrule + '-width'] = value;
62
+ break;
63
+ case '_border_style':
64
+ cssrules[inputtheme][inputrule + '-style'] = value;
65
+ break;
66
+ case '_border_color':
67
+ cssrules[inputtheme][inputrule + '-color'] = value;
68
+ break;
69
+ case '_background_url':
70
+ cssrules[inputtheme]['background-image'] = ctc_image_url(inputtheme, value);
71
+ break;
72
+ case '_background_color':
73
+ cssrules[inputtheme]['background-color'] = obj.value;
74
+ break;
75
+ case '_background_color1':
76
+ gradient[inputtheme].start = value;
77
+ has_gradient[inputtheme] = true;
78
+ break;
79
+ case '_background_color2':
80
+ gradient[inputtheme].end = value;
81
+ has_gradient[inputtheme] = true;
82
+ break;
83
+ case '_background_origin':
84
+ gradient[inputtheme].origin = value;
85
+ has_gradient[inputtheme] = true;
86
+ break;
87
+ }
88
+ } else {
89
+ // handle borders
90
+ if (parts = inputrule.match(/^border(\-(top|right|bottom|left))?$/) && !value.match(/none/)) {
91
+ subparts = value.split(/ +/);
92
+ cssrules[inputtheme][inputrule + '-width'] = 'undefined' == typeof subparts[0] ? '' : subparts[0];
93
+ cssrules[inputtheme][inputrule + '-style'] = 'undefined' == typeof subparts[1] ? '' : subparts[1];
94
+ cssrules[inputtheme][inputrule + '-color'] = 'undefined' == typeof subparts[2] ? '' : subparts[2];
95
+ // handle background images
96
+ } else if ( 'background-image' == inputrule ) {
97
+ if (value.match(/url\(/)) {
98
+ cssrules[inputtheme]['background-image'] = ctc_image_url(inputtheme, value);
99
+ } else {
100
+ subparts = value.split(/ +/);
101
+ if (subparts.length > 2) {
102
+ gradient[inputtheme].origin = 'undefined' == typeof subparts[0] ? 'top' : subparts[0];
103
+ gradient[inputtheme].start = 'undefined' == typeof subparts[1] ? 'transparent' : subparts[1];
104
+ gradient[inputtheme].end = 'undefined' == typeof subparts[2] ? 'transparent' : subparts[2];
105
+ has_gradient[inputtheme] = true;
106
+ } else {
107
+ cssrules[inputtheme]['background-image'] = value;
108
+ }
109
+ }
110
+ } else {
111
+ cssrules[inputtheme][inputrule] = value;
112
+ }
113
+ }
114
+ });
115
+ // update swatch
116
+ if ('undefined' != typeof $swatch) {
117
+ $($swatch).removeAttr('style');
118
+ if (has_gradient.parent) { $($swatch).ctcgrad(gradient.parent.origin, [gradient.parent.start, gradient.parent.end]); }
119
+ $($swatch).css(cssrules.parent);
120
+ if (!($swatch.attr('id').match(/parent/))){
121
+ if (has_gradient.child) { $($swatch).ctcgrad(gradient.child.origin, [gradient.child.start, gradient.child.end]); }
122
+ $($swatch).css(cssrules.child);
123
+ }
124
+ }
125
+ return postdata;
126
+ },
127
+ ctc_update_cache = function(response) {
128
+ var currQuery, currSelId, currRule;
129
+ $(response).each(function(){
130
+ switch (this.obj) {
131
+ case 'imports':
132
+ ctcAjax.imports = this.data;
133
+ break;
134
+
135
+ case 'rule_val':
136
+ ctcAjax.rule_val[this.key] = this.data;
137
+ currRuleId = this.key;
138
+ break;
139
+
140
+ case 'val_qry':
141
+ ctcAjax.val_qry[this.key] = this.data;
142
+ break;
143
+
144
+ case 'rule':
145
+ ctcAjax.rule = this.data;
146
+ break;
147
+
148
+ case 'sel_ndx':
149
+ if (ctc_is_empty(this.key)) {
150
+ ctcAjax.sel_ndx = this.data;
151
+ } else if ('qsid' == this.key) {
152
+ ctcAjax.sel_ndx[this.data['query']][this.data['selector']] = this.data['qsid'];
153
+ } else {
154
+ ctcAjax.sel_ndx[this.key] = this.data;
155
+ currQuery = this.key;
156
+ }
157
+ break;
158
+
159
+ case 'sel_val':
160
+ ctcAjax.sel_val[this.key] = this.data;
161
+ currSelId = this.key;
162
+ break;
163
+ }
164
+ });
165
+ },
166
+ ctc_image_url = function(theme, value) {
167
+ var parts = value.match(/url\([" ]*(.+?)[" ]*\)/),
168
+ path = ('undefined' == typeof parts ? null : parts[1]),
169
+ url = ctcAjax.theme_uri + '/' + ('parent' == theme ? ctcAjax.parnt : ctcAjax.child) + '/',
170
+ image_url;
171
+ if (!path) {
172
+ return false;
173
+ } else if (path.match(/^(http:|\/)/)) {
174
+ image_url = value;
175
+ } else {
176
+ image_url = 'url(' + url + path + ')';
177
+ }
178
+ return image_url;
179
+ },
180
+
181
+ ctc_is_empty = function(obj) {
182
+ // first bail when definitely empty or undefined (true)
183
+ if ('undefined' == typeof obj || false === obj || null === obj || '' === obj || 0 === obj) { return true; }
184
+ // then, if this is bool, string or number it must not be empty (false)
185
+ if (true === obj || "string" === typeof obj || "number" === typeof obj) { return false; }
186
+ // thanks to Abena Kuttin for Win safe version
187
+ // check for object type to be safe
188
+ if ("object" === typeof obj) {
189
+ // Use a standard for in loop
190
+ for (var x in obj) {
191
+ // A for in will iterate over members on the prototype
192
+ // chain as well, but Object.getOwnPropertyNames returns
193
+ // only those directly on the object, so use hasOwnProperty.
194
+ if (obj.hasOwnProperty(x)) {
195
+ // any value means not empty (false)
196
+ return false;
197
+ }
198
+ }
199
+ // no properties, so return empty (true)
200
+ return true;
201
+ }
202
+ // this must be an unsupported datatype, so return not empty
203
+ return false;
204
+
205
+ },
206
+
207
+ ctc_load_queries = function() {
208
+ var arr = [];
209
+ if (1 === loading.sel_ndx) return arr;
210
+ if (0 === loading.sel_ndx) { // {
211
+ // retrieve from server
212
+ loading.sel_ndx = 1;
213
+ ctc_query_css('sel_ndx', null, ctc_setup_query_menu);
214
+ return arr;
215
+ }
216
+ if (false === ctc_is_empty(ctcAjax.sel_ndx)) {
217
+ $.each(ctcAjax.sel_ndx, function(key, value) {
218
+ var obj = { label: key, value: key };
219
+ arr.push(obj);
220
+ });
221
+ }
222
+ return arr;
223
+ },
224
+
225
+ ctc_load_selectors = function(query) {
226
+ var arr = [];
227
+ if (1 === loading.sel_ndx) {
228
+ return arr;
229
+ }
230
+ if (0 === loading.sel_ndx) {
231
+ // retrieve from server
232
+ loading.sel_ndx = 1;
233
+ ctc_query_css('sel_ndx', query, ctc_setup_selector_menu);
234
+ return arr;
235
+ }
236
+ if (false === ctc_is_empty(ctcAjax.sel_ndx[query])) {
237
+ $.each(ctcAjax.sel_ndx[query], function(key, value) {
238
+ var obj = { label: key, value: value };
239
+ arr.push(obj);
240
+ });
241
+ }
242
+ return arr;
243
+ },
244
+
245
+ ctc_load_rules = function() {
246
+ var arr = [];
247
+ if (1 === loading.rule) return arr;
248
+ if (0 === loading.rule) {
249
+ loading.rule = 1;
250
+ ctc_query_css('rule', null, ctc_setup_rule_menu);
251
+ return arr;
252
+ }
253
+ if (false === ctc_is_empty(ctcAjax.rule)) {
254
+ $.each(ctcAjax.rule, function(key, value) {
255
+ var obj = { label: value, value: key };
256
+ arr.push(obj);
257
+ });
258
+ }
259
+ return arr.sort(function (a, b) {
260
+ if (a.label > b.label)
261
+ return 1;
262
+ if (a.label < b.label)
263
+ return -1;
264
+ return 0;
265
+ });
266
+ },
267
+
268
+ ctc_render_child_rule_input = function(qsid, rule, specific) {
269
+ var html = '',
270
+ value = (ctc_is_empty(ctcAjax.sel_val[qsid]) || ctc_is_empty(ctcAjax.sel_val[qsid].value)
271
+ || ctc_is_empty(ctcAjax.sel_val[qsid].value[rule]) ? '' : ctcAjax.sel_val[qsid].value[rule]),
272
+ oldRuleObj = ctc_decode_value(rule, ('undefined' == typeof value ? '' : value['parnt'])),
273
+ newRuleObj = ctc_decode_value(rule, ('undefined' == typeof value ? '' : value['child']));
274
+ if (false === ctc_is_empty(ctcAjax.sel_val[qsid])) {
275
+ html += '<div class="ctc-' + (specific ? 'selector' : 'input' ) + '-row clearfix">' + lf;
276
+ html += '<div class="ctc-input-cell">' + (specific ? ctcAjax.sel_val[qsid].selector
277
+ + (ctc_is_empty(oldRuleObj.orig) ? '<br/>' + ctcAjax.child_only_txt : '') : rule) + '</div>' + lf;
278
+ if (!specific) {
279
+ html += '<div class="ctc-parent-value ctc-input-cell" id="ctc_parent_' + rule + '_' + qsid + '">'
280
+ + (ctc_is_empty(oldRuleObj.orig) ? '[no value]' : oldRuleObj.orig) + '</div>' + lf;
281
+ }
282
+ html += '<div class="ctc-input-cell">' + lf;
283
+ if (false === ctc_is_empty(oldRuleObj.names)){
284
+ $.each(oldRuleObj.names, function(ndx, newname) {
285
+ newname = (ctc_is_empty(newname) ? '' : newname);
286
+ html += '<div class="ctc-child-input-cell">' + lf;
287
+ var id = 'ctc_' + (specific? '' : 'ovrd_') + 'child_' + rule + '_' + qsid + newname,
288
+ newval;
289
+ if (!(newval = newRuleObj.values.shift()) ){
290
+ newval = '';
291
+ }
292
+
293
+ html += (ctc_is_empty(newname) ? '' : ctcAjax.field_labels[newname] + ':<br/>')
294
+ + '<input type="text" id="' + id + '" name="' + id + '" class="ctc-child-value'
295
+ + ((newname + rule).match(/color/) ? ' color-picker' : '')
296
+ + ((newname).match(/url/) ? ' ctc-input-wide' : '')
297
+ + '" value="' + newval + '" />' + lf;
298
+ html += '</div>' + lf;
299
+ });
300
+ }
301
+ html += '</div>' + lf;
302
+ html += (specific ? '<div class="ctc-swatch ctc-specific" id="ctc_child_' + rule + '_' + qsid + '_swatch">'
303
+ + ctcAjax.swatch_txt + '</div>' + lf
304
+ + '<div class="ctc-child-input-cell ctc-button-cell" id="ctc_save_' + rule + '_' + qsid + '_cell">' + lf
305
+ + '<input type="button" class="button ctc-save-input" id="ctc_save_' + rule + '_' + qsid
306
+ + '" name="ctc_save_' + rule + '_' + qsid + '" value="Save" /></div>' + lf : '');
307
+ html += '</div><!-- end input row -->' + lf;
308
+ }
309
+ return html;
310
+ },
311
+
312
+ ctc_render_selector_inputs = function(qsid) {
313
+ if (1 === loading.sel_val) {
314
+ return false;
315
+ }
316
+ if (0 == loading.sel_val) {
317
+ loading.sel_val = 1;
318
+ ctc_query_css('sel_val', qsid, ctc_render_selector_inputs);
319
+ return false;
320
+ }
321
+ var html = '';
322
+ if (false === ctc_is_empty(ctcAjax.sel_val[qsid] && false === ctc_is_empty(ctcAjax.sel_val[qsid].value))){
323
+ $.each(ctcAjax.sel_val[qsid].value, function(rule, value) {
324
+ html += ctc_render_child_rule_input(qsid, rule, false);
325
+ });
326
+ }
327
+ $('#ctc_sel_ovrd_rule_inputs').html(html).find('.color-picker').each(function() {
328
+ ctc_setup_iris(this);
329
+ });
330
+ ctc_coalesce_inputs('#ctc_child_all_0_swatch');
331
+ }
332
+
333
+ ctc_render_rule_value_inputs = function(ruleid) {
334
+ if (1 === loading.rule_val) return false;
335
+
336
+ if (0 == loading.rule_val) {
337
+ loading.rule_val = 1;
338
+ ctc_query_css('rule_val', ruleid, ctc_render_rule_value_inputs);
339
+ return false;
340
+ }
341
+ var rule = ctcAjax.rule[ruleid],
342
+ html = '<div class="ctc-input-row clearfix" id="ctc_rule_row_' + rule + '">' + lf;
343
+ if (false === ctc_is_empty(ctcAjax.rule_val[ruleid])){
344
+ $.each(ctcAjax.rule_val[ruleid], function(valid, value) {
345
+ var oldRuleObj = ctc_decode_value(rule, value);
346
+ html += '<div class="ctc-parent-row clearfix" id="ctc_rule_row_' + rule + '_' + valid + '">' + lf;
347
+ html += '<div class="ctc-input-cell ctc-parent-value" id="ctc_parent_' + rule + '_' + valid + '">'
348
+ + oldRuleObj.orig + '</div>' + lf;
349
+ html += '<div class="ctc-input-cell">' + lf;
350
+ html += '<div class="ctc-swatch ctc-specific" id="ctc_parent_'+rule+'_' + valid + '_swatch">'
351
+ + ctcAjax.swatch_txt + '</div></div>' + lf;
352
+ html += '<div class="ctc-input-cell"><a href="#" class="ctc-selector-handle" id="ctc_selector_' + rule + '_' + valid + '">'
353
+ + ctcAjax.selector_txt + '</a></div>' + lf;
354
+ html += '<div id="ctc_selector_' + rule + '_' + valid + '_container" class="ctc-selector-container clearfix">' + lf;
355
+ html += '<a href="#" id="ctc_selector_' + rule + '_' + valid + '_close" class="ctc-selector-handle" style="float:right">'
356
+ + ctcAjax.close_txt + '</a><div id="ctc_status_val_qry_' + valid + '"></div>' + lf;
357
+ html += '<div id="ctc_selector_' + rule + '_' + valid + '_rows"></div>' + lf;
358
+ html += '</div></div>' + lf;
359
+ });
360
+ html += '</div>' + lf;
361
+ }
362
+ $('#ctc_rule_value_inputs').html(html).find('.ctc-swatch').each(function() {
363
+ ctc_coalesce_inputs(this);
364
+ });
365
+ },
366
+
367
+ ctc_render_selector_value_inputs = function(valid) {
368
+ if (1 == loading.val_qry) return false;
369
+ var params,
370
+ page_ruleid,
371
+ rule = $('#ctc_rule_menu_selected').text(),
372
+ selector,
373
+ html = '';
374
+ if (0 === loading.val_qry) {
375
+ loading.val_qry = 1;
376
+ params = { 'rule': rule };
377
+ ctc_query_css('val_qry', valid, ctc_render_selector_value_inputs, params);
378
+ return false;
379
+ }
380
+ if (false === ctc_is_empty(ctcAjax.val_qry[valid])){
381
+ $.each(ctcAjax.val_qry[valid], function(rule, queries) {
382
+ page_rule = rule;
383
+ $.each(queries, function(query, selectors) {
384
+ html += '<h4 class="ctc-query-heading">' + query + '</h4>' + lf;
385
+ if (false === ctc_is_empty(selectors)){
386
+ $.each(selectors, function(qsid, data) {
387
+ ctcAjax.sel_val[qsid] = data;
388
+ html += ctc_render_child_rule_input(qsid, rule, true);
389
+ });
390
+ }
391
+ });
392
+ });
393
+ }
394
+ selector = '#ctc_selector_' + rule + '_' + valid + '_rows';
395
+ $(selector).html(html).find('.color-picker').each(function() {
396
+ ctc_setup_iris(this);
397
+ });
398
+ $(selector).find('.ctc-swatch').each(function() {
399
+ ctc_coalesce_inputs(this);
400
+ });
401
+
402
+ },
403
+ ctc_query_css = function(obj, key, callback, params) {
404
+ var postdata = { 'ctc_query_obj' : obj, 'ctc_query_key': key },
405
+ status_sel = '#ctc_status_' + obj + ('val_qry' == obj ? '_' + key : '');
406
+
407
+ if ('object' === typeof params) {
408
+ $.each(params, function(key, val){
409
+ postdata['ctc_query_' + key] = val;
410
+ });
411
+ }
412
+ $('.ctc-status-icon').remove();
413
+ $(status_sel).append('<span class="ctc-status-icon spinner"></span>');
414
+ $('.spinner').show();
415
+ // add wp ajax action to array
416
+ postdata['action'] = 'ctc_query';
417
+ postdata['_wpnonce'] = $('#_wpnonce').val();
418
+ // ajax post input data
419
+ $.post(
420
+ // get ajax url from localized object
421
+ ctcAjax.ajaxurl,
422
+ //Data
423
+ postdata,
424
+ //on success function
425
+ function(response){
426
+ // hide spinner
427
+ loading[obj] = 2;
428
+ $('.ctc-status-icon').removeClass('spinner');
429
+ // show check mark
430
+ if (ctc_is_empty(response)) {
431
+ $('.ctc-status-icon').addClass('failure');
432
+ } else {
433
+ $('.ctc-status-icon').addClass('success');
434
+ // update data objects
435
+ ctc_update_cache(response);
436
+ if ('function' === typeof callback) {
437
+ callback(key);
438
+ }
439
+ return false;
440
+ }
441
+ },'json'
442
+ ).fail(function(){
443
+ loading[obj] = 0;
444
+ // hide spinner
445
+ $('.ctc-status-icon').removeClass('spinner');
446
+ // show check mark
447
+ $('.ctc-status-icon').addClass('failure');
448
+ });
449
+ return false;
450
+ },
451
+ ctc_save = function(obj) {
452
+ var postdata = {},
453
+ $selector, $query, $imports, $rule;
454
+ // disable the button until ajax returns
455
+ $(obj).prop('disabled', true);
456
+ // clear previous success/fail icons
457
+ $('.ctc-status-icon').remove();
458
+ // show spinner
459
+ $(obj).parent('.ctc-textarea-button-cell, .ctc-button-cell').append('<span class="ctc-status-icon spinner"></span>');
460
+ $('.spinner').show();
461
+ if (($selector = $('#ctc_new_selectors')) && 'ctc_save_new_selectors' == $(obj).attr('id')) {
462
+ postdata['ctc_new_selectors'] = $selector.val();
463
+ if ($query = $('#ctc_sel_ovrd_query_selected')) {
464
+ postdata['ctc_sel_ovrd_query'] = $query.text();
465
+ }
466
+ } else if (($imports = $('#ctc_child_imports')) && 'ctc_save_imports' == $(obj).attr('id')) {
467
+ postdata['ctc_child_imports'] = $imports.val();
468
+ } else {
469
+ // coalesce inputs
470
+ postdata = ctc_coalesce_inputs(obj);
471
+ }
472
+ // add wp ajax action to array
473
+ postdata['action'] = 'ctc_update';
474
+ postdata['_wpnonce'] = $('#_wpnonce').val();
475
+ // ajax post input data
476
+ $.post(
477
+ // get ajax url from localized object
478
+ ctcAjax.ajaxurl,
479
+ //Data
480
+ postdata,
481
+ //on success function
482
+ function(response){
483
+ // release button
484
+ $(obj).prop('disabled', false);
485
+ // hide spinner
486
+ $('.ctc-status-icon').removeClass('spinner');
487
+ // show check mark
488
+ if (ctc_is_empty(response)) {
489
+ $('.ctc-status-icon').addClass('failure');
490
+ } else {
491
+ $('.ctc-status-icon').addClass('success');
492
+ $('#ctc_new_selectors').val('');
493
+ // update data objects
494
+ ctc_update_cache(response);
495
+ ctc_setup_menus();
496
+ }
497
+ return false;
498
+ },
499
+ 'json'
500
+ ).fail(function(){
501
+ // release button
502
+ $(obj).prop('disabled', false);
503
+ // hide spinner
504
+ $('.ctc-status-icon').removeClass('spinner');
505
+ // show check mark
506
+ $('.ctc-status-icon').addClass('failure');
507
+ });
508
+ return false;
509
+ },
510
+ /* stub for future ajax loader
511
+ ctc_load_css = function(e) {
512
+
513
+
514
+ var postdata = $(this).serializeArray();
515
+ // disable the button until ajax returns
516
+ $('#ctc_load_styles').prop('disabled', true);
517
+ // clear previous success/fail icons
518
+ $('.ctc-status-icon').remove();
519
+ // show spinner
520
+ $('#ctc_load_styles').parent('.ctc-input-cell').append('<span class="ctc-status-icon spinner"></span>');
521
+ $('.spinner').show();
522
+ return true;
523
+
524
+ // ajax post input data
525
+ $.post(
526
+ // get ajax url from localized object
527
+ ctcAjax.ajaxurl,
528
+ //Data
529
+ postdata,
530
+ //on success function
531
+ function(response){
532
+ // release button
533
+ $('#ctc_load_styles').prop('disabled', false);
534
+ // hide spinner
535
+ $('.ctc-status-icon').removeClass('spinner');
536
+ // show check mark
537
+ if (ctc_is_empty(response.updated)) {
538
+ $('.ctc-status-icon').addClass('failure');
539
+ // update notice
540
+ if (false === ctc_is_empty(response.error)) {
541
+ ctc_set_notice({'error': response.error});
542
+ }
543
+ } else {
544
+ $('.ctc-status-icon').addClass('success');
545
+ // update notice
546
+ if (false === ctc_is_empty(response.updated)) {
547
+ ctc_set_notice({'updated': response.updated});
548
+ }
549
+ if (false === ctc_is_empty(response.themes)) {
550
+ ctcAjax.themes = response.themes;
551
+ }
552
+ if (false === ctc_is_empty(response.menu)) {
553
+ $('#ctc_theme_child').html(response.menu);
554
+ }
555
+ $('.nav-tab, .ctc-option-panel, .ctc-radio, .ctc-select, label').fadeIn('fast');
556
+ }
557
+ return false;
558
+ },
559
+ 'json'
560
+ ).fail(function(){
561
+ // release button
562
+ $('#ctc_load_styles').prop('disabled', false);
563
+ // hide spinner
564
+ $('.ctc-status-icon').removeClass('spinner');
565
+ // show check mark
566
+ $('.ctc-status-icon').addClass('failure');
567
+ });
568
+ return false;
569
+ },*/
570
+ ctc_decode_value = function(rule, value) {
571
+ value = ('undefined' == typeof value ? '' : value);
572
+ var obj = { 'orig': value };
573
+ if (rule.match(/^border(\-(top|right|bottom|left))?$/)) {
574
+ var params = value.split(/ +/);
575
+ obj['names'] = [
576
+ '_border_width',
577
+ '_border_style',
578
+ '_border_color',
579
+ ];
580
+ obj['values'] = [
581
+ ('undefined' == typeof params[0] ? '' : params[0]),
582
+ ('undefined' == typeof params[1] ? '' : params[1]),
583
+ ('undefined' == typeof params[2] ? '' : params[2])
584
+ ];
585
+ } else if (rule.match(/^background\-image/)) {
586
+ obj['names'] = [
587
+ '_background_url',
588
+ '_background_origin',
589
+ '_background_color1',
590
+ '_background_color2'
591
+ ];
592
+ obj['values'] = ['','','',''];
593
+ if (value.match(/:/)) {
594
+ var params = value.split(/:/);
595
+ obj['values'][1] = ('undefined' == typeof params[0] ? '' : params[0]);
596
+ obj['values'][2] = ('undefined' == typeof params[1] ? '' : params[1]);
597
+ obj['values'][3] = ('undefined' == typeof params[3] ? '' : params[3]);
598
+ obj['orig'] = [ obj['values'][1], obj['values'][2], obj['values'][3] ].join(' '); // display "origin color1 color2"
599
+ } else {
600
+ obj['values'][0] = value;
601
+ }
602
+ } else {
603
+ obj['names'] = [''];
604
+ obj['values'] = [ value ];
605
+ }
606
+ return obj;
607
+ },
608
+
609
+ ctc_set_query = function(value) {
610
+ $('#ctc_sel_ovrd_query').val('');
611
+ $('#ctc_sel_ovrd_query_selected').text(value);
612
+ ctc_setup_selector_menu(value);
613
+ $('#ctc_new_selector_row').show();
614
+ },
615
+
616
+ ctc_set_selector = function(value,label) {
617
+ $('#ctc_sel_ovrd_selector').val('');
618
+ $('#ctc_sel_ovrd_selector_selected').text(label);
619
+ $('#ctc_sel_ovrd_qsid').val(value);
620
+ if (1 != loading.sel_val) loading.sel_val = 0;
621
+ ctc_render_selector_inputs(value);
622
+ $('#ctc_sel_ovrd_new_rule, #ctc_sel_ovrd_rule_header,#ctc_sel_ovrd_rule_inputs_container,#ctc_sel_ovrd_rule_inputs').show();
623
+ },
624
+
625
+ ctc_set_rule = function(value,label) {
626
+ $('#ctc_rule_menu').val('');
627
+ $('#ctc_rule_menu_selected').text(label);
628
+ if (1 != loading.rule_val) loading.rule_val = 0;
629
+ ctc_render_rule_value_inputs(value);
630
+ $('#ctc_rule_value_inputs,#ctc_input_row_rule_header').show();
631
+ },
632
+ ctc_setup_query_menu = function() {
633
+ ctc_queries = ctc_load_queries();
634
+ $('#ctc_sel_ovrd_query').autocomplete({
635
+ source: ctc_queries,
636
+ minLength: 0,
637
+ selectFirst: true,
638
+ autoFocus: true,
639
+ select: function(e, ui) {
640
+ ctc_set_query(ui.item.value);
641
+ return false;
642
+ },
643
+ focus: function(e) { e.preventDefault(); }
644
+ });
645
+ },
646
+ ctc_setup_selector_menu = function(query) {
647
+ ctc_selectors = ctc_load_selectors(query);
648
+ $('#ctc_sel_ovrd_selector').autocomplete({
649
+ source: ctc_selectors,
650
+ selectFirst: true,
651
+ autoFocus: true,
652
+ select: function(e, ui) {
653
+ ctc_set_selector(ui.item.value, ui.item.label);
654
+ return false;
655
+ },
656
+ focus: function(e) { e.preventDefault(); }
657
+ });
658
+ },
659
+ ctc_setup_rule_menu = function() {
660
+ ctc_rules = ctc_load_rules();
661
+ $('#ctc_rule_menu').autocomplete({
662
+ source: ctc_rules,
663
+ //minLength: 0,
664
+ selectFirst: true,
665
+ autoFocus: true,
666
+ select: function(e, ui) {
667
+ ctc_set_rule(ui.item.value, ui.item.label);
668
+ return false;
669
+ },
670
+ focus: function(e) { e.preventDefault(); }
671
+ });
672
+ },
673
+ ctc_setup_new_rule_menu = function() {
674
+ $('#ctc_new_rule_menu').autocomplete({
675
+ source: ctc_rules,
676
+ //minLength: 0,
677
+ selectFirst: true,
678
+ autoFocus: true,
679
+ select: function(e, ui) {
680
+ var qsid = $('#ctc_sel_ovrd_qsid').val();
681
+ $('#ctc_sel_ovrd_rule_inputs').append(ctc_render_child_rule_input(qsid, ui.item.label, false)).find('.color-picker').each(function() {
682
+ ctc_setup_iris(this);
683
+ });
684
+ $('#ctc_new_rule_menu').val('');
685
+ return false;
686
+ },
687
+ focus: function(e) { e.preventDefault(); }
688
+ });
689
+ },
690
+ ctc_setup_menus = function() {
691
+ ctc_setup_query_menu();
692
+ ctc_setup_selector_menu('');
693
+ ctc_setup_rule_menu();
694
+ ctc_setup_new_rule_menu();
695
+ },
696
+ ctc_theme_exists = function(testslug, testtype) {
697
+ var exists = false;
698
+ $.each(ctcAjax.themes, function(type, theme){
699
+ $.each(theme, function(slug, data){
700
+ if (slug == testslug && ('parnt' == type || 'new' == testtype)) {
701
+ exists = true;
702
+ return false;
703
+ }
704
+ });
705
+ if (exists) return false;
706
+ });
707
+ return exists;
708
+ },
709
+
710
+ ctc_set_notice = function(noticearr) {
711
+ var errorHtml = '';
712
+ if (false === ctc_is_empty(noticearr)) {
713
+ $.each(noticearr, function(type, list){
714
+ errorHtml += '<div class="' + type + '"><ul>' + lf;
715
+ $(list).each(function(ndx, el){
716
+ errorHtml += '<li>' + el.toString() + '</li>' + lf;
717
+ });
718
+ errorHtml += '</ul></div>';
719
+ });
720
+ }
721
+ $('#ctc_error_notice').html(errorHtml);
722
+ },
723
+ ctc_validate = function() {
724
+ var regex = /[^\w\-]/,
725
+ newslug = $('#ctc_child_template').val().replace(regex).toLowerCase(),
726
+ slug = $('#ctc_theme_child').val().replace(regex).toLowerCase(),
727
+ type = $('input[name=ctc_child_type]:checked').val(),
728
+ errors = [];
729
+ if ('new' == type) slug = newslug;
730
+ if (ctc_theme_exists(slug, type)) {
731
+ errors.push(ctcAjax.theme_exists_txt.replace(/%s/, slug));
732
+ }
733
+ if ('' == slug || slug.match(/^[^a-z]/)) {
734
+ errors.push(ctcAjax.inval_theme_txt);
735
+ }
736
+ if ('' == $('#ctc_child_name').val()) {
737
+ errors.push(ctcAjax.inval_name_txt);
738
+ }
739
+ if (errors.length) {
740
+ ctc_set_notice({'error': errors});
741
+ return false;
742
+ }
743
+ return true;
744
+ },
745
+ ctc_set_theme_menu = function() {
746
+ var slug = $('#ctc_theme_child').val();
747
+ if (false === ctc_is_empty(ctcAjax.themes.child[slug])) {
748
+ $('#ctc_child_name').val(ctcAjax.themes.child[slug].Name);
749
+ $('#ctc_child_author').val(ctcAjax.themes.child[slug].Author);
750
+ $('#ctc_child_version').val(ctcAjax.themes.child[slug].Version);
751
+ }
752
+ },
753
+ fade_update_notice = function() {
754
+ $('.updated').fadeOut('slow', function(){ $('.updated').remove(); });
755
+ },
756
+ // initialize vars
757
+ // ajax semaphores: 0 = reload, 1 = loading, 2 = loaded
758
+ loading = {
759
+ 'rule': 2,
760
+ 'sel_ndx': 2,
761
+ 'val_qry': 0,
762
+ 'rule_val': 0,
763
+ 'sel_val': 0
764
+ },
765
+
766
+ ctc_selectors = [],
767
+ ctc_queries = [],
768
+ ctc_rules = [];
769
+ // -- end var definitions
770
+
771
+ // initialize Iris color picker
772
+ $('.color-picker').each(function() {
773
+ ctc_setup_iris(this);
774
+ });
775
+ // bind event handlers
776
+ $('.ctc-option-panel-container').on('focus', '.color-picker', function(){
777
+ ctc_set_notice('')
778
+ $(this).iris('toggle');
779
+ $('.iris-picker').css({'position':'absolute', 'z-index':10});
780
+ });
781
+ $('.ctc-option-panel-container').on('focus', 'input', function() {
782
+ ctc_set_notice('')
783
+ $('.color-picker').not(this).iris('hide');
784
+ });
785
+ $('.ctc-option-panel-container').on('change', '.ctc-child-value', function() {
786
+ ctc_coalesce_inputs(this);
787
+ });
788
+ $('.ctc-option-panel-container').on('click', '.ctc-selector-handle', function(e) {
789
+ e.preventDefault();
790
+ ctc_set_notice('')
791
+ var id = $(this).attr('id').replace('_close', ''),
792
+ valid = id.replace(/\D+/g, '');
793
+ if ($('#' + id + '_container').is(':hidden')) {
794
+ if (1 != loading.val_qry) loading.val_qry = 0;
795
+ ctc_render_selector_value_inputs(valid);
796
+ }
797
+ $('#' + id + '_container').fadeToggle('fast');
798
+ $('.ctc-selector-container').not('#' + id + '_container').fadeOut('fast');
799
+ });
800
+ $('.nav-tab').on('click', function(e){
801
+ e.preventDefault();
802
+ // clear the notice box
803
+ ctc_set_notice('')
804
+ var id = '#' + $(this).attr('id'), panelid = id + '_panel';
805
+ $('.nav-tab').removeClass('nav-tab-active');
806
+ $('.ctc-option-panel').removeClass('ctc-option-panel-active');
807
+ $('.ctc-selector-container').hide();
808
+ $(id).addClass('nav-tab-active');
809
+ $('.ctc-option-panel-container').scrollTop(0);
810
+ $(panelid).addClass('ctc-option-panel-active');
811
+ });
812
+ $('#view_child_options,#view_parnt_options').on('click', function(e){
813
+ ctc_set_notice('')
814
+ var stamp = new Date().getTime(),
815
+ theme = $(this).attr('id').match(/(child|parnt)/)[1],
816
+ css_uri = ctcAjax.theme_uri + '/' + ctcAjax[theme] + '/style.css?' + stamp;
817
+ $.get(
818
+ css_uri,
819
+ function(response){
820
+ $('#view_'+theme+'_options_panel').text(response);
821
+ }
822
+ ).fail(function(){
823
+ $('#view_'+theme+'_options_panel').text(ctcAjax.css_fail_txt);
824
+ });
825
+ });
826
+ $('#ctc_load_form').on('submit', function() {
827
+ return (ctc_validate() && confirm(ctcAjax.load_txt) ) ;
828
+ });
829
+ $(document).on('click', '.ctc-save-input', function(e) {
830
+ ctc_save(this);
831
+ });
832
+ // initialize menus
833
+ ctc_setup_menus();
834
+ $('input[type=submit],input[type=button]').prop('disabled', false);
835
+ setTimeout(fade_update_notice, 6000);
836
+ });
837
+
838
+
js/chld-thm-cfg.min.js ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Script: chld-thm-cfg.js
3
+ * Plugin URI: http://www.lilaeamedia.com/plugins/child-theme-configurator/
4
+ * Description: Handles jQuery, AJAX and other UI
5
+ * Version: 1.1.0
6
+ * Author: Lilaea Media
7
+ * Author URI: http://www.lilaeamedia.com/
8
+ * License: GPLv2
9
+ * Copyright (C) 2013 Lilaea Media
10
+ */
11
+ ;jQuery(document).ready(function(f){var k="\n",l=function(m){f(m).iris({change:function(){i(m)}})},i=function(s){var o=/^(ctc_(ovrd_)?(parent|child)_([a-z\-]+)_(\d+))(_\w+)?$/,t=f(s).parents(".ctc-selector-row, .ctc-parent-row").first(),r=t.find(".ctc-swatch").first(),q={parent:{},child:{}},p={parent:{origin:"",start:"",end:""},child:{origin:"",start:"",end:""}},n={child:false,parent:false},m={};t.find(".ctc-parent-value, .ctc-child-value").each(function(){var A=f(this).attr("id"),u=A.match(o),v=u[3],C=("undefined"==typeof u[4]?"":u[4]),z=u[5],y=("undefined"==typeof u[6]?"":u[6]),B=("parent"==v?f(this).text():f(this).val()),x,w;if("child"==v){m[A]=B}if(a(B)){return}if(false===a(y)){switch(y){case"_border_width":q[v][C+"-width"]=B;break;case"_border_style":q[v][C+"-style"]=B;break;case"_border_color":q[v][C+"-color"]=B;break;case"_background_url":q[v]["background-image"]=c(v,B);break;case"_background_color":q[v]["background-color"]=s.value;break;case"_background_color1":p[v].start=B;n[v]=true;break;case"_background_color2":p[v].end=B;n[v]=true;break;case"_background_origin":p[v].origin=B;n[v]=true;break}}else{if(x=C.match(/^border(\-(top|right|bottom|left))?$/)&&!B.match(/none/)){w=B.split(/ +/);q[v][C+"-width"]="undefined"==typeof w[0]?"":w[0];q[v][C+"-style"]="undefined"==typeof w[1]?"":w[1];q[v][C+"-color"]="undefined"==typeof w[2]?"":w[2]}else{if("background-image"==C){if(B.match(/url\(/)){q[v]["background-image"]=c(v,B)}else{w=B.split(/ +/);if(w.length>2){p[v].origin="undefined"==typeof w[0]?"top":w[0];p[v].start="undefined"==typeof w[1]?"transparent":w[1];p[v].end="undefined"==typeof w[2]?"transparent":w[2];n[v]=true}else{q[v]["background-image"]=B}}}else{q[v][C]=B}}}});if("undefined"!=typeof r){f(r).removeAttr("style");if(n.parent){f(r).ctcgrad(p.parent.origin,[p.parent.start,p.parent.end])}f(r).css(q.parent);if(!(r.attr("id").match(/parent/))){if(n.child){f(r).ctcgrad(p.child.origin,[p.child.start,p.child.end])}f(r).css(q.child)}}return m},b=function(o){var n,p,m;f(o).each(function(){switch(this.obj){case"imports":ctcAjax.imports=this.data;break;case"rule_val":ctcAjax.rule_val[this.key]=this.data;currRuleId=this.key;break;case"val_qry":ctcAjax.val_qry[this.key]=this.data;break;case"rule":ctcAjax.rule=this.data;break;case"sel_ndx":if(a(this.key)){ctcAjax.sel_ndx=this.data}else{if("qsid"==this.key){ctcAjax.sel_ndx[this.data.query][this.data.selector]=this.data.qsid}else{ctcAjax.sel_ndx[this.key]=this.data;n=this.key}}break;case"sel_val":ctcAjax.sel_val[this.key]=this.data;p=this.key;break}})},c=function(q,n){var p=n.match(/url\([" ]*(.+?)[" ]*\)/),o=("undefined"==typeof p?null:p[1]),m=ctcAjax.theme_uri+"/"+("parent"==q?ctcAjax.parnt:ctcAjax.child)+"/",r;if(!o){return false}else{if(o.match(/^(http:|\/)/)){r=n}else{r="url("+m+o+")"}}return r},a=function(n){if("undefined"==typeof n||false===n||null===n||""===n||0===n){return true}if(true===n||"string"===typeof n||"number"===typeof n){return false}if("object"===typeof n){for(var m in n){if(n.hasOwnProperty(m)){return false}}return true}return false},h=function(){var m=[];if(1===loading.sel_ndx){return m}if(0===loading.sel_ndx){loading.sel_ndx=1;ctc_query_css("sel_ndx",null,ctc_setup_query_menu);return m}if(false===a(ctcAjax.sel_ndx)){f.each(ctcAjax.sel_ndx,function(n,o){var p={label:n,value:n};m.push(p)})}return m},e=function(n){var m=[];if(1===loading.sel_ndx){return m}if(0===loading.sel_ndx){loading.sel_ndx=1;ctc_query_css("sel_ndx",n,ctc_setup_selector_menu);return m}if(false===a(ctcAjax.sel_ndx[n])){f.each(ctcAjax.sel_ndx[n],function(o,p){var q={label:o,value:p};m.push(q)})}return m},j=function(){var m=[];if(1===loading.rule){return m}if(0===loading.rule){loading.rule=1;ctc_query_css("rule",null,ctc_setup_rule_menu);return m}if(false===a(ctcAjax.rule)){f.each(ctcAjax.rule,function(n,o){var p={label:o,value:n};m.push(p)})}return m.sort(function(o,n){if(o.label>n.label){return 1}if(o.label<n.label){return -1}return 0})},g=function(o,s,n){var p="",r=(a(ctcAjax.sel_val[o])||a(ctcAjax.sel_val[o].value)||a(ctcAjax.sel_val[o].value[s])?"":ctcAjax.sel_val[o].value[s]),q=ctc_decode_value(s,("undefined"==typeof r?"":r.parnt)),m=ctc_decode_value(s,("undefined"==typeof r?"":r.child));if(false===a(ctcAjax.sel_val[o])){p+='<div class="ctc-'+(n?"selector":"input")+'-row clearfix">'+k;p+='<div class="ctc-input-cell">'+(n?ctcAjax.sel_val[o].selector+(a(q.orig)?"<br/>"+ctcAjax.child_only_txt:""):s)+"</div>"+k;if(!n){p+='<div class="ctc-parent-value ctc-input-cell" id="ctc_parent_'+s+"_"+o+'">'+(a(q.orig)?"[no value]":q.orig)+"</div>"+k}p+='<div class="ctc-input-cell">'+k;if(false===a(q.names)){f.each(q.names,function(t,u){u=(a(u)?"":u);p+='<div class="ctc-child-input-cell">'+k;var w="ctc_"+(n?"":"ovrd_")+"child_"+s+"_"+o+u,v;if(!(v=m.values.shift())){v=""}p+=(a(u)?"":ctcAjax.field_labels[u]+":<br/>")+'<input type="text" id="'+w+'" name="'+w+'" class="ctc-child-value'+((u+s).match(/color/)?" color-picker":"")+((u).match(/url/)?" ctc-input-wide":"")+'" value="'+v+'" />'+k;p+="</div>"+k})}p+="</div>"+k;p+=(n?'<div class="ctc-swatch ctc-specific" id="ctc_child_'+s+"_"+o+'_swatch">'+ctcAjax.swatch_txt+"</div>"+k+'<div class="ctc-child-input-cell ctc-button-cell" id="ctc_save_'+s+"_"+o+'_cell">'+k+'<input type="button" class="button ctc-save-input" id="ctc_save_'+s+"_"+o+'" name="ctc_save_'+s+"_"+o+'" value="Save" /></div>'+k:"");p+="</div><!-- end input row -->"+k}return p},d=function(m){if(1===loading.sel_val){return false}if(0==loading.sel_val){loading.sel_val=1;ctc_query_css("sel_val",m,d);return false}var n="";if(false===a(ctcAjax.sel_val[m]&&false===a(ctcAjax.sel_val[m].value))){f.each(ctcAjax.sel_val[m].value,function(p,o){n+=g(m,p,false)})}f("#ctc_sel_ovrd_rule_inputs").html(n).find(".color-picker").each(function(){l(this)});i("#ctc_child_all_0_swatch")};ctc_render_rule_value_inputs=function(n){if(1===loading.rule_val){return false}if(0==loading.rule_val){loading.rule_val=1;ctc_query_css("rule_val",n,ctc_render_rule_value_inputs);return false}var o=ctcAjax.rule[n],m='<div class="ctc-input-row clearfix" id="ctc_rule_row_'+o+'">'+k;if(false===a(ctcAjax.rule_val[n])){f.each(ctcAjax.rule_val[n],function(q,r){var p=ctc_decode_value(o,r);m+='<div class="ctc-parent-row clearfix" id="ctc_rule_row_'+o+"_"+q+'">'+k;m+='<div class="ctc-input-cell ctc-parent-value" id="ctc_parent_'+o+"_"+q+'">'+p.orig+"</div>"+k;m+='<div class="ctc-input-cell">'+k;m+='<div class="ctc-swatch ctc-specific" id="ctc_parent_'+o+"_"+q+'_swatch">'+ctcAjax.swatch_txt+"</div></div>"+k;m+='<div class="ctc-input-cell"><a href="#" class="ctc-selector-handle" id="ctc_selector_'+o+"_"+q+'">'+ctcAjax.selector_txt+"</a></div>"+k;m+='<div id="ctc_selector_'+o+"_"+q+'_container" class="ctc-selector-container clearfix">'+k;m+='<a href="#" id="ctc_selector_'+o+"_"+q+'_close" class="ctc-selector-handle" style="float:right">'+ctcAjax.close_txt+'</a><div id="ctc_status_val_qry_'+q+'"></div>'+k;m+='<div id="ctc_selector_'+o+"_"+q+'_rows"></div>'+k;m+="</div></div>"+k});m+="</div>"+k}f("#ctc_rule_value_inputs").html(m).find(".ctc-swatch").each(function(){i(this)})},ctc_render_selector_value_inputs=function(p){if(1==loading.val_qry){return false}var r,n,q=f("#ctc_rule_menu_selected").text(),m,o="";if(0===loading.val_qry){loading.val_qry=1;r={rule:q};ctc_query_css("val_qry",p,ctc_render_selector_value_inputs,r);return false}if(false===a(ctcAjax.val_qry[p])){f.each(ctcAjax.val_qry[p],function(t,s){page_rule=t;f.each(s,function(v,u){o+='<h4 class="ctc-query-heading">'+v+"</h4>"+k;if(false===a(u)){f.each(u,function(w,x){ctcAjax.sel_val[w]=x;o+=g(w,t,true)})}})})}m="#ctc_selector_"+q+"_"+p+"_rows";f(m).html(o).find(".color-picker").each(function(){l(this)});f(m).find(".ctc-swatch").each(function(){i(this)})},ctc_query_css=function(o,n,r,p){var m={ctc_query_obj:o,ctc_query_key:n},q="#ctc_status_"+o+("val_qry"==o?"_"+n:"");if("object"===typeof p){f.each(p,function(s,t){m["ctc_query_"+s]=t})}f(".ctc-status-icon").remove();f(q).append('<span class="ctc-status-icon spinner"></span>');f(".spinner").show();m.action="ctc_query";m._wpnonce=f("#_wpnonce").val();f.post(ctcAjax.ajaxurl,m,function(s){loading[o]=2;f(".ctc-status-icon").removeClass("spinner");if(a(s)){f(".ctc-status-icon").addClass("failure")}else{f(".ctc-status-icon").addClass("success");b(s);if("function"===typeof r){r(n)}return false}},"json").fail(function(){loading[o]=0;f(".ctc-status-icon").removeClass("spinner");f(".ctc-status-icon").addClass("failure")});return false},ctc_save=function(q){var p={},r,o,m,n;f(q).prop("disabled",true);f(".ctc-status-icon").remove();f(q).parent(".ctc-textarea-button-cell, .ctc-button-cell").append('<span class="ctc-status-icon spinner"></span>');f(".spinner").show();if((r=f("#ctc_new_selectors"))&&"ctc_save_new_selectors"==f(q).attr("id")){p.ctc_new_selectors=r.val();if(o=f("#ctc_sel_ovrd_query_selected")){p.ctc_sel_ovrd_query=o.text()}}else{if((m=f("#ctc_child_imports"))&&"ctc_save_imports"==f(q).attr("id")){p.ctc_child_imports=m.val()}else{p=i(q)}}p.action="ctc_update";p._wpnonce=f("#_wpnonce").val();f.post(ctcAjax.ajaxurl,p,function(s){f(q).prop("disabled",false);f(".ctc-status-icon").removeClass("spinner");if(a(s)){f(".ctc-status-icon").addClass("failure")}else{f(".ctc-status-icon").addClass("success");f("#ctc_new_selectors").val("");b(s);ctc_setup_menus()}return false},"json").fail(function(){f(q).prop("disabled",false);f(".ctc-status-icon").removeClass("spinner");f(".ctc-status-icon").addClass("failure")});return false},ctc_decode_value=function(o,m){m=("undefined"==typeof m?"":m);var n={orig:m};if(o.match(/^border(\-(top|right|bottom|left))?$/)){var p=m.split(/ +/);n.names=["_border_width","_border_style","_border_color"];n.values=[("undefined"==typeof p[0]?"":p[0]),("undefined"==typeof p[1]?"":p[1]),("undefined"==typeof p[2]?"":p[2])]}else{if(o.match(/^background\-image/)){n.names=["_background_url","_background_origin","_background_color1","_background_color2"];n.values=["","","",""];if(m.match(/:/)){var p=m.split(/:/);n.values[1]=("undefined"==typeof p[0]?"":p[0]);n.values[2]=("undefined"==typeof p[1]?"":p[1]);n.values[3]=("undefined"==typeof p[3]?"":p[3]);n.orig=[n.values[1],n.values[2],n.values[3]].join(" ")}else{n.values[0]=m}}else{n.names=[""];n.values=[m]}}return n},ctc_set_query=function(m){f("#ctc_sel_ovrd_query").val("");f("#ctc_sel_ovrd_query_selected").text(m);ctc_setup_selector_menu(m);f("#ctc_new_selector_row").show()},ctc_set_selector=function(n,m){f("#ctc_sel_ovrd_selector").val("");f("#ctc_sel_ovrd_selector_selected").text(m);f("#ctc_sel_ovrd_qsid").val(n);if(1!=loading.sel_val){loading.sel_val=0}d(n);f("#ctc_sel_ovrd_new_rule, #ctc_sel_ovrd_rule_header,#ctc_sel_ovrd_rule_inputs_container,#ctc_sel_ovrd_rule_inputs").show()},ctc_set_rule=function(n,m){f("#ctc_rule_menu").val("");f("#ctc_rule_menu_selected").text(m);if(1!=loading.rule_val){loading.rule_val=0}ctc_render_rule_value_inputs(n);f("#ctc_rule_value_inputs,#ctc_input_row_rule_header").show()},ctc_setup_query_menu=function(){ctc_queries=h();f("#ctc_sel_ovrd_query").autocomplete({source:ctc_queries,minLength:0,selectFirst:true,autoFocus:true,select:function(n,m){ctc_set_query(m.item.value);return false},focus:function(m){m.preventDefault()}})},ctc_setup_selector_menu=function(m){ctc_selectors=e(m);f("#ctc_sel_ovrd_selector").autocomplete({source:ctc_selectors,selectFirst:true,autoFocus:true,select:function(o,n){ctc_set_selector(n.item.value,n.item.label);return false},focus:function(n){n.preventDefault()}})},ctc_setup_rule_menu=function(){ctc_rules=j();f("#ctc_rule_menu").autocomplete({source:ctc_rules,selectFirst:true,autoFocus:true,select:function(n,m){ctc_set_rule(m.item.value,m.item.label);return false},focus:function(m){m.preventDefault()}})},ctc_setup_new_rule_menu=function(){f("#ctc_new_rule_menu").autocomplete({source:ctc_rules,selectFirst:true,autoFocus:true,select:function(o,n){var m=f("#ctc_sel_ovrd_qsid").val();f("#ctc_sel_ovrd_rule_inputs").append(g(m,n.item.label,false)).find(".color-picker").each(function(){l(this)});f("#ctc_new_rule_menu").val("");return false},focus:function(m){m.preventDefault()}})},ctc_setup_menus=function(){ctc_setup_query_menu();ctc_setup_selector_menu("");ctc_setup_rule_menu();ctc_setup_new_rule_menu()},ctc_theme_exists=function(m,n){var o=false;f.each(ctcAjax.themes,function(p,q){f.each(q,function(r,s){if(r==m&&("parnt"==p||"new"==n)){o=true;return false}});if(o){return false}});return o},ctc_set_notice=function(m){var n="";if(false===a(m)){f.each(m,function(o,p){n+='<div class="'+o+'"><ul>'+k;f(p).each(function(q,r){n+="<li>"+r.toString()+"</li>"+k});n+="</ul></div>"})}f("#ctc_error_notice").html(n)},ctc_validate=function(){var p=/[^\w\-]/,n=f("#ctc_child_template").val().replace(p).toLowerCase(),m=f("#ctc_theme_child").val().replace(p).toLowerCase(),o=f("input[name=ctc_child_type]:checked").val(),q=[];if("new"==o){m=n}if(ctc_theme_exists(m,o)){q.push(ctcAjax.theme_exists_txt.replace(/%s/,m))}if(""==m||m.match(/^[^a-z]/)){q.push(ctcAjax.inval_theme_txt)}if(""==f("#ctc_child_name").val()){q.push(ctcAjax.inval_name_txt)}if(q.length){ctc_set_notice({error:q});return false}return true},ctc_set_theme_menu=function(){var m=f("#ctc_theme_child").val();if(false===a(ctcAjax.themes.child[m])){f("#ctc_child_name").val(ctcAjax.themes.child[m].Name);f("#ctc_child_author").val(ctcAjax.themes.child[m].Author);f("#ctc_child_version").val(ctcAjax.themes.child[m].Version)}},fade_update_notice=function(){f(".updated").fadeOut("slow",function(){f(".updated").remove()})},loading={rule:2,sel_ndx:2,val_qry:0,rule_val:0,sel_val:0},ctc_selectors=[],ctc_queries=[],ctc_rules=[];f(".color-picker").each(function(){l(this)});f(".ctc-option-panel-container").on("focus",".color-picker",function(){ctc_set_notice("");f(this).iris("toggle");f(".iris-picker").css({position:"absolute","z-index":10})});f(".ctc-option-panel-container").on("focus","input",function(){ctc_set_notice("");f(".color-picker").not(this).iris("hide")});f(".ctc-option-panel-container").on("change",".ctc-child-value",function(){i(this)});f(".ctc-option-panel-container").on("click",".ctc-selector-handle",function(n){n.preventDefault();ctc_set_notice("");var o=f(this).attr("id").replace("_close",""),m=o.replace(/\D+/g,"");if(f("#"+o+"_container").is(":hidden")){if(1!=loading.val_qry){loading.val_qry=0}ctc_render_selector_value_inputs(m)}f("#"+o+"_container").fadeToggle("fast");f(".ctc-selector-container").not("#"+o+"_container").fadeOut("fast")});f(".nav-tab").on("click",function(n){n.preventDefault();ctc_set_notice("");var o="#"+f(this).attr("id"),m=o+"_panel";f(".nav-tab").removeClass("nav-tab-active");f(".ctc-option-panel").removeClass("ctc-option-panel-active");f(".ctc-selector-container").hide();f(o).addClass("nav-tab-active");f(".ctc-option-panel-container").scrollTop(0);f(m).addClass("ctc-option-panel-active")});f("#view_child_options,#view_parnt_options").on("click",function(p){ctc_set_notice("");var m=new Date().getTime(),o=f(this).attr("id").match(/(child|parnt)/)[1],n=ctcAjax.theme_uri+"/"+ctcAjax[o]+"/style.css?"+m;f.get(n,function(q){f("#view_"+o+"_options_panel").text(q)}).fail(function(){f("#view_"+o+"_options_panel").text(ctcAjax.css_fail_txt)})});f("#ctc_load_form").on("submit",function(){return(ctc_validate()&&confirm(ctcAjax.load_txt))});f(document).on("click",".ctc-save-input",function(m){ctc_save(this)});ctc_setup_menus();f("input[type=submit],input[type=button]").prop("disabled",false);setTimeout(fade_update_notice,6000)});
js/ctcgrad.js ADDED
@@ -0,0 +1,203 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * CTC Gradient Functions
3
+ * Adapted from Iris
4
+ * Copyright (c) 2012–2013 Automattic.
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/ctcgrad.min.js ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ /*!
2
+ * CTC Gradient Functions
3
+ * Adapted from Iris
4
+ * Copyright (c) 2012–2013 Automattic.
5
+ * Licensed under the GPLv2 license.
6
+ */
7
+ (function(i,f){var d,q,b,a,o,e,l,c,h;l=navigator.userAgent.toLowerCase();c=navigator.appName==="Microsoft Internet Explorer";h=c?parseFloat(l.match(/msie ([0-9]{1,}[\.0-9]{0,})/)[1]):0;q=(c&&h<10);a=["-moz-","-webkit-","-o-","-ms-"];p();if(q&&h<=7){i.fn.ctcgrad=i.noop;i.support.ctcgrad=false;return}i.support.ctcgrad=true;function p(){var r,s;if(q){b="filter"}else{r=i('<div id="ctcgrad-gradtest" />');s="linear-gradient(top,#fff,#000)";i.each(a,function(t,u){r.css("backgroundImage",u+s);if(r.css("backgroundImage").match("gradient")){b=t;return false}});if(b===false){r.css("background","-webkit-gradient(linear,0% 0%,0% 100%,from(#fff),to(#000))");if(r.css("backgroundImage").match("gradient")){b="webkit"}}r.remove()}}function n(r,s){r=(r.match(/(\d+deg|top|left|bottom|right)( (top|left|bottom|right))?/)?r:"top");s=i.isArray(s)?s:Array.prototype.slice.call(arguments,1);if(b==="webkit"){return m(r,s)}else{return a[b]+"linear-gradient("+r+", "+s.join(", ")+")"}}function g(x,A){var w,C,u,r,v,B,z,y,t,s;x=(x==="left")?"left":"top";A=i.isArray(A)?A:Array.prototype.slice.call(arguments,1);w=(x==="top")?0:1;C=i(this);u=A.length-1;r="filter";v=(w===1)?"left":"top";B=(w===1)?"right":"bottom";z=(w===1)?"height":"width";if(C.css("position")==="static"){C.css({position:"relative"})}A=j(A);i.each(A,function(D,F){var E,G;if(D===u){return false}E=A[D+1];if(F.stop===E.stop){return}G=100-parseFloat(E.stop)+"%";F.octoHex=new Color(F.color).toIEOctoHex();E.octoHex=new Color(E.color).toIEOctoHex();s="progid:DXImageTransform.Microsoft.Gradient(GradientType="+w+", StartColorStr='"+F.octoHex+"', EndColorStr='"+E.octoHex+"')"});return s}function m(r,s){var t=[];r=(r==="top")?"0% 0%,0% 100%,":"0% 100%,100% 100%,";s=j(s);i.each(s,function(u,v){t.push("color-stop("+(parseFloat(v.stop)/100)+", "+v.color+")")});return"-webkit-gradient(linear,"+r+t.join(",")+")"}function j(t){var s=[],u=[],r=[],v=t.length-1;i.each(t,function(y,A){var w=A,z=false,x=A.match(/1?[0-9]{1,2}%$/);if(x){w=A.replace(/\s?1?[0-9]{1,2}%$/,"");z=x.shift()}s.push(w);u.push(z)});if(u[0]===false){u[0]="0%"}if(u[v]===false){u[v]="100%"}u=k(u);i.each(u,function(w){r[w]={color:s[w],stop:u[w]}});return r}function k(z){var u=0,y=z.length-1,t=0,w=false,r,x,s,v;if(z.length<=2||i.inArray(false,z)<0){return z}while(t<z.length-1){if(!w&&z[t]===false){u=t-1;w=true}else{if(w&&z[t]!==false){y=t;t=z.length}}t++}x=y-u;v=parseInt(z[u].replace("%"),10);r=(parseFloat(z[y].replace("%"))-v)/x;t=u+1;s=1;while(t<y){z[t]=(v+(s*r))+"%";s++;t++}return k(z)}i.fn.ctcgrad=function(r){var s=arguments;if(q){i(this).css("filter",g.apply(this,s))}else{i(this).css("backgroundImage",n.apply(this,s))}}}(jQuery));
lang/chld_thm_cfg.pot ADDED
@@ -0,0 +1,495 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (C) 2013 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.1.0\n"
6
+ "Report-Msgid-Bugs-To: http://wordpress.org/tag/child-theme-configurator\n"
7
+ "POT-Creation-Date: 2013-12-08 03:44:46+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: 2013-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/class-ctc-ui.php:46
16
+ msgid "Parent/Child"
17
+ msgstr ""
18
+
19
+ #: includes/class-ctc-ui.php:49 includes/class-ctc-ui.php:365
20
+ msgid "Query/Selector"
21
+ msgstr ""
22
+
23
+ #: includes/class-ctc-ui.php:52 includes/class-ctc-ui.php:378
24
+ msgid "Rule/Value"
25
+ msgstr ""
26
+
27
+ #: includes/class-ctc-ui.php:55
28
+ msgid "@import"
29
+ msgstr ""
30
+
31
+ #: includes/class-ctc-ui.php:58
32
+ msgid "View Child CSS"
33
+ msgstr ""
34
+
35
+ #: includes/class-ctc-ui.php:61
36
+ msgid "View Parent CSS"
37
+ msgstr ""
38
+
39
+ #: includes/class-ctc-ui.php:70
40
+ msgid "Parent Theme"
41
+ msgstr ""
42
+
43
+ #: includes/class-ctc-ui.php:82
44
+ msgid "Child Theme"
45
+ msgstr ""
46
+
47
+ #: includes/class-ctc-ui.php:90
48
+ msgid "Create New Child Theme"
49
+ msgstr ""
50
+
51
+ #: includes/class-ctc-ui.php:99
52
+ msgid "Use Existing Child Theme"
53
+ msgstr ""
54
+
55
+ #: includes/class-ctc-ui.php:117
56
+ msgid "Child Theme Name"
57
+ msgstr ""
58
+
59
+ #: includes/class-ctc-ui.php:128
60
+ msgid "Author"
61
+ msgstr ""
62
+
63
+ #: includes/class-ctc-ui.php:139
64
+ msgid "Version"
65
+ msgstr ""
66
+
67
+ #: includes/class-ctc-ui.php:153
68
+ msgid "Generate Child Theme"
69
+ msgstr ""
70
+
71
+ #: includes/class-ctc-ui.php:164 includes/class-ctc-ui.php:233
72
+ msgid "Rule"
73
+ msgstr ""
74
+
75
+ #: includes/class-ctc-ui.php:177
76
+ msgid "Value"
77
+ msgstr ""
78
+
79
+ #: includes/class-ctc-ui.php:180 includes/class-ctc-ui.php:218
80
+ #: includes/class-ctc.php:94
81
+ msgid "Sample"
82
+ msgstr ""
83
+
84
+ #: includes/class-ctc-ui.php:183 includes/class-ctc.php:95
85
+ msgid "Selectors"
86
+ msgstr ""
87
+
88
+ #: includes/class-ctc-ui.php:194
89
+ msgid "Query"
90
+ msgstr ""
91
+
92
+ #: includes/class-ctc-ui.php:205
93
+ msgid "Selector"
94
+ msgstr ""
95
+
96
+ #: includes/class-ctc-ui.php:236
97
+ msgid "Parent Value"
98
+ msgstr ""
99
+
100
+ #: includes/class-ctc-ui.php:239
101
+ msgid "Child Value"
102
+ msgstr ""
103
+
104
+ #: includes/class-ctc-ui.php:245
105
+ msgid "New Rule"
106
+ msgstr ""
107
+
108
+ #: includes/class-ctc-ui.php:256
109
+ msgid "New Selector(s)"
110
+ msgstr ""
111
+
112
+ #: includes/class-ctc-ui.php:275
113
+ msgid "@import Statements"
114
+ msgstr ""
115
+
116
+ #: includes/class-ctc-ui.php:331
117
+ msgid "Child Theme <strong>%s</strong> has been generated successfully."
118
+ msgstr ""
119
+
120
+ #: includes/class-ctc-ui.php:348
121
+ msgid "Start Here"
122
+ msgstr ""
123
+
124
+ #: includes/class-ctc-ui.php:349
125
+ msgid ""
126
+ "\n"
127
+ "<p>The first step is to create a child theme and import your parent theme "
128
+ "styles into the configurator.</p>\n"
129
+ "<ol><li>Select an existing parent theme from the menu.</li>\n"
130
+ "<li>Select \"New\" or \"Existing\" child theme.\n"
131
+ "<ul><li>If creating a new theme, enter a \"slug\" (lower case, no spaces). "
132
+ "This is used to name the theme directory and identify the theme to WordPress."
133
+ "</li>\n"
134
+ "<li>If using an existing theme, select a child theme from the menu.</li></"
135
+ "ul></li>\n"
136
+ "<li>Enter a Name for the child theme.</li>\n"
137
+ "<li>Enter an author for the child theme.</li>\n"
138
+ "<li>Enter the child theme version number.</li>\n"
139
+ "<li>Click \"Generate Child Theme.\" If you are loading an existing child "
140
+ "theme, The Child Theme Configurator will create a backup of your existing "
141
+ "stylesheet in the theme directory.</li></ol>\n"
142
+ "\t\t\t\t "
143
+ msgstr ""
144
+
145
+ #: includes/class-ctc-ui.php:366
146
+ msgid ""
147
+ "\n"
148
+ "<p>There are two ways to identify and override parent styles. The Child "
149
+ "Theme Configurator lets you search styles by <strong>selector</strong> and "
150
+ "by <strong>rule</strong>. If you wish to change a specific selector (e.g., "
151
+ "h1), use the \"Query/Selector\" tab. If you have a specific value you wish "
152
+ "to change site-wide (e.g., the color of the type), use the \"Rule/Value\" "
153
+ "tab.</p>\n"
154
+ "<p>The Query/Selector tab lets you find specific selectors and edit them. "
155
+ "First, find the query that contains the selector you wish to edit by typing "
156
+ "in the <strong>Query</strong> autoselect box. Select by clicking with the "
157
+ "mouse or by pressing the \"Enter\" or \"Tab\" keys. Selectors are in the "
158
+ "<strong>base</strong> query by default.</p>\n"
159
+ "<p>Next, find the selector by typing in the <strong>Selector</strong> "
160
+ "autoselect box. Select by clicking with the mouse or by pressing the \"Enter"
161
+ "\" or \"Tab\" keys.</p>\n"
162
+ "<p>This will load all of the rules for that selector with the Parent values "
163
+ "on the left and the Child values inputs on the right. Any existing child "
164
+ "values will be automatically populated. There is also a Sample preview that "
165
+ "displays the combination of Parent and Child overrides. Note that the "
166
+ "<strong>border</strong> and <strong>background-image</strong> get special "
167
+ "treatment.</p>\n"
168
+ "<p>Click \"Save\" to update the child stylesheet and save your changes to "
169
+ "the WordPress admin.</p>\n"
170
+ "\t\t\t\t "
171
+ msgstr ""
172
+
173
+ #: includes/class-ctc-ui.php:379
174
+ msgid ""
175
+ "\n"
176
+ "<p>There are two ways to identify and override parent styles. The Child "
177
+ "Theme Configurator lets you search styles by <strong>selector</strong> and "
178
+ "by <strong>rule</strong>. If you wish to change a specific selector (e.g., "
179
+ "h1), use the \"Query/Selector\" tab. If you have a specific value you wish "
180
+ "to change site-wide (e.g., the color of the type), use the \"Rule/Value\" "
181
+ "tab.</p>\n"
182
+ "<p>The Rule/Value tab lets you find specific values for a given rule and "
183
+ "then edit that value for individual selectors that use that rule/value "
184
+ "combination. First, find the rule you wish to override by typing in the "
185
+ "<strong>Rule</strong> autoselect box. Select by clicking with the mouse or "
186
+ "by pressing the \"Enter\" or \"Tab\" keys.</p>\n"
187
+ "<p>This will load all of the unique values that exist for that rule in the "
188
+ "parent stylesheet with a Sample preview for that value. If there are values "
189
+ "that exist in the child stylesheet that do not exist in the parent "
190
+ "stylesheet, they will be displayed as well.</p>\n"
191
+ "<p>For each unique value, click the \"Selectors\" link to view a list of "
192
+ "selectors that use that rule/value combination, grouped by query with a "
193
+ "Sample preview of the value and inputs for the child value. Any existing "
194
+ "child values will be automatically populated.</p>\n"
195
+ "<p>Click \"Save\" to update the child stylesheet and save your changes to "
196
+ "the WordPress admin.</p>\n"
197
+ "\t\t\t\t "
198
+ msgstr ""
199
+
200
+ #: includes/class-ctc-ui.php:391
201
+ msgid "Add New Styles"
202
+ msgstr ""
203
+
204
+ #: includes/class-ctc-ui.php:392
205
+ msgid ""
206
+ "\n"
207
+ "<p>If you wish to add additional rules to a given selector, first load the "
208
+ "selector using the Query/Selector tab. Then find the rule you wish to "
209
+ "override by typing in the <strong>New Rule</strong> autoselect box. Select "
210
+ "by clicking with the mouse or by pressing the \"Enter\" or \"Tab\" keys. "
211
+ "This will add a new input row to the selector inputs.</p>\n"
212
+ "<p>If you wish to add completely new selectors, or even new @media queries, "
213
+ "you can enter free-form CSS in the \"New Selector\" textarea. Be aware that "
214
+ "your syntax must be correct (i.e., balanced curly braces, etc.) for the "
215
+ "parser to load the new styles. You will know it is invalid because a red \"X"
216
+ "\" will appear next to the save button.</p>\n"
217
+ "<p>If you prefer to use shorthand syntax for rules and values instead of the "
218
+ "inputs provided by the Child Theme Configurator, you can enter them here as "
219
+ "well. The parser will convert your input into normalized CSS code "
220
+ "automatically.</p>\n"
221
+ "\t\t\t\t "
222
+ msgstr ""
223
+
224
+ #: includes/class-ctc-ui.php:402
225
+ msgid "@imports"
226
+ msgstr ""
227
+
228
+ #: includes/class-ctc-ui.php:403
229
+ msgid ""
230
+ "\n"
231
+ "<p>You can add additional stylesheets and web fonts by typing @import rules "
232
+ "into the textarea on the @import tab. <strong>Important: The Child Theme "
233
+ "Configurator adds the @import rule that loads the Parent Theme's stylesheet "
234
+ "automatically. Do not need to add it here.</strong></p>\n"
235
+ "<p>Below is an example that loads a local custom stylesheet (you would have "
236
+ "to add the \"fonts\" directory and stylesheet) as well as the web font "
237
+ "\"Open Sans\" from Google Web Fonts:</p>\n"
238
+ "<blockquote><pre><code>\n"
239
+ "@import url(fonts/stylesheet.css);\n"
240
+ "@import url(http://fonts.googleapis.com/css?family=Open"
241
+ "+Sans:400,400italic,700,700italic);\n"
242
+ "</code></pre></blockquote>\n"
243
+ "\t\t\t\t "
244
+ msgstr ""
245
+
246
+ #: includes/class-ctc-ui.php:416
247
+ msgid "Preview and Activate"
248
+ msgstr ""
249
+
250
+ #: includes/class-ctc-ui.php:417
251
+ msgid ""
252
+ "\n"
253
+ "<p>Click the View Child or Parent CSS tab to reference the stylesheet code. "
254
+ "To preview the stylesheet as a WordPress theme follow these steps:</p>\n"
255
+ "<ol><li>Navigate to Appearance > Themes in the WordPress Admin. You will now "
256
+ "see the new Child Theme as one of the installed Themes.</li>\n"
257
+ "<li>Click \"Live Preview\" below the new Child Theme to see it in action.</"
258
+ "li>\n"
259
+ "<li>When you are ready to take the Child Theme live, click \"Activate.\"</"
260
+ "li></ol>\n"
261
+ "\t\t\t\t "
262
+ msgstr ""
263
+
264
+ #: includes/class-ctc-ui.php:428
265
+ msgid "FAQs"
266
+ msgstr ""
267
+
268
+ #: includes/class-ctc-ui.php:429
269
+ msgid ""
270
+ "\n"
271
+ "<h5 id=\"specific_color\">How do I change a specific color/font style/"
272
+ "background?</h5>\n"
273
+ "<p>You can override a specific value globally using the Rule/Value tab. See "
274
+ "Rule/Value, above.</p>\n"
275
+ "<h5 id=\"add_styles\">How do I add styles that aren't in the Parent Theme?</"
276
+ "h5>\n"
277
+ "<p>You can add queries and selectors using the \"New Selector(s)\" textarea "
278
+ "on the Query/Selector tab. See Query/Selector, above.</p>\n"
279
+ "<h5 id=\"add_styles\">How do I remove a style from the Parent Theme?</h5>\n"
280
+ "<p>You shouldn't really \"remove\" a style from the Parent. You can, "
281
+ "however, set the rule to \"inherit,\" \"none,\" or zero (depending on the "
282
+ "rule). This will negate the Parent value. Some experimentation may be "
283
+ "necessary.</p>\n"
284
+ "<h5 id=\"remove_styles\">How do I remove a style from the Child Theme?</h5>\n"
285
+ "<p>Delete the value from the input for the rule you wish to remove. The "
286
+ "Child Theme Configurator only adds overrides for rules that contain values.</"
287
+ "p>\n"
288
+ "<h5 id=\"gradients\">How do I create cross-browser gradients?</h5>\n"
289
+ "<p>The Child Theme Configurator automatically generates the vendor prefixes "
290
+ "and filters to display gradients across most browsers. It uses a normalized "
291
+ "syntax and only supports two colors without intermediate stops. The inputs "
292
+ "consist of origin (e.g., top, left, 135deg, etc.), start color and end "
293
+ "color. The browser-specific syntax is generated automatically when you save "
294
+ "these values. <strong>Note:</strong> For Internet Explorer, a filter rule "
295
+ "approximates the gradient but can only be horizontal (origin top) or "
296
+ "vertical (origin left). The legacy webkit-gradient syntax is not supported.</"
297
+ "p>\n"
298
+ "<h5 id=\"responsive\">How do I make my Theme responsive?</h5>\n"
299
+ "<p>This topic is beyond the scope of this document. The short answer is to "
300
+ "use a responsive Parent Theme. Some common characteristics of responsive "
301
+ "design are:\n"
302
+ "<ul><li>Avoiding fixed width and height values. Using max- and min-height "
303
+ "values and percentages are ways to make your designs respond to the viewer's "
304
+ "browser size.</li>\n"
305
+ "<li>Combining floats and clears with inline and relative positions allow the "
306
+ "elements to adjust gracefully to their container's width.</li>\n"
307
+ "<li>Showing and hiding content with Javascript.</li></ul>\n"
308
+ "<h5 id=\"web_fonts\">How do I add Web Fonts?</h5>\n"
309
+ "<p>The easiest method is to paste the @import code provided by Google, Font "
310
+ "Squirrel or any other Web Font site into the @import tab. The fonts will "
311
+ "then be available to use as a value of the <strong>font-family</strong> "
312
+ "rule. Be sure you understand the license for any embedded fonts.</p>\n"
313
+ "<p>You can also create a secondary stylesheet that contains @font-face rules "
314
+ "and import it using the @import tab. <strong>Note:</strong> Currently the "
315
+ "Child Theme Configurator does not generate previews of imported web fonts, "
316
+ "but will in a later release.</p>\n"
317
+ "<h5 id=\"functions_file\">Where is the functions.php file?</h5>\n"
318
+ "<p>You can add your own functions.php file, and any other files and "
319
+ "directories you need for your Child Theme. The Child Theme Configurator "
320
+ "helps you identify and override the Parent stylesheet without touching the "
321
+ "other files.</p>\n"
322
+ " "
323
+ msgstr ""
324
+
325
+ #: includes/class-ctc-ui.php:456
326
+ msgid "Glossary"
327
+ msgstr ""
328
+
329
+ #: includes/class-ctc-ui.php:457
330
+ msgid ""
331
+ "\n"
332
+ "<h3 id=\"terms\">Glossary</h3>\n"
333
+ "<ul><li id=\"parent_theme\"><strong>Parent Theme</strong> The WordPress "
334
+ "Theme you wish to edit. WordPress first loads the Child Theme, then loads "
335
+ "the Parent Theme. If a style exists in the Child Theme, it overrides the "
336
+ "Parent Theme.</li>\n"
337
+ " <li id=\"child_theme\"><strong>Child Theme</strong> New Theme based on "
338
+ "Parent Theme. You can create any number of Child Themes from a single Parent "
339
+ "Theme.</li>\n"
340
+ " <li id=\"class\"><strong>Class</strong> A term used to organize objects. "
341
+ "For example, a &lt;div&gt; might be assigned the \"blue-text\" class. The "
342
+ "stylesheet might then assign the \"color: blue;\" rule to members of the "
343
+ "\"blue-text\" class. Thus, the &lt;div&gt; would display text as blue in the "
344
+ "browser.</li>\n"
345
+ " <li id=\"selector\"><strong>Selector</strong> One or more html elements, "
346
+ "classes, ids or other terms used to identify groups of objects.</li>\n"
347
+ " <li id=\"rule\"><strong>Rule</strong> One of many standardized attributes "
348
+ "used to tell the browser how to display objects matching a given selector. "
349
+ "Examples are <strong>color</strong>, <strong>background-image</strong> and "
350
+ "<strong>font-size</strong>.</li>\n"
351
+ "<li id=\"at-rule\"><strong>At-rule</strong> CSS browser instruction to "
352
+ "extend default functionality. The Child Theme Configurator supports two At-"
353
+ "rules:\n"
354
+ "<ul> <li id=\"import\"><strong>@import</strong> Instructs the browser to "
355
+ "load additional CSS information from an external source.</li>\n"
356
+ " <li id=\"query\"><strong>@media (Media Query)</strong> Identifies blocks of "
357
+ "styles that are used only when certain browser characteristics are true. "
358
+ "Examples are max-width, screen and print.</li>\n"
359
+ "</ul></li>\n"
360
+ " <li id=\"override\"><strong>Override</strong> When a selector exists in "
361
+ "both the Child Theme and the Parent Theme, the Child Theme takes priority "
362
+ "over the Parent theme. This is where the Child Theme Configurator stands "
363
+ "out: it helps you create <strong>exact overrides</strong> of selectors from "
364
+ "the Parent Theme, eliminating hours of trial and error.</li>\n"
365
+ " </ul> \n"
366
+ "\t\t\t\t "
367
+ msgstr ""
368
+
369
+ #: includes/class-ctc-ui.php:478
370
+ msgid "Contact us"
371
+ msgstr ""
372
+
373
+ #: includes/class-ctc-ui.php:479
374
+ msgid "Plugin Website"
375
+ msgstr ""
376
+
377
+ #: includes/class-ctc-ui.php:480
378
+ msgid "Donate"
379
+ msgstr ""
380
+
381
+ #: includes/class-ctc-ui.php:481
382
+ msgid "Give Us 5 Stars"
383
+ msgstr ""
384
+
385
+ #: includes/class-ctc-ui.php:482
386
+ msgid "WordPress Codex"
387
+ msgstr ""
388
+
389
+ #: includes/class-ctc-ui.php:483
390
+ msgid "WordPress Answers"
391
+ msgstr ""
392
+
393
+ #. #-#-#-#-# child-theme-configurator.pot (Child Theme Configurator 1.1.0) #-#-#-#-#
394
+ #. Plugin Name of the plugin/theme
395
+ #: includes/class-ctc.php:43
396
+ msgid "Child Theme Configurator"
397
+ msgstr ""
398
+
399
+ #: includes/class-ctc.php:44
400
+ msgid "Child Themes"
401
+ msgstr ""
402
+
403
+ #: includes/class-ctc.php:84
404
+ msgid "URL/None"
405
+ msgstr ""
406
+
407
+ #: includes/class-ctc.php:85
408
+ msgid "Origin"
409
+ msgstr ""
410
+
411
+ #: includes/class-ctc.php:86
412
+ msgid "Color 1"
413
+ msgstr ""
414
+
415
+ #: includes/class-ctc.php:87
416
+ msgid "Color 2"
417
+ msgstr ""
418
+
419
+ #: includes/class-ctc.php:88
420
+ msgid "Width"
421
+ msgstr ""
422
+
423
+ #: includes/class-ctc.php:89
424
+ msgid "Style"
425
+ msgstr ""
426
+
427
+ #: includes/class-ctc.php:90
428
+ msgid "Color"
429
+ msgstr ""
430
+
431
+ #: includes/class-ctc.php:92
432
+ msgid "Are you sure? This will replace your current settings."
433
+ msgstr ""
434
+
435
+ #: includes/class-ctc.php:96
436
+ msgid "Close"
437
+ msgstr ""
438
+
439
+ #: includes/class-ctc.php:97
440
+ msgid "The stylesheet cannot be displayed."
441
+ msgstr ""
442
+
443
+ #: includes/class-ctc.php:98
444
+ msgid "(Child Only)"
445
+ msgstr ""
446
+
447
+ #: includes/class-ctc.php:99
448
+ msgid "Please enter a valid Child Theme"
449
+ msgstr ""
450
+
451
+ #: includes/class-ctc.php:100 includes/class-ctc.php:218
452
+ msgid "Please enter a valid Child Theme name"
453
+ msgstr ""
454
+
455
+ #: includes/class-ctc.php:101
456
+ msgid "<strong>%s</strong> exists. Please enter a different Child Theme"
457
+ msgstr ""
458
+
459
+ #: includes/class-ctc.php:203
460
+ msgid "%s does not exist. Please select a valid Parent Theme"
461
+ msgstr ""
462
+
463
+ #: includes/class-ctc.php:206
464
+ msgid "Please select a valid Parent Theme"
465
+ msgstr ""
466
+
467
+ #: includes/class-ctc.php:211
468
+ msgid ""
469
+ "<strong>%s</strong> exists. Please enter a different Child Theme template "
470
+ "name"
471
+ msgstr ""
472
+
473
+ #: includes/class-ctc.php:215
474
+ msgid "Please enter a valid Child Theme template name"
475
+ msgstr ""
476
+
477
+ #: includes/class-ctc.php:221
478
+ msgid "You do not have permission to configure child themes."
479
+ msgstr ""
480
+
481
+ #. Plugin URI of the plugin/theme
482
+ msgid "http://www.lilaeamedia.com/plugins/child-theme-configurator/"
483
+ msgstr ""
484
+
485
+ #. Description of the plugin/theme
486
+ msgid "Create Child Theme from any Theme or Stylesheet"
487
+ msgstr ""
488
+
489
+ #. Author of the plugin/theme
490
+ msgid "Lilaea Media"
491
+ msgstr ""
492
+
493
+ #. Author URI of the plugin/theme
494
+ msgid "http://www.lilaeamedia.com/"
495
+ msgstr ""
readme.txt ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ === Child Theme Configurator ===
2
+ Contributors: lilaeamedia
3
+ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=8QE5YJ8WE96AJ
4
+ Tags: child theme, custom theme, CSS, responsive design, CSS editor, theme generator
5
+ Requires at least: 3.5
6
+ Tested up to: 3.8
7
+ Stable tag: 1.1.0
8
+ License: GPLv2 or later
9
+ License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
+
11
+ Create a Child Theme from any installed Theme. Each CSS selector, rule and value can then be searched, previewed and modified.
12
+
13
+ == Description ==
14
+
15
+ Created by Lilaea Media, the team that brought you IntelliWidget, the Child Theme Configurator provides a new approach to WordPress stylesheets. The Child Theme Configurator lets you identify and override only the Parent Theme style attributes you want to change. It gives you unlimited control over your WordPress look and feel while leaving your Parent Theme untouched.
16
+
17
+ The Child Theme Configurator attacks this challenge from a new angle. First, it parses and indexes a Theme's stylesheet so that every media query, selector, rule and value are at your fingertips. Second, it shows you how each change you make will look before you commit it to the Child Theme.Finally, it saves your work so that you can fine-tune your Child Theme without the risk of losing your edits.
18
+ You can create any number of Child Themes from any existing Parent Theme. The Child Theme Configurator lets you choose from your installed themes (even existing Child Themes) and save the results in your Themes directory.
19
+
20
+ When you are ready, just activate the Child Theme and your WordPress site takes on the new look and feel automatically.
21
+
22
+ Why create Child Themes using the Child Theme Configurator?
23
+
24
+ * Apply changes in a Child Theme without touching the Parent Theme
25
+ * Identify and override exact selectors from the Parent Theme
26
+ * Change colors, backgrounds, font styles globally without changing other rules.
27
+ * Tweak individual style selectors
28
+ * Automatically create and preview CSS3 gradients
29
+ * Automatically generate cross-browser and vendor-prefixed rules
30
+ * View style changes before commiting to them
31
+ * Add and modify individual @media queries
32
+ * Import web fonts and use them in place of Theme fonts
33
+ * Save hours of development time
34
+
35
+
36
+ == Installation ==
37
+
38
+ 1. Download the Child Theme Configurator plugin archive and unzip it.
39
+ 2. Upload the child-theme-configurator directory to your WordPress plugins directory (e.g., /path/to/wordpress/wp-content/plugins/)
40
+ 3. Activate the plugin through the 'Plugins' menu in WordPress
41
+
42
+ == Frequently Asked Questions ==
43
+
44
+ = Where is the functions.php file? =
45
+
46
+ You can add your own functions.php file, and any other files and directories you need for your Child Theme. The Child Theme Configurator helps you identify and override selectors in the Parent stylesheet without touching the other files.
47
+
48
+ = How Do I change a specific color/font style/background? =
49
+
50
+ You can override a specific value globally using the Rule/Value tab. See "Rule/Value," below.
51
+
52
+ = How Do I add styles that aren't in the Parent Theme? =
53
+
54
+ You can add queries and selectors using the "New Selector(s)" textarea on the Query/Selector tab. See "Query/Selector," below.
55
+
56
+ = How Do I remove a style from the Parent Theme? =
57
+
58
+ You can't really "remove" a style from the Parent. You can, however, set the rule to "inherit," "none," or zero (depending on the rule). This will negate the Parent value. Some experimentation may be necessary.
59
+
60
+ = How Do I remove a style from the Child Theme? =
61
+
62
+ Delete the value from the input for the rule you wish to remove. The Child Theme Configurator only adds overrides for rules that contain values.
63
+
64
+ = How Do I create cross-browser gradients? =
65
+
66
+ The Child Theme Configurator uses a standardized syntax for gradients and only supports two-color gradients without intermediate stops. The inputs consist of origin (e.g., top, left, 135deg, etc.), start color and end color. The browser-specific syntax is generated automatically when you save these values. See Caveats, below, for more information.
67
+
68
+ = How Do I make my Theme responsive? =
69
+
70
+ This topic is beyond the scope of this document. The short answer is to use a responsive Parent Theme. Some common characteristics of responsive design are:
71
+
72
+ * Avoiding fixed width and height values. Using max- and min-height values and percentages are ways to make your designs respond to the viewer's browser size.
73
+ * Combining floats and clears with inline and relative positions allow the elements to adjust gracefully to their container's width.
74
+ * Showing and hiding content with Javascript.
75
+
76
+ = How Do I add Web Fonts? =
77
+
78
+ The easiest method is to paste the @import code provided by Google, Font Squirrel or any other Web Font site into the @import tab. The fonts will then be available to use as a value of the font-family rule. Be sure you understand the license for any embedded fonts.
79
+
80
+ You can also create a secondary stylesheet that contains @font-face rules and import it using the @import tab.
81
+
82
+ == Screenshots ==
83
+
84
+ 1. Example of the Parent/Child Panel.
85
+ 2. Example of the Query/Selector Panel.
86
+ 3. Example of the Rule/Value Panel.
87
+ 4. Example of the @imports Panel.
88
+ 5. Example of the Preview CSS Panel.
89
+
90
+ == Changelog ==
91
+
92
+ = 1.1.0 =
93
+ * Corrected parsing for certain backgrounds and gradients (e.g., supports hsla color syntax)
94
+ * Handle empty selectors
95
+ * Ajax load for menus and updates
96
+ * Clean up Parent/Child form UI and validation
97
+ * Streamlined UI overall
98
+
99
+ = 1.0.1 =
100
+ * Updates to Readme.txt
101
+
102
+ = 1.0.0 =
103
+ * Initial release.
104
+
105
+ == Upgrade Notice ==
106
+
107
+ = 1.0.0 =
108
+ * Initial release.
109
+
110
+ == Create Your Child Theme ==
111
+
112
+ The first step is to create a child theme and import your parent theme styles into the configurator.
113
+
114
+ 1. Select an existing parent theme from the menu.
115
+ 2. Select "New" or "Existing" child theme.
116
+ * If creating a new theme, enter a "slug" (lower case, no spaces). This is used to name the theme directory and identify the theme to WordPress.</li>
117
+ * If using an existing theme, select a child theme from the menu.
118
+ 3. Enter a Name for the child theme.
119
+ 4. Enter an author for the child theme.
120
+ 5. Enter the child theme version number.
121
+ 6. Click "Generate Child Theme." If you are loading an existing child theme, The Child Theme Configurator will create a backup of your existing stylesheet in the theme directory.
122
+
123
+ == Override Parent Styles ==
124
+
125
+ There are two ways to identify and override parent styles. The Child Theme Configurator lets you search styles by selector and by rule. 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 "Rule/Value" tab.
126
+
127
+ = Query/Selector =
128
+
129
+ 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 Query autoselect box. Select by clicking with the mouse or by pressing the "Enter" or "Tab" keys. Selectors are in the base query by default.
130
+ Next, find the selector by typing in the Selector autoselect box. Select by clicking with the mouse or by pressing the "Enter" or "Tab" keys.
131
+
132
+ This will load all of the rules 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 border and background-image get special treatment.
133
+
134
+ Click "Save" to update the child stylesheet and save your changes to the WordPress admin.
135
+
136
+ = Rule/Value =
137
+
138
+ The Rule/Value tab lets you find specific values for a given rule and then edit that value for individual selectors that use that rule/value combination. First, find the rule you wish to override by typing in the Rule autoselect box. Select by clicking with the mouse or by pressing the "Enter" or "Tab" keys.
139
+
140
+ This will load all of the unique values that exist for that rule 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.
141
+
142
+ For each unique value, click the "Selectors" link to view a list of selectors that use that rule/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.
143
+
144
+ Click "Save" to update the child stylesheet and save your changes to the WordPress admin.
145
+
146
+ == Add New Styles ==
147
+
148
+ If you wish to add additional rules to a given selector, first load the selector using the Query/Selector tab. Then find the rule you wish to override by typing in the New Rule 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.
149
+
150
+ If you wish to add completely new selectors, or even new @media queries, you can enter free-form CSS in the "New Selector" 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.
151
+
152
+ If you prefer to use shorthand syntax for rules 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.
153
+
154
+ == Add Imports ==
155
+
156
+ You can add additional stylesheets and web fonts by typing @import rules into the textarea on the @import tab. Important: The Child Theme Configurator adds the @import rule that loads the Parent Theme's stylesheet automatically. Do not need to add it here.
157
+
158
+ == Preview and Activate ==
159
+
160
+ Click the Preview CSS tab to see your new masterpiece as CSS code. To preview the stylesheet as a WordPress theme follow these steps:
161
+
162
+ 1. Navigate to Appearance > Themes in the WordPress Admin. You will now see the new Child Theme as one of the installed Themes.
163
+ 2. Click "Live Preview" below the new Child Theme to see it in action.
164
+ 3. When you are ready to take the Child Theme live, click "Activate."
165
+
166
+ == Caveats ==
167
+
168
+ * No web font preview. Look for live preview of imported fonts in a later release.
169
+ * No webkit-gradient. The Child Theme Configurator plugin does not support the legacy webkit gradient. If there is a demand, we will add it in a future release, but most Chrome and Safari users should have upgraded by now.
170
+ * Only two-color gradients. The Child Theme Configurator plugin is powerful, but we have simplified the gradient interface. You can use any gradient you want as long as it has two colors and no intermediate stops.
171
+ * No @font-face rules. The Child Theme Configurator plugin only supports @media and @import. If you need other @rules, put them in a separate stylesheet and import them into the Child Theme stylesheet.
172
+ * Menus may not include certain rules. The Child Theme Configurator plugin loads the rules that exist in the Parent stylesheet. If you find rules are missing from the menus, you can add them using a filter. Stay tuned for details.
173
+
174
+ == Documentation ==
175
+
176
+ Go to http://www.lilaeamedia.com/plugins/child-theme-configurator
screenshot-1.jpg ADDED
Binary file
screenshot-2.jpg ADDED
Binary file
screenshot-3.jpg ADDED
Binary file
screenshot-4.jpg ADDED
Binary file
screenshot-5.jpg ADDED
Binary file