Child Theme Configurator - Version 1.7.5

Version Description

  • Uses spectrum color picker to support transparency and named colors.
  • Refactored entire system to support fallback values for any property.
  • Fix path when duplicating child theme on first run
  • New Feature: "delete child values" button - easily revert styles in child theme stylesheet
Download this release

Release Info

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

Code changes from version 1.7.4.2 to 1.7.5

child-theme-configurator.php CHANGED
@@ -6,7 +6,7 @@ if ( !defined( 'ABSPATH' ) ) exit;
6
  Plugin Name: Child Theme Configurator
7
  Plugin URI: http://www.childthemeconfigurator.com
8
  Description: Create a child theme that follows WP best practice to enqueue stylesheets. Easy to use CSS editor lets you find, preview and customize any style.
9
- Version: 1.7.4.2
10
  Author: Lilaea Media
11
  Author URI: http://www.lilaeamedia.com
12
  Text Domain: chld_thm_cfg
@@ -22,7 +22,7 @@ if ( !defined( 'ABSPATH' ) ) exit;
22
  define( 'CHLD_THM_CFG_DOCS_URL', "http://www.childthemeconfigurator.com" );
23
  defined( 'CHLD_THM_CFG_OPTIONS' ) or
24
  define( 'CHLD_THM_CFG_OPTIONS', 'chld_thm_cfg_options' );
25
- define( 'CHLD_THM_CFG_VERSION', '1.7.4.2' );
26
  define( 'CHLD_THM_CFG_MIN_WP_VERSION', '3.7' );
27
  defined( 'CHLD_THM_CFG_BPSEL' ) or
28
  define( 'CHLD_THM_CFG_BPSEL', '2500' );
6
  Plugin Name: Child Theme Configurator
7
  Plugin URI: http://www.childthemeconfigurator.com
8
  Description: Create a child theme that follows WP best practice to enqueue stylesheets. Easy to use CSS editor lets you find, preview and customize any style.
9
+ Version: 1.7.5
10
  Author: Lilaea Media
11
  Author URI: http://www.lilaeamedia.com
12
  Text Domain: chld_thm_cfg
22
  define( 'CHLD_THM_CFG_DOCS_URL', "http://www.childthemeconfigurator.com" );
23
  defined( 'CHLD_THM_CFG_OPTIONS' ) or
24
  define( 'CHLD_THM_CFG_OPTIONS', 'chld_thm_cfg_options' );
25
+ define( 'CHLD_THM_CFG_VERSION', '1.7.5' );
26
  define( 'CHLD_THM_CFG_MIN_WP_VERSION', '3.7' );
27
  defined( 'CHLD_THM_CFG_BPSEL' ) or
28
  define( 'CHLD_THM_CFG_BPSEL', '2500' );
css/chld-thm-cfg.css CHANGED
@@ -134,7 +134,9 @@ a.ctc-recent-tab {
134
  margin: 0 2% 0 0;/*color:#7f7f7f;
135
  border: 1px solid #ddd;*/
136
  }
137
-
 
 
138
  .ctc-parent-row {
139
  clear: both;
140
  position: relative;
@@ -152,6 +154,9 @@ a.ctc-recent-tab {
152
  margin-right: 2%;
153
  word-wrap: break-word;
154
  }
 
 
 
155
  .ctc-input-cell-wide {
156
  display: block;
157
  float: left;
@@ -175,8 +180,8 @@ a.ctc-recent-tab {
175
  .ctc-save-input {
176
  }
177
 
178
- .ctc-button-cell, .ctc-input-cell.ctc-button-cell {
179
- /*width: 85px;*/
180
  }
181
 
182
  .ctc-textarea-button-cell {
@@ -198,6 +203,12 @@ a.ctc-recent-tab {
198
  display: none;
199
  outline: none;
200
  }
 
 
 
 
 
 
201
 
202
  .ctc-selector-container {
203
  clear: both;
@@ -580,4 +591,513 @@ h3.theme-name {
580
  #get_pro_panel img {
581
  max-width: 100%;
582
  height: auto;
583
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
  margin: 0 2% 0 0;/*color:#7f7f7f;
135
  border: 1px solid #ddd;*/
136
  }
137
+ .ctc-selector-inner-container .ctc-swatch.ctc-specific {
138
+ max-width:13%;
139
+ }
140
  .ctc-parent-row {
141
  clear: both;
142
  position: relative;
154
  margin-right: 2%;
155
  word-wrap: break-word;
156
  }
157
+ .ctc-selector-inner-container .ctc-input-cell {
158
+ width:35%;
159
+ }
160
  .ctc-input-cell-wide {
161
  display: block;
162
  float: left;
180
  .ctc-save-input {
181
  }
182
 
183
+ .ctc-selector-inner-container .ctc-button-cell, .ctc-selector-inner-container .ctc-input-cell.ctc-button-cell {
184
+ width: 8%;
185
  }
186
 
187
  .ctc-textarea-button-cell {
203
  display: none;
204
  outline: none;
205
  }
206
+ .ctc-delete-input {
207
+ font-size: 0.8em;
208
+ float:right;
209
+ color: darkred;
210
+ text-decoration:none;
211
+ }
212
 
213
  .ctc-selector-container {
214
  clear: both;
591
  #get_pro_panel img {
592
  max-width: 100%;
593
  height: auto;
594
+ }
595
+
596
+ /***
597
+ Spectrum Colorpicker v1.7.0
598
+ https://github.com/bgrins/spectrum
599
+ Author: Brian Grinstead
600
+ License: MIT
601
+ ***/
602
+
603
+ .sp-container {
604
+ position:absolute;
605
+ top:0;
606
+ left:0;
607
+ display:inline-block;
608
+ *display: inline;
609
+ *zoom: 1;
610
+ /* https://github.com/bgrins/spectrum/issues/40 */
611
+ z-index: 9999994;
612
+ overflow: hidden;
613
+ }
614
+ .sp-container.sp-flat {
615
+ position: relative;
616
+ }
617
+
618
+ /* Fix for * { box-sizing: border-box; } */
619
+ .sp-container,
620
+ .sp-container * {
621
+ -webkit-box-sizing: content-box;
622
+ -moz-box-sizing: content-box;
623
+ box-sizing: content-box;
624
+ }
625
+
626
+ /* http://ansciath.tumblr.com/post/7347495869/css-aspect-ratio */
627
+ .sp-top {
628
+ position:relative;
629
+ width: 100%;
630
+ display:inline-block;
631
+ }
632
+ .sp-top-inner {
633
+ position:absolute;
634
+ top:0;
635
+ left:0;
636
+ bottom:0;
637
+ right:0;
638
+ }
639
+ .sp-color {
640
+ position: absolute;
641
+ top:0;
642
+ left:0;
643
+ bottom:0;
644
+ right:20%;
645
+ }
646
+ .sp-hue {
647
+ position: absolute;
648
+ top:0;
649
+ right:0;
650
+ bottom:0;
651
+ left:84%;
652
+ height: 100%;
653
+ }
654
+
655
+ .sp-clear-enabled .sp-hue {
656
+ top:33px;
657
+ height: 77.5%;
658
+ }
659
+
660
+ .sp-fill {
661
+ padding-top: 80%;
662
+ }
663
+ .sp-sat, .sp-val {
664
+ position: absolute;
665
+ top:0;
666
+ left:0;
667
+ right:0;
668
+ bottom:0;
669
+ }
670
+
671
+ .sp-alpha-enabled .sp-top {
672
+ margin-bottom: 18px;
673
+ }
674
+ .sp-alpha-enabled .sp-alpha {
675
+ display: block;
676
+ }
677
+ .sp-alpha-handle {
678
+ position:absolute;
679
+ top:-4px;
680
+ bottom: -4px;
681
+ width: 6px;
682
+ left: 50%;
683
+ cursor: pointer;
684
+ border: 1px solid black;
685
+ background: white;
686
+ opacity: .8;
687
+ }
688
+ .sp-alpha {
689
+ display: none;
690
+ position: absolute;
691
+ bottom: -14px;
692
+ right: 0;
693
+ left: 0;
694
+ height: 8px;
695
+ }
696
+ .sp-alpha-inner {
697
+ border: solid 1px #333;
698
+ }
699
+
700
+ .sp-clear {
701
+ display: none;
702
+ }
703
+
704
+ .sp-clear.sp-clear-display {
705
+ background-position: center;
706
+ }
707
+
708
+ .sp-clear-enabled .sp-clear {
709
+ display: block;
710
+ position:absolute;
711
+ top:0px;
712
+ right:0;
713
+ bottom:0;
714
+ left:84%;
715
+ height: 28px;
716
+ }
717
+
718
+ /* Don't allow text selection */
719
+ .sp-container, .sp-replacer, .sp-preview, .sp-dragger, .sp-slider, .sp-alpha, .sp-clear, .sp-alpha-handle, .sp-container.sp-dragging .sp-input, .sp-container button {
720
+ -webkit-user-select:none;
721
+ -moz-user-select: -moz-none;
722
+ -o-user-select:none;
723
+ user-select: none;
724
+ }
725
+
726
+ .sp-container.sp-input-disabled .sp-input-container {
727
+ display: none;
728
+ }
729
+ .sp-container.sp-buttons-disabled .sp-button-container {
730
+ display: none;
731
+ }
732
+ .sp-container.sp-palette-buttons-disabled .sp-palette-button-container {
733
+ display: none;
734
+ }
735
+ .sp-palette-only .sp-picker-container {
736
+ display: none;
737
+ }
738
+ .sp-palette-disabled .sp-palette-container {
739
+ display: none;
740
+ }
741
+
742
+ .sp-initial-disabled .sp-initial {
743
+ display: none;
744
+ }
745
+
746
+
747
+ /* Gradients for hue, saturation and value instead of images. Not pretty... but it works */
748
+ .sp-sat {
749
+ background-image: -webkit-gradient(linear, 0 0, 100% 0, from(#FFF), to(rgba(204, 154, 129, 0)));
750
+ background-image: -webkit-linear-gradient(left, #FFF, rgba(204, 154, 129, 0));
751
+ background-image: -moz-linear-gradient(left, #fff, rgba(204, 154, 129, 0));
752
+ background-image: -o-linear-gradient(left, #fff, rgba(204, 154, 129, 0));
753
+ background-image: -ms-linear-gradient(left, #fff, rgba(204, 154, 129, 0));
754
+ background-image: linear-gradient(to right, #fff, rgba(204, 154, 129, 0));
755
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr=#FFFFFFFF, endColorstr=#00CC9A81)";
756
+ filter : progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr='#FFFFFFFF', endColorstr='#00CC9A81');
757
+ }
758
+ .sp-val {
759
+ background-image: -webkit-gradient(linear, 0 100%, 0 0, from(#000000), to(rgba(204, 154, 129, 0)));
760
+ background-image: -webkit-linear-gradient(bottom, #000000, rgba(204, 154, 129, 0));
761
+ background-image: -moz-linear-gradient(bottom, #000, rgba(204, 154, 129, 0));
762
+ background-image: -o-linear-gradient(bottom, #000, rgba(204, 154, 129, 0));
763
+ background-image: -ms-linear-gradient(bottom, #000, rgba(204, 154, 129, 0));
764
+ background-image: linear-gradient(to top, #000, rgba(204, 154, 129, 0));
765
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#00CC9A81, endColorstr=#FF000000)";
766
+ filter : progid:DXImageTransform.Microsoft.gradient(startColorstr='#00CC9A81', endColorstr='#FF000000');
767
+ }
768
+
769
+ .sp-hue {
770
+ background: -moz-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
771
+ background: -ms-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
772
+ background: -o-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
773
+ background: -webkit-gradient(linear, left top, left bottom, from(#ff0000), color-stop(0.17, #ffff00), color-stop(0.33, #00ff00), color-stop(0.5, #00ffff), color-stop(0.67, #0000ff), color-stop(0.83, #ff00ff), to(#ff0000));
774
+ background: -webkit-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
775
+ background: linear-gradient(to bottom, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
776
+ }
777
+
778
+ /* IE filters do not support multiple color stops.
779
+ Generate 6 divs, line them up, and do two color gradients for each.
780
+ Yes, really.
781
+ */
782
+ .sp-1 {
783
+ height:17%;
784
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0000', endColorstr='#ffff00');
785
+ }
786
+ .sp-2 {
787
+ height:16%;
788
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff00', endColorstr='#00ff00');
789
+ }
790
+ .sp-3 {
791
+ height:17%;
792
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ff00', endColorstr='#00ffff');
793
+ }
794
+ .sp-4 {
795
+ height:17%;
796
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ffff', endColorstr='#0000ff');
797
+ }
798
+ .sp-5 {
799
+ height:16%;
800
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0000ff', endColorstr='#ff00ff');
801
+ }
802
+ .sp-6 {
803
+ height:17%;
804
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff00ff', endColorstr='#ff0000');
805
+ }
806
+
807
+ .sp-hidden {
808
+ display: none !important;
809
+ }
810
+
811
+ /* Clearfix hack */
812
+ .sp-cf:before, .sp-cf:after { content: ""; display: table; }
813
+ .sp-cf:after { clear: both; }
814
+ .sp-cf { *zoom: 1; }
815
+
816
+ /* Mobile devices, make hue slider bigger so it is easier to slide */
817
+ @media (max-device-width: 480px) {
818
+ .sp-color { right: 40%; }
819
+ .sp-hue { left: 63%; }
820
+ .sp-fill { padding-top: 60%; }
821
+ }
822
+ .sp-dragger {
823
+ border-radius: 5px;
824
+ height: 5px;
825
+ width: 5px;
826
+ border: 1px solid #fff;
827
+ background: #000;
828
+ cursor: pointer;
829
+ position:absolute;
830
+ top:0;
831
+ left: 0;
832
+ }
833
+ .sp-slider {
834
+ position: absolute;
835
+ top:0;
836
+ cursor:pointer;
837
+ height: 3px;
838
+ left: -1px;
839
+ right: -1px;
840
+ border: 1px solid #000;
841
+ background: white;
842
+ opacity: .8;
843
+ }
844
+
845
+ /*
846
+ Theme authors:
847
+ Here are the basic themeable display options (colors, fonts, global widths).
848
+ See http://bgrins.github.io/spectrum/themes/ for instructions.
849
+ */
850
+
851
+ .sp-container {
852
+ border-radius: 0;
853
+ background-color: #ECECEC;
854
+ border: solid 1px #f0c49B;
855
+ padding: 0;
856
+ }
857
+ .sp-container, .sp-container button, .sp-container input, .sp-color, .sp-hue, .sp-clear {
858
+ font: normal 12px "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif;
859
+ -webkit-box-sizing: border-box;
860
+ -moz-box-sizing: border-box;
861
+ -ms-box-sizing: border-box;
862
+ box-sizing: border-box;
863
+ }
864
+ .sp-top {
865
+ margin-bottom: 3px;
866
+ }
867
+ .sp-color, .sp-hue, .sp-clear {
868
+ border: solid 1px #666;
869
+ }
870
+
871
+ /* Input */
872
+ .sp-input-container {
873
+ float:right;
874
+ width: 100px;
875
+ margin-bottom: 4px;
876
+ }
877
+ .sp-initial-disabled .sp-input-container {
878
+ width: 100%;
879
+ }
880
+ .sp-input {
881
+ font-size: 12px !important;
882
+ border: 1px inset;
883
+ padding: 4px 5px;
884
+ margin: 0;
885
+ width: 100%;
886
+ background:transparent;
887
+ border-radius: 3px;
888
+ color: #222;
889
+ }
890
+ .sp-input:focus {
891
+ border: 1px solid orange;
892
+ }
893
+ .sp-input.sp-validation-error {
894
+ border: 1px solid red;
895
+ background: #fdd;
896
+ }
897
+ .sp-picker-container , .sp-palette-container {
898
+ float:left;
899
+ position: relative;
900
+ padding: 10px;
901
+ padding-bottom: 300px;
902
+ margin-bottom: -290px;
903
+ }
904
+ .sp-picker-container {
905
+ width: 172px;
906
+ border-left: solid 1px #fff;
907
+ }
908
+
909
+ /* Palettes */
910
+ .sp-palette-container {
911
+ border-right: solid 1px #ccc;
912
+ }
913
+
914
+ .sp-palette-only .sp-palette-container {
915
+ border: 0;
916
+ }
917
+
918
+ .sp-palette .sp-thumb-el {
919
+ display: block;
920
+ position:relative;
921
+ float:left;
922
+ width: 24px;
923
+ height: 15px;
924
+ margin: 3px;
925
+ cursor: pointer;
926
+ border:solid 2px transparent;
927
+ }
928
+ .sp-palette .sp-thumb-el:hover, .sp-palette .sp-thumb-el.sp-thumb-active {
929
+ border-color: orange;
930
+ }
931
+ .sp-thumb-el {
932
+ position:relative;
933
+ }
934
+
935
+ /* Initial */
936
+ .sp-initial {
937
+ float: left;
938
+ border: solid 1px #333;
939
+ }
940
+ .sp-initial span {
941
+ width: 30px;
942
+ height: 25px;
943
+ border:none;
944
+ display:block;
945
+ float:left;
946
+ margin:0;
947
+ }
948
+
949
+ .sp-initial .sp-clear-display {
950
+ background-position: center;
951
+ }
952
+
953
+ /* Buttons */
954
+ .sp-palette-button-container,
955
+ .sp-button-container {
956
+ float: right;
957
+ }
958
+
959
+ /* Replacer (the little preview div that shows up instead of the <input>) */
960
+ .sp-replacer {
961
+ margin:0;
962
+ overflow:hidden;
963
+ cursor:pointer;
964
+ padding: 4px;
965
+ display:inline-block;
966
+ *zoom: 1;
967
+ *display: inline;
968
+ border: solid 1px #91765d;
969
+ background: #eee;
970
+ color: #333;
971
+ vertical-align: middle;
972
+ }
973
+ .sp-replacer:hover, .sp-replacer.sp-active {
974
+ border-color: #F0C49B;
975
+ color: #111;
976
+ }
977
+ .sp-replacer.sp-disabled {
978
+ cursor:default;
979
+ border-color: silver;
980
+ color: silver;
981
+ }
982
+ .sp-dd {
983
+ padding: 2px 0;
984
+ height: 16px;
985
+ line-height: 16px;
986
+ float:left;
987
+ font-size:10px;
988
+ font-family:sans-serif;
989
+ }
990
+ .sp-preview {
991
+ position:relative;
992
+ width:25px;
993
+ height: 20px;
994
+ border: solid 1px #222;
995
+ margin-right: 5px;
996
+ float:left;
997
+ z-index: 0;
998
+ }
999
+
1000
+ .sp-palette {
1001
+ *width: 220px;
1002
+ max-width: 220px;
1003
+ }
1004
+ .sp-palette .sp-thumb-el {
1005
+ width:16px;
1006
+ height: 16px;
1007
+ margin:2px 1px;
1008
+ border: solid 1px #d0d0d0;
1009
+ }
1010
+
1011
+ .sp-container {
1012
+ padding-bottom:0;
1013
+ }
1014
+
1015
+
1016
+ /* Buttons: http://hellohappy.org/css3-buttons/ */
1017
+ .sp-container button {
1018
+ background-color: #eeeeee;
1019
+ background-image: -webkit-linear-gradient(top, #eeeeee, #cccccc);
1020
+ background-image: -moz-linear-gradient(top, #eeeeee, #cccccc);
1021
+ background-image: -ms-linear-gradient(top, #eeeeee, #cccccc);
1022
+ background-image: -o-linear-gradient(top, #eeeeee, #cccccc);
1023
+ background-image: linear-gradient(to bottom, #eeeeee, #cccccc);
1024
+ border: 1px solid #ccc;
1025
+ border-bottom: 1px solid #bbb;
1026
+ border-radius: 3px;
1027
+ color: #333;
1028
+ font-size: 14px;
1029
+ line-height: 1;
1030
+ padding: 5px 4px;
1031
+ text-align: center;
1032
+ text-shadow: 0 1px 0 #eee;
1033
+ vertical-align: middle;
1034
+ }
1035
+ .sp-container button:hover {
1036
+ background-color: #dddddd;
1037
+ background-image: -webkit-linear-gradient(top, #dddddd, #bbbbbb);
1038
+ background-image: -moz-linear-gradient(top, #dddddd, #bbbbbb);
1039
+ background-image: -ms-linear-gradient(top, #dddddd, #bbbbbb);
1040
+ background-image: -o-linear-gradient(top, #dddddd, #bbbbbb);
1041
+ background-image: linear-gradient(to bottom, #dddddd, #bbbbbb);
1042
+ border: 1px solid #bbb;
1043
+ border-bottom: 1px solid #999;
1044
+ cursor: pointer;
1045
+ text-shadow: 0 1px 0 #ddd;
1046
+ }
1047
+ .sp-container button:active {
1048
+ border: 1px solid #aaa;
1049
+ border-bottom: 1px solid #888;
1050
+ -webkit-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
1051
+ -moz-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
1052
+ -ms-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
1053
+ -o-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
1054
+ box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
1055
+ }
1056
+ .sp-cancel {
1057
+ font-size: 11px;
1058
+ color: #d93f3f !important;
1059
+ margin:0;
1060
+ padding:2px;
1061
+ margin-right: 5px;
1062
+ vertical-align: middle;
1063
+ text-decoration:none;
1064
+
1065
+ }
1066
+ .sp-cancel:hover {
1067
+ color: #d93f3f !important;
1068
+ text-decoration: underline;
1069
+ }
1070
+
1071
+
1072
+ .sp-palette span:hover, .sp-palette span.sp-thumb-active {
1073
+ border-color: #000;
1074
+ }
1075
+
1076
+ .sp-preview, .sp-alpha, .sp-thumb-el {
1077
+ position:relative;
1078
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);
1079
+ }
1080
+ .sp-preview-inner, .sp-alpha-inner, .sp-thumb-inner {
1081
+ display:block;
1082
+ position:absolute;
1083
+ top:0;left:0;bottom:0;right:0;
1084
+ }
1085
+
1086
+ .sp-palette .sp-thumb-inner {
1087
+ background-position: 50% 50%;
1088
+ background-repeat: no-repeat;
1089
+ }
1090
+
1091
+ .sp-palette .sp-thumb-light.sp-thumb-active .sp-thumb-inner {
1092
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIVJREFUeNpiYBhsgJFMffxAXABlN5JruT4Q3wfi/0DsT64h8UD8HmpIPCWG/KemIfOJCUB+Aoacx6EGBZyHBqI+WsDCwuQ9mhxeg2A210Ntfo8klk9sOMijaURm7yc1UP2RNCMbKE9ODK1HM6iegYLkfx8pligC9lCD7KmRof0ZhjQACDAAceovrtpVBRkAAAAASUVORK5CYII=);
1093
+ }
1094
+
1095
+ .sp-palette .sp-thumb-dark.sp-thumb-active .sp-thumb-inner {
1096
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAMdJREFUOE+tkgsNwzAMRMugEAahEAahEAZhEAqlEAZhEAohEAYh81X2dIm8fKpEspLGvudPOsUYpxE2BIJCroJmEW9qJ+MKaBFhEMNabSy9oIcIPwrB+afvAUFoK4H0tMaQ3XtlrggDhOVVMuT4E5MMG0FBbCEYzjYT7OxLEvIHQLY2zWwQ3D+9luyOQTfKDiFD3iUIfPk8VqrKjgAiSfGFPecrg6HN6m/iBcwiDAo7WiBeawa+Kwh7tZoSCGLMqwlSAzVDhoK+6vH4G0P5wdkAAAAASUVORK5CYII=);
1097
+ }
1098
+
1099
+ .sp-clear-display {
1100
+ background-repeat:no-repeat;
1101
+ background-position: center;
1102
+ background-image: url(data:image/gif;base64,R0lGODlhFAAUAPcAAAAAAJmZmZ2dnZ6enqKioqOjo6SkpKWlpaampqenp6ioqKmpqaqqqqurq/Hx8fLy8vT09PX19ff39/j4+Pn5+fr6+vv7+wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAP8ALAAAAAAUABQAAAihAP9FoPCvoMGDBy08+EdhQAIJCCMybCDAAYUEARBAlFiQQoMABQhKUJBxY0SPICEYHBnggEmDKAuoPMjS5cGYMxHW3IiT478JJA8M/CjTZ0GgLRekNGpwAsYABHIypcAgQMsITDtWJYBR6NSqMico9cqR6tKfY7GeBCuVwlipDNmefAtTrkSzB1RaIAoXodsABiZAEFB06gIBWC1mLVgBa0AAOw==);
1103
+ }
includes/class-ctc-css.php CHANGED
@@ -5,8 +5,8 @@ if ( !defined( 'ABSPATH' ) ) exit;
5
  /*
6
  Class: ChildThemeConfiguratorCSS
7
  Plugin URI: http://www.childthemeconfigurator.com/
8
- Description: Handles all CSS output, parsing, normalization
9
- Version: 1.7.4.2
10
  Author: Lilaea Media
11
  Author URI: http://www.lilaeamedia.com/
12
  Text Domain: chld_thm_cfg
@@ -51,11 +51,16 @@ class ChildThemeConfiguratorCSS {
51
  var $child_version; // stylesheet version
52
  var $max_sel;
53
  var $vendorrule = array(
54
- 'box-sizing',
55
- 'font-smoothing',
56
- 'border-radius',
57
- 'box-shadow',
58
  'transition',
 
 
 
 
 
59
  'transform'
60
  );
61
  var $configvars = array(
@@ -130,10 +135,12 @@ class ChildThemeConfiguratorCSS {
130
  $this->recent = array();
131
  $this->imports = array( 'child' => array(), 'parnt' => array() );
132
  }
 
133
  // helper function to globalize ctc object
134
  function ctc() {
135
  return ChildThemeConfigurator::ctc();
136
  }
 
137
  // loads current ctc config data into local memory
138
  function load_config() {
139
  $option = CHLD_THM_CFG_OPTIONS . apply_filters( 'chld_thm_cfg_option', '' );
@@ -152,6 +159,7 @@ class ChildThemeConfiguratorCSS {
152
  return FALSE;
153
  endif;
154
  }
 
155
  // writes ctc config data to options api
156
  function save_config( $override = NULL ) {
157
  if ( isset( $override ) ) $option = $override;
@@ -256,6 +264,7 @@ class ChildThemeConfiguratorCSS {
256
  $this->{ $prop } = $value;
257
  else return FALSE;
258
  }
 
259
  // formats css string for accurate parsing
260
  function normalize_css() {
261
  if ( preg_match( "/(\}[\w\#\.]|; *\})/", $this->styles ) ): // prettify compressed CSS
@@ -265,6 +274,7 @@ class ChildThemeConfiguratorCSS {
265
  $this->styles = preg_replace( "/\s*\}\s*/s", "\n}\n", $this->styles ); // close brace
266
  endif;
267
  }
 
268
  // creates header comments for stylesheet
269
  function get_css_header() {
270
  $parnt = $this->get_prop( 'parnt' );
@@ -281,95 +291,233 @@ class ChildThemeConfiguratorCSS {
281
  . '*/' . LF . LF . '@charset "UTF-8";' . LF . LF
282
  . ( 'import' == $this->enqueue ? '@import url(\'../' . $parnt . '/style.css\');' . LF : '' );
283
  }
 
284
  // formats file path for child theme file
285
  function get_child_target( $file = 'style.css' ) {
286
  return trailingslashit( get_theme_root() ) . trailingslashit( $this->get_prop( 'child' ) ) . $file;
287
  }
 
288
  // formats file path for parent theme file
289
  function get_parent_source( $file = 'style.css' ) {
290
  return trailingslashit( get_theme_root() ) . trailingslashit( $this->get_prop( 'parnt' ) ) . $file;
291
  }
292
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
293
  /**
294
  * update_arrays
295
  * accepts CSS properties as raw strings and normilizes into
296
  * CTC object arrays, creating update cache in the process.
297
- * Update cache is returned to UI via AJAX to refresh page.
 
 
 
 
 
 
 
 
 
 
298
  */
299
- function update_arrays( $template, $query, $sel, $rule = NULL, $value = NULL, $important = 0 ) {
 
 
 
 
 
 
 
 
 
300
  if ( $this->max_sel ) return;
301
  if ( FALSE === strpos( $query, '@' ) ):
302
  $query = 'base';
303
  endif;
304
  // normalize selector styling
305
  $sel = implode( ', ', preg_split( '#\s*,\s*#s', trim( $sel ) ) );
306
- // add selector and query to index
307
- if ( !isset( $this->dict_query[ $query ] ) ) $this->dict_query[ $query ] = ++$this->querykey;
308
- if ( !isset( $this->dict_sel[ $sel ] ) ) $this->dict_sel[ $sel ] = ++$this->selkey;
309
- if ( !isset( $this->sel_ndx[ $this->dict_query[ $query ] ][ $this->dict_sel[ $sel ] ] ) ):
310
- // stop parsing if limit is reached to prevent out of memory on serialize
311
- if ( $this->qskey >= $this->ctc()->sel_limit ):
312
- $this->max_sel = 1;
313
- $this->ctc()->debug( 'Maximum num selectors reached ( limit: ' . $this->ctc()->sel_limit . ' )', __FUNCTION__ );
314
- return;
315
- endif;
316
- // increment key number
317
- $this->sel_ndx[ $this->dict_query[ $query ] ][ $this->dict_sel[ $sel ] ] = ++$this->qskey;
318
-
319
- $this->dict_qs[ $this->qskey ][ 's' ] = $this->dict_sel[ $sel ];
320
- $this->dict_qs[ $this->qskey ][ 'q' ] = $this->dict_query[ $query ];
321
- endif;
322
 
323
- // update sequence for this selector if this is a later instance to keep cascade priority
324
- if ( !isset( $this->dict_seq[ $this->qskey ] ) )
325
- $this->dict_seq[ $this->qskey ] = $this->qskey;
326
  // set data and value
327
  if ( $rule ):
328
- if ( !isset( $this->dict_rule[ $rule ] ) ):
329
- $this->dict_rule[ $rule ] = ++$this->rulekey;
330
- endif;
331
- $qsid = $this->sel_ndx[ $this->dict_query[ $query ] ][ $this->dict_sel[ $sel ] ];
332
- $ruleid = $this->dict_rule[ $rule ];
333
- if ( !isset( $this->dict_val[ $value ] ) ):
334
- $this->dict_val[ $value ] = ++$this->valkey;
335
- endif;
336
 
337
- $this->val_ndx[ $qsid ][ $ruleid ][ $template ] = $this->dict_val[ $value ];
338
- // set the important flag for this value
339
- $this->val_ndx[ $qsid ][ $ruleid ][ 'i_' . $template ] = $important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
340
  return $qsid;
341
  endif;
342
  }
343
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
344
  function prune_if_empty( $qsid ) {
345
- if (! isset( $this->dict_val[ '' ] ) ) return FALSE;
346
- $empty = $this->dict_val[ '' ];
347
  foreach ( $this->val_ndx[ $qsid ] as $ruleid => $arr ):
348
- if ( ( isset( $arr[ 'child' ] ) && $empty != $arr[ 'child' ] )
349
- || ( isset( $arr[ 'parnt' ] ) && $empty != $arr[ 'parnt' ] )
350
- ):
351
- return FALSE;
352
- endif;
 
 
 
 
353
  endforeach;
354
  // no values, prune from sel index, val index and qs dict data ( keep other dictionary records )
355
  unset( $this->sel_ndx[ $this->dict_qs[ $qsid ][ 'q' ] ][ $this->dict_qs[ $qsid ][ 's' ] ] );
356
  unset( $this->val_ndx[ $qsid ] );
357
  unset( $this->dict_qs[ $qsid ] );
 
358
  }
359
 
360
- /* recurse_directory
 
361
  * searches filesystem for valid files based on parameters and returns array of filepaths.
362
- * Because it requires logic specific to CTC, core WP recurse function is not used.
363
  */
364
  function recurse_directory( $rootdir, $ext = 'css', $all = FALSE ) {
365
- if ( !$this->is_file_ok( $rootdir, 'search' ) ) return array(); // make sure we are only recursing theme and plugin files
 
 
366
  $files = array();
367
  $dirs = array( $rootdir );
368
  $loops = 0;
369
- if ( 'img' == $ext ):
370
-
371
  $ext = '(' . implode( '|', array_keys( $this->ctc()->imgmimes ) ) . ')';
372
- endif;
373
  while( count( $dirs ) && $loops < CHLD_THM_CFG_MAX_RECURSE_LOOPS ): // failsafe valve
374
  $loops++;
375
  $dir = array_shift( $dirs );
@@ -379,7 +527,7 @@ class ChildThemeConfiguratorCSS {
379
  $filepath = trailingslashit( $dir ) . $file;
380
  if ( is_dir( $filepath ) ):
381
  array_unshift( $dirs, $filepath );
382
- if ( $all ):
383
  $files[] = $filepath;
384
  endif;
385
  elseif ( is_file( $filepath ) && ( $all || preg_match( "/\.".$ext."$/i", $filepath ) ) ):
@@ -391,16 +539,22 @@ class ChildThemeConfiguratorCSS {
391
  endwhile;
392
  return $files;
393
  }
394
- /*
 
395
  * parse_post_data
396
  * Parse user form input into separate properties and pass to update_arrays
 
397
  */
398
  function parse_post_data() {
399
  $this->cache_updates = TRUE;
400
  if ( isset( $_POST[ 'ctc_new_selectors' ] ) ):
401
  $this->styles = $this->parse_css_input( LF . $_POST[ 'ctc_new_selectors' ] );
402
  $this->parse_css( 'child',
403
- ( isset( $_POST[ 'ctc_sel_ovrd_query' ] ) ? trim( $_POST[ 'ctc_sel_ovrd_query' ] ) : NULL ), FALSE );
 
 
 
 
404
  elseif ( isset( $_POST[ 'ctc_child_imports' ] ) ):
405
  $this->imports[ 'child' ] = array();
406
  $this->styles = $this->parse_css_input( $_POST[ 'ctc_child_imports' ] );
@@ -436,87 +590,147 @@ class ChildThemeConfiguratorCSS {
436
  endforeach;
437
  $parts = array();
438
  foreach ( preg_grep( '#^ctc_(ovrd|\d+)_child#', array_keys( $_POST ) ) as $post_key ):
439
- if ( preg_match( '#^ctc_(ovrd|\d+)_child_([\w\-]+?)_(\d+?)(_(.+))?$#', $post_key, $matches ) ):
440
- $valid = $matches[ 1 ];
441
- $rule = $matches[ 2 ];
442
  if ( NULL == $rule || !isset( $this->dict_rule[ $rule ] ) ) continue;
443
- $ruleid = $this->dict_rule[ $rule ];
444
- $qsid = $matches[ 3 ];
445
- $value = $this->normalize_color( $this->sanitize( $this->parse_css_input( $_POST[ $post_key ] ) ) );
446
- $important = $this->is_important( $value );
447
- if ( !empty( $_POST[ 'ctc_' . $valid . '_child_' . $rule . '_i_' . $qsid ] ) ) $important = 1;
448
-
449
  $selarr = $this->denorm_query_sel( $qsid );
450
- if ( !empty( $matches[ 5 ] ) ):
451
- $parts[ $qsid ][ $rule ][ $matches[ 5 ] ] = $value;
452
- $parts[ $qsid ][ $rule ][ 'important' ] = $important;
453
  $parts[ $qsid ][ $rule ][ 'query' ] = $selarr[ 'query' ];
454
  $parts[ $qsid ][ $rule ][ 'selector' ] = $selarr[ 'selector' ];
455
  else:
456
  if ( $newselector && $newselector != $selarr[ 'selector' ] ):
457
  // If this is a renamed selector, add new selector to array
458
- $newqsid = $this->update_arrays( 'child', $selarr[ 'query' ], $newselector,
459
- $rule, trim( $value ), $important );
 
 
 
 
 
 
 
460
  // clear the original selector's child value:
461
- $this->update_arrays( 'child', $selarr[ 'query' ], $selarr[ 'selector' ], $rule, '' );
462
- // remove if all values have been cleared
463
- // note: 1.7.2 we are only pruning after rename
464
- $this->prune_if_empty( $qsid );
 
 
 
 
 
 
465
  else:
466
  // otherwise, just update with the new values:
467
- $this->update_arrays( 'child', $selarr[ 'query' ], $selarr[ 'selector' ],
468
- $rule, trim( $value ), $important );
 
 
 
 
 
 
 
469
  endif;
470
  endif;
471
  endif;
472
  endforeach;
473
- foreach ( $parts as $qsid => $rule_arr ):
474
- foreach ( $rule_arr as $rule => $rule_part ):
475
- if ( 'background' == $rule ):
476
- $value = $rule_part[ 'background_url' ];
477
- elseif ( 'background-image' == $rule ):
478
- if ( empty( $rule_part[ 'background_url' ] ) ):
479
- if ( empty( $rule_part[ 'background_color2' ] ) ):
480
- $value = '';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
481
  else:
482
- $value = implode( ':', array(
483
- $rule_part[ 'background_origin' ],
484
- $rule_part[ 'background_color1' ], '0%',
485
- $rule_part[ 'background_color2' ], '100%'
486
- ) );
487
  endif;
 
 
 
 
 
 
 
 
 
 
488
  else:
489
- $value = $rule_part[ 'background_url' ];
490
  endif;
491
- elseif ( preg_match( '#^border(\-(top|right|bottom|left))?$#', $rule ) ):
492
- $value = implode( ' ', array(
493
- $rule_part[ 'border_width' ],
494
- $rule_part[ 'border_style' ],
495
- $rule_part[ 'border_color' ]
496
- ) );
497
- else:
498
- $value = '';
499
- endif;
500
- if ( $newselector && $newselector != $rule_part[ 'selector' ] ):
501
- // If this is a renamed selector, add new selector to array
502
- $newqsid = $this->update_arrays( 'child', $rule_part[ 'query' ], $newselector,
503
- $rule, trim( $value ), $rule_part[ 'important' ] );
504
- // clear the original selector's child value:
505
- $this->update_arrays( 'child', $rule_part[ 'query' ], $rule_part[ 'selector' ], $rule, '' );
506
- else:
507
- // otherwise, just update with the new values:
508
- $this->update_arrays( 'child', $rule_part[ 'query' ], $rule_part[ 'selector' ],
509
- $rule, trim( $value ), $rule_part[ 'important' ] );
510
- endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
511
  endforeach;
512
- endforeach;
513
  // if this is a renamed selector, update sequence dict
514
  if ( $newqsid ):
515
  if ( !isset( $this->dict_seq[ $newqsid ] ) )
516
  $this->dict_seq[ $newqsid ] = $this->dict_seq[ $qsid ];
517
- // pass this back to browser
518
- $qsid = $newqsid;
519
  endif;
 
 
 
520
  // return updated qsid to browser to update form
521
  if ( $this->ctc()->cache_updates ):
522
  $this->ctc()->updates[] = array(
@@ -533,28 +747,30 @@ class ChildThemeConfiguratorCSS {
533
  add_action( 'chld_thm_cfg_addl_files', array( $this->ctc(), 'enqueue_parent_css' ), 15, 2 );
534
  }
535
 
536
- /*
537
  * parse_css_input
538
  * Normalize raw user CSS input so that the parser can read it.
539
- * TODO: this is a stub for future use
540
  */
541
  function parse_css_input( $styles ) {
542
  return $this->repl_octal( stripslashes( $this->esc_octal( $styles ) ) );
543
  }
 
544
  // strips non printables and potential commands
545
  function sanitize( $styles ) {
546
  return sanitize_text_field( preg_replace( '/[^[:print:]]/', '', $styles ) );
547
  }
 
548
  // escapes octal values in input to allow for specific ascii strings in content rule
549
  function esc_octal( $styles ){
550
  return preg_replace( "#(['\"])\\\\([0-9a-f]{4})(['\"])#i", "$1##bs##$2$3", $styles );
551
  }
 
552
  // unescapes octal values for writing specific ascii strings in content rule
553
  function repl_octal( $styles ) {
554
  return str_replace( "##bs##", "\\", $styles );
555
  }
556
 
557
- /*
558
  * parse_css_file
559
  * reads stylesheet to get WordPress meta data and passes rest to parse_css
560
  */
@@ -574,7 +790,12 @@ class ChildThemeConfiguratorCSS {
574
  preg_match( $regex, $this->styles, $matches );
575
  $child_name = $this->get_prop( 'child_name' );
576
  if ( !empty( $matches[ 1 ] ) && 'child' == $template && empty( $child_name ) ) $this->set_prop( 'child_name', $matches[ 1 ] );
577
- $this->parse_css( $cfgtemplate ? $cfgtemplate : $template, NULL, TRUE, $this->ctc()->normalize_path( dirname( $file ) ) );
 
 
 
 
 
578
  }
579
 
580
  // loads raw css file into local memory
@@ -607,11 +828,12 @@ class ChildThemeConfiguratorCSS {
607
  endif;
608
  }
609
 
610
- /*
611
  * parse_css
612
  * Accepts raw CSS as text and parses into individual properties.
 
613
  */
614
- function parse_css( $template, $basequery = NULL, $parse_imports = TRUE, $relpath = '' ) {
615
  if ( FALSE === strpos( $basequery, '@' ) ):
616
  $basequery = 'base';
617
  endif;
@@ -645,7 +867,9 @@ class ChildThemeConfiguratorCSS {
645
  ) as $regex ): // (((?!\@media).) backreference too memory intensive - rolled back in v 1.4.8.1
646
  preg_match_all( $regex, $this->styles, $matches );
647
  foreach ( $matches[ 1 ] as $segment ):
648
- $ruleset[ trim( $segment ) ] = array_shift( $matches[ 2 ] ) . ( isset( $ruleset[ trim( $segment ) ] )?$ruleset[ trim( $segment ) ]:'' );
 
 
649
  endforeach;
650
  // stripping rulesets leaves base styles
651
  $this->styles = preg_replace( $regex, '', $this->styles );
@@ -662,14 +886,16 @@ class ChildThemeConfiguratorCSS {
662
  preg_match_all( $regex, $segment, $matches );
663
  foreach( $matches[ 1 ] as $sel ):
664
  $stuff = array_shift( $matches[ 2 ] );
665
- $this->update_arrays( $template, $query, $sel );
 
 
 
 
666
  // handle base64 data
667
  $stuff = preg_replace( '#data:([^;]+?);([^\)]+?)\)#s', "data:$1%%semi%%$2)", $stuff );
 
 
668
  foreach ( explode( ';', $stuff ) as $ruleval ):
669
- /**
670
- * FIXME: set limit of number of parsed selectors?
671
- * if ( $this->qskey > CHLD_THM_CFG_MAX_SELECTORS ) break;
672
- */
673
  if ( FALSE === strpos( $ruleval, ':' ) ) continue;
674
  list( $rule, $value ) = explode( ':', $ruleval, 2 );
675
  $rule = trim( $rule );
@@ -702,8 +928,9 @@ class ChildThemeConfiguratorCSS {
702
  // normalize gradients
703
  if ( FALSE !== strpos( $value, 'gradient' ) ):
704
  if ( FALSE !== strpos( $rule, 'filter' ) ):
 
705
  $rule = 'background-image';
706
- continue; // treat as background-image, we'll add filter rule later
707
  endif;
708
  if ( FALSE !== strpos( $value, 'webkit-gradient' ) ) continue; // bail on legacy webkit, we'll add it later
709
  $value = $this->encode_gradient( $value );
@@ -712,7 +939,20 @@ class ChildThemeConfiguratorCSS {
712
  $rule = preg_replace( '#(\-(o|ms|moz|webkit)\-)?(' . implode( '|', $this->vendorrule ) . ')#', "$3", $rule );
713
  if ( 'parnt' == $template && 'background-image' == $rule && strstr( $value, 'url(' ) )
714
  $value = $this->convert_rel_url( $value, $relpath );
715
- $qsid = $this->update_arrays( $template, $query, $sel, $rule, $value, $important );
 
 
 
 
 
 
 
 
 
 
 
 
 
716
  endforeach;
717
  endforeach;
718
  endforeach;
@@ -747,12 +987,13 @@ class ChildThemeConfiguratorCSS {
747
  return $newvalue;
748
  }
749
 
750
- /*
751
  * write_css
752
  * converts normalized CSS object data into stylesheet.
753
  * Preserves selector sequence and !important flags of parent stylesheet.
754
  * @media query blocks are sorted using internal heuristics (see sort_queries)
755
  * New selectors are appended to the end of each media query block.
 
756
  */
757
  function write_css( $backup = FALSE ) {
758
  // write new stylesheet
@@ -769,35 +1010,48 @@ class ChildThemeConfiguratorCSS {
769
  uasort( $selectors, array( $this, 'cmp_seq' ) );
770
  if ( 'base' != $query ) $sel_output .= $query . ' {' . LF;
771
  foreach ( $selectors as $selid => $qsid ):
772
- $has_value = 0;
773
- $sel = $selarr[ $selid ];
774
  if ( !empty( $this->val_ndx[ $qsid ] ) ):
775
- $shorthand = array();
776
- foreach ( $this->val_ndx[ $qsid ] as $ruleid => $valid ):
777
- if ( isset( $valid[ 'child' ] )
778
- && isset( $valarr[ $valid[ 'child' ] ] )
779
- && '' !== $valarr[ $valid[ 'child' ] ]
780
- && ( !isset( $valid[ 'parnt' ] ) || $valid[ 'parnt' ] != $valid[ 'child' ] ) ):
781
- if ( ! $has_value ):
782
- $sel_output .= isset( $this->dict_seq[ $qsid ] )?'/*' . $this->dict_seq[ $qsid ] . '*/' . LF:'';
783
- // show load order
784
- $sel_output .= $sel . ' {' . LF;
785
- $has_value = 1;
786
- $has_selector = 1;
787
- endif;
788
- $important_parnt = empty( $valid[ 'i_parnt' ] ) ? 0 : 1;
789
- $important = isset( $valid[ 'i_child' ] ) ? $valid[ 'i_child' ] : $important_parnt;
790
- $sel_output .= $this->add_vendor_rules(
791
- $rulearr[ $ruleid ],
792
- $valarr[ $valid[ 'child' ] ],
793
- $shorthand,
794
- $important
795
- );
 
 
 
 
 
 
 
 
 
 
 
796
  endif;
797
  endforeach;
798
- $sel_output .= $this->encode_shorthand( $shorthand ); // . ( $important ? ' !important' : '' );
799
- if ( $has_value ):
800
- $sel_output .= '}' . LF;
 
 
 
 
801
  endif;
802
  endif;
803
  endforeach;
@@ -835,32 +1089,115 @@ class ChildThemeConfiguratorCSS {
835
  return FALSE;
836
  }
837
 
838
- /*
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
839
  * add_vendor_rules
840
- * Applies vendor prefixes to rules/values
841
- * These are based on commonly used practices and not all vendor prefixed are supported
842
  * TODO: verify this logic against vendor and W3C documentation
843
  */
844
- function add_vendor_rules( $rule, $value, &$shorthand, $important = 0 ) {
845
- $rules = '';
846
  if ( 'filter' == $rule && ( FALSE !== strpos( $value, 'progid:DXImageTransform.Microsoft.Gradient' ) ) ) return;
847
  $importantstr = $important ? ' !important' : '';
848
  if ( preg_match( "/^(margin|padding)\-(top|right|bottom|left)$/", $rule, $matches ) ):
849
- $shorthand[ $matches[ 1 ] ][ $matches[ 2 ] ] = $value . $importantstr;
850
- return '';
 
 
 
851
  elseif ( preg_match( '/^(' . implode( '|', $this->vendorrule ) . ')$/', $rule ) ):
852
  foreach( array( 'moz', 'webkit', 'o' ) as $prefix ):
853
- $rules .= ' -' . $prefix . '-' . $rule . ': ' . $value . $importantstr . ';' . LF;
854
  endforeach;
855
- $rules .= ' ' . $rule . ': ' . $value . $importantstr . ';' . LF;
856
  elseif ( 'background-image' == $rule ):
857
  // gradient?
858
 
859
  if ( $gradient = $this->decode_gradient( $value ) ):
860
  // standard gradient
861
  foreach( array( 'moz', 'webkit', 'o', 'ms' ) as $prefix ):
862
- $rules .= ' background-image: -' . $prefix . '-' . 'linear-gradient(' . $gradient[ 'origin' ] . ', '
863
- . $gradient[ 'color1' ] . ', ' . $gradient[ 'color2' ] . ')' . $importantstr . ';' . LF;
864
  endforeach;
865
  // W3C standard gradient
866
  // rotate origin 90 degrees
@@ -876,30 +1213,31 @@ class ChildThemeConfiguratorCSS {
876
  endforeach;
877
  $org = 'to ' . implode( ' ', $dirs );
878
  endif;
879
- $rules .= ' background-image: linear-gradient(' . $org . ', '
880
- . $gradient[ 'color1' ] . ', ' . $gradient[ 'color2' ] . ')' . $importantstr . ';' . LF;
881
 
882
  // legacy webkit gradient - we'll add if there is demand
883
  // '-webkit-gradient(linear,' .$origin . ', ' . $color1 . ', '. $color2 . ')';
884
 
885
- // MS filter gradient
886
- $type = ( in_array( $gradient[ 'origin' ], array( 'left', 'right', '0deg', '180deg' ) ) ? 1 : 0 );
887
- $color1 = preg_replace( "/^#/", '#00', $gradient[ 'color1' ] );
888
- $rules .= ' filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=' . $type . ', StartColorStr="'
889
- . strtoupper( $color1 ) . '", EndColorStr="' . strtoupper( $gradient[ 'color2' ] ) . '")'
890
- . $importantstr . ';' . LF;
 
 
891
  else:
892
  // url or other value
893
- $rules .= ' ' . $rule . ': ' . $value . $importantstr . ';' . LF;
894
  endif;
895
  else:
896
  $rule = preg_replace_callback( "/\d+/", array( $this, 'from_ascii' ), $rule );
897
- $rules .= ' ' . $rule . ': ' . $value . $importantstr . ';' . LF;
898
  endif;
899
- return $rules;
900
  }
901
 
902
- /*
903
  * normalize_background
904
  * parses background shorthand value and returns
905
  * normalized rule/value pairs for each property
@@ -946,7 +1284,7 @@ class ChildThemeConfiguratorCSS {
946
  endif;
947
  }
948
 
949
- /*
950
  * normalize_font
951
  * parses font shorthand value and returns
952
  * normalized rule/value pairs for each property
@@ -976,7 +1314,7 @@ class ChildThemeConfiguratorCSS {
976
  endif;
977
  }
978
 
979
- /*
980
  * normalize_margin_padding
981
  * parses margin or padding shorthand value and returns
982
  * normalized rule/value pairs for each property
@@ -996,114 +1334,68 @@ class ChildThemeConfiguratorCSS {
996
  $values[ 3 ] = $parts[ 3 ];
997
  }
998
 
999
- /*
1000
- * encode_shorthand
1001
- * converts CTC long syntax into CSS shorthand
1002
- */
1003
- function encode_shorthand( $shorthand ) {
1004
- $rules = '';
1005
- $importantstr = ' !important';
1006
- foreach ( array_keys( $shorthand ) as $key ):
1007
- $important = array();
1008
- $rule = array();
1009
- $importantct = 0;
1010
- // which sides do we have and are they important?
1011
- foreach( $shorthand[ $key ] as $side => $val ):
1012
- $ict = 0;
1013
- $rule[ $side ] = trim( preg_replace( '/'.$importantstr.'/', '', $val, 1, $ict ) );
1014
- $important[ $side ] = $ict;
1015
- $importantct += $ict;
1016
- endforeach;
1017
- // shorthand must have 4 explicit values and all must have same priority
1018
- if ( 4 == count( $rule ) && ( 0 == $importantct || 4 == $importantct ) ):
1019
- // let's try to condense the values into as few as possible, starting with the top value
1020
- $parts = array();
1021
- $parts[ 0 ] = $rule[ 'top' ];
1022
- // if left is not the same as right, we must use all 4 values
1023
- if ( $rule[ 'left' ] !== $rule[ 'right' ] ):
1024
- $parts[ 3 ] = $rule[ 'left' ];
1025
- $parts[ 2 ] = $rule[ 'bottom' ];
1026
- $parts[ 1 ] = $rule[ 'right' ];
1027
- endif;
1028
- // if top is not the same as bottom, we must use at least 3 values
1029
- if ( $rule[ 'bottom' ] !== $rule[ 'top' ] ):
1030
- $parts[ 2 ] = $rule[ 'bottom' ];
1031
- $parts[ 1 ] = $rule[ 'right' ];
1032
- endif;
1033
- // if top is not the same as right, we must use at least 2 values
1034
- if ( $rule[ 'right' ] !== $rule[ 'top' ] ):
1035
- $parts[ 1 ] = $rule[ 'right' ];
1036
- endif;
1037
- // the order of the sides is critical: top right bottom left
1038
- ksort( $parts );
1039
- $shorthandstr = implode( ' ', $parts );
1040
- // if important counter is > 0, it must be == 4, add flag
1041
- $rules .= ' ' . $key . ': ' . $shorthandstr . ( $importantct ? ' ' . $importantstr : '' ) . ';' . LF;
1042
- else:
1043
- // otherwise return separate rule for each side
1044
- foreach ( $rule as $side => $value ):
1045
- $rules .= ' ' . $key . '-' . $side . ': ' . $value . ( $important[ $side ] ? $importantstr : '' ) . ';' . LF;
1046
- endforeach;
1047
- endif;
1048
- endforeach;
1049
- return $rules;
1050
- }
1051
-
1052
- /*
1053
  * encode_gradient
1054
- * Normalize linear gradients from a bazillion formats into standard CTC syntax:
 
1055
  * Currently only supports two-color linear gradients with no inner stops.
1056
  * TODO: legacy webkit? more gradients?
1057
  */
1058
  function encode_gradient( $value ) {
1059
  // don't try this at home, kids
1060
- $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';
1061
  $param = $parts = array();
1062
  preg_match( $regex, $value, $parts );
1063
- if ( empty( $parts[ 13 ] ) ):
1064
  if ( empty( $parts[ 2 ] ) ):
1065
  $param[ 0 ] = 'top';
 
 
 
 
 
 
1066
  else:
1067
  $param[ 0 ] = trim( $parts[ 2 ] );
1068
  endif;
1069
- if ( empty( $parts[ 8 ] ) ):
1070
  $param[ 2 ] = '0%';
1071
  else:
1072
- $param[ 2 ] = trim( $parts[ 8 ] );
1073
  endif;
1074
- if ( empty( $parts[ 11 ] ) ):
1075
  $param[ 4 ] = '100%';
1076
  else:
1077
- $param[ 4 ] = trim( $parts[ 11 ] );
1078
  endif;
1079
- elseif( '0' == $parts[ 13 ] ):
1080
  $param[ 0 ] = 'top';
1081
  $param[ 2 ] = '0%';
1082
  $param[ 4 ] = '100%';
1083
- elseif ( '1' == $parts[ 13 ] ):
1084
  $param[ 0 ] = 'left';
1085
  $param[ 2 ] = '0%';
1086
  $param[ 4 ] = '100%';
1087
  endif;
1088
- if ( isset( $parts[ 7 ] ) && isset( $parts[ 10 ] ) ):
1089
- $param[ 1 ] = $parts[ 7 ];
1090
- $param[ 3 ] = $parts[ 10 ];
1091
  ksort( $param );
1092
  return implode( ':', $param );
1093
- else: return $value;
 
1094
  endif;
1095
  }
1096
 
1097
- /*
1098
  * decode_border
1099
  * De-normalize CTC border syntax into individual properties.
1100
  */
1101
  function decode_border( $value ) {
1102
- if ( preg_match( '#^(0|none)#i', $value ) ):
 
1103
  $parts[ 0 ] = $value;
1104
  $parts[ 1 ] = $parts[ 2 ] = '';
1105
- else:
1106
- $parts = preg_split( '#\s+#', $value, 3 );
1107
  endif;
1108
  return array(
1109
  'width' => empty( $parts[ 0 ] ) ? '' : $parts[ 0 ],
@@ -1112,7 +1404,7 @@ class ChildThemeConfiguratorCSS {
1112
  );
1113
  }
1114
 
1115
- /*
1116
  * decode_gradient
1117
  * Decode CTC gradient syntax into individual properties.
1118
  */
@@ -1130,46 +1422,57 @@ class ChildThemeConfiguratorCSS {
1130
  return FALSE;
1131
  }
1132
 
1133
- /*
1134
  * denorm_rule_val
1135
  * Return array of unique values corresponding to specific rule
 
1136
  */
1137
  function denorm_rule_val( $ruleid ) {
1138
  $rule_sel_arr = array();
1139
  $val_arr = array_flip( $this->dict_val );
1140
- foreach ( $this->val_ndx as $selid => $rules ):
1141
  if ( !isset( $rules[ $ruleid ] ) ) continue;
1142
- foreach ( $rules[ $ruleid ] as $theme => $val ):
1143
- // skip important flag and invalid values
1144
- if ( strstr( $theme, 'i_' ) || !isset( $val_arr[ $val ] ) || '' === $val_arr[ $val ] ) continue;
1145
- $rule_sel_arr[ $val ] = $val_arr[ $val ];
 
 
 
1146
  endforeach;
1147
  endforeach;
1148
  return $rule_sel_arr;
1149
  }
1150
 
1151
- /*
1152
  * denorm_val_query
1153
  * Return array of queries, selectors, rules, and values corresponding to
1154
  * specific rule/value combo grouped by query, selector
 
1155
  */
1156
  function denorm_val_query( $valid, $rule ) {
1157
  $value_query_arr = array();
 
1158
  foreach ( $this->val_ndx as $qsid => $rules ):
1159
  foreach ( $rules as $ruleid => $values ):
1160
- if ( $ruleid != $this->dict_rule[ $rule ] ) continue;
1161
- foreach ( $values as $name => $val ):
1162
- if ( 'i' == $name || $val != $valid ) continue;
1163
- $selarr = $this->denorm_query_sel( $qsid );
1164
- $valarr = $this->denorm_sel_val( $qsid );
1165
- $value_query_arr[ $rule ][ $selarr[ 'query' ] ][ $qsid ] = $valarr;
 
 
 
 
1166
  endforeach;
1167
  endforeach;
1168
  endforeach;
 
1169
  return $value_query_arr;
1170
  }
1171
 
1172
- /*
1173
  * denorm_query_sel
1174
  * Return id, query and selector values of a specific qsid (query-selector ID)
1175
  */
@@ -1186,7 +1489,7 @@ class ChildThemeConfiguratorCSS {
1186
  );
1187
  }
1188
 
1189
- /*
1190
  * denorm_sel_val
1191
  * Return array of rules, and values matching specific qsid (query-selector ID)
1192
  * grouped by query, selector
@@ -1197,22 +1500,67 @@ class ChildThemeConfiguratorCSS {
1197
  $rulearr = array_flip( $this->dict_rule );
1198
  if ( isset( $this->val_ndx[ $qsid ] ) && is_array( $this->val_ndx[ $qsid ] ) ):
1199
  foreach ( $this->val_ndx[ $qsid ] as $ruleid => $values ):
1200
- foreach ( $values as $name => $val ):
1201
- if ( 'i_parnt' == $name || 'i_child' == $name ):
1202
- $selarr[ 'value' ][ $rulearr[ $ruleid ] ][ $name ] = ( empty( $val ) ? 0 : 1 );
1203
- elseif ( !isset( $valarr[ $val ] ) || '' === $valarr[ $val ] ):
1204
- continue;
1205
- else:
1206
- $selarr[ 'value' ][ $rulearr[ $ruleid ] ][ $name ] = $valarr[ $val ];
 
 
 
 
1207
  endif;
1208
  endforeach;
1209
- // add load order
1210
  endforeach;
1211
  endif;
1212
  return $selarr;
1213
  }
1214
 
1215
- /*
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1216
  * denorm_sel_ndx
1217
  * Return denormalized array containing query and selector heirarchy
1218
  */
@@ -1225,13 +1573,13 @@ class ChildThemeConfiguratorCSS {
1225
  $sel_ndx_norm[ $queryarr[ $queryid ] ][ $selarr[ $selid ] ] = $qsid;
1226
  endforeach;
1227
  endforeach;
1228
- return empty( $query ) ? array_keys( $sel_ndx_norm ) : $sel_ndx_norm[ $query ];
1229
  }
1230
 
1231
- /*
1232
  * is_important
1233
- * Strip important flag from value ref and return boolean
1234
- * Value is updated because it is a ref
1235
  */
1236
  function is_important( &$value ) {
1237
  $important = 0;
@@ -1239,7 +1587,7 @@ class ChildThemeConfiguratorCSS {
1239
  return $important;
1240
  }
1241
 
1242
- /*
1243
  * sort_queries
1244
  * De-normalize query data and return array sorted as follows:
1245
  * base
@@ -1266,6 +1614,18 @@ class ChildThemeConfiguratorCSS {
1266
  return $queries;
1267
  }
1268
 
 
 
 
 
 
 
 
 
 
 
 
 
1269
  // sort selectors based on dict_seq if exists, otherwise qsid
1270
  function cmp_seq( $a, $b ) {
1271
  $cmpa = isset( $this->dict_seq[ $a ] ) ? $this->dict_seq[ $a ] : $a;
@@ -1274,7 +1634,7 @@ class ChildThemeConfiguratorCSS {
1274
  return ( $cmpa < $cmpb ) ? -1 : 1;
1275
  }
1276
 
1277
- /*
1278
  * obj_to_utf8
1279
  * sets object data to UTF8
1280
  * flattens to array
@@ -1288,16 +1648,19 @@ class ChildThemeConfiguratorCSS {
1288
  else
1289
  return is_null( $data ) ? '' : utf8_encode( $data );
1290
  }
 
1291
  // convert ascii character into decimal value
1292
  function to_ascii( $matches ) {
1293
  return ord( $matches[ 0 ] );
1294
  }
 
1295
  // convert decimal value into ascii character
1296
  function from_ascii( $matches ) {
1297
  return chr( $matches[ 0 ] );
1298
  }
1299
 
1300
- /* is_file_ok
 
1301
  * verify file exists and is in valid location
1302
  */
1303
  function is_file_ok( $stylesheet, $permission = 'read' ) {
@@ -1331,7 +1694,9 @@ class ChildThemeConfiguratorCSS {
1331
  $this->ctc()->debug( $stylesheet . ' is not in wp folders!', __FUNCTION__ );
1332
  return FALSE;
1333
  }
1334
- /* normalize_color
 
 
1335
  * Sets hex string to lowercase and shortens to 3 char format if possible
1336
  */
1337
  function normalize_color( $value ) {
@@ -1339,9 +1704,9 @@ class ChildThemeConfiguratorCSS {
1339
  $value = preg_replace( "/#([0-9A-F])\\1([0-9A-F])\\2([0-9A-F])\\3/i", "#$1$2$3", $value );
1340
  return $value;
1341
  }
 
1342
  // callback for normalize_color regex
1343
  function tolower( $matches ) {
1344
  return '#' . strtolower( $matches[ 1 ] );
1345
  }
1346
- }
1347
- ?>
5
  /*
6
  Class: ChildThemeConfiguratorCSS
7
  Plugin URI: http://www.childthemeconfigurator.com/
8
+ Description: Handles all CSS input, output, parsing, normalization and storage
9
+ Version: 1.7.5
10
  Author: Lilaea Media
11
  Author URI: http://www.lilaeamedia.com/
12
  Text Domain: chld_thm_cfg
51
  var $child_version; // stylesheet version
52
  var $max_sel;
53
  var $vendorrule = array(
54
+ 'box\-sizing',
55
+ 'font\-smoothing',
56
+ 'border(\-(top|right|bottom|left))*\-radius',
57
+ 'box\-shadow',
58
  'transition',
59
+ 'transition\-property',
60
+ 'transition\-duration',
61
+ 'transition\-timing\-function',
62
+ 'transition\-delay',
63
+ 'hyphens',
64
  'transform'
65
  );
66
  var $configvars = array(
135
  $this->recent = array();
136
  $this->imports = array( 'child' => array(), 'parnt' => array() );
137
  }
138
+
139
  // helper function to globalize ctc object
140
  function ctc() {
141
  return ChildThemeConfigurator::ctc();
142
  }
143
+
144
  // loads current ctc config data into local memory
145
  function load_config() {
146
  $option = CHLD_THM_CFG_OPTIONS . apply_filters( 'chld_thm_cfg_option', '' );
159
  return FALSE;
160
  endif;
161
  }
162
+
163
  // writes ctc config data to options api
164
  function save_config( $override = NULL ) {
165
  if ( isset( $override ) ) $option = $override;
264
  $this->{ $prop } = $value;
265
  else return FALSE;
266
  }
267
+
268
  // formats css string for accurate parsing
269
  function normalize_css() {
270
  if ( preg_match( "/(\}[\w\#\.]|; *\})/", $this->styles ) ): // prettify compressed CSS
274
  $this->styles = preg_replace( "/\s*\}\s*/s", "\n}\n", $this->styles ); // close brace
275
  endif;
276
  }
277
+
278
  // creates header comments for stylesheet
279
  function get_css_header() {
280
  $parnt = $this->get_prop( 'parnt' );
291
  . '*/' . LF . LF . '@charset "UTF-8";' . LF . LF
292
  . ( 'import' == $this->enqueue ? '@import url(\'../' . $parnt . '/style.css\');' . LF : '' );
293
  }
294
+
295
  // formats file path for child theme file
296
  function get_child_target( $file = 'style.css' ) {
297
  return trailingslashit( get_theme_root() ) . trailingslashit( $this->get_prop( 'child' ) ) . $file;
298
  }
299
+
300
  // formats file path for parent theme file
301
  function get_parent_source( $file = 'style.css' ) {
302
  return trailingslashit( get_theme_root() ) . trailingslashit( $this->get_prop( 'parnt' ) ) . $file;
303
  }
304
+
305
+ /**
306
+ * get_dict_id
307
+ * lookup function retrieves normalized id from string input
308
+ * automatically adds to dictionary if it does not exist
309
+ * incrementing key value for dictionary
310
+ */
311
+ function get_dict_id( $dict, $value ) {
312
+ $property = 'dict_' . $dict;
313
+ $key = $dict . 'key';
314
+ if ( !isset( $this->{ $property }[ $value ] ) )
315
+ // add value to index
316
+ $this->{ $property }[ $value ] = ++$this->{ $key };
317
+ return $this->{ $property }[ $value ];
318
+ }
319
+
320
+ /**
321
+ * get_qsid
322
+ * query/selector id is the combination of two dictionary values
323
+ * also throttles parsing if memory limit is reached
324
+ */
325
+ function get_qsid( $query, $sel ) {
326
+ $q = $this->get_dict_id( 'query', $query );
327
+ $s = $this->get_dict_id( 'sel', $sel );
328
+ if ( !isset( $this->sel_ndx[ $q ][ $s ] ) ):
329
+ // stop parsing if limit is reached to prevent out of memory on serialize
330
+ if ( $this->qskey >= $this->ctc()->sel_limit ):
331
+ $this->max_sel = 1;
332
+ $this->ctc()->debug( 'Maximum num selectors reached ( limit: ' . $this->ctc()->sel_limit . ' )', __FUNCTION__ );
333
+ return FALSE;
334
+ endif;
335
+ // increment key number
336
+ $this->sel_ndx[ $q ][ $s ] = ++$this->qskey;
337
+ $this->dict_qs[ $this->qskey ][ 's' ] = $s;
338
+ $this->dict_qs[ $this->qskey ][ 'q' ] = $q;
339
+ // update sequence for this selector if this is a later instance to keep cascade priority
340
+ if ( !isset( $this->dict_seq[ $this->qskey ] ) )
341
+ $this->dict_seq[ $this->qskey ] = $this->qskey;
342
+
343
+ endif;
344
+ return $this->sel_ndx[ $q ][ $s ];
345
+ }
346
+
347
  /**
348
  * update_arrays
349
  * accepts CSS properties as raw strings and normilizes into
350
  * CTC object arrays, creating update cache in the process.
351
+ * ( Update cache is returned to UI via AJAX to refresh page )
352
+ * This has been refactored in v1.7.5 to accommodate multiple values per property.
353
+ * @param $template parnt or child
354
+ * @param $query media query
355
+ * @param $sel selector
356
+ * @param $rule property (rule)
357
+ * @param $value individual value ( property has array of values )
358
+ * @param $important important flag for value
359
+ * @param $rulevalid unique id of value for property
360
+ * @param $reset clear current values to prevent multiple values from being generated from Raw CSS post input data
361
+ * @return $qsid query/selector id for this entry
362
  */
363
+ function update_arrays(
364
+ $template,
365
+ $query,
366
+ $sel,
367
+ $rule = NULL,
368
+ $value = NULL,
369
+ $important = 0,
370
+ $rulevalid = NULL,
371
+ $reset = FALSE
372
+ ) {
373
  if ( $this->max_sel ) return;
374
  if ( FALSE === strpos( $query, '@' ) ):
375
  $query = 'base';
376
  endif;
377
  // normalize selector styling
378
  $sel = implode( ', ', preg_split( '#\s*,\s*#s', trim( $sel ) ) );
379
+ if ( !( $qsid = $this->get_qsid( $query, $sel ) ) ) return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
380
 
 
 
 
381
  // set data and value
382
  if ( $rule ):
383
+ // get ids and quit if max is reached ( get_qsid handles )
384
+ $ruleid = $this->get_dict_id( 'rule', $rule );
385
+ $valid = $this->get_dict_id( 'val', $value );
386
+
387
+ /**
388
+ * v1.7.5
389
+ * modify existing data sructure to allow multiple property values
390
+ */
391
 
392
+ // create empty array if reset is TRUE
393
+ // OR IF ruleval array does not exist
394
+ if ( $reset || !isset( $this->val_ndx[ $qsid ][ $ruleid ][ $template ] )
395
+ || !is_array( $this->val_ndx[ $qsid ][ $ruleid ][ $template ] ) )
396
+ $this->val_ndx[ $qsid ][ $ruleid ][ $template ] = array();
397
+ $this->convert_ruleval_array( $this->val_ndx[ $qsid ][ $ruleid ] );
398
+ // rulevalid passed
399
+ if ( isset( $rulevalid ) ):
400
+ $this->unset_rule_value( $this->val_ndx[ $qsid ][ $ruleid ][ $template ], $rulevalid );
401
+ // value empty?
402
+ if ( '' === $value ):
403
+ // value exist?
404
+ elseif ( $id = $this->rule_value_exists( $this->val_ndx[ $qsid ][ $ruleid ][ $template ], $valid ) ):
405
+ $this->unset_rule_value( $this->val_ndx[ $qsid ][ $ruleid ][ $template ], $id );
406
+ $this->update_rule_value( $this->val_ndx[ $qsid ][ $ruleid ][ $template ], $rulevalid, $valid, $important );
407
+ // update new value
408
+ else:
409
+ $this->update_rule_value( $this->val_ndx[ $qsid ][ $ruleid ][ $template ], $rulevalid, $valid, $important );
410
+ endif;
411
+ // rulevalid not passed
412
+ else:
413
+ // value exist?
414
+ if ( $id = $this->rule_value_exists( $this->val_ndx[ $qsid ][ $ruleid ][ $template ], $valid ) ):
415
+ $this->unset_rule_value( $this->val_ndx[ $qsid ][ $ruleid ][ $template ], $id );
416
+ $this->update_rule_value( $this->val_ndx[ $qsid ][ $ruleid ][ $template ], $id, $valid, $important );
417
+ // get new id and update new value
418
+ else:
419
+ $id = $this->get_rule_value_id( $this->val_ndx[ $qsid ][ $ruleid ][ $template ] );
420
+ $this->update_rule_value( $this->val_ndx[ $qsid ][ $ruleid ][ $template ], $id, $valid, $important );
421
+ endif;
422
+ endif;
423
+ // return query selector id
424
  return $qsid;
425
  endif;
426
  }
427
 
428
+ /*
429
+ * rule_value_exists
430
+ * Determine if a value already exists for a property
431
+ * and return its id
432
+ */
433
+ function rule_value_exists( &$arr, $valid ) {
434
+ foreach ( $arr as $valarr ):
435
+ if ( isset( $valarr[ 0 ] ) && isset( $valarr[ 2 ] ) && $valid == $valarr[ 0 ] ):
436
+ return $valarr[ 2 ];
437
+ endif;
438
+ endforeach;
439
+ return FALSE;
440
+ }
441
+
442
+ /*
443
+ * get_rule_value_id
444
+ * Generate a new rulevalid by iterating existing ids
445
+ * and returning the next in sequence
446
+ */
447
+ function get_rule_value_id( &$arr ) {
448
+ $newid = 1;
449
+ foreach ( $arr as $valarr )
450
+ if ( isset( $valarr[ 2 ] ) && $valarr[ 2 ] >= $newid ) $newid = $valarr[ 2 ] + 1;
451
+ return $newid;
452
+ }
453
+
454
+ /*
455
+ * update_rule_value
456
+ * Generate a new value subarray
457
+ */
458
+ function update_rule_value( &$arr, $id, $valid, $important ) {
459
+ $arr[] = array(
460
+ $valid,
461
+ $important,
462
+ $id,
463
+ );
464
+ }
465
+
466
+ /*
467
+ * unset_rule_value
468
+ * Delete (splice) old value subarray from values
469
+ */
470
+ function unset_rule_value( &$arr, $id ) {
471
+ $index = 0;
472
+ foreach ( $arr as $valarr ):
473
+ if ( $id == $valarr[ 2 ] ):
474
+ //echo 'found ' . $valarr[ 2 ] . '(index ' . $index . " )\n";
475
+ array_splice( $arr, $index, 1 );
476
+ break;
477
+ endif;
478
+ ++$index;
479
+ endforeach;
480
+ }
481
+
482
+ /*
483
+ * prune_if_empty
484
+ * Automatically cleans up hierarchies when no values exist
485
+ * in either parent or child for a given selector.
486
+ */
487
  function prune_if_empty( $qsid ) {
488
+ $empty = $this->get_dict_id( 'val', '' );
 
489
  foreach ( $this->val_ndx[ $qsid ] as $ruleid => $arr ):
490
+ foreach ( array( 'child', 'parnt' ) as $template ):
491
+ if ( isset( $arr[ $template ] ) ):
492
+ // v1.7.5: don't prune until converted to multi value format
493
+ if ( !is_array( $arr[ $template ] ) ) return FALSE;
494
+ // otherwise check each value, if not empty return false
495
+ foreach ( $arr[ $template ] as $valarr )
496
+ if ( $empty != $valarr[ 0 ] ) return FALSE;
497
+ endif;
498
+ endforeach;
499
  endforeach;
500
  // no values, prune from sel index, val index and qs dict data ( keep other dictionary records )
501
  unset( $this->sel_ndx[ $this->dict_qs[ $qsid ][ 'q' ] ][ $this->dict_qs[ $qsid ][ 's' ] ] );
502
  unset( $this->val_ndx[ $qsid ] );
503
  unset( $this->dict_qs[ $qsid ] );
504
+ unset( $this->dict_seq[ $qsid ] );
505
  }
506
 
507
+ /**
508
+ * recurse_directory
509
  * searches filesystem for valid files based on parameters and returns array of filepaths.
510
+ * Core WP recurse function is not used because we require logic specific to CTC.
511
  */
512
  function recurse_directory( $rootdir, $ext = 'css', $all = FALSE ) {
513
+ // make sure we are only recursing theme and plugin files
514
+ if ( !$this->is_file_ok( $rootdir, 'search' ) )
515
+ return array();
516
  $files = array();
517
  $dirs = array( $rootdir );
518
  $loops = 0;
519
+ if ( 'img' == $ext )
 
520
  $ext = '(' . implode( '|', array_keys( $this->ctc()->imgmimes ) ) . ')';
 
521
  while( count( $dirs ) && $loops < CHLD_THM_CFG_MAX_RECURSE_LOOPS ): // failsafe valve
522
  $loops++;
523
  $dir = array_shift( $dirs );
527
  $filepath = trailingslashit( $dir ) . $file;
528
  if ( is_dir( $filepath ) ):
529
  array_unshift( $dirs, $filepath );
530
+ if ( $all ):
531
  $files[] = $filepath;
532
  endif;
533
  elseif ( is_file( $filepath ) && ( $all || preg_match( "/\.".$ext."$/i", $filepath ) ) ):
539
  endwhile;
540
  return $files;
541
  }
542
+
543
+ /**
544
  * parse_post_data
545
  * Parse user form input into separate properties and pass to update_arrays
546
+ * FIXME - this function has grown too monolithic - refactor and componentize
547
  */
548
  function parse_post_data() {
549
  $this->cache_updates = TRUE;
550
  if ( isset( $_POST[ 'ctc_new_selectors' ] ) ):
551
  $this->styles = $this->parse_css_input( LF . $_POST[ 'ctc_new_selectors' ] );
552
  $this->parse_css( 'child',
553
+ isset( $_POST[ 'ctc_sel_ovrd_query' ] ) ? trim( $_POST[ 'ctc_sel_ovrd_query' ] ) : NULL,
554
+ FALSE,
555
+ '',
556
+ TRUE
557
+ );
558
  elseif ( isset( $_POST[ 'ctc_child_imports' ] ) ):
559
  $this->imports[ 'child' ] = array();
560
  $this->styles = $this->parse_css_input( $_POST[ 'ctc_child_imports' ] );
590
  endforeach;
591
  $parts = array();
592
  foreach ( preg_grep( '#^ctc_(ovrd|\d+)_child#', array_keys( $_POST ) ) as $post_key ):
593
+ if ( preg_match( '#^ctc_(ovrd|\d+)_child_([\w\-]+?)_(\d+?)_(\d+?)(_(.+))?$#', $post_key, $matches ) ):
594
+ $valid = $matches[ 1 ];
595
+ $rule = $matches[ 2 ];
596
  if ( NULL == $rule || !isset( $this->dict_rule[ $rule ] ) ) continue;
597
+ $ruleid = $this->dict_rule[ $rule ];
598
+ $qsid = $matches[ 3 ];
599
+ $rulevalid = $matches[ 4 ];
600
+ $value = $this->normalize_color( $this->sanitize( $this->parse_css_input( $_POST[ $post_key ] ) ) );
601
+ $important = $this->is_important( $value );
602
+ if ( !empty( $_POST[ 'ctc_' . $valid . '_child_' . $rule . '_i_' . $qsid . '_' . $rulevalid ] ) ) $important = 1;
603
  $selarr = $this->denorm_query_sel( $qsid );
604
+ if ( !empty( $matches[ 6 ] ) ):
605
+ $parts[ $qsid ][ $rule ][ 'values' ][ $rulevalid ][ $matches[ 6 ] ] = $value;
606
+ $parts[ $qsid ][ $rule ][ 'values' ][ $rulevalid ][ 'important' ] = $important;
607
  $parts[ $qsid ][ $rule ][ 'query' ] = $selarr[ 'query' ];
608
  $parts[ $qsid ][ $rule ][ 'selector' ] = $selarr[ 'selector' ];
609
  else:
610
  if ( $newselector && $newselector != $selarr[ 'selector' ] ):
611
  // If this is a renamed selector, add new selector to array
612
+ $newqsid = $this->update_arrays(
613
+ 'child',
614
+ $selarr[ 'query' ],
615
+ $newselector,
616
+ $rule,
617
+ trim( $value ),
618
+ $important,
619
+ $rulevalid
620
+ );
621
  // clear the original selector's child value:
622
+ $this->update_arrays(
623
+ 'child',
624
+ $selarr[ 'query' ],
625
+ $selarr[ 'selector' ],
626
+ $rule,
627
+ '',
628
+ 0,
629
+ $rulevalid
630
+ );
631
+ $this->dict_seq[ $newqsid ] = $this->dict_seq[ $qsid ];
632
  else:
633
  // otherwise, just update with the new values:
634
+ $this->update_arrays(
635
+ 'child',
636
+ $selarr[ 'query' ],
637
+ $selarr[ 'selector' ],
638
+ $rule,
639
+ trim( $value ),
640
+ $important,
641
+ $rulevalid
642
+ );
643
  endif;
644
  endif;
645
  endif;
646
  endforeach;
647
+ /**
648
+ * Inputs for border and background-image are broken into multiple "rule parts"
649
+ * With the addition of multiple property values in v1.7.5, the parts loop
650
+ * has been modified to segment the parts into rulevalids under a new 'values' array.
651
+ * The important flag has also been moved into the parts array.
652
+ */
653
+ foreach ( $parts as $qsid => $rules ):
654
+ foreach ( $rules as $rule => $rule_arr ):
655
+ // new 'values' array to segment parts into rulevalids
656
+ foreach ( $rule_arr[ 'values' ] as $rulevalid => $rule_part ):
657
+ if ( 'background' == $rule ):
658
+ $value = $rule_part[ 'background_url' ];
659
+ elseif ( 'background-image' == $rule ):
660
+ if ( empty( $rule_part[ 'background_url' ] ) ):
661
+ if ( empty( $rule_part[ 'background_color2' ] ) ):
662
+ $value = '';
663
+ else:
664
+ if ( empty( $rule_part[ 'background_origin' ] ) )
665
+ $rule_part[ 'background_origin' ] = 'top';
666
+ if ( empty( $rule_part[ 'background_color1' ] ) )
667
+ $rule_part[ 'background_color1' ] = $rule_part[ 'background_color2' ];
668
+ $value = implode( ':', array(
669
+ $rule_part[ 'background_origin' ],
670
+ $rule_part[ 'background_color1' ], '0%',
671
+ $rule_part[ 'background_color2' ], '100%'
672
+ ) );
673
+ endif;
674
  else:
675
+ $value = $rule_part[ 'background_url' ];
 
 
 
 
676
  endif;
677
+ elseif ( preg_match( '#^border(\-(top|right|bottom|left))?$#', $rule ) ):
678
+ if ( empty( $rule_part[ 'border_width' ] ) && !empty( $rule_part[ 'border_color' ] ) )
679
+ $rule_part[ 'border_width' ] = '1px';
680
+ if ( empty( $rule_part[ 'border_style' ] ) && !empty( $rule_part[ 'border_color' ] ) )
681
+ $rule_part[ 'border_style' ] = 'solid';
682
+ $value = implode( ' ', array(
683
+ $rule_part[ 'border_width' ],
684
+ $rule_part[ 'border_style' ],
685
+ $rule_part[ 'border_color' ]
686
+ ) );
687
  else:
688
+ $value = '';
689
  endif;
690
+ if ( $newselector && $newselector != $rule_arr[ 'selector' ] ):
691
+ // If this is a renamed selector, add new selector to array
692
+ $newqsid = $this->update_arrays(
693
+ 'child',
694
+ $rule_arr[ 'query' ],
695
+ $newselector,
696
+ $rule,
697
+ trim( $value ),
698
+ $rule_part[ 'important' ],
699
+ $rulevalid
700
+ );
701
+ // clear the original selector's child value:
702
+ $this->update_arrays(
703
+ 'child',
704
+ $rule_arr[ 'query' ],
705
+ $rule_arr[ 'selector' ],
706
+ $rule,
707
+ '',
708
+ 0,
709
+ $rulevalid
710
+ );
711
+ else:
712
+ // otherwise, just update with the new values:
713
+ $this->update_arrays(
714
+ 'child',
715
+ $rule_arr[ 'query' ],
716
+ $rule_arr[ 'selector' ],
717
+ $rule,
718
+ trim( $value ),
719
+ $rule_part[ 'important' ],
720
+ $rulevalid
721
+ );
722
+ endif;
723
+ endforeach;
724
  endforeach;
725
+ endforeach;
726
  // if this is a renamed selector, update sequence dict
727
  if ( $newqsid ):
728
  if ( !isset( $this->dict_seq[ $newqsid ] ) )
729
  $this->dict_seq[ $newqsid ] = $this->dict_seq[ $qsid ];
 
 
730
  endif;
731
+ // remove if all values have been cleared
732
+ $this->prune_if_empty( $qsid );
733
+ $qsid = $newqsid ? $newqsid : $qsid;
734
  // return updated qsid to browser to update form
735
  if ( $this->ctc()->cache_updates ):
736
  $this->ctc()->updates[] = array(
747
  add_action( 'chld_thm_cfg_addl_files', array( $this->ctc(), 'enqueue_parent_css' ), 15, 2 );
748
  }
749
 
750
+ /**
751
  * parse_css_input
752
  * Normalize raw user CSS input so that the parser can read it.
 
753
  */
754
  function parse_css_input( $styles ) {
755
  return $this->repl_octal( stripslashes( $this->esc_octal( $styles ) ) );
756
  }
757
+
758
  // strips non printables and potential commands
759
  function sanitize( $styles ) {
760
  return sanitize_text_field( preg_replace( '/[^[:print:]]/', '', $styles ) );
761
  }
762
+
763
  // escapes octal values in input to allow for specific ascii strings in content rule
764
  function esc_octal( $styles ){
765
  return preg_replace( "#(['\"])\\\\([0-9a-f]{4})(['\"])#i", "$1##bs##$2$3", $styles );
766
  }
767
+
768
  // unescapes octal values for writing specific ascii strings in content rule
769
  function repl_octal( $styles ) {
770
  return str_replace( "##bs##", "\\", $styles );
771
  }
772
 
773
+ /**
774
  * parse_css_file
775
  * reads stylesheet to get WordPress meta data and passes rest to parse_css
776
  */
790
  preg_match( $regex, $this->styles, $matches );
791
  $child_name = $this->get_prop( 'child_name' );
792
  if ( !empty( $matches[ 1 ] ) && 'child' == $template && empty( $child_name ) ) $this->set_prop( 'child_name', $matches[ 1 ] );
793
+ $this->parse_css(
794
+ $cfgtemplate ? $cfgtemplate : $template,
795
+ NULL,
796
+ TRUE,
797
+ $this->ctc()->normalize_path( dirname( $file ) )
798
+ );
799
  }
800
 
801
  // loads raw css file into local memory
828
  endif;
829
  }
830
 
831
+ /**
832
  * parse_css
833
  * Accepts raw CSS as text and parses into individual properties.
834
+ * FIXME - this function has grown too monolithic - refactor and componentize
835
  */
836
+ function parse_css( $template, $basequery = NULL, $parse_imports = TRUE, $relpath = '', $reset = FALSE ) {
837
  if ( FALSE === strpos( $basequery, '@' ) ):
838
  $basequery = 'base';
839
  endif;
867
  ) as $regex ): // (((?!\@media).) backreference too memory intensive - rolled back in v 1.4.8.1
868
  preg_match_all( $regex, $this->styles, $matches );
869
  foreach ( $matches[ 1 ] as $segment ):
870
+ $ruleset[ trim( $segment ) ] = array_shift( $matches[ 2 ] )
871
+ . ( isset( $ruleset[ trim( $segment ) ] ) ?
872
+ $ruleset[ trim( $segment ) ] : '' );
873
  endforeach;
874
  // stripping rulesets leaves base styles
875
  $this->styles = preg_replace( $regex, '', $this->styles );
886
  preg_match_all( $regex, $segment, $matches );
887
  foreach( $matches[ 1 ] as $sel ):
888
  $stuff = array_shift( $matches[ 2 ] );
889
+ $this->update_arrays(
890
+ $template,
891
+ $query,
892
+ $sel
893
+ );
894
  // handle base64 data
895
  $stuff = preg_replace( '#data:([^;]+?);([^\)]+?)\)#s', "data:$1%%semi%%$2)", $stuff );
896
+ // rule semaphore makes sure rules are only reset the first time they appear
897
+ $resetrule = array();
898
  foreach ( explode( ';', $stuff ) as $ruleval ):
 
 
 
 
899
  if ( FALSE === strpos( $ruleval, ':' ) ) continue;
900
  list( $rule, $value ) = explode( ':', $ruleval, 2 );
901
  $rule = trim( $rule );
928
  // normalize gradients
929
  if ( FALSE !== strpos( $value, 'gradient' ) ):
930
  if ( FALSE !== strpos( $rule, 'filter' ) ):
931
+ // treat as background-image, we'll add filter rule later
932
  $rule = 'background-image';
933
+ continue;
934
  endif;
935
  if ( FALSE !== strpos( $value, 'webkit-gradient' ) ) continue; // bail on legacy webkit, we'll add it later
936
  $value = $this->encode_gradient( $value );
939
  $rule = preg_replace( '#(\-(o|ms|moz|webkit)\-)?(' . implode( '|', $this->vendorrule ) . ')#', "$3", $rule );
940
  if ( 'parnt' == $template && 'background-image' == $rule && strstr( $value, 'url(' ) )
941
  $value = $this->convert_rel_url( $value, $relpath );
942
+ // by default, set semaphore true to allow multiple values
943
+ if ( !$reset ) $resetrule[ $rule ] = TRUE;
944
+
945
+ $qsid = $this->update_arrays(
946
+ $template,
947
+ $query,
948
+ $sel,
949
+ $rule,
950
+ $value,
951
+ $important,
952
+ NULL, // no rulevalid is passed when parsing from css (vs post input data)
953
+ empty( $resetrule[ $rule ] ) // if rule semaphore is TRUE, reset will be FALSE
954
+ );
955
+ $resetrule[ $rule ] = TRUE; // set rule semaphore so if same rule occurs again, it is not reset
956
  endforeach;
957
  endforeach;
958
  endforeach;
987
  return $newvalue;
988
  }
989
 
990
+ /**
991
  * write_css
992
  * converts normalized CSS object data into stylesheet.
993
  * Preserves selector sequence and !important flags of parent stylesheet.
994
  * @media query blocks are sorted using internal heuristics (see sort_queries)
995
  * New selectors are appended to the end of each media query block.
996
+ * FIXME - this function has grown too monolithic - refactor and componentize
997
  */
998
  function write_css( $backup = FALSE ) {
999
  // write new stylesheet
1010
  uasort( $selectors, array( $this, 'cmp_seq' ) );
1011
  if ( 'base' != $query ) $sel_output .= $query . ' {' . LF;
1012
  foreach ( $selectors as $selid => $qsid ):
 
 
1013
  if ( !empty( $this->val_ndx[ $qsid ] ) ):
1014
+ $sel = $selarr[ $selid ];
1015
+ $shorthand = array();
1016
+ $rule_output = array();
1017
+ foreach ( $this->val_ndx[ $qsid ] as $ruleid => $temparr ):
1018
+ // normalize values for backward compatability
1019
+ $this->convert_ruleval_array( $temparr );
1020
+ if ( isset( $temparr[ 'child' ] ) &&
1021
+ ( !isset( $temparr[ 'parnt' ] ) || $temparr[ 'parnt' ] != $temparr[ 'child' ] ) ):
1022
+ foreach ( $temparr[ 'child' ] as $rulevalarr ):
1023
+ $this->add_vendor_rules(
1024
+ $rule_output,
1025
+ $shorthand,
1026
+ $rulearr[ $ruleid ],
1027
+ $valarr[ $rulevalarr[ 0 ] ],
1028
+ $rulevalarr[ 1 ],
1029
+ $rulevalarr[ 2 ]
1030
+ );
1031
+ endforeach;
1032
+ /**
1033
+ * for testing
1034
+ else:
1035
+ foreach ( $temparr[ 'parnt' ] as $rulevalarr ):
1036
+ $this->add_vendor_rules(
1037
+ $rule_output,
1038
+ $shorthand,
1039
+ $rulearr[ $ruleid ],
1040
+ $valarr[ $rulevalarr[ 0 ] ],
1041
+ $rulevalarr[ 1 ],
1042
+ $rulevalarr[ 2 ]
1043
+ );
1044
+ endforeach;
1045
+ */
1046
  endif;
1047
  endforeach;
1048
+ /** FIXME ** need better way to sort rules and multiple values ***/
1049
+ $this->encode_shorthand( $shorthand, $rule_output );
1050
+ if ( count( $rule_output ) ):
1051
+ // show load order
1052
+ $sel_output .= isset( $this->dict_seq[ $qsid ] )?'/*' . $this->dict_seq[ $qsid ] . '*/' . LF:'';
1053
+ $sel_output .= $sel . ' {' . LF . $this->stringify_rule_output( $rule_output ) . '}' . LF;
1054
+ $has_selector = 1;
1055
  endif;
1056
  endif;
1057
  endforeach;
1089
  return FALSE;
1090
  }
1091
 
1092
+ function stringify_rule_output( &$rule_output ) {
1093
+ $output = '';
1094
+ asort( $rule_output );
1095
+ //print_r( $rule_output );
1096
+ foreach ( $rule_output as $rule => $sortstr )
1097
+ $output .= ' ' . $rule . ";\n";
1098
+ return $output;
1099
+ }
1100
+
1101
+ function sortstr( $rule, $rulevalid ) {
1102
+ return substr( "0000" . $this->get_dict_id( 'rule', $rule ), -4) . substr( "00" . $rulevalid, -2 );
1103
+ }
1104
+
1105
+ /**
1106
+ * encode_shorthand
1107
+ * converts CTC long syntax into CSS shorthand
1108
+ * v1.7.5 refactored for multiple values per property
1109
+ * FIXME - somehow condense all these foreach loops?
1110
+ */
1111
+ function encode_shorthand( $shorthand, &$rule_output ) {
1112
+ //print_r( $shorthand );
1113
+ foreach ( $shorthand as $property => $sides ):
1114
+ if ( isset( $sides[ 'top' ] ) ):
1115
+ foreach ( $sides[ 'top' ] as $tval => $tarr ):
1116
+ if ( isset( $sides[ 'right' ] ) ):
1117
+ $currseq = $tarr[ 1 ];
1118
+ foreach ( $sides[ 'right' ] as $rval => $rarr ):
1119
+ // value must exist from side and priority must match all sides
1120
+ if ( isset( $sides[ 'bottom' ] ) && $tarr[ 0 ] == $rarr[ 0 ] ):
1121
+ if ( $rarr[ 1 ] > $currseq ) $currseq = $rarr[ 1 ];
1122
+ foreach ( $sides[ 'bottom' ] as $bval => $barr ):
1123
+ if ( isset( $sides[ 'left' ] ) && $tarr[ 0 ] == $barr[ 0 ] ):
1124
+ // use highest sort sequence of all sides
1125
+ if ( $barr[ 1 ] > $currseq ) $currseq = $barr[ 1 ];
1126
+ foreach ( $sides[ 'left' ] as $lval => $larr ):
1127
+ if ( $tarr[ 0 ] != $larr[ 0 ] ) continue;
1128
+ if ( $larr[ 1 ] > $currseq ) $currseq = $larr[ 1 ];
1129
+
1130
+ $combo = array(
1131
+ $tval,
1132
+ $rval,
1133
+ $bval,
1134
+ $lval,
1135
+ );
1136
+ // remove from shorthand array
1137
+ unset( $shorthand[ $property ][ 'top' ][ $tval ] );
1138
+ unset( $shorthand[ $property ][ 'right' ][ $rval ] );
1139
+ unset( $shorthand[ $property ][ 'bottom' ][ $bval ] );
1140
+ unset( $shorthand[ $property ][ 'left' ][ $lval ] );
1141
+
1142
+ // combine into shorthand syntax
1143
+ if ( $lval == $rval ) array_pop( $combo );
1144
+ if ( $bval == $tval ) array_pop( $combo );
1145
+ if ( $rval == $tval && $bval == $tval ) array_pop( $combo );
1146
+
1147
+ // set rule
1148
+ $rule_output[ $property . ': ' . implode( ' ', $combo ) . ( $tarr[ 0 ] ? ' !important' : '' ) ] = $this->sortstr( $property, $currseq );
1149
+ // reset sort sequence
1150
+ $currseq = 0;
1151
+ endforeach;
1152
+ endif;
1153
+ endforeach;
1154
+ endif;
1155
+ endforeach;
1156
+ endif;
1157
+ endforeach;
1158
+ endif;
1159
+ endforeach;
1160
+ // add remaining rules
1161
+ foreach ( $shorthand as $property => $sides ):
1162
+ foreach ( $sides as $side => $values ):
1163
+ $rule = $property . '-' . $side;
1164
+ foreach ( $values as $val => $valarr ):
1165
+ // set rule
1166
+ $rule_output[ $rule . ': ' . $val . ( $valarr[ 0 ] ? ' !important' : '' ) ] = $this->sortstr( $rule, $valarr[ 1 ] );
1167
+ endforeach;
1168
+ endforeach;
1169
+ endforeach;
1170
+ }
1171
+
1172
+ /**
1173
  * add_vendor_rules
1174
+ * Applies vendor prefixes to rules/values and separates out shorthand properties .
1175
+ * These are based on commonly used practices and not all vendor prefixes are supported.
1176
  * TODO: verify this logic against vendor and W3C documentation
1177
  */
1178
+ function add_vendor_rules( &$rule_output, &$shorthand, $rule, $value, $important, $rulevalid ) {
1179
+ if ( '' === trim( $value ) ) return;
1180
  if ( 'filter' == $rule && ( FALSE !== strpos( $value, 'progid:DXImageTransform.Microsoft.Gradient' ) ) ) return;
1181
  $importantstr = $important ? ' !important' : '';
1182
  if ( preg_match( "/^(margin|padding)\-(top|right|bottom|left)$/", $rule, $matches ) ):
1183
+ $shorthand[ $matches[ 1 ] ][ $matches[ 2 ] ][ $value ] = array(
1184
+ $important,
1185
+ $rulevalid,
1186
+ );
1187
+ return;
1188
  elseif ( preg_match( '/^(' . implode( '|', $this->vendorrule ) . ')$/', $rule ) ):
1189
  foreach( array( 'moz', 'webkit', 'o' ) as $prefix ):
1190
+ $rule_output[ '-' . $prefix . '-' . $rule . ': ' . $value . $importantstr ] = $this->sortstr( $rule, $rulevalid++ );
1191
  endforeach;
1192
+ $rule_output[ $rule . ': ' . $value . $importantstr ] = $this->sortstr( $rule, $rulevalid );
1193
  elseif ( 'background-image' == $rule ):
1194
  // gradient?
1195
 
1196
  if ( $gradient = $this->decode_gradient( $value ) ):
1197
  // standard gradient
1198
  foreach( array( 'moz', 'webkit', 'o', 'ms' ) as $prefix ):
1199
+ $rule_output[ 'background-image: -' . $prefix . '-' . 'linear-gradient(' . $gradient[ 'origin' ] . ', '
1200
+ . $gradient[ 'color1' ] . ', ' . $gradient[ 'color2' ] . ')' . $importantstr ] = $this->sortstr( $rule, $rulevalid++ );
1201
  endforeach;
1202
  // W3C standard gradient
1203
  // rotate origin 90 degrees
1213
  endforeach;
1214
  $org = 'to ' . implode( ' ', $dirs );
1215
  endif;
1216
+ $rule_output[ 'background-image: linear-gradient(' . $org . ', '
1217
+ . $gradient[ 'color1' ] . ', ' . $gradient[ 'color2' ] . ')' . $importantstr ] = $this->sortstr( $rule, $rulevalid );
1218
 
1219
  // legacy webkit gradient - we'll add if there is demand
1220
  // '-webkit-gradient(linear,' .$origin . ', ' . $color1 . ', '. $color2 . ')';
1221
 
1222
+ /**
1223
+ * MS filter gradient - DEPRECATED in v1.7.5
1224
+ * $type = ( in_array( $gradient[ 'origin' ], array( 'left', 'right', '0deg', '180deg' ) ) ? 1 : 0 );
1225
+ * $color1 = preg_replace( "/^#/", '#00', $gradient[ 'color1' ] );
1226
+ * $rule_output[ 'filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=' . $type . ', StartColorStr="'
1227
+ * . strtoupper( $color1 ) . '", EndColorStr="' . strtoupper( $gradient[ 'color2' ] ) . '")'
1228
+ * . $importantstr ] = $this->sortstr( $rule, $rulevalid );
1229
+ */
1230
  else:
1231
  // url or other value
1232
+ $rule_output[ $rule . ': ' . $value . $importantstr ] = $this->sortstr( $rule, $rulevalid );
1233
  endif;
1234
  else:
1235
  $rule = preg_replace_callback( "/\d+/", array( $this, 'from_ascii' ), $rule );
1236
+ $rule_output[ $rule . ': ' . $value . $importantstr ] = $this->sortstr( $rule, $rulevalid );
1237
  endif;
 
1238
  }
1239
 
1240
+ /**
1241
  * normalize_background
1242
  * parses background shorthand value and returns
1243
  * normalized rule/value pairs for each property
1284
  endif;
1285
  }
1286
 
1287
+ /**
1288
  * normalize_font
1289
  * parses font shorthand value and returns
1290
  * normalized rule/value pairs for each property
1314
  endif;
1315
  }
1316
 
1317
+ /**
1318
  * normalize_margin_padding
1319
  * parses margin or padding shorthand value and returns
1320
  * normalized rule/value pairs for each property
1334
  $values[ 3 ] = $parts[ 3 ];
1335
  }
1336
 
1337
+ /**
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1338
  * encode_gradient
1339
+ * Normalize linear gradients from a bazillion formats into standard CTC syntax.
1340
+ * This has been refactored in v1.7.5 to accommodate new spectrum color picker color "names."
1341
  * Currently only supports two-color linear gradients with no inner stops.
1342
  * TODO: legacy webkit? more gradients?
1343
  */
1344
  function encode_gradient( $value ) {
1345
  // don't try this at home, kids
1346
+ $regex = '#gradient[^\)]*?\((((to )?(top|bottom|left|right)?( (top|bottom|left|right))?|\d+deg),)?([^\w\#\)]*[\'"]?(\#\w{3,8}|rgba?\([\d., ]+?\)|hsla?\([\d%., ]+?\)|[a-z]+)( [\d.]+%)?)([^\w\#\)]*[\'"]?(\#\w{3,8}|rgba?\([\d., ]+?\)|hsla?\([\d%., ]+?\)|[a-z]+)( [\d.]+%)?)([^\w\)]*gradienttype=[\'"]?(\d)[\'"]?)?[^\w\)]*\)#i';
1347
  $param = $parts = array();
1348
  preg_match( $regex, $value, $parts );
1349
+ if ( empty( $parts[ 14 ] ) ):
1350
  if ( empty( $parts[ 2 ] ) ):
1351
  $param[ 0 ] = 'top';
1352
+ elseif ( 'to ' == $parts[ 3 ] ):
1353
+
1354
+ $param[ 0 ] = ( 'top' == $parts[ 4 ] ? 'bottom' :
1355
+ ( 'left' == $parts[ 4 ] ? 'right' :
1356
+ ( 'right' == $parts[ 4 ] ? 'left' :
1357
+ 'top' ) ) ) ;
1358
  else:
1359
  $param[ 0 ] = trim( $parts[ 2 ] );
1360
  endif;
1361
+ if ( empty( $parts[ 9 ] ) ):
1362
  $param[ 2 ] = '0%';
1363
  else:
1364
+ $param[ 2 ] = trim( $parts[ 9 ] );
1365
  endif;
1366
+ if ( empty( $parts[ 12 ] ) ):
1367
  $param[ 4 ] = '100%';
1368
  else:
1369
+ $param[ 4 ] = trim( $parts[ 12 ] );
1370
  endif;
1371
+ elseif( '0' == $parts[ 14 ] ):
1372
  $param[ 0 ] = 'top';
1373
  $param[ 2 ] = '0%';
1374
  $param[ 4 ] = '100%';
1375
+ elseif ( '1' == $parts[ 14 ] ):
1376
  $param[ 0 ] = 'left';
1377
  $param[ 2 ] = '0%';
1378
  $param[ 4 ] = '100%';
1379
  endif;
1380
+ if ( isset( $parts[ 8 ] ) && isset( $parts[ 11 ] ) ):
1381
+ $param[ 1 ] = $parts[ 8 ];
1382
+ $param[ 3 ] = $parts[ 11 ];
1383
  ksort( $param );
1384
  return implode( ':', $param );
1385
+ else:
1386
+ return $value;
1387
  endif;
1388
  }
1389
 
1390
+ /**
1391
  * decode_border
1392
  * De-normalize CTC border syntax into individual properties.
1393
  */
1394
  function decode_border( $value ) {
1395
+ $parts = preg_split( '#\s+#', $value, 3 );
1396
+ if ( 1 == count( $parts ) ):
1397
  $parts[ 0 ] = $value;
1398
  $parts[ 1 ] = $parts[ 2 ] = '';
 
 
1399
  endif;
1400
  return array(
1401
  'width' => empty( $parts[ 0 ] ) ? '' : $parts[ 0 ],
1404
  );
1405
  }
1406
 
1407
+ /**
1408
  * decode_gradient
1409
  * Decode CTC gradient syntax into individual properties.
1410
  */
1422
  return FALSE;
1423
  }
1424
 
1425
+ /**
1426
  * denorm_rule_val
1427
  * Return array of unique values corresponding to specific rule
1428
+ * FIXME: only return child if no parent value exists
1429
  */
1430
  function denorm_rule_val( $ruleid ) {
1431
  $rule_sel_arr = array();
1432
  $val_arr = array_flip( $this->dict_val );
1433
+ foreach ( $this->val_ndx as $qsid => $rules ):
1434
  if ( !isset( $rules[ $ruleid ] ) ) continue;
1435
+ $this->convert_ruleval_array( $rules[ $ruleid ] );
1436
+ foreach ( array( 'parnt', 'child' ) as $template ):
1437
+ if ( isset( $rules[ $ruleid ][ $template ] ) ):
1438
+ foreach ( $rules[ $ruleid ][ $template ] as $rulevalarr ):
1439
+ $rule_sel_arr[ $rulevalarr[ 0 ] ] = $val_arr[ $rulevalarr[ 0 ] ];
1440
+ endforeach;
1441
+ endif;
1442
  endforeach;
1443
  endforeach;
1444
  return $rule_sel_arr;
1445
  }
1446
 
1447
+ /**
1448
  * denorm_val_query
1449
  * Return array of queries, selectors, rules, and values corresponding to
1450
  * specific rule/value combo grouped by query, selector
1451
+ * FIXME: only return child values corresponding to specific rulevalid of matching parent value
1452
  */
1453
  function denorm_val_query( $valid, $rule ) {
1454
  $value_query_arr = array();
1455
+ if( $thisruleid = $this->get_dict_id( 'rule', $rule ) ):
1456
  foreach ( $this->val_ndx as $qsid => $rules ):
1457
  foreach ( $rules as $ruleid => $values ):
1458
+ if ( $ruleid != $thisruleid ) continue;
1459
+ $this->convert_ruleval_array( $values );
1460
+ foreach ( array( 'parnt', 'child' ) as $template ):
1461
+ if ( isset( $values[ $template ] ) ):
1462
+ foreach ( $values[ $template ] as $rulevalarr ):
1463
+ if ( $rulevalarr[ 0 ] != $valid ) continue;
1464
+ $selarr = $this->denorm_query_sel( $qsid );
1465
+ $value_query_arr[ $rule ][ $selarr[ 'query' ] ][ $qsid ] = $this->denorm_sel_val( $qsid );
1466
+ endforeach;
1467
+ endif;
1468
  endforeach;
1469
  endforeach;
1470
  endforeach;
1471
+ endif;
1472
  return $value_query_arr;
1473
  }
1474
 
1475
+ /**
1476
  * denorm_query_sel
1477
  * Return id, query and selector values of a specific qsid (query-selector ID)
1478
  */
1489
  );
1490
  }
1491
 
1492
+ /**
1493
  * denorm_sel_val
1494
  * Return array of rules, and values matching specific qsid (query-selector ID)
1495
  * grouped by query, selector
1500
  $rulearr = array_flip( $this->dict_rule );
1501
  if ( isset( $this->val_ndx[ $qsid ] ) && is_array( $this->val_ndx[ $qsid ] ) ):
1502
  foreach ( $this->val_ndx[ $qsid ] as $ruleid => $values ):
1503
+ // convert old value to new format
1504
+ $this->convert_ruleval_array( $values );
1505
+ foreach ( array( 'parnt', 'child' ) as $template ):
1506
+ if ( isset( $values[ $template ] ) ):
1507
+ foreach ( $values[ $template ] as $rulevalarr ):
1508
+ $selarr[ 'value' ][ $rulearr[ $ruleid ] ][ $template ][] = array(
1509
+ $valarr[ $rulevalarr[ 0 ] ],
1510
+ $rulevalarr[ 1 ],
1511
+ isset( $rulevalarr[ 2 ] ) ? $rulevalarr[ 2 ] : 1,
1512
+ );
1513
+ endforeach;
1514
  endif;
1515
  endforeach;
 
1516
  endforeach;
1517
  endif;
1518
  return $selarr;
1519
  }
1520
 
1521
+ /**
1522
+ * convert and/or normalize rule/value index
1523
+ * to support multiple values per property ( rule )
1524
+ * allows backward compatility with < v1.7.5
1525
+ */
1526
+ function convert_ruleval_array( &$arr ) {
1527
+ foreach ( array( 'parnt', 'child' ) as $template ):
1528
+ // skip if empty array
1529
+ if ( !isset( $arr[ $template ] ) ) continue;
1530
+ // check if using original data structure ( value is scalar )
1531
+ if ( ! is_array( $arr[ $template ] ) ):
1532
+ /**
1533
+ * create new array to replace old scalar value
1534
+ * value structure is
1535
+ * [0] => value
1536
+ * [1] => important
1537
+ * [2] => priority
1538
+ */
1539
+ $temparr = array( array( $arr[ $template ], $arr[ 'i_' . $template ], 0, 1 ) );
1540
+ $arr[ $template ] = $temparr;
1541
+ endif;
1542
+ $newarr = array();
1543
+ // iterate each value and enforce array structure
1544
+ foreach ( $arr[ $template ] as $rulevalid => $rulevalarr ):
1545
+ // skip if empty array
1546
+ if ( empty ( $rulevalarr ) ) continue;
1547
+ //
1548
+ if ( ! is_array( $rulevalarr ) ):
1549
+ // important flag moves to individual value array
1550
+ $important = isset( $arr[ 'i_' . $template ] ) ? $arr[ 'i_' . $template ] : 0;
1551
+ unset( $arr[ 'i_' . $template ] );
1552
+ $val = (int) $rulevalarr;
1553
+ $rulevalarr = array( $val, $important, $rulevalid );
1554
+ elseif ( !isset( $rulevalarr[ 2 ] ) ):
1555
+ $rulevalarr[ 2 ] = $rulevalid;
1556
+ endif;
1557
+ $newarr[] = $rulevalarr;
1558
+ endforeach;
1559
+ $arr[ $template ] = $newarr;
1560
+ endforeach;
1561
+ }
1562
+
1563
+ /**
1564
  * denorm_sel_ndx
1565
  * Return denormalized array containing query and selector heirarchy
1566
  */
1573
  $sel_ndx_norm[ $queryarr[ $queryid ] ][ $selarr[ $selid ] ] = $qsid;
1574
  endforeach;
1575
  endforeach;
1576
+ return empty( $query ) ? array_keys( $sel_ndx_norm ) : $this->sort_selectors( $sel_ndx_norm[ $query ] );
1577
  }
1578
 
1579
+ /**
1580
  * is_important
1581
+ * Strip important flag from value reference and return boolean
1582
+ * Updating two values at once
1583
  */
1584
  function is_important( &$value ) {
1585
  $important = 0;
1587
  return $important;
1588
  }
1589
 
1590
+ /**
1591
  * sort_queries
1592
  * De-normalize query data and return array sorted as follows:
1593
  * base
1614
  return $queries;
1615
  }
1616
 
1617
+ function sort_selectors( $selarr ) {
1618
+ uksort( $selarr, array( $this, 'cmp_sel' ) );
1619
+ return $selarr;
1620
+ }
1621
+
1622
+ function cmp_sel( $a, $b ) {
1623
+ $cmpa = preg_replace( "/\W/", '', $a );
1624
+ $cmpb = preg_replace( "/\W/", '', $b );
1625
+ if ( $cmpa == $cmpb ) return 0;
1626
+ return ( $cmpa < $cmpb ) ? -1 : 1;
1627
+ }
1628
+
1629
  // sort selectors based on dict_seq if exists, otherwise qsid
1630
  function cmp_seq( $a, $b ) {
1631
  $cmpa = isset( $this->dict_seq[ $a ] ) ? $this->dict_seq[ $a ] : $a;
1634
  return ( $cmpa < $cmpb ) ? -1 : 1;
1635
  }
1636
 
1637
+ /**
1638
  * obj_to_utf8
1639
  * sets object data to UTF8
1640
  * flattens to array
1648
  else
1649
  return is_null( $data ) ? '' : utf8_encode( $data );
1650
  }
1651
+
1652
  // convert ascii character into decimal value
1653
  function to_ascii( $matches ) {
1654
  return ord( $matches[ 0 ] );
1655
  }
1656
+
1657
  // convert decimal value into ascii character
1658
  function from_ascii( $matches ) {
1659
  return chr( $matches[ 0 ] );
1660
  }
1661
 
1662
+ /**
1663
+ * is_file_ok
1664
  * verify file exists and is in valid location
1665
  */
1666
  function is_file_ok( $stylesheet, $permission = 'read' ) {
1694
  $this->ctc()->debug( $stylesheet . ' is not in wp folders!', __FUNCTION__ );
1695
  return FALSE;
1696
  }
1697
+
1698
+ /**
1699
+ * normalize_color
1700
  * Sets hex string to lowercase and shortens to 3 char format if possible
1701
  */
1702
  function normalize_color( $value ) {
1704
  $value = preg_replace( "/#([0-9A-F])\\1([0-9A-F])\\2([0-9A-F])\\3/i", "#$1$2$3", $value );
1705
  return $value;
1706
  }
1707
+
1708
  // callback for normalize_color regex
1709
  function tolower( $matches ) {
1710
  return '#' . strtolower( $matches[ 1 ] );
1711
  }
1712
+ }
 
includes/class-ctc-ui.php CHANGED
@@ -5,7 +5,7 @@ if ( !defined( 'ABSPATH' ) ) exit;
5
  Class: Child_Theme_Configurator_UI
6
  Plugin URI: http://www.childthemeconfigurator.com/
7
  Description: Handles the plugin User Interface
8
- Version: 1.7.4.2
9
  Author: Lilaea Media
10
  Author URI: http://www.lilaeamedia.com/
11
  Text Domain: chld_thm_cfg
5
  Class: Child_Theme_Configurator_UI
6
  Plugin URI: http://www.childthemeconfigurator.com/
7
  Description: Handles the plugin User Interface
8
+ Version: 1.7.5
9
  Author: Lilaea Media
10
  Author URI: http://www.lilaeamedia.com/
11
  Text Domain: chld_thm_cfg
includes/class-ctc.php CHANGED
@@ -6,7 +6,7 @@ if ( !defined( 'ABSPATH' ) ) exit;
6
  Class: Child_Theme_Configurator
7
  Plugin URI: http://www.childthemeconfigurator.com/
8
  Description: Main Controller Class
9
- Version: 1.7.4.2
10
  Author: Lilaea Media
11
  Author URI: http://www.lilaeamedia.com/
12
  Text Domain: chld_thm_cfg
@@ -108,7 +108,8 @@ class ChildThemeConfiguratorAdmin {
108
  }
109
 
110
  function enqueue_scripts() {
111
- wp_enqueue_style( 'chld-thm-cfg-admin', CHLD_THM_CFG_URL . 'css/chld-thm-cfg.css', array(), '1.7.4.2' );
 
112
 
113
  // we need to use local jQuery UI Widget/Menu/Selectmenu 1.11.2 because selectmenu is not included in < 1.11.2
114
  // this will be updated in a later release to use WP Core scripts when it is widely adopted
@@ -116,12 +117,13 @@ class ChildThemeConfiguratorAdmin {
116
  wp_enqueue_script( 'jquery-ui-selectmenu', CHLD_THM_CFG_URL . 'js/selectmenu.min.js',
117
  array( 'jquery','jquery-ui-core','jquery-ui-position' ), FALSE, TRUE );
118
  endif;
 
119
  wp_enqueue_script( 'ctc-thm-cfg-ctcgrad', CHLD_THM_CFG_URL . 'js/ctcgrad.min.js', array( 'jquery' ), FALSE, TRUE );
120
  wp_enqueue_script( 'chld-thm-cfg-admin', CHLD_THM_CFG_URL . 'js/chld-thm-cfg.min.js',
121
  array(
122
  'jquery-ui-autocomplete',
123
  'jquery-ui-selectmenu',
124
- 'iris',
125
  'ctc-thm-cfg-ctcgrad'
126
  ), FALSE, TRUE );
127
  $localize_array = apply_filters( 'chld_thm_cfg_localize_script', array(
@@ -152,7 +154,7 @@ class ChildThemeConfiguratorAdmin {
152
  'important_txt' => __( '<span style="font-size:10px">!</span>', 'chld_thm_cfg' ),
153
  'selector_txt' => __( 'Selectors', 'chld_thm_cfg' ),
154
  'close_txt' => __( 'Close', 'chld_thm_cfg' ),
155
- 'edit_txt' => __( 'Edit', 'chld_thm_cfg' ),
156
  'cancel_txt' => __( 'Cancel', 'chld_thm_cfg' ),
157
  'rename_txt' => __( 'Rename', 'chld_thm_cfg' ),
158
  'css_fail_txt' => __( 'The stylesheet cannot be displayed.', 'chld_thm_cfg' ),
@@ -590,7 +592,7 @@ class ChildThemeConfiguratorAdmin {
590
  __( '<strong>%s</strong> exists. Please enter a different Child Theme template name.',
591
  'chld_thm_cfg' ), $clone );
592
  else:
593
- $this->clone_child_theme( $clone );
594
  if ( empty( $this->errors ) ):
595
  $this->copy_theme_mods( $child, $clone );
596
  $child = $clone;
@@ -1129,23 +1131,25 @@ add_action( 'wp_enqueue_scripts', 'chld_thm_cfg_child_css', 999 );
1129
  return FALSE;
1130
  }
1131
 
1132
- function clone_child_theme( $newchild ) {
1133
  if ( !$this->fs ) return FALSE; // return if no filesystem access
1134
  global $wp_filesystem;
 
 
 
1135
  $dir = untrailingslashit( $this->css->get_child_target( '' ) );
1136
- $child = $this->theme_basename( '', $dir );
1137
  $themedir = trailingslashit( get_theme_root() );
1138
  $fsthemedir = $this->fspath( $themedir );
1139
  $files = $this->css->recurse_directory( $dir, NULL, TRUE );
1140
  $errors = array();
1141
  foreach ( $files as $file ):
1142
  $childfile = $this->theme_basename( $child, $this->normalize_path( $file ) );
1143
- $newfile = trailingslashit( $newchild ) . $childfile;
1144
  $childpath = $fsthemedir . trailingslashit( $child ) . $childfile;
1145
  $newpath = $fsthemedir . $newfile;
1146
  $this->debug( 'Verifying child dir... ', __FUNCTION__ );
1147
  if ( $this->verify_child_dir( is_dir( $file ) ? $newfile : dirname( $newfile ) ) ):
1148
- if ( is_file( $file ) && !$wp_filesystem->copy( $childpath, $newpath ) ):
1149
  $errors[] = 'could not copy ' . $newpath;
1150
  endif;
1151
  else:
6
  Class: Child_Theme_Configurator
7
  Plugin URI: http://www.childthemeconfigurator.com/
8
  Description: Main Controller Class
9
+ Version: 1.7.5
10
  Author: Lilaea Media
11
  Author URI: http://www.lilaeamedia.com/
12
  Text Domain: chld_thm_cfg
108
  }
109
 
110
  function enqueue_scripts() {
111
+ wp_enqueue_style( 'chld-thm-cfg-admin', CHLD_THM_CFG_URL . 'css/chld-thm-cfg.css', array(), '1.7.5' );
112
+ wp_enqueue_style( 'ctc-spectrum', CHLD_THM_CFG_URL . 'css/spectrum.css', array(), '1.7.5' );
113
 
114
  // we need to use local jQuery UI Widget/Menu/Selectmenu 1.11.2 because selectmenu is not included in < 1.11.2
115
  // this will be updated in a later release to use WP Core scripts when it is widely adopted
117
  wp_enqueue_script( 'jquery-ui-selectmenu', CHLD_THM_CFG_URL . 'js/selectmenu.min.js',
118
  array( 'jquery','jquery-ui-core','jquery-ui-position' ), FALSE, TRUE );
119
  endif;
120
+ wp_enqueue_script( 'ctc-spectrum', CHLD_THM_CFG_URL . 'js/spectrum.min.js', array( 'jquery' ), FALSE, TRUE );
121
  wp_enqueue_script( 'ctc-thm-cfg-ctcgrad', CHLD_THM_CFG_URL . 'js/ctcgrad.min.js', array( 'jquery' ), FALSE, TRUE );
122
  wp_enqueue_script( 'chld-thm-cfg-admin', CHLD_THM_CFG_URL . 'js/chld-thm-cfg.min.js',
123
  array(
124
  'jquery-ui-autocomplete',
125
  'jquery-ui-selectmenu',
126
+ 'ctc-spectrum',
127
  'ctc-thm-cfg-ctcgrad'
128
  ), FALSE, TRUE );
129
  $localize_array = apply_filters( 'chld_thm_cfg_localize_script', array(
154
  'important_txt' => __( '<span style="font-size:10px">!</span>', 'chld_thm_cfg' ),
155
  'selector_txt' => __( 'Selectors', 'chld_thm_cfg' ),
156
  'close_txt' => __( 'Close', 'chld_thm_cfg' ),
157
+ 'edit_txt' => __( 'Edit Selector', 'chld_thm_cfg' ),
158
  'cancel_txt' => __( 'Cancel', 'chld_thm_cfg' ),
159
  'rename_txt' => __( 'Rename', 'chld_thm_cfg' ),
160
  'css_fail_txt' => __( 'The stylesheet cannot be displayed.', 'chld_thm_cfg' ),
592
  __( '<strong>%s</strong> exists. Please enter a different Child Theme template name.',
593
  'chld_thm_cfg' ), $clone );
594
  else:
595
+ $this->clone_child_theme( $child, $clone );
596
  if ( empty( $this->errors ) ):
597
  $this->copy_theme_mods( $child, $clone );
598
  $child = $clone;
1131
  return FALSE;
1132
  }
1133
 
1134
+ function clone_child_theme( $child, $clone ) {
1135
  if ( !$this->fs ) return FALSE; // return if no filesystem access
1136
  global $wp_filesystem;
1137
+ // set child theme if not set for get_child_target to use new child theme as source
1138
+ $this->css->set_prop( 'child', $child );
1139
+
1140
  $dir = untrailingslashit( $this->css->get_child_target( '' ) );
 
1141
  $themedir = trailingslashit( get_theme_root() );
1142
  $fsthemedir = $this->fspath( $themedir );
1143
  $files = $this->css->recurse_directory( $dir, NULL, TRUE );
1144
  $errors = array();
1145
  foreach ( $files as $file ):
1146
  $childfile = $this->theme_basename( $child, $this->normalize_path( $file ) );
1147
+ $newfile = trailingslashit( $clone ) . $childfile;
1148
  $childpath = $fsthemedir . trailingslashit( $child ) . $childfile;
1149
  $newpath = $fsthemedir . $newfile;
1150
  $this->debug( 'Verifying child dir... ', __FUNCTION__ );
1151
  if ( $this->verify_child_dir( is_dir( $file ) ? $newfile : dirname( $newfile ) ) ):
1152
+ if ( is_file( $file ) && !@$wp_filesystem->copy( $childpath, $newpath ) ):
1153
  $errors[] = 'could not copy ' . $newpath;
1154
  endif;
1155
  else:
includes/forms/parent-child.php CHANGED
@@ -214,7 +214,6 @@ if ( !defined( 'ABSPATH' ) ) exit;
214
  <?php _e( 'This will overwrite child theme options you may have already set.', 'chld_thm_cfg' ); ?>
215
  </div>
216
  </div><?php endif; ?>
217
- <?php if ( '' == $hidechild ): ?>
218
  <div class="ctc-input-row clearfix">
219
  <div class="ctc-input-cell"> <strong><label for="ctc_backup">
220
  <?php _e( 'Backup current stylesheet', 'chld_thm_cfg' ); ?>
@@ -229,6 +228,7 @@ if ( !defined( 'ABSPATH' ) ) exit;
229
  <?php _e( 'This creates a copy of the current stylesheet before applying changes. You can remove old backup files using the Files tab.', 'chld_thm_cfg' ); ?>
230
  </div>
231
  </div>
 
232
  <div class="ctc-input-row clearfix">
233
  <div class="ctc-input-cell ctc-section-toggle" id="ctc_revert_css"> <strong>
234
  <?php _e( 'Reset/Restore from backup', 'chld_thm_cfg' ); ?>
@@ -283,6 +283,15 @@ if ( count( $stylesheets ) ):?>
283
  endif; ?>
284
  </div>
285
  <div class="ctc-input-row clearfix">
 
 
 
 
 
 
 
 
 
286
  <div class="ctc-input-cell"> <strong>&nbsp;</strong> </div>
287
  <div class="ctc-input-cell">
288
  <input class="ctc_submit button button-primary" id="ctc_load_styles" name="ctc_load_styles" type="submit"
214
  <?php _e( 'This will overwrite child theme options you may have already set.', 'chld_thm_cfg' ); ?>
215
  </div>
216
  </div><?php endif; ?>
 
217
  <div class="ctc-input-row clearfix">
218
  <div class="ctc-input-cell"> <strong><label for="ctc_backup">
219
  <?php _e( 'Backup current stylesheet', 'chld_thm_cfg' ); ?>
228
  <?php _e( 'This creates a copy of the current stylesheet before applying changes. You can remove old backup files using the Files tab.', 'chld_thm_cfg' ); ?>
229
  </div>
230
  </div>
231
+ <?php if ( '' == $hidechild ): ?>
232
  <div class="ctc-input-row clearfix">
233
  <div class="ctc-input-cell ctc-section-toggle" id="ctc_revert_css"> <strong>
234
  <?php _e( 'Reset/Restore from backup', 'chld_thm_cfg' ); ?>
283
  endif; ?>
284
  </div>
285
  <div class="ctc-input-row clearfix">
286
+ <?php if ( '' == $hidechild && !$enqueueset ): ?>
287
+ <div class="ctc-input-cell"> <strong>&nbsp;</strong> </div>
288
+ <div class="ctc-input-cell-wide">
289
+ <div class="update-nag">
290
+ <strong><?php _e( 'Please read before you click:', 'chld_thm_cfg' ); ?></strong>
291
+ <p><?php _e( 'This plugin makes significant modifications to your child theme, to include changing CSS, removing comments and adding php functions.', 'chld_thm_cfg' ); ?>
292
+ <?php _e( 'If you are using an existing Child Theme,', 'chld_thm_cfg' ); ?> <a href="<?php echo CHLD_THM_CFG_DOCS_URL; ?>/how-to-use/#duplicating-existing-child-themes" target="_blank"><?php _e( 'please consider using the Duplicate Child Theme option', 'chld_thm_cfg' ); ?></a> <?php _e( 'before proceeding.', 'chld_thm_cfg' ); ?></p>
293
+ </div><p>&nbsp;</p></div>
294
+ <?php endif; ?>
295
  <div class="ctc-input-cell"> <strong>&nbsp;</strong> </div>
296
  <div class="ctc-input-cell">
297
  <input class="ctc_submit button button-primary" id="ctc_load_styles" name="ctc_load_styles" type="submit"
includes/forms/query-selector.php CHANGED
@@ -43,13 +43,14 @@ if ( !defined( 'ABSPATH' ) ) exit;
43
  <div class="ctc-input-cell ctc-button-cell" id="ctc_save_query_selector_cell">
44
  <input type="submit" class="button button-primary ctc-save-input" id="ctc_save_query_selector"
45
  name="ctc_save_query_selector" value="<?php _e( 'Save Child Values', 'chld_thm_cfg' ); ?>" disabled />
 
46
  <input type="hidden" id="ctc_sel_ovrd_qsid"
47
  name="ctc_sel_ovrd_qsid" value="" />
48
  </div>
49
  </div>
50
  <div class="ctc-input-row clearfix" id="ctc_sel_ovrd_rule_header" style="display:none">
51
  <div class="ctc-input-cell"> <strong>
52
- <?php _e( 'Rule', 'chld_thm_cfg' ); ?>
53
  </strong> </div>
54
  <div class="ctc-input-cell"> <strong>
55
  <?php _e( 'Parent Value', 'chld_thm_cfg' ); ?>
@@ -61,7 +62,7 @@ if ( !defined( 'ABSPATH' ) ) exit;
61
  <div id="ctc_sel_ovrd_rule_inputs" style="display:none"> </div>
62
  <div class="ctc-input-row clearfix" id="ctc_sel_ovrd_new_rule" style="display:none">
63
  <div class="ctc-input-cell"> <strong>
64
- <?php _e( 'New Rule', 'chld_thm_cfg' ); ?>
65
  </strong> </div>
66
  <div class="ctc-input-cell">
67
  <div class="ui-widget">
43
  <div class="ctc-input-cell ctc-button-cell" id="ctc_save_query_selector_cell">
44
  <input type="submit" class="button button-primary ctc-save-input" id="ctc_save_query_selector"
45
  name="ctc_save_query_selector" value="<?php _e( 'Save Child Values', 'chld_thm_cfg' ); ?>" disabled />
46
+ <a class="ctc-delete-input" id="ctc_delete_query_selector" href="#"><?php _e( 'Delete Child Values', 'chld_thm_cfg' ); ?></a>
47
  <input type="hidden" id="ctc_sel_ovrd_qsid"
48
  name="ctc_sel_ovrd_qsid" value="" />
49
  </div>
50
  </div>
51
  <div class="ctc-input-row clearfix" id="ctc_sel_ovrd_rule_header" style="display:none">
52
  <div class="ctc-input-cell"> <strong>
53
+ <?php _e( 'Property', 'chld_thm_cfg' ); ?>
54
  </strong> </div>
55
  <div class="ctc-input-cell"> <strong>
56
  <?php _e( 'Parent Value', 'chld_thm_cfg' ); ?>
62
  <div id="ctc_sel_ovrd_rule_inputs" style="display:none"> </div>
63
  <div class="ctc-input-row clearfix" id="ctc_sel_ovrd_new_rule" style="display:none">
64
  <div class="ctc-input-cell"> <strong>
65
+ <?php _e( 'New Property', 'chld_thm_cfg' ); ?>
66
  </strong> </div>
67
  <div class="ctc-input-cell">
68
  <div class="ui-widget">
includes/forms/rule-value.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
  if ( !defined( 'ABSPATH' ) ) exit;
3
- // Rule/Value Panel
4
  $ctcpage = apply_filters( 'chld_thm_cfg_admin_page', CHLD_THM_CFG_MENU );
5
  ?>
6
 
@@ -10,7 +10,7 @@ if ( !defined( 'ABSPATH' ) ) exit;
10
  <?php wp_nonce_field( apply_filters( 'chld_thm_cfg_action', 'ctc_update' ) ); ?>
11
  <div class="ctc-input-row clearfix" id="ctc_input_row_rule_menu">
12
  <div class="ctc-input-cell"> <strong>
13
- <?php _e( 'Rule', 'chld_thm_cfg' ); ?>
14
  </strong> </div>
15
  <div class="ctc-input-cell" id="ctc_rule_menu_selected">&nbsp;</div>
16
  <div id="ctc_status_rule_val"></div>
1
  <?php
2
  if ( !defined( 'ABSPATH' ) ) exit;
3
+ // Property/Value Panel
4
  $ctcpage = apply_filters( 'chld_thm_cfg_admin_page', CHLD_THM_CFG_MENU );
5
  ?>
6
 
10
  <?php wp_nonce_field( apply_filters( 'chld_thm_cfg_action', 'ctc_update' ) ); ?>
11
  <div class="ctc-input-row clearfix" id="ctc_input_row_rule_menu">
12
  <div class="ctc-input-cell"> <strong>
13
+ <?php _e( 'Property', 'chld_thm_cfg' ); ?>
14
  </strong> </div>
15
  <div class="ctc-input-cell" id="ctc_rule_menu_selected">&nbsp;</div>
16
  <div id="ctc_status_rule_val"></div>
includes/forms/tabs.php CHANGED
@@ -16,7 +16,7 @@ $active_tab = isset( $_GET[ 'tab' ] ) ? $_GET[ 'tab' ] : 'parent_child_options';
16
  <?php _e( 'Query/Selector', 'chld_thm_cfg' ); ?>
17
  </a><!----><a id="rule_value_options" href=""
18
  class="nav-tab<?php echo 'rule_value_options' == $active_tab ? ' nav-tab-active' : ''; ?>" <?php echo $hidechild; ?>>
19
- <?php _e( 'Rule/Value', 'chld_thm_cfg' ); ?>
20
  </a><!----><a id="import_options" href=""
21
  class="nav-tab<?php echo 'import_options' == $active_tab ? ' nav-tab-active' : ''; ?>" <?php echo $hidechild; ?>>
22
  <?php _e( 'Web Fonts', 'chld_thm_cfg' ); ?>
16
  <?php _e( 'Query/Selector', 'chld_thm_cfg' ); ?>
17
  </a><!----><a id="rule_value_options" href=""
18
  class="nav-tab<?php echo 'rule_value_options' == $active_tab ? ' nav-tab-active' : ''; ?>" <?php echo $hidechild; ?>>
19
+ <?php _e( 'Property/Value', 'chld_thm_cfg' ); ?>
20
  </a><!----><a id="import_options" href=""
21
  class="nav-tab<?php echo 'import_options' == $active_tab ? ' nav-tab-active' : ''; ?>" <?php echo $hidechild; ?>>
22
  <?php _e( 'Web Fonts', 'chld_thm_cfg' ); ?>
includes/help/help_en_US.php CHANGED
@@ -40,30 +40,34 @@ This option imports the parent stylesheet from the child stylesheet. This enable
40
  <iframe src="//fast.wistia.net/embed/iframe/c0fbu8jhtj" allowtransparency="true" frameborder="0" scrolling="no" class="wistia_embed" name="wistia_embed" allowfullscreen mozallowfullscreen webkitallowfullscreen oallowfullscreen msallowfullscreen width="640" height="360"></iframe><!-- END tab -->
41
  <!-- BEGIN tab -->
42
  <h3 id="ctc_query_selector">Query/Selector Tab</h3>
43
- <p>There are two ways to identify and override parent styles. The Child Theme Configurator lets you search styles by <strong>selector</strong> and by <strong>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>
44
  <p>The Query/Selector tab lets you find specific selectors and edit them. First, find the query that contains the selector you wish to edit by typing in the <strong>Query</strong> autoselect box. Select by clicking with the mouse or by pressing the "Enter" or "Tab" keys. Selectors are in the <strong>base</strong> query by default.</p>
45
  <p>Next, find the selector by typing in the <strong>Selector</strong> autoselect box. Select by clicking with the mouse or by pressing the "Enter" or "Tab" keys.</p>
46
- <p>This will load all of the 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>
47
  <p>The "Order" field contains the original sequence of the selector in the parent theme stylesheet. You can change the selector order sequence by entering a lower or higher number in the "Order" field. You can also force style overrides (so called "!important" flag) by checking the "!" box next to each input. Please use judiciously.</p>
48
  <p>Click "Save" to update the child stylesheet and save your changes to the WordPress admin.</p>
49
  <!-- END tab -->
50
  <!-- BEGIN tab -->
51
  <h3 id="ctc_new_styles">Adding New Styles</h3>
52
- <p>If you wish to add additional 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>
53
  <p>If you wish to add completely new selectors, or even new @media queries, you can enter free-form CSS in the "Raw CSS" textarea. Be aware that your syntax must be correct (i.e., balanced curly braces, etc.) for the parser to load the new styles. You will know it is invalid because a red "X" will appear next to the save button.</p>
54
- <p>If you prefer to use shorthand syntax for 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>
55
  <!-- END tab -->
56
  <!-- BEGIN tab -->
57
- <h3 id="ctc_rule_value">Rule/Value Tab</h3>
58
- <p>There are two ways to identify and override parent styles. The Child Theme Configurator lets you search styles by <strong>selector</strong> and by <strong>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>
59
- <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>
60
- <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>
61
- <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>
62
  <p>Click "Save" to update the child stylesheet and save your changes to the WordPress admin.</p>
63
  <!-- END tab -->
64
  <!-- BEGIN tab -->
65
  <h3 id="ctc_imports">Web Fonts Tab</h3>
66
- <p>You can add additional stylesheets and web fonts by typing @import rules into the textarea on the Web Fonts tab. <strong>Important: do not import the parent theme stylesheet here. Use the &quot;Parent stylesheet handling&quot; option from the Parent/Child tab.</strong></p>
 
 
 
 
67
  <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>
68
  <blockquote><pre><code>&#64;import url(fonts/stylesheet.css);
69
  &#64;import url(http://fonts.googleapis.com/css?family=Open+Sans:400,400italic,700,700italic);</code></pre></blockquote>
@@ -118,7 +122,8 @@ This option imports the parent stylesheet from the child stylesheet. This enable
118
  <code>[path/to/wordpress]/wp-content/themes/[child-theme]</code>
119
 
120
  <p>To prevent this in the future, always test your child themes with Live Preview before activating them.</p>
121
-
 
122
  <h5 id="menus_broken">Why are my menus displaying incorrectly when I activate the new child theme?</h5>...or...
123
  <h5 id="header_broken">Why is my custom header missing when I activate the new child theme?</h5>...or...
124
  <h5 id="background_broken">Why does my custom background go back to the default when I activate the new child theme?</h5>...or...
@@ -141,7 +146,7 @@ This option imports the parent stylesheet from the child stylesheet. This enable
141
  <h5 id="existing_parent">How do I move changes I have already made to my theme into a Child Theme?</h5>
142
  <p><a href="<?php echo CHLD_THM_CFG_DOCS_URL; ?>/how-to-use/#child_from_modified_parent" class="scroll-to">Follow these steps</a>. </p>
143
  <h5 id="web_fonts">How do I add Web Fonts?</h5>
144
- <p>The easiest method is to paste the @import code provided by <a href="http://www.google.com/fonts" title="Google Fonts">Google</a>, <a href="http://www.fontsquirrel.com/" title="Font Squirrel">Font Squirrel</a> or any other Web Font site into the Web Fonts 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>
145
  <p>You can also create a secondary stylesheet that contains @font-face rules and import it using the Web Fonts tab. </p>
146
  <h5 id="plugin">Does it work with plugins?</h5>
147
  <p>We offer a premium extension to let you easily modify styles for any WordPress Plugin installed on your website. The Child Theme Configurator Plugin Extension scans your plugins and allows you to create custom stylesheets in your Child Theme. <a href="<?php echo CHLD_THM_CFG_DOCS_URL; ?>/child-theme-configurator-pro/" title="Take Control of your Plugin Styles with Child Theme Configurator Plugin Extension for WordPress">Learn more <i class="genericon genericon-next"></i></a>
@@ -168,15 +173,15 @@ The plugin only loads the bulk of the code in the admin when you are using the t
168
  <h5 id="functions">Where are the .php files?</h5>
169
  <p>The configurator automatically adds a blank functions.php file to the child theme directory. You can copy parent theme template files using the Files tab. If you want to create new templates and directories you will have to create/upload them manually via FTP or SSH. Remember that a child theme will automatically inherit the parent theme's templates unless they also exist in the child theme directory. Only copy templates that you intend to customize.</p>
170
  <h5 id="specific_color">How do I change a specific color/font style/background?</h5>
171
- <p>You can override a specific value globally using the Rule/Value tab. See Rule/Value, above.</p>
172
  <h5 id="add_styles">How do I add styles that aren't in the Parent Theme?</h5>
173
  <p>You can add queries and selectors using the "Raw CSS" textarea on the Query/Selector tab. See Query/Selector, above. </p>
174
  <h5 id="add_styles">How do I remove a style from the Parent Theme?</h5>
175
- <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>
176
  <h5 id="remove_styles">How do I remove a style from the Child Theme?</h5>
177
- <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>
178
  <h5 id="important_flag">How do I set the !important flag?</h5>
179
- <p>We always recommend relying on good cascading design over global overrides. To that end, you have ability to change the load order of child theme styles by entering a value in the "Order" field. And yes, you can now set rules as important by checking the "!" box next to each input. Please use judiciously. </p>
180
  <h5 id="gradients">How do I create cross-browser gradients?</h5>
181
  <p>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. </p>
182
  <h5 id="responsive">How do I make my Theme responsive?</h5>
@@ -192,9 +197,9 @@ The plugin only loads the bulk of the code in the admin when you are using the t
192
  <ul>
193
  <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>
194
  <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>
195
- <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>
196
  <li id="selector"><strong>Selector</strong> One or more html elements, classes, ids or other terms used to identify groups of objects.</li>
197
- <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>
198
  <li id="at-rule"><strong>At-rule</strong> CSS browser instruction to extend default functionality. The Child Theme Configurator supports two At-rules:
199
  <ul>
200
  <li id="import"><strong>@import</strong> Instructs the browser to load additional CSS information from an external source.</li>
40
  <iframe src="//fast.wistia.net/embed/iframe/c0fbu8jhtj" allowtransparency="true" frameborder="0" scrolling="no" class="wistia_embed" name="wistia_embed" allowfullscreen mozallowfullscreen webkitallowfullscreen oallowfullscreen msallowfullscreen width="640" height="360"></iframe><!-- END tab -->
41
  <!-- BEGIN tab -->
42
  <h3 id="ctc_query_selector">Query/Selector Tab</h3>
43
+ <p>There are two ways to identify and override parent styles. The Child Theme Configurator lets you search styles by <strong>selector</strong> and by <strong>property</strong>. If you wish to change a specific selector (e.g., h1), use the "Query/Selector" tab. If you have a specific value you wish to change site-wide (e.g., the color of the type), use the "Property/Value" tab.</p>
44
  <p>The Query/Selector tab lets you find specific selectors and edit them. First, find the query that contains the selector you wish to edit by typing in the <strong>Query</strong> autoselect box. Select by clicking with the mouse or by pressing the "Enter" or "Tab" keys. Selectors are in the <strong>base</strong> query by default.</p>
45
  <p>Next, find the selector by typing in the <strong>Selector</strong> autoselect box. Select by clicking with the mouse or by pressing the "Enter" or "Tab" keys.</p>
46
+ <p>This will load all of the properties for that selector with the Parent values on the left and the Child values inputs on the right. Any existing child values will be automatically populated. There is also a Sample preview that displays the combination of Parent and Child overrides. Note that the <strong>border</strong> and <strong>background-image</strong> get special treatment.</p>
47
  <p>The "Order" field contains the original sequence of the selector in the parent theme stylesheet. You can change the selector order sequence by entering a lower or higher number in the "Order" field. You can also force style overrides (so called "!important" flag) by checking the "!" box next to each input. Please use judiciously.</p>
48
  <p>Click "Save" to update the child stylesheet and save your changes to the WordPress admin.</p>
49
  <!-- END tab -->
50
  <!-- BEGIN tab -->
51
  <h3 id="ctc_new_styles">Adding New Styles</h3>
52
+ <p>If you wish to add additional properties to a given selector, first load the selector using the Query/Selector tab. Then find the property you wish to override by typing in the <strong>New Property</strong> autoselect box. Select by clicking with the mouse or by pressing the "Enter" or "Tab" keys. This will add a new input row to the selector inputs.</p>
53
  <p>If you wish to add completely new selectors, or even new @media queries, you can enter free-form CSS in the "Raw CSS" textarea. Be aware that your syntax must be correct (i.e., balanced curly braces, etc.) for the parser to load the new styles. You will know it is invalid because a red "X" will appear next to the save button.</p>
54
+ <p>If you prefer to use shorthand syntax for properties and values instead of the inputs provided by the Child Theme Configurator, you can enter them here as well. The parser will convert your input into normalized CSS code automatically.</p>
55
  <!-- END tab -->
56
  <!-- BEGIN tab -->
57
+ <h3 id="ctc_property_value">Property/Value Tab</h3>
58
+ <p>There are two ways to identify and override parent styles. The Child Theme Configurator lets you search styles by <strong>selector</strong> and by <strong>property</strong>. If you wish to change a specific selector (e.g., h1), use the "Query/Selector" tab. If you have a specific value you wish to change site-wide (e.g., the color of the type), use the "Property/Value" tab.</p>
59
+ <p>The Property/Value tab lets you find specific values for a given property and then edit that value for individual selectors that use that property/value combination. First, find the property you wish to override by typing in the <strong>Property</strong> autoselect box. Select by clicking with the mouse or by pressing the "Enter" or "Tab" keys.</p>
60
+ <p>This will load all of the unique values that exist for that property in the parent stylesheet with a Sample preview for that value. If there are values that exist in the child stylesheet that do not exist in the parent stylesheet, they will be displayed as well.</p>
61
+ <p>For each unique value, click the "Selectors" link to view a list of selectors that use that property/value combination, grouped by query with a Sample preview of the value and inputs for the child value. Any existing child values will be automatically populated.</p>
62
  <p>Click "Save" to update the child stylesheet and save your changes to the WordPress admin.</p>
63
  <!-- END tab -->
64
  <!-- BEGIN tab -->
65
  <h3 id="ctc_imports">Web Fonts Tab</h3>
66
+ <p>You can link additional stylesheets and web fonts by typing @import rules into the textarea on the Web Fonts tab.</p>
67
+ <p><strong>Note:</strong> Child Theme Configurator no longer writes @import rules to the stylesheet. Instead, it uses the @import keyword to identify and enqueue them in the script queue. WordPress then converts them to &lt;link&gt; tags in the rendered HTML.</p>
68
+ <p>Important: do not import the parent theme stylesheet here. Use the "Parent stylesheet handling" option from the Parent/Child tab.</p>
69
+ <p>If you selected any stylesheets under “Parse additional stylesheets” when you created your child theme, those styles will be available to create overrides in the Child Theme stylesheet.</p>
70
+ <p>WordPress will automatically load the additional stylesheets when it loads the parent theme, so you do not need to add @import rules for them here.</p>
71
  <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>
72
  <blockquote><pre><code>&#64;import url(fonts/stylesheet.css);
73
  &#64;import url(http://fonts.googleapis.com/css?family=Open+Sans:400,400italic,700,700italic);</code></pre></blockquote>
122
  <code>[path/to/wordpress]/wp-content/themes/[child-theme]</code>
123
 
124
  <p>To prevent this in the future, always test your child themes with Live Preview before activating them.</p>
125
+ <h5 id="no-comments">How do I add comments?</h5>
126
+ <p><strong>Arbitrary comments are not supported.</strong> Providing a high level of flexibility for previewing and modifying styles requires sophisticated parsing and data structures. Maintaining comments that bound to any particular element in the stylesheet is prohibitively expensive compared to the value it would add. Although we are working to include this as an option in the future, <em>currently all comments are stripped from the child theme stylesheet code.</em></p>
127
  <h5 id="menus_broken">Why are my menus displaying incorrectly when I activate the new child theme?</h5>...or...
128
  <h5 id="header_broken">Why is my custom header missing when I activate the new child theme?</h5>...or...
129
  <h5 id="background_broken">Why does my custom background go back to the default when I activate the new child theme?</h5>...or...
146
  <h5 id="existing_parent">How do I move changes I have already made to my theme into a Child Theme?</h5>
147
  <p><a href="<?php echo CHLD_THM_CFG_DOCS_URL; ?>/how-to-use/#child_from_modified_parent" class="scroll-to">Follow these steps</a>. </p>
148
  <h5 id="web_fonts">How do I add Web Fonts?</h5>
149
+ <p>The easiest method is to paste the @import code provided by <a href="http://www.google.com/fonts" title="Google Fonts">Google</a>, <a href="http://www.fontsquirrel.com/" title="Font Squirrel">Font Squirrel</a> or any other Web Font site into the Web Fonts tab. The fonts will then be available to use as a value of the <strong>font-family</strong> property. Be sure you understand the license for any embedded fonts. </p>
150
  <p>You can also create a secondary stylesheet that contains @font-face rules and import it using the Web Fonts tab. </p>
151
  <h5 id="plugin">Does it work with plugins?</h5>
152
  <p>We offer a premium extension to let you easily modify styles for any WordPress Plugin installed on your website. The Child Theme Configurator Plugin Extension scans your plugins and allows you to create custom stylesheets in your Child Theme. <a href="<?php echo CHLD_THM_CFG_DOCS_URL; ?>/child-theme-configurator-pro/" title="Take Control of your Plugin Styles with Child Theme Configurator Plugin Extension for WordPress">Learn more <i class="genericon genericon-next"></i></a>
173
  <h5 id="functions">Where are the .php files?</h5>
174
  <p>The configurator automatically adds a blank functions.php file to the child theme directory. You can copy parent theme template files using the Files tab. If you want to create new templates and directories you will have to create/upload them manually via FTP or SSH. Remember that a child theme will automatically inherit the parent theme's templates unless they also exist in the child theme directory. Only copy templates that you intend to customize.</p>
175
  <h5 id="specific_color">How do I change a specific color/font style/background?</h5>
176
+ <p>You can override a specific value globally using the Property/Value tab. See Property/Value, above.</p>
177
  <h5 id="add_styles">How do I add styles that aren't in the Parent Theme?</h5>
178
  <p>You can add queries and selectors using the "Raw CSS" textarea on the Query/Selector tab. See Query/Selector, above. </p>
179
  <h5 id="add_styles">How do I remove a style from the Parent Theme?</h5>
180
+ <p>You shouldn't really "remove" a style from the Parent. You can, however, set the property to "inherit," "none," or zero (depending on the property). This will negate the Parent value. Some experimentation may be necessary.</p>
181
  <h5 id="remove_styles">How do I remove a style from the Child Theme?</h5>
182
+ <p>Delete the value from the input for the property you wish to remove. The Child Theme Configurator only adds overrides for properties that contain values. </p>
183
  <h5 id="important_flag">How do I set the !important flag?</h5>
184
+ <p>We always recommend relying on good cascading design over global overrides. To that end, you have ability to change the load order of child theme styles by entering a value in the "Order" field. You can set properties as important by checking the "!" box next to each input. Please use judiciously. </p>
185
  <h5 id="gradients">How do I create cross-browser gradients?</h5>
186
  <p>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. </p>
187
  <h5 id="responsive">How do I make my Theme responsive?</h5>
197
  <ul>
198
  <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>
199
  <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>
200
+ <li id="class"><strong>Class</strong> A term used to organize objects. For example, a &lt;div&gt; might be assigned the "blue-text" class. The stylesheet might then assign "color: blue;" to members of the "blue-text" class. Thus, the &lt;div&gt; would display text as blue in the browser.</li>
201
  <li id="selector"><strong>Selector</strong> One or more html elements, classes, ids or other terms used to identify groups of objects.</li>
202
+ <li id="property"><strong>Property</strong> One of many standardized terms used to tell the browser how to display objects matching a given selector. Examples are <strong>color</strong>, <strong>background-image</strong> and <strong>font-size</strong>.</li>
203
  <li id="at-rule"><strong>At-rule</strong> CSS browser instruction to extend default functionality. The Child Theme Configurator supports two At-rules:
204
  <ul>
205
  <li id="import"><strong>@import</strong> Instructs the browser to load additional CSS information from an external source.</li>
js/chld-thm-cfg.js CHANGED
@@ -2,13 +2,18 @@
2
  * Script: chld-thm-cfg.js
3
  * Plugin URI: http://www.childthemeconfigurator.com/
4
  * Description: Handles jQuery, AJAX and other UI
5
- * Version: 1.7.4.2
6
  * Author: Lilaea Media
7
  * Author URI: http://www.lilaeamedia.com/
8
  * License: GPLv2
9
  * Copyright (C) 2014-2015 Lilaea Media
10
  */
11
- ;
 
 
 
 
 
12
  ( function( $ ) {
13
  $.chldthmcfg = {
14
  //console.log( 'executing main function' );
@@ -32,6 +37,12 @@
32
  return ascii;
33
  },
34
 
 
 
 
 
 
 
35
  is_empty: function( obj ) {
36
  // first bail when definitely empty or undefined ( true ) NOTE: numeric zero returns false !
37
  if ( 'undefined' == typeof obj || false === obj || null === obj || '' === obj ) { return true; }
@@ -55,7 +66,11 @@
55
  // this must be an unsupported datatype, so return not empty
56
  return false;
57
  },
58
- // initialize functions
 
 
 
 
59
  theme_exists: function( testslug, testtype ) {
60
  var exists = false;
61
  $.each( ctcAjax.themes, function( type, theme ) {
@@ -119,7 +134,7 @@
119
  var panelid = id + '_panel';
120
  $( '.nav-tab' ).removeClass( 'nav-tab-active' );
121
  $( '.ctc-option-panel' ).removeClass( 'ctc-option-panel-active' );
122
- $( '.ctc-selector-container' ).hide();
123
  $( id ).addClass( 'nav-tab-active' );
124
  $( '.ctc-option-panel-container' ).scrollTop( 0 );
125
  $( panelid ).addClass( 'ctc-option-panel-active' );
@@ -150,9 +165,10 @@
150
  },
151
 
152
  coalesce_inputs: function( obj ) {
153
- //console.log( 'coalesce_inputs ' + $( obj ).attr( 'id' ) );
154
  var self = this,
155
- regex = /^(ctc_(ovrd|\d+)_(parent|child)_([0-9a-z\-]+)_(\d+))(_\w+)?$/,
 
156
  container = $( obj ).parents( '.ctc-selector-row, .ctc-parent-row' ).first(),
157
  swatch = container.find( '.ctc-swatch' ).first(),
158
  cssrules = { 'parent': {}, 'child': {} },
@@ -177,24 +193,27 @@
177
  inputseq = inputparts[ 2 ],
178
  inputtheme = inputparts[ 3 ],
179
  inputrule = ( 'undefined' == typeof inputparts[ 4 ] ? '' : inputparts[ 4 ] ),
 
180
  qsid = inputparts[ 5 ],
181
- rulepart = ( 'undefined' == typeof inputparts[ 6 ] ? '' : inputparts[ 6 ] ),
182
- value = ( 'parent' == inputtheme ? $( this ).text().replace( /!$/, '' ) : $( this ).val() ),
183
- important = 'ctc_' + inputseq + '_child_' + inputrule + '_i_' + qsid,
 
184
  parts, subparts;
185
- if ( !self.is_empty( $( this ).data( 'color' ) ) ) {
186
- value = $( this ).data( 'color' );
187
- $( this ).data( 'color', null );
188
- }
189
- //console.log( 'id: ' + inputid + ' value: ' + value );
190
  if ( 'child' == inputtheme ) {
191
- postdata[ inputid ] = value;
192
- postdata[ important ] = ( $( '#' + important ).is( ':checked' ) ) ? 1 : 0;
 
 
 
 
 
193
  }
194
- if ( '' != value ) {
195
  // handle specific inputs
196
  if ( !self.is_empty( rulepart ) ) {
197
- //console.log( 'rulepart: ' + rulepart + ' value: ' + value );
198
  switch( rulepart ) {
199
  case '_border_width':
200
  cssrules[ inputtheme ][ inputrule + '-width' ] = ( 'none' == value ? 0 : value );
@@ -209,7 +228,7 @@
209
  cssrules[ inputtheme ][ 'background-image' ] = self.image_url( inputtheme, value );
210
  break;
211
  case '_background_color':
212
- cssrules[ inputtheme ][ 'background-color' ] = obj.value;
213
  break;
214
  case '_background_color1':
215
  gradient[ inputtheme ].start = value;
@@ -227,20 +246,35 @@
227
  } else {
228
  // handle borders
229
  if ( parts = inputrule.toString().match( /^border(\-(top|right|bottom|left))?$/ ) && !value.match( /none/ ) ) {
230
- subparts = value.toString().split( / +/ );
231
- cssrules[ inputtheme ][ inputrule + '-width' ] = 'undefined' == typeof subparts[ 0 ] ? '' : subparts[ 0 ];
232
- cssrules[ inputtheme ][ inputrule + '-style' ] = 'undefined' == typeof subparts[ 1 ] ? '' : subparts[ 1 ];
233
- cssrules[ inputtheme ][ inputrule + '-color' ] = 'undefined' == typeof subparts[ 2 ] ? '' : subparts[ 2 ];
 
 
 
 
 
 
 
 
 
234
  // handle background images
235
  } else if ( 'background-image' == inputrule && !value.match( /none/ ) ) {
236
  if ( value.toString().match( /url\(/ ) ) {
237
  cssrules[ inputtheme ][ 'background-image' ] = self.image_url( inputtheme, value );
238
  } else {
239
- subparts = value.toString().split( / +/ );
240
- if ( subparts.length > 2 ) {
241
- gradient[ inputtheme ].origin = 'undefined' == typeof subparts[ 0 ] ? 'top' : subparts[ 0 ];
242
- gradient[ inputtheme ].start = 'undefined' == typeof subparts[ 1 ] ? 'transparent' : subparts[ 1 ];
243
- gradient[ inputtheme ].end = 'undefined' == typeof subparts[ 2 ] ? 'transparent' : subparts[ 2 ];
 
 
 
 
 
 
244
  has_gradient[ inputtheme ] = true;
245
  } else {
246
  cssrules[ inputtheme ][ 'background-image' ] = value;
@@ -258,11 +292,14 @@
258
  if ( has_gradient.parent ) {
259
  swatch.ctcgrad( gradient.parent.origin, [ gradient.parent.start, gradient.parent.end ] );
260
  }
 
 
261
  swatch.css( cssrules.parent );
262
  if ( !( swatch.attr( 'id' ).toString().match( /parent/ ) ) ) {
263
  if ( has_gradient.child ) {
264
  swatch.ctcgrad( gradient.child.origin, [ gradient.child.start, gradient.child.end ] );
265
  }
 
266
  swatch.css( cssrules.child );
267
  }
268
  swatch.css( {'z-index':-1} );
@@ -271,46 +308,60 @@
271
  },
272
 
273
  decode_value: function( rule, value ) {
 
274
  value = ( 'undefined' == typeof value ? '' : value );
275
  var self = this,
276
- obj = { 'orig': value };
 
 
 
 
277
  if ( rule.toString().match( /^border(\-(top|right|bottom|left))?$/ ) ) {
278
- var params = value.toString().split( / +/ );
279
- obj[ 'names' ] = [
 
 
280
  '_border_width',
281
  '_border_style',
282
  '_border_color',
283
  ];
284
- obj[ 'values' ] = [
285
- ( 'undefined' == typeof params[ 0 ] ? '' : params[ 0 ] ),
286
- ( 'undefined' == typeof params[ 1 ] ? '' : params[ 1 ] ),
287
- ( 'undefined' == typeof params[ 2 ] ? '' : params[ 2 ] )
288
- ];
 
 
 
 
289
  } else if ( rule.toString().match( /^background\-image/ ) ) {
290
- obj[ 'names' ] = [
291
  '_background_url',
292
  '_background_origin',
293
  '_background_color1',
294
  '_background_color2'
295
  ];
296
- obj[ 'values' ] = [ '', '', '', '' ];
297
- if ( false === ( self.is_empty( value ) ) && !( value.toString().match( /(url|none)/ ) ) ) {
298
- var params = value.toString().split( /:/ );
299
- obj[ 'values' ][ 1 ] = ( 'undefined' == typeof params[ 0 ] ? '' : params[ 0 ] );
300
- obj[ 'values' ][ 2 ] = ( 'undefined' == typeof params[ 1 ] ? '' : params[ 1 ] );
301
- obj[ 'values' ][ 3 ] = ( 'undefined' == typeof params[ 3 ] ? '' : params[ 3 ] );
302
- obj[ 'orig' ] = [
303
- obj[ 'values' ][ 1 ],
304
- obj[ 'values' ][ 2 ],
305
- obj[ 'values' ][ 3 ]
 
 
 
 
 
306
  ].join( ' ' );
307
  } else {
308
- obj[ 'values' ][ 0 ] = value;
309
  }
310
- } else {
311
- obj[ 'names' ] = [ '' ];
312
- obj[ 'values' ] = [ value ];
313
  }
 
314
  return obj;
315
  },
316
 
@@ -416,24 +467,10 @@
416
  get_filtered_rules: function( request, response ) {
417
  //console.log( 'get_filtered_rules' );
418
  var arr = [],
419
- matcher = new RegExp( $.ui.autocomplete.escapeRegex( request.term ), "i" ),
420
- data = $.chldthmcfg.current_qsdata,
421
- noval = ( $.chldthmcfg.is_empty( data ) ) || ( $.chldthmcfg.is_empty( data.value ) );
422
  $.each( $( '#ctc_rule_menu' ).data( 'menu' ), function( key, val ) {
423
- var skip = false;
424
  if ( matcher.test( key ) ) {
425
- if ( !noval ) {
426
- // skip rule if in current selector array
427
- $.each( data.value, function( rule, value ) {
428
- if ( key == rule.replace( /\d+/g, self.from_ascii ) ) {
429
- skip = true;
430
- return false;
431
- }
432
- } );
433
- if ( skip ) {
434
- return;
435
- }
436
- }
437
  arr.push( { 'label': key, 'value': val } );
438
  }
439
  } );
@@ -441,72 +478,108 @@
441
  },
442
 
443
  /**
444
- * render individual row of inputs for a given selector/rule combination
 
445
  */
446
- input_row: function( qsid, rule, seq, data ) {
447
- //console.log( 'input_row: ' + qsid + ' rule: ' + rule + ' seq: ' + seq );
448
  var self = this,
449
- html = '',
450
- value = ( self.is_empty( data ) || self.is_empty( data.value ) || self.is_empty( data.value[ rule ] ) ?
451
- '' : data.value[ rule ] ),
452
- parentObj = self.decode_value( rule, ( self.is_empty( value ) ?
453
- '' : value.parnt ) ),
454
- parentImp = ( !self.is_empty( value ) && !self.is_empty( value.i_parnt ) && 1 == value.i_parnt ) ?
455
- self.getxt( 'important' ) : '',
456
- childObj = self.decode_value( rule, ( self.is_empty( value ) ?
457
- '' : value[ 'child' ] ) ),
458
- childImp = ( !self.is_empty( value ) && !self.is_empty( value.i_child ) && 1 == value.i_child ) ? 1 : 0,
459
- impid = 'ctc_' + seq + '_child_' + rule + '_i_' + qsid;
460
- if ( !self.is_empty( data ) ) {
461
- html += '<div class="ctc-' + ( 'ovrd' == seq ? 'input' : 'selector' )
462
- + '-row clearfix">' + "\n" + '<div class="ctc-input-cell">'
463
- + ( 'ovrd' == seq ? rule.replace( /\d+/g, self.from_ascii ) :
464
- data.selector + '<br/><a href="#" class="ctc-selector-edit"'
465
- + ' id="ctc_selector_edit_' + qsid + '" >' + self.getxt( 'edit' ) + '</a> '
466
- + ( self.is_empty( parentObj.orig ) ? self.getxt( 'child_only' ) : '' ) )
467
- + '</div>' + "\n";
468
- if ( 'ovrd' == seq ) {
469
- html += '<div class="ctc-parent-value ctc-input-cell"'
470
- + ' id="ctc_' + seq + '_parent_' + rule + '_' + qsid + '">'
471
- + ( self.is_empty( parentObj.orig ) ? '[no value]' : parentObj.orig + parentImp )
472
- + '</div>' + "\n";
473
- }
474
- html += '<div class="ctc-input-cell">' + "\n";
475
- if ( !self.is_empty( parentObj.names ) ) {
476
- $.each( parentObj.names, function( ndx, newname ) {
477
- newname = ( self.is_empty( newname ) ? '' : newname );
478
- html += '<div class="ctc-child-input-cell">' + "\n";
479
- var id = 'ctc_' + seq + '_child_' + rule + '_' + qsid + newname,
480
- newval;
481
- if ( false === ( newval = childObj.values.shift() ) ) {
482
- newval = '';
483
  }
484
-
485
- html += ( self.is_empty( newname ) ? '' : self.getxt( newname ) + ':<br/>' )
486
- + '<input type="text" id="' + id + '" name="' + id + '" class="ctc-child-value'
487
- + ( ( newname + rule ).toString().match( /color/ ) ? ' color-picker' : '' )
488
- + ( ( newname ).toString().match( /url/ ) ? ' ctc-input-wide' : '' )
489
- + '" value="' + self.esc_quot( newval ) + '" />' + "\n" + '</div>' + "\n";
490
  } );
491
- html += '<label for="' + impid + '"><input type="checkbox"'
492
- + ' id="' + impid + '" name="' + impid + '" value="1" '
493
- + ( 1 === childImp ? 'checked' : '' ) + ' />'
494
- + self.getxt( 'important' ) + '</label>' + "\n";
495
  }
496
- html += '</div>' + "\n" + ( 'ovrd' == seq ? '' :
497
- '<div class="ctc-swatch ctc-specific"'
498
- + ' id="ctc_child_' + rule + '_' + qsid + '_swatch">'
499
- + self.getxt( 'swatch' ) + '</div>' + "\n"
500
- + '<div class="ctc-child-input-cell ctc-button-cell"'
501
- + ' id="ctc_save_' + rule + '_' + qsid + '_cell">' + "\n"
502
- + '<input type="button" class="button ctc-save-input"'
503
- + ' id="ctc_save_' + rule + '_' + qsid + '"'
504
- + ' name="ctc_save_' + rule + '_' + qsid + '"'
505
- + ' value="Save" /></div>' + "\n" )
506
- + '</div><!-- end input row -->' + "\n";
507
- //console.log( html );
508
- } else {
509
- //console.log( 'sel_val ' + qsid + ' is empty' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
510
  }
511
  return html;
512
  },
@@ -530,17 +603,57 @@
530
  * The "setup" functions initialize jQuery UI widgets
531
  */
532
  setup_iris: function( obj ) {
 
533
  var self = this;
 
 
 
 
 
 
534
  try {
535
- $( obj ).iris( {
536
- change: function( e, ui ) {
537
-
538
- $( obj ).data( 'color', ui.color.toString() );
 
 
 
 
 
539
  self.coalesce_inputs( obj );
540
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
541
  } );
 
542
  } catch ( exn ) {
543
- self.jquery_exception( exn, 'Iris Color Picker' );
 
 
 
 
 
 
 
 
 
 
 
544
  }
545
  },
546
 
@@ -605,7 +718,7 @@
605
  }
606
  } ).data( 'menu' , {} );
607
  } catch ( exn ) {
608
- self.jquery_exception( exn, 'Rule Menu' );
609
  }
610
  },
611
 
@@ -618,26 +731,37 @@
618
  selectFirst: true,
619
  autoFocus: true,
620
  select: function( e, ui ) {
 
621
  e.preventDefault();
622
- if ( self.is_empty( self.current_qsdata.value ) ) {
623
- self.current_qsdata[ 'value' ] = {};
624
- }
625
- self.current_qsdata.value[ ui.item.label ] = { 'child': '' };
626
  var newrule = ui.item.label.replace( /[^\w\-]/g, self.to_ascii ),
627
- n = $( self.input_row( self.current_qsid, newrule, 'ovrd', self.current_qsdata ) ),
 
628
  first;
629
- $( '#ctc_sel_ovrd_rule_inputs' ).append( n );
 
 
 
 
 
 
 
 
 
 
 
 
 
630
  $( '#ctc_new_rule_menu' ).val( '' );
631
 
632
- n.find( 'input[type="text"]' ).each( function( ndx, el ) {
633
  if (! first) first = el;
634
  if ( $( el ).hasClass( 'color-picker' ) )
635
- self.setup_iris( el );
636
  } );
637
  if ( first )
638
  $( first ).focus();
639
  if ( self.jquery_err.length )
640
- self.jquery_notice();
641
  return false;
642
  },
643
  focus: function( e ) {
@@ -645,7 +769,7 @@
645
  }
646
  } ).data( 'menu' , {} );
647
  } catch ( exn ) {
648
- self.jquery_exception( exn, 'New Rule Menu' );
649
  }
650
  },
651
 
@@ -654,13 +778,13 @@
654
  if ( $( '#ctc_theme_child' ).length && $( '#ctc_child_type_existing' ).is( ':checked' ) ) {
655
  var child = $( '#ctc_theme_child' ).val();
656
  if ( !self.is_empty( child ) ) {
657
- $( '#ctc_child_name' ).val( ctcAjax.themes[ 'child' ][ child ].Name );
658
- $( '#ctc_child_author' ).val( ctcAjax.themes[ 'child' ][ child ].Author );
659
- $( '#ctc_child_version' ).val( ctcAjax.themes[ 'child' ][ child ].Version );
660
- $( '#ctc_child_authoruri' ).val( ctcAjax.themes[ 'child' ][ child ].AuthorURI );
661
- $( '#ctc_child_themeuri' ).val( ctcAjax.themes[ 'child' ][ child ].ThemeURI );
662
- $( '#ctc_child_descr' ).val( ctcAjax.themes[ 'child' ][ child ].Descr );
663
- $( '#ctc_child_tags' ).val( ctcAjax.themes[ 'child' ][ child ].Tags );
664
  $( '#ctc_duplicate_theme' ).prop( 'checked', false );
665
  $( '#ctc_duplicate_theme_slug' ).val( '' );
666
  $( '#input_row_duplicate_theme' ).show();
@@ -681,7 +805,7 @@
681
  } );
682
  }
683
  $( '#ctc_error_notice' ).html( errorHtml );
684
- $('html, body').animate({ scrollTop: 0 }, 'slow');
685
  },
686
 
687
  set_parent_menu: function( obj ) {
@@ -698,7 +822,7 @@
698
  if ( !self.is_empty( ctcAjax.themes.child[ obj.value ] ) ) {
699
  template = ctcAjax.themes.child[ obj.value ].Template,
700
  parent = $( '#ctc_theme_parnt' ).val();
701
- console.log( 'template: ' + template + ' parent: ' + parent );
702
  if ( template == parent ) {
703
  $( '#ctc_child_name' ).val( ctcAjax.themes.child[ obj.value ].Name );
704
  $( '#ctc_child_author' ).val( ctcAjax.themes.child[ obj.value ].Author );
@@ -714,6 +838,7 @@
714
 
715
  set_query: function( value ) {
716
  var self = this;
 
717
  //console.log( 'set_query: ' + value );
718
  self.current_query = value;
719
  $( '#ctc_sel_ovrd_query' ).val( '' );
@@ -722,26 +847,31 @@
722
  $( '#ctc_sel_ovrd_selector_selected' ).html( '&nbsp;' );
723
  //$( '#ctc_sel_ovrd_rule_inputs' ).html( '' );
724
  self.load_selectors();
 
725
  },
726
 
727
  set_selector: function( value, label ) {
728
  var self = this;
 
729
  //console.log( 'set_selector: ' + value + ' label: ' + label );
730
  $( '#ctc_sel_ovrd_selector' ).val( '' );
731
  self.current_qsid = value;
732
  self.reload_menus = false;
733
  self.load_selector_values();
 
734
  },
735
 
736
  set_rule: function( value, label ) {
737
  //console.log( 'set_rule: ' + value + ' label: ' + label );
738
  var self = this;
 
739
  $( '#ctc_rule_menu' ).val( '' );
740
  $( '#ctc_rule_menu_selected' ).text( label );
741
  $( '.ctc-rewrite-toggle' ).text( self.getxt( 'rename' ) );
742
  $( '#ctc_rule_value_inputs, #ctc_input_row_rule_header' ).show();
743
  // retrieve unique values by rule
744
  self.query_css( 'rule_val', value );
 
745
  },
746
 
747
  set_qsid: function( obj ) {
@@ -852,9 +982,9 @@
852
  }
853
  self.reload_menus = true;
854
  } else if ( ( $imports = $( '#ctc_child_imports' ) )
855
- && 'ctc_save_imports' == $( obj ).attr( 'id' ) ) {
856
  postdata[ 'ctc_child_imports' ] = $imports.val();
857
- } else if ( 'ctc_is_debug' == $( obj ).attr( 'id' ) ) {
858
  postdata[ 'ctc_is_debug' ] = $( '#ctc_is_debug' ).is( ':checked' ) ? 1 : 0;
859
  } else {
860
  // coalesce inputs
@@ -889,16 +1019,18 @@
889
  ajax_post: function( obj, data, datatype ) {
890
  var self = this,
891
  url = ctcAjax.ajaxurl;
892
- //console.log( 'ajax_post: ' + obj );
893
- //console.log( data );
894
  // get ajax url from localized object
895
  $.ajax( {
896
  url: url,
897
  data: data,
898
- dataType: self.is_empty( datatype ) ? 'json' : datatype,
 
 
899
  type: 'POST'
900
  } ).done( function( response ) {
901
- //console.log( response );
902
  self.handle_success( obj, response );
903
  } ).fail( function() {
904
  self.handle_failure( obj );
@@ -909,7 +1041,7 @@
909
  var self = this;
910
  //console.log( 'handle_failure: ' + obj );
911
  $( '.query-icon, .save-icon' ).removeClass( 'spinner' ).addClass( 'failure' );
912
- $( 'input[type=submit], input[type=button], input[type=checkbox]' ).prop( 'disabled', false );
913
  $( '.ajax-pending' ).removeClass( 'ajax-pending' );
914
  //FIXME: return fail text in ajax response
915
  if ( 'preview' == obj )
@@ -934,7 +1066,7 @@
934
  // show check mark
935
  // FIXME: distinction between save and query, update specific status icon
936
  $( '.query-icon, .save-icon' ).addClass( 'success' );
937
- $( 'input[type=submit], input[type=button], input[type=checkbox]' ).prop( 'disabled', false );
938
  // update ui from each response object
939
  $( response ).each( function() {
940
  if ( 'function' == typeof self.update[ this.obj ] ) {
@@ -954,8 +1086,8 @@
954
  self.jquery_err.push( '<code><small>' + type + ': ' + exn.message + fn + ln + '</small></code>' );
955
  },
956
 
957
- jquery_notice: function() {
958
-
959
  var self = this,
960
  culprits = [],
961
  errors = [];
@@ -969,9 +1101,9 @@
969
  }
970
  } );
971
  errors.push( '<strong>' + self.getxt( 'js' ) + '</strong> ' + self.getxt( 'contact' ) );
972
- if ( 1 == ctcAjax.is_debug ) {
973
  errors.push( self.jquery_err.join( '<br/>' ) );
974
- }
975
  if ( culprits.length ) {
976
  errors.push( self.getxt( 'jquery' ) + '<br/>' + culprits.join( '<br/>' ) );
977
  }
@@ -1007,13 +1139,13 @@
1007
  html += self.input_row( self.current_qsid, rule, 'ovrd', self.current_qsdata );
1008
  } );
1009
  $( '#ctc_sel_ovrd_rule_inputs' ).html( html ).find( '.color-picker' ).each( function() {
1010
- self.setup_iris( this );
1011
  } );
1012
  self.coalesce_inputs( '#ctc_child_all_0_swatch' );
1013
  $( '#ctc_sel_ovrd_rule_header' ).show();
1014
  }
1015
  if ( self.jquery_err.length ) {
1016
- self.jquery_notice();
1017
  } else {
1018
  //console.log( 'reload menus: ' + ( self.reload_menus ? 'true' : 'false' ) );
1019
  if ( self.reload_menus ) {
@@ -1029,7 +1161,7 @@
1029
  //self.scrolltop();
1030
  }
1031
  },
1032
- // render list of unique values for given rule on Rule/Value tab
1033
  rule_val: function( res ) {
1034
  //console.log( 'update.rule_val: ' + res.key );
1035
  //console.log( res.data );
@@ -1070,7 +1202,7 @@
1070
  self.coalesce_inputs( this );
1071
  } );
1072
  },
1073
- // render list of selectors grouped by query for given value on Rule/Value Tab
1074
  val_qry: function( res ) {
1075
  var self = this,
1076
  html = '';
@@ -1089,12 +1221,12 @@
1089
  }
1090
  selector = '#ctc_selector_' + rule + '_' + res.key + '_rows';
1091
  $( selector ).html( html ).find( '.color-picker' ).each( function() {
1092
- self.setup_iris( this );
1093
  } );
1094
  $( selector ).find( '.ctc-swatch' ).each( function() {
1095
  self.coalesce_inputs( this );
1096
  } );
1097
- if ( self.jquery_err.length ) self.jquery_notice();
1098
  },
1099
  // populate list of queries and attach to query input element
1100
  queries: function( res ) {
@@ -1174,23 +1306,6 @@
1174
  }
1175
  }
1176
  if ( self.is_empty( self.jquery_err ) ){
1177
- // bind event handlers
1178
- // these elements get replaced so use delegated events
1179
- $( '#ctc_main' ).on( 'focus', '.color-picker', function() { //'.ctc-option-panel-container'
1180
- //set_notice( '' )
1181
- try {
1182
- $( '.color-picker' ).not( this ).iris( 'hide' );
1183
- $( this ).iris( 'toggle' );
1184
- $( '.iris-picker' ).css( {'position':'absolute', 'z-index':10} );
1185
- } catch ( exn ) {
1186
- self.jquery_exception( exn, 'Iris Color Picker' );
1187
- }
1188
- } );
1189
-
1190
- $( '#ctc_main' ).on( 'change', '.ctc-child-value, input[type=checkbox]', function() {
1191
- self.coalesce_inputs( this );
1192
- } );
1193
-
1194
  $( '#ctc_main' ).on( 'click', '.ctc-selector-handle', function( e ) {
1195
  //'.ctc-option-panel-container'
1196
  e.preventDefault();
@@ -1210,10 +1325,12 @@
1210
  $( '#' + id + '_container' ).fadeToggle( 'fast' );
1211
  $( '.ctc-selector-container' ).not( '#' + id + '_container' ).fadeOut( 'fast' );
1212
  } );
1213
- $( '#ctc_main' ).on( 'click', '.ctc-save-input[type=button]', function( e ) {
 
1214
  if ( $( this ).hasClass( 'ajax-pending' ) ) return false;
1215
  $( this ).addClass( 'ajax-pending' );
1216
  self.save( this ); // refresh menus after updating data
 
1217
  } );
1218
  $( '#ctc_main' ).on( 'click', '.ctc-selector-edit', function( e ) {
1219
  e.preventDefault();
@@ -1333,7 +1450,7 @@
1333
  setTimeout( self.fade_update_notice, 20000 );
1334
  } else {
1335
  //$( '.ctc-select' ).css( { 'visibility': 'visible' } ).show();
1336
- self.jquery_notice();
1337
  }
1338
  },
1339
  // object properties
@@ -1343,7 +1460,11 @@
1343
  current_query: 'base',
1344
  current_qsid: null,
1345
  current_qsdata: {},
1346
- jquery_err: []
 
 
 
 
1347
  };
1348
  } ( jQuery ) );
1349
 
2
  * Script: chld-thm-cfg.js
3
  * Plugin URI: http://www.childthemeconfigurator.com/
4
  * Description: Handles jQuery, AJAX and other UI
5
+ * Version: 1.7.5
6
  * Author: Lilaea Media
7
  * Author URI: http://www.lilaeamedia.com/
8
  * License: GPLv2
9
  * Copyright (C) 2014-2015 Lilaea Media
10
  */
11
+
12
+ // ** for muliple property values: **
13
+ // make sure sequence is passed with rule/val updates
14
+ // determine sequence based on sequence of value array
15
+ // add sequence to input name
16
+
17
  ( function( $ ) {
18
  $.chldthmcfg = {
19
  //console.log( 'executing main function' );
37
  return ascii;
38
  },
39
 
40
+ /**
41
+ * is_empty
42
+ * return true if value evaluates to false, null, null string,
43
+ * empty array, empty object or undefined
44
+ * but NOT 0 ( zero returns false )
45
+ */
46
  is_empty: function( obj ) {
47
  // first bail when definitely empty or undefined ( true ) NOTE: numeric zero returns false !
48
  if ( 'undefined' == typeof obj || false === obj || null === obj || '' === obj ) { return true; }
66
  // this must be an unsupported datatype, so return not empty
67
  return false;
68
  },
69
+
70
+ /**
71
+ * theme_exists
72
+ * returns true if theme is already present for type
73
+ */
74
  theme_exists: function( testslug, testtype ) {
75
  var exists = false;
76
  $.each( ctcAjax.themes, function( type, theme ) {
134
  var panelid = id + '_panel';
135
  $( '.nav-tab' ).removeClass( 'nav-tab-active' );
136
  $( '.ctc-option-panel' ).removeClass( 'ctc-option-panel-active' );
137
+ //$( '.ctc-selector-container' ).hide();
138
  $( id ).addClass( 'nav-tab-active' );
139
  $( '.ctc-option-panel-container' ).scrollTop( 0 );
140
  $( panelid ).addClass( 'ctc-option-panel-active' );
165
  },
166
 
167
  coalesce_inputs: function( obj ) {
168
+ //**console.log( 'coalesce_inputs ' + $( obj ).attr( 'id' ) );
169
  var self = this,
170
+ id = $( obj ).attr( 'id' ),
171
+ regex = /^(ctc_(ovrd|\d+)_(parent|child)_([0-9a-z\-]+)_(\d+?)(_(\d+))?)(_\w+)?$/,
172
  container = $( obj ).parents( '.ctc-selector-row, .ctc-parent-row' ).first(),
173
  swatch = container.find( '.ctc-swatch' ).first(),
174
  cssrules = { 'parent': {}, 'child': {} },
193
  inputseq = inputparts[ 2 ],
194
  inputtheme = inputparts[ 3 ],
195
  inputrule = ( 'undefined' == typeof inputparts[ 4 ] ? '' : inputparts[ 4 ] ),
196
+ rulevalid = inputparts[ 7 ],
197
  qsid = inputparts[ 5 ],
198
+ rulepart = ( 'undefined' == typeof inputparts[ 7 ] ? '' : inputparts[ 8 ] ),
199
+ value = ( 'parent' == inputtheme ? $( this ).text().replace( /!$/, '' ) :
200
+ ( 'seq' != inputrule && 'ctc_delete_query_selector' == id ? '' : $( this ).val() ) ), // clear values if delete was clicked
201
+ important = ( 'seq' == inputrule ? false : 'ctc_' + inputseq + '_child_' + inputrule + '_i_' + qsid + '_' + rulevalid ),
202
  parts, subparts;
203
+ //**console.log( inputparts );
204
+ //**console.log( 'value: ' + value );
 
 
 
205
  if ( 'child' == inputtheme ) {
206
+ if ( !self.is_empty( $( this ).data( 'color' ) ) ) {
207
+ value = self.color_text( $( this ).data( 'color' ) );
208
+ $( this ).data( 'color', null );
209
+ }
210
+ postdata[ inputid ] = value;
211
+ if ( important )
212
+ postdata[ important ] = ( $( '#' + important ).is( ':checked' ) ) ? 1 : 0;
213
  }
214
+ if ( '' !== value ) {
215
  // handle specific inputs
216
  if ( !self.is_empty( rulepart ) ) {
 
217
  switch( rulepart ) {
218
  case '_border_width':
219
  cssrules[ inputtheme ][ inputrule + '-width' ] = ( 'none' == value ? 0 : value );
228
  cssrules[ inputtheme ][ 'background-image' ] = self.image_url( inputtheme, value );
229
  break;
230
  case '_background_color':
231
+ cssrules[ inputtheme ][ 'background-color' ] = value; // was obj.value ???
232
  break;
233
  case '_background_color1':
234
  gradient[ inputtheme ].start = value;
246
  } else {
247
  // handle borders
248
  if ( parts = inputrule.toString().match( /^border(\-(top|right|bottom|left))?$/ ) && !value.match( /none/ ) ) {
249
+ var borderregx = new RegExp( self.border_regx + self.color_regx, 'i' ),
250
+ subparts = value.toString().match( borderregx );
251
+ //**console.log( 'border after regex: ');
252
+ //**console.log( value );
253
+ //**console.log( borderregx );
254
+ //**console.log( subparts );
255
+ if ( !self.is_empty( subparts ) ) {
256
+ subparts.shift();
257
+ cssrules[ inputtheme ][ inputrule + '-width' ] = subparts.shift() || '';
258
+ subparts.shift();
259
+ cssrules[ inputtheme ][ inputrule + '-style' ] = subparts.shift() || '';
260
+ cssrules[ inputtheme ][ inputrule + '-color' ] = subparts.shift() || '';
261
+ }
262
  // handle background images
263
  } else if ( 'background-image' == inputrule && !value.match( /none/ ) ) {
264
  if ( value.toString().match( /url\(/ ) ) {
265
  cssrules[ inputtheme ][ 'background-image' ] = self.image_url( inputtheme, value );
266
  } else {
267
+ var gradregex = new RegExp( self.grad_regx + self.color_regx + self.color_regx, 'i' ),
268
+ subparts = value.toString().match( gradregex );
269
+ //**console.log( 'background-image after regex: ');
270
+ //**console.log( value );
271
+ //**console.log( gradregex );
272
+ //**console.log( subparts );
273
+ if ( !self.is_empty( subparts ) && subparts.length > 2 ) {
274
+ subparts.shift();
275
+ gradient[ inputtheme ].origin = subparts.shift() || 'top';
276
+ gradient[ inputtheme ].start = subparts.shift() || 'transparent';
277
+ gradient[ inputtheme ].end = subparts.shift() || 'transparent';
278
  has_gradient[ inputtheme ] = true;
279
  } else {
280
  cssrules[ inputtheme ][ 'background-image' ] = value;
292
  if ( has_gradient.parent ) {
293
  swatch.ctcgrad( gradient.parent.origin, [ gradient.parent.start, gradient.parent.end ] );
294
  }
295
+ //**console.log( 'combined css rules' );
296
+ //**console.log( cssrules );
297
  swatch.css( cssrules.parent );
298
  if ( !( swatch.attr( 'id' ).toString().match( /parent/ ) ) ) {
299
  if ( has_gradient.child ) {
300
  swatch.ctcgrad( gradient.child.origin, [ gradient.child.start, gradient.child.end ] );
301
  }
302
+ //console.log( cssrules.child );
303
  swatch.css( cssrules.child );
304
  }
305
  swatch.css( {'z-index':-1} );
308
  },
309
 
310
  decode_value: function( rule, value ) {
311
+ //**console.log( 'in decode_value ( ' + rule + ' ...' );
312
  value = ( 'undefined' == typeof value ? '' : value );
313
  var self = this,
314
+ obj = {
315
+ 'orig': value,
316
+ 'names': [ '' ],
317
+ 'values': [ value ]
318
+ };
319
  if ( rule.toString().match( /^border(\-(top|right|bottom|left))?$/ ) ) {
320
+ var regex = new RegExp( self.border_regx + '(' + self.color_regx + ')?', 'i' ),
321
+ params = value.toString().match( regex );
322
+ if ( self.is_empty( params ) ) params = [];
323
+ obj.names = [
324
  '_border_width',
325
  '_border_style',
326
  '_border_color',
327
  ];
328
+ orig = params.shift();
329
+ //**console.log( value );
330
+ //**console.log( regex );
331
+ //**console.log( params );
332
+ obj.values[ 0 ] = params.shift() || '';
333
+ params.shift();
334
+ obj.values[ 1 ] = params.shift() || '';
335
+ params.shift();
336
+ obj.values[ 2 ] = params.shift() || '';
337
  } else if ( rule.toString().match( /^background\-image/ ) ) {
338
+ obj.names = [
339
  '_background_url',
340
  '_background_origin',
341
  '_background_color1',
342
  '_background_color2'
343
  ];
344
+ obj.values = [ '', '', '', '' ];
345
+ if ( !self.is_empty( value ) && !( value.toString().match( /(url|none)/ ) ) ) {
346
+ var params = value.toString().split( /:/ ),
347
+ stop1, stop2;
348
+ //**console.log( value );
349
+ //**console.log( params );
350
+ obj.values[ 1 ] = params.shift() || '';
351
+ obj.values[ 2 ] = params.shift() || '';
352
+ stop1 = params.shift() || '';
353
+ obj.values[ 3 ] = params.shift() || '';
354
+ stop2 = params.shift() || '';
355
+ obj.orig = [
356
+ obj.values[ 1 ],
357
+ obj.values[ 2 ],
358
+ obj.values[ 3 ]
359
  ].join( ' ' );
360
  } else {
361
+ obj.values[ 0 ] = value;
362
  }
 
 
 
363
  }
364
+ //**console.log( obj );
365
  return obj;
366
  },
367
 
467
  get_filtered_rules: function( request, response ) {
468
  //console.log( 'get_filtered_rules' );
469
  var arr = [],
470
+ matcher = new RegExp( $.ui.autocomplete.escapeRegex( request.term ), "i" ); //,
 
 
471
  $.each( $( '#ctc_rule_menu' ).data( 'menu' ), function( key, val ) {
472
+ //multiple versions of rule ok
473
  if ( matcher.test( key ) ) {
 
 
 
 
 
 
 
 
 
 
 
 
474
  arr.push( { 'label': key, 'value': val } );
475
  }
476
  } );
478
  },
479
 
480
  /**
481
+ * parent and child values are stored in separate arrays
482
+ * this function puts them into parent/child columns by rulevalid
483
  */
484
+ merge_ruleval_arrays: function( rule, value, isnew ) {
485
+ //**console.log( 'merge_ruleval_arrays' );
486
  var self = this,
487
+ valarr = {};
488
+ nextval = isnew ? value.child.pop() : null; // if new rule, pop off the top before counting
489
+ //**console.log( value );
490
+ $.each( [ 'parnt', 'child' ], function( ndx, template ) {
491
+ // iterate through parent and child val arrays and populate new assoc array with parent/child for each rulevalid
492
+ if ( !self.is_empty( value[ template ] ) ) {
493
+ $.each( value[ template ], function( ndx2, val ) {
494
+ if ( isnew ) {
495
+ // if new rule, increment new rulevalid but do not add to parent/child assoc array
496
+ if ( parseInt( val[ 2 ] ) >= parseInt( nextval[ 2 ] ) ) nextval[ 2 ] = parseInt( val[ 2 ] ) + 1;
497
+ } else {
498
+ // add to parent/child assoc array with rulevalid as key
499
+ if ( self.is_empty( valarr[ val[ 2 ] ] ) ) valarr[ val[ 2 ] ] = {};
500
+ valarr[ val[ 2 ] ][ template ] = val;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
501
  }
 
 
 
 
 
 
502
  } );
 
 
 
 
503
  }
504
+ } );
505
+ // if new rule, create new parent child assoc array element with new rulevalid as key
506
+ if ( isnew ) {
507
+ valarr[ nextval[ 2 ] ] = {
508
+ parnt: [],
509
+ child: nextval
510
+ };
511
+ }
512
+ return valarr;
513
+ },
514
+
515
+ /**
516
+ * input_row
517
+ * render individual row of inputs for a given selector/rule combination
518
+ * qsid query/selector id
519
+ * rule css property
520
+ * seq panel id from rule/value tab
521
+ * data contains all rules/values for selector
522
+ * isnew is passed true when new rule is selected from menu
523
+ */
524
+ input_row: function( qsid, rule, seq, data, isnew ) {
525
+ var self = this,
526
+ html = '';
527
+ if ( !self.is_empty( data ) && !self.is_empty( data.value ) && !self.is_empty( data.value[ rule ] ) ) {
528
+ var value = data.value[ rule ],
529
+ valarr = self.merge_ruleval_arrays( rule, value, isnew );
530
+ $.each( valarr, function( ndx, val ) {
531
+ var pval = self.decode_value( rule, self.is_empty( val.parnt ) ? '' : val.parnt[ 0 ] ),
532
+ pimp = self.is_empty( val.parnt ) || 0 == val.parnt[ 1 ] ? 0 : 1,
533
+ cval = self.decode_value( rule, self.is_empty( val.child ) ? '' : val.child[ 0 ] ),
534
+ cimp = self.is_empty( val.child ) || 0 == val.child[ 1 ] ? 0 : 1;
535
+ html += '<div class="ctc-' + ( 'ovrd' == seq ? 'input' : 'selector' ) + '-row clearfix"><div class="ctc-input-cell">';
536
+ if ( 'ovrd' == seq ) {
537
+ html += rule.replace( /\d+/g, self.from_ascii );
538
+ } else {
539
+ html += data.selector + '<br/><a href="#" class="ctc-selector-edit"'
540
+ + ' id="ctc_selector_edit_' + qsid + '" >' + self.getxt( 'edit' ) + '</a> '
541
+ + ( self.is_empty( pval.orig ) ? self.getxt( 'child_only' ) : '' );
542
+ }
543
+ html += '</div><div class="ctc-parent-value ctc-input-cell"' + ( 'ovrd' != seq ? ' style="display:none"' : '' )
544
+ + ' id="ctc_' + seq + '_parent_' + rule + '_' + qsid + '_' + ndx + '">'
545
+ + ( self.is_empty( pval.orig ) ? '[no value]' : pval.orig + ( pimp ? self.getxt( 'important' ) : '' ) )
546
+ + '</div><div class="ctc-input-cell">';
547
+ if ( !self.is_empty( pval.names ) ) {
548
+ $.each( pval.names, function( namendx, newname ) {
549
+ newname = ( self.is_empty( newname ) ? '' : newname );
550
+ html += '<div class="ctc-child-input-cell clear">';
551
+ var id = 'ctc_' + seq + '_child_' + rule + '_' + qsid + '_' + ndx + newname,
552
+ newval;
553
+ if ( false === ( newval = cval.values.shift() ) ) {
554
+ newval = '';
555
+ }
556
+
557
+ html += ( self.is_empty( newname ) ? '' : self.getxt( newname ) + ':<br/>' )
558
+ + '<input type="text" id="' + id + '" name="' + id + '" class="ctc-child-value'
559
+ + ( ( newname + rule ).toString().match( /color/ ) ? ' color-picker' : '' )
560
+ + ( ( newname ).toString().match( /url/ ) ? ' ctc-input-wide' : '' )
561
+ + '" value="' + self.esc_quot( newval ) + '" /></div>';
562
+ } );
563
+ var impid = 'ctc_' + seq + '_child_' + rule + '_i_' + qsid + '_' + ndx;
564
+ html += '<label for="' + impid + '"><input type="checkbox"'
565
+ + ' id="' + impid + '" name="' + impid + '" value="1" '
566
+ + ( cimp ? 'checked' : '' ) + ' />'
567
+ + self.getxt( 'important' ) + '</label>';
568
+ }
569
+ html += '</div>';
570
+ if ( 'ovrd' != seq ) {
571
+ html += '<div class="ctc-swatch ctc-specific"'
572
+ + ' id="ctc_child_' + rule + '_' + qsid + '_' + ndx + '_swatch">'
573
+ + self.getxt( 'swatch' ) + '</div>'
574
+ + '<div class="ctc-child-input-cell ctc-button-cell"'
575
+ + ' id="ctc_save_' + rule + '_' + qsid + '_' + ndx + '_cell">'
576
+ + '<input type="button" class="button ctc-save-input"'
577
+ + ' id="ctc_save_' + rule + '_' + qsid + '_' + ndx + '"'
578
+ + ' name="ctc_save_' + rule + '_' + qsid + '_' + ndx + '"'
579
+ + ' value="Save" /></div>';
580
+ }
581
+ html += '</div><!-- end input row -->' + "\n";
582
+ } );
583
  }
584
  return html;
585
  },
603
  * The "setup" functions initialize jQuery UI widgets
604
  */
605
  setup_iris: function( obj ) {
606
+ // deprecated: using spectrum for alpha support
607
  var self = this;
608
+ self.setup_spectrum( obj );
609
+ },
610
+
611
+ setup_spectrum: function( obj ) {
612
+ var self = this,
613
+ colortxt = $( obj ).attr( 'id' ) + '_colortxt';
614
  try {
615
+ $( obj ).spectrum( {
616
+ showInput: true,
617
+ allowEmpty: true,
618
+ showAlpha: true,
619
+ showInitial: true,
620
+ preferredFormat: "hex", // 'name', //
621
+ clickoutFiresChange: true,
622
+ move: function( color ) {
623
+ $( obj ).data( 'color', color );
624
  self.coalesce_inputs( obj );
625
  }
626
+ } ).on( 'change', function( e ){
627
+ var color = $( this ).spectrum( 'get' );
628
+ //console.log( 'color change: ' + color );
629
+ self.coalesce_inputs( this );
630
+ } ).on( 'keyup', function( e ) {
631
+ // update spectrum ui to match text input after half-second delay
632
+ var $this = this,
633
+ $val = $( this ).val();
634
+ clearTimeout( $( this ).data( 'spectrumTimer' ) );
635
+ $( this ).data( 'spectrumTimer', setTimeout(
636
+ function() {
637
+ self.coalesce_inputs( $this );
638
+ $( $this ).spectrum( 'set', $val );
639
+ },
640
+ 500
641
+ ) );
642
  } );
643
+
644
  } catch ( exn ) {
645
+ self.jquery_exception( exn, 'Spectrum Color Picker' );
646
+ }
647
+ },
648
+
649
+ color_text: function( color ) {
650
+ var self = this;
651
+ if ( self.is_empty( color ) ) {
652
+ return '';
653
+ } else if ( color.getAlpha() < 1 ) {
654
+ return color.toRgbString();
655
+ } else {
656
+ return color.toHexString();
657
  }
658
  },
659
 
718
  }
719
  } ).data( 'menu' , {} );
720
  } catch ( exn ) {
721
+ self.jquery_exception( exn, 'Property Menu' );
722
  }
723
  },
724
 
731
  selectFirst: true,
732
  autoFocus: true,
733
  select: function( e, ui ) {
734
+ //console.log( 'new rule selected' );
735
  e.preventDefault();
 
 
 
 
736
  var newrule = ui.item.label.replace( /[^\w\-]/g, self.to_ascii ),
737
+ n = 1,
738
+ row,
739
  first;
740
+ if ( self.is_empty( self.current_qsdata.value ) ) {
741
+ self.current_qsdata.value = {};
742
+ }
743
+ if ( self.is_empty( self.current_qsdata.value[ ui.item.label ] ) ) {
744
+ self.current_qsdata.value[ ui.item.label ] = {};
745
+ }
746
+ if ( self.is_empty( self.current_qsdata.value[ ui.item.label ].child ) ) {
747
+ self.current_qsdata.value[ ui.item.label ].child = [];
748
+ }
749
+ // seed current qsdata with new blank value with id 1
750
+ // this will be modified during input_row function to be next id in order
751
+ self.current_qsdata.value[ ui.item.label ].child.push( [ '', 0, 1, 1 ] );
752
+ row = $( self.input_row( self.current_qsid, newrule, 'ovrd', self.current_qsdata, true ) );
753
+ $( '#ctc_sel_ovrd_rule_inputs' ).append( row );
754
  $( '#ctc_new_rule_menu' ).val( '' );
755
 
756
+ row.find( 'input[type="text"]' ).each( function( ndx, el ) {
757
  if (! first) first = el;
758
  if ( $( el ).hasClass( 'color-picker' ) )
759
+ self.setup_spectrum( el );
760
  } );
761
  if ( first )
762
  $( first ).focus();
763
  if ( self.jquery_err.length )
764
+ self.jquery_notice( 'setup_new_rule_menu' );
765
  return false;
766
  },
767
  focus: function( e ) {
769
  }
770
  } ).data( 'menu' , {} );
771
  } catch ( exn ) {
772
+ self.jquery_exception( exn, 'New Property Menu' );
773
  }
774
  },
775
 
778
  if ( $( '#ctc_theme_child' ).length && $( '#ctc_child_type_existing' ).is( ':checked' ) ) {
779
  var child = $( '#ctc_theme_child' ).val();
780
  if ( !self.is_empty( child ) ) {
781
+ $( '#ctc_child_name' ).val( ctcAjax.themes.child[ child ].Name );
782
+ $( '#ctc_child_author' ).val( ctcAjax.themes.child[ child ].Author );
783
+ $( '#ctc_child_version' ).val( ctcAjax.themes.child[ child ].Version );
784
+ $( '#ctc_child_authoruri' ).val( ctcAjax.themes.child[ child ].AuthorURI );
785
+ $( '#ctc_child_themeuri' ).val( ctcAjax.themes.child[ child ].ThemeURI );
786
+ $( '#ctc_child_descr' ).val( ctcAjax.themes.child[ child ].Descr );
787
+ $( '#ctc_child_tags' ).val( ctcAjax.themes.child[ child ].Tags );
788
  $( '#ctc_duplicate_theme' ).prop( 'checked', false );
789
  $( '#ctc_duplicate_theme_slug' ).val( '' );
790
  $( '#input_row_duplicate_theme' ).show();
805
  } );
806
  }
807
  $( '#ctc_error_notice' ).html( errorHtml );
808
+ $( 'html, body' ).animate( { scrollTop: 0 }, 'slow' );
809
  },
810
 
811
  set_parent_menu: function( obj ) {
822
  if ( !self.is_empty( ctcAjax.themes.child[ obj.value ] ) ) {
823
  template = ctcAjax.themes.child[ obj.value ].Template,
824
  parent = $( '#ctc_theme_parnt' ).val();
825
+ //console.log( 'template: ' + template + ' parent: ' + parent );
826
  if ( template == parent ) {
827
  $( '#ctc_child_name' ).val( ctcAjax.themes.child[ obj.value ].Name );
828
  $( '#ctc_child_author' ).val( ctcAjax.themes.child[ obj.value ].Author );
838
 
839
  set_query: function( value ) {
840
  var self = this;
841
+ if ( self.is_empty( value ) ) return false;
842
  //console.log( 'set_query: ' + value );
843
  self.current_query = value;
844
  $( '#ctc_sel_ovrd_query' ).val( '' );
847
  $( '#ctc_sel_ovrd_selector_selected' ).html( '&nbsp;' );
848
  //$( '#ctc_sel_ovrd_rule_inputs' ).html( '' );
849
  self.load_selectors();
850
+ self.scrolltop();
851
  },
852
 
853
  set_selector: function( value, label ) {
854
  var self = this;
855
+ if ( self.is_empty( value ) ) return false;
856
  //console.log( 'set_selector: ' + value + ' label: ' + label );
857
  $( '#ctc_sel_ovrd_selector' ).val( '' );
858
  self.current_qsid = value;
859
  self.reload_menus = false;
860
  self.load_selector_values();
861
+ self.scrolltop();
862
  },
863
 
864
  set_rule: function( value, label ) {
865
  //console.log( 'set_rule: ' + value + ' label: ' + label );
866
  var self = this;
867
+ if ( self.is_empty( value ) ) return false;
868
  $( '#ctc_rule_menu' ).val( '' );
869
  $( '#ctc_rule_menu_selected' ).text( label );
870
  $( '.ctc-rewrite-toggle' ).text( self.getxt( 'rename' ) );
871
  $( '#ctc_rule_value_inputs, #ctc_input_row_rule_header' ).show();
872
  // retrieve unique values by rule
873
  self.query_css( 'rule_val', value );
874
+ self.scrolltop();
875
  },
876
 
877
  set_qsid: function( obj ) {
982
  }
983
  self.reload_menus = true;
984
  } else if ( ( $imports = $( '#ctc_child_imports' ) )
985
+ && 'ctc_save_imports' == id ) {
986
  postdata[ 'ctc_child_imports' ] = $imports.val();
987
+ } else if ( 'ctc_is_debug' == id ) {
988
  postdata[ 'ctc_is_debug' ] = $( '#ctc_is_debug' ).is( ':checked' ) ? 1 : 0;
989
  } else {
990
  // coalesce inputs
1019
  ajax_post: function( obj, data, datatype ) {
1020
  var self = this,
1021
  url = ctcAjax.ajaxurl;
1022
+ //**console.log( 'ajax_post: ' + obj );
1023
+ //**console.log( data );
1024
  // get ajax url from localized object
1025
  $.ajax( {
1026
  url: url,
1027
  data: data,
1028
+ dataType: ( self.is_empty( datatype ) ? 'json' : datatype ),
1029
+ // 'ctc_update' == data.action && // 'rule_val' == obj ? 'text' : // 'qsid' == obj ? 'text' :
1030
+ // 'ctc_update' == data.action && 'qsid' == obj ? 'text' :
1031
  type: 'POST'
1032
  } ).done( function( response ) {
1033
+ //**console.log( response );
1034
  self.handle_success( obj, response );
1035
  } ).fail( function() {
1036
  self.handle_failure( obj );
1041
  var self = this;
1042
  //console.log( 'handle_failure: ' + obj );
1043
  $( '.query-icon, .save-icon' ).removeClass( 'spinner' ).addClass( 'failure' );
1044
+ $( 'input[type=submit], input[type=button], input[type=checkbox],.ctc-delete-input' ).prop( 'disabled', false );
1045
  $( '.ajax-pending' ).removeClass( 'ajax-pending' );
1046
  //FIXME: return fail text in ajax response
1047
  if ( 'preview' == obj )
1066
  // show check mark
1067
  // FIXME: distinction between save and query, update specific status icon
1068
  $( '.query-icon, .save-icon' ).addClass( 'success' );
1069
+ $( 'input[type=submit], input[type=button], input[type=checkbox],.ctc-delete-input' ).prop( 'disabled', false );
1070
  // update ui from each response object
1071
  $( response ).each( function() {
1072
  if ( 'function' == typeof self.update[ this.obj ] ) {
1086
  self.jquery_err.push( '<code><small>' + type + ': ' + exn.message + fn + ln + '</small></code>' );
1087
  },
1088
 
1089
+ jquery_notice: function( fn ) {
1090
+ //console.log( fn );
1091
  var self = this,
1092
  culprits = [],
1093
  errors = [];
1101
  }
1102
  } );
1103
  errors.push( '<strong>' + self.getxt( 'js' ) + '</strong> ' + self.getxt( 'contact' ) );
1104
+ //if ( 1 == ctcAjax.is_debug ) {
1105
  errors.push( self.jquery_err.join( '<br/>' ) );
1106
+ //}
1107
  if ( culprits.length ) {
1108
  errors.push( self.getxt( 'jquery' ) + '<br/>' + culprits.join( '<br/>' ) );
1109
  }
1139
  html += self.input_row( self.current_qsid, rule, 'ovrd', self.current_qsdata );
1140
  } );
1141
  $( '#ctc_sel_ovrd_rule_inputs' ).html( html ).find( '.color-picker' ).each( function() {
1142
+ self.setup_spectrum( this );
1143
  } );
1144
  self.coalesce_inputs( '#ctc_child_all_0_swatch' );
1145
  $( '#ctc_sel_ovrd_rule_header' ).show();
1146
  }
1147
  if ( self.jquery_err.length ) {
1148
+ self.jquery_notice( 'update.qsid' );
1149
  } else {
1150
  //console.log( 'reload menus: ' + ( self.reload_menus ? 'true' : 'false' ) );
1151
  if ( self.reload_menus ) {
1161
  //self.scrolltop();
1162
  }
1163
  },
1164
+ // render list of unique values for given rule on Property/Value tab
1165
  rule_val: function( res ) {
1166
  //console.log( 'update.rule_val: ' + res.key );
1167
  //console.log( res.data );
1202
  self.coalesce_inputs( this );
1203
  } );
1204
  },
1205
+ // render list of selectors grouped by query for given value on Property/Value Tab
1206
  val_qry: function( res ) {
1207
  var self = this,
1208
  html = '';
1221
  }
1222
  selector = '#ctc_selector_' + rule + '_' + res.key + '_rows';
1223
  $( selector ).html( html ).find( '.color-picker' ).each( function() {
1224
+ self.setup_spectrum( this );
1225
  } );
1226
  $( selector ).find( '.ctc-swatch' ).each( function() {
1227
  self.coalesce_inputs( this );
1228
  } );
1229
+ if ( self.jquery_err.length ) self.jquery_notice( 'val_qry' );
1230
  },
1231
  // populate list of queries and attach to query input element
1232
  queries: function( res ) {
1306
  }
1307
  }
1308
  if ( self.is_empty( self.jquery_err ) ){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1309
  $( '#ctc_main' ).on( 'click', '.ctc-selector-handle', function( e ) {
1310
  //'.ctc-option-panel-container'
1311
  e.preventDefault();
1325
  $( '#' + id + '_container' ).fadeToggle( 'fast' );
1326
  $( '.ctc-selector-container' ).not( '#' + id + '_container' ).fadeOut( 'fast' );
1327
  } );
1328
+ $( '#ctc_main' ).on( 'click', '.ctc-save-input[type=button], .ctc-delete-input', function( e ) {
1329
+ e.preventDefault();
1330
  if ( $( this ).hasClass( 'ajax-pending' ) ) return false;
1331
  $( this ).addClass( 'ajax-pending' );
1332
  self.save( this ); // refresh menus after updating data
1333
+ return false;
1334
  } );
1335
  $( '#ctc_main' ).on( 'click', '.ctc-selector-edit', function( e ) {
1336
  e.preventDefault();
1450
  setTimeout( self.fade_update_notice, 20000 );
1451
  } else {
1452
  //$( '.ctc-select' ).css( { 'visibility': 'visible' } ).show();
1453
+ self.jquery_notice( 'init' );
1454
  }
1455
  },
1456
  // object properties
1460
  current_query: 'base',
1461
  current_qsid: null,
1462
  current_qsdata: {},
1463
+ jquery_err: [],
1464
+ color_regx: '\\s+(\\#[a-f0-9]{3,6}|rgba?\\([\\d., ]+?\\)|hsla?\\([\\d%., ]+?\\)|[a-z]+)',
1465
+ border_regx: '(\\w+)(\\s+(\\w+))?',
1466
+ grad_regx: '(\\w+)'
1467
+
1468
  };
1469
  } ( jQuery ) );
1470
 
js/chld-thm-cfg.min.js CHANGED
@@ -1 +1 @@
1
- !function(e){e.chldthmcfg={esc_quot:function(e){var t=this;return t.is_empty(e)?e:e.toString().replace(/"/g,"&quot;")},getxt:function(e){return(text=ctcAjax[e+"_txt"])?text:""},from_ascii:function(e){var t=parseInt(e),c=String.fromCharCode(t);return c},to_ascii:function(e){var t=e.charCodeAt(0);return t},is_empty:function(e){if("undefined"==typeof e||!1===e||null===e||""===e)return!0;if(!0===e||"string"==typeof e||"number"==typeof e)return!1;if("object"==typeof e){for(var t in e)if(e.hasOwnProperty(t))return!1;return!0}return!1},theme_exists:function(t,c){var n=!1;return e.each(ctcAjax.themes,function(i,a){return e.each(a,function(e,a){return e!=t||"parnt"!=i&&"new"!=c?void 0:(n=!0,!1)}),n?!1:void 0}),n},validate:function(){var t=this,c=/[^\w\-]/,n=e("#ctc_child_template").length?e("#ctc_child_template").val().toString().replace(c).toLowerCase():"",i=e("#ctc_theme_child").length?e("#ctc_theme_child").val().toString().replace(c).toLowerCase():n,a=e("input[name=ctc_child_type]:checked").val(),r=[];return"new"==a&&(i=n),t.theme_exists(i,a)&&r.push(t.getxt("theme_exists").toString().replace(/%s/,i)),""===i&&r.push(t.getxt("inval_theme")),""===e("#ctc_child_name").val()&&r.push(t.getxt("inval_name")),r.length?(t.set_notice({error:r}),!1):!0},autogen_slugs:function(){if(e("#ctc_theme_parnt").length){for(var t=this,c=e("#ctc_theme_parnt").val(),n=slugbase=c+"-child",i=ctcAjax.themes.parnt[c].Name+" Child",a="",r="",s="00";t.theme_exists(n,"new");)a=""==a?2:a+1,r=s.substring(0,s.length-a.toString().length)+a.toString(),n=slugbase+r;t.testslug=n,t.testname=i+(r.length?" "+r:"")}},focus_panel:function(t){var c=t+"_panel";e(".nav-tab").removeClass("nav-tab-active"),e(".ctc-option-panel").removeClass("ctc-option-panel-active"),e(".ctc-selector-container").hide(),e(t).addClass("nav-tab-active"),e(".ctc-option-panel-container").scrollTop(0),e(c).addClass("ctc-option-panel-active")},selector_input_toggle:function(t){var c,n=this;e("#ctc_rewrite_selector").length?(c=e("#ctc_rewrite_selector_orig").val(),e("#ctc_sel_ovrd_selector_selected").text(c),e(t).text(n.getxt("rename"))):(c=e("#ctc_sel_ovrd_selector_selected").text(),e("#ctc_sel_ovrd_selector_selected").html('<textarea id="ctc_rewrite_selector" name="ctc_rewrite_selector" autocomplete="off"></textarea><input id="ctc_rewrite_selector_orig" name="ctc_rewrite_selector_orig" type="hidden" value="'+n.esc_quot(c)+'"/>'),e("#ctc_rewrite_selector").val(c),e(t).text(n.getxt("cancel")))},fade_update_notice:function(){e(".updated, .error").slideUp("slow",function(){e(".updated").remove()})},coalesce_inputs:function(t){var c=this,n=/^(ctc_(ovrd|\d+)_(parent|child)_([0-9a-z\-]+)_(\d+))(_\w+)?$/,i=e(t).parents(".ctc-selector-row, .ctc-parent-row").first(),a=i.find(".ctc-swatch").first(),r={parent:{},child:{}},s={parent:{origin:"",start:"",end:""},child:{origin:"",start:"",end:""}},l={child:!1,parent:!1},o={};return i.find(".ctc-parent-value, .ctc-child-value").each(function(){var i,a,_=e(this).attr("id"),u=_.toString().match(n),d=u[2],p=u[3],h="undefined"==typeof u[4]?"":u[4],m=u[5],v="undefined"==typeof u[6]?"":u[6],f="parent"==p?e(this).text().replace(/!$/,""):e(this).val(),g="ctc_"+d+"_child_"+h+"_i_"+m;if(c.is_empty(e(this).data("color"))||(f=e(this).data("color"),e(this).data("color",null)),"child"==p&&(o[_]=f,o[g]=e("#"+g).is(":checked")?1:0),""!=f)if(c.is_empty(v))(i=h.toString().match(/^border(\-(top|right|bottom|left))?$/)&&!f.match(/none/))?(a=f.toString().split(/ +/),r[p][h+"-width"]="undefined"==typeof a[0]?"":a[0],r[p][h+"-style"]="undefined"==typeof a[1]?"":a[1],r[p][h+"-color"]="undefined"==typeof a[2]?"":a[2]):"background-image"!=h||f.match(/none/)?"seq"!=h&&(r[p][h]=f):f.toString().match(/url\(/)?r[p]["background-image"]=c.image_url(p,f):(a=f.toString().split(/ +/),a.length>2?(s[p].origin="undefined"==typeof a[0]?"top":a[0],s[p].start="undefined"==typeof a[1]?"transparent":a[1],s[p].end="undefined"==typeof a[2]?"transparent":a[2],l[p]=!0):r[p]["background-image"]=f);else switch(v){case"_border_width":r[p][h+"-width"]="none"==f?0:f;break;case"_border_style":r[p][h+"-style"]=f;break;case"_border_color":r[p][h+"-color"]=f;break;case"_background_url":r[p]["background-image"]=c.image_url(p,f);break;case"_background_color":r[p]["background-color"]=t.value;break;case"_background_color1":s[p].start=f,l[p]=!0;break;case"_background_color2":s[p].end=f,l[p]=!0;break;case"_background_origin":s[p].origin=f,l[p]=!0}}),"undefined"==typeof a||c.is_empty(a.attr("id"))||(a.removeAttr("style"),l.parent&&a.ctcgrad(s.parent.origin,[s.parent.start,s.parent.end]),a.css(r.parent),a.attr("id").toString().match(/parent/)||(l.child&&a.ctcgrad(s.child.origin,[s.child.start,s.child.end]),a.css(r.child)),a.css({"z-index":-1})),o},decode_value:function(e,t){t="undefined"==typeof t?"":t;var c=this,n={orig:t};if(e.toString().match(/^border(\-(top|right|bottom|left))?$/)){var i=t.toString().split(/ +/);n.names=["_border_width","_border_style","_border_color"],n.values=["undefined"==typeof i[0]?"":i[0],"undefined"==typeof i[1]?"":i[1],"undefined"==typeof i[2]?"":i[2]]}else if(e.toString().match(/^background\-image/))if(n.names=["_background_url","_background_origin","_background_color1","_background_color2"],n.values=["","","",""],!1!==c.is_empty(t)||t.toString().match(/(url|none)/))n.values[0]=t;else{var i=t.toString().split(/:/);n.values[1]="undefined"==typeof i[0]?"":i[0],n.values[2]="undefined"==typeof i[1]?"":i[1],n.values[3]="undefined"==typeof i[3]?"":i[3],n.orig=[n.values[1],n.values[2],n.values[3]].join(" ")}else n.names=[""],n.values=[t];return n},image_url:function(e,t){var c,n=this,i=t.toString().match(/url\(['" ]*(.+?)['" ]*\)/),a=n.is_empty(i)?null:i[1],r=ctcAjax.theme_uri+"/"+("parent"==e?ctcAjax.parnt:ctcAjax.child)+"/";return a?c=a.toString().match(/^(data:|https?:|\/)/)?t:"url("+r+a+")":!1},setup_menus:function(){var e=this;e.setup_query_menu(),e.setup_selector_menu(),e.setup_rule_menu(),e.setup_new_rule_menu(),e.load_queries(),e.load_rules(),e.set_query(e.current_query)},load_queries:function(){var e=this;e.query_css("queries",null)},load_selectors:function(){var e=this;e.query_css("selectors",e.current_query)},load_rules:function(){var e=this;e.query_css("rules",null)},load_selector_values:function(){var e=this;e.query_css("qsid",e.current_qsid)},get_queries:function(t,c){var n=[],i=new RegExp(e.ui.autocomplete.escapeRegex(t.term),"i");e.each(this.element.data("menu"),function(e,t){i.test(t)&&n.push({label:t,value:t})}),c(n)},get_selectors:function(t,c){var n=[],i=new RegExp(e.ui.autocomplete.escapeRegex(t.term),"i");e.each(this.element.data("menu"),function(e,t){i.test(e)&&n.push({label:e,value:t})}),c(n)},get_rules:function(t,c){var n=[],i=new RegExp(e.ui.autocomplete.escapeRegex(t.term),"i");e.each(this.element.data("menu"),function(e,t){i.test(e)&&n.push({label:e,value:t})}),c(n)},get_filtered_rules:function(t,c){var n=[],i=new RegExp(e.ui.autocomplete.escapeRegex(t.term),"i"),a=e.chldthmcfg.current_qsdata,r=e.chldthmcfg.is_empty(a)||e.chldthmcfg.is_empty(a.value);e.each(e("#ctc_rule_menu").data("menu"),function(t,c){var s=!1;if(i.test(t)){if(!r&&(e.each(a.value,function(e,c){return t==e.replace(/\d+/g,self.from_ascii)?(s=!0,!1):void 0}),s))return;n.push({label:t,value:c})}}),c(n)},input_row:function(t,c,n,i){var a=this,r="",s=a.is_empty(i)||a.is_empty(i.value)||a.is_empty(i.value[c])?"":i.value[c],l=a.decode_value(c,a.is_empty(s)?"":s.parnt),o=a.is_empty(s)||a.is_empty(s.i_parnt)||1!=s.i_parnt?"":a.getxt("important"),_=a.decode_value(c,a.is_empty(s)?"":s.child),u=a.is_empty(s)||a.is_empty(s.i_child)||1!=s.i_child?0:1,d="ctc_"+n+"_child_"+c+"_i_"+t;return a.is_empty(i)||(r+='<div class="ctc-'+("ovrd"==n?"input":"selector")+'-row clearfix">\n<div class="ctc-input-cell">'+("ovrd"==n?c.replace(/\d+/g,a.from_ascii):i.selector+'<br/><a href="#" class="ctc-selector-edit" id="ctc_selector_edit_'+t+'" >'+a.getxt("edit")+"</a> "+(a.is_empty(l.orig)?a.getxt("child_only"):""))+"</div>\n","ovrd"==n&&(r+='<div class="ctc-parent-value ctc-input-cell" id="ctc_'+n+"_parent_"+c+"_"+t+'">'+(a.is_empty(l.orig)?"[no value]":l.orig+o)+"</div>\n"),r+='<div class="ctc-input-cell">\n',a.is_empty(l.names)||(e.each(l.names,function(e,i){i=a.is_empty(i)?"":i,r+='<div class="ctc-child-input-cell">\n';var s,l="ctc_"+n+"_child_"+c+"_"+t+i;!1===(s=_.values.shift())&&(s=""),r+=(a.is_empty(i)?"":a.getxt(i)+":<br/>")+'<input type="text" id="'+l+'" name="'+l+'" class="ctc-child-value'+((i+c).toString().match(/color/)?" color-picker":"")+(i.toString().match(/url/)?" ctc-input-wide":"")+'" value="'+a.esc_quot(s)+'" />\n</div>\n'}),r+='<label for="'+d+'"><input type="checkbox" id="'+d+'" name="'+d+'" value="1" '+(1===u?"checked":"")+" />"+a.getxt("important")+"</label>\n"),r+="</div>\n"+("ovrd"==n?"":'<div class="ctc-swatch ctc-specific" id="ctc_child_'+c+"_"+t+'_swatch">'+a.getxt("swatch")+'</div>\n<div class="ctc-child-input-cell ctc-button-cell" id="ctc_save_'+c+"_"+t+'_cell">\n<input type="button" class="button ctc-save-input" id="ctc_save_'+c+"_"+t+'" name="ctc_save_'+c+"_"+t+'" value="Save" /></div>\n')+"</div><!-- end input row -->\n"),r},scrolltop:function(){e("html, body, .ctc-option-panel-container").animate({scrollTop:0})},css_preview:function(e){var e,t=this;(e=e.match(/(child|parnt)/)[1])||(e="child"),t.query_css("preview",e)},setup_iris:function(t){var c=this;try{e(t).iris({change:function(n,i){e(t).data("color",i.color.toString()),c.coalesce_inputs(t)}})}catch(n){c.jquery_exception(n,"Iris Color Picker")}},setup_query_menu:function(){var t=this;try{e("#ctc_sel_ovrd_query").autocomplete({source:t.get_queries,minLength:0,selectFirst:!0,autoFocus:!0,select:function(e,c){return t.set_query(c.item.value),!1},focus:function(e){e.preventDefault()}}).data("menu",{})}catch(c){t.jquery_exception(c,"Query Menu")}},setup_selector_menu:function(){var t=this;try{e("#ctc_sel_ovrd_selector").autocomplete({source:t.get_selectors,selectFirst:!0,autoFocus:!0,select:function(e,c){return t.set_selector(c.item.value,c.item.label),!1},focus:function(e){e.preventDefault()}}).data("menu",{})}catch(c){t.jquery_exception(c,"Selector Menu")}},setup_rule_menu:function(){var t=this;try{e("#ctc_rule_menu").autocomplete({source:t.get_rules,selectFirst:!0,autoFocus:!0,select:function(e,c){return t.set_rule(c.item.value,c.item.label),!1},focus:function(e){e.preventDefault()}}).data("menu",{})}catch(c){t.jquery_exception(c,"Rule Menu")}},setup_new_rule_menu:function(){var t=this;try{e("#ctc_new_rule_menu").autocomplete({source:t.get_filtered_rules,selectFirst:!0,autoFocus:!0,select:function(c,n){c.preventDefault(),t.is_empty(t.current_qsdata.value)&&(t.current_qsdata.value={}),t.current_qsdata.value[n.item.label]={child:""};var i,a=n.item.label.replace(/[^\w\-]/g,t.to_ascii),r=e(t.input_row(t.current_qsid,a,"ovrd",t.current_qsdata));return e("#ctc_sel_ovrd_rule_inputs").append(r),e("#ctc_new_rule_menu").val(""),r.find('input[type="text"]').each(function(c,n){i||(i=n),e(n).hasClass("color-picker")&&t.setup_iris(n)}),i&&e(i).focus(),t.jquery_err.length&&t.jquery_notice(),!1},focus:function(e){e.preventDefault()}}).data("menu",{})}catch(c){t.jquery_exception(c,"New Rule Menu")}},set_existing:function(){var t=this;if(e("#ctc_theme_child").length&&e("#ctc_child_type_existing").is(":checked")){var c=e("#ctc_theme_child").val();t.is_empty(c)||(e("#ctc_child_name").val(ctcAjax.themes.child[c].Name),e("#ctc_child_author").val(ctcAjax.themes.child[c].Author),e("#ctc_child_version").val(ctcAjax.themes.child[c].Version),e("#ctc_child_authoruri").val(ctcAjax.themes.child[c].AuthorURI),e("#ctc_child_themeuri").val(ctcAjax.themes.child[c].ThemeURI),e("#ctc_child_descr").val(ctcAjax.themes.child[c].Descr),e("#ctc_child_tags").val(ctcAjax.themes.child[c].Tags),e("#ctc_duplicate_theme").prop("checked",!1),e("#ctc_duplicate_theme_slug").val(""),e("#input_row_duplicate_theme").show())}},set_notice:function(t){var c=this,n="";c.is_empty(t)||e.each(t,function(t,c){n+='<div class="'+t+'"><ul>\n',e(c).each(function(e,t){n+="<li>"+t.toString()+"</li>\n"}),n+="</ul></div>"}),e("#ctc_error_notice").html(n),e("html, body").animate({scrollTop:0},"slow")},set_parent_menu:function(t){e("#ctc_theme_parnt").parents(".ctc-input-row").first().append('<span class="ctc-status-icon spinner"></span>'),e(".spinner").show(),document.location="?page="+ctcAjax.page+"&ctc_parent="+t.value},set_child_menu:function(t){var c,n,i=this;i.is_empty(ctcAjax.themes.child[t.value])||(c=ctcAjax.themes.child[t.value].Template,n=e("#ctc_theme_parnt").val(),console.log("template: "+c+" parent: "+n),c==n?(e("#ctc_child_name").val(ctcAjax.themes.child[t.value].Name),e("#ctc_child_author").val(ctcAjax.themes.child[t.value].Author),e("#ctc_child_version").val(ctcAjax.themes.child[t.value].Version)):(e("#ctc_theme_child").parents(".ctc-input-row").first().append('<span class="ctc-status-icon spinner"></span>'),e(".spinner").show(),document.location="?page="+ctcAjax.page+"&ctc_parent="+c+"&ctc_child="+t.value))},set_query:function(t){var c=this;c.current_query=t,e("#ctc_sel_ovrd_query").val(""),e("#ctc_sel_ovrd_query_selected").text(t),e("#ctc_sel_ovrd_selector").val(""),e("#ctc_sel_ovrd_selector_selected").html("&nbsp;"),c.load_selectors()},set_selector:function(t,c){var n=this;e("#ctc_sel_ovrd_selector").val(""),n.current_qsid=t,n.reload_menus=!1,n.load_selector_values()},set_rule:function(t,c){var n=this;e("#ctc_rule_menu").val(""),e("#ctc_rule_menu_selected").text(c),e(".ctc-rewrite-toggle").text(n.getxt("rename")),e("#ctc_rule_value_inputs, #ctc_input_row_rule_header").show(),n.query_css("rule_val",t)},set_qsid:function(t){var c=this;c.current_qsid=e(t).attr("id").match(/_(\d+)$/)[1],c.focus_panel("#query_selector_options"),c.reload_menus=!0,c.load_selector_values()},set_addl_css:function(){var t,c=this,n=e("#ctc_theme_parnt").val(),i=ctcAjax.theme_uri.replace(/^https?:\/\//,""),a=ctcAjax.homeurl.replace(/^https?/,ctcAjax.ssl?"https":"http"),r=a+"?preview=1&p=x&template="+n+"&stylesheet="+n,s=new RegExp("<link rel=[\"']stylesheet[\"'][^>]+?"+i+"/"+n+"/(.+?\\.css)[^>]+?>","g");c.is_empty(n)||(n!=ctcAjax.parnt?e.get(r,function(c){for(;(t=s.exec(c))&&"style.css"!=t[1];)t[1].match(/bootstrap/)||e(".ctc_checkbox").each(function(c,n){e(this).val()==t[1]&&e(this).prop("checked",!0)});c=null}):e(ctcAjax.addl_css).each(function(t,c){e("#ctc_stylesheet_files .ctc_checkbox").each(function(t,n){e(this).val()==c&&e(this).prop("checked",!0)})}))},query_css:function(t,c,n){var i=this,a={ctc_query_obj:t,ctc_query_key:c},r="#ctc_status_"+t+("val_qry"==t?"_"+c:"");"object"==typeof n&&e.each(n,function(e,t){a["ctc_query_"+e]=t}),e(".query-icon").remove(),e(r+" .ctc-status-icon").remove(),e(r).append('<span class="ctc-status-icon spinner query-icon"></span>'),e(".spinner").show(),a.action=i.is_empty(e("#ctc_action").val())||"plugin"!=e("#ctc_action").val()?"ctc_query":"ctc_plgqry",a._wpnonce=e("#_wpnonce").val(),i.ajax_post(t,a)},save:function(t){var c,n,i,a,r,s=this,l=(ctcAjax.ajaxurl,{}),o=e(t).attr("id");e(t).prop("disabled",!0),e(".ctc-status-icon").remove(),e(t).parent(".ctc-textarea-button-cell, .ctc-button-cell").append('<span class="ctc-status-icon spinner save-icon"></span>'),o.match(/ctc_configtype/)?(e(t).parents(".ctc-input-row").first().append('<span class="ctc-status-icon spinner save-icon"></span>'),l.ctc_configtype=e(t).val()):(c=e("#ctc_new_selectors"))&&"ctc_save_new_selectors"==e(t).attr("id")?(l.ctc_new_selectors=c.val(),(n=e("#ctc_sel_ovrd_query_selected"))&&(l.ctc_sel_ovrd_query=n.text()),s.reload_menus=!0):(i=e("#ctc_child_imports"))&&"ctc_save_imports"==e(t).attr("id")?l.ctc_child_imports=i.val():"ctc_is_debug"==e(t).attr("id")?l.ctc_is_debug=e("#ctc_is_debug").is(":checked")?1:0:l=s.coalesce_inputs(t),e(".save-icon").show(),e("#ctc_sel_ovrd_selector_selected").find("#ctc_rewrite_selector").each(function(){a=e("#ctc_rewrite_selector").val(),r=e("#ctc_rewrite_selector_orig").val(),s.is_empty(a)||!a.toString().match(/\w/)?a=r:(l.ctc_rewrite_selector=a,s.reload_menus=!0),e(".ctc-rewrite-toggle").text(s.getxt("rename")),e("#ctc_sel_ovrd_selector_selected").html(a)}),l.action=s.is_empty(e("#ctc_action").val())||"plugin"!=e("#ctc_action").val()?"ctc_update":"ctc_plugin",l._wpnonce=e("#_wpnonce").val(),s.ajax_post("qsid",l)},ajax_post:function(t,c,n){var i=this,a=ctcAjax.ajaxurl;e.ajax({url:a,data:c,dataType:i.is_empty(n)?"json":n,type:"POST"}).done(function(e){i.handle_success(t,e)}).fail(function(){i.handle_failure(t)})},handle_failure:function(t){var c=this;e(".query-icon, .save-icon").removeClass("spinner").addClass("failure"),e("input[type=submit], input[type=button], input[type=checkbox]").prop("disabled",!1),e(".ajax-pending").removeClass("ajax-pending"),"preview"==t&&e("#view_parnt_options_panel,#view_child_options_panel").text(c.getxt("css_fail"))},handle_success:function(t,c){var n=this;e(".query-icon, .save-icon").removeClass("spinner"),e(".ajax-pending").removeClass("ajax-pending"),n.is_empty(c)?n.handle_failure(t):(e("#ctc_new_selectors").val(""),e(".query-icon, .save-icon").addClass("success"),e("input[type=submit], input[type=button], input[type=checkbox]").prop("disabled",!1),e(c).each(function(){"function"==typeof n.update[this.obj]&&n.update[this.obj].call(n,this)}))},jquery_exception:function(e,t){var c=this,n=c.is_empty(e.lineNumber)?"":" line: "+e.lineNumber,i=c.is_empty(e.fileName)?"":" "+e.fileName.split(/\?/)[0];c.jquery_err.push("<code><small>"+t+": "+e.message+i+n+"</small></code>")},jquery_notice:function(){var t=this,c=[],n=[];e("input[type=submit], input[type=button]").prop("disabled",!0),e("script").each(function(n,i){var a=e(this).prop("src");t.is_empty(a)||!a.match(/jquery(\.min|\.js|\-?ui)/i)||a.match(/load\-scripts.php/)||c.push("<code><small>"+a.split(/\?/)[0]+"</small></code>")}),n.push("<strong>"+t.getxt("js")+"</strong> "+t.getxt("contact")),1==ctcAjax.is_debug&&n.push(t.jquery_err.join("<br/>")),c.length&&n.push(t.getxt("jquery")+"<br/>"+c.join("<br/>")),n.push(t.getxt("plugin")),t.set_notice({error:n})},update:{qsid:function(t){var c,n,i,a=this;a.current_qsid=t.key,a.current_qsdata=t.data,e("#ctc_sel_ovrd_qsid").val(a.current_qsid),a.is_empty(a.current_qsdata.seq)?e("#ctc_child_load_order_container").empty():(c="ctc_ovrd_child_seq_"+a.current_qsid,i=parseInt(a.current_qsdata.seq),n='<input type="text" id="'+c+'" name="'+c+'" class="ctc-child-value" value="'+i+'" />',e("#ctc_child_load_order_container").html(n)),a.is_empty(a.current_qsdata.value)?(e("#ctc_sel_ovrd_rule_inputs").empty(),e("#ctc_sel_ovrd_rule_header").hide()):(n="",e.each(a.current_qsdata.value,function(e,t){n+=a.input_row(a.current_qsid,e,"ovrd",a.current_qsdata)}),e("#ctc_sel_ovrd_rule_inputs").html(n).find(".color-picker").each(function(){a.setup_iris(this)}),a.coalesce_inputs("#ctc_child_all_0_swatch"),e("#ctc_sel_ovrd_rule_header").show()),a.jquery_err.length?a.jquery_notice():(a.reload_menus&&(a.set_query(a.current_qsdata.query),a.load_rules()),e("#ctc_sel_ovrd_selector_selected").text(a.current_qsdata.selector),e(".ctc-rewrite-toggle").text(a.getxt("rename")),e("#ctc_sel_ovrd_new_rule,#ctc_sel_ovrd_rule_inputs_container,#ctc_sel_ovrd_rule_inputs,.ctc-rewrite-toggle").show())},rule_val:function(t){var c=this,n=e("#ctc_rule_menu_selected").text(),i='<div class="ctc-input-row clearfix" id="ctc_rule_row_'+n+'">\n';c.is_empty(t.data)||(e.each(t.data,function(e,t){var a=c.decode_value(n,t);i+='<div class="ctc-parent-row clearfix" id="ctc_rule_row_'+n+"_"+e+'">\n<div class="ctc-input-cell ctc-parent-value" id="ctc_'+e+"_parent_"+n+"_"+e+'">'+a.orig+'</div>\n<div class="ctc-input-cell">\n<div class="ctc-swatch ctc-specific" id="ctc_'+e+"_parent_"+n+"_"+e+'_swatch">'+c.getxt("swatch")+'</div></div>\n<div class="ctc-input-cell"><a href="#" class="ctc-selector-handle" id="ctc_selector_'+n+"_"+e+'">'+c.getxt("selector")+'</a></div>\n<div id="ctc_selector_'+n+"_"+e+'_container" class="ctc-selector-container">\n<a href="#" id="ctc_selector_'+n+"_"+e+'_close" class="ctc-selector-handle ctc-exit" title="'+c.getxt("close")+'"></a><div id="ctc_selector_'+n+"_"+e+'_inner_container" class="ctc-selector-inner-container clearfix">\n<div id="ctc_status_val_qry_'+e+'"></div>\n<div id="ctc_selector_'+n+"_"+e+'_rows"></div>\n</div></div></div>\n'}),i+="</div>\n"),e("#ctc_rule_value_inputs").html(i).find(".ctc-swatch").each(function(){c.coalesce_inputs(this)})},val_qry:function(t){var c=this,n="";c.is_empty(t.data)||e.each(t.data,function(i,a){page_rule=i,e.each(a,function(a,r){n+='<h4 class="ctc-query-heading">'+a+"</h4>\n",c.is_empty(r)||e.each(r,function(e,a){n+=c.input_row(e,i,t.key,a)})})}),selector="#ctc_selector_"+rule+"_"+t.key+"_rows",e(selector).html(n).find(".color-picker").each(function(){c.setup_iris(this)}),e(selector).find(".ctc-swatch").each(function(){c.coalesce_inputs(this)}),c.jquery_err.length&&c.jquery_notice()},queries:function(t){e("#ctc_sel_ovrd_query").data("menu",t.data)},selectors:function(t){e("#ctc_sel_ovrd_selector").data("menu",t.data)},rules:function(t){e("#ctc_rule_menu").data("menu",t.data)},debug:function(t){e("#ctc_debug_container").html(t.data)},preview:function(t){e("#view_"+t.key+"_options_panel").text(t.data)}},init:function(){var t=this;if(t.autogen_slugs(),t.set_existing(),!e("#ctc_theme_parnt").is("input")){try{e.widget("ctc.themeMenu",e.ui.selectmenu,{_renderItem:function(t,c){var n=e("<li>");return e("#ctc_theme_option_"+c.value).detach().appendTo(n),n.appendTo(t)}})}catch(c){t.jquery_exception(c,"Theme Menu")}try{e("#ctc_theme_parnt").themeMenu({select:function(e,c){t.set_parent_menu(c.item)}})}catch(c){"function"==typeof themeMenu?e("#ctc_theme_parnt").themeMenu("destroy"):e("#ctc_theme_parnt-button").remove(),t.jquery_exception(c,"Parent Theme Menu")}if(t.is_empty(ctcAjax.themes.child))e("#ctc_child_name").length&&(e("#ctc_child_name").val(t.testname),e("#ctc_child_template").val(t.testslug));else try{e("#ctc_theme_child").themeMenu({select:function(e,c){t.set_child_menu(c.item)}})}catch(c){"function"==typeof themeMenu?e("#ctc_theme_child").themeMenu("destroy"):e("#ctc_theme_child-button").remove(),t.jquery_exception(c,"Child Theme Menu")}}t.is_empty(t.jquery_err)?(e("#ctc_main").on("focus",".color-picker",function(){try{e(".color-picker").not(this).iris("hide"),e(this).iris("toggle"),e(".iris-picker").css({position:"absolute","z-index":10})}catch(c){t.jquery_exception(c,"Iris Color Picker")}}),e("#ctc_main").on("change",".ctc-child-value, input[type=checkbox]",function(){t.coalesce_inputs(this)}),e("#ctc_main").on("click",".ctc-selector-handle",function(c){if(c.preventDefault(),e(this).hasClass("ajax-pending"))return!1;e(this).addClass("ajax-pending");var n=e(this).attr("id").toString().replace("_close",""),i=n.toString().match(/_([^_]+)_(\d+)$/);e("#"+n+"_container").is(":hidden")&&(t.is_empty(i[1])||t.is_empty(i[2])||(rule=i[1],valid=i[2],t.query_css("val_qry",valid,{rule:rule}))),e("#"+n+"_container").fadeToggle("fast"),e(".ctc-selector-container").not("#"+n+"_container").fadeOut("fast")}),e("#ctc_main").on("click",".ctc-save-input[type=button]",function(c){return e(this).hasClass("ajax-pending")?!1:(e(this).addClass("ajax-pending"),void t.save(this))}),e("#ctc_main").on("click",".ctc-selector-edit",function(c){return c.preventDefault(),e(this).hasClass("ajax-pending")?!1:(e(this).addClass("ajax-pending"),void t.set_qsid(this))}),e("#ctc_main").on("click",".ctc-rewrite-toggle",function(e){e.preventDefault(),t.selector_input_toggle(this)}),e("#ctc_main").on("click","#ctc_copy_selector",function(c){var n=e("#ctc_sel_ovrd_selector_selected").text().trim();t.is_empty(n)||e("#ctc_new_selectors").val(e("#ctc_new_selectors").val()+"\n"+n+" {\n\n}")}),e("#ctc_configtype").on("change",function(c){var n=e(this).val();if(t.is_empty(n)||"theme"==n){e(".ctc-theme-only, .ctc-themeonly-container").removeClass("ctc-disabled"),e(".ctc-theme-only, .ctc-themeonly-container input").prop("disabled",!1);try{e("#ctc_theme_parnt, #ctc_theme_child").themeMenu("enable")}catch(i){t.jquery_exception(i,"Theme Menu")}}else{e(".ctc-theme-only, .ctc-themeonly-container").addClass("ctc-disabled"),e(".ctc-theme-only, .ctc-themeonly-container input").prop("disabled",!0);try{e("#ctc_theme_parnt, #ctc_theme_child").themeMenu("disable")}catch(i){t.jquery_exception(i,"Theme Menu")}}}),e(".nav-tab").on("click",function(c){c.preventDefault(),e(".ctc-status-icon").remove();var n="#"+e(this).attr("id");t.focus_panel(n)}),e(".ctc-section-toggle").on("click",function(t){t.preventDefault(),e(this).parents(".ctc-input-row, .update-nag").first().find(".ctc-section-toggle").each(function(){e(this).toggleClass("open")});var c=e(this).attr("id").replace(/\d$/,"")+"_content";return e("#"+c).stop().slideToggle("fast"),!1}),e("#view_child_options, #view_parnt_options").on("click",function(c){return e(this).hasClass("ajax-pending")?!1:(e(this).addClass("ajax-pending"),void t.css_preview(e(this).attr("id")))}),e("#ctc_load_form").on("submit",function(){return t.validate()}),e("#ctc_query_selector_form").on("submit",function(c){return c.preventDefault(),$this=e("#ctc_save_query_selector"),$this.hasClass("ajax-pending")?!1:($this.addClass("ajax-pending"),t.save($this),!1)}),e("#ctc_theme_child, #ctc_theme_child-button, #ctc_child_type_existing").on("focus click",function(){e("#ctc_child_type_existing").prop("checked",!0),e("#ctc_child_type_new").prop("checked",!1),e("#ctc_child_template").val(""),t.set_existing()}),e("#ctc_duplicate_theme").on("click",function(){e("#ctc_duplicate_theme").is(":checked")?(e("#ctc_child_name").val(t.testname),e("#ctc_duplicate_theme_slug").val(t.testslug)):t.set_existing()}),e("#ctc_child_type_new, #ctc_child_template").on("focus click",function(){e("#ctc_child_type_existing").prop("checked",!1),e("#ctc_duplicate_theme").prop("checked",!1),e("#ctc_duplicate_theme_slug").val(""),e("#ctc_child_type_new").prop("checked",!0),e("#input_row_duplicate_theme").hide(),e("#ctc_child_name").val(t.testname),e("#ctc_child_template").val(t.testslug)}),e("#ctc_is_debug").on("change",function(e){t.save(this)}),e(".ctc-live-preview").on("click",function(t){return t.stopImmediatePropagation(),t.preventDefault(),document.location=e(this).prop("href"),!1}),t.setup_menus(),t.set_addl_css(),e("input[type=submit], input[type=button]").prop("disabled",!1),t.scrolltop(),setTimeout(t.fade_update_notice,2e4)):t.jquery_notice()},testslug:"",testname:"",reload_menus:!1,current_query:"base",current_qsid:null,current_qsdata:{},jquery_err:[]}}(jQuery),jQuery(document).ready(function(e){e.chldthmcfg.init()});
1
+ !function(e){e.chldthmcfg={esc_quot:function(e){var t=this;return t.is_empty(e)?e:e.toString().replace(/"/g,"&quot;")},getxt:function(e){return(text=ctcAjax[e+"_txt"])?text:""},from_ascii:function(e){var t=parseInt(e),c=String.fromCharCode(t);return c},to_ascii:function(e){var t=e.charCodeAt(0);return t},is_empty:function(e){if("undefined"==typeof e||!1===e||null===e||""===e)return!0;if(!0===e||"string"==typeof e||"number"==typeof e)return!1;if("object"==typeof e){for(var t in e)if(e.hasOwnProperty(t))return!1;return!0}return!1},theme_exists:function(t,c){var n=!1;return e.each(ctcAjax.themes,function(i,a){return e.each(a,function(e,a){return e!=t||"parnt"!=i&&"new"!=c?void 0:(n=!0,!1)}),n?!1:void 0}),n},validate:function(){var t=this,c=/[^\w\-]/,n=e("#ctc_child_template").length?e("#ctc_child_template").val().toString().replace(c).toLowerCase():"",i=e("#ctc_theme_child").length?e("#ctc_theme_child").val().toString().replace(c).toLowerCase():n,a=e("input[name=ctc_child_type]:checked").val(),r=[];return"new"==a&&(i=n),t.theme_exists(i,a)&&r.push(t.getxt("theme_exists").toString().replace(/%s/,i)),""===i&&r.push(t.getxt("inval_theme")),""===e("#ctc_child_name").val()&&r.push(t.getxt("inval_name")),r.length?(t.set_notice({error:r}),!1):!0},autogen_slugs:function(){if(e("#ctc_theme_parnt").length){for(var t=this,c=e("#ctc_theme_parnt").val(),n=slugbase=c+"-child",i=ctcAjax.themes.parnt[c].Name+" Child",a="",r="",s="00";t.theme_exists(n,"new");)a=""==a?2:a+1,r=s.substring(0,s.length-a.toString().length)+a.toString(),n=slugbase+r;t.testslug=n,t.testname=i+(r.length?" "+r:"")}},focus_panel:function(t){var c=t+"_panel";e(".nav-tab").removeClass("nav-tab-active"),e(".ctc-option-panel").removeClass("ctc-option-panel-active"),e(t).addClass("nav-tab-active"),e(".ctc-option-panel-container").scrollTop(0),e(c).addClass("ctc-option-panel-active")},selector_input_toggle:function(t){var c,n=this;e("#ctc_rewrite_selector").length?(c=e("#ctc_rewrite_selector_orig").val(),e("#ctc_sel_ovrd_selector_selected").text(c),e(t).text(n.getxt("rename"))):(c=e("#ctc_sel_ovrd_selector_selected").text(),e("#ctc_sel_ovrd_selector_selected").html('<textarea id="ctc_rewrite_selector" name="ctc_rewrite_selector" autocomplete="off"></textarea><input id="ctc_rewrite_selector_orig" name="ctc_rewrite_selector_orig" type="hidden" value="'+n.esc_quot(c)+'"/>'),e("#ctc_rewrite_selector").val(c),e(t).text(n.getxt("cancel")))},fade_update_notice:function(){e(".updated, .error").slideUp("slow",function(){e(".updated").remove()})},coalesce_inputs:function(t){var c=this,n=e(t).attr("id"),i=/^(ctc_(ovrd|\d+)_(parent|child)_([0-9a-z\-]+)_(\d+?)(_(\d+))?)(_\w+)?$/,a=e(t).parents(".ctc-selector-row, .ctc-parent-row").first(),r=a.find(".ctc-swatch").first(),s={parent:{},child:{}},l={parent:{origin:"",start:"",end:""},child:{origin:"",start:"",end:""}},_={child:!1,parent:!1},o={};return a.find(".ctc-parent-value, .ctc-child-value").each(function(){var t,a,r=e(this).attr("id"),u=r.toString().match(i),d=u[2],p=u[3],h="undefined"==typeof u[4]?"":u[4],m=u[7],v=u[5],f="undefined"==typeof u[7]?"":u[8],g="parent"==p?e(this).text().replace(/!$/,""):"seq"!=h&&"ctc_delete_query_selector"==n?"":e(this).val(),y="seq"==h?!1:"ctc_"+d+"_child_"+h+"_i_"+v+"_"+m;if("child"==p&&(c.is_empty(e(this).data("color"))||(g=c.color_text(e(this).data("color")),e(this).data("color",null)),o[r]=g,y&&(o[y]=e("#"+y).is(":checked")?1:0)),""!==g)if(c.is_empty(f))if(t=h.toString().match(/^border(\-(top|right|bottom|left))?$/)&&!g.match(/none/)){var x=new RegExp(c.border_regx+c.color_regx,"i"),a=g.toString().match(x);c.is_empty(a)||(a.shift(),s[p][h+"-width"]=a.shift()||"",a.shift(),s[p][h+"-style"]=a.shift()||"",s[p][h+"-color"]=a.shift()||"")}else if("background-image"!=h||g.match(/none/))"seq"!=h&&(s[p][h]=g);else if(g.toString().match(/url\(/))s[p]["background-image"]=c.image_url(p,g);else{var w=new RegExp(c.grad_regx+c.color_regx+c.color_regx,"i"),a=g.toString().match(w);!c.is_empty(a)&&a.length>2?(a.shift(),l[p].origin=a.shift()||"top",l[p].start=a.shift()||"transparent",l[p].end=a.shift()||"transparent",_[p]=!0):s[p]["background-image"]=g}else switch(f){case"_border_width":s[p][h+"-width"]="none"==g?0:g;break;case"_border_style":s[p][h+"-style"]=g;break;case"_border_color":s[p][h+"-color"]=g;break;case"_background_url":s[p]["background-image"]=c.image_url(p,g);break;case"_background_color":s[p]["background-color"]=g;break;case"_background_color1":l[p].start=g,_[p]=!0;break;case"_background_color2":l[p].end=g,_[p]=!0;break;case"_background_origin":l[p].origin=g,_[p]=!0}}),"undefined"==typeof r||c.is_empty(r.attr("id"))||(r.removeAttr("style"),_.parent&&r.ctcgrad(l.parent.origin,[l.parent.start,l.parent.end]),r.css(s.parent),r.attr("id").toString().match(/parent/)||(_.child&&r.ctcgrad(l.child.origin,[l.child.start,l.child.end]),r.css(s.child)),r.css({"z-index":-1})),o},decode_value:function(e,t){t="undefined"==typeof t?"":t;var c=this,n={orig:t,names:[""],values:[t]};if(e.toString().match(/^border(\-(top|right|bottom|left))?$/)){var i=new RegExp(c.border_regx+"("+c.color_regx+")?","i"),a=t.toString().match(i);c.is_empty(a)&&(a=[]),n.names=["_border_width","_border_style","_border_color"],orig=a.shift(),n.values[0]=a.shift()||"",a.shift(),n.values[1]=a.shift()||"",a.shift(),n.values[2]=a.shift()||""}else if(e.toString().match(/^background\-image/))if(n.names=["_background_url","_background_origin","_background_color1","_background_color2"],n.values=["","","",""],c.is_empty(t)||t.toString().match(/(url|none)/))n.values[0]=t;else{var r,s,a=t.toString().split(/:/);n.values[1]=a.shift()||"",n.values[2]=a.shift()||"",r=a.shift()||"",n.values[3]=a.shift()||"",s=a.shift()||"",n.orig=[n.values[1],n.values[2],n.values[3]].join(" ")}return n},image_url:function(e,t){var c,n=this,i=t.toString().match(/url\(['" ]*(.+?)['" ]*\)/),a=n.is_empty(i)?null:i[1],r=ctcAjax.theme_uri+"/"+("parent"==e?ctcAjax.parnt:ctcAjax.child)+"/";return a?c=a.toString().match(/^(data:|https?:|\/)/)?t:"url("+r+a+")":!1},setup_menus:function(){var e=this;e.setup_query_menu(),e.setup_selector_menu(),e.setup_rule_menu(),e.setup_new_rule_menu(),e.load_queries(),e.load_rules(),e.set_query(e.current_query)},load_queries:function(){var e=this;e.query_css("queries",null)},load_selectors:function(){var e=this;e.query_css("selectors",e.current_query)},load_rules:function(){var e=this;e.query_css("rules",null)},load_selector_values:function(){var e=this;e.query_css("qsid",e.current_qsid)},get_queries:function(t,c){var n=[],i=new RegExp(e.ui.autocomplete.escapeRegex(t.term),"i");e.each(this.element.data("menu"),function(e,t){i.test(t)&&n.push({label:t,value:t})}),c(n)},get_selectors:function(t,c){var n=[],i=new RegExp(e.ui.autocomplete.escapeRegex(t.term),"i");e.each(this.element.data("menu"),function(e,t){i.test(e)&&n.push({label:e,value:t})}),c(n)},get_rules:function(t,c){var n=[],i=new RegExp(e.ui.autocomplete.escapeRegex(t.term),"i");e.each(this.element.data("menu"),function(e,t){i.test(e)&&n.push({label:e,value:t})}),c(n)},get_filtered_rules:function(t,c){var n=[],i=new RegExp(e.ui.autocomplete.escapeRegex(t.term),"i");e.each(e("#ctc_rule_menu").data("menu"),function(e,t){i.test(e)&&n.push({label:e,value:t})}),c(n)},merge_ruleval_arrays:function(t,c,n){var i=this,a={};return nextval=n?c.child.pop():null,e.each(["parnt","child"],function(t,r){i.is_empty(c[r])||e.each(c[r],function(e,t){n?parseInt(t[2])>=parseInt(nextval[2])&&(nextval[2]=parseInt(t[2])+1):(i.is_empty(a[t[2]])&&(a[t[2]]={}),a[t[2]][r]=t)})}),n&&(a[nextval[2]]={parnt:[],child:nextval}),a},input_row:function(t,c,n,i,a){var r=this,s="";if(!r.is_empty(i)&&!r.is_empty(i.value)&&!r.is_empty(i.value[c])){var l=i.value[c],_=r.merge_ruleval_arrays(c,l,a);e.each(_,function(a,l){var _=r.decode_value(c,r.is_empty(l.parnt)?"":l.parnt[0]),o=r.is_empty(l.parnt)||0==l.parnt[1]?0:1,u=r.decode_value(c,r.is_empty(l.child)?"":l.child[0]),d=r.is_empty(l.child)||0==l.child[1]?0:1;if(s+='<div class="ctc-'+("ovrd"==n?"input":"selector")+'-row clearfix"><div class="ctc-input-cell">',s+="ovrd"==n?c.replace(/\d+/g,r.from_ascii):i.selector+'<br/><a href="#" class="ctc-selector-edit" id="ctc_selector_edit_'+t+'" >'+r.getxt("edit")+"</a> "+(r.is_empty(_.orig)?r.getxt("child_only"):""),s+='</div><div class="ctc-parent-value ctc-input-cell"'+("ovrd"!=n?' style="display:none"':"")+' id="ctc_'+n+"_parent_"+c+"_"+t+"_"+a+'">'+(r.is_empty(_.orig)?"[no value]":_.orig+(o?r.getxt("important"):""))+'</div><div class="ctc-input-cell">',!r.is_empty(_.names)){e.each(_.names,function(e,i){i=r.is_empty(i)?"":i,s+='<div class="ctc-child-input-cell clear">';var l,_="ctc_"+n+"_child_"+c+"_"+t+"_"+a+i;!1===(l=u.values.shift())&&(l=""),s+=(r.is_empty(i)?"":r.getxt(i)+":<br/>")+'<input type="text" id="'+_+'" name="'+_+'" class="ctc-child-value'+((i+c).toString().match(/color/)?" color-picker":"")+(i.toString().match(/url/)?" ctc-input-wide":"")+'" value="'+r.esc_quot(l)+'" /></div>'});var p="ctc_"+n+"_child_"+c+"_i_"+t+"_"+a;s+='<label for="'+p+'"><input type="checkbox" id="'+p+'" name="'+p+'" value="1" '+(d?"checked":"")+" />"+r.getxt("important")+"</label>"}s+="</div>","ovrd"!=n&&(s+='<div class="ctc-swatch ctc-specific" id="ctc_child_'+c+"_"+t+"_"+a+'_swatch">'+r.getxt("swatch")+'</div><div class="ctc-child-input-cell ctc-button-cell" id="ctc_save_'+c+"_"+t+"_"+a+'_cell"><input type="button" class="button ctc-save-input" id="ctc_save_'+c+"_"+t+"_"+a+'" name="ctc_save_'+c+"_"+t+"_"+a+'" value="Save" /></div>'),s+="</div><!-- end input row -->\n"})}return s},scrolltop:function(){e("html, body, .ctc-option-panel-container").animate({scrollTop:0})},css_preview:function(e){var e,t=this;(e=e.match(/(child|parnt)/)[1])||(e="child"),t.query_css("preview",e)},setup_iris:function(e){var t=this;t.setup_spectrum(e)},setup_spectrum:function(t){{var c=this;e(t).attr("id")+"_colortxt"}try{e(t).spectrum({showInput:!0,allowEmpty:!0,showAlpha:!0,showInitial:!0,preferredFormat:"hex",clickoutFiresChange:!0,move:function(n){e(t).data("color",n),c.coalesce_inputs(t)}}).on("change",function(t){e(this).spectrum("get");c.coalesce_inputs(this)}).on("keyup",function(t){var n=this,i=e(this).val();clearTimeout(e(this).data("spectrumTimer")),e(this).data("spectrumTimer",setTimeout(function(){c.coalesce_inputs(n),e(n).spectrum("set",i)},500))})}catch(n){c.jquery_exception(n,"Spectrum Color Picker")}},color_text:function(e){var t=this;return t.is_empty(e)?"":e.getAlpha()<1?e.toRgbString():e.toHexString()},setup_query_menu:function(){var t=this;try{e("#ctc_sel_ovrd_query").autocomplete({source:t.get_queries,minLength:0,selectFirst:!0,autoFocus:!0,select:function(e,c){return t.set_query(c.item.value),!1},focus:function(e){e.preventDefault()}}).data("menu",{})}catch(c){t.jquery_exception(c,"Query Menu")}},setup_selector_menu:function(){var t=this;try{e("#ctc_sel_ovrd_selector").autocomplete({source:t.get_selectors,selectFirst:!0,autoFocus:!0,select:function(e,c){return t.set_selector(c.item.value,c.item.label),!1},focus:function(e){e.preventDefault()}}).data("menu",{})}catch(c){t.jquery_exception(c,"Selector Menu")}},setup_rule_menu:function(){var t=this;try{e("#ctc_rule_menu").autocomplete({source:t.get_rules,selectFirst:!0,autoFocus:!0,select:function(e,c){return t.set_rule(c.item.value,c.item.label),!1},focus:function(e){e.preventDefault()}}).data("menu",{})}catch(c){t.jquery_exception(c,"Property Menu")}},setup_new_rule_menu:function(){var t=this;try{e("#ctc_new_rule_menu").autocomplete({source:t.get_filtered_rules,selectFirst:!0,autoFocus:!0,select:function(c,n){c.preventDefault();var i,a,r=n.item.label.replace(/[^\w\-]/g,t.to_ascii);return t.is_empty(t.current_qsdata.value)&&(t.current_qsdata.value={}),t.is_empty(t.current_qsdata.value[n.item.label])&&(t.current_qsdata.value[n.item.label]={}),t.is_empty(t.current_qsdata.value[n.item.label].child)&&(t.current_qsdata.value[n.item.label].child=[]),t.current_qsdata.value[n.item.label].child.push(["",0,1,1]),i=e(t.input_row(t.current_qsid,r,"ovrd",t.current_qsdata,!0)),e("#ctc_sel_ovrd_rule_inputs").append(i),e("#ctc_new_rule_menu").val(""),i.find('input[type="text"]').each(function(c,n){a||(a=n),e(n).hasClass("color-picker")&&t.setup_spectrum(n)}),a&&e(a).focus(),t.jquery_err.length&&t.jquery_notice("setup_new_rule_menu"),!1},focus:function(e){e.preventDefault()}}).data("menu",{})}catch(c){t.jquery_exception(c,"New Property Menu")}},set_existing:function(){var t=this;if(e("#ctc_theme_child").length&&e("#ctc_child_type_existing").is(":checked")){var c=e("#ctc_theme_child").val();t.is_empty(c)||(e("#ctc_child_name").val(ctcAjax.themes.child[c].Name),e("#ctc_child_author").val(ctcAjax.themes.child[c].Author),e("#ctc_child_version").val(ctcAjax.themes.child[c].Version),e("#ctc_child_authoruri").val(ctcAjax.themes.child[c].AuthorURI),e("#ctc_child_themeuri").val(ctcAjax.themes.child[c].ThemeURI),e("#ctc_child_descr").val(ctcAjax.themes.child[c].Descr),e("#ctc_child_tags").val(ctcAjax.themes.child[c].Tags),e("#ctc_duplicate_theme").prop("checked",!1),e("#ctc_duplicate_theme_slug").val(""),e("#input_row_duplicate_theme").show())}},set_notice:function(t){var c=this,n="";c.is_empty(t)||e.each(t,function(t,c){n+='<div class="'+t+'"><ul>\n',e(c).each(function(e,t){n+="<li>"+t.toString()+"</li>\n"}),n+="</ul></div>"}),e("#ctc_error_notice").html(n),e("html, body").animate({scrollTop:0},"slow")},set_parent_menu:function(t){e("#ctc_theme_parnt").parents(".ctc-input-row").first().append('<span class="ctc-status-icon spinner"></span>'),e(".spinner").show(),document.location="?page="+ctcAjax.page+"&ctc_parent="+t.value},set_child_menu:function(t){var c,n,i=this;i.is_empty(ctcAjax.themes.child[t.value])||(c=ctcAjax.themes.child[t.value].Template,n=e("#ctc_theme_parnt").val(),c==n?(e("#ctc_child_name").val(ctcAjax.themes.child[t.value].Name),e("#ctc_child_author").val(ctcAjax.themes.child[t.value].Author),e("#ctc_child_version").val(ctcAjax.themes.child[t.value].Version)):(e("#ctc_theme_child").parents(".ctc-input-row").first().append('<span class="ctc-status-icon spinner"></span>'),e(".spinner").show(),document.location="?page="+ctcAjax.page+"&ctc_parent="+c+"&ctc_child="+t.value))},set_query:function(t){var c=this;return c.is_empty(t)?!1:(c.current_query=t,e("#ctc_sel_ovrd_query").val(""),e("#ctc_sel_ovrd_query_selected").text(t),e("#ctc_sel_ovrd_selector").val(""),e("#ctc_sel_ovrd_selector_selected").html("&nbsp;"),c.load_selectors(),void c.scrolltop())},set_selector:function(t,c){var n=this;return n.is_empty(t)?!1:(e("#ctc_sel_ovrd_selector").val(""),n.current_qsid=t,n.reload_menus=!1,n.load_selector_values(),void n.scrolltop())},set_rule:function(t,c){var n=this;return n.is_empty(t)?!1:(e("#ctc_rule_menu").val(""),e("#ctc_rule_menu_selected").text(c),e(".ctc-rewrite-toggle").text(n.getxt("rename")),e("#ctc_rule_value_inputs, #ctc_input_row_rule_header").show(),n.query_css("rule_val",t),void n.scrolltop())},set_qsid:function(t){var c=this;c.current_qsid=e(t).attr("id").match(/_(\d+)$/)[1],c.focus_panel("#query_selector_options"),c.reload_menus=!0,c.load_selector_values()},set_addl_css:function(){var t,c=this,n=e("#ctc_theme_parnt").val(),i=ctcAjax.theme_uri.replace(/^https?:\/\//,""),a=ctcAjax.homeurl.replace(/^https?/,ctcAjax.ssl?"https":"http"),r=a+"?preview=1&p=x&template="+n+"&stylesheet="+n,s=new RegExp("<link rel=[\"']stylesheet[\"'][^>]+?"+i+"/"+n+"/(.+?\\.css)[^>]+?>","g");c.is_empty(n)||(n!=ctcAjax.parnt?e.get(r,function(c){for(;(t=s.exec(c))&&"style.css"!=t[1];)t[1].match(/bootstrap/)||e(".ctc_checkbox").each(function(c,n){e(this).val()==t[1]&&e(this).prop("checked",!0)});c=null}):e(ctcAjax.addl_css).each(function(t,c){e("#ctc_stylesheet_files .ctc_checkbox").each(function(t,n){e(this).val()==c&&e(this).prop("checked",!0)})}))},query_css:function(t,c,n){var i=this,a={ctc_query_obj:t,ctc_query_key:c},r="#ctc_status_"+t+("val_qry"==t?"_"+c:"");"object"==typeof n&&e.each(n,function(e,t){a["ctc_query_"+e]=t}),e(".query-icon").remove(),e(r+" .ctc-status-icon").remove(),e(r).append('<span class="ctc-status-icon spinner query-icon"></span>'),e(".spinner").show(),a.action=i.is_empty(e("#ctc_action").val())||"plugin"!=e("#ctc_action").val()?"ctc_query":"ctc_plgqry",a._wpnonce=e("#_wpnonce").val(),i.ajax_post(t,a)},save:function(t){var c,n,i,a,r,s=this,l=(ctcAjax.ajaxurl,{}),_=e(t).attr("id");e(t).prop("disabled",!0),e(".ctc-status-icon").remove(),e(t).parent(".ctc-textarea-button-cell, .ctc-button-cell").append('<span class="ctc-status-icon spinner save-icon"></span>'),_.match(/ctc_configtype/)?(e(t).parents(".ctc-input-row").first().append('<span class="ctc-status-icon spinner save-icon"></span>'),l.ctc_configtype=e(t).val()):(c=e("#ctc_new_selectors"))&&"ctc_save_new_selectors"==e(t).attr("id")?(l.ctc_new_selectors=c.val(),(n=e("#ctc_sel_ovrd_query_selected"))&&(l.ctc_sel_ovrd_query=n.text()),s.reload_menus=!0):(i=e("#ctc_child_imports"))&&"ctc_save_imports"==_?l.ctc_child_imports=i.val():"ctc_is_debug"==_?l.ctc_is_debug=e("#ctc_is_debug").is(":checked")?1:0:l=s.coalesce_inputs(t),e(".save-icon").show(),e("#ctc_sel_ovrd_selector_selected").find("#ctc_rewrite_selector").each(function(){a=e("#ctc_rewrite_selector").val(),r=e("#ctc_rewrite_selector_orig").val(),s.is_empty(a)||!a.toString().match(/\w/)?a=r:(l.ctc_rewrite_selector=a,s.reload_menus=!0),e(".ctc-rewrite-toggle").text(s.getxt("rename")),e("#ctc_sel_ovrd_selector_selected").html(a)}),l.action=s.is_empty(e("#ctc_action").val())||"plugin"!=e("#ctc_action").val()?"ctc_update":"ctc_plugin",l._wpnonce=e("#_wpnonce").val(),s.ajax_post("qsid",l)},ajax_post:function(t,c,n){var i=this,a=ctcAjax.ajaxurl;e.ajax({url:a,data:c,dataType:i.is_empty(n)?"json":n,type:"POST"}).done(function(e){i.handle_success(t,e)}).fail(function(){i.handle_failure(t)})},handle_failure:function(t){var c=this;e(".query-icon, .save-icon").removeClass("spinner").addClass("failure"),e("input[type=submit], input[type=button], input[type=checkbox],.ctc-delete-input").prop("disabled",!1),e(".ajax-pending").removeClass("ajax-pending"),"preview"==t&&e("#view_parnt_options_panel,#view_child_options_panel").text(c.getxt("css_fail"))},handle_success:function(t,c){var n=this;e(".query-icon, .save-icon").removeClass("spinner"),e(".ajax-pending").removeClass("ajax-pending"),n.is_empty(c)?n.handle_failure(t):(e("#ctc_new_selectors").val(""),e(".query-icon, .save-icon").addClass("success"),e("input[type=submit], input[type=button], input[type=checkbox],.ctc-delete-input").prop("disabled",!1),e(c).each(function(){"function"==typeof n.update[this.obj]&&n.update[this.obj].call(n,this)}))},jquery_exception:function(e,t){var c=this,n=c.is_empty(e.lineNumber)?"":" line: "+e.lineNumber,i=c.is_empty(e.fileName)?"":" "+e.fileName.split(/\?/)[0];c.jquery_err.push("<code><small>"+t+": "+e.message+i+n+"</small></code>")},jquery_notice:function(t){var c=this,n=[],i=[];e("input[type=submit], input[type=button]").prop("disabled",!0),e("script").each(function(t,i){var a=e(this).prop("src");c.is_empty(a)||!a.match(/jquery(\.min|\.js|\-?ui)/i)||a.match(/load\-scripts.php/)||n.push("<code><small>"+a.split(/\?/)[0]+"</small></code>")}),i.push("<strong>"+c.getxt("js")+"</strong> "+c.getxt("contact")),i.push(c.jquery_err.join("<br/>")),n.length&&i.push(c.getxt("jquery")+"<br/>"+n.join("<br/>")),i.push(c.getxt("plugin")),c.set_notice({error:i})},update:{qsid:function(t){var c,n,i,a=this;a.current_qsid=t.key,a.current_qsdata=t.data,e("#ctc_sel_ovrd_qsid").val(a.current_qsid),a.is_empty(a.current_qsdata.seq)?e("#ctc_child_load_order_container").empty():(c="ctc_ovrd_child_seq_"+a.current_qsid,i=parseInt(a.current_qsdata.seq),n='<input type="text" id="'+c+'" name="'+c+'" class="ctc-child-value" value="'+i+'" />',e("#ctc_child_load_order_container").html(n)),a.is_empty(a.current_qsdata.value)?(e("#ctc_sel_ovrd_rule_inputs").empty(),e("#ctc_sel_ovrd_rule_header").hide()):(n="",e.each(a.current_qsdata.value,function(e,t){n+=a.input_row(a.current_qsid,e,"ovrd",a.current_qsdata)}),e("#ctc_sel_ovrd_rule_inputs").html(n).find(".color-picker").each(function(){a.setup_spectrum(this)}),a.coalesce_inputs("#ctc_child_all_0_swatch"),e("#ctc_sel_ovrd_rule_header").show()),a.jquery_err.length?a.jquery_notice("update.qsid"):(a.reload_menus&&(a.set_query(a.current_qsdata.query),a.load_rules()),e("#ctc_sel_ovrd_selector_selected").text(a.current_qsdata.selector),e(".ctc-rewrite-toggle").text(a.getxt("rename")),e("#ctc_sel_ovrd_new_rule,#ctc_sel_ovrd_rule_inputs_container,#ctc_sel_ovrd_rule_inputs,.ctc-rewrite-toggle").show())},rule_val:function(t){var c=this,n=e("#ctc_rule_menu_selected").text(),i='<div class="ctc-input-row clearfix" id="ctc_rule_row_'+n+'">\n';c.is_empty(t.data)||(e.each(t.data,function(e,t){var a=c.decode_value(n,t);i+='<div class="ctc-parent-row clearfix" id="ctc_rule_row_'+n+"_"+e+'">\n<div class="ctc-input-cell ctc-parent-value" id="ctc_'+e+"_parent_"+n+"_"+e+'">'+a.orig+'</div>\n<div class="ctc-input-cell">\n<div class="ctc-swatch ctc-specific" id="ctc_'+e+"_parent_"+n+"_"+e+'_swatch">'+c.getxt("swatch")+'</div></div>\n<div class="ctc-input-cell"><a href="#" class="ctc-selector-handle" id="ctc_selector_'+n+"_"+e+'">'+c.getxt("selector")+'</a></div>\n<div id="ctc_selector_'+n+"_"+e+'_container" class="ctc-selector-container">\n<a href="#" id="ctc_selector_'+n+"_"+e+'_close" class="ctc-selector-handle ctc-exit" title="'+c.getxt("close")+'"></a><div id="ctc_selector_'+n+"_"+e+'_inner_container" class="ctc-selector-inner-container clearfix">\n<div id="ctc_status_val_qry_'+e+'"></div>\n<div id="ctc_selector_'+n+"_"+e+'_rows"></div>\n</div></div></div>\n'}),i+="</div>\n"),e("#ctc_rule_value_inputs").html(i).find(".ctc-swatch").each(function(){c.coalesce_inputs(this)})},val_qry:function(t){var c=this,n="";c.is_empty(t.data)||e.each(t.data,function(i,a){page_rule=i,e.each(a,function(a,r){n+='<h4 class="ctc-query-heading">'+a+"</h4>\n",c.is_empty(r)||e.each(r,function(e,a){n+=c.input_row(e,i,t.key,a)})})}),selector="#ctc_selector_"+rule+"_"+t.key+"_rows",e(selector).html(n).find(".color-picker").each(function(){c.setup_spectrum(this)}),e(selector).find(".ctc-swatch").each(function(){c.coalesce_inputs(this)}),c.jquery_err.length&&c.jquery_notice("val_qry")},queries:function(t){e("#ctc_sel_ovrd_query").data("menu",t.data)},selectors:function(t){e("#ctc_sel_ovrd_selector").data("menu",t.data)},rules:function(t){e("#ctc_rule_menu").data("menu",t.data)},debug:function(t){e("#ctc_debug_container").html(t.data)},preview:function(t){e("#view_"+t.key+"_options_panel").text(t.data)}},init:function(){var t=this;if(t.autogen_slugs(),t.set_existing(),!e("#ctc_theme_parnt").is("input")){try{e.widget("ctc.themeMenu",e.ui.selectmenu,{_renderItem:function(t,c){var n=e("<li>");return e("#ctc_theme_option_"+c.value).detach().appendTo(n),n.appendTo(t)}})}catch(c){t.jquery_exception(c,"Theme Menu")}try{e("#ctc_theme_parnt").themeMenu({select:function(e,c){t.set_parent_menu(c.item)}})}catch(c){"function"==typeof themeMenu?e("#ctc_theme_parnt").themeMenu("destroy"):e("#ctc_theme_parnt-button").remove(),t.jquery_exception(c,"Parent Theme Menu")}if(t.is_empty(ctcAjax.themes.child))e("#ctc_child_name").length&&(e("#ctc_child_name").val(t.testname),e("#ctc_child_template").val(t.testslug));else try{e("#ctc_theme_child").themeMenu({select:function(e,c){t.set_child_menu(c.item)}})}catch(c){"function"==typeof themeMenu?e("#ctc_theme_child").themeMenu("destroy"):e("#ctc_theme_child-button").remove(),t.jquery_exception(c,"Child Theme Menu")}}t.is_empty(t.jquery_err)?(e("#ctc_main").on("click",".ctc-selector-handle",function(c){if(c.preventDefault(),e(this).hasClass("ajax-pending"))return!1;e(this).addClass("ajax-pending");var n=e(this).attr("id").toString().replace("_close",""),i=n.toString().match(/_([^_]+)_(\d+)$/);e("#"+n+"_container").is(":hidden")&&(t.is_empty(i[1])||t.is_empty(i[2])||(rule=i[1],valid=i[2],t.query_css("val_qry",valid,{rule:rule}))),e("#"+n+"_container").fadeToggle("fast"),e(".ctc-selector-container").not("#"+n+"_container").fadeOut("fast")}),e("#ctc_main").on("click",".ctc-save-input[type=button], .ctc-delete-input",function(c){return c.preventDefault(),e(this).hasClass("ajax-pending")?!1:(e(this).addClass("ajax-pending"),t.save(this),!1)}),e("#ctc_main").on("click",".ctc-selector-edit",function(c){return c.preventDefault(),e(this).hasClass("ajax-pending")?!1:(e(this).addClass("ajax-pending"),void t.set_qsid(this))}),e("#ctc_main").on("click",".ctc-rewrite-toggle",function(e){e.preventDefault(),t.selector_input_toggle(this)}),e("#ctc_main").on("click","#ctc_copy_selector",function(c){var n=e("#ctc_sel_ovrd_selector_selected").text().trim();t.is_empty(n)||e("#ctc_new_selectors").val(e("#ctc_new_selectors").val()+"\n"+n+" {\n\n}")}),e("#ctc_configtype").on("change",function(c){var n=e(this).val();if(t.is_empty(n)||"theme"==n){e(".ctc-theme-only, .ctc-themeonly-container").removeClass("ctc-disabled"),e(".ctc-theme-only, .ctc-themeonly-container input").prop("disabled",!1);try{e("#ctc_theme_parnt, #ctc_theme_child").themeMenu("enable")}catch(i){t.jquery_exception(i,"Theme Menu")}}else{e(".ctc-theme-only, .ctc-themeonly-container").addClass("ctc-disabled"),e(".ctc-theme-only, .ctc-themeonly-container input").prop("disabled",!0);try{e("#ctc_theme_parnt, #ctc_theme_child").themeMenu("disable")}catch(i){t.jquery_exception(i,"Theme Menu")}}}),e(".nav-tab").on("click",function(c){c.preventDefault(),e(".ctc-status-icon").remove();var n="#"+e(this).attr("id");t.focus_panel(n)}),e(".ctc-section-toggle").on("click",function(t){t.preventDefault(),e(this).parents(".ctc-input-row, .update-nag").first().find(".ctc-section-toggle").each(function(){e(this).toggleClass("open")});var c=e(this).attr("id").replace(/\d$/,"")+"_content";return e("#"+c).stop().slideToggle("fast"),!1}),e("#view_child_options, #view_parnt_options").on("click",function(c){return e(this).hasClass("ajax-pending")?!1:(e(this).addClass("ajax-pending"),void t.css_preview(e(this).attr("id")))}),e("#ctc_load_form").on("submit",function(){return t.validate()}),e("#ctc_query_selector_form").on("submit",function(c){return c.preventDefault(),$this=e("#ctc_save_query_selector"),$this.hasClass("ajax-pending")?!1:($this.addClass("ajax-pending"),t.save($this),!1)}),e("#ctc_theme_child, #ctc_theme_child-button, #ctc_child_type_existing").on("focus click",function(){e("#ctc_child_type_existing").prop("checked",!0),e("#ctc_child_type_new").prop("checked",!1),e("#ctc_child_template").val(""),t.set_existing()}),e("#ctc_duplicate_theme").on("click",function(){e("#ctc_duplicate_theme").is(":checked")?(e("#ctc_child_name").val(t.testname),e("#ctc_duplicate_theme_slug").val(t.testslug)):t.set_existing()}),e("#ctc_child_type_new, #ctc_child_template").on("focus click",function(){e("#ctc_child_type_existing").prop("checked",!1),e("#ctc_duplicate_theme").prop("checked",!1),e("#ctc_duplicate_theme_slug").val(""),e("#ctc_child_type_new").prop("checked",!0),e("#input_row_duplicate_theme").hide(),e("#ctc_child_name").val(t.testname),e("#ctc_child_template").val(t.testslug)}),e("#ctc_is_debug").on("change",function(e){t.save(this)}),e(".ctc-live-preview").on("click",function(t){return t.stopImmediatePropagation(),t.preventDefault(),document.location=e(this).prop("href"),!1}),t.setup_menus(),t.set_addl_css(),e("input[type=submit], input[type=button]").prop("disabled",!1),t.scrolltop(),setTimeout(t.fade_update_notice,2e4)):t.jquery_notice("init")},testslug:"",testname:"",reload_menus:!1,current_query:"base",current_qsid:null,current_qsdata:{},jquery_err:[],color_regx:"\\s+(\\#[a-f0-9]{3,6}|rgba?\\([\\d., ]+?\\)|hsla?\\([\\d%., ]+?\\)|[a-z]+)",border_regx:"(\\w+)(\\s+(\\w+))?",grad_regx:"(\\w+)"}}(jQuery),jQuery(document).ready(function(e){e.chldthmcfg.init()});
js/spectrum.js ADDED
@@ -0,0 +1,2352 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Spectrum Colorpicker v1.7.0
2
+ // https://github.com/bgrins/spectrum
3
+ // Author: Brian Grinstead
4
+ // License: MIT
5
+ // Modifications for CTC (c) 2015 LIlaea Media LLC
6
+
7
+ (function (factory) {
8
+ "use strict";
9
+
10
+ if (typeof define === 'function' && define.amd) { // AMD
11
+ define(['jquery'], factory);
12
+ }
13
+ else if (typeof exports == "object" && typeof module == "object") { // CommonJS
14
+ module.exports = factory;
15
+ }
16
+ else { // Browser
17
+ factory(jQuery);
18
+ }
19
+ })(function($, undefined) {
20
+ "use strict";
21
+
22
+ var defaultOpts = {
23
+
24
+ // Callbacks
25
+ beforeShow: noop,
26
+ move: noop,
27
+ change: noop,
28
+ show: noop,
29
+ hide: noop,
30
+
31
+ // Options
32
+ color: false,
33
+ flat: false,
34
+ showInput: false,
35
+ allowEmpty: false,
36
+ showButtons: true,
37
+ clickoutFiresChange: true,
38
+ showInitial: false,
39
+ showPalette: false,
40
+ showPaletteOnly: false,
41
+ hideAfterPaletteSelect: false,
42
+ togglePaletteOnly: false,
43
+ showSelectionPalette: true,
44
+ localStorageKey: false,
45
+ appendTo: "body",
46
+ maxSelectionSize: 7,
47
+ cancelText: "cancel",
48
+ chooseText: "choose",
49
+ togglePaletteMoreText: "more",
50
+ togglePaletteLessText: "less",
51
+ clearText: "Clear Color Selection",
52
+ noColorSelectedText: "No Color Selected",
53
+ preferredFormat: false,
54
+ className: "", // Deprecated - use containerClassName and replacerClassName instead.
55
+ containerClassName: "",
56
+ replacerClassName: "",
57
+ showAlpha: false,
58
+ theme: "sp-light",
59
+ palette: [["#ffffff", "#000000", "#ff0000", "#ff8000", "#ffff00", "#008000", "#0000ff", "#4b0082", "#9400d3"]],
60
+ selectionPalette: [],
61
+ disabled: false,
62
+ offset: null
63
+ },
64
+ spectrums = [],
65
+ IE = !!/msie/i.exec( window.navigator.userAgent ),
66
+ rgbaSupport = (function() {
67
+ function contains( str, substr ) {
68
+ return !!~('' + str).indexOf(substr);
69
+ }
70
+
71
+ var elem = document.createElement('div');
72
+ var style = elem.style;
73
+ style.cssText = 'background-color:rgba(0,0,0,.5)';
74
+ return contains(style.backgroundColor, 'rgba') || contains(style.backgroundColor, 'hsla');
75
+ })(),
76
+ replaceInput = [
77
+ "<div class='sp-replacer'>",
78
+ "<div class='sp-preview'><div class='sp-preview-inner'></div></div>",
79
+ "<div class='sp-dd'>&#9660;</div>",
80
+ "</div>"
81
+ ].join(''),
82
+ markup = (function () {
83
+
84
+ // IE does not support gradients with multiple stops, so we need to simulate
85
+ // that for the rainbow slider with 8 divs that each have a single gradient
86
+ var gradientFix = "";
87
+ if (IE) {
88
+ for (var i = 1; i <= 6; i++) {
89
+ gradientFix += "<div class='sp-" + i + "'></div>";
90
+ }
91
+ }
92
+
93
+ return [
94
+ "<div class='sp-container sp-hidden'>",
95
+ "<div class='sp-palette-container'>",
96
+ "<div class='sp-palette sp-thumb sp-cf'></div>",
97
+ "<div class='sp-palette-button-container sp-cf'>",
98
+ "<button type='button' class='sp-palette-toggle'></button>",
99
+ "</div>",
100
+ "</div>",
101
+ "<div class='sp-picker-container'>",
102
+ "<div class='sp-top sp-cf'>",
103
+ "<div class='sp-fill'></div>",
104
+ "<div class='sp-top-inner'>",
105
+ "<div class='sp-color'>",
106
+ "<div class='sp-sat'>",
107
+ "<div class='sp-val'>",
108
+ "<div class='sp-dragger'></div>",
109
+ "</div>",
110
+ "</div>",
111
+ "</div>",
112
+ "<div class='sp-clear sp-clear-display'>",
113
+ "</div>",
114
+ "<div class='sp-hue'>",
115
+ "<div class='sp-slider'></div>",
116
+ gradientFix,
117
+ "</div>",
118
+ "</div>",
119
+ "<div class='sp-alpha'><div class='sp-alpha-inner'><div class='sp-alpha-handle'></div></div></div>",
120
+ "</div>",
121
+ "<div class='sp-input-container sp-cf'>",
122
+ "<input class='sp-input' type='text' spellcheck='false' />",
123
+ "</div>",
124
+ "<div class='sp-initial sp-thumb sp-cf'></div>",
125
+ "<div class='sp-button-container sp-cf'>",
126
+ "<a class='sp-cancel' href='#'></a>",
127
+ "<button type='button' class='sp-choose'></button>",
128
+ "</div>",
129
+ "</div>",
130
+ "</div>"
131
+ ].join("");
132
+ })();
133
+
134
+ function paletteTemplate (p, color, className, opts) {
135
+ var html = [];
136
+ for (var i = 0; i < p.length; i++) {
137
+ var current = p[i];
138
+ if(current) {
139
+ var tiny = tinycolor(current);
140
+ var c = tiny.toHsl().l < 0.5 ? "sp-thumb-el sp-thumb-dark" : "sp-thumb-el sp-thumb-light";
141
+ c += (tinycolor.equals(color, current)) ? " sp-thumb-active" : "";
142
+ var formattedString = tiny.toString(opts.preferredFormat || "rgb");
143
+ var swatchStyle = rgbaSupport ? ("background-color:" + tiny.toRgbString()) : "filter:" + tiny.toFilter();
144
+ html.push('<span title="' + formattedString + '" data-color="' + tiny.toRgbString() + '" class="' + c + '"><span class="sp-thumb-inner" style="' + swatchStyle + ';" /></span>');
145
+ } else {
146
+ var cls = 'sp-clear-display';
147
+ html.push($('<div />')
148
+ .append($('<span data-color="" style="background-color:transparent;" class="' + cls + '"></span>')
149
+ .attr('title', opts.noColorSelectedText)
150
+ )
151
+ .html()
152
+ );
153
+ }
154
+ }
155
+ return "<div class='sp-cf " + className + "'>" + html.join('') + "</div>";
156
+ }
157
+
158
+ function hideAll() {
159
+ for (var i = 0; i < spectrums.length; i++) {
160
+ if (spectrums[i]) {
161
+ spectrums[i].hide();
162
+ }
163
+ }
164
+ }
165
+
166
+ function instanceOptions(o, callbackContext) {
167
+ var opts = $.extend({}, defaultOpts, o);
168
+ opts.callbacks = {
169
+ 'move': bind(opts.move, callbackContext),
170
+ 'change': bind(opts.change, callbackContext),
171
+ 'show': bind(opts.show, callbackContext),
172
+ 'hide': bind(opts.hide, callbackContext),
173
+ 'beforeShow': bind(opts.beforeShow, callbackContext)
174
+ };
175
+
176
+ return opts;
177
+ }
178
+
179
+ function spectrum(element, o) {
180
+
181
+ var opts = instanceOptions(o, element),
182
+ flat = opts.flat,
183
+ showSelectionPalette = opts.showSelectionPalette,
184
+ localStorageKey = opts.localStorageKey,
185
+ theme = opts.theme,
186
+ callbacks = opts.callbacks,
187
+ resize = throttle(reflow, 10),
188
+ visible = false,
189
+ isDragging = false,
190
+ dragWidth = 0,
191
+ dragHeight = 0,
192
+ dragHelperHeight = 0,
193
+ slideHeight = 0,
194
+ slideWidth = 0,
195
+ alphaWidth = 0,
196
+ alphaSlideHelperWidth = 0,
197
+ slideHelperHeight = 0,
198
+ currentHue = 0,
199
+ currentSaturation = 0,
200
+ currentValue = 0,
201
+ currentAlpha = 1,
202
+ palette = [],
203
+ paletteArray = [],
204
+ paletteLookup = {},
205
+ selectionPalette = opts.selectionPalette.slice(0),
206
+ maxSelectionSize = opts.maxSelectionSize,
207
+ draggingClass = "sp-dragging",
208
+ shiftMovementDirection = null;
209
+
210
+ var doc = element.ownerDocument,
211
+ body = doc.body,
212
+ boundElement = $(element),
213
+ disabled = false,
214
+ container = $(markup, doc).addClass(theme),
215
+ pickerContainer = container.find(".sp-picker-container"),
216
+ dragger = container.find(".sp-color"),
217
+ dragHelper = container.find(".sp-dragger"),
218
+ slider = container.find(".sp-hue"),
219
+ slideHelper = container.find(".sp-slider"),
220
+ alphaSliderInner = container.find(".sp-alpha-inner"),
221
+ alphaSlider = container.find(".sp-alpha"),
222
+ alphaSlideHelper = container.find(".sp-alpha-handle"),
223
+ textInput = container.find(".sp-input"),
224
+ paletteContainer = container.find(".sp-palette"),
225
+ initialColorContainer = container.find(".sp-initial"),
226
+ cancelButton = container.find(".sp-cancel"),
227
+ clearButton = container.find(".sp-clear"),
228
+ chooseButton = container.find(".sp-choose"),
229
+ toggleButton = container.find(".sp-palette-toggle"),
230
+ isInput = boundElement.is("input"),
231
+ isInputTypeColor = isInput && boundElement.attr("type") === "color" && inputTypeColorSupport(),
232
+ shouldReplace = isInput && !flat,
233
+ replacer = (shouldReplace) ? $(replaceInput).addClass(theme).addClass(opts.className).addClass(opts.replacerClassName) : $([]),
234
+ offsetElement = (shouldReplace) ? replacer : boundElement,
235
+ previewElement = replacer.find(".sp-preview-inner"),
236
+ initialColor = opts.color || (isInput && boundElement.val()),
237
+ colorOnShow = false,
238
+ preferredFormat = opts.preferredFormat,
239
+ currentPreferredFormat = preferredFormat,
240
+ clickoutFiresChange = !opts.showButtons || opts.clickoutFiresChange,
241
+ isEmpty = !initialColor,
242
+ allowEmpty = opts.allowEmpty && !isInputTypeColor;
243
+
244
+ function applyOptions() {
245
+
246
+ if (opts.showPaletteOnly) {
247
+ opts.showPalette = true;
248
+ }
249
+
250
+ toggleButton.text(opts.showPaletteOnly ? opts.togglePaletteMoreText : opts.togglePaletteLessText);
251
+
252
+ if (opts.palette) {
253
+ palette = opts.palette.slice(0);
254
+ paletteArray = $.isArray(palette[0]) ? palette : [palette];
255
+ paletteLookup = {};
256
+ for (var i = 0; i < paletteArray.length; i++) {
257
+ for (var j = 0; j < paletteArray[i].length; j++) {
258
+ var rgb = tinycolor(paletteArray[i][j]).toRgbString();
259
+ paletteLookup[rgb] = true;
260
+ }
261
+ }
262
+ }
263
+
264
+ container.toggleClass("sp-flat", flat);
265
+ container.toggleClass("sp-input-disabled", !opts.showInput);
266
+ container.toggleClass("sp-alpha-enabled", opts.showAlpha);
267
+ container.toggleClass("sp-clear-enabled", allowEmpty);
268
+ container.toggleClass("sp-buttons-disabled", !opts.showButtons);
269
+ container.toggleClass("sp-palette-buttons-disabled", !opts.togglePaletteOnly);
270
+ container.toggleClass("sp-palette-disabled", !opts.showPalette);
271
+ container.toggleClass("sp-palette-only", opts.showPaletteOnly);
272
+ container.toggleClass("sp-initial-disabled", !opts.showInitial);
273
+ container.addClass(opts.className).addClass(opts.containerClassName);
274
+
275
+ reflow();
276
+ }
277
+
278
+ function initialize() {
279
+
280
+ if (IE) {
281
+ container.find("*:not(input)").attr("unselectable", "on");
282
+ }
283
+
284
+ applyOptions();
285
+
286
+ if (shouldReplace) {
287
+ boundElement.after(replacer);//.hide();
288
+ }
289
+
290
+ if (!allowEmpty) {
291
+ clearButton.hide();
292
+ }
293
+
294
+ if (flat) {
295
+ boundElement.after(container).hide();
296
+ }
297
+ else {
298
+
299
+ var appendTo = opts.appendTo === "parent" ? boundElement.parent() : $(opts.appendTo);
300
+ if (appendTo.length !== 1) {
301
+ appendTo = $("body");
302
+ }
303
+
304
+ appendTo.append(container);
305
+ }
306
+
307
+ updateSelectionPaletteFromStorage();
308
+
309
+ offsetElement.on("click.spectrum touchstart.spectrum", function (e) {
310
+ if (!disabled) {
311
+ toggle();
312
+ }
313
+
314
+ e.stopPropagation();
315
+
316
+ if (!$(e.target).is("input")) {
317
+ e.preventDefault();
318
+ }
319
+ });
320
+
321
+ if(boundElement.is(":disabled") || (opts.disabled === true)) {
322
+ disable();
323
+ }
324
+
325
+ // Prevent clicks from bubbling up to document. This would cause it to be hidden.
326
+ container.click(stopPropagation);
327
+
328
+ // Handle user typed input
329
+ textInput.change(setFromTextInput);
330
+ textInput.bind("paste", function () {
331
+ //console.log( 'paste event' );
332
+ setTimeout(setFromTextInput, 1);
333
+ });
334
+ textInput.keydown(function (e) { if (e.keyCode == 13) {
335
+ //console.log( 'return event' );
336
+ setFromTextInput();
337
+ } });
338
+
339
+ cancelButton.text(opts.cancelText);
340
+ cancelButton.bind("click.spectrum", function (e) {
341
+ e.stopPropagation();
342
+ e.preventDefault();
343
+ revert();
344
+ hide();
345
+ });
346
+
347
+ clearButton.attr("title", opts.clearText);
348
+ clearButton.bind("click.spectrum", function (e) {
349
+ e.stopPropagation();
350
+ e.preventDefault();
351
+ isEmpty = true;
352
+ move();
353
+
354
+ if(flat) {
355
+ //for the flat style, this is a change event
356
+ updateOriginalInput(true);
357
+ }
358
+ });
359
+
360
+ chooseButton.text(opts.chooseText);
361
+ chooseButton.bind("click.spectrum", function (e) {
362
+ e.stopPropagation();
363
+ e.preventDefault();
364
+
365
+ if (IE && textInput.is(":focus")) {
366
+ textInput.trigger('change');
367
+ }
368
+
369
+ if (isValid()) {
370
+ updateOriginalInput(true);
371
+ hide();
372
+ }
373
+ });
374
+
375
+ toggleButton.text(opts.showPaletteOnly ? opts.togglePaletteMoreText : opts.togglePaletteLessText);
376
+ toggleButton.bind("click.spectrum", function (e) {
377
+ e.stopPropagation();
378
+ e.preventDefault();
379
+
380
+ opts.showPaletteOnly = !opts.showPaletteOnly;
381
+
382
+ // To make sure the Picker area is drawn on the right, next to the
383
+ // Palette area (and not below the palette), first move the Palette
384
+ // to the left to make space for the picker, plus 5px extra.
385
+ // The 'applyOptions' function puts the whole container back into place
386
+ // and takes care of the button-text and the sp-palette-only CSS class.
387
+ if (!opts.showPaletteOnly && !flat) {
388
+ container.css('left', '-=' + (pickerContainer.outerWidth(true) + 5));
389
+ }
390
+ applyOptions();
391
+ });
392
+
393
+ draggable(alphaSlider, function (dragX, dragY, e) {
394
+ currentAlpha = (dragX / alphaWidth);
395
+ isEmpty = false;
396
+ if (e.shiftKey) {
397
+ currentAlpha = Math.round(currentAlpha * 10) / 10;
398
+ }
399
+
400
+ move();
401
+ }, dragStart, dragStop);
402
+
403
+ draggable(slider, function (dragX, dragY) {
404
+ currentHue = parseFloat(dragY / slideHeight);
405
+ isEmpty = false;
406
+ if (!opts.showAlpha) {
407
+ currentAlpha = 1;
408
+ }
409
+ move();
410
+ }, dragStart, dragStop);
411
+
412
+ draggable(dragger, function (dragX, dragY, e) {
413
+
414
+ // shift+drag should snap the movement to either the x or y axis.
415
+ if (!e.shiftKey) {
416
+ shiftMovementDirection = null;
417
+ }
418
+ else if (!shiftMovementDirection) {
419
+ var oldDragX = currentSaturation * dragWidth;
420
+ var oldDragY = dragHeight - (currentValue * dragHeight);
421
+ var furtherFromX = Math.abs(dragX - oldDragX) > Math.abs(dragY - oldDragY);
422
+
423
+ shiftMovementDirection = furtherFromX ? "x" : "y";
424
+ }
425
+
426
+ var setSaturation = !shiftMovementDirection || shiftMovementDirection === "x";
427
+ var setValue = !shiftMovementDirection || shiftMovementDirection === "y";
428
+
429
+ if (setSaturation) {
430
+ currentSaturation = parseFloat(dragX / dragWidth);
431
+ }
432
+ if (setValue) {
433
+ currentValue = parseFloat((dragHeight - dragY) / dragHeight);
434
+ }
435
+
436
+ isEmpty = false;
437
+ if (!opts.showAlpha) {
438
+ currentAlpha = 1;
439
+ }
440
+
441
+ move();
442
+
443
+ }, dragStart, dragStop);
444
+
445
+ if (!!initialColor) {
446
+ //console.log( 'initialColor: ' + initialColor );
447
+ set(initialColor);
448
+ // In case color was black - update the preview UI and set the format
449
+ // since the set function will not run (default color is black).
450
+ //console.log( 'initialize: calling updateUI...' );
451
+ updateUI();
452
+ //currentPreferredFormat = preferredFormat || tinycolor(initialColor).format;
453
+
454
+ addColorToSelectionPalette(initialColor);
455
+ }
456
+ else {
457
+ updateUI();
458
+ }
459
+
460
+ if (flat) {
461
+ show();
462
+ }
463
+
464
+ function paletteElementClick(e) {
465
+ if (e.data && e.data.ignore) {
466
+ set($(e.target).closest(".sp-thumb-el").data("color"));
467
+ move();
468
+ }
469
+ else {
470
+ set($(e.target).closest(".sp-thumb-el").data("color"));
471
+ move();
472
+ updateOriginalInput(true);
473
+ if (opts.hideAfterPaletteSelect) {
474
+ hide();
475
+ }
476
+ }
477
+
478
+ return false;
479
+ }
480
+
481
+ var paletteEvent = IE ? "mousedown.spectrum" : "click.spectrum touchstart.spectrum";
482
+ paletteContainer.delegate(".sp-thumb-el", paletteEvent, paletteElementClick);
483
+ initialColorContainer.delegate(".sp-thumb-el:nth-child(1)", paletteEvent, { ignore: true }, paletteElementClick);
484
+ }
485
+
486
+ function updateSelectionPaletteFromStorage() {
487
+
488
+ if (localStorageKey && window.localStorage) {
489
+
490
+ // Migrate old palettes over to new format. May want to remove this eventually.
491
+ try {
492
+ var oldPalette = window.localStorage[localStorageKey].split(",#");
493
+ if (oldPalette.length > 1) {
494
+ delete window.localStorage[localStorageKey];
495
+ $.each(oldPalette, function(i, c) {
496
+ addColorToSelectionPalette(c);
497
+ });
498
+ }
499
+ }
500
+ catch(e) { }
501
+
502
+ try {
503
+ selectionPalette = window.localStorage[localStorageKey].split(";");
504
+ }
505
+ catch (e) { }
506
+ }
507
+ }
508
+
509
+ function addColorToSelectionPalette(color) {
510
+ if (showSelectionPalette) {
511
+ var rgb = tinycolor(color).toRgbString();
512
+ if (!paletteLookup[rgb] && $.inArray(rgb, selectionPalette) === -1) {
513
+ selectionPalette.push(rgb);
514
+ while(selectionPalette.length > maxSelectionSize) {
515
+ selectionPalette.shift();
516
+ }
517
+ }
518
+
519
+ if (localStorageKey && window.localStorage) {
520
+ try {
521
+ window.localStorage[localStorageKey] = selectionPalette.join(";");
522
+ }
523
+ catch(e) { }
524
+ }
525
+ }
526
+ }
527
+
528
+ function getUniqueSelectionPalette() {
529
+ var unique = [];
530
+ if (opts.showPalette) {
531
+ for (var i = 0; i < selectionPalette.length; i++) {
532
+ var rgb = tinycolor(selectionPalette[i]).toRgbString();
533
+
534
+ if (!paletteLookup[rgb]) {
535
+ unique.push(selectionPalette[i]);
536
+ }
537
+ }
538
+ }
539
+
540
+ return unique.reverse().slice(0, opts.maxSelectionSize);
541
+ }
542
+
543
+ function drawPalette() {
544
+
545
+ var currentColor = get();
546
+
547
+ var html = $.map(paletteArray, function (palette, i) {
548
+ return paletteTemplate(palette, currentColor, "sp-palette-row sp-palette-row-" + i, opts);
549
+ });
550
+
551
+ updateSelectionPaletteFromStorage();
552
+
553
+ if (selectionPalette) {
554
+ html.push(paletteTemplate(getUniqueSelectionPalette(), currentColor, "sp-palette-row sp-palette-row-selection", opts));
555
+ }
556
+
557
+ paletteContainer.html(html.join(""));
558
+ }
559
+
560
+ function drawInitial() {
561
+ if (opts.showInitial) {
562
+ var initial = colorOnShow;
563
+ var current = get();
564
+ initialColorContainer.html(paletteTemplate([initial, current], current, "sp-palette-row-initial", opts));
565
+ }
566
+ }
567
+
568
+ function dragStart() {
569
+ if (dragHeight <= 0 || dragWidth <= 0 || slideHeight <= 0) {
570
+ reflow();
571
+ }
572
+ isDragging = true;
573
+ container.addClass(draggingClass);
574
+ shiftMovementDirection = null;
575
+ boundElement.trigger('dragstart.spectrum', [ get() ]);
576
+ }
577
+
578
+ function dragStop() {
579
+ isDragging = false;
580
+ container.removeClass(draggingClass);
581
+ boundElement.trigger('dragstop.spectrum', [ get() ]);
582
+ }
583
+
584
+ function setFromTextInput( e ) {
585
+ //console.log( 'setFromTextInput' );
586
+ //console.log( e );
587
+ var value = textInput.val();
588
+ if ((value === null || value === "") && allowEmpty) {
589
+ set(null);
590
+ updateOriginalInput(true);
591
+ }
592
+ else {
593
+ var tiny = tinycolor(value);
594
+ //console.log( 'setFromTextInput: ' + tiny.getFormat() );
595
+ if (tiny.isValid()) {
596
+ preferredFormat = currentPreferredFormat = tiny.getFormat();
597
+ set(tiny);
598
+ updateOriginalInput(true);
599
+ }
600
+ else {
601
+ textInput.addClass("sp-validation-error");
602
+ }
603
+ }
604
+ //console.log( 'setFromTextInput: ' + value );
605
+ //console.log( 'setFromTextInput: ' + currentPreferredFormat );
606
+ }
607
+
608
+ function toggle() {
609
+ if (visible) {
610
+ hide();
611
+ }
612
+ else {
613
+ show();
614
+ }
615
+ }
616
+
617
+ function show() {
618
+ var event = $.Event('beforeShow.spectrum');
619
+
620
+ if (visible) {
621
+ reflow();
622
+ return;
623
+ }
624
+
625
+ boundElement.trigger(event, [ get() ]);
626
+
627
+ if (callbacks.beforeShow(get()) === false || event.isDefaultPrevented()) {
628
+ return;
629
+ }
630
+
631
+ hideAll();
632
+ visible = true;
633
+
634
+ $(doc).bind("keydown.spectrum", onkeydown);
635
+ $(doc).bind("click.spectrum", clickout);
636
+ $(window).bind("resize.spectrum", resize);
637
+ replacer.addClass("sp-active");
638
+ container.removeClass("sp-hidden");
639
+
640
+ reflow();
641
+ updateUI();
642
+
643
+ colorOnShow = get();
644
+
645
+ drawInitial();
646
+ callbacks.show(colorOnShow);
647
+ boundElement.trigger('show.spectrum', [ colorOnShow ]);
648
+ }
649
+
650
+ function onkeydown(e) {
651
+ // Close on ESC
652
+ if (e.keyCode === 27) {
653
+ hide();
654
+ }
655
+ }
656
+
657
+ function clickout(e) {
658
+ // Return on right click.
659
+ if (e.button == 2) { return; }
660
+
661
+ // If a drag event was happening during the mouseup, don't hide
662
+ // on click.
663
+ if (isDragging) { return; }
664
+
665
+ if (clickoutFiresChange) {
666
+ updateOriginalInput(true);
667
+ }
668
+ else {
669
+ revert();
670
+ }
671
+ hide();
672
+ }
673
+
674
+ function hide() {
675
+ // Return if hiding is unnecessary
676
+ if (!visible || flat) { return; }
677
+ visible = false;
678
+
679
+ $(doc).unbind("keydown.spectrum", onkeydown);
680
+ $(doc).unbind("click.spectrum", clickout);
681
+ $(window).unbind("resize.spectrum", resize);
682
+
683
+ replacer.removeClass("sp-active");
684
+ container.addClass("sp-hidden");
685
+
686
+ callbacks.hide(get());
687
+ boundElement.trigger('hide.spectrum', [ get() ]);
688
+ }
689
+
690
+ function revert() {
691
+ set(colorOnShow, true);
692
+ }
693
+
694
+ function set(color, ignoreFormatChange) {
695
+ if (tinycolor.equals(color, get())) {
696
+ // Update UI just in case a validation error needs
697
+ // to be cleared.
698
+ //console.log( 'set ( no change ): calling updateUI...' );
699
+ updateUI();
700
+ return;
701
+ }
702
+
703
+ var newColor, newHsv, newFormat;
704
+ if (!color && allowEmpty) {
705
+ isEmpty = true;
706
+ } else {
707
+ isEmpty = false;
708
+ newColor = tinycolor(color);
709
+ newHsv = newColor.toHsv();
710
+
711
+ currentHue = (newHsv.h % 360) / 360;
712
+ currentSaturation = newHsv.s;
713
+ currentValue = newHsv.v;
714
+ currentAlpha = newHsv.a;
715
+ }
716
+ //console.log( 'set ( newColor ): calling updateUI...' );
717
+ updateUI();
718
+
719
+ if (newColor && newColor.isValid() && !ignoreFormatChange) {
720
+ newFormat = newColor.getFormat();
721
+ if ( 'name' === newFormat ) {
722
+ preferredFormat = newFormat;
723
+ }
724
+ currentPreferredFormat = preferredFormat || newFormat;
725
+ }
726
+ }
727
+
728
+ function get(opts) {
729
+ opts = opts || { };
730
+
731
+ if (allowEmpty && isEmpty) {
732
+ return null;
733
+ }
734
+
735
+ return tinycolor.fromRatio({
736
+ h: currentHue,
737
+ s: currentSaturation,
738
+ v: currentValue,
739
+ a: Math.round(currentAlpha * 100) / 100
740
+ }, { format: opts.format || currentPreferredFormat });
741
+ }
742
+
743
+ function isValid() {
744
+ return !textInput.hasClass("sp-validation-error");
745
+ }
746
+
747
+ function move() {
748
+ updateUI();
749
+
750
+ callbacks.move(get());
751
+ boundElement.trigger('move.spectrum', [ get() ]);
752
+ }
753
+
754
+ function updateUI() {
755
+
756
+ textInput.removeClass("sp-validation-error");
757
+
758
+ updateHelperLocations();
759
+
760
+ // Update dragger background color (gradients take care of saturation and value).
761
+ var flatColor = tinycolor.fromRatio({ h: currentHue, s: 1, v: 1 });
762
+ dragger.css("background-color", flatColor.toHexString());
763
+
764
+ // Get a format that alpha will be included in (hex and names ignore alpha)
765
+ var format = currentPreferredFormat;
766
+ if (currentAlpha < 1 && !(currentAlpha === 0 && format === "name")) {
767
+ if (format === "hex" || format === "hex3" || format === "hex6" || format === "name") {
768
+ format = "rgb";
769
+ }
770
+ }
771
+ //console.log( 'updateUI: format: ' + format );
772
+ var realColor = get({ format: format }),
773
+ displayColor = '';
774
+
775
+ //reset background info for preview element
776
+ previewElement.removeClass("sp-clear-display");
777
+ previewElement.css('background-color', 'transparent');
778
+
779
+ if (!realColor && allowEmpty) {
780
+ // Update the replaced elements background with icon indicating no color selection
781
+ previewElement.addClass("sp-clear-display");
782
+ }
783
+ else {
784
+ var realHex = realColor.toHexString(),
785
+ realRgb = realColor.toRgbString();
786
+
787
+ // Update the replaced elements background color (with actual selected color)
788
+ if (rgbaSupport || realColor.alpha === 1) {
789
+ previewElement.css("background-color", realRgb);
790
+ }
791
+ else {
792
+ previewElement.css("background-color", "transparent");
793
+ previewElement.css("filter", realColor.toFilter());
794
+ }
795
+
796
+ if (opts.showAlpha) {
797
+ var rgb = realColor.toRgb();
798
+ rgb.a = 0;
799
+ var realAlpha = tinycolor(rgb).toRgbString();
800
+ var gradient = "linear-gradient(left, " + realAlpha + ", " + realHex + ")";
801
+
802
+ if (IE) {
803
+ alphaSliderInner.css("filter", tinycolor(realAlpha).toFilter({ gradientType: 1 }, realHex));
804
+ }
805
+ else {
806
+ alphaSliderInner.css("background", "-webkit-" + gradient);
807
+ alphaSliderInner.css("background", "-moz-" + gradient);
808
+ alphaSliderInner.css("background", "-ms-" + gradient);
809
+ // Use current syntax gradient on unprefixed property.
810
+ alphaSliderInner.css("background",
811
+ "linear-gradient(to right, " + realAlpha + ", " + realHex + ")");
812
+ }
813
+ }
814
+
815
+ displayColor = realColor.toString(format);
816
+ }
817
+
818
+ // Update the text entry input as it changes happen
819
+ if (opts.showInput) {
820
+ //console.log( 'updateUI: displayColor: ' + displayColor );
821
+ textInput.val(displayColor);
822
+ }
823
+
824
+ if (opts.showPalette) {
825
+ drawPalette();
826
+ }
827
+
828
+ drawInitial();
829
+ }
830
+
831
+ function updateHelperLocations() {
832
+ var s = currentSaturation;
833
+ var v = currentValue;
834
+
835
+ if(allowEmpty && isEmpty) {
836
+ //if selected color is empty, hide the helpers
837
+ alphaSlideHelper.hide();
838
+ slideHelper.hide();
839
+ dragHelper.hide();
840
+ }
841
+ else {
842
+ //make sure helpers are visible
843
+ alphaSlideHelper.show();
844
+ slideHelper.show();
845
+ dragHelper.show();
846
+
847
+ // Where to show the little circle in that displays your current selected color
848
+ var dragX = s * dragWidth;
849
+ var dragY = dragHeight - (v * dragHeight);
850
+ dragX = Math.max(
851
+ -dragHelperHeight,
852
+ Math.min(dragWidth - dragHelperHeight, dragX - dragHelperHeight)
853
+ );
854
+ dragY = Math.max(
855
+ -dragHelperHeight,
856
+ Math.min(dragHeight - dragHelperHeight, dragY - dragHelperHeight)
857
+ );
858
+ dragHelper.css({
859
+ "top": dragY + "px",
860
+ "left": dragX + "px"
861
+ });
862
+
863
+ var alphaX = currentAlpha * alphaWidth;
864
+ alphaSlideHelper.css({
865
+ "left": (alphaX - (alphaSlideHelperWidth / 2)) + "px"
866
+ });
867
+
868
+ // Where to show the bar that displays your current selected hue
869
+ var slideY = (currentHue) * slideHeight;
870
+ slideHelper.css({
871
+ "top": (slideY - slideHelperHeight) + "px"
872
+ });
873
+ }
874
+ }
875
+
876
+ function updateOriginalInput(fireCallback) {
877
+ var color = get(),
878
+ displayColor = '',
879
+ hasChanged = !tinycolor.equals(color, colorOnShow),
880
+ format = currentPreferredFormat;
881
+ if (color) {
882
+ /**
883
+ * This is pulled from UpdateUI
884
+ * Original input needs to follow same logic, right?
885
+ */
886
+ if (currentAlpha < 1 && !(currentAlpha === 0 && format === "name")) {
887
+ if (format === "hex" || format === "hex3" || format === "hex6" || format === "name") {
888
+ format = "rgb";
889
+ }
890
+ }
891
+ displayColor = color.toString(format);
892
+ //console.log( 'updateOriginalInput: ' + ' format: ' + format );
893
+ //console.log( 'currentPreferredFormat: ' + currentPreferredFormat);
894
+ //console.log( 'colorOnShow: ' + colorOnShow );
895
+ //console.log( 'displayColor: ' + displayColor );
896
+ //console.log( 'hasChanged: ' + hasChanged );
897
+ //console.log( 'isInput: ' + isInput );
898
+ //console.log( 'fireCallback: ' + fireCallback );
899
+ // Update the selection palette with the current color
900
+ addColorToSelectionPalette(color);
901
+ }
902
+
903
+ if (isInput) {
904
+ boundElement.val(displayColor);
905
+ }
906
+
907
+ if (fireCallback && hasChanged) {
908
+ callbacks.change(color);
909
+ boundElement.trigger('change', [ color ]);
910
+ }
911
+ }
912
+
913
+ function reflow() {
914
+ dragWidth = dragger.width();
915
+ dragHeight = dragger.height();
916
+ dragHelperHeight = dragHelper.height();
917
+ slideWidth = slider.width();
918
+ slideHeight = slider.height();
919
+ slideHelperHeight = slideHelper.height();
920
+ alphaWidth = alphaSlider.width();
921
+ alphaSlideHelperWidth = alphaSlideHelper.width();
922
+
923
+ if (!flat) {
924
+ container.css("position", "absolute");
925
+ if (opts.offset) {
926
+ container.offset(opts.offset);
927
+ } else {
928
+ container.offset(getOffset(container, offsetElement));
929
+ }
930
+ }
931
+
932
+ updateHelperLocations();
933
+
934
+ if (opts.showPalette) {
935
+ drawPalette();
936
+ }
937
+
938
+ boundElement.trigger('reflow.spectrum');
939
+ }
940
+
941
+ function destroy() {
942
+ boundElement.show();
943
+ offsetElement.unbind("click.spectrum touchstart.spectrum");
944
+ container.remove();
945
+ replacer.remove();
946
+ spectrums[spect.id] = null;
947
+ }
948
+
949
+ function option(optionName, optionValue) {
950
+ if (optionName === undefined) {
951
+ return $.extend({}, opts);
952
+ }
953
+ if (optionValue === undefined) {
954
+ return opts[optionName];
955
+ }
956
+
957
+ opts[optionName] = optionValue;
958
+ applyOptions();
959
+ }
960
+
961
+ function enable() {
962
+ disabled = false;
963
+ boundElement.attr("disabled", false);
964
+ offsetElement.removeClass("sp-disabled");
965
+ }
966
+
967
+ function disable() {
968
+ hide();
969
+ disabled = true;
970
+ boundElement.attr("disabled", true);
971
+ offsetElement.addClass("sp-disabled");
972
+ }
973
+
974
+ function setOffset(coord) {
975
+ opts.offset = coord;
976
+ reflow();
977
+ }
978
+
979
+ initialize();
980
+
981
+ var spect = {
982
+ show: show,
983
+ hide: hide,
984
+ toggle: toggle,
985
+ reflow: reflow,
986
+ option: option,
987
+ enable: enable,
988
+ disable: disable,
989
+ offset: setOffset,
990
+ set: function (c) {
991
+ set(c);
992
+ // for CTC, don't update original input
993
+ // because set is called from original input
994
+ //updateOriginalInput();
995
+ },
996
+ get: get,
997
+ destroy: destroy,
998
+ container: container
999
+ };
1000
+
1001
+ spect.id = spectrums.push(spect) - 1;
1002
+
1003
+ return spect;
1004
+ }
1005
+
1006
+ /**
1007
+ * checkOffset - get the offset below/above and left/right element depending on screen position
1008
+ * Thanks https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.datepicker.js
1009
+ */
1010
+ function getOffset(picker, input) {
1011
+ var extraY = 0;
1012
+ var dpWidth = picker.outerWidth();
1013
+ var dpHeight = picker.outerHeight();
1014
+ var inputHeight = input.outerHeight();
1015
+ var doc = picker[0].ownerDocument;
1016
+ var docElem = doc.documentElement;
1017
+ var viewWidth = docElem.clientWidth + $(doc).scrollLeft();
1018
+ var viewHeight = docElem.clientHeight + $(doc).scrollTop();
1019
+ var offset = input.offset();
1020
+ offset.top += inputHeight;
1021
+
1022
+ offset.left -=
1023
+ Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
1024
+ Math.abs(offset.left + dpWidth - viewWidth) : 0);
1025
+
1026
+ offset.top -=
1027
+ Math.min(offset.top, ((offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
1028
+ Math.abs(dpHeight + inputHeight - extraY) : extraY));
1029
+
1030
+ return offset;
1031
+ }
1032
+
1033
+ /**
1034
+ * noop - do nothing
1035
+ */
1036
+ function noop() {
1037
+
1038
+ }
1039
+
1040
+ /**
1041
+ * stopPropagation - makes the code only doing this a little easier to read in line
1042
+ */
1043
+ function stopPropagation(e) {
1044
+ e.stopPropagation();
1045
+ }
1046
+
1047
+ /**
1048
+ * Create a function bound to a given object
1049
+ * Thanks to underscore.js
1050
+ */
1051
+ function bind(func, obj) {
1052
+ var slice = Array.prototype.slice;
1053
+ var args = slice.call(arguments, 2);
1054
+ return function () {
1055
+ return func.apply(obj, args.concat(slice.call(arguments)));
1056
+ };
1057
+ }
1058
+
1059
+ /**
1060
+ * Lightweight drag helper. Handles containment within the element, so that
1061
+ * when dragging, the x is within [0,element.width] and y is within [0,element.height]
1062
+ */
1063
+ function draggable(element, onmove, onstart, onstop) {
1064
+ onmove = onmove || function () { };
1065
+ onstart = onstart || function () { };
1066
+ onstop = onstop || function () { };
1067
+ var doc = document;
1068
+ var dragging = false;
1069
+ var offset = {};
1070
+ var maxHeight = 0;
1071
+ var maxWidth = 0;
1072
+ var hasTouch = ('ontouchstart' in window);
1073
+
1074
+ var duringDragEvents = {};
1075
+ duringDragEvents["selectstart"] = prevent;
1076
+ duringDragEvents["dragstart"] = prevent;
1077
+ duringDragEvents["touchmove mousemove"] = move;
1078
+ duringDragEvents["touchend mouseup"] = stop;
1079
+
1080
+ function prevent(e) {
1081
+ if (e.stopPropagation) {
1082
+ e.stopPropagation();
1083
+ }
1084
+ if (e.preventDefault) {
1085
+ e.preventDefault();
1086
+ }
1087
+ e.returnValue = false;
1088
+ }
1089
+
1090
+ function move(e) {
1091
+ if (dragging) {
1092
+ // Mouseup happened outside of window
1093
+ if (IE && doc.documentMode < 9 && !e.button) {
1094
+ return stop();
1095
+ }
1096
+
1097
+ var t0 = e.originalEvent && e.originalEvent.touches && e.originalEvent.touches[0];
1098
+ var pageX = t0 && t0.pageX || e.pageX;
1099
+ var pageY = t0 && t0.pageY || e.pageY;
1100
+
1101
+ var dragX = Math.max(0, Math.min(pageX - offset.left, maxWidth));
1102
+ var dragY = Math.max(0, Math.min(pageY - offset.top, maxHeight));
1103
+
1104
+ if (hasTouch) {
1105
+ // Stop scrolling in iOS
1106
+ prevent(e);
1107
+ }
1108
+
1109
+ onmove.apply(element, [dragX, dragY, e]);
1110
+ }
1111
+ }
1112
+
1113
+ function start(e) {
1114
+ var rightclick = (e.which) ? (e.which == 3) : (e.button == 2);
1115
+
1116
+ if (!rightclick && !dragging) {
1117
+ if (onstart.apply(element, arguments) !== false) {
1118
+ dragging = true;
1119
+ maxHeight = $(element).height();
1120
+ maxWidth = $(element).width();
1121
+ offset = $(element).offset();
1122
+
1123
+ $(doc).bind(duringDragEvents);
1124
+ $(doc.body).addClass("sp-dragging");
1125
+
1126
+ move(e);
1127
+
1128
+ prevent(e);
1129
+ }
1130
+ }
1131
+ }
1132
+
1133
+ function stop() {
1134
+ if (dragging) {
1135
+ $(doc).unbind(duringDragEvents);
1136
+ $(doc.body).removeClass("sp-dragging");
1137
+
1138
+ // Wait a tick before notifying observers to allow the click event
1139
+ // to fire in Chrome.
1140
+ setTimeout(function() {
1141
+ onstop.apply(element, arguments);
1142
+ }, 0);
1143
+ }
1144
+ dragging = false;
1145
+ }
1146
+
1147
+ $(element).bind("touchstart mousedown", start);
1148
+ }
1149
+
1150
+ function throttle(func, wait, debounce) {
1151
+ var timeout;
1152
+ return function () {
1153
+ var context = this, args = arguments;
1154
+ var throttler = function () {
1155
+ timeout = null;
1156
+ func.apply(context, args);
1157
+ };
1158
+ if (debounce) clearTimeout(timeout);
1159
+ if (debounce || !timeout) timeout = setTimeout(throttler, wait);
1160
+ };
1161
+ }
1162
+
1163
+ function inputTypeColorSupport() {
1164
+ return $.fn.spectrum.inputTypeColorSupport();
1165
+ }
1166
+
1167
+ /**
1168
+ * Define a jQuery plugin
1169
+ */
1170
+ var dataID = "spectrum.id";
1171
+ $.fn.spectrum = function (opts, extra) {
1172
+
1173
+ if (typeof opts == "string") {
1174
+
1175
+ var returnValue = this;
1176
+ var args = Array.prototype.slice.call( arguments, 1 );
1177
+
1178
+ this.each(function () {
1179
+ var spect = spectrums[$(this).data(dataID)];
1180
+ if (spect) {
1181
+ var method = spect[opts];
1182
+ if (!method) {
1183
+ throw new Error( "Spectrum: no such method: '" + opts + "'" );
1184
+ }
1185
+
1186
+ if (opts == "get") {
1187
+ returnValue = spect.get();
1188
+ }
1189
+ else if (opts == "container") {
1190
+ returnValue = spect.container;
1191
+ }
1192
+ else if (opts == "option") {
1193
+ returnValue = spect.option.apply(spect, args);
1194
+ }
1195
+ else if (opts == "destroy") {
1196
+ spect.destroy();
1197
+ $(this).removeData(dataID);
1198
+ }
1199
+ else {
1200
+ method.apply(spect, args);
1201
+ }
1202
+ }
1203
+ });
1204
+
1205
+ return returnValue;
1206
+ }
1207
+
1208
+ // Initializing a new instance of spectrum
1209
+ return this.spectrum("destroy").each(function () {
1210
+ var options = $.extend({}, opts, $(this).data());
1211
+ var spect = spectrum(this, options);
1212
+ $(this).data(dataID, spect.id);
1213
+ });
1214
+ };
1215
+
1216
+ $.fn.spectrum.load = true;
1217
+ $.fn.spectrum.loadOpts = {};
1218
+ $.fn.spectrum.draggable = draggable;
1219
+ $.fn.spectrum.defaults = defaultOpts;
1220
+ $.fn.spectrum.inputTypeColorSupport = function inputTypeColorSupport() {
1221
+ if (typeof inputTypeColorSupport._cachedResult === "undefined") {
1222
+ var colorInput = $("<input type='color' value='!' />")[0];
1223
+ inputTypeColorSupport._cachedResult = colorInput.type === "color" && colorInput.value !== "!";
1224
+ }
1225
+ return inputTypeColorSupport._cachedResult;
1226
+ };
1227
+
1228
+ $.spectrum = { };
1229
+ $.spectrum.localization = { };
1230
+ $.spectrum.palettes = { };
1231
+
1232
+ $.fn.spectrum.processNativeColorInputs = function () {
1233
+ var colorInputs = $("input[type=color]");
1234
+ if (colorInputs.length && !inputTypeColorSupport()) {
1235
+ colorInputs.spectrum({
1236
+ preferredFormat: "hex6"
1237
+ });
1238
+ }
1239
+ };
1240
+
1241
+ // TinyColor v1.1.2
1242
+ // https://github.com/bgrins/TinyColor
1243
+ // Brian Grinstead, MIT License
1244
+
1245
+ (function() {
1246
+
1247
+ var trimLeft = /^[\s,#]+/,
1248
+ trimRight = /\s+$/,
1249
+ tinyCounter = 0,
1250
+ math = Math,
1251
+ mathRound = math.round,
1252
+ mathMin = math.min,
1253
+ mathMax = math.max,
1254
+ mathRandom = math.random;
1255
+
1256
+ var tinycolor = function(color, opts) {
1257
+
1258
+ color = (color) ? color : '';
1259
+ opts = opts || { };
1260
+
1261
+ // If input is already a tinycolor, return itself
1262
+ if (color instanceof tinycolor) {
1263
+ return color;
1264
+ }
1265
+ // If we are called as a function, call using new instead
1266
+ if (!(this instanceof tinycolor)) {
1267
+ return new tinycolor(color, opts);
1268
+ }
1269
+
1270
+ var rgb = inputToRGB(color);
1271
+ this._originalInput = color,
1272
+ this._r = rgb.r,
1273
+ this._g = rgb.g,
1274
+ this._b = rgb.b,
1275
+ this._a = rgb.a,
1276
+ this._roundA = mathRound(100*this._a) / 100,
1277
+ this._format = opts.format || rgb.format;
1278
+ this._gradientType = opts.gradientType;
1279
+
1280
+ // Don't let the range of [0,255] come back in [0,1].
1281
+ // Potentially lose a little bit of precision here, but will fix issues where
1282
+ // .5 gets interpreted as half of the total, instead of half of 1
1283
+ // If it was supposed to be 128, this was already taken care of by `inputToRgb`
1284
+ if (this._r < 1) { this._r = mathRound(this._r); }
1285
+ if (this._g < 1) { this._g = mathRound(this._g); }
1286
+ if (this._b < 1) { this._b = mathRound(this._b); }
1287
+
1288
+ this._ok = rgb.ok;
1289
+ this._tc_id = tinyCounter++;
1290
+ };
1291
+
1292
+ tinycolor.prototype = {
1293
+ isDark: function() {
1294
+ return this.getBrightness() < 128;
1295
+ },
1296
+ isLight: function() {
1297
+ return !this.isDark();
1298
+ },
1299
+ isValid: function() {
1300
+ return this._ok;
1301
+ },
1302
+ getOriginalInput: function() {
1303
+ return this._originalInput;
1304
+ },
1305
+ getFormat: function() {
1306
+ return this._format;
1307
+ },
1308
+ getAlpha: function() {
1309
+ return this._a;
1310
+ },
1311
+ getBrightness: function() {
1312
+ var rgb = this.toRgb();
1313
+ return (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000;
1314
+ },
1315
+ setAlpha: function(value) {
1316
+ this._a = boundAlpha(value);
1317
+ this._roundA = mathRound(100*this._a) / 100;
1318
+ return this;
1319
+ },
1320
+ toHsv: function() {
1321
+ var hsv = rgbToHsv(this._r, this._g, this._b);
1322
+ return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: this._a };
1323
+ },
1324
+ toHsvString: function() {
1325
+ var hsv = rgbToHsv(this._r, this._g, this._b);
1326
+ var h = mathRound(hsv.h * 360), s = mathRound(hsv.s * 100), v = mathRound(hsv.v * 100);
1327
+ return (this._a == 1) ?
1328
+ "hsv(" + h + ", " + s + "%, " + v + "%)" :
1329
+ "hsva(" + h + ", " + s + "%, " + v + "%, "+ this._roundA + ")";
1330
+ },
1331
+ toHsl: function() {
1332
+ var hsl = rgbToHsl(this._r, this._g, this._b);
1333
+ return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: this._a };
1334
+ },
1335
+ toHslString: function() {
1336
+ var hsl = rgbToHsl(this._r, this._g, this._b);
1337
+ var h = mathRound(hsl.h * 360), s = mathRound(hsl.s * 100), l = mathRound(hsl.l * 100);
1338
+ return (this._a == 1) ?
1339
+ "hsl(" + h + ", " + s + "%, " + l + "%)" :
1340
+ "hsla(" + h + ", " + s + "%, " + l + "%, "+ this._roundA + ")";
1341
+ },
1342
+ toHex: function(allow3Char) {
1343
+ return rgbToHex(this._r, this._g, this._b, allow3Char);
1344
+ },
1345
+ toHexString: function(allow3Char) {
1346
+ return '#' + this.toHex(allow3Char);
1347
+ },
1348
+ toHex8: function() {
1349
+ return rgbaToHex(this._r, this._g, this._b, this._a);
1350
+ },
1351
+ toHex8String: function() {
1352
+ return '#' + this.toHex8();
1353
+ },
1354
+ toRgb: function() {
1355
+ return { r: mathRound(this._r), g: mathRound(this._g), b: mathRound(this._b), a: this._a };
1356
+ },
1357
+ toRgbString: function() {
1358
+ return (this._a == 1) ?
1359
+ "rgb(" + mathRound(this._r) + ", " + mathRound(this._g) + ", " + mathRound(this._b) + ")" :
1360
+ "rgba(" + mathRound(this._r) + ", " + mathRound(this._g) + ", " + mathRound(this._b) + ", " + this._roundA + ")";
1361
+ },
1362
+ toPercentageRgb: function() {
1363
+ return { r: mathRound(bound01(this._r, 255) * 100) + "%", g: mathRound(bound01(this._g, 255) * 100) + "%", b: mathRound(bound01(this._b, 255) * 100) + "%", a: this._a };
1364
+ },
1365
+ toPercentageRgbString: function() {
1366
+ return (this._a == 1) ?
1367
+ "rgb(" + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%)" :
1368
+ "rgba(" + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%, " + this._roundA + ")";
1369
+ },
1370
+ toName: function() {
1371
+ if (this._a === 0) {
1372
+ return "transparent";
1373
+ }
1374
+
1375
+ if (this._a < 1) {
1376
+ return false;
1377
+ }
1378
+
1379
+ return hexNames[rgbToHex(this._r, this._g, this._b, true)] || false;
1380
+ },
1381
+ toFilter: function(secondColor) {
1382
+ var hex8String = '#' + rgbaToHex(this._r, this._g, this._b, this._a);
1383
+ var secondHex8String = hex8String;
1384
+ var gradientType = this._gradientType ? "GradientType = 1, " : "";
1385
+
1386
+ if (secondColor) {
1387
+ var s = tinycolor(secondColor);
1388
+ secondHex8String = s.toHex8String();
1389
+ }
1390
+
1391
+ return "progid:DXImageTransform.Microsoft.gradient("+gradientType+"startColorstr="+hex8String+",endColorstr="+secondHex8String+")";
1392
+ },
1393
+ toString: function(format) {
1394
+ var formatSet = !!format;
1395
+ format = format || this._format;
1396
+
1397
+ var formattedString = false;
1398
+ var hasAlpha = this._a < 1 && this._a >= 0;
1399
+ var needsAlphaFormat = !formatSet && hasAlpha && (format === "hex" || format === "hex6" || format === "hex3" || format === "name");
1400
+
1401
+ if (needsAlphaFormat) {
1402
+ // Special case for "transparent", all other non-alpha formats
1403
+ // will return rgba when there is transparency.
1404
+ if (format === "name" && this._a === 0) {
1405
+ return this.toName();
1406
+ }
1407
+ return this.toRgbString();
1408
+ }
1409
+ if (format === "rgb") {
1410
+ formattedString = this.toRgbString();
1411
+ }
1412
+ if (format === "prgb") {
1413
+ formattedString = this.toPercentageRgbString();
1414
+ }
1415
+ if (format === "hex" || format === "hex6") {
1416
+ formattedString = this.toHexString();
1417
+ }
1418
+ if (format === "hex3") {
1419
+ formattedString = this.toHexString(true);
1420
+ }
1421
+ if (format === "hex8") {
1422
+ formattedString = this.toHex8String();
1423
+ }
1424
+ if (format === "name") {
1425
+ formattedString = this.toName();
1426
+ }
1427
+ if (format === "hsl") {
1428
+ formattedString = this.toHslString();
1429
+ }
1430
+ if (format === "hsv") {
1431
+ formattedString = this.toHsvString();
1432
+ }
1433
+
1434
+ return formattedString || this.toHexString();
1435
+ },
1436
+
1437
+ _applyModification: function(fn, args) {
1438
+ var color = fn.apply(null, [this].concat([].slice.call(args)));
1439
+ this._r = color._r;
1440
+ this._g = color._g;
1441
+ this._b = color._b;
1442
+ this.setAlpha(color._a);
1443
+ return this;
1444
+ },
1445
+ lighten: function() {
1446
+ return this._applyModification(lighten, arguments);
1447
+ },
1448
+ brighten: function() {
1449
+ return this._applyModification(brighten, arguments);
1450
+ },
1451
+ darken: function() {
1452
+ return this._applyModification(darken, arguments);
1453
+ },
1454
+ desaturate: function() {
1455
+ return this._applyModification(desaturate, arguments);
1456
+ },
1457
+ saturate: function() {
1458
+ return this._applyModification(saturate, arguments);
1459
+ },
1460
+ greyscale: function() {
1461
+ return this._applyModification(greyscale, arguments);
1462
+ },
1463
+ spin: function() {
1464
+ return this._applyModification(spin, arguments);
1465
+ },
1466
+
1467
+ _applyCombination: function(fn, args) {
1468
+ return fn.apply(null, [this].concat([].slice.call(args)));
1469
+ },
1470
+ analogous: function() {
1471
+ return this._applyCombination(analogous, arguments);
1472
+ },
1473
+ complement: function() {
1474
+ return this._applyCombination(complement, arguments);
1475
+ },
1476
+ monochromatic: function() {
1477
+ return this._applyCombination(monochromatic, arguments);
1478
+ },
1479
+ splitcomplement: function() {
1480
+ return this._applyCombination(splitcomplement, arguments);
1481
+ },
1482
+ triad: function() {
1483
+ return this._applyCombination(triad, arguments);
1484
+ },
1485
+ tetrad: function() {
1486
+ return this._applyCombination(tetrad, arguments);
1487
+ }
1488
+ };
1489
+
1490
+ // If input is an object, force 1 into "1.0" to handle ratios properly
1491
+ // String input requires "1.0" as input, so 1 will be treated as 1
1492
+ tinycolor.fromRatio = function(color, opts) {
1493
+ if (typeof color == "object") {
1494
+ var newColor = {};
1495
+ for (var i in color) {
1496
+ if (color.hasOwnProperty(i)) {
1497
+ if (i === "a") {
1498
+ newColor[i] = color[i];
1499
+ }
1500
+ else {
1501
+ newColor[i] = convertToPercentage(color[i]);
1502
+ }
1503
+ }
1504
+ }
1505
+ color = newColor;
1506
+ }
1507
+
1508
+ return tinycolor(color, opts);
1509
+ };
1510
+
1511
+ // Given a string or object, convert that input to RGB
1512
+ // Possible string inputs:
1513
+ //
1514
+ // "red"
1515
+ // "#f00" or "f00"
1516
+ // "#ff0000" or "ff0000"
1517
+ // "#ff000000" or "ff000000"
1518
+ // "rgb 255 0 0" or "rgb (255, 0, 0)"
1519
+ // "rgb 1.0 0 0" or "rgb (1, 0, 0)"
1520
+ // "rgba (255, 0, 0, 1)" or "rgba 255, 0, 0, 1"
1521
+ // "rgba (1.0, 0, 0, 1)" or "rgba 1.0, 0, 0, 1"
1522
+ // "hsl(0, 100%, 50%)" or "hsl 0 100% 50%"
1523
+ // "hsla(0, 100%, 50%, 1)" or "hsla 0 100% 50%, 1"
1524
+ // "hsv(0, 100%, 100%)" or "hsv 0 100% 100%"
1525
+ //
1526
+ function inputToRGB(color) {
1527
+
1528
+ var rgb = { r: 0, g: 0, b: 0 };
1529
+ var a = 1;
1530
+ var ok = false;
1531
+ var format = false;
1532
+
1533
+ if (typeof color == "string") {
1534
+ color = stringInputToObject(color);
1535
+ }
1536
+
1537
+ if (typeof color == "object") {
1538
+ if (color.hasOwnProperty("r") && color.hasOwnProperty("g") && color.hasOwnProperty("b")) {
1539
+ rgb = rgbToRgb(color.r, color.g, color.b);
1540
+ ok = true;
1541
+ format = String(color.r).substr(-1) === "%" ? "prgb" : "rgb";
1542
+ }
1543
+ else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("v")) {
1544
+ color.s = convertToPercentage(color.s);
1545
+ color.v = convertToPercentage(color.v);
1546
+ rgb = hsvToRgb(color.h, color.s, color.v);
1547
+ ok = true;
1548
+ format = "hsv";
1549
+ }
1550
+ else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("l")) {
1551
+ color.s = convertToPercentage(color.s);
1552
+ color.l = convertToPercentage(color.l);
1553
+ rgb = hslToRgb(color.h, color.s, color.l);
1554
+ ok = true;
1555
+ format = "hsl";
1556
+ }
1557
+
1558
+ if (color.hasOwnProperty("a")) {
1559
+ a = color.a;
1560
+ }
1561
+ }
1562
+
1563
+ a = boundAlpha(a);
1564
+
1565
+ return {
1566
+ ok: ok,
1567
+ format: color.format || format,
1568
+ r: mathMin(255, mathMax(rgb.r, 0)),
1569
+ g: mathMin(255, mathMax(rgb.g, 0)),
1570
+ b: mathMin(255, mathMax(rgb.b, 0)),
1571
+ a: a
1572
+ };
1573
+ }
1574
+
1575
+
1576
+ // Conversion Functions
1577
+ // --------------------
1578
+
1579
+ // `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from:
1580
+ // <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>
1581
+
1582
+ // `rgbToRgb`
1583
+ // Handle bounds / percentage checking to conform to CSS color spec
1584
+ // <http://www.w3.org/TR/css3-color/>
1585
+ // *Assumes:* r, g, b in [0, 255] or [0, 1]
1586
+ // *Returns:* { r, g, b } in [0, 255]
1587
+ function rgbToRgb(r, g, b){
1588
+ return {
1589
+ r: bound01(r, 255) * 255,
1590
+ g: bound01(g, 255) * 255,
1591
+ b: bound01(b, 255) * 255
1592
+ };
1593
+ }
1594
+
1595
+ // `rgbToHsl`
1596
+ // Converts an RGB color value to HSL.
1597
+ // *Assumes:* r, g, and b are contained in [0, 255] or [0, 1]
1598
+ // *Returns:* { h, s, l } in [0,1]
1599
+ function rgbToHsl(r, g, b) {
1600
+
1601
+ r = bound01(r, 255);
1602
+ g = bound01(g, 255);
1603
+ b = bound01(b, 255);
1604
+
1605
+ var max = mathMax(r, g, b), min = mathMin(r, g, b);
1606
+ var h, s, l = (max + min) / 2;
1607
+
1608
+ if(max == min) {
1609
+ h = s = 0; // achromatic
1610
+ }
1611
+ else {
1612
+ var d = max - min;
1613
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
1614
+ switch(max) {
1615
+ case r: h = (g - b) / d + (g < b ? 6 : 0); break;
1616
+ case g: h = (b - r) / d + 2; break;
1617
+ case b: h = (r - g) / d + 4; break;
1618
+ }
1619
+
1620
+ h /= 6;
1621
+ }
1622
+
1623
+ return { h: h, s: s, l: l };
1624
+ }
1625
+
1626
+ // `hslToRgb`
1627
+ // Converts an HSL color value to RGB.
1628
+ // *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100]
1629
+ // *Returns:* { r, g, b } in the set [0, 255]
1630
+ function hslToRgb(h, s, l) {
1631
+ var r, g, b;
1632
+
1633
+ h = bound01(h, 360);
1634
+ s = bound01(s, 100);
1635
+ l = bound01(l, 100);
1636
+
1637
+ function hue2rgb(p, q, t) {
1638
+ if(t < 0) t += 1;
1639
+ if(t > 1) t -= 1;
1640
+ if(t < 1/6) return p + (q - p) * 6 * t;
1641
+ if(t < 1/2) return q;
1642
+ if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
1643
+ return p;
1644
+ }
1645
+
1646
+ if(s === 0) {
1647
+ r = g = b = l; // achromatic
1648
+ }
1649
+ else {
1650
+ var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
1651
+ var p = 2 * l - q;
1652
+ r = hue2rgb(p, q, h + 1/3);
1653
+ g = hue2rgb(p, q, h);
1654
+ b = hue2rgb(p, q, h - 1/3);
1655
+ }
1656
+
1657
+ return { r: r * 255, g: g * 255, b: b * 255 };
1658
+ }
1659
+
1660
+ // `rgbToHsv`
1661
+ // Converts an RGB color value to HSV
1662
+ // *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]
1663
+ // *Returns:* { h, s, v } in [0,1]
1664
+ function rgbToHsv(r, g, b) {
1665
+
1666
+ r = bound01(r, 255);
1667
+ g = bound01(g, 255);
1668
+ b = bound01(b, 255);
1669
+
1670
+ var max = mathMax(r, g, b), min = mathMin(r, g, b);
1671
+ var h, s, v = max;
1672
+
1673
+ var d = max - min;
1674
+ s = max === 0 ? 0 : d / max;
1675
+
1676
+ if(max == min) {
1677
+ h = 0; // achromatic
1678
+ }
1679
+ else {
1680
+ switch(max) {
1681
+ case r: h = (g - b) / d + (g < b ? 6 : 0); break;
1682
+ case g: h = (b - r) / d + 2; break;
1683
+ case b: h = (r - g) / d + 4; break;
1684
+ }
1685
+ h /= 6;
1686
+ }
1687
+ return { h: h, s: s, v: v };
1688
+ }
1689
+
1690
+ // `hsvToRgb`
1691
+ // Converts an HSV color value to RGB.
1692
+ // *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]
1693
+ // *Returns:* { r, g, b } in the set [0, 255]
1694
+ function hsvToRgb(h, s, v) {
1695
+
1696
+ h = bound01(h, 360) * 6;
1697
+ s = bound01(s, 100);
1698
+ v = bound01(v, 100);
1699
+
1700
+ var i = math.floor(h),
1701
+ f = h - i,
1702
+ p = v * (1 - s),
1703
+ q = v * (1 - f * s),
1704
+ t = v * (1 - (1 - f) * s),
1705
+ mod = i % 6,
1706
+ r = [v, q, p, p, t, v][mod],
1707
+ g = [t, v, v, q, p, p][mod],
1708
+ b = [p, p, t, v, v, q][mod];
1709
+
1710
+ return { r: r * 255, g: g * 255, b: b * 255 };
1711
+ }
1712
+
1713
+ // `rgbToHex`
1714
+ // Converts an RGB color to hex
1715
+ // Assumes r, g, and b are contained in the set [0, 255]
1716
+ // Returns a 3 or 6 character hex
1717
+ function rgbToHex(r, g, b, allow3Char) {
1718
+
1719
+ var hex = [
1720
+ pad2(mathRound(r).toString(16)),
1721
+ pad2(mathRound(g).toString(16)),
1722
+ pad2(mathRound(b).toString(16))
1723
+ ];
1724
+
1725
+ // Return a 3 character hex if possible
1726
+ if (allow3Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1)) {
1727
+ return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);
1728
+ }
1729
+
1730
+ return hex.join("");
1731
+ }
1732
+ // `rgbaToHex`
1733
+ // Converts an RGBA color plus alpha transparency to hex
1734
+ // Assumes r, g, b and a are contained in the set [0, 255]
1735
+ // Returns an 8 character hex
1736
+ function rgbaToHex(r, g, b, a) {
1737
+
1738
+ var hex = [
1739
+ pad2(convertDecimalToHex(a)),
1740
+ pad2(mathRound(r).toString(16)),
1741
+ pad2(mathRound(g).toString(16)),
1742
+ pad2(mathRound(b).toString(16))
1743
+ ];
1744
+
1745
+ return hex.join("");
1746
+ }
1747
+
1748
+ // `equals`
1749
+ // Can be called with any tinycolor input
1750
+ tinycolor.equals = function (color1, color2) {
1751
+ if (!color1 || !color2) { return false; }
1752
+ return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString();
1753
+ };
1754
+ tinycolor.random = function() {
1755
+ return tinycolor.fromRatio({
1756
+ r: mathRandom(),
1757
+ g: mathRandom(),
1758
+ b: mathRandom()
1759
+ });
1760
+ };
1761
+
1762
+
1763
+ // Modification Functions
1764
+ // ----------------------
1765
+ // Thanks to less.js for some of the basics here
1766
+ // <https://github.com/cloudhead/less.js/blob/master/lib/less/functions.js>
1767
+
1768
+ function desaturate(color, amount) {
1769
+ amount = (amount === 0) ? 0 : (amount || 10);
1770
+ var hsl = tinycolor(color).toHsl();
1771
+ hsl.s -= amount / 100;
1772
+ hsl.s = clamp01(hsl.s);
1773
+ return tinycolor(hsl);
1774
+ }
1775
+
1776
+ function saturate(color, amount) {
1777
+ amount = (amount === 0) ? 0 : (amount || 10);
1778
+ var hsl = tinycolor(color).toHsl();
1779
+ hsl.s += amount / 100;
1780
+ hsl.s = clamp01(hsl.s);
1781
+ return tinycolor(hsl);
1782
+ }
1783
+
1784
+ function greyscale(color) {
1785
+ return tinycolor(color).desaturate(100);
1786
+ }
1787
+
1788
+ function lighten (color, amount) {
1789
+ amount = (amount === 0) ? 0 : (amount || 10);
1790
+ var hsl = tinycolor(color).toHsl();
1791
+ hsl.l += amount / 100;
1792
+ hsl.l = clamp01(hsl.l);
1793
+ return tinycolor(hsl);
1794
+ }
1795
+
1796
+ function brighten(color, amount) {
1797
+ amount = (amount === 0) ? 0 : (amount || 10);
1798
+ var rgb = tinycolor(color).toRgb();
1799
+ rgb.r = mathMax(0, mathMin(255, rgb.r - mathRound(255 * - (amount / 100))));
1800
+ rgb.g = mathMax(0, mathMin(255, rgb.g - mathRound(255 * - (amount / 100))));
1801
+ rgb.b = mathMax(0, mathMin(255, rgb.b - mathRound(255 * - (amount / 100))));
1802
+ return tinycolor(rgb);
1803
+ }
1804
+
1805
+ function darken (color, amount) {
1806
+ amount = (amount === 0) ? 0 : (amount || 10);
1807
+ var hsl = tinycolor(color).toHsl();
1808
+ hsl.l -= amount / 100;
1809
+ hsl.l = clamp01(hsl.l);
1810
+ return tinycolor(hsl);
1811
+ }
1812
+
1813
+ // Spin takes a positive or negative amount within [-360, 360] indicating the change of hue.
1814
+ // Values outside of this range will be wrapped into this range.
1815
+ function spin(color, amount) {
1816
+ var hsl = tinycolor(color).toHsl();
1817
+ var hue = (mathRound(hsl.h) + amount) % 360;
1818
+ hsl.h = hue < 0 ? 360 + hue : hue;
1819
+ return tinycolor(hsl);
1820
+ }
1821
+
1822
+ // Combination Functions
1823
+ // ---------------------
1824
+ // Thanks to jQuery xColor for some of the ideas behind these
1825
+ // <https://github.com/infusion/jQuery-xcolor/blob/master/jquery.xcolor.js>
1826
+
1827
+ function complement(color) {
1828
+ var hsl = tinycolor(color).toHsl();
1829
+ hsl.h = (hsl.h + 180) % 360;
1830
+ return tinycolor(hsl);
1831
+ }
1832
+
1833
+ function triad(color) {
1834
+ var hsl = tinycolor(color).toHsl();
1835
+ var h = hsl.h;
1836
+ return [
1837
+ tinycolor(color),
1838
+ tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }),
1839
+ tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l })
1840
+ ];
1841
+ }
1842
+
1843
+ function tetrad(color) {
1844
+ var hsl = tinycolor(color).toHsl();
1845
+ var h = hsl.h;
1846
+ return [
1847
+ tinycolor(color),
1848
+ tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }),
1849
+ tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }),
1850
+ tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l })
1851
+ ];
1852
+ }
1853
+
1854
+ function splitcomplement(color) {
1855
+ var hsl = tinycolor(color).toHsl();
1856
+ var h = hsl.h;
1857
+ return [
1858
+ tinycolor(color),
1859
+ tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l}),
1860
+ tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l})
1861
+ ];
1862
+ }
1863
+
1864
+ function analogous(color, results, slices) {
1865
+ results = results || 6;
1866
+ slices = slices || 30;
1867
+
1868
+ var hsl = tinycolor(color).toHsl();
1869
+ var part = 360 / slices;
1870
+ var ret = [tinycolor(color)];
1871
+
1872
+ for (hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360; --results; ) {
1873
+ hsl.h = (hsl.h + part) % 360;
1874
+ ret.push(tinycolor(hsl));
1875
+ }
1876
+ return ret;
1877
+ }
1878
+
1879
+ function monochromatic(color, results) {
1880
+ results = results || 6;
1881
+ var hsv = tinycolor(color).toHsv();
1882
+ var h = hsv.h, s = hsv.s, v = hsv.v;
1883
+ var ret = [];
1884
+ var modification = 1 / results;
1885
+
1886
+ while (results--) {
1887
+ ret.push(tinycolor({ h: h, s: s, v: v}));
1888
+ v = (v + modification) % 1;
1889
+ }
1890
+
1891
+ return ret;
1892
+ }
1893
+
1894
+ // Utility Functions
1895
+ // ---------------------
1896
+
1897
+ tinycolor.mix = function(color1, color2, amount) {
1898
+ amount = (amount === 0) ? 0 : (amount || 50);
1899
+
1900
+ var rgb1 = tinycolor(color1).toRgb();
1901
+ var rgb2 = tinycolor(color2).toRgb();
1902
+
1903
+ var p = amount / 100;
1904
+ var w = p * 2 - 1;
1905
+ var a = rgb2.a - rgb1.a;
1906
+
1907
+ var w1;
1908
+
1909
+ if (w * a == -1) {
1910
+ w1 = w;
1911
+ } else {
1912
+ w1 = (w + a) / (1 + w * a);
1913
+ }
1914
+
1915
+ w1 = (w1 + 1) / 2;
1916
+
1917
+ var w2 = 1 - w1;
1918
+
1919
+ var rgba = {
1920
+ r: rgb2.r * w1 + rgb1.r * w2,
1921
+ g: rgb2.g * w1 + rgb1.g * w2,
1922
+ b: rgb2.b * w1 + rgb1.b * w2,
1923
+ a: rgb2.a * p + rgb1.a * (1 - p)
1924
+ };
1925
+
1926
+ return tinycolor(rgba);
1927
+ };
1928
+
1929
+
1930
+ // Readability Functions
1931
+ // ---------------------
1932
+ // <http://www.w3.org/TR/AERT#color-contrast>
1933
+
1934
+ // `readability`
1935
+ // Analyze the 2 colors and returns an object with the following properties:
1936
+ // `brightness`: difference in brightness between the two colors
1937
+ // `color`: difference in color/hue between the two colors
1938
+ tinycolor.readability = function(color1, color2) {
1939
+ var c1 = tinycolor(color1);
1940
+ var c2 = tinycolor(color2);
1941
+ var rgb1 = c1.toRgb();
1942
+ var rgb2 = c2.toRgb();
1943
+ var brightnessA = c1.getBrightness();
1944
+ var brightnessB = c2.getBrightness();
1945
+ var colorDiff = (
1946
+ Math.max(rgb1.r, rgb2.r) - Math.min(rgb1.r, rgb2.r) +
1947
+ Math.max(rgb1.g, rgb2.g) - Math.min(rgb1.g, rgb2.g) +
1948
+ Math.max(rgb1.b, rgb2.b) - Math.min(rgb1.b, rgb2.b)
1949
+ );
1950
+
1951
+ return {
1952
+ brightness: Math.abs(brightnessA - brightnessB),
1953
+ color: colorDiff
1954
+ };
1955
+ };
1956
+
1957
+ // `readable`
1958
+ // http://www.w3.org/TR/AERT#color-contrast
1959
+ // Ensure that foreground and background color combinations provide sufficient contrast.
1960
+ // *Example*
1961
+ // tinycolor.isReadable("#000", "#111") => false
1962
+ tinycolor.isReadable = function(color1, color2) {
1963
+ var readability = tinycolor.readability(color1, color2);
1964
+ return readability.brightness > 125 && readability.color > 500;
1965
+ };
1966
+
1967
+ // `mostReadable`
1968
+ // Given a base color and a list of possible foreground or background
1969
+ // colors for that base, returns the most readable color.
1970
+ // *Example*
1971
+ // tinycolor.mostReadable("#123", ["#fff", "#000"]) => "#000"
1972
+ tinycolor.mostReadable = function(baseColor, colorList) {
1973
+ var bestColor = null;
1974
+ var bestScore = 0;
1975
+ var bestIsReadable = false;
1976
+ for (var i=0; i < colorList.length; i++) {
1977
+
1978
+ // We normalize both around the "acceptable" breaking point,
1979
+ // but rank brightness constrast higher than hue.
1980
+
1981
+ var readability = tinycolor.readability(baseColor, colorList[i]);
1982
+ var readable = readability.brightness > 125 && readability.color > 500;
1983
+ var score = 3 * (readability.brightness / 125) + (readability.color / 500);
1984
+
1985
+ if ((readable && ! bestIsReadable) ||
1986
+ (readable && bestIsReadable && score > bestScore) ||
1987
+ ((! readable) && (! bestIsReadable) && score > bestScore)) {
1988
+ bestIsReadable = readable;
1989
+ bestScore = score;
1990
+ bestColor = tinycolor(colorList[i]);
1991
+ }
1992
+ }
1993
+ return bestColor;
1994
+ };
1995
+
1996
+
1997
+ // Big List of Colors
1998
+ // ------------------
1999
+ // <http://www.w3.org/TR/css3-color/#svg-color>
2000
+ var names = tinycolor.names = {
2001
+ aliceblue: "f0f8ff",
2002
+ antiquewhite: "faebd7",
2003
+ aqua: "0ff",
2004
+ aquamarine: "7fffd4",
2005
+ azure: "f0ffff",
2006
+ beige: "f5f5dc",
2007
+ bisque: "ffe4c4",
2008
+ black: "000",
2009
+ blanchedalmond: "ffebcd",
2010
+ blue: "00f",
2011
+ blueviolet: "8a2be2",
2012
+ brown: "a52a2a",
2013
+ burlywood: "deb887",
2014
+ burntsienna: "ea7e5d",
2015
+ cadetblue: "5f9ea0",
2016
+ chartreuse: "7fff00",
2017
+ chocolate: "d2691e",
2018
+ coral: "ff7f50",
2019
+ cornflowerblue: "6495ed",
2020
+ cornsilk: "fff8dc",
2021
+ crimson: "dc143c",
2022
+ cyan: "0ff",
2023
+ darkblue: "00008b",
2024
+ darkcyan: "008b8b",
2025
+ darkgoldenrod: "b8860b",
2026
+ darkgray: "a9a9a9",
2027
+ darkgreen: "006400",
2028
+ darkgrey: "a9a9a9",
2029
+ darkkhaki: "bdb76b",
2030
+ darkmagenta: "8b008b",
2031
+ darkolivegreen: "556b2f",
2032
+ darkorange: "ff8c00",
2033
+ darkorchid: "9932cc",
2034
+ darkred: "8b0000",
2035
+ darksalmon: "e9967a",
2036
+ darkseagreen: "8fbc8f",
2037
+ darkslateblue: "483d8b",
2038
+ darkslategray: "2f4f4f",
2039
+ darkslategrey: "2f4f4f",
2040
+ darkturquoise: "00ced1",
2041
+ darkviolet: "9400d3",
2042
+ deeppink: "ff1493",
2043
+ deepskyblue: "00bfff",
2044
+ dimgray: "696969",
2045
+ dimgrey: "696969",
2046
+ dodgerblue: "1e90ff",
2047
+ firebrick: "b22222",
2048
+ floralwhite: "fffaf0",
2049
+ forestgreen: "228b22",
2050
+ fuchsia: "f0f",
2051
+ gainsboro: "dcdcdc",
2052
+ ghostwhite: "f8f8ff",
2053
+ gold: "ffd700",
2054
+ goldenrod: "daa520",
2055
+ gray: "808080",
2056
+ green: "008000",
2057
+ greenyellow: "adff2f",
2058
+ grey: "808080",
2059
+ honeydew: "f0fff0",
2060
+ hotpink: "ff69b4",
2061
+ indianred: "cd5c5c",
2062
+ indigo: "4b0082",
2063
+ ivory: "fffff0",
2064
+ khaki: "f0e68c",
2065
+ lavender: "e6e6fa",
2066
+ lavenderblush: "fff0f5",
2067
+ lawngreen: "7cfc00",
2068
+ lemonchiffon: "fffacd",
2069
+ lightblue: "add8e6",
2070
+ lightcoral: "f08080",
2071
+ lightcyan: "e0ffff",
2072
+ lightgoldenrodyellow: "fafad2",
2073
+ lightgray: "d3d3d3",
2074
+ lightgreen: "90ee90",
2075
+ lightgrey: "d3d3d3",
2076
+ lightpink: "ffb6c1",
2077
+ lightsalmon: "ffa07a",
2078
+ lightseagreen: "20b2aa",
2079
+ lightskyblue: "87cefa",
2080
+ lightslategray: "789",
2081
+ lightslategrey: "789",
2082
+ lightsteelblue: "b0c4de",
2083
+ lightyellow: "ffffe0",
2084
+ lime: "0f0",
2085
+ limegreen: "32cd32",
2086
+ linen: "faf0e6",
2087
+ magenta: "f0f",
2088
+ maroon: "800000",
2089
+ mediumaquamarine: "66cdaa",
2090
+ mediumblue: "0000cd",
2091
+ mediumorchid: "ba55d3",
2092
+ mediumpurple: "9370db",
2093
+ mediumseagreen: "3cb371",
2094
+ mediumslateblue: "7b68ee",
2095
+ mediumspringgreen: "00fa9a",
2096
+ mediumturquoise: "48d1cc",
2097
+ mediumvioletred: "c71585",
2098
+ midnightblue: "191970",
2099
+ mintcream: "f5fffa",
2100
+ mistyrose: "ffe4e1",
2101
+ moccasin: "ffe4b5",
2102
+ navajowhite: "ffdead",
2103
+ navy: "000080",
2104
+ oldlace: "fdf5e6",
2105
+ olive: "808000",
2106
+ olivedrab: "6b8e23",
2107
+ orange: "ffa500",
2108
+ orangered: "ff4500",
2109
+ orchid: "da70d6",
2110
+ palegoldenrod: "eee8aa",
2111
+ palegreen: "98fb98",
2112
+ paleturquoise: "afeeee",
2113
+ palevioletred: "db7093",
2114
+ papayawhip: "ffefd5",
2115
+ peachpuff: "ffdab9",
2116
+ peru: "cd853f",
2117
+ pink: "ffc0cb",
2118
+ plum: "dda0dd",
2119
+ powderblue: "b0e0e6",
2120
+ purple: "800080",
2121
+ rebeccapurple: "663399",
2122
+ red: "f00",
2123
+ rosybrown: "bc8f8f",
2124
+ royalblue: "4169e1",
2125
+ saddlebrown: "8b4513",
2126
+ salmon: "fa8072",
2127
+ sandybrown: "f4a460",
2128
+ seagreen: "2e8b57",
2129
+ seashell: "fff5ee",
2130
+ sienna: "a0522d",
2131
+ silver: "c0c0c0",
2132
+ skyblue: "87ceeb",
2133
+ slateblue: "6a5acd",
2134
+ slategray: "708090",
2135
+ slategrey: "708090",
2136
+ snow: "fffafa",
2137
+ springgreen: "00ff7f",
2138
+ steelblue: "4682b4",
2139
+ tan: "d2b48c",
2140
+ teal: "008080",
2141
+ thistle: "d8bfd8",
2142
+ tomato: "ff6347",
2143
+ turquoise: "40e0d0",
2144
+ violet: "ee82ee",
2145
+ wheat: "f5deb3",
2146
+ white: "fff",
2147
+ whitesmoke: "f5f5f5",
2148
+ yellow: "ff0",
2149
+ yellowgreen: "9acd32"
2150
+ };
2151
+
2152
+ // Make it easy to access colors via `hexNames[hex]`
2153
+ var hexNames = tinycolor.hexNames = flip(names);
2154
+
2155
+
2156
+ // Utilities
2157
+ // ---------
2158
+
2159
+ // `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }`
2160
+ function flip(o) {
2161
+ var flipped = { };
2162
+ for (var i in o) {
2163
+ if (o.hasOwnProperty(i)) {
2164
+ flipped[o[i]] = i;
2165
+ }
2166
+ }
2167
+ return flipped;
2168
+ }
2169
+
2170
+ // Return a valid alpha value [0,1] with all invalid values being set to 1
2171
+ function boundAlpha(a) {
2172
+ a = parseFloat(a);
2173
+
2174
+ if (isNaN(a) || a < 0 || a > 1) {
2175
+ a = 1;
2176
+ }
2177
+
2178
+ return a;
2179
+ }
2180
+
2181
+ // Take input from [0, n] and return it as [0, 1]
2182
+ function bound01(n, max) {
2183
+ if (isOnePointZero(n)) { n = "100%"; }
2184
+
2185
+ var processPercent = isPercentage(n);
2186
+ n = mathMin(max, mathMax(0, parseFloat(n)));
2187
+
2188
+ // Automatically convert percentage into number
2189
+ if (processPercent) {
2190
+ n = parseInt(n * max, 10) / 100;
2191
+ }
2192
+
2193
+ // Handle floating point rounding errors
2194
+ if ((math.abs(n - max) < 0.000001)) {
2195
+ return 1;
2196
+ }
2197
+
2198
+ // Convert into [0, 1] range if it isn't already
2199
+ return (n % max) / parseFloat(max);
2200
+ }
2201
+
2202
+ // Force a number between 0 and 1
2203
+ function clamp01(val) {
2204
+ return mathMin(1, mathMax(0, val));
2205
+ }
2206
+
2207
+ // Parse a base-16 hex value into a base-10 integer
2208
+ function parseIntFromHex(val) {
2209
+ return parseInt(val, 16);
2210
+ }
2211
+
2212
+ // Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1
2213
+ // <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0>
2214
+ function isOnePointZero(n) {
2215
+ return typeof n == "string" && n.indexOf('.') != -1 && parseFloat(n) === 1;
2216
+ }
2217
+
2218
+ // Check to see if string passed in is a percentage
2219
+ function isPercentage(n) {
2220
+ return typeof n === "string" && n.indexOf('%') != -1;
2221
+ }
2222
+
2223
+ // Force a hex value to have 2 characters
2224
+ function pad2(c) {
2225
+ return c.length == 1 ? '0' + c : '' + c;
2226
+ }
2227
+
2228
+ // Replace a decimal with it's percentage value
2229
+ function convertToPercentage(n) {
2230
+ if (n <= 1) {
2231
+ n = (n * 100) + "%";
2232
+ }
2233
+
2234
+ return n;
2235
+ }
2236
+
2237
+ // Converts a decimal to a hex value
2238
+ function convertDecimalToHex(d) {
2239
+ return Math.round(parseFloat(d) * 255).toString(16);
2240
+ }
2241
+ // Converts a hex value to a decimal
2242
+ function convertHexToDecimal(h) {
2243
+ return (parseIntFromHex(h) / 255);
2244
+ }
2245
+
2246
+ var matchers = (function() {
2247
+
2248
+ // <http://www.w3.org/TR/css3-values/#integers>
2249
+ var CSS_INTEGER = "[-\\+]?\\d+%?";
2250
+
2251
+ // <http://www.w3.org/TR/css3-values/#number-value>
2252
+ var CSS_NUMBER = "[-\\+]?\\d*\\.\\d+%?";
2253
+
2254
+ // Allow positive/negative integer/number. Don't capture the either/or, just the entire outcome.
2255
+ var CSS_UNIT = "(?:" + CSS_NUMBER + ")|(?:" + CSS_INTEGER + ")";
2256
+
2257
+ // Actual matching.
2258
+ // Parentheses and commas are optional, but not required.
2259
+ // Whitespace can take the place of commas or opening paren
2260
+ var PERMISSIVE_MATCH3 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";
2261
+ var PERMISSIVE_MATCH4 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";
2262
+
2263
+ return {
2264
+ rgb: new RegExp("rgb" + PERMISSIVE_MATCH3),
2265
+ rgba: new RegExp("rgba" + PERMISSIVE_MATCH4),
2266
+ hsl: new RegExp("hsl" + PERMISSIVE_MATCH3),
2267
+ hsla: new RegExp("hsla" + PERMISSIVE_MATCH4),
2268
+ hsv: new RegExp("hsv" + PERMISSIVE_MATCH3),
2269
+ hsva: new RegExp("hsva" + PERMISSIVE_MATCH4),
2270
+ hex3: /^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
2271
+ hex6: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,
2272
+ hex8: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/
2273
+ };
2274
+ })();
2275
+
2276
+ // `stringInputToObject`
2277
+ // Permissive string parsing. Take in a number of formats, and output an object
2278
+ // based on detected format. Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}`
2279
+ function stringInputToObject(color) {
2280
+
2281
+ color = color.replace(trimLeft,'').replace(trimRight, '').toLowerCase();
2282
+ var named = false;
2283
+ if (names[color]) {
2284
+ color = names[color];
2285
+ named = true;
2286
+ }
2287
+ else if (color == 'transparent') {
2288
+ return { r: 0, g: 0, b: 0, a: 0, format: "name" };
2289
+ }
2290
+
2291
+ // Try to match string input using regular expressions.
2292
+ // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360]
2293
+ // Just return an object and let the conversion functions handle that.
2294
+ // This way the result will be the same whether the tinycolor is initialized with string or object.
2295
+ var match;
2296
+ if ((match = matchers.rgb.exec(color))) {
2297
+ return { r: match[1], g: match[2], b: match[3] };
2298
+ }
2299
+ if ((match = matchers.rgba.exec(color))) {
2300
+ return { r: match[1], g: match[2], b: match[3], a: match[4] };
2301
+ }
2302
+ if ((match = matchers.hsl.exec(color))) {
2303
+ return { h: match[1], s: match[2], l: match[3] };
2304
+ }
2305
+ if ((match = matchers.hsla.exec(color))) {
2306
+ return { h: match[1], s: match[2], l: match[3], a: match[4] };
2307
+ }
2308
+ if ((match = matchers.hsv.exec(color))) {
2309
+ return { h: match[1], s: match[2], v: match[3] };
2310
+ }
2311
+ if ((match = matchers.hsva.exec(color))) {
2312
+ return { h: match[1], s: match[2], v: match[3], a: match[4] };
2313
+ }
2314
+ if ((match = matchers.hex8.exec(color))) {
2315
+ return {
2316
+ a: convertHexToDecimal(match[1]),
2317
+ r: parseIntFromHex(match[2]),
2318
+ g: parseIntFromHex(match[3]),
2319
+ b: parseIntFromHex(match[4]),
2320
+ format: named ? "name" : "hex8"
2321
+ };
2322
+ }
2323
+ if ((match = matchers.hex6.exec(color))) {
2324
+ return {
2325
+ r: parseIntFromHex(match[1]),
2326
+ g: parseIntFromHex(match[2]),
2327
+ b: parseIntFromHex(match[3]),
2328
+ format: named ? "name" : "hex"
2329
+ };
2330
+ }
2331
+ if ((match = matchers.hex3.exec(color))) {
2332
+ return {
2333
+ r: parseIntFromHex(match[1] + '' + match[1]),
2334
+ g: parseIntFromHex(match[2] + '' + match[2]),
2335
+ b: parseIntFromHex(match[3] + '' + match[3]),
2336
+ format: named ? "name" : "hex"
2337
+ };
2338
+ }
2339
+
2340
+ return false;
2341
+ }
2342
+
2343
+ window.tinycolor = tinycolor;
2344
+ })();
2345
+
2346
+ $(function () {
2347
+ if ($.fn.spectrum.load) {
2348
+ $.fn.spectrum.processNativeColorInputs();
2349
+ }
2350
+ });
2351
+
2352
+ });
js/spectrum.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(t){"use strict";"function"==typeof define&&define.amd?define(["jquery"],t):"object"==typeof exports&&"object"==typeof module?module.exports=t:t(jQuery)}(function(t,e){"use strict";function r(e,r,n,a){for(var i=[],s=0;s<e.length;s++){var o=e[s];if(o){var l=tinycolor(o),c=l.toHsl().l<.5?"sp-thumb-el sp-thumb-dark":"sp-thumb-el sp-thumb-light";c+=tinycolor.equals(r,o)?" sp-thumb-active":"";var f=l.toString(a.preferredFormat||"rgb"),u=b?"background-color:"+l.toRgbString():"filter:"+l.toFilter();i.push('<span title="'+f+'" data-color="'+l.toRgbString()+'" class="'+c+'"><span class="sp-thumb-inner" style="'+u+';" /></span>')}else{var h="sp-clear-display";i.push(t("<div />").append(t('<span data-color="" style="background-color:transparent;" class="'+h+'"></span>').attr("title",a.noColorSelectedText)).html())}}return"<div class='sp-cf "+n+"'>"+i.join("")+"</div>"}function n(){for(var t=0;t<p.length;t++)p[t]&&p[t].hide()}function a(e,r){var n=t.extend({},d,e);return n.callbacks={move:c(n.move,r),change:c(n.change,r),show:c(n.show,r),hide:c(n.hide,r),beforeShow:c(n.beforeShow,r)},n}function i(i,o){function c(){if(W.showPaletteOnly&&(W.showPalette=!0),Dt.text(W.showPaletteOnly?W.togglePaletteMoreText:W.togglePaletteLessText),W.palette){dt=W.palette.slice(0),pt=t.isArray(dt[0])?dt:[dt],gt={};for(var e=0;e<pt.length;e++)for(var r=0;r<pt[e].length;r++){var n=tinycolor(pt[e][r]).toRgbString();gt[n]=!0}}kt.toggleClass("sp-flat",X),kt.toggleClass("sp-input-disabled",!W.showInput),kt.toggleClass("sp-alpha-enabled",W.showAlpha),kt.toggleClass("sp-clear-enabled",Jt),kt.toggleClass("sp-buttons-disabled",!W.showButtons),kt.toggleClass("sp-palette-buttons-disabled",!W.togglePaletteOnly),kt.toggleClass("sp-palette-disabled",!W.showPalette),kt.toggleClass("sp-palette-only",W.showPaletteOnly),kt.toggleClass("sp-initial-disabled",!W.showInitial),kt.addClass(W.className).addClass(W.containerClassName),z()}function d(){function e(e){return e.data&&e.data.ignore?(O(t(e.target).closest(".sp-thumb-el").data("color")),j()):(O(t(e.target).closest(".sp-thumb-el").data("color")),j(),I(!0),W.hideAfterPaletteSelect&&F()),!1}if(g&&kt.find("*:not(input)").attr("unselectable","on"),c(),Bt&&_t.after(Lt),Jt||jt.hide(),X)_t.after(kt).hide();else{var r="parent"===W.appendTo?_t.parent():t(W.appendTo);1!==r.length&&(r=t("body")),r.append(kt)}y(),Kt.on("click.spectrum touchstart.spectrum",function(e){xt||A(),e.stopPropagation(),t(e.target).is("input")||e.preventDefault()}),(_t.is(":disabled")||W.disabled===!0)&&V(),kt.click(l),Tt.change(P),Tt.bind("paste",function(){setTimeout(P,1)}),Tt.keydown(function(t){13==t.keyCode&&P()}),Et.text(W.cancelText),Et.bind("click.spectrum",function(t){t.stopPropagation(),t.preventDefault(),T(),F()}),jt.attr("title",W.clearText),jt.bind("click.spectrum",function(t){t.stopPropagation(),t.preventDefault(),Qt=!0,j(),X&&I(!0)}),qt.text(W.chooseText),qt.bind("click.spectrum",function(t){t.stopPropagation(),t.preventDefault(),g&&Tt.is(":focus")&&Tt.trigger("change"),E()&&(I(!0),F())}),Dt.text(W.showPaletteOnly?W.togglePaletteMoreText:W.togglePaletteLessText),Dt.bind("click.spectrum",function(t){t.stopPropagation(),t.preventDefault(),W.showPaletteOnly=!W.showPaletteOnly,W.showPaletteOnly||X||kt.css("left","-="+(St.outerWidth(!0)+5)),c()}),f(Ht,function(t,e,r){ht=t/st,Qt=!1,r.shiftKey&&(ht=Math.round(10*ht)/10),j()},S,C),f(At,function(t,e){ct=parseFloat(e/at),Qt=!1,W.showAlpha||(ht=1),j()},S,C),f(Ct,function(t,e,r){if(r.shiftKey){if(!yt){var n=ft*et,a=rt-ut*rt,i=Math.abs(t-n)>Math.abs(e-a);yt=i?"x":"y"}}else yt=null;var s=!yt||"x"===yt,o=!yt||"y"===yt;s&&(ft=parseFloat(t/et)),o&&(ut=parseFloat((rt-e)/rt)),Qt=!1,W.showAlpha||(ht=1),j()},S,C),$t?(O($t),q(),w($t)):q(),X&&M();var n=g?"mousedown.spectrum":"click.spectrum touchstart.spectrum";Ot.delegate(".sp-thumb-el",n,e),Nt.delegate(".sp-thumb-el:nth-child(1)",n,{ignore:!0},e)}function y(){if(G&&window.localStorage){try{var e=window.localStorage[G].split(",#");e.length>1&&(delete window.localStorage[G],t.each(e,function(t,e){w(e)}))}catch(r){}try{bt=window.localStorage[G].split(";")}catch(r){}}}function w(e){if(Y){var r=tinycolor(e).toRgbString();if(!gt[r]&&-1===t.inArray(r,bt))for(bt.push(r);bt.length>vt;)bt.shift();if(G&&window.localStorage)try{window.localStorage[G]=bt.join(";")}catch(n){}}}function _(){var t=[];if(W.showPalette)for(var e=0;e<bt.length;e++){var r=tinycolor(bt[e]).toRgbString();gt[r]||t.push(bt[e])}return t.reverse().slice(0,W.maxSelectionSize)}function x(){var e=N(),n=t.map(pt,function(t,n){return r(t,e,"sp-palette-row sp-palette-row-"+n,W)});y(),bt&&n.push(r(_(),e,"sp-palette-row sp-palette-row-selection",W)),Ot.html(n.join(""))}function k(){if(W.showInitial){var t=Wt,e=N();Nt.html(r([t,e],e,"sp-palette-row-initial",W))}}function S(){(0>=rt||0>=et||0>=at)&&z(),tt=!0,kt.addClass(mt),yt=null,_t.trigger("dragstart.spectrum",[N()])}function C(){tt=!1,kt.removeClass(mt),_t.trigger("dragstop.spectrum",[N()])}function P(t){var e=Tt.val();if(null!==e&&""!==e||!Jt){var r=tinycolor(e);r.isValid()?(Xt=Yt=r.getFormat(),O(r),I(!0)):Tt.addClass("sp-validation-error")}else O(null),I(!0)}function A(){Z?F():M()}function M(){var e=t.Event("beforeShow.spectrum");return Z?void z():(_t.trigger(e,[N()]),void(J.beforeShow(N())===!1||e.isDefaultPrevented()||(n(),Z=!0,t(wt).bind("keydown.spectrum",R),t(wt).bind("click.spectrum",H),t(window).bind("resize.spectrum",U),Lt.addClass("sp-active"),kt.removeClass("sp-hidden"),z(),q(),Wt=N(),k(),J.show(Wt),_t.trigger("show.spectrum",[Wt]))))}function R(t){27===t.keyCode&&F()}function H(t){2!=t.button&&(tt||(Gt?I(!0):T(),F()))}function F(){Z&&!X&&(Z=!1,t(wt).unbind("keydown.spectrum",R),t(wt).unbind("click.spectrum",H),t(window).unbind("resize.spectrum",U),Lt.removeClass("sp-active"),kt.addClass("sp-hidden"),J.hide(N()),_t.trigger("hide.spectrum",[N()]))}function T(){O(Wt,!0)}function O(t,e){if(tinycolor.equals(t,N()))return void q();var r,n,a;!t&&Jt?Qt=!0:(Qt=!1,r=tinycolor(t),n=r.toHsv(),ct=n.h%360/360,ft=n.s,ut=n.v,ht=n.a),q(),r&&r.isValid()&&!e&&(a=r.getFormat(),"name"===a&&(Xt=a),Yt=Xt||a)}function N(t){return t=t||{},Jt&&Qt?null:tinycolor.fromRatio({h:ct,s:ft,v:ut,a:Math.round(100*ht)/100},{format:t.format||Yt})}function E(){return!Tt.hasClass("sp-validation-error")}function j(){q(),J.move(N()),_t.trigger("move.spectrum",[N()])}function q(){Tt.removeClass("sp-validation-error"),D();var t=tinycolor.fromRatio({h:ct,s:1,v:1});Ct.css("background-color",t.toHexString());var e=Yt;1>ht&&(0!==ht||"name"!==e)&&("hex"===e||"hex3"===e||"hex6"===e||"name"===e)&&(e="rgb");var r=N({format:e}),n="";if(Vt.removeClass("sp-clear-display"),Vt.css("background-color","transparent"),!r&&Jt)Vt.addClass("sp-clear-display");else{var a=r.toHexString(),i=r.toRgbString();if(b||1===r.alpha?Vt.css("background-color",i):(Vt.css("background-color","transparent"),Vt.css("filter",r.toFilter())),W.showAlpha){var s=r.toRgb();s.a=0;var o=tinycolor(s).toRgbString(),l="linear-gradient(left, "+o+", "+a+")";g?Rt.css("filter",tinycolor(o).toFilter({gradientType:1},a)):(Rt.css("background","-webkit-"+l),Rt.css("background","-moz-"+l),Rt.css("background","-ms-"+l),Rt.css("background","linear-gradient(to right, "+o+", "+a+")"))}n=r.toString(e)}W.showInput&&Tt.val(n),W.showPalette&&x(),k()}function D(){var t=ft,e=ut;if(Jt&&Qt)Ft.hide(),Mt.hide(),Pt.hide();else{Ft.show(),Mt.show(),Pt.show();var r=t*et,n=rt-e*rt;r=Math.max(-nt,Math.min(et-nt,r-nt)),n=Math.max(-nt,Math.min(rt-nt,n-nt)),Pt.css({top:n+"px",left:r+"px"});var a=ht*st;Ft.css({left:a-ot/2+"px"});var i=ct*at;Mt.css({top:i-lt+"px"})}}function I(t){var e=N(),r="",n=!tinycolor.equals(e,Wt),a=Yt;e&&(1>ht&&(0!==ht||"name"!==a)&&("hex"===a||"hex3"===a||"hex6"===a||"name"===a)&&(a="rgb"),r=e.toString(a),w(e)),It&&_t.val(r),t&&n&&(J.change(e),_t.trigger("change",[e]))}function z(){et=Ct.width(),rt=Ct.height(),nt=Pt.height(),it=At.width(),at=At.height(),lt=Mt.height(),st=Ht.width(),ot=Ft.width(),X||(kt.css("position","absolute"),kt.offset(W.offset?W.offset:s(kt,Kt))),D(),W.showPalette&&x(),_t.trigger("reflow.spectrum")}function B(){_t.show(),Kt.unbind("click.spectrum touchstart.spectrum"),kt.remove(),Lt.remove(),p[Ut.id]=null}function L(r,n){return r===e?t.extend({},W):n===e?W[r]:(W[r]=n,void c())}function K(){xt=!1,_t.attr("disabled",!1),Kt.removeClass("sp-disabled")}function V(){F(),xt=!0,_t.attr("disabled",!0),Kt.addClass("sp-disabled")}function $(t){W.offset=t,z()}var W=a(o,i),X=W.flat,Y=W.showSelectionPalette,G=W.localStorageKey,Q=W.theme,J=W.callbacks,U=u(z,10),Z=!1,tt=!1,et=0,rt=0,nt=0,at=0,it=0,st=0,ot=0,lt=0,ct=0,ft=0,ut=0,ht=1,dt=[],pt=[],gt={},bt=W.selectionPalette.slice(0),vt=W.maxSelectionSize,mt="sp-dragging",yt=null,wt=i.ownerDocument,_t=(wt.body,t(i)),xt=!1,kt=t(m,wt).addClass(Q),St=kt.find(".sp-picker-container"),Ct=kt.find(".sp-color"),Pt=kt.find(".sp-dragger"),At=kt.find(".sp-hue"),Mt=kt.find(".sp-slider"),Rt=kt.find(".sp-alpha-inner"),Ht=kt.find(".sp-alpha"),Ft=kt.find(".sp-alpha-handle"),Tt=kt.find(".sp-input"),Ot=kt.find(".sp-palette"),Nt=kt.find(".sp-initial"),Et=kt.find(".sp-cancel"),jt=kt.find(".sp-clear"),qt=kt.find(".sp-choose"),Dt=kt.find(".sp-palette-toggle"),It=_t.is("input"),zt=It&&"color"===_t.attr("type")&&h(),Bt=It&&!X,Lt=Bt?t(v).addClass(Q).addClass(W.className).addClass(W.replacerClassName):t([]),Kt=Bt?Lt:_t,Vt=Lt.find(".sp-preview-inner"),$t=W.color||It&&_t.val(),Wt=!1,Xt=W.preferredFormat,Yt=Xt,Gt=!W.showButtons||W.clickoutFiresChange,Qt=!$t,Jt=W.allowEmpty&&!zt;d();var Ut={show:M,hide:F,toggle:A,reflow:z,option:L,enable:K,disable:V,offset:$,set:function(t){O(t)},get:N,destroy:B,container:kt};return Ut.id=p.push(Ut)-1,Ut}function s(e,r){var n=0,a=e.outerWidth(),i=e.outerHeight(),s=r.outerHeight(),o=e[0].ownerDocument,l=o.documentElement,c=l.clientWidth+t(o).scrollLeft(),f=l.clientHeight+t(o).scrollTop(),u=r.offset();return u.top+=s,u.left-=Math.min(u.left,u.left+a>c&&c>a?Math.abs(u.left+a-c):0),u.top-=Math.min(u.top,u.top+i>f&&f>i?Math.abs(i+s-n):n),u}function o(){}function l(t){t.stopPropagation()}function c(t,e){var r=Array.prototype.slice,n=r.call(arguments,2);return function(){return t.apply(e,n.concat(r.call(arguments)))}}function f(e,r,n,a){function i(t){t.stopPropagation&&t.stopPropagation(),t.preventDefault&&t.preventDefault(),t.returnValue=!1}function s(t){if(f){if(g&&c.documentMode<9&&!t.button)return l();var n=t.originalEvent&&t.originalEvent.touches&&t.originalEvent.touches[0],a=n&&n.pageX||t.pageX,s=n&&n.pageY||t.pageY,o=Math.max(0,Math.min(a-u.left,d)),b=Math.max(0,Math.min(s-u.top,h));p&&i(t),r.apply(e,[o,b,t])}}function o(r){var a=r.which?3==r.which:2==r.button;a||f||n.apply(e,arguments)!==!1&&(f=!0,h=t(e).height(),d=t(e).width(),u=t(e).offset(),t(c).bind(b),t(c.body).addClass("sp-dragging"),s(r),i(r))}function l(){f&&(t(c).unbind(b),t(c.body).removeClass("sp-dragging"),setTimeout(function(){a.apply(e,arguments)},0)),f=!1}r=r||function(){},n=n||function(){},a=a||function(){};var c=document,f=!1,u={},h=0,d=0,p="ontouchstart"in window,b={};b.selectstart=i,b.dragstart=i,b["touchmove mousemove"]=s,b["touchend mouseup"]=l,t(e).bind("touchstart mousedown",o)}function u(t,e,r){var n;return function(){var a=this,i=arguments,s=function(){n=null,t.apply(a,i)};r&&clearTimeout(n),(r||!n)&&(n=setTimeout(s,e))}}function h(){return t.fn.spectrum.inputTypeColorSupport()}var d={beforeShow:o,move:o,change:o,show:o,hide:o,color:!1,flat:!1,showInput:!1,allowEmpty:!1,showButtons:!0,clickoutFiresChange:!0,showInitial:!1,showPalette:!1,showPaletteOnly:!1,hideAfterPaletteSelect:!1,togglePaletteOnly:!1,showSelectionPalette:!0,localStorageKey:!1,appendTo:"body",maxSelectionSize:7,cancelText:"cancel",chooseText:"choose",togglePaletteMoreText:"more",togglePaletteLessText:"less",clearText:"Clear Color Selection",noColorSelectedText:"No Color Selected",preferredFormat:!1,className:"",containerClassName:"",replacerClassName:"",showAlpha:!1,theme:"sp-light",palette:[["#ffffff","#000000","#ff0000","#ff8000","#ffff00","#008000","#0000ff","#4b0082","#9400d3"]],selectionPalette:[],disabled:!1,offset:null},p=[],g=!!/msie/i.exec(window.navigator.userAgent),b=function(){function t(t,e){return!!~(""+t).indexOf(e)}var e=document.createElement("div"),r=e.style;return r.cssText="background-color:rgba(0,0,0,.5)",t(r.backgroundColor,"rgba")||t(r.backgroundColor,"hsla")}(),v=["<div class='sp-replacer'>","<div class='sp-preview'><div class='sp-preview-inner'></div></div>","<div class='sp-dd'>&#9660;</div>","</div>"].join(""),m=function(){var t="";if(g)for(var e=1;6>=e;e++)t+="<div class='sp-"+e+"'></div>";return["<div class='sp-container sp-hidden'>","<div class='sp-palette-container'>","<div class='sp-palette sp-thumb sp-cf'></div>","<div class='sp-palette-button-container sp-cf'>","<button type='button' class='sp-palette-toggle'></button>","</div>","</div>","<div class='sp-picker-container'>","<div class='sp-top sp-cf'>","<div class='sp-fill'></div>","<div class='sp-top-inner'>","<div class='sp-color'>","<div class='sp-sat'>","<div class='sp-val'>","<div class='sp-dragger'></div>","</div>","</div>","</div>","<div class='sp-clear sp-clear-display'>","</div>","<div class='sp-hue'>","<div class='sp-slider'></div>",t,"</div>","</div>","<div class='sp-alpha'><div class='sp-alpha-inner'><div class='sp-alpha-handle'></div></div></div>","</div>","<div class='sp-input-container sp-cf'>","<input class='sp-input' type='text' spellcheck='false' />","</div>","<div class='sp-initial sp-thumb sp-cf'></div>","<div class='sp-button-container sp-cf'>","<a class='sp-cancel' href='#'></a>","<button type='button' class='sp-choose'></button>","</div>","</div>","</div>"].join("")}(),y="spectrum.id";t.fn.spectrum=function(e,r){if("string"==typeof e){var n=this,a=Array.prototype.slice.call(arguments,1);return this.each(function(){var r=p[t(this).data(y)];if(r){var i=r[e];if(!i)throw new Error("Spectrum: no such method: '"+e+"'");"get"==e?n=r.get():"container"==e?n=r.container:"option"==e?n=r.option.apply(r,a):"destroy"==e?(r.destroy(),t(this).removeData(y)):i.apply(r,a)}}),n}return this.spectrum("destroy").each(function(){var r=t.extend({},e,t(this).data()),n=i(this,r);t(this).data(y,n.id)})},t.fn.spectrum.load=!0,t.fn.spectrum.loadOpts={},t.fn.spectrum.draggable=f,t.fn.spectrum.defaults=d,t.fn.spectrum.inputTypeColorSupport=function w(){if("undefined"==typeof w._cachedResult){var e=t("<input type='color' value='!' />")[0];w._cachedResult="color"===e.type&&"!"!==e.value}return w._cachedResult},t.spectrum={},t.spectrum.localization={},t.spectrum.palettes={},t.fn.spectrum.processNativeColorInputs=function(){var e=t("input[type=color]");e.length&&!h()&&e.spectrum({preferredFormat:"hex6"})},function(){function t(t){var r={r:0,g:0,b:0},a=1,s=!1,o=!1;return"string"==typeof t&&(t=T(t)),"object"==typeof t&&(t.hasOwnProperty("r")&&t.hasOwnProperty("g")&&t.hasOwnProperty("b")?(r=e(t.r,t.g,t.b),s=!0,o="%"===String(t.r).substr(-1)?"prgb":"rgb"):t.hasOwnProperty("h")&&t.hasOwnProperty("s")&&t.hasOwnProperty("v")?(t.s=R(t.s),t.v=R(t.v),r=i(t.h,t.s,t.v),s=!0,o="hsv"):t.hasOwnProperty("h")&&t.hasOwnProperty("s")&&t.hasOwnProperty("l")&&(t.s=R(t.s),t.l=R(t.l),r=n(t.h,t.s,t.l),s=!0,o="hsl"),t.hasOwnProperty("a")&&(a=t.a)),a=x(a),{ok:s,format:t.format||o,r:D(255,I(r.r,0)),g:D(255,I(r.g,0)),b:D(255,I(r.b,0)),a:a}}function e(t,e,r){return{r:255*k(t,255),g:255*k(e,255),b:255*k(r,255)}}function r(t,e,r){t=k(t,255),e=k(e,255),r=k(r,255);var n,a,i=I(t,e,r),s=D(t,e,r),o=(i+s)/2;if(i==s)n=a=0;else{var l=i-s;switch(a=o>.5?l/(2-i-s):l/(i+s),i){case t:n=(e-r)/l+(r>e?6:0);break;case e:n=(r-t)/l+2;break;case r:n=(t-e)/l+4}n/=6}return{h:n,s:a,l:o}}function n(t,e,r){function n(t,e,r){return 0>r&&(r+=1),r>1&&(r-=1),1/6>r?t+6*(e-t)*r:.5>r?e:2/3>r?t+(e-t)*(2/3-r)*6:t}var a,i,s;if(t=k(t,360),e=k(e,100),r=k(r,100),0===e)a=i=s=r;else{var o=.5>r?r*(1+e):r+e-r*e,l=2*r-o;a=n(l,o,t+1/3),i=n(l,o,t),s=n(l,o,t-1/3)}return{r:255*a,g:255*i,b:255*s}}function a(t,e,r){t=k(t,255),e=k(e,255),r=k(r,255);var n,a,i=I(t,e,r),s=D(t,e,r),o=i,l=i-s;if(a=0===i?0:l/i,i==s)n=0;else{switch(i){case t:n=(e-r)/l+(r>e?6:0);break;case e:n=(r-t)/l+2;break;case r:n=(t-e)/l+4}n/=6}return{h:n,s:a,v:o}}function i(t,e,r){t=6*k(t,360),e=k(e,100),r=k(r,100);var n=j.floor(t),a=t-n,i=r*(1-e),s=r*(1-a*e),o=r*(1-(1-a)*e),l=n%6,c=[r,s,i,i,o,r][l],f=[o,r,r,s,i,i][l],u=[i,i,o,r,r,s][l];return{r:255*c,g:255*f,b:255*u}}function s(t,e,r,n){var a=[M(q(t).toString(16)),M(q(e).toString(16)),M(q(r).toString(16))];return n&&a[0].charAt(0)==a[0].charAt(1)&&a[1].charAt(0)==a[1].charAt(1)&&a[2].charAt(0)==a[2].charAt(1)?a[0].charAt(0)+a[1].charAt(0)+a[2].charAt(0):a.join("")}function o(t,e,r,n){var a=[M(H(n)),M(q(t).toString(16)),M(q(e).toString(16)),M(q(r).toString(16))];return a.join("")}function l(t,e){e=0===e?0:e||10;var r=B(t).toHsl();return r.s-=e/100,r.s=S(r.s),B(r)}function c(t,e){e=0===e?0:e||10;var r=B(t).toHsl();return r.s+=e/100,r.s=S(r.s),B(r)}function f(t){return B(t).desaturate(100)}function u(t,e){e=0===e?0:e||10;var r=B(t).toHsl();return r.l+=e/100,r.l=S(r.l),B(r)}function h(t,e){e=0===e?0:e||10;var r=B(t).toRgb();return r.r=I(0,D(255,r.r-q(255*-(e/100)))),r.g=I(0,D(255,r.g-q(255*-(e/100)))),r.b=I(0,D(255,r.b-q(255*-(e/100)))),B(r)}function d(t,e){e=0===e?0:e||10;var r=B(t).toHsl();return r.l-=e/100,r.l=S(r.l),B(r)}function p(t,e){var r=B(t).toHsl(),n=(q(r.h)+e)%360;return r.h=0>n?360+n:n,B(r)}function g(t){var e=B(t).toHsl();return e.h=(e.h+180)%360,B(e)}function b(t){var e=B(t).toHsl(),r=e.h;return[B(t),B({h:(r+120)%360,s:e.s,l:e.l}),B({h:(r+240)%360,s:e.s,l:e.l})]}function v(t){var e=B(t).toHsl(),r=e.h;return[B(t),B({h:(r+90)%360,s:e.s,l:e.l}),B({h:(r+180)%360,s:e.s,l:e.l}),B({h:(r+270)%360,s:e.s,l:e.l})]}function m(t){var e=B(t).toHsl(),r=e.h;return[B(t),B({h:(r+72)%360,s:e.s,l:e.l}),B({h:(r+216)%360,s:e.s,l:e.l})]}function y(t,e,r){e=e||6,r=r||30;var n=B(t).toHsl(),a=360/r,i=[B(t)];for(n.h=(n.h-(a*e>>1)+720)%360;--e;)n.h=(n.h+a)%360,i.push(B(n));return i}function w(t,e){e=e||6;for(var r=B(t).toHsv(),n=r.h,a=r.s,i=r.v,s=[],o=1/e;e--;)s.push(B({h:n,s:a,v:i})),i=(i+o)%1;return s}function _(t){var e={};for(var r in t)t.hasOwnProperty(r)&&(e[t[r]]=r);return e}function x(t){return t=parseFloat(t),(isNaN(t)||0>t||t>1)&&(t=1),t}function k(t,e){P(t)&&(t="100%");var r=A(t);return t=D(e,I(0,parseFloat(t))),r&&(t=parseInt(t*e,10)/100),j.abs(t-e)<1e-6?1:t%e/parseFloat(e)}function S(t){return D(1,I(0,t))}function C(t){return parseInt(t,16)}function P(t){return"string"==typeof t&&-1!=t.indexOf(".")&&1===parseFloat(t)}function A(t){return"string"==typeof t&&-1!=t.indexOf("%")}function M(t){return 1==t.length?"0"+t:""+t}function R(t){return 1>=t&&(t=100*t+"%"),t}function H(t){return Math.round(255*parseFloat(t)).toString(16)}function F(t){return C(t)/255}function T(t){t=t.replace(O,"").replace(N,"").toLowerCase();var e=!1;if(L[t])t=L[t],e=!0;else if("transparent"==t)return{r:0,g:0,b:0,a:0,format:"name"};var r;return(r=V.rgb.exec(t))?{r:r[1],g:r[2],b:r[3]}:(r=V.rgba.exec(t))?{r:r[1],g:r[2],b:r[3],a:r[4]}:(r=V.hsl.exec(t))?{h:r[1],s:r[2],l:r[3]}:(r=V.hsla.exec(t))?{h:r[1],s:r[2],l:r[3],a:r[4]}:(r=V.hsv.exec(t))?{h:r[1],s:r[2],v:r[3]}:(r=V.hsva.exec(t))?{h:r[1],s:r[2],v:r[3],a:r[4]}:(r=V.hex8.exec(t))?{a:F(r[1]),r:C(r[2]),g:C(r[3]),b:C(r[4]),format:e?"name":"hex8"}:(r=V.hex6.exec(t))?{r:C(r[1]),g:C(r[2]),b:C(r[3]),format:e?"name":"hex"}:(r=V.hex3.exec(t))?{r:C(r[1]+""+r[1]),g:C(r[2]+""+r[2]),b:C(r[3]+""+r[3]),format:e?"name":"hex"}:!1}var O=/^[\s,#]+/,N=/\s+$/,E=0,j=Math,q=j.round,D=j.min,I=j.max,z=j.random,B=function(e,r){if(e=e?e:"",r=r||{},e instanceof B)return e;if(!(this instanceof B))return new B(e,r);var n=t(e);this._originalInput=e,this._r=n.r,this._g=n.g,this._b=n.b,this._a=n.a,this._roundA=q(100*this._a)/100,this._format=r.format||n.format,this._gradientType=r.gradientType,this._r<1&&(this._r=q(this._r)),this._g<1&&(this._g=q(this._g)),this._b<1&&(this._b=q(this._b)),this._ok=n.ok,this._tc_id=E++};B.prototype={isDark:function(){return this.getBrightness()<128},isLight:function(){return!this.isDark()},isValid:function(){return this._ok},getOriginalInput:function(){return this._originalInput},getFormat:function(){return this._format},getAlpha:function(){return this._a},getBrightness:function(){var t=this.toRgb();return(299*t.r+587*t.g+114*t.b)/1e3},setAlpha:function(t){return this._a=x(t),this._roundA=q(100*this._a)/100,this},toHsv:function(){var t=a(this._r,this._g,this._b);return{h:360*t.h,s:t.s,v:t.v,a:this._a}},toHsvString:function(){var t=a(this._r,this._g,this._b),e=q(360*t.h),r=q(100*t.s),n=q(100*t.v);return 1==this._a?"hsv("+e+", "+r+"%, "+n+"%)":"hsva("+e+", "+r+"%, "+n+"%, "+this._roundA+")"},toHsl:function(){var t=r(this._r,this._g,this._b);return{h:360*t.h,s:t.s,l:t.l,a:this._a}},toHslString:function(){var t=r(this._r,this._g,this._b),e=q(360*t.h),n=q(100*t.s),a=q(100*t.l);return 1==this._a?"hsl("+e+", "+n+"%, "+a+"%)":"hsla("+e+", "+n+"%, "+a+"%, "+this._roundA+")"},toHex:function(t){return s(this._r,this._g,this._b,t)},toHexString:function(t){return"#"+this.toHex(t)},toHex8:function(){return o(this._r,this._g,this._b,this._a)},toHex8String:function(){return"#"+this.toHex8()},toRgb:function(){return{r:q(this._r),g:q(this._g),b:q(this._b),a:this._a}},toRgbString:function(){return 1==this._a?"rgb("+q(this._r)+", "+q(this._g)+", "+q(this._b)+")":"rgba("+q(this._r)+", "+q(this._g)+", "+q(this._b)+", "+this._roundA+")"},toPercentageRgb:function(){return{r:q(100*k(this._r,255))+"%",g:q(100*k(this._g,255))+"%",b:q(100*k(this._b,255))+"%",a:this._a}},toPercentageRgbString:function(){return 1==this._a?"rgb("+q(100*k(this._r,255))+"%, "+q(100*k(this._g,255))+"%, "+q(100*k(this._b,255))+"%)":"rgba("+q(100*k(this._r,255))+"%, "+q(100*k(this._g,255))+"%, "+q(100*k(this._b,255))+"%, "+this._roundA+")"},toName:function(){return 0===this._a?"transparent":this._a<1?!1:K[s(this._r,this._g,this._b,!0)]||!1},toFilter:function(t){var e="#"+o(this._r,this._g,this._b,this._a),r=e,n=this._gradientType?"GradientType = 1, ":"";if(t){var a=B(t);r=a.toHex8String()}return"progid:DXImageTransform.Microsoft.gradient("+n+"startColorstr="+e+",endColorstr="+r+")"},toString:function(t){var e=!!t;t=t||this._format;var r=!1,n=this._a<1&&this._a>=0,a=!e&&n&&("hex"===t||"hex6"===t||"hex3"===t||"name"===t);return a?"name"===t&&0===this._a?this.toName():this.toRgbString():("rgb"===t&&(r=this.toRgbString()),"prgb"===t&&(r=this.toPercentageRgbString()),("hex"===t||"hex6"===t)&&(r=this.toHexString()),"hex3"===t&&(r=this.toHexString(!0)),"hex8"===t&&(r=this.toHex8String()),"name"===t&&(r=this.toName()),"hsl"===t&&(r=this.toHslString()),"hsv"===t&&(r=this.toHsvString()),r||this.toHexString())},_applyModification:function(t,e){var r=t.apply(null,[this].concat([].slice.call(e)));return this._r=r._r,this._g=r._g,this._b=r._b,this.setAlpha(r._a),this},lighten:function(){return this._applyModification(u,arguments)},brighten:function(){return this._applyModification(h,arguments)},darken:function(){return this._applyModification(d,arguments)},desaturate:function(){return this._applyModification(l,arguments)},saturate:function(){return this._applyModification(c,arguments)},greyscale:function(){return this._applyModification(f,arguments)},spin:function(){return this._applyModification(p,arguments)},_applyCombination:function(t,e){return t.apply(null,[this].concat([].slice.call(e)))},analogous:function(){return this._applyCombination(y,arguments)},complement:function(){return this._applyCombination(g,arguments)},monochromatic:function(){return this._applyCombination(w,arguments)},splitcomplement:function(){return this._applyCombination(m,arguments)},triad:function(){return this._applyCombination(b,arguments)},tetrad:function(){return this._applyCombination(v,arguments)}},B.fromRatio=function(t,e){if("object"==typeof t){var r={};for(var n in t)t.hasOwnProperty(n)&&("a"===n?r[n]=t[n]:r[n]=R(t[n]));t=r}return B(t,e)},B.equals=function(t,e){return t&&e?B(t).toRgbString()==B(e).toRgbString():!1},B.random=function(){return B.fromRatio({r:z(),g:z(),b:z()})},B.mix=function(t,e,r){r=0===r?0:r||50;var n,a=B(t).toRgb(),i=B(e).toRgb(),s=r/100,o=2*s-1,l=i.a-a.a;n=o*l==-1?o:(o+l)/(1+o*l),n=(n+1)/2;var c=1-n,f={r:i.r*n+a.r*c,g:i.g*n+a.g*c,b:i.b*n+a.b*c,a:i.a*s+a.a*(1-s)};return B(f)},B.readability=function(t,e){var r=B(t),n=B(e),a=r.toRgb(),i=n.toRgb(),s=r.getBrightness(),o=n.getBrightness(),l=Math.max(a.r,i.r)-Math.min(a.r,i.r)+Math.max(a.g,i.g)-Math.min(a.g,i.g)+Math.max(a.b,i.b)-Math.min(a.b,i.b);return{brightness:Math.abs(s-o),color:l}},B.isReadable=function(t,e){var r=B.readability(t,e);return r.brightness>125&&r.color>500},B.mostReadable=function(t,e){for(var r=null,n=0,a=!1,i=0;i<e.length;i++){var s=B.readability(t,e[i]),o=s.brightness>125&&s.color>500,l=3*(s.brightness/125)+s.color/500;(o&&!a||o&&a&&l>n||!o&&!a&&l>n)&&(a=o,n=l,r=B(e[i]))}return r};var L=B.names={aliceblue:"f0f8ff",antiquewhite:"faebd7",aqua:"0ff",aquamarine:"7fffd4",azure:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"000",blanchedalmond:"ffebcd",blue:"00f",blueviolet:"8a2be2",brown:"a52a2a",burlywood:"deb887",burntsienna:"ea7e5d",cadetblue:"5f9ea0",chartreuse:"7fff00",chocolate:"d2691e",coral:"ff7f50",cornflowerblue:"6495ed",cornsilk:"fff8dc",crimson:"dc143c",cyan:"0ff",darkblue:"00008b",darkcyan:"008b8b",darkgoldenrod:"b8860b",darkgray:"a9a9a9",darkgreen:"006400",darkgrey:"a9a9a9",darkkhaki:"bdb76b",darkmagenta:"8b008b",darkolivegreen:"556b2f",darkorange:"ff8c00",darkorchid:"9932cc",darkred:"8b0000",darksalmon:"e9967a",darkseagreen:"8fbc8f",darkslateblue:"483d8b",darkslategray:"2f4f4f",darkslategrey:"2f4f4f",darkturquoise:"00ced1",darkviolet:"9400d3",deeppink:"ff1493",deepskyblue:"00bfff",dimgray:"696969",dimgrey:"696969",dodgerblue:"1e90ff",firebrick:"b22222",floralwhite:"fffaf0",forestgreen:"228b22",fuchsia:"f0f",gainsboro:"dcdcdc",ghostwhite:"f8f8ff",gold:"ffd700",goldenrod:"daa520",gray:"808080",green:"008000",greenyellow:"adff2f",grey:"808080",honeydew:"f0fff0",hotpink:"ff69b4",indianred:"cd5c5c",indigo:"4b0082",ivory:"fffff0",khaki:"f0e68c",lavender:"e6e6fa",lavenderblush:"fff0f5",lawngreen:"7cfc00",lemonchiffon:"fffacd",lightblue:"add8e6",lightcoral:"f08080",lightcyan:"e0ffff",lightgoldenrodyellow:"fafad2",lightgray:"d3d3d3",lightgreen:"90ee90",lightgrey:"d3d3d3",lightpink:"ffb6c1",lightsalmon:"ffa07a",lightseagreen:"20b2aa",lightskyblue:"87cefa",lightslategray:"789",lightslategrey:"789",lightsteelblue:"b0c4de",lightyellow:"ffffe0",lime:"0f0",limegreen:"32cd32",linen:"faf0e6",magenta:"f0f",maroon:"800000",mediumaquamarine:"66cdaa",mediumblue:"0000cd",mediumorchid:"ba55d3",mediumpurple:"9370db",mediumseagreen:"3cb371",mediumslateblue:"7b68ee",mediumspringgreen:"00fa9a",mediumturquoise:"48d1cc",mediumvioletred:"c71585",midnightblue:"191970",mintcream:"f5fffa",mistyrose:"ffe4e1",moccasin:"ffe4b5",navajowhite:"ffdead",navy:"000080",oldlace:"fdf5e6",olive:"808000",olivedrab:"6b8e23",orange:"ffa500",orangered:"ff4500",orchid:"da70d6",palegoldenrod:"eee8aa",palegreen:"98fb98",paleturquoise:"afeeee",palevioletred:"db7093",papayawhip:"ffefd5",peachpuff:"ffdab9",peru:"cd853f",pink:"ffc0cb",plum:"dda0dd",powderblue:"b0e0e6",purple:"800080",rebeccapurple:"663399",red:"f00",rosybrown:"bc8f8f",royalblue:"4169e1",saddlebrown:"8b4513",salmon:"fa8072",sandybrown:"f4a460",seagreen:"2e8b57",seashell:"fff5ee",sienna:"a0522d",silver:"c0c0c0",skyblue:"87ceeb",slateblue:"6a5acd",slategray:"708090",slategrey:"708090",snow:"fffafa",springgreen:"00ff7f",steelblue:"4682b4",tan:"d2b48c",teal:"008080",thistle:"d8bfd8",tomato:"ff6347",turquoise:"40e0d0",violet:"ee82ee",wheat:"f5deb3",white:"fff",whitesmoke:"f5f5f5",yellow:"ff0",yellowgreen:"9acd32"},K=B.hexNames=_(L),V=function(){var t="[-\\+]?\\d+%?",e="[-\\+]?\\d*\\.\\d+%?",r="(?:"+e+")|(?:"+t+")",n="[\\s|\\(]+("+r+")[,|\\s]+("+r+")[,|\\s]+("+r+")\\s*\\)?",a="[\\s|\\(]+("+r+")[,|\\s]+("+r+")[,|\\s]+("+r+")[,|\\s]+("+r+")\\s*\\)?";return{rgb:new RegExp("rgb"+n),rgba:new RegExp("rgba"+a),hsl:new RegExp("hsl"+n),hsla:new RegExp("hsla"+a),hsv:new RegExp("hsv"+n),hsva:new RegExp("hsva"+a),hex3:/^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex6:/^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,hex8:/^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/}}();window.tinycolor=B}(),t(function(){t.fn.spectrum.load&&t.fn.spectrum.processNativeColorInputs()})});
lang/chld_thm_cfg.pot CHANGED
@@ -2,9 +2,9 @@
2
  # This file is distributed under the same license as the Child Theme Configurator package.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: Child Theme Configurator 1.7.4\n"
6
  "Report-Msgid-Bugs-To: http://wordpress.org/tag/child-theme-configurator\n"
7
- "POT-Creation-Date: 2015-04-11 16:59:47+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
@@ -12,7 +12,7 @@ msgstr ""
12
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13
  "Language-Team: LANGUAGE <LL@li.org>\n"
14
 
15
- #. #-#-#-#-# child-theme-configurator.pot (Child Theme Configurator 1.7.4) #-#-#-#-#
16
  #. Plugin Name of the plugin/theme
17
  #: child-theme-configurator.php:78 child-theme-configurator.php:88
18
  #: includes/forms/main.php:23
@@ -80,142 +80,142 @@ msgstr ""
80
  msgid "before activating."
81
  msgstr ""
82
 
83
- #: includes/class-ctc.php:143
84
  msgid "URL/None"
85
  msgstr ""
86
 
87
- #: includes/class-ctc.php:144
88
  msgid "Origin"
89
  msgstr ""
90
 
91
- #: includes/class-ctc.php:145
92
  msgid "Color 1"
93
  msgstr ""
94
 
95
- #: includes/class-ctc.php:146
96
  msgid "Color 2"
97
  msgstr ""
98
 
99
- #: includes/class-ctc.php:147
100
  msgid "Width/None"
101
  msgstr ""
102
 
103
- #: includes/class-ctc.php:148
104
  msgid "Style"
105
  msgstr ""
106
 
107
- #: includes/class-ctc.php:149
108
  msgid "Color"
109
  msgstr ""
110
 
111
- #: includes/class-ctc.php:151
112
  msgid "Are you sure? This will replace your current settings."
113
  msgstr ""
114
 
115
- #: includes/class-ctc.php:152
116
  msgid "<span style=\"font-size:10px\">!</span>"
117
  msgstr ""
118
 
119
- #: includes/class-ctc.php:153 includes/forms/rule-value.php:32
120
  msgid "Selectors"
121
  msgstr ""
122
 
123
- #: includes/class-ctc.php:154
124
  msgid "Close"
125
  msgstr ""
126
 
127
- #: includes/class-ctc.php:155
128
- msgid "Edit"
129
  msgstr ""
130
 
131
- #: includes/class-ctc.php:156
132
  msgid "Cancel"
133
  msgstr ""
134
 
135
- #: includes/class-ctc.php:157
136
  msgid "Rename"
137
  msgstr ""
138
 
139
- #: includes/class-ctc.php:158
140
  msgid "The stylesheet cannot be displayed."
141
  msgstr ""
142
 
143
- #: includes/class-ctc.php:159
144
  msgid "(Child Only)"
145
  msgstr ""
146
 
147
- #: includes/class-ctc.php:160
148
  msgid "Please enter a valid Child Theme."
149
  msgstr ""
150
 
151
- #: includes/class-ctc.php:161
152
  msgid "Please enter a valid Child Theme name."
153
  msgstr ""
154
 
155
- #: includes/class-ctc.php:162
156
  msgid "<strong>%s</strong> exists. Please enter a different Child Theme"
157
  msgstr ""
158
 
159
- #: includes/class-ctc.php:163
160
  msgid "The page could not be loaded correctly."
161
  msgstr ""
162
 
163
- #: includes/class-ctc.php:165
164
  msgid ""
165
  "Conflicting or out-of-date jQuery libraries were loaded by another plugin:"
166
  msgstr ""
167
 
168
- #: includes/class-ctc.php:167
169
  msgid "Deactivating or replacing plugins may resolve this issue."
170
  msgstr ""
171
 
172
- #: includes/class-ctc.php:168
173
  msgid "%sWhy am I seeing this?%s"
174
  msgstr ""
175
 
176
- #: includes/class-ctc.php:391
177
  msgid "Zip file creation failed."
178
  msgstr ""
179
 
180
- #: includes/class-ctc.php:427
181
  msgid "The Functions file is required and cannot be deleted."
182
  msgstr ""
183
 
184
- #: includes/class-ctc.php:509
185
  msgid "You do not have permission to configure child themes."
186
  msgstr ""
187
 
188
- #: includes/class-ctc.php:556
189
  msgid "%s does not exist. Please select a valid Parent Theme."
190
  msgstr ""
191
 
192
- #: includes/class-ctc.php:560
193
  msgid "Please select a valid Parent Theme."
194
  msgstr ""
195
 
196
- #: includes/class-ctc.php:563
197
  msgid "Please enter a valid Child Theme directory."
198
  msgstr ""
199
 
200
- #: includes/class-ctc.php:571 includes/class-ctc.php:586
201
  msgid "Please enter a valid Child Theme template name."
202
  msgstr ""
203
 
204
- #: includes/class-ctc.php:576 includes/class-ctc.php:590
205
  msgid ""
206
  "<strong>%s</strong> exists. Please enter a different Child Theme template "
207
  "name."
208
  msgstr ""
209
 
210
- #: includes/class-ctc.php:603
211
  msgid "Your theme directories are not writable."
212
  msgstr ""
213
 
214
- #: includes/class-ctc.php:679
215
  msgid "Your stylesheet is not writable."
216
  msgstr ""
217
 
218
- #: includes/class-ctc.php:948
219
  msgid ""
220
  "A closing PHP tag was detected in Child theme functions file so \"Parent "
221
  "Stylesheet Handling\" option was not configured. Closing PHP at the end of "
@@ -224,47 +224,47 @@ msgid ""
224
  "click \"Generate/Rebuild Child Theme Files\" again."
225
  msgstr ""
226
 
227
- #: includes/class-ctc.php:1048
228
  msgid "Could not delete file."
229
  msgstr ""
230
 
231
- #: includes/class-ctc.php:1124
232
  msgid "Could not set write permissions."
233
  msgstr ""
234
 
235
- #: includes/class-ctc.php:1223
236
  msgid "There were errors while resetting permissions."
237
  msgstr ""
238
 
239
- #: includes/class-ctc.php:1265
240
  msgid "Could not upload file."
241
  msgstr ""
242
 
243
- #: includes/class-ctc.php:1348
244
  msgid ""
245
  "The child theme is in read-only mode and Child Theme Configurator cannot "
246
  "apply changes. Click to see options"
247
  msgstr ""
248
 
249
- #: includes/class-ctc.php:1351
250
  msgid ""
251
  "<li>Temporarily set write permissions by clicking the button below. When you "
252
  "are finished editing, revert to read-only by clicking \"Make read-only\" "
253
  "under the \"Files\" tab.</li>"
254
  msgstr ""
255
 
256
- #: includes/class-ctc.php:1354
257
  msgid "Make files writable"
258
  msgstr ""
259
 
260
- #: includes/class-ctc.php:1355
261
  msgid ""
262
  "<li><a target=\"_blank\" href=\"http://codex.wordpress.org/Editing_wp-"
263
  "config.php#WordPress_Upgrade_Constants\" title=\"Editin wp-config.php\">Add "
264
  "your FTP/SSH credentials to the WordPress config file</a>.</li>"
265
  msgstr ""
266
 
267
- #: includes/class-ctc.php:1357
268
  msgid ""
269
  "<li><a target=\"_blank\" href=\"http://technet.microsoft.com/en-us/library/"
270
  "cc771170\" title=\"Setting Application Pool Identity\">Assign WordPress to "
@@ -272,18 +272,18 @@ msgid ""
272
  "li>"
273
  msgstr ""
274
 
275
- #: includes/class-ctc.php:1358
276
  msgid ""
277
  "<li><a target=\"_blank\" href=\"http://codex.wordpress.org/"
278
  "Changing_File_Permissions\" title=\"Changing File Permissions\">Set write "
279
  "permissions on the server manually</a> (not recommended).</li>"
280
  msgstr ""
281
 
282
- #: includes/class-ctc.php:1360
283
  msgid "<li>Run PHP under Apache with suEXEC (contact your web host).</li>"
284
  msgstr ""
285
 
286
- #: includes/class-ctc.php:1371
287
  msgid ""
288
  "This Child Theme is not owned by your website account. It may have been "
289
  "created by a prior version of this plugin or by another program. Moving "
@@ -292,25 +292,25 @@ msgid ""
292
  "below."
293
  msgstr ""
294
 
295
- #: includes/class-ctc.php:1374
296
  msgid "Correct Child Theme Permissions"
297
  msgstr ""
298
 
299
- #: includes/class-ctc.php:1381
300
  msgid ""
301
  "Child Theme Configurator needs to update its interal data. Please set your "
302
  "preferences below and click \"Generate Child Theme Files\" to update your "
303
  "configuration."
304
  msgstr ""
305
 
306
- #: includes/class-ctc.php:1387
307
  msgid ""
308
  "<strong>However, some styles could not be parsed due to memory limits.</"
309
  "strong> Try deselecting \"Additional Stylesheets\" below and click "
310
  "\"Generate/Rebuild Child Theme Files\". %sWhy am I seeing this?%s"
311
  msgstr ""
312
 
313
- #: includes/class-ctc.php:1396
314
  msgid ""
315
  "Child Theme Configurator did not detect any configuration data because a "
316
  "previously configured Child Theme has been removed. Please set your "
@@ -321,7 +321,7 @@ msgstr ""
321
  msgid "Parse additional stylesheets:"
322
  msgstr ""
323
 
324
- #: includes/forms/addl_css.php:11 includes/forms/parent-child.php:256
325
  msgid ""
326
  "Stylesheets that are currently being loaded by the parent theme are "
327
  "automatically selected below (except for Bootstrap stylesheets which add a "
@@ -329,11 +329,31 @@ msgid ""
329
  "only the additional stylesheets you wish to customize."
330
  msgstr ""
331
 
332
- #: includes/forms/addl_panels.php:8 includes/forms/addl_panels.php:9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
333
  msgid "Learn more about IntelliWidget"
334
  msgstr ""
335
 
336
- #: includes/forms/addl_panels.php:9
337
  msgid ""
338
  "IntelliWidget is a versatile widget manager that does the work of multiple "
339
  "plugins by combining custom page menus, featured posts, sliders and other "
@@ -341,133 +361,121 @@ msgid ""
341
  "or site-wide basis."
342
  msgstr ""
343
 
344
- #: includes/forms/addl_panels.php:10 includes/forms/addl_panels.php:13
345
  msgid "Learn more"
346
  msgstr ""
347
 
348
- #: includes/forms/addl_panels.php:11 includes/forms/addl_panels.php:12
349
  msgid "Learn more about IW Responsive Menu"
350
  msgstr ""
351
 
352
- #: includes/forms/addl_panels.php:12
353
  msgid ""
354
  "IntelliWidget Responsive Menu lets you break free from your theme’s built-in "
355
  "responsive menu options and gives you complete control over the user "
356
  "experience."
357
  msgstr ""
358
 
359
- #: includes/forms/addl_panels.php:16 includes/help/help_en_US.php:212
360
  msgid "Learn more about CTC Pro"
361
  msgstr ""
362
 
363
- #: includes/forms/addl_panels.php:17
364
  msgid "Customizing WordPress just got even easier."
365
  msgstr ""
366
 
367
- #: includes/forms/addl_panels.php:18
368
  msgid ""
369
  "Thousands of users have already seen the benefits of using Child Theme "
370
  "Configurator. If you spend any amount of time customizing WordPress, CTC Pro "
371
  "will help maximize your productivity."
372
  msgstr ""
373
 
374
- #: includes/forms/addl_panels.php:19
375
  msgid "Designed by Developers Who Use It Every Day."
376
  msgstr ""
377
 
378
- #: includes/forms/addl_panels.php:20
379
  msgid ""
380
  "We've packed in more features to make design work quicker and easier with "
381
  "<strong>Child Theme Configurator Pro.</strong>"
382
  msgstr ""
383
 
384
- #: includes/forms/addl_panels.php:22
385
  msgid "Customize Plugin Stylesheets"
386
  msgstr ""
387
 
388
- #: includes/forms/addl_panels.php:23
389
  msgid ""
390
  "Apply the power of CTC's top-rated interface to your site's plugin styles. "
391
  "All new design makes it much easier to get the results you want."
392
  msgstr ""
393
 
394
- #: includes/forms/addl_panels.php:24
395
  msgid "Quick Preview"
396
  msgstr ""
397
 
398
- #: includes/forms/addl_panels.php:24
399
  msgid "Test your child theme with a single click."
400
  msgstr ""
401
 
402
- #: includes/forms/addl_panels.php:25
403
  msgid "Find related styles"
404
  msgstr ""
405
 
406
- #: includes/forms/addl_panels.php:25
407
  msgid ""
408
  "Use the \"All Styles\" panel to edit groups of selectors from a single "
409
  "combined list."
410
  msgstr ""
411
 
412
- #: includes/forms/addl_panels.php:26
413
  msgid "Find styles by Nav Menu"
414
  msgstr ""
415
 
416
- #: includes/forms/addl_panels.php:26
417
  msgid "Tweak menus quickly and easily."
418
  msgstr ""
419
 
420
- #: includes/forms/addl_panels.php:27
421
  msgid "Most recent edits"
422
  msgstr ""
423
 
424
- #: includes/forms/addl_panels.php:27
425
  msgid "Return to recently edited selectors from a toggleable sidebar."
426
  msgstr ""
427
 
428
- #: includes/forms/addl_panels.php:28
429
  msgid "Genesis Framework Support"
430
  msgstr ""
431
 
432
- #: includes/forms/addl_panels.php:29
433
  msgid ""
434
  "Automatically detects and configures Genesis Child Themes with more "
435
  "frameworks on the way."
436
  msgstr ""
437
 
438
- #: includes/forms/addl_panels.php:30
439
  msgid "Top-rated Online Support"
440
  msgstr ""
441
 
442
- #: includes/forms/addl_panels.php:31
443
  msgid "Online Documentation"
444
  msgstr ""
445
 
446
- #: includes/forms/addl_panels.php:32
447
  msgid "Tutorial Videos"
448
  msgstr ""
449
 
450
- #: includes/forms/addl_panels.php:34
451
- msgid "Upgrade Now"
452
- msgstr ""
453
-
454
- #: includes/forms/addl_panels.php:34
455
- msgid "Buy Now - Only $17.95 USD*"
456
- msgstr ""
457
-
458
- #: includes/forms/addl_panels.php:34
459
- msgid "*Prices subject to change."
460
- msgstr ""
461
-
462
  #: includes/forms/addl_tabs.php:8
463
- msgid "Get Pro"
464
  msgstr ""
465
 
466
  #: includes/forms/backup.php:8
467
  msgid "Backup"
468
  msgstr ""
469
 
470
- #: includes/forms/backups.php:10 includes/forms/parent-child.php:239
471
  msgid "Restore backup from"
472
  msgstr ""
473
 
@@ -575,14 +583,6 @@ msgstr ""
575
  msgid "Make read-only"
576
  msgstr ""
577
 
578
- #: includes/forms/files.php:99
579
- msgid "Debug"
580
- msgstr ""
581
-
582
- #: includes/forms/files.php:102
583
- msgid "Check the box to enable debugging output."
584
- msgstr ""
585
-
586
  #: includes/forms/images.php:10
587
  msgid "Child Theme Images"
588
  msgstr ""
@@ -667,8 +667,8 @@ msgstr ""
667
  msgid "Duplicate Theme Slug"
668
  msgstr ""
669
 
670
- #: includes/forms/parent-child.php:118 includes/forms/parent-child.php:198
671
- #: includes/forms/parent-child.php:213
672
  msgid "NOTE:"
673
  msgstr ""
674
 
@@ -676,58 +676,66 @@ msgstr ""
676
  msgid "This will copy all child theme files and apply changes to new version."
677
  msgstr ""
678
 
679
- #: includes/forms/parent-child.php:127
 
 
 
 
 
 
 
 
680
  msgid "Stylesheet handling"
681
  msgstr ""
682
 
683
- #: includes/forms/parent-child.php:128
684
  msgid "(click to view options)"
685
  msgstr ""
686
 
687
- #: includes/forms/parent-child.php:130
688
  msgid ""
689
  "This theme may not apply child theme styles correctly with the current "
690
  "settings:"
691
  msgstr ""
692
 
693
- #: includes/forms/parent-child.php:132
694
  msgid "Don't show again."
695
  msgstr ""
696
 
697
- #: includes/forms/parent-child.php:132
698
  msgid "View options"
699
  msgstr ""
700
 
701
- #: includes/forms/parent-child.php:135
702
  msgid "Which option should I use?"
703
  msgstr ""
704
 
705
- #: includes/forms/parent-child.php:140
706
  msgid "None (handled by theme)"
707
  msgstr ""
708
 
709
- #: includes/forms/parent-child.php:144
710
  msgid ""
711
  "Select this option if all stylesheets are correctly enqueued for child "
712
  "themes. If you find that styles are not being applied correctly, use a "
713
  "different option."
714
  msgstr ""
715
 
716
- #: includes/forms/parent-child.php:151
717
  msgid "Enqueue parent stylesheet (default)"
718
  msgstr ""
719
 
720
- #: includes/forms/parent-child.php:154
721
  msgid ""
722
  "Select this option if the theme enqueues the active stylesheet but has no "
723
  "special handling for child themes. Start with this option if unsure."
724
  msgstr ""
725
 
726
- #: includes/forms/parent-child.php:161
727
  msgid "Enqueue child stylesheet"
728
  msgstr ""
729
 
730
- #: includes/forms/parent-child.php:164
731
  msgid ""
732
  "Select this option if the theme enqueues the parent stylesheet but does not "
733
  "enqueue the child stylesheet at all. This can happen if "
@@ -735,67 +743,89 @@ msgid ""
735
  "used to link the stylesheet."
736
  msgstr ""
737
 
738
- #: includes/forms/parent-child.php:167
739
  msgid "Recommended for this theme:"
740
  msgstr ""
741
 
742
- #: includes/forms/parent-child.php:173
743
  msgid "Enqueue both parent and child stylesheets"
744
  msgstr ""
745
 
746
- #: includes/forms/parent-child.php:176
747
  msgid ""
748
  "Select this option if stylesheet link tags are hard-coded into the header "
749
  "template (common in older themes). This enables the child stylesheet to "
750
  "override the parent stylesheet without using <code>@import</code>."
751
  msgstr ""
752
 
753
- #: includes/forms/parent-child.php:183
754
  msgid "<code>@import</code> parent stylesheet"
755
  msgstr ""
756
 
757
- #: includes/forms/parent-child.php:186
758
  msgid ""
759
  "This option imports the parent stylesheet from the child stylesheet. This "
760
  "enables the child stylesheet to override the parent stylesheet, but using "
761
  "<code>@import</code> is no longer recommended."
762
  msgstr ""
763
 
764
- #: includes/forms/parent-child.php:191
765
  msgid "Copy Parent Theme Menus, Widgets and other Customizer Options"
766
  msgstr ""
767
 
768
- #: includes/forms/parent-child.php:200
769
  msgid "This will overwrite child theme options you may have already set."
770
  msgstr ""
771
 
772
- #: includes/forms/parent-child.php:206
773
  msgid "Backup current stylesheet"
774
  msgstr ""
775
 
776
- #: includes/forms/parent-child.php:215
777
  msgid ""
778
  "This creates a copy of the current stylesheet before applying changes. You "
779
  "can remove old backup files using the Files tab."
780
  msgstr ""
781
 
782
- #: includes/forms/parent-child.php:220
783
  msgid "Reset/Restore from backup"
784
  msgstr ""
785
 
786
- #: includes/forms/parent-child.php:226
787
  msgid "Leave unchanged"
788
  msgstr ""
789
 
790
- #: includes/forms/parent-child.php:232
791
  msgid "Reset all"
792
  msgstr ""
793
 
794
- #: includes/forms/parent-child.php:252
795
  msgid "Parse additional stylesheets"
796
  msgstr ""
797
 
798
- #: includes/forms/parent-child.php:275
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
799
  msgid "Generate/Rebuild Child Theme Files"
800
  msgstr ""
801
 
@@ -815,43 +845,47 @@ msgstr ""
815
  msgid "Save Child Values"
816
  msgstr ""
817
 
818
- #: includes/forms/query-selector.php:52 includes/forms/rule-value.php:13
819
- msgid "Rule"
 
 
 
 
820
  msgstr ""
821
 
822
- #: includes/forms/query-selector.php:55
823
  msgid "Parent Value"
824
  msgstr ""
825
 
826
- #: includes/forms/query-selector.php:58
827
  msgid "Child Value"
828
  msgstr ""
829
 
830
- #: includes/forms/query-selector.php:64
831
- msgid "New Rule"
832
  msgstr ""
833
 
834
- #: includes/forms/query-selector.php:74
835
  msgid "Order"
836
  msgstr ""
837
 
838
- #: includes/forms/query-selector.php:83
839
  msgid "Copy Selector"
840
  msgstr ""
841
 
842
- #: includes/forms/query-selector.php:85 includes/forms/webfonts.php:15
843
  msgid "Save"
844
  msgstr ""
845
 
846
- #: includes/forms/query-selector.php:88
847
  msgid "Raw CSS"
848
  msgstr ""
849
 
850
- #: includes/forms/query-selector.php:90
851
  msgid "Use to enter shorthand CSS or new @media queries and selectors."
852
  msgstr ""
853
 
854
- #: includes/forms/query-selector.php:90
855
  msgid ""
856
  "Values entered here are merged into existing child styles or added to the "
857
  "child stylesheet if they do not exist in the parent."
@@ -886,7 +920,7 @@ msgid "Query/Selector"
886
  msgstr ""
887
 
888
  #: includes/forms/tabs.php:19
889
- msgid "Rule/Value"
890
  msgstr ""
891
 
892
  #: includes/forms/tabs.php:22
2
  # This file is distributed under the same license as the Child Theme Configurator package.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: Child Theme Configurator 1.7.5\n"
6
  "Report-Msgid-Bugs-To: http://wordpress.org/tag/child-theme-configurator\n"
7
+ "POT-Creation-Date: 2015-06-21 07:39:17+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
12
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13
  "Language-Team: LANGUAGE <LL@li.org>\n"
14
 
15
+ #. #-#-#-#-# chld_thm_cfg.pot (Child Theme Configurator 1.7.5) #-#-#-#-#
16
  #. Plugin Name of the plugin/theme
17
  #: child-theme-configurator.php:78 child-theme-configurator.php:88
18
  #: includes/forms/main.php:23
80
  msgid "before activating."
81
  msgstr ""
82
 
83
+ #: includes/class-ctc.php:145
84
  msgid "URL/None"
85
  msgstr ""
86
 
87
+ #: includes/class-ctc.php:146
88
  msgid "Origin"
89
  msgstr ""
90
 
91
+ #: includes/class-ctc.php:147
92
  msgid "Color 1"
93
  msgstr ""
94
 
95
+ #: includes/class-ctc.php:148
96
  msgid "Color 2"
97
  msgstr ""
98
 
99
+ #: includes/class-ctc.php:149
100
  msgid "Width/None"
101
  msgstr ""
102
 
103
+ #: includes/class-ctc.php:150
104
  msgid "Style"
105
  msgstr ""
106
 
107
+ #: includes/class-ctc.php:151
108
  msgid "Color"
109
  msgstr ""
110
 
111
+ #: includes/class-ctc.php:153
112
  msgid "Are you sure? This will replace your current settings."
113
  msgstr ""
114
 
115
+ #: includes/class-ctc.php:154
116
  msgid "<span style=\"font-size:10px\">!</span>"
117
  msgstr ""
118
 
119
+ #: includes/class-ctc.php:155 includes/forms/rule-value.php:32
120
  msgid "Selectors"
121
  msgstr ""
122
 
123
+ #: includes/class-ctc.php:156
124
  msgid "Close"
125
  msgstr ""
126
 
127
+ #: includes/class-ctc.php:157
128
+ msgid "Edit Selector"
129
  msgstr ""
130
 
131
+ #: includes/class-ctc.php:158
132
  msgid "Cancel"
133
  msgstr ""
134
 
135
+ #: includes/class-ctc.php:159
136
  msgid "Rename"
137
  msgstr ""
138
 
139
+ #: includes/class-ctc.php:160
140
  msgid "The stylesheet cannot be displayed."
141
  msgstr ""
142
 
143
+ #: includes/class-ctc.php:161
144
  msgid "(Child Only)"
145
  msgstr ""
146
 
147
+ #: includes/class-ctc.php:162
148
  msgid "Please enter a valid Child Theme."
149
  msgstr ""
150
 
151
+ #: includes/class-ctc.php:163
152
  msgid "Please enter a valid Child Theme name."
153
  msgstr ""
154
 
155
+ #: includes/class-ctc.php:164
156
  msgid "<strong>%s</strong> exists. Please enter a different Child Theme"
157
  msgstr ""
158
 
159
+ #: includes/class-ctc.php:165
160
  msgid "The page could not be loaded correctly."
161
  msgstr ""
162
 
163
+ #: includes/class-ctc.php:167
164
  msgid ""
165
  "Conflicting or out-of-date jQuery libraries were loaded by another plugin:"
166
  msgstr ""
167
 
168
+ #: includes/class-ctc.php:169
169
  msgid "Deactivating or replacing plugins may resolve this issue."
170
  msgstr ""
171
 
172
+ #: includes/class-ctc.php:170
173
  msgid "%sWhy am I seeing this?%s"
174
  msgstr ""
175
 
176
+ #: includes/class-ctc.php:393
177
  msgid "Zip file creation failed."
178
  msgstr ""
179
 
180
+ #: includes/class-ctc.php:429
181
  msgid "The Functions file is required and cannot be deleted."
182
  msgstr ""
183
 
184
+ #: includes/class-ctc.php:511
185
  msgid "You do not have permission to configure child themes."
186
  msgstr ""
187
 
188
+ #: includes/class-ctc.php:558
189
  msgid "%s does not exist. Please select a valid Parent Theme."
190
  msgstr ""
191
 
192
+ #: includes/class-ctc.php:562
193
  msgid "Please select a valid Parent Theme."
194
  msgstr ""
195
 
196
+ #: includes/class-ctc.php:565
197
  msgid "Please enter a valid Child Theme directory."
198
  msgstr ""
199
 
200
+ #: includes/class-ctc.php:573 includes/class-ctc.php:588
201
  msgid "Please enter a valid Child Theme template name."
202
  msgstr ""
203
 
204
+ #: includes/class-ctc.php:578 includes/class-ctc.php:592
205
  msgid ""
206
  "<strong>%s</strong> exists. Please enter a different Child Theme template "
207
  "name."
208
  msgstr ""
209
 
210
+ #: includes/class-ctc.php:605
211
  msgid "Your theme directories are not writable."
212
  msgstr ""
213
 
214
+ #: includes/class-ctc.php:683
215
  msgid "Your stylesheet is not writable."
216
  msgstr ""
217
 
218
+ #: includes/class-ctc.php:953
219
  msgid ""
220
  "A closing PHP tag was detected in Child theme functions file so \"Parent "
221
  "Stylesheet Handling\" option was not configured. Closing PHP at the end of "
224
  "click \"Generate/Rebuild Child Theme Files\" again."
225
  msgstr ""
226
 
227
+ #: includes/class-ctc.php:1053
228
  msgid "Could not delete file."
229
  msgstr ""
230
 
231
+ #: includes/class-ctc.php:1129
232
  msgid "Could not set write permissions."
233
  msgstr ""
234
 
235
+ #: includes/class-ctc.php:1230
236
  msgid "There were errors while resetting permissions."
237
  msgstr ""
238
 
239
+ #: includes/class-ctc.php:1272
240
  msgid "Could not upload file."
241
  msgstr ""
242
 
243
+ #: includes/class-ctc.php:1355
244
  msgid ""
245
  "The child theme is in read-only mode and Child Theme Configurator cannot "
246
  "apply changes. Click to see options"
247
  msgstr ""
248
 
249
+ #: includes/class-ctc.php:1358
250
  msgid ""
251
  "<li>Temporarily set write permissions by clicking the button below. When you "
252
  "are finished editing, revert to read-only by clicking \"Make read-only\" "
253
  "under the \"Files\" tab.</li>"
254
  msgstr ""
255
 
256
+ #: includes/class-ctc.php:1361
257
  msgid "Make files writable"
258
  msgstr ""
259
 
260
+ #: includes/class-ctc.php:1362
261
  msgid ""
262
  "<li><a target=\"_blank\" href=\"http://codex.wordpress.org/Editing_wp-"
263
  "config.php#WordPress_Upgrade_Constants\" title=\"Editin wp-config.php\">Add "
264
  "your FTP/SSH credentials to the WordPress config file</a>.</li>"
265
  msgstr ""
266
 
267
+ #: includes/class-ctc.php:1364
268
  msgid ""
269
  "<li><a target=\"_blank\" href=\"http://technet.microsoft.com/en-us/library/"
270
  "cc771170\" title=\"Setting Application Pool Identity\">Assign WordPress to "
272
  "li>"
273
  msgstr ""
274
 
275
+ #: includes/class-ctc.php:1365
276
  msgid ""
277
  "<li><a target=\"_blank\" href=\"http://codex.wordpress.org/"
278
  "Changing_File_Permissions\" title=\"Changing File Permissions\">Set write "
279
  "permissions on the server manually</a> (not recommended).</li>"
280
  msgstr ""
281
 
282
+ #: includes/class-ctc.php:1367
283
  msgid "<li>Run PHP under Apache with suEXEC (contact your web host).</li>"
284
  msgstr ""
285
 
286
+ #: includes/class-ctc.php:1378
287
  msgid ""
288
  "This Child Theme is not owned by your website account. It may have been "
289
  "created by a prior version of this plugin or by another program. Moving "
292
  "below."
293
  msgstr ""
294
 
295
+ #: includes/class-ctc.php:1381
296
  msgid "Correct Child Theme Permissions"
297
  msgstr ""
298
 
299
+ #: includes/class-ctc.php:1388
300
  msgid ""
301
  "Child Theme Configurator needs to update its interal data. Please set your "
302
  "preferences below and click \"Generate Child Theme Files\" to update your "
303
  "configuration."
304
  msgstr ""
305
 
306
+ #: includes/class-ctc.php:1394
307
  msgid ""
308
  "<strong>However, some styles could not be parsed due to memory limits.</"
309
  "strong> Try deselecting \"Additional Stylesheets\" below and click "
310
  "\"Generate/Rebuild Child Theme Files\". %sWhy am I seeing this?%s"
311
  msgstr ""
312
 
313
+ #: includes/class-ctc.php:1403
314
  msgid ""
315
  "Child Theme Configurator did not detect any configuration data because a "
316
  "previously configured Child Theme has been removed. Please set your "
321
  msgid "Parse additional stylesheets:"
322
  msgstr ""
323
 
324
+ #: includes/forms/addl_css.php:11 includes/forms/parent-child.php:270
325
  msgid ""
326
  "Stylesheets that are currently being loaded by the parent theme are "
327
  "automatically selected below (except for Bootstrap stylesheets which add a "
329
  "only the additional stylesheets you wish to customize."
330
  msgstr ""
331
 
332
+ #: includes/forms/addl_panels.php:9 includes/forms/addl_panels.php:38
333
+ msgid "Use coupon code"
334
+ msgstr ""
335
+
336
+ #: includes/forms/addl_panels.php:9 includes/forms/addl_panels.php:38
337
+ msgid "wordpress-org"
338
+ msgstr ""
339
+
340
+ #: includes/forms/addl_panels.php:9 includes/forms/addl_panels.php:38
341
+ msgid "and get <strong>20% off entire order</strong>."
342
+ msgstr ""
343
+
344
+ #: includes/forms/addl_panels.php:10 includes/forms/addl_panels.php:39
345
+ msgid "Order Now"
346
+ msgstr ""
347
+
348
+ #: includes/forms/addl_panels.php:10 includes/forms/addl_panels.php:39
349
+ msgid "*Prices and offers subject to change."
350
+ msgstr ""
351
+
352
+ #: includes/forms/addl_panels.php:11 includes/forms/addl_panels.php:12
353
  msgid "Learn more about IntelliWidget"
354
  msgstr ""
355
 
356
+ #: includes/forms/addl_panels.php:12
357
  msgid ""
358
  "IntelliWidget is a versatile widget manager that does the work of multiple "
359
  "plugins by combining custom page menus, featured posts, sliders and other "
361
  "or site-wide basis."
362
  msgstr ""
363
 
364
+ #: includes/forms/addl_panels.php:13 includes/forms/addl_panels.php:16
365
  msgid "Learn more"
366
  msgstr ""
367
 
368
+ #: includes/forms/addl_panels.php:14 includes/forms/addl_panels.php:15
369
  msgid "Learn more about IW Responsive Menu"
370
  msgstr ""
371
 
372
+ #: includes/forms/addl_panels.php:15
373
  msgid ""
374
  "IntelliWidget Responsive Menu lets you break free from your theme’s built-in "
375
  "responsive menu options and gives you complete control over the user "
376
  "experience."
377
  msgstr ""
378
 
379
+ #: includes/forms/addl_panels.php:19 includes/help/help_en_US.php:217
380
  msgid "Learn more about CTC Pro"
381
  msgstr ""
382
 
383
+ #: includes/forms/addl_panels.php:20
384
  msgid "Customizing WordPress just got even easier."
385
  msgstr ""
386
 
387
+ #: includes/forms/addl_panels.php:21
388
  msgid ""
389
  "Thousands of users have already seen the benefits of using Child Theme "
390
  "Configurator. If you spend any amount of time customizing WordPress, CTC Pro "
391
  "will help maximize your productivity."
392
  msgstr ""
393
 
394
+ #: includes/forms/addl_panels.php:22
395
  msgid "Designed by Developers Who Use It Every Day."
396
  msgstr ""
397
 
398
+ #: includes/forms/addl_panels.php:23
399
  msgid ""
400
  "We've packed in more features to make design work quicker and easier with "
401
  "<strong>Child Theme Configurator Pro.</strong>"
402
  msgstr ""
403
 
404
+ #: includes/forms/addl_panels.php:25
405
  msgid "Customize Plugin Stylesheets"
406
  msgstr ""
407
 
408
+ #: includes/forms/addl_panels.php:26
409
  msgid ""
410
  "Apply the power of CTC's top-rated interface to your site's plugin styles. "
411
  "All new design makes it much easier to get the results you want."
412
  msgstr ""
413
 
414
+ #: includes/forms/addl_panels.php:27
415
  msgid "Quick Preview"
416
  msgstr ""
417
 
418
+ #: includes/forms/addl_panels.php:27
419
  msgid "Test your child theme with a single click."
420
  msgstr ""
421
 
422
+ #: includes/forms/addl_panels.php:28
423
  msgid "Find related styles"
424
  msgstr ""
425
 
426
+ #: includes/forms/addl_panels.php:28
427
  msgid ""
428
  "Use the \"All Styles\" panel to edit groups of selectors from a single "
429
  "combined list."
430
  msgstr ""
431
 
432
+ #: includes/forms/addl_panels.php:29
433
  msgid "Find styles by Nav Menu"
434
  msgstr ""
435
 
436
+ #: includes/forms/addl_panels.php:29
437
  msgid "Tweak menus quickly and easily."
438
  msgstr ""
439
 
440
+ #: includes/forms/addl_panels.php:30
441
  msgid "Most recent edits"
442
  msgstr ""
443
 
444
+ #: includes/forms/addl_panels.php:30
445
  msgid "Return to recently edited selectors from a toggleable sidebar."
446
  msgstr ""
447
 
448
+ #: includes/forms/addl_panels.php:31
449
  msgid "Genesis Framework Support"
450
  msgstr ""
451
 
452
+ #: includes/forms/addl_panels.php:32
453
  msgid ""
454
  "Automatically detects and configures Genesis Child Themes with more "
455
  "frameworks on the way."
456
  msgstr ""
457
 
458
+ #: includes/forms/addl_panels.php:33
459
  msgid "Top-rated Online Support"
460
  msgstr ""
461
 
462
+ #: includes/forms/addl_panels.php:34
463
  msgid "Online Documentation"
464
  msgstr ""
465
 
466
+ #: includes/forms/addl_panels.php:35
467
  msgid "Tutorial Videos"
468
  msgstr ""
469
 
 
 
 
 
 
 
 
 
 
 
 
 
470
  #: includes/forms/addl_tabs.php:8
471
+ msgid "Upgrade"
472
  msgstr ""
473
 
474
  #: includes/forms/backup.php:8
475
  msgid "Backup"
476
  msgstr ""
477
 
478
+ #: includes/forms/backups.php:10 includes/forms/parent-child.php:253
479
  msgid "Restore backup from"
480
  msgstr ""
481
 
583
  msgid "Make read-only"
584
  msgstr ""
585
 
 
 
 
 
 
 
 
 
586
  #: includes/forms/images.php:10
587
  msgid "Child Theme Images"
588
  msgstr ""
667
  msgid "Duplicate Theme Slug"
668
  msgstr ""
669
 
670
+ #: includes/forms/parent-child.php:118 includes/forms/parent-child.php:212
671
+ #: includes/forms/parent-child.php:226
672
  msgid "NOTE:"
673
  msgstr ""
674
 
676
  msgid "This will copy all child theme files and apply changes to new version."
677
  msgstr ""
678
 
679
+ #: includes/forms/parent-child.php:126
680
+ msgid "Debug"
681
+ msgstr ""
682
+
683
+ #: includes/forms/parent-child.php:134
684
+ msgid "Check the box to enable debugging output."
685
+ msgstr ""
686
+
687
+ #: includes/forms/parent-child.php:141
688
  msgid "Stylesheet handling"
689
  msgstr ""
690
 
691
+ #: includes/forms/parent-child.php:142
692
  msgid "(click to view options)"
693
  msgstr ""
694
 
695
+ #: includes/forms/parent-child.php:144
696
  msgid ""
697
  "This theme may not apply child theme styles correctly with the current "
698
  "settings:"
699
  msgstr ""
700
 
701
+ #: includes/forms/parent-child.php:146
702
  msgid "Don't show again."
703
  msgstr ""
704
 
705
+ #: includes/forms/parent-child.php:146
706
  msgid "View options"
707
  msgstr ""
708
 
709
+ #: includes/forms/parent-child.php:149
710
  msgid "Which option should I use?"
711
  msgstr ""
712
 
713
+ #: includes/forms/parent-child.php:154
714
  msgid "None (handled by theme)"
715
  msgstr ""
716
 
717
+ #: includes/forms/parent-child.php:158
718
  msgid ""
719
  "Select this option if all stylesheets are correctly enqueued for child "
720
  "themes. If you find that styles are not being applied correctly, use a "
721
  "different option."
722
  msgstr ""
723
 
724
+ #: includes/forms/parent-child.php:165
725
  msgid "Enqueue parent stylesheet (default)"
726
  msgstr ""
727
 
728
+ #: includes/forms/parent-child.php:168
729
  msgid ""
730
  "Select this option if the theme enqueues the active stylesheet but has no "
731
  "special handling for child themes. Start with this option if unsure."
732
  msgstr ""
733
 
734
+ #: includes/forms/parent-child.php:175
735
  msgid "Enqueue child stylesheet"
736
  msgstr ""
737
 
738
+ #: includes/forms/parent-child.php:178
739
  msgid ""
740
  "Select this option if the theme enqueues the parent stylesheet but does not "
741
  "enqueue the child stylesheet at all. This can happen if "
743
  "used to link the stylesheet."
744
  msgstr ""
745
 
746
+ #: includes/forms/parent-child.php:181
747
  msgid "Recommended for this theme:"
748
  msgstr ""
749
 
750
+ #: includes/forms/parent-child.php:187
751
  msgid "Enqueue both parent and child stylesheets"
752
  msgstr ""
753
 
754
+ #: includes/forms/parent-child.php:190
755
  msgid ""
756
  "Select this option if stylesheet link tags are hard-coded into the header "
757
  "template (common in older themes). This enables the child stylesheet to "
758
  "override the parent stylesheet without using <code>@import</code>."
759
  msgstr ""
760
 
761
+ #: includes/forms/parent-child.php:197
762
  msgid "<code>@import</code> parent stylesheet"
763
  msgstr ""
764
 
765
+ #: includes/forms/parent-child.php:200
766
  msgid ""
767
  "This option imports the parent stylesheet from the child stylesheet. This "
768
  "enables the child stylesheet to override the parent stylesheet, but using "
769
  "<code>@import</code> is no longer recommended."
770
  msgstr ""
771
 
772
+ #: includes/forms/parent-child.php:205
773
  msgid "Copy Parent Theme Menus, Widgets and other Customizer Options"
774
  msgstr ""
775
 
776
+ #: includes/forms/parent-child.php:214
777
  msgid "This will overwrite child theme options you may have already set."
778
  msgstr ""
779
 
780
+ #: includes/forms/parent-child.php:219
781
  msgid "Backup current stylesheet"
782
  msgstr ""
783
 
784
+ #: includes/forms/parent-child.php:228
785
  msgid ""
786
  "This creates a copy of the current stylesheet before applying changes. You "
787
  "can remove old backup files using the Files tab."
788
  msgstr ""
789
 
790
+ #: includes/forms/parent-child.php:234
791
  msgid "Reset/Restore from backup"
792
  msgstr ""
793
 
794
+ #: includes/forms/parent-child.php:240
795
  msgid "Leave unchanged"
796
  msgstr ""
797
 
798
+ #: includes/forms/parent-child.php:246
799
  msgid "Reset all"
800
  msgstr ""
801
 
802
+ #: includes/forms/parent-child.php:266
803
  msgid "Parse additional stylesheets"
804
  msgstr ""
805
 
806
+ #: includes/forms/parent-child.php:290
807
+ msgid "Please read before you click:"
808
+ msgstr ""
809
+
810
+ #: includes/forms/parent-child.php:291
811
+ msgid ""
812
+ "This plugin makes significant modifications to your child theme, to include "
813
+ "changing CSS, removing comments and adding php functions."
814
+ msgstr ""
815
+
816
+ #: includes/forms/parent-child.php:292
817
+ msgid "If you are using an existing Child Theme,"
818
+ msgstr ""
819
+
820
+ #: includes/forms/parent-child.php:292
821
+ msgid "please consider using the Duplicate Child Theme option"
822
+ msgstr ""
823
+
824
+ #: includes/forms/parent-child.php:292
825
+ msgid "before proceeding."
826
+ msgstr ""
827
+
828
+ #: includes/forms/parent-child.php:298
829
  msgid "Generate/Rebuild Child Theme Files"
830
  msgstr ""
831
 
845
  msgid "Save Child Values"
846
  msgstr ""
847
 
848
+ #: includes/forms/query-selector.php:47
849
+ msgid "Delete Child Values"
850
+ msgstr ""
851
+
852
+ #: includes/forms/query-selector.php:54 includes/forms/rule-value.php:13
853
+ msgid "Property"
854
  msgstr ""
855
 
856
+ #: includes/forms/query-selector.php:57
857
  msgid "Parent Value"
858
  msgstr ""
859
 
860
+ #: includes/forms/query-selector.php:60
861
  msgid "Child Value"
862
  msgstr ""
863
 
864
+ #: includes/forms/query-selector.php:66
865
+ msgid "New Property"
866
  msgstr ""
867
 
868
+ #: includes/forms/query-selector.php:76
869
  msgid "Order"
870
  msgstr ""
871
 
872
+ #: includes/forms/query-selector.php:85
873
  msgid "Copy Selector"
874
  msgstr ""
875
 
876
+ #: includes/forms/query-selector.php:87 includes/forms/webfonts.php:15
877
  msgid "Save"
878
  msgstr ""
879
 
880
+ #: includes/forms/query-selector.php:90
881
  msgid "Raw CSS"
882
  msgstr ""
883
 
884
+ #: includes/forms/query-selector.php:92
885
  msgid "Use to enter shorthand CSS or new @media queries and selectors."
886
  msgstr ""
887
 
888
+ #: includes/forms/query-selector.php:92
889
  msgid ""
890
  "Values entered here are merged into existing child styles or added to the "
891
  "child stylesheet if they do not exist in the parent."
920
  msgstr ""
921
 
922
  #: includes/forms/tabs.php:19
923
+ msgid "Property/Value"
924
  msgstr ""
925
 
926
  #: includes/forms/tabs.php:22
readme.txt CHANGED
@@ -3,22 +3,22 @@ Contributors: lilaeamedia
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=8QE5YJ8WE96AJ
4
  Tags: child theme, child themes, customize theme, CSS, responsive, css editor, child theme generator, child theme creator, stylesheet, customizer
5
  Requires at least: 3.9
6
- Tested up to: 4.2
7
- Stable tag: 1.7.4.2
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
11
- Create a child theme that follows WP best practice to enqueue stylesheets. Easy to use CSS editor lets you find, preview and customize any style.
12
 
13
  == Description ==
14
 
15
- Child Theme Configurator is a fast and easy to use CSS editor that allows you to create a child theme and customize it beyond the options of the Customizer. Designed for WordPress users who want to be able to customize stylesheets directly, the Child Theme Configurator lets you easily identify and override the exact CSS attributes you want to change. It gives you unlimited control over your WordPress look and feel while leaving your Parent Theme untouched. [Learn more about how to create a child theme](http://www.childthemeconfigurator.com).
16
 
17
  = Take Control of Your Child Themes =
18
 
19
- https://www.youtube.com/watch?v=53M7RVxDYEY
20
 
21
- The Child Theme Configurator parses and indexes your stylesheets so that every CSS 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 themes without the risk of losing your edits.
22
 
23
  You can create any number of child themes from your existing Parent Themes. The Child Theme Configurator lets you choose from your installed themes (even existing child themes) and save the results in your Themes directory.
24
 
@@ -27,18 +27,21 @@ When you are ready, just activate the Child Theme and your WordPress site takes
27
  = Why create child themes using the Child Theme Configurator? =
28
 
29
  * Update themes without losing customizations
 
 
30
  * Copy existing widgets, menus and other options to child theme
 
 
 
31
  * Save hours of development time
32
  * Multisite compatible
33
  * Make modifications unavailable to the Customizer
34
- * Uses WP best practice for enqueuing (linking) stylesheets
35
  * Export child themes as Zip Archive
36
  * Use web fonts in your child theme
37
  * Identify and override exact selectors from the parent theme
38
  * Change specific colors, backgrounds, font styles, etc., without changing other elements
39
- * Automatically generate cross-browser and vendor-prefixed rules and CSS gradients
40
  * Preview style changes before committing to them
41
- * Customize @media queries for responsive design
42
  * Uses WP Filesystem API – will not create files you cannot remove
43
 
44
  = Child Theme Configurator PRO =
@@ -119,7 +122,7 @@ Select this option if all stylesheets are correctly enqueued for child themes. I
119
 
120
  = Is there a tutorial? =
121
 
122
- https://www.youtube.com/watch?v=53M7RVxDYEY
123
 
124
  = If the parent theme changes (e.g., upgrade), do I have to update the child theme? =
125
 
@@ -131,6 +134,10 @@ A child theme is not a "copy" of the parent theme. It is a special feature of Wo
131
 
132
  No. Child Theme Configurator is designed to work independently of themes and plugins. Just remember that if you re-install, you must rebuild the configuration data using the Parent/Child tab.
133
 
 
 
 
 
134
  = Does it work with Multisite? =
135
 
136
  Yes. Go to "Network Admin > Themes > Child Themes." Child themes must be "Network enabled" to preview and activate for Network sites.
@@ -194,7 +201,7 @@ Click the "Help" tab at the top right for a quick reference.
194
 
195
  = How do I add Web Fonts? =
196
 
197
- The easiest method is to paste the @import code provided by Google, Font Squirrel or any other Web Font site into the Web Fonts 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.
198
 
199
  You can also create a secondary stylesheet that contains @font-face rules and import it using the Web Fonts tab.
200
 
@@ -223,7 +230,7 @@ The Child Theme Configurator automatically adds a blank functions.php file to th
223
 
224
  = How do I change a specific color/font style/background? =
225
 
226
- You can override a specific CSS value globally using the Rule/Value tab. See Rule/Value, above.
227
 
228
  = How do I add styles that aren't in the Parent Theme? =
229
 
@@ -231,15 +238,15 @@ You can add queries and selectors using the "Raw CSS" textarea on the Query/Sele
231
 
232
  = How do I remove a style from the Parent Theme? =
233
 
234
- 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.
235
 
236
  = How do I remove a style from the Child Theme? =
237
 
238
- 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.
239
 
240
  = How do I set the !important flag? =
241
 
242
- We always recommend relying on good cascading design over global overrides. To that end, you have ability to change the load order of child theme styles by entering a value in the "Order" field. And yes, you can now set rules as important by checking the "!" box next to each input. Please use judiciously.
243
 
244
  = How do I create cross-browser gradients? =
245
 
@@ -263,12 +270,18 @@ https://www.youtube.com/watch?v=iBiiAgsK4G4
263
  1. Parent/Child tab
264
  2. Parent/Child tab with parent theme menu open
265
  3. Query/Selector tab
266
- 4. Rule/Value tab
267
  5. Web Fonts tab
268
  6. Parent CSS tab
269
  7. Files tab
270
 
271
  == Changelog ==
 
 
 
 
 
 
272
  = 1.7.4.2 =
273
  * Will not write child theme stylesheet if error detected in functions.php
274
 
@@ -291,7 +304,7 @@ https://www.youtube.com/watch?v=iBiiAgsK4G4
291
  = 1.7.2.1 =
292
  * Fix: hide called before iris init
293
  * Fix: @import not being written on rebuild/configure
294
- * Fix: min height on rule/value panel
295
  * Only prune child theme selectors on rename
296
 
297
  = 1.7.1 =
@@ -314,7 +327,7 @@ https://www.youtube.com/watch?v=iBiiAgsK4G4
314
  = 1.6.5 =
315
  * Fix: incorrect path generation and validation on Windows servers
316
  * Added error handling and notification to prevent jQuery conflicts and out of memory conditions
317
- * Fix: removed max-height on rule/value overlay
318
  * Added debug option
319
 
320
  = 1.6.4 =
@@ -393,7 +406,7 @@ https://www.youtube.com/watch?v=iBiiAgsK4G4
393
 
394
  = 1.4.6 =
395
  * Feature: export child themes as zip archive
396
- * Added transform to list of vendor rules
397
  * Bug fixed: parser not loading multiple instances of same @media rulesets
398
  * Refactored uploader to use wp core functions for compatibility and security
399
  * Increased CHLD_THM_CFG_MAX_RECURSE_LOOPS to 1000 to accommodate complex parent frameworks
@@ -458,16 +471,16 @@ https://www.youtube.com/watch?v=iBiiAgsK4G4
458
  * New Features: You can now rename selectors in place from the Query/Selector panel. Made stylesheet backup optional. Bugs fixed: Incorrect parsing of background position when '0', fixed type error when background image url value is removed.
459
 
460
  = 1.2.1 =
461
- * Bugs fixed: "star hack" rules no longer throwing js error. Important flag now works on borders and gradients.
462
 
463
  = 1.2.0 =
464
- * New features: Link to Query/Selector tab from specific Rule/Value selector, new rule focus on adding new rule. Bugs fixed: clear Query/Selector inputs when loaded selector is empty, use latest min.js script.
465
 
466
  = 1.1.9 =
467
  * Added check for writability before attempting to create child theme files to avoid fatal error on servers not running suEXEC. Fixed a bug in the ctc_update_cache function that was throwing a fatal JS error when new media queries were saved via the Raw CSS input. Configurator now adds functions.php file to child theme when it does not exist.
468
 
469
  = 1.1.8 =
470
- * Added reorder sequence and important flag functionality. Fixed bug where multiple inputs with same selector/rule combo were assigned the same id. Fixed bug in the shorthand encoding routine.
471
 
472
  = 1.1.7 =
473
  * Added tutorial video to help tabs.
@@ -478,10 +491,10 @@ https://www.youtube.com/watch?v=iBiiAgsK4G4
478
  = 1.1.5 =
479
  * Query/Selector panel now defaults to 'base'
480
  * Fixed bug causing background-image with full urls (http://) to be parsed as gradients
481
- * Fixed bug causing rule menu to throw error when selector has no rules
482
 
483
  = 1.1.4 =
484
- * Fixed sort bug in shorthand parser that was returning rules in wrong order
485
 
486
  = 1.1.3 =
487
  * Fixed bug that assumed lowercase only for theme slugs. (Thanks to timk)
@@ -497,7 +510,7 @@ https://www.youtube.com/watch?v=iBiiAgsK4G4
497
  * Fixed gettext calls to use static namespace parameter
498
  * Auto populate child theme inputs when existing theme is selected
499
  * Correctly remove border when values are blanked
500
- * Fixed duplicate "new rule" bug on Query/Selector panel
501
  * added timestamp to backup file
502
  * Added encode_shorthand function to recombine margin/padding values when all 4 sides are present
503
 
@@ -512,18 +525,18 @@ https://www.youtube.com/watch?v=iBiiAgsK4G4
512
  * Initial release.
513
 
514
  == Upgrade Notice ==
515
- Version 1.7.3 now converts @import statements to link tags and checks parent theme for hard-coded stylesheet link tags and other problematic code issues. 1.7.3.1 added dismiss option to warnings by popular demand.
516
 
517
  == Override Parent Styles ==
518
 
519
- There are two ways to identify and override parent styles. The Child Theme Configurator lets you search styles by CSS selector and by rule. If you wish to change a specific CSS selector (e.g., h1), use the "Query/Selector" tab. If you have a specific CSS value you wish to change site-wide (e.g., the color of the type), use the "Rule/Value" tab.
520
 
521
  = Query/Selector Tab =
522
 
523
  The Query/Selector tab lets you find specific CSS selectors and edit them. First, find the query that contains the CSS 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. CSS selectors are in the base query by default.
524
  Next, find the CSS selector by typing in the "Selector" autoselect box. Select by clicking with the mouse or by pressing the "Enter" or "Tab" keys.
525
 
526
- This will load all of the rules for that CSS selector with the Parent values on the left and the child theme values inputs on the right. Any existing child theme 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.
527
 
528
  The "Order" field contains the original sequence of the CSS selector in the parent theme stylesheet. You can change the CSS selector order sequence by entering a lower or higher number in the "Order" field. You can also force style overrides (so called "!important" flag) by checking the "!" box next to each input. Please use judiciously.
529
 
@@ -531,23 +544,23 @@ Click "Save" to update the child theme stylesheet and save your changes to the W
531
 
532
  == Adding New Styles ==
533
 
534
- If you wish to add additional rules to a given CSS 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.
535
 
536
  If you wish to add completely new CSS selectors, or even new @media queries, you can enter free-form CSS in the "Raw CSS" textarea. Be aware that your syntax must be correct (i.e., balanced curly braces, etc.) for the parser to load the new styles. You will know it is invalid because a red "X" will appear next to the save button.
537
 
538
- 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.
539
 
540
- = Rule/Value Tab =
541
 
542
- The Rule/Value tab lets you find specific values for a given rule and then edit that value for individual CSS 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.
543
 
544
- This will load all of the unique values that exist for that rule in the parent theme stylesheet with a Sample preview for that value. If there are values that exist in the child theme stylesheet that do not exist in the parent stylesheet, they will be displayed as well.
545
 
546
- For each unique value, click the "Selectors" link to view a list of CSS selectors that use that rule/value combination, grouped by query with a Sample preview of the value and inputs for the child theme value. Any existing child theme values will be automatically populated.
547
 
548
  Click "Save" to update the child theme stylesheet and save your changes to the WordPress admin.
549
 
550
- If you want to edit all of the rules for the CSS selector you can click the “Edit” link and the CSS selector will automatically load in the Query/Selector Tab.
551
 
552
  == Web Fonts Tab ==
553
 
@@ -593,16 +606,16 @@ Some themes (particularly commercial themes) do not correctly load parent templa
593
 
594
  == Caveats ==
595
 
 
 
596
  * 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.
597
  * 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.
598
- * The Child Theme Configurator plugin works with the vast majority of CSS rules, however some obscure options are not auto-prefixed.
599
- * The Child Theme Configurator plugin does not support the legacy webkit gradient.
600
- * CSS Rules are auto-discovered. The Child Theme Configurator plugin loads the rules that exist in the Parent stylesheet. You can always add new rules using the "Raw CSS" text area.
601
- * Multiple versions of the same rule in a single selector are not supported, with a few exceptions. The Child Theme Configurator plugin will automatically generate vendor-prefix variations for background-image, border-radius, transform, transition, and others.
602
 
603
  == Documentation ==
604
 
605
- Go to http://www.childthemeconfigurator.com/documentation/
606
 
607
  Serbo-Croatian translation courtesy of Borisa Djuraskovic borisad@webhostinghub.com http://www.webhostinghub.com
608
 
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=8QE5YJ8WE96AJ
4
  Tags: child theme, child themes, customize theme, CSS, responsive, css editor, child theme generator, child theme creator, stylesheet, customizer
5
  Requires at least: 3.9
6
+ Tested up to: 4.3
7
+ Stable tag: 1.7.5
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
11
+ Create child themes and customize styles, templates and functions. Enqueues stylesheets and web fonts. Handles rgba, vendor-prefixes and more.
12
 
13
  == Description ==
14
 
15
+ Child Theme Configurator is a fast and easy to use CSS editor that allows you to create a child theme and customize it beyond the options of the Customizer. Designed for WordPress users who want to be able to customize stylesheets directly, the Child Theme Configurator lets you easily identify and override the exact CSS attributes you want to change. It properly enqueues theme and font stylesheets for optimum performance and handles vendor-specific syntax, giving you unlimited control over your WordPress look and feel while leaving your Parent Theme untouched. [Learn more about how to create a child theme](http://www.childthemeconfigurator.com).
16
 
17
  = Take Control of Your Child Themes =
18
 
19
+ https://www.youtube.com/watch?v=NQ1M-ZlRScY
20
 
21
+ The Child Theme Configurator parses and indexes your stylesheets so that every CSS media query, selector, property 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 themes without the risk of losing your edits.
22
 
23
  You can create any number of child themes from your existing Parent Themes. The Child Theme Configurator lets you choose from your installed themes (even existing child themes) and save the results in your Themes directory.
24
 
27
  = Why create child themes using the Child Theme Configurator? =
28
 
29
  * Update themes without losing customizations
30
+ * Enqueue (link) stylesheets instead of using @import
31
+ * Customize @media queries for responsive design
32
  * Copy existing widgets, menus and other options to child theme
33
+ * Select hex, RGBA (transparent) and named colors using Spectrum color picker
34
+ * Add fallback styles (multiple values per property)
35
+ * Resolve common child theme issues with almost any parent theme
36
  * Save hours of development time
37
  * Multisite compatible
38
  * Make modifications unavailable to the Customizer
 
39
  * Export child themes as Zip Archive
40
  * Use web fonts in your child theme
41
  * Identify and override exact selectors from the parent theme
42
  * Change specific colors, backgrounds, font styles, etc., without changing other elements
43
+ * Automatically generate cross-browser and vendor-prefixed properties and CSS gradients
44
  * Preview style changes before committing to them
 
45
  * Uses WP Filesystem API – will not create files you cannot remove
46
 
47
  = Child Theme Configurator PRO =
122
 
123
  = Is there a tutorial? =
124
 
125
+ https://www.youtube.com/watch?v=NQ1M-ZlRScY
126
 
127
  = If the parent theme changes (e.g., upgrade), do I have to update the child theme? =
128
 
134
 
135
  No. Child Theme Configurator is designed to work independently of themes and plugins. Just remember that if you re-install, you must rebuild the configuration data using the Parent/Child tab.
136
 
137
+ = How do I add comments? =
138
+
139
+ Arbitrary comments are not supported. Providing a high level of flexibility for previewing and modifying styles requires sophisticated parsing and data structures. Maintaining comments that bound to any particular element in the stylesheet is prohibitively expensive compared to the value it would add. Although we are working to include this as an option in the future, currently all comments are stripped from the child theme stylesheet code.
140
+
141
  = Does it work with Multisite? =
142
 
143
  Yes. Go to "Network Admin > Themes > Child Themes." Child themes must be "Network enabled" to preview and activate for Network sites.
201
 
202
  = How do I add Web Fonts? =
203
 
204
+ The easiest method is to paste the @import code provided by Google, Font Squirrel or any other Web Font site into the Web Fonts tab. The fonts will then be available to use as a value of the font-family property. Be sure you understand the license for any embedded fonts.
205
 
206
  You can also create a secondary stylesheet that contains @font-face rules and import it using the Web Fonts tab.
207
 
230
 
231
  = How do I change a specific color/font style/background? =
232
 
233
+ You can override a specific CSS value globally using the Property/Value tab. See Property/Value, above.
234
 
235
  = How do I add styles that aren't in the Parent Theme? =
236
 
238
 
239
  = How do I remove a style from the Parent Theme? =
240
 
241
+ You shouldn't really "remove" a style from the Parent. You can, however, set the property to "inherit," "none," or zero (depending on the property). This will negate the Parent value. Some experimentation may be necessary.
242
 
243
  = How do I remove a style from the Child Theme? =
244
 
245
+ Delete the value from the input for the property you wish to remove. The Child Theme Configurator only adds overrides for properties that contain values.
246
 
247
  = How do I set the !important flag? =
248
 
249
+ We always recommend relying on good cascading design over global overrides. To that end, you have ability to change the load order of child theme styles by entering a value in the "Order" field. And yes, you can now set properties as important by checking the "!" box next to each input. Please use judiciously.
250
 
251
  = How do I create cross-browser gradients? =
252
 
270
  1. Parent/Child tab
271
  2. Parent/Child tab with parent theme menu open
272
  3. Query/Selector tab
273
+ 4. Property/Value tab
274
  5. Web Fonts tab
275
  6. Parent CSS tab
276
  7. Files tab
277
 
278
  == Changelog ==
279
+ = 1.7.5 =
280
+ * Uses spectrum color picker to support transparency and named colors.
281
+ * Refactored entire system to support fallback values for any property.
282
+ * Fix path when duplicating child theme on first run
283
+ * New Feature: "delete child values" button - easily revert styles in child theme stylesheet
284
+
285
  = 1.7.4.2 =
286
  * Will not write child theme stylesheet if error detected in functions.php
287
 
304
  = 1.7.2.1 =
305
  * Fix: hide called before iris init
306
  * Fix: @import not being written on rebuild/configure
307
+ * Fix: min height on property/value panel
308
  * Only prune child theme selectors on rename
309
 
310
  = 1.7.1 =
327
  = 1.6.5 =
328
  * Fix: incorrect path generation and validation on Windows servers
329
  * Added error handling and notification to prevent jQuery conflicts and out of memory conditions
330
+ * Fix: removed max-height on property/value overlay
331
  * Added debug option
332
 
333
  = 1.6.4 =
406
 
407
  = 1.4.6 =
408
  * Feature: export child themes as zip archive
409
+ * Added transform to list of vendor properties
410
  * Bug fixed: parser not loading multiple instances of same @media rulesets
411
  * Refactored uploader to use wp core functions for compatibility and security
412
  * Increased CHLD_THM_CFG_MAX_RECURSE_LOOPS to 1000 to accommodate complex parent frameworks
471
  * New Features: You can now rename selectors in place from the Query/Selector panel. Made stylesheet backup optional. Bugs fixed: Incorrect parsing of background position when '0', fixed type error when background image url value is removed.
472
 
473
  = 1.2.1 =
474
+ * Bugs fixed: "star hack" properties no longer throwing js error. Important flag now works on borders and gradients.
475
 
476
  = 1.2.0 =
477
+ * New features: Link to Query/Selector tab from specific Property/Value selector, new property focus on adding new property. Bugs fixed: clear Query/Selector inputs when loaded selector is empty, use latest min.js script.
478
 
479
  = 1.1.9 =
480
  * Added check for writability before attempting to create child theme files to avoid fatal error on servers not running suEXEC. Fixed a bug in the ctc_update_cache function that was throwing a fatal JS error when new media queries were saved via the Raw CSS input. Configurator now adds functions.php file to child theme when it does not exist.
481
 
482
  = 1.1.8 =
483
+ * Added reorder sequence and important flag functionality. Fixed bug where multiple inputs with same selector/property combo were assigned the same id. Fixed bug in the shorthand encoding routine.
484
 
485
  = 1.1.7 =
486
  * Added tutorial video to help tabs.
491
  = 1.1.5 =
492
  * Query/Selector panel now defaults to 'base'
493
  * Fixed bug causing background-image with full urls (http://) to be parsed as gradients
494
+ * Fixed bug causing property menu to throw error when selector has no properties
495
 
496
  = 1.1.4 =
497
+ * Fixed sort bug in shorthand parser that was returning properties in wrong order
498
 
499
  = 1.1.3 =
500
  * Fixed bug that assumed lowercase only for theme slugs. (Thanks to timk)
510
  * Fixed gettext calls to use static namespace parameter
511
  * Auto populate child theme inputs when existing theme is selected
512
  * Correctly remove border when values are blanked
513
+ * Fixed duplicate "new property" bug on Query/Selector panel
514
  * added timestamp to backup file
515
  * Added encode_shorthand function to recombine margin/padding values when all 4 sides are present
516
 
525
  * Initial release.
526
 
527
  == Upgrade Notice ==
528
+ Version 1.7.5 adds long-awaited delete child values button and support for multiple fallback styles along with several other improvements. Replaced Iris color picker with Spectrum which supports rgba, hsla and named colors.
529
 
530
  == Override Parent Styles ==
531
 
532
+ There are two ways to identify and override parent styles. The Child Theme Configurator lets you search styles by CSS selector and by property. If you wish to change a specific CSS selector (e.g., h1), use the "Query/Selector" tab. If you have a specific CSS value you wish to change site-wide (e.g., the color of the type), use the "Property/Value" tab.
533
 
534
  = Query/Selector Tab =
535
 
536
  The Query/Selector tab lets you find specific CSS selectors and edit them. First, find the query that contains the CSS 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. CSS selectors are in the base query by default.
537
  Next, find the CSS selector by typing in the "Selector" autoselect box. Select by clicking with the mouse or by pressing the "Enter" or "Tab" keys.
538
 
539
+ This will load all of the properties for that CSS selector with the Parent values on the left and the child theme values inputs on the right. Any existing child theme 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.
540
 
541
  The "Order" field contains the original sequence of the CSS selector in the parent theme stylesheet. You can change the CSS selector order sequence by entering a lower or higher number in the "Order" field. You can also force style overrides (so called "!important" flag) by checking the "!" box next to each input. Please use judiciously.
542
 
544
 
545
  == Adding New Styles ==
546
 
547
+ If you wish to add additional properties to a given CSS selector, first load the selector using the Query/Selector tab. Then find the property you wish to override by typing in the New Property 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.
548
 
549
  If you wish to add completely new CSS selectors, or even new @media queries, you can enter free-form CSS in the "Raw CSS" textarea. Be aware that your syntax must be correct (i.e., balanced curly braces, etc.) for the parser to load the new styles. You will know it is invalid because a red "X" will appear next to the save button.
550
 
551
+ If you prefer to use shorthand syntax for properties and values instead of the inputs provided by the Child Theme Configurator, you can enter them here as well. The parser will convert your input into normalized CSS code automatically.
552
 
553
+ = Property/Value Tab =
554
 
555
+ The Property/Value tab lets you find specific values for a given property and then edit that value for individual CSS selectors that use that property/value combination. First, find the property you wish to override by typing in the Property autoselect box. Select by clicking with the mouse or by pressing the "Enter" or "Tab" keys.
556
 
557
+ This will load all of the unique values that exist for that property in the parent theme stylesheet with a Sample preview for that value. If there are values that exist in the child theme stylesheet that do not exist in the parent stylesheet, they will be displayed as well.
558
 
559
+ For each unique value, click the "Selectors" link to view a list of CSS selectors that use that property/value combination, grouped by query with a Sample preview of the value and inputs for the child theme value. Any existing child theme values will be automatically populated.
560
 
561
  Click "Save" to update the child theme stylesheet and save your changes to the WordPress admin.
562
 
563
+ If you want to edit all of the properties for the CSS selector you can click the “Edit” link and the CSS selector will automatically load in the Query/Selector Tab.
564
 
565
  == Web Fonts Tab ==
566
 
606
 
607
  == Caveats ==
608
 
609
+ * Arbitrary comments are not supported. Providing a high level of flexibility for previewing and modifying styles requires a sophisticated parsing system. Maintaining comments that bound to any particular element in the stylesheet is prohibitively expensive compared to the value it would add. Although we are working to include this as an option in the future, currently all comments are stripped from the child theme stylesheet code.
610
+ * Legacy gradient syntax is not supported. The Child Theme Configurator plugin does not support the MS filter gradient or legacy webkit gradient. These will continue to work if they are used in the parent theme, but will not be written to the child theme stylesheet. If there is a demand, we may add it in a future release, but most users should have upgraded by now.
611
  * 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.
612
  * 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.
613
+ * Not all CSS properties are customizable. The Child Theme Configurator plugin works with the vast majority of vendor-specific properties, however we’ve left out some of the more obscure options. As with legacy gradients, they will work, but will not be automatically enhanced by the Configurator.
614
+ * CSS properties are auto-discovered. The Child Theme Configurator plugin loads the properties that exist in the Parent stylesheet. You can always add new rules using the “Raw CSS” text area.
 
 
615
 
616
  == Documentation ==
617
 
618
+ Go to http://www.childthemeconfigurator.com/
619
 
620
  Serbo-Croatian translation courtesy of Borisa Djuraskovic borisad@webhostinghub.com http://www.webhostinghub.com
621
 
screenshot-1.jpg CHANGED
Binary file
screenshot-2.jpg CHANGED
Binary file
screenshot-3.jpg CHANGED
Binary file
screenshot-4.jpg CHANGED
Binary file
screenshot-5.jpg CHANGED
Binary file
screenshot-6.jpg CHANGED
Binary file
screenshot-7.jpg CHANGED
Binary file