WordPress Social Sharing Plugin – Social Warfare - Version 1.4.8

Version Description

Download this release

Release Info

Developer WarfarePlugins
Plugin Icon 128x128 WordPress Social Sharing Plugin – Social Warfare
Version 1.4.8
Comparing to
See all releases

Version 1.4.8

Files changed (115) hide show
  1. README.md +2 -0
  2. admin.js +118 -0
  3. css/admin.css +147 -0
  4. css/style.css +270 -0
  5. fonts/sw-icon-font.eot +0 -0
  6. fonts/sw-icon-font.svg +38 -0
  7. fonts/sw-icon-font.ttf +0 -0
  8. fonts/sw-icon-font.woff +0 -0
  9. functions/admin-page-class/admin-page-class.php +3634 -0
  10. functions/admin-page-class/css/Admin_Page_Class.css +534 -0
  11. functions/admin-page-class/css/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  12. functions/admin-page-class/css/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  13. functions/admin-page-class/css/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  14. functions/admin-page-class/css/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  15. functions/admin-page-class/css/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  16. functions/admin-page-class/css/images/ui-bg_glass_75_ffffff_1x400.png +0 -0
  17. functions/admin-page-class/css/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  18. functions/admin-page-class/css/images/ui-bg_inset-soft_95_fef1ec_1x100.png +0 -0
  19. functions/admin-page-class/css/images/ui-icons_222222_256x240.png +0 -0
  20. functions/admin-page-class/css/images/ui-icons_2e83ff_256x240.png +0 -0
  21. functions/admin-page-class/css/images/ui-icons_454545_256x240.png +0 -0
  22. functions/admin-page-class/css/images/ui-icons_888888_256x240.png +0 -0
  23. functions/admin-page-class/css/images/ui-icons_cd0a0a_256x240.png +0 -0
  24. functions/admin-page-class/css/images/ui-icons_f6cf3b_256x240.png +0 -0
  25. functions/admin-page-class/css/jquery-ui.css +1393 -0
  26. functions/admin-page-class/images/add.png +0 -0
  27. functions/admin-page-class/images/ajax-loader.gif +0 -0
  28. functions/admin-page-class/images/delete-16.png +0 -0
  29. functions/admin-page-class/images/edit.png +0 -0
  30. functions/admin-page-class/images/remove.png +0 -0
  31. functions/admin-page-class/js/Admin_Page_Class.js +1056 -0
  32. functions/admin-page-class/js/FancyCheckbox/FancyCheckbox.css +24 -0
  33. functions/admin-page-class/js/FancyCheckbox/FancyCheckbox.js +121 -0
  34. functions/admin-page-class/js/FancyCheckbox/FancyCheckbox.min.css +1 -0
  35. functions/admin-page-class/js/FancyCheckbox/FancyCheckbox.min.js +7 -0
  36. functions/admin-page-class/js/FancyCheckbox/images/firerift.png +0 -0
  37. functions/admin-page-class/js/FancyCheckbox/images/iphone.png +0 -0
  38. functions/admin-page-class/js/FancyCheckbox/images/on-off.png +0 -0
  39. functions/admin-page-class/js/codemirror/clike.js +234 -0
  40. functions/admin-page-class/js/codemirror/codemirror.css +107 -0
  41. functions/admin-page-class/js/codemirror/codemirror.js +2817 -0
  42. functions/admin-page-class/js/codemirror/css.js +124 -0
  43. functions/admin-page-class/js/codemirror/javascript.js +360 -0
  44. functions/admin-page-class/js/codemirror/php.js +121 -0
  45. functions/admin-page-class/js/codemirror/solarizedDark.css +19 -0
  46. functions/admin-page-class/js/codemirror/solarizedLight.css +19 -0
  47. functions/admin-page-class/js/codemirror/xml.js +260 -0
  48. functions/admin-page-class/js/plupload/myplupload.css +29 -0
  49. functions/admin-page-class/js/plupload/myplupload.js +140 -0
  50. functions/admin-page-class/js/select2/LICENSE +485 -0
  51. functions/admin-page-class/js/select2/select2-spinner.gif +0 -0
  52. functions/admin-page-class/js/select2/select2.css +533 -0
  53. functions/admin-page-class/js/select2/select2.js +2446 -0
  54. functions/admin-page-class/js/select2/select2.png +0 -0
  55. functions/admin-page-class/js/select2/select2x2.png +0 -0
  56. functions/admin-page-class/js/time-and-date/jquery-ui-timepicker-addon.js +1299 -0
  57. functions/admin-page-class/lang/default.mo +0 -0
  58. functions/admin-page-class/lang/default.po +317 -0
  59. functions/admin-page-class/lang/en_US.mo +0 -0
  60. functions/admin-page-class/lang/en_US.po +317 -0
  61. functions/admin-page-class/lang/es_ES.mo +0 -0
  62. functions/admin-page-class/lang/es_ES.po +326 -0
  63. functions/admin-page-class/lang/he_IL.mo +0 -0
  64. functions/admin-page-class/lang/he_IL.po +318 -0
  65. functions/admin-page-class/lang/pt_BR.mo +0 -0
  66. functions/admin-page-class/lang/pt_BR.po +326 -0
  67. functions/bitly.php +310 -0
  68. functions/buttons-floating.php +105 -0
  69. functions/buttons-standard.php +263 -0
  70. functions/click-to-tweet/assets/css/admin.css +13 -0
  71. functions/click-to-tweet/assets/css/style1.css +174 -0
  72. functions/click-to-tweet/assets/css/style2.css +172 -0
  73. functions/click-to-tweet/assets/css/style3.css +164 -0
  74. functions/click-to-tweet/assets/css/style4.css +167 -0
  75. functions/click-to-tweet/assets/css/styles.css +170 -0
  76. functions/click-to-tweet/assets/img/twitter-little-bird-button.png +0 -0
  77. functions/click-to-tweet/assets/img/twitter-little-bird-white.png +0 -0
  78. functions/click-to-tweet/assets/img/twitter-little-bird.png +0 -0
  79. functions/click-to-tweet/assets/js/clickToTweet.js +100 -0
  80. functions/click-to-tweet/assets/js/tmclicktotweet_plugin.js +27 -0
  81. functions/click-to-tweet/clickToTweet.php +99 -0
  82. functions/curl_functions.php +106 -0
  83. functions/excerpt.php +41 -0
  84. functions/header-meta-tags.php +660 -0
  85. functions/kilomega.php +70 -0
  86. functions/languages.php +216 -0
  87. functions/mobile-detection.php +12 -0
  88. functions/options-fetch.php +102 -0
  89. functions/options-page.php +1284 -0
  90. functions/permalinks.php +285 -0
  91. functions/post-options.php +175 -0
  92. functions/profile-fields.php +45 -0
  93. functions/registration.php +147 -0
  94. functions/share-count-class.php +102 -0
  95. functions/share-count-function.php +148 -0
  96. functions/social-networks/buffer.php +106 -0
  97. functions/social-networks/email.php +91 -0
  98. functions/social-networks/facebook.php +100 -0
  99. functions/social-networks/googlePlus.php +99 -0
  100. functions/social-networks/linkedIn.php +100 -0
  101. functions/social-networks/pinterest.php +157 -0
  102. functions/social-networks/pocket.php +86 -0
  103. functions/social-networks/reddit.php +126 -0
  104. functions/social-networks/stumbleupon.php +108 -0
  105. functions/social-networks/tumblr.php +107 -0
  106. functions/social-networks/twitter.php +172 -0
  107. functions/social-networks/whatsapp.php +101 -0
  108. functions/social-networks/yummly.php +120 -0
  109. functions/sw-shortcode-generator.js +49 -0
  110. functions/sw-shortcode-generator.php +68 -0
  111. functions/updates/composer.json +19 -0
  112. functions/updates/css/puc-debug-bar.css +62 -0
  113. functions/updates/debug-bar-panel.php +146 -0
  114. functions/updates/debug-bar-plugin.php +102 -0
  115. functions/updates/github-checker.php +336 -0
README.md ADDED
@@ -0,0 +1,2 @@
 
 
1
+ # Warfare Plugins / Social Warfare Repository and Issue Tracker
2
+ This is a public repository for the Social Warfare WordPress plugin created primarily for the purpose of publishing and maintaining a public list of bugs, known issues, and feature requests with the community at large. Please use the "Issues" link above to track or add information to existing issues or to submit new issues altogether.
admin.js ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Function for SM Title Counting
2
+ function smTitleRemaining() {
3
+ var smTitle = jQuery('#socialWarfare textarea#nc_ogTitle').val();
4
+ var remaining = 60 - smTitle.length;
5
+ if(smTitle.length > 0 && remaining >= 0) {
6
+ jQuery('#socialWarfare .nc_ogTitleWrapper .sw_CountDown').removeClass('sw_red').addClass('sw_blue');
7
+ } else if (smTitle.length > 0 && remaining < 0 ) {
8
+ jQuery('#socialWarfare .nc_ogTitleWrapper .sw_CountDown').removeClass('sw_blue').addClass('sw_red');
9
+ } else {
10
+ jQuery('#socialWarfare .nc_ogTitleWrapper .sw_CountDown').removeClass('sw_blue').removeClass('sw_red');
11
+ }
12
+ jQuery('#socialWarfare .nc_ogTitleWrapper .counterNumber').html(remaining);
13
+ }
14
+
15
+ // Function for SM Description Counting
16
+ function smDescriptionRemaining() {
17
+ var smDescription = jQuery('#socialWarfare textarea#nc_ogDescription').val();
18
+ var remaining = 160 - smDescription.length;
19
+ if(smDescription.length > 0 && remaining >= 0) {
20
+ jQuery('#socialWarfare .nc_ogDescriptionWrapper .sw_CountDown').removeClass('sw_red').addClass('sw_blue');
21
+ } else if (smDescription.length > 0 && remaining < 0 ) {
22
+ jQuery('#socialWarfare .nc_ogDescriptionWrapper .sw_CountDown').removeClass('sw_blue').addClass('sw_red');
23
+ } else {
24
+ jQuery('#socialWarfare .nc_ogDescriptionWrapper .sw_CountDown').removeClass('sw_blue').removeClass('sw_red');
25
+ }
26
+ jQuery('#socialWarfare .nc_ogDescriptionWrapper .counterNumber').html(remaining);
27
+ }
28
+
29
+ // Function for Twitter Box Counting
30
+ function twitterRemaining() {
31
+ var smTwitter = jQuery('#socialWarfare textarea#nc_customTweet').val();
32
+ var handle = jQuery('#socialWarfare .twitterID label').html();
33
+ if(smTwitter.indexOf('http') > -1) {
34
+ linkSpace = 0;
35
+ jQuery('.tweetLinkSection').css({'text-decoration':'line-through'});
36
+ } else {
37
+ linkSpace = 23;
38
+ jQuery('.tweetLinkSection').css({'text-decoration':'none'});
39
+ };
40
+ if(typeof handle === 'undefined') {
41
+ var remaining = 140 - getTweetLength(smTwitter) - linkSpace;
42
+ } else {
43
+ var remaining = 140 - getTweetLength(smTwitter) - handle.length - linkSpace - 6;
44
+ }
45
+ if(smTwitter.length > 0 && remaining >= 0) { jQuery('#socialWarfare .nc_customTweetWrapper .sw_CountDown').removeClass('sw_red').addClass('sw_blue');
46
+ } else if (smTwitter.length > 0 && remaining < 0 ) { jQuery('#socialWarfare .nc_customTweetWrapper .sw_CountDown').removeClass('sw_blue').addClass('sw_red');
47
+ } else { jQuery('#socialWarfare .nc_customTweetWrapper .sw_CountDown').removeClass('sw_blue').removeClass('sw_red'); }
48
+ jQuery('#socialWarfare .nc_customTweetWrapper .counterNumber').html(remaining);
49
+ }
50
+
51
+ function getTweetLength(input) {
52
+ var tmp = "";
53
+ for(var i = 0; i < 22; i++){tmp+="o"}
54
+ return input.replace(/(http:\/\/[\S]*)/g, tmp).length;
55
+ };
56
+
57
+ jQuery(document).ready( function() {
58
+ if(jQuery('#socialWarfare.postbox').length) {
59
+
60
+ // Add the CountDown Box for the Social Media Title
61
+ jQuery('#socialWarfare #nc_ogTitle').parent().prepend('<div class="sw_CountDown"><span class="counterNumber">60</span> Characters Remaining</div>');
62
+
63
+ // Add the CountDown Box for the Social Media Description
64
+ jQuery('#socialWarfare #nc_ogDescription').parent().prepend('<div class="sw_CountDown"><span class="counterNumber">150</span> Characters Remaining</div>');
65
+
66
+ // Add the CountDown Box for the Twitter Box
67
+ jQuery('#socialWarfare #nc_customTweet').parent().prepend('<div class="sw_CountDown"><span class="counterNumber">118</span> Characters Remaining</div>');
68
+
69
+ smTitleRemaining();
70
+ jQuery('#socialWarfare textarea#nc_ogTitle').on('input', function() { smTitleRemaining(); });
71
+
72
+ smDescriptionRemaining();
73
+ jQuery('#socialWarfare textarea#nc_ogDescription').on('input', function() { smDescriptionRemaining(); });
74
+
75
+ twitterRemaining();
76
+ jQuery('#socialWarfare textarea#nc_customTweet').on('input', function() { twitterRemaining(); });
77
+
78
+ // Setup an initilazation loop
79
+ var sw_post_initialization = setInterval( function() {
80
+
81
+ var sw_og_image = jQuery('.nc_ogImageWrapper ul.rwmb-media-list');
82
+ var sw_pin_image = jQuery('.nc_pinterestImageWrapper ul.rwmb-media-list');
83
+
84
+ // Check if the media list has been created yet
85
+ if(sw_og_image.length && sw_og_image.is(':empty')) {
86
+
87
+ // Setup the Open Graph Image Placeholder
88
+ var smWidth = sw_og_image.width();
89
+ var smHeight = smWidth * (9/16);
90
+ sw_og_image.css({height:smHeight+'px'});
91
+
92
+ } else {
93
+
94
+ var smHeight = sw_og_image.find('img').height();
95
+ sw_og_image.css({height:smHeight+'px'});
96
+
97
+ }
98
+
99
+ if(sw_pin_image.length && sw_pin_image.is(':empty')) {
100
+
101
+ // Setup the Open Graph Image Placeholder
102
+ var pinWidth = sw_pin_image.width();
103
+ var pinHeight = pinWidth * (3/2);
104
+ sw_pin_image.css({height:pinHeight+'px'});
105
+
106
+ } else {
107
+
108
+ var pinHeight = sw_pin_image.find('img').height();
109
+ sw_pin_image.css({height:pinHeight+'px'});
110
+
111
+ }
112
+
113
+
114
+ } , 1000 );
115
+
116
+ };
117
+
118
+ });
css/admin.css ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .ui-tabs-nav {
2
+ border-bottom: 1px solid #ccc;
3
+ height: 27px;
4
+ margin: 20px 0;
5
+ padding: 0;
6
+ }
7
+
8
+ .ui-tabs-nav li {
9
+ display: block;
10
+ float: left;
11
+ margin: 0;
12
+ }
13
+
14
+ .ui-tabs-nav li a {
15
+ padding: 4px 20px 6px;
16
+ font-weight: bold;
17
+ }
18
+
19
+ .ui-tabs-nav li a {
20
+ border-style: solid;
21
+ border-color: #CCC #CCC #F9F9F9;
22
+ border-width: 1px 1px 0;
23
+ color: #C1C1C1;
24
+ text-shadow: rgba(255, 255, 255, 1) 0 1px 0;
25
+ display: inline-block;
26
+ padding: 4px 14px 6px;
27
+ text-decoration: none;
28
+ margin: 0 6px -1px 0;
29
+ -moz-border-radius: 5px 5px 0 0;
30
+ -webkit-border-top-left-radius: 5px;
31
+ -webkit-border-top-right-radius: 5px;
32
+ -khtml-border-top-left-radius: 5px;
33
+ -khtml-border-top-right-radius: 5px;
34
+ border-top-left-radius: 5px;
35
+ border-top-right-radius: 5px;
36
+ }
37
+
38
+ .ui-tabs-nav li.ui-tabs-selected a,
39
+ .ui-tabs-nav li.ui-state-active a {
40
+ border-width: 1px;
41
+ color: #464646;
42
+ }
43
+
44
+ .ui-tabs-panel {
45
+ clear: both;
46
+ }
47
+
48
+ .ui-tabs-panel h3 {
49
+ font: italic normal normal 24px/29px Georgia,"Times New Roman","Bitstream Charter",Times,serif;
50
+ margin: 0;
51
+ padding: 0 0 5px;
52
+ line-height: 35px;
53
+ text-shadow: 0 1px 0 #fff;
54
+ }
55
+
56
+ .ui-tabs-panel h4 {
57
+ font-size: 15px;
58
+ font-weight: bold;
59
+ margin: 1em 0;
60
+ }
61
+ .notAvailable {
62
+ opacity:0.3;
63
+ }
64
+ .sw_CountDown {
65
+ background-color: #CCC;
66
+ display: inline-block;
67
+ float: right;
68
+ padding: 5px 15px;
69
+ border-radius: 3px 3px 0 0;
70
+ color: #FFF;
71
+ font-weight: bold;
72
+ margin-top:-27px;
73
+ }
74
+ .sw_CountDown.sw_blue {
75
+ background-color:#30394F;
76
+ }
77
+ .sw_CountDown.sw_red {
78
+ background-color:#EE464F;
79
+ }
80
+ #socialWarfare textarea.large-text {
81
+ width:100%;
82
+ }
83
+
84
+ #socialWarfare ul.rwmb-media-list.ui-sortable {
85
+ display: block;
86
+ width: 100%;
87
+ background-size: contain;
88
+ background-position-x: center;
89
+ background-repeat: no-repeat;
90
+ background-color: #ccc;
91
+ border-radius:4px;
92
+ }
93
+ #socialWarfare .nc_ogImageWrapper ul.rwmb-media-list {
94
+ background-image: url('../images/img-placeholder-og.jpg');
95
+ }
96
+ #socialWarfare .nc_pinterestImageWrapper ul.rwmb-media-list {
97
+ background-image: url('../images/img-placeholder-pin.jpg');
98
+ }
99
+
100
+ .rwmb-field.rwmb-textarea-wrapper.nc_ogTitleWrapper, .rwmb-field.rwmb-textarea-wrapper.nc_ogDescriptionWrapper, .rwmb-field.rwmb-textarea-wrapper.nc_pinterestDescriptionWrapper, .rwmb-field.rwmb-textarea-wrapper.nc_customTweetWrapper, .rwmb-field.rwmb-select-wrapper.nc_postLocationWrapper, .rwmb-field.rwmb-select-wrapper.nc_floatLocationWrapper {
101
+ width: 63%;
102
+ float: left;
103
+ }
104
+
105
+ .rwmb-field.rwmb-image_advanced-wrapper.nc_ogImageWrapper, .rwmb-field.rwmb-image_advanced-wrapper.nc_pinterestImageWrapper {
106
+ width: 30%;
107
+ float: left;
108
+ margin-right: 3%;
109
+ }
110
+ #socialWarfare .rwmb-label, #socialWarfare .rwmb-input {width:100%;}
111
+ #socialWarfare .rwmb-field {margin-top:10px;}
112
+ #socialWarfare .rwmb-image-item, #socialWarfare .rwmb-media-preview, #socialWarfare .rwmb-media-content .centered, #socialWarfare .rwmb-media-content img {width:100%;height:auto;max-height:none;}
113
+ .wp-core-ui #socialWarfare a.rwmb-add-media.button {
114
+ display: block;
115
+ background: #30394f;
116
+ color: #fff;
117
+ font-size: 12px;
118
+ line-height: 1;
119
+ text-align: center;
120
+ vertical-align: middle;
121
+ padding: 15px 25px;
122
+ margin: 0;
123
+ box-shadow: none;
124
+ border: none;
125
+ height: auto;
126
+ }
127
+ .wp-core-ui #socialWarfare a.rwmb-add-media.button:hover {
128
+ background: #EE464F;
129
+ }
130
+
131
+ #socialWarfare .rwmb-media-content img {
132
+ -webkit-transform: translate(0%, 0%); */
133
+ -ms-transform: translate(0%, 0%);
134
+ transform: translate(0%, 0%); */
135
+ }
136
+ #socialWarfare .rwmb-media-content {overflow:visible;}
137
+ #socialWarfare .rwmb-media-preview:before {padding-top:0px;}
138
+ #socialWarfare .rwmb-media-content {position:inherit;}
139
+ #socialWarfare .rwmb-divider-wrapper hr {border:none!important}
140
+ #socialWarfare .rwmb-label label {
141
+ font-weight: bold;
142
+ color: #30394f;
143
+ font-size: 18px;
144
+ }
145
+ #socialWarfare .rwmb-label { margin-bottom:10px; }
146
+ #socialWarfare h2.hndle span:before {content:'p';margin-right:10px;font-family:"sw-icon-font";vertical-align:middle;}
147
+ #socialWarfare .dashicons, #socialWarfare .sw {vertical-align:middle;margin-right:10px;font-size:18px;}
css/style.css ADDED
@@ -0,0 +1,270 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Global Styles */
2
+ .nc_socialPanel {clear: both;width: 100%!important;margin-top:20px!important;margin-bottom:20px!important;height: 30px;padding: 0;line-height:1;}
3
+ .nc_wrapper .nc_socialPanel {margin-top:10px!important;margin-bottom:10px!important;}
4
+ div.nc_socialPanel .nc_tweetContainer {float:left;margin:0 5px;cursor:pointer;height:32px;font-family: 'Lato';border-radius:2px;transition:all 0.1s linear;border-size:1px;}
5
+ .nc_socialPanel .nc_tweetContainer a.nc_tweet, .nc_socialPanel .totes .sw_count {display: block;font-size: 18px!important;font-family: 'Lato', sans-serif;font-weight: bold;text-decoration: none;height:30px;text-transform:none;}
6
+ .nc_socialPanel a .sw_count {padding: 0;line-height: 32px;display:inline-block;}
7
+ .nc_socialPanel span:before {content:initial!important}
8
+ .nc_socialPanel .totes .sw_count {line-height:30px;}
9
+ .nc_socialPanel .spaceManWilly {display:block;max-width:none!important}
10
+ .nc_socialPanel span.sw_count {font-size:14px;}
11
+ .nc_socialPanel span.iconFiller {font-size: 18px;}
12
+ /* Adjusted Margins for First and Last Elements */
13
+ .nc_socialPanel.notMobile .nc_tweetContainer:nth-child(1) {margin-left:0;}
14
+ .nc_socialPanel.notMobile .nc_tweetContainer:nth-last-child(1) {margin-right:0;}
15
+ .nc_socialPanel:not(.nc_socialPanelSide) {opacity:0; transition: opacity .2s ease-in-out;}
16
+ .nc_socialPanel:not(.nc_socialPanelSide) div.totes.totesalt:nth-child(1) {margin-left:0;padding-left:0;margin-right:15px;}
17
+ .nc_socialPanel:not(.nc_socialPanelSide) div.totes.totesalt:nth-last-child(1) {margin-right:0px;padding-right:0px;}
18
+ /* Click to Tweet Cursor */
19
+ a.sw_CTT {cursor:pointer;}
20
+ /* Icons and Calls to Action */
21
+ span.sw_share {font-weight: normal;font-size: 14px;display:block;height: 30px;vertical-align: middle;line-height: 30px;float:right;max-width:none!important;}
22
+ .nc_socialPanel .sw {margin: 0 7px;height: 30px;line-height: 32px; text-shadow:none!important;width:20px;}
23
+ /* Default Icon Settings */
24
+ .iconFiller {display:block;float:left;transition: width .1s linear;overflow:hidden;height:30px}
25
+ .nc_socialPanel .iconFiller {width: 30px;}
26
+ /* Mobile Fix */
27
+ .mobile .nc_tweetContainer:nth-last-child(2), .nc_tweetContainer.totes:nth-last-child(1) {margin-right:0;}
28
+ /* Total Shares */
29
+ .nc_socialPanel .totes {color:white;padding:0px 10px;display:block;font-size:19px;cursor:default;background:#c4c4c4;border:1px solid #e08a0f;border-radius:2px;}
30
+ .nc_socialPanel div.totes.totesalt, .nc_socialPanel:hover div.totes.totesalt:not(:nth-child(1)) {background:transparent!important;color:#474B4D;margin-left:10px;border:none;}
31
+ div.nc_socialPanel:hover div.totes.totesalt:not(:nth-child(1)) {background:transparent;color:#474B4D;margin-left:10px;}
32
+ .nc_socialPanel .totes.totesalt .sw_label {font-size:10px;color:#474B4D;vertical-align:middle;}
33
+ .nc_socialPanel .totes .sw_label {font-size:10px;vertical-align:middle;}
34
+ .nc_socialPanel .totes.totesalt .sw_count {color:#474B4D;font-size:24px;}
35
+ .nc_socialPanel:hover .totes, .nc_socialPanel.sw_fullColor .totes, .nc_socialPanel.sw_fade .totes, .nc_socialPanel.sw_customFull:hover div.totes {background:#e08a0f;}
36
+ .nc_socialPanel:not(.nc_socialPanelSide) .nc_tweetContainer.totes.totesalt:before {content: "o";font-family: "sw-icon-font";display: inline-block;vertical-align: top;margin-top: 7px;}
37
+ .nc_socialPanel div.totes.totesalt, .nc_socialPanel:hover div.totes.totesalt:not(:nth-child(1)) {margin-left: 0 !important;}
38
+ .nc_socialPanel:not(.nc_socialPanelSide) .totes.totesalt .sw_count {line-height: 0;margin-top: 12px;display: inline-block;vertical-align: middle;margin-left:10px;min-width:35px;}
39
+ span.sw_label {display: block;position: absolute;margin-top: 13px;text-transform: uppercase;font-size: 9px !important;text-align: center !important;}
40
+ .nc_socialPanelSide span.sw_label {margin-top:0;}
41
+ /* Button Shapes */
42
+ .nc_socialPanel.sw_leaf .nc_tweetContainer {border-radius:15px 0;border-width:1px;}
43
+ .nc_socialPanel.sw_pill .nc_tweetContainer {border-radius:50px; border-width:1px;}
44
+ .nc_socialPanel.sw_shift .nc_tweetContainer:not(.totes) {border-width:1px;-webkit-transform:skew(-25deg);-moz-transform:skew(-25deg);-o-transform:skew(-25deg); }
45
+ .nc_socialPanel.sw_shift .nc_tweetContainer a {-webkit-transform:skew(25deg);-moz-transform:skew(25deg);-o-transform:skew(25deg); }
46
+ .sw_connected .nc_tweetContainer, .sw_connected:hover .nc_tweetContainer, .sw_connected .nc_tweetContainer:hover {margin:0!important;border-radius:0!important;border-width:1px;}
47
+ /*Flash & Fresh Outlines */
48
+ .nc_socialPanel.sw_flatFresh.sw_d_fullColor .googlePlus, html body .nc_socialPanel.sw_flatFresh.sw_i_fullColor .googlePlus:hover, body .nc_socialPanel.sw_flatFresh.sw_o_fullColor:hover .googlePlus {border:1px solid #df4b37;}
49
+ .nc_socialPanel.sw_flatFresh.sw_d_fullColor .twitter, html body .nc_socialPanel.sw_flatFresh.sw_i_fullColor .twitter:hover, body .nc_socialPanel.sw_flatFresh.sw_o_fullColor:hover .twitter {border:1px solid #429cd6;}
50
+ .nc_socialPanel.sw_flatFresh.sw_d_fullColor .fb, html body .nc_socialPanel.sw_flatFresh.sw_i_fullColor .fb:hover, body .nc_socialPanel.sw_flatFresh.sw_o_fullColor:hover .fb {border:1px solid #3a589e;}
51
+ .nc_socialPanel.sw_flatFresh.sw_d_fullColor .nc_pinterest, html body .nc_socialPanel.sw_flatFresh.sw_i_fullColor .nc_pinterest:hover, body .nc_socialPanel.sw_flatFresh.sw_o_fullColor:hover .nc_pinterest {border:1px solid #cd2029;}
52
+ .nc_socialPanel.sw_flatFresh.sw_d_fullColor .linkedIn, html body .nc_socialPanel.sw_flatFresh.sw_i_fullColor .linkedIn:hover, body .nc_socialPanel.sw_flatFresh.sw_o_fullColor:hover .linkedIn {border:1px solid #0d77b7;}
53
+ .nc_socialPanel.sw_flatFresh.sw_d_fullColor .sw_tumblr, html body .nc_socialPanel.sw_flatFresh.sw_i_fullColor .sw_tumblr:hover, body .nc_socialPanel.sw_flatFresh.sw_o_fullColor:hover .sw_tumblr {border:1px solid #39475d;}
54
+ .nc_socialPanel.sw_flatFresh.sw_d_fullColor .sw_stumbleupon, html body .nc_socialPanel.sw_flatFresh.sw_i_fullColor .sw_stumbleupon:hover, body .nc_socialPanel.sw_flatFresh.sw_o_fullColor:hover .sw_stumbleupon {border:1px solid #ef5025;}
55
+ .nc_socialPanel.sw_flatFresh.sw_d_fullColor .sw_yummly, html body .nc_socialPanel.sw_flatFresh.sw_i_fullColor .sw_yummly:hover, body .nc_socialPanel.sw_flatFresh.sw_o_fullColor:hover .sw_yummly {border:1px solid #e26426;}
56
+ .nc_socialPanel.sw_flatFresh.sw_d_fullColor .sw_reddit, html body .nc_socialPanel.sw_flatFresh.sw_i_fullColor .sw_reddit:hover, body .nc_socialPanel.sw_flatFresh.sw_o_fullColor:hover .sw_reddit {border:1px solid #f04b23;}
57
+ .nc_socialPanel.sw_flatFresh.sw_d_fullColor .sw_email, html body .nc_socialPanel.sw_flatFresh.sw_i_fullColor .sw_email:hover, body .nc_socialPanel.sw_flatFresh.sw_o_fullColor:hover .sw_email {border:1px solid #6bcce9;}
58
+ .nc_socialPanel.sw_flatFresh.sw_d_fullColor .sw_whatsapp, html body .nc_socialPanel.sw_flatFresh.sw_i_fullColor .sw_whatsapp:hover, body .nc_socialPanel.sw_flatFresh.sw_o_fullColor:hover .sw_whatsapp {border:1px solid #71c169;}
59
+ .nc_socialPanel.sw_flatFresh.sw_d_fullColor .sw_pocket, html body .nc_socialPanel.sw_flatFresh.sw_i_fullColor .sw_pocket:hover, body .nc_socialPanel.sw_flatFresh.sw_o_fullColor:hover .sw_pocket {border:1px solid #ef4056;}
60
+ .nc_socialPanel.sw_flatFresh.sw_d_fullColor .sw_buffer, html body .nc_socialPanel.sw_flatFresh.sw_i_fullColor .sw_buffer:hover, body .nc_socialPanel.sw_flatFresh.sw_o_fullColor:hover .sw_buffer {border:1px solid #323b43;}
61
+ /* Full Color */
62
+ .nc_socialPanel.sw_d_fullColor a, html body .nc_socialPanel.sw_i_fullColor .nc_tweetContainer:hover a, body .nc_socialPanel.sw_o_fullColor:hover a {color:white;}
63
+ .nc_socialPanel.sw_d_fullColor .googlePlus, html body .nc_socialPanel.sw_i_fullColor .googlePlus:hover, body .nc_socialPanel.sw_o_fullColor:hover .googlePlus {background:#df4b37;border:1px solid #c44133;}
64
+ .nc_socialPanel.sw_d_fullColor .twitter, html body .nc_socialPanel.sw_i_fullColor .twitter:hover, body .nc_socialPanel.sw_o_fullColor:hover .twitter {background:#429cd6;border:1px solid #3c87b2;}
65
+ .nc_socialPanel.sw_d_fullColor .fb, html body .nc_socialPanel.sw_i_fullColor .fb:hover, body .nc_socialPanel.sw_o_fullColor:hover .fb {background:#3a589e;border:1px solid #2e4675;}
66
+ .nc_socialPanel.sw_d_fullColor .nc_pinterest, html body .nc_socialPanel.sw_i_fullColor .nc_pinterest:hover, body .nc_socialPanel.sw_o_fullColor:hover .nc_pinterest {background:#cd2029;border:1px solid #aa1b29;}
67
+ .nc_socialPanel.sw_d_fullColor .linkedIn, html body .nc_socialPanel.sw_i_fullColor .linkedIn:hover, body .nc_socialPanel.sw_o_fullColor:hover .linkedIn {background:#0d77b7;border:1px solid #0c6591;}
68
+ .nc_socialPanel.sw_d_fullColor .sw_tumblr, html body .nc_socialPanel.sw_i_fullColor .sw_tumblr:hover, body .nc_socialPanel.sw_o_fullColor:hover .sw_tumblr {background:#39475d;border:1px solid #27313f;}
69
+ .nc_socialPanel.sw_d_fullColor .sw_stumbleupon, html body .nc_socialPanel.sw_i_fullColor .sw_stumbleupon:hover, body .nc_socialPanel.sw_o_fullColor:hover .sw_stumbleupon {background:#ef5025;border:1px solid #d34427;}
70
+ .nc_socialPanel.sw_d_fullColor .sw_yummly, html body .nc_socialPanel.sw_i_fullColor .sw_yummly:hover, body .nc_socialPanel.sw_o_fullColor:hover .sw_yummly {background:#e26426;border:1px solid #b65027;}
71
+ .nc_socialPanel.sw_d_fullColor .sw_reddit, html body .nc_socialPanel.sw_i_fullColor .sw_reddit:hover, body .nc_socialPanel.sw_o_fullColor:hover .sw_reddit {background:#f04b23;border:1px solid #d33f27;}
72
+ .nc_socialPanel.sw_d_fullColor .sw_email, html body .nc_socialPanel.sw_i_fullColor .sw_email:hover, body .nc_socialPanel.sw_o_fullColor:hover .sw_email {background:#6bcce9;border:1px solid #61bace;}
73
+ .nc_socialPanel.sw_d_fullColor .sw_whatsapp, html body .nc_socialPanel.sw_i_fullColor .sw_whatsapp:hover, body .nc_socialPanel.sw_o_fullColor:hover .sw_whatsapp {background:#71c169;border:1px solid #28b04b;}
74
+ .nc_socialPanel.sw_d_fullColor .sw_pocket, html body .nc_socialPanel.sw_i_fullColor .sw_pocket:hover, body .nc_socialPanel.sw_o_fullColor:hover .sw_pocket {background:#ef4056;border:1px solid #ce3d55;}
75
+ .nc_socialPanel.sw_d_fullColor .sw_buffer, html body .nc_socialPanel.sw_i_fullColor .sw_buffer:hover, body .nc_socialPanel.sw_o_fullColor:hover .sw_buffer {background:#323b43;border:1px solid #59626a;}
76
+ /* Three Dee */
77
+ .nc_socialPanel.sw_threeDee.sw_d_fullColor .googlePlus, html body .nc_socialPanel.sw_threeDee.sw_i_fullColor .googlePlus:hover, body .nc_socialPanel.sw_threeDee.sw_o_fullColor:hover .googlePlus {border-bottom:3px solid #c44133;}
78
+ .nc_socialPanel.sw_threeDee.sw_d_fullColor .twitter, html body .nc_socialPanel.sw_threeDee.sw_i_fullColor .twitter:hover, body .nc_socialPanel.sw_threeDee.sw_o_fullColor:hover .twitter {border-bottom:3px solid #5595bc;}
79
+ .nc_socialPanel.sw_threeDee.sw_d_fullColor .fb, html body .nc_socialPanel.sw_threeDee.sw_i_fullColor .fb:hover, body .nc_socialPanel.sw_threeDee.sw_o_fullColor:hover .fb {border-bottom:3px solid #2e4675;}
80
+ .nc_socialPanel.sw_threeDee.sw_d_fullColor .nc_pinterest, html body .nc_socialPanel.sw_threeDee.sw_i_fullColor .nc_pinterest:hover, body .nc_socialPanel.sw_threeDee.sw_o_fullColor:hover .nc_pinterest {border-bottom:3px solid #aa1b29;}
81
+ .nc_socialPanel.sw_threeDee.sw_d_fullColor .linkedIn, html body .nc_socialPanel.sw_threeDee.sw_i_fullColor .linkedIn:hover, body .nc_socialPanel.sw_threeDee.sw_o_fullColor:hover .linkedIn {border-bottom:3px solid #0c6591;}
82
+ .nc_socialPanel.sw_threeDee.sw_d_fullColor .sw_tumblr, html body .nc_socialPanel.sw_threeDee.sw_i_fullColor .sw_tumblr:hover, body .nc_socialPanel.sw_threeDee.sw_o_fullColor:hover .sw_tumblr {border-bottom:3px solid #27313f;}
83
+ .nc_socialPanel.sw_threeDee.sw_d_fullColor .sw_stumbleupon, html body .nc_socialPanel.sw_threeDee.sw_i_fullColor .sw_stumbleupon:hover, body .nc_socialPanel.sw_threeDee.sw_o_fullColor:hover .sw_stumbleupon {border-bottom:3px solid #d34427;}
84
+ .nc_socialPanel.sw_threeDee.sw_d_fullColor .sw_yummly, html body .nc_socialPanel.sw_threeDee.sw_i_fullColor .sw_yummly:hover, body .nc_socialPanel.sw_threeDee.sw_o_fullColor:hover .sw_yummly {border-bottom:3px solid #b65027;}
85
+ .nc_socialPanel.sw_threeDee.sw_d_fullColor .sw_reddit, html body .nc_socialPanel.sw_threeDee.sw_i_fullColor .sw_reddit:hover, body .nc_socialPanel.sw_threeDee.sw_o_fullColor:hover .sw_reddit {border-bottom:3px solid #d33f27;}
86
+ .nc_socialPanel.sw_threeDee.sw_d_fullColor .sw_email, html body .nc_socialPanel.sw_threeDee.sw_i_fullColor .sw_email:hover, body .nc_socialPanel.sw_threeDee.sw_o_fullColor:hover .sw_email {border-bottom:3px solid #61bace;}
87
+ .nc_socialPanel.sw_threeDee.sw_d_fullColor .sw_whatsapp, html body .nc_socialPanel.sw_threeDee.sw_i_fullColor .sw_whatsapp:hover, body .nc_socialPanel.sw_threeDee.sw_o_fullColor:hover .sw_whatsapp {border-bottom:3px solid #28b04b;}
88
+ .nc_socialPanel.sw_threeDee.sw_d_fullColor .sw_pocket, html body .nc_socialPanel.sw_threeDee.sw_i_fullColor .sw_pocket:hover, body .nc_socialPanel.sw_threeDee.sw_o_fullColor:hover .sw_pocket {border-bottom:3px solid #ce3d55;}
89
+ .nc_socialPanel.sw_threeDee.sw_d_fullColor .sw_buffer, html body .nc_socialPanel.sw_threeDee.sw_i_fullColor .sw_buffer:hover, body .nc_socialPanel.sw_threeDee.sw_o_fullColor:hover .sw_buffer {border-bottom:3px solid #59626a;}
90
+
91
+ /* Light Gray */
92
+ .nc_socialPanel.sw_d_lightGray a, html body .nc_socialPanel.sw_i_lightGray .nc_tweetContainer:hover a, body .nc_socialPanel.sw_o_lightGray:hover a {color:white}
93
+ .nc_socialPanel.sw_d_lightGray .nc_tweetContainer, html body .nc_socialPanel.sw_i_lightGray .nc_tweetContainer:hover, body .nc_socialPanel.sw_o_lightGray:hover .nc_tweetContainer {background-color:#ccc;border:1px solid #ccc;}
94
+ .nc_socialPanel.sw_threeDee.sw_d_lightGray .nc_tweetContainer:not(.totesalt), html body .nc_socialPanel.sw_threeDee.sw_i_lightGray .nc_tweetContainer:not(.totesalt):hover, body .nc_socialPanel.sw_threeDee.sw_o_lightGray:hover .nc_tweetContainer:not(.totesalt) {border-bottom:3px solid #999;}
95
+ /* Medium Gray */
96
+ .nc_socialPanel.sw_d_mediumGray a, html body .nc_socialPanel.sw_i_mediumGray a:hover, body .nc_socialPanel.sw_o_mediumGray:hover a {color:white;}
97
+ .nc_socialPanel.sw_d_mediumGray .nc_tweetContainer, html body .nc_socialPanel.sw_i_mediumGray .nc_tweetContainer:hover, body .nc_socialPanel.sw_o_mediumGray:hover .nc_tweetContainer {background-color:#999;border:1px solid #999}
98
+ .nc_socialPanel.sw_threeDee.sw_d_mediumGray .nc_tweetContainer:not(.totesalt), html body .nc_socialPanel.sw_threeDee.sw_i_mediumGray .nc_tweetContainer:not(.totesalt):hover, body .nc_socialPanel.sw_threeDee.sw_o_mediumGray:hover .nc_tweetContainer:not(.totesalt) {border-bottom:3px solid #444}
99
+ /* Dark Gray */
100
+ .nc_socialPanel.sw_d_darkGray a, html body .nc_socialPanel.sw_i_darkGray a:hover, body .nc_socialPanel.sw_o_darkGray:hover a {color:white;}
101
+ .nc_socialPanel.sw_d_darkGray .nc_tweetContainer, html body .nc_socialPanel.sw_i_darkGray .nc_tweetContainer:hover, body .nc_socialPanel.sw_o_darkGray:hover .nc_tweetContainer {background-color:#444;border:1px solid #444}
102
+ .nc_socialPanel.sw_threeDee.sw_d_darkGray .nc_tweetContainer:not(.totesalt), html body .nc_socialPanel.sw_threeDee.sw_i_darkGray .nc_tweetContainer:not(.totesalt):hover, body .nc_socialPanel.sw_threeDee.sw_o_darkGray:hover .nc_tweetContainer:not(.totesalt) {border-bottom:3px solid #222}
103
+ /* Light Gray Outlines */
104
+ .nc_socialPanel.sw_d_lgOutlines a, html body .nc_socialPanel.sw_i_lgOutlines a:hover, body .nc_socialPanel.sw_o_lgOutlines:hover a { color:#ccc }
105
+ .nc_socialPanel.sw_d_lgOutlines .nc_tweetContainer, html body .nc_socialPanel.sw_i_lgOutlines .nc_tweetContainer:hover, body .nc_socialPanel.sw_o_lgOutlines:hover .nc_tweetContainer { background:transparent; border:1px solid #ccc; }
106
+ /* Medium Gray Outlines */
107
+ .nc_socialPanel.sw_d_mdOutlines a, html body .nc_socialPanel.sw_i_mdOutlines a:hover, body .nc_socialPanel.sw_o_mdOutlines:hover a { color:#999 }
108
+ .nc_socialPanel.sw_d_mdOutlines .nc_tweetContainer, html body .nc_socialPanel.sw_i_mdOutlines .nc_tweetContainer:hover, body .nc_socialPanel.sw_o_mdOutlines:hover .nc_tweetContainer { background:transparent; border:1px solid #999; }
109
+ /* Dark Gray Outlines */
110
+ .nc_socialPanel.sw_d_dgOutlines a, html body .nc_socialPanel.sw_i_dgOutlines a:hover, body .nc_socialPanel.sw_o_dgOutlines:hover a { color:#444 }
111
+ .nc_socialPanel.sw_d_dgOutlines .nc_tweetContainer, html body .nc_socialPanel.sw_i_dgOutlines .nc_tweetContainer:hover, body .nc_socialPanel.sw_o_dgOutlines:hover .nc_tweetContainer { background:transparent; border:1px solid #444; }
112
+ /* Color Outlines */
113
+ .nc_socialPanel.sw_d_colorOutlines .googlePlus a, html body .nc_socialPanel.sw_i_colorOutlines .googlePlus a:hover, body .nc_socialPanel.sw_o_colorOutlines:hover .googlePlus a {color:#df4b37;}
114
+ .nc_socialPanel.sw_d_colorOutlines .twitter a, html body .nc_socialPanel.sw_i_colorOutlines .twitter a:hover, body .nc_socialPanel.sw_o_colorOutlines:hover .twitter a {color:#429cd6;}
115
+ .nc_socialPanel.sw_d_colorOutlines .fb a, html body .nc_socialPanel.sw_i_colorOutlines .fb a:hover, body .nc_socialPanel.sw_o_colorOutlines:hover .fb a {color:#3a589e;}
116
+ .nc_socialPanel.sw_d_colorOutlines .nc_pinterest a, html body .nc_socialPanel.sw_i_colorOutlines .nc_pinterest a:hover, body .nc_socialPanel.sw_o_colorOutlines:hover .nc_pinterest a {color:#cd2029;}
117
+ .nc_socialPanel.sw_d_colorOutlines .linkedIn a, html body .nc_socialPanel.sw_i_colorOutlines .linkedIn a:hover, body .nc_socialPanel.sw_o_colorOutlines:hover .linkedIn a {color:#0d77b7;}
118
+ .nc_socialPanel.sw_d_colorOutlines .sw_tumblr a, html body .nc_socialPanel.sw_i_colorOutlines .sw_tumblr a:hover, body .nc_socialPanel.sw_o_colorOutlines:hover .sw_tumblr a {color:#39475d;}
119
+ .nc_socialPanel.sw_d_colorOutlines .sw_stumbleupon a, html body .nc_socialPanel.sw_i_colorOutlines .sw_stumbleupon a:hover, body .nc_socialPanel.sw_o_colorOutlines:hover .sw_stumbleupon a {color:#ef5025;}
120
+ .nc_socialPanel.sw_d_colorOutlines .sw_yummly a, html body .nc_socialPanel.sw_i_colorOutlines .sw_yummly a:hover, body .nc_socialPanel.sw_o_colorOutlines:hover .sw_yummly a {color:#e26426;}
121
+ .nc_socialPanel.sw_d_colorOutlines .sw_whatsapp a, html body .nc_socialPanel.sw_i_colorOutlines .sw_whatsapp a:hover, body .nc_socialPanel.sw_o_colorOutlines:hover .sw_whatsapp a {color:#71c169;}
122
+ .nc_socialPanel.sw_d_colorOutlines .sw_pocket a, html body .nc_socialPanel.sw_i_colorOutlines .sw_pocket a:hover, body .nc_socialPanel.sw_o_colorOutlines:hover .sw_pocket a {color:#ef4056;}
123
+ .nc_socialPanel.sw_d_colorOutlines .sw_reddit a, html body .nc_socialPanel.sw_i_colorOutlines .sw_reddit a:hover, body .nc_socialPanel.sw_o_colorOutlines:hover .sw_reddit a {color:#f04b23;}
124
+ .nc_socialPanel.sw_d_colorOutlines .sw_email a, html body .nc_socialPanel.sw_i_colorOutlines .sw_email a:hover, body .nc_socialPanel.sw_o_colorOutlines:hover .sw_email a {color:#6bcce9;}
125
+ .nc_socialPanel.sw_d_colorOutlines .sw_buffer a, html body .nc_socialPanel.sw_i_colorOutlines .sw_buffer a:hover, body .nc_socialPanel.sw_o_colorOutlines:hover .sw_buffer a {color:#323b43;}
126
+ /* Color Outlines */
127
+ .nc_socialPanel.sw_d_colorOutlines .googlePlus, html body .nc_socialPanel.sw_i_colorOutlines .googlePlus:hover, body .nc_socialPanel.sw_o_colorOutlines:hover .googlePlus {background:transparent;border:1px solid #df4b37;}
128
+ .nc_socialPanel.sw_d_colorOutlines .twitter, html body .nc_socialPanel.sw_i_colorOutlines .twitter:hover, body .nc_socialPanel.sw_o_colorOutlines:hover .twitter {background:transparent;border:1px solid #429cd6;}
129
+ .nc_socialPanel.sw_d_colorOutlines .fb, html body .nc_socialPanel.sw_i_colorOutlines .fb:hover, body .nc_socialPanel.sw_o_colorOutlines:hover .fb {background:transparent;border:1px solid #3a589e;}
130
+ .nc_socialPanel.sw_d_colorOutlines .nc_pinterest, html body .nc_socialPanel.sw_i_colorOutlines .nc_pinterest:hover, body .nc_socialPanel.sw_o_colorOutlines:hover .nc_pinterest {background:transparent;border:1px solid #cd2029;}
131
+ .nc_socialPanel.sw_d_colorOutlines .linkedIn, html body .nc_socialPanel.sw_i_colorOutlines .linkedIn:hover, body .nc_socialPanel.sw_o_colorOutlines:hover .linkedIn {background:transparent;border:1px solid #0d77b7;}
132
+ .nc_socialPanel.sw_d_colorOutlines .sw_tumblr, html body .nc_socialPanel.sw_i_colorOutlines .sw_tumblr:hover, body .nc_socialPanel.sw_o_colorOutlines:hover .sw_tumblr {background:transparent;border:1px solid #39475d;}
133
+ .nc_socialPanel.sw_d_colorOutlines .sw_stumbleupon, html body .nc_socialPanel.sw_i_colorOutlines .sw_stumbleupon:hover, body .nc_socialPanel.sw_o_colorOutlines:hover .sw_stumbleupon {background:transparent;border:1px solid #ef5025;}
134
+ .nc_socialPanel.sw_d_colorOutlines .sw_yummly, html body .nc_socialPanel.sw_i_colorOutlines .sw_yummly:hover, body .nc_socialPanel.sw_o_colorOutlines:hover .sw_yummly {background:transparent;border:1px solid #e26426;}
135
+ .nc_socialPanel.sw_d_colorOutlines .sw_whatsapp, html body .nc_socialPanel.sw_i_colorOutlines .sw_whatsapp:hover, body .nc_socialPanel.sw_o_colorOutlines:hover .sw_whatsapp {background:transparent;border:1px solid #71c169;}
136
+ .nc_socialPanel.sw_d_colorOutlines .sw_reddit, html body .nc_socialPanel.sw_i_colorOutlines .sw_reddit:hover, body .nc_socialPanel.sw_o_colorOutlines:hover .sw_reddit {background:transparent;border:1px solid #f04b23;}
137
+ .nc_socialPanel.sw_d_colorOutlines .sw_email, html body .nc_socialPanel.sw_i_colorOutlines .sw_email:hover, body .nc_socialPanel.sw_o_colorOutlines:hover .sw_email {background:transparent;border:1px solid #6bcce9;}
138
+ .nc_socialPanel.sw_d_colorOutlines .sw_pocket, html body .nc_socialPanel.sw_i_colorOutlines .sw_pocket:hover, body .nc_socialPanel.sw_o_colorOutlines:hover .sw_pocket {background:transparent;border:1px solid #ef4056;}
139
+ .nc_socialPanel.sw_d_colorOutlines .sw_buffer, html body .nc_socialPanel.sw_i_colorOutlines .sw_buffer:hover, body .nc_socialPanel.sw_o_colorOutlines:hover .sw_buffer {background:transparent;border:1px solid #323b43;}
140
+ /* Side Floating Buttons */
141
+ .nc_socialPanelSide {z-index:9999999;width:auto;top:200px;overflow:hidden;transition:all 0.2s linear;height:auto;width:100px!important;overflow:visible;}
142
+ .nc_socialPanelSide.slide {position:fixed;left:-100px;transition:all 0.2s linear;}
143
+ .nc_socialPanelSide.fade {position:fixed;left:5px;display:none;transition:all 0.2s linear;}
144
+ .nc_socialPanelSide .nc_tweetContainer {width: auto;height: 32px;background: #DD4B38;margin: 3px 0!important;padding: 0;display: block;font-family: 'Lato',sans-serif;clear: both;vertical-align: top;width:90px;transition:all 0.1s linear;overflow:hidden;border-radius:3px;}
145
+ .nc_socialPanelSide .nc_tweetContainer .iconFiller {display: inline-block;width: 21px;height: 40px;margin: 0 6px;padding: 0;vertical-align: middle;transition:all 0.1s linear;}
146
+ .nc_socialPanelSide .nc_tweetContainer .sw_count {display: inline-block;width: 0;overflow:hidden;line-height: 35px;text-align: right;padding: 0;font-size: 14px;margin: 0;height: 32px;vertical-align: top;transition:all 0.1s linear;}
147
+ .nc_socialPanelSide .nc_tweetContainer a {display: block;text-decoration: none;padding: 0;margin: 0;vertical-align: top;height: 36px;cursor:pointer;transition:all 0.1s linear;font-weight:500;}
148
+ .nc_socialPanelSide .nc_tweetContainer .sw, .nc_socialPanelSide .nc_tweetContainer .sw_share {line-height:34px;float:left;}
149
+ .nc_socialPanelSide .nc_tweetContainer .sw_share {font-size:13px;}
150
+ .nc_socialPanelSide .nc_tweetContainer:hover, .nc_socialPanelSide .nc_tweetContainer:hover .iconFiller, .nc_socialPanelSide .nc_tweetContainer:hover .sw_count {transition:all 0.1s linear;}
151
+ /* Side Floating Boxes */
152
+ .nc_socialPanelSide.sw_boxed {transform:scale(0.9);}
153
+ .nc_socialPanelSide.sw_boxed .nc_tweetContainer {margin-bottom:5px;}
154
+ .nc_socialPanelSide.sw_boxed .nc_tweetContainer, .nc_socialPanelSide.sw_boxed .nc_tweetContainer a {height:75px; width:75px;position:relative;}
155
+ .nc_socialPanelSide.sw_boxed .nc_tweetContainer i.sw {width: 60px;text-align: center;padding-top: 10px;font-size: 27px;height: 40px;}
156
+ .nc_socialPanelSide.sw_boxed .nc_tweetContainer:not(.totes) span.sw_share {position: absolute;bottom: 0;left: 0;width: 75px;text-align: center;height: 35px;opacity:0;}
157
+ .nc_socialPanelSide.sw_boxed .nc_tweetContainer:not(.totes) .sw_hide span.sw_share {opacity:1;}
158
+ .nc_socialPanelSide.sw_boxed .nc_tweetContainer:not(.totes) span.sw_count {transition: padding 0.1s linear;position: absolute;bottom: 0;left: 0;width: 75px;text-align: center;height: 35px;padding:0;}
159
+ .nc_socialPanelSide.sw_boxed .nc_tweetContainer:not(.totes) span.sw_count.sw_hide, .nc_socialPanelSide.sw_boxed .nc_tweetContainer span.sw_hide .iconFiller, .nc_socialPanelSide.sw_boxed .nc_tweetContainer span.sw_hide .spaceManWilly {height:75px;opacity:1;}
160
+ .nc_socialPanelSide.sw_boxed .nc_tweetContainer span.iconFiller {width:75px;height:40px;}
161
+ .nc_socialPanelSide.sw_boxed .nc_tweetContainer:not(.totes):hover span.sw_share:not(.sw_hide) {opacity:1;}
162
+ .nc_socialPanelSide.sw_boxed .nc_tweetContainer:not(.totes):hover span.sw_count:not(.sw_hide) {opacity:0;}
163
+ .nc_socialPanelSide.sw_boxed .totes {width:75px!important;padding:0;}
164
+ /* Side Floating Sizes */
165
+ .nc_socialPanelSide .nc_tweetContainer:not(.totes) {line-height:34px;}
166
+ .nc_socialPanelSide .nc_tweetContainer:not(.totes) .iconFiller {width:30px;margin-left:2px;}
167
+ .nc_socialPanelSide .nc_tweetContainer:not(.totes) .sw_count {width:48px;padding:0 8px;}
168
+ .nc_socialPanelSide:not(.sw_boxed) .nc_tweetContainer:not(.totes):hover {width:130px;}
169
+ .nc_socialPanelSide .nc_tweetContainer:not(.totes):hover .iconFiller, .nc_socialPanelSide .nc_tweetContainer:not(.totes) .spaceManWilly {width:72px;}
170
+ /* Side Floating Totals */
171
+ .nc_socialPanelSide .nc_tweetContainer.totes {background: rgba(0, 0, 0, 0);height: 45px;font-weight: 500;text-align: center;width:90px;margin:0;padding:0;border:0px!important;}
172
+ .nc_socialPanelSide .nc_tweetContainer.totes .sw_count {font-family: 'Lato', sans-serif;color: #444;font-weight: 500;display: block;width: 100%;text-align: center;height:28px;}
173
+ .nc_socialPanelSide .nc_tweetContainer.totes .sw_label {font-family: 'Lato', sans-serif;display: block;width: 100%;text-align: center;font-size: 50%;color: #444;font-weight:500;}
174
+ /* Top and Bottom Floating Buttons */
175
+ .nc_wrapper {position: fixed;background: white;width: 100%;transition: top 0.5s, bottom 0.5s;z-index:99999;}
176
+ .nc_wrapper.floatBottom {bottom:0px;left:0;}
177
+ .nc_wrapper.floatTop {top:0px;left:0;}
178
+ .nc_floater {width: 740px;left: 304px;position: relative;margin: 10px 0;}
179
+ /* Side Floating Options with Shares Hidden */
180
+ .nc_socialPanelSide.hideCounts a {text-align:center;}
181
+ .nc_socialPanelSide.hideCounts .iconFiller {float:none;text-align:left;}
182
+ .nc_socialPanel.mobile .iconFiller ~ .sw_count {display:none;}
183
+ /* Custom Font Icons */
184
+ .sw {display: inline-block;font-family:"sw-icon-font"!important;font-size: inherit;text-rendering: auto;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;transform: translate(0, 0);font-style:normal;font-weight:normal;}
185
+ .sw:before{display:block!important;}
186
+ .wp-editor-container .sw:before {font-size:18px;line-height:22px;}
187
+ .wp-editor-container .sw-twitter:before{color:#429cd6;}
188
+ .wp-editor-container .sw-social-warfare:before{color:#ee464f;}
189
+ .mce-container .sw-social-warfare {font-size: 20px;vertical-align: middle;margin-right: 15px;color: #ee464f;}
190
+ .sw-google-plus:before {content: "h";}
191
+ .sw-pinterest:before {content: "b";}
192
+ .sw-twitter:before {content: "s";}
193
+ .sw-facebook:before {content: "j";}
194
+ .sw-linkedin:before {content: "f";}
195
+ .sw-tumblr:before {content: "r";}
196
+ .sw-stumbleupon:before {content: "q";}
197
+ .sw-reddit:before {content: "a";}
198
+ .sw-email:before {content: "k"}
199
+ .sw-yummly:before {content: "x"}
200
+ .sw-whatsapp:before {content: "y"}
201
+ .sw-pocket:before {content: "B"}
202
+ .sw-buffer:before {content: "z"}
203
+ .sw-social-warfare:before {content: "p"}
204
+ /* Click to Tweet Global Styles */
205
+ .sw_CTT {text-decoration:none!important;}
206
+ .sw-tweet-clear {zoom: 1;}
207
+ .sw-tweet-clear:after {display: block;visibility: hidden;height: 0;clear: both;content: ".";}
208
+ .sw-click-to-tweet {display: block;position: relative;padding: 15px 30px;margin: 15px 0px;}
209
+ .sw-click-to-tweet:after {content: ".";display: block;clear: both;visibility: hidden;line-height: 0;height: 0;}
210
+ .sw-click-to-tweet .sw-ctt-text {margin: 0;padding: 0;position: relative;margin-bottom: 10px;word-wrap: break-word;}
211
+ a .sw-click-to-tweet .sw-ctt-text {margin: 0;padding: 0;position: relative;font-size: 24px;line-height: 140%;text-transform: none;font-weight: 500;text-decoration: none;text-transform: none;display:block;}
212
+ .sw-click-to-tweet .sw-ctt-btn {margin: 10px 0 0 0;padding: 3px;position: relative;display: block;text-transform: uppercase;font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 12px;font-weight: bold;line-height: 100%;float: right;padding-right: 5px;text-decoration: none;}
213
+ .sw-click-to-tweet i.sw-twitter {float: right;font-size:21px;margin-left:15px;text-transform:none;margin-top:2px;}
214
+ /*Click to Tweet Style #1 */
215
+ a.sw_CTT.style1 .sw-click-to-tweet {background-color:#fff;border:1px solid #dddddd;border-radius:4px;}
216
+ a.style1 .sw-click-to-tweet .sw-ctt-text {text-decoration: none;color: #999999;}
217
+ a.style1:hover .sw-click-to-tweet .sw-ctt-text {text-decoration: none;color: #666666;}
218
+ a.style1 .sw-click-to-tweet .sw-ctt-btn {text-decoration: none;color: #999999;}
219
+ a.style1:hover .sw-click-to-tweet .sw-ctt-btn {text-decoration: none;color: #666666;}
220
+ a.style1 .sw-click-to-tweet i.sw-twitter {color:#429cd6;}
221
+ /*Click to Tweet Style #2 */
222
+ a.sw_CTT.style2 .sw-click-to-tweet {background-color:#fff;border:4px double #dddddd;border-radius:0px;}
223
+ a.style2 .sw-click-to-tweet .sw-ctt-text {text-decoration: none;color: #666666; font-style:italic; }
224
+ a.style2:hover .sw-click-to-tweet .sw-ctt-text {text-decoration: none;color: #666666;}
225
+ a.style2 .sw-click-to-tweet .sw-ctt-btn {text-decoration: none;color: #666666;}
226
+ a.style2:hover .sw-click-to-tweet .sw-ctt-btn {text-decoration: none;color: #666666;}
227
+ a.style2 .sw-click-to-tweet i.sw-twitter {color:#429cd6;}
228
+ /*Click to Tweet Style #3 */
229
+ a.sw_CTT.style3:hover .sw-click-to-tweet {border-left:10px solid #3c87b2;padding-right:20px;transition:all .25s linear;}
230
+ a.sw_CTT.style3 .sw-click-to-tweet {border:none;border-left:10px solid #429cd6;background-color:#429cd6;border-radius:0px;padding-right:20px;transition:all .25s linear;}
231
+ a.style3 .sw-click-to-tweet .sw-ctt-text {text-decoration: none;color: #FFFFFF; font-style:italic; }
232
+ a.style3:hover .sw-click-to-tweet .sw-ctt-text, a.style3 .sw-click-to-tweet .sw-ctt-btn, a.style3:hover .sw-click-to-tweet .sw-ctt-btn, a.style3 .sw-click-to-tweet i.sw-twitter {text-decoration: none;color: #FFFFFF;}
233
+ /*Click to Tweet Style #4 */
234
+ a.sw_CTT.style4:hover .sw-click-to-tweet {border-left: 10px solid #3c87b2;transition:all .25s linear;}
235
+ a.sw_CTT.style4 .sw-click-to-tweet {background-color:#333;border-left: 10px solid #C33;border-radius:0px;transition:all .25s linear;}
236
+ a.style4 .sw-click-to-tweet .sw-ctt-text {text-decoration: none;color: #FFFFFF; }
237
+ a.style4:hover .sw-click-to-tweet .sw-ctt-text {text-decoration: none;color: #FFFFFF;}
238
+ a.style4 .sw-click-to-tweet .sw-ctt-btn {text-decoration: none;color: #FFFFFF;}
239
+ a.style4:hover .sw-click-to-tweet .sw-ctt-btn {text-decoration: none;color: #FFFFFF;}
240
+ a.style4 .sw-click-to-tweet i.sw-twitter {color:#FFFFFF;}
241
+ /*Click to Tweet Style #5 */
242
+ a.sw_CTT.style5:hover .sw-click-to-tweet {border-left: 10px solid #30394F;transition:all .25s linear;background-color:#D34250;}
243
+ a.sw_CTT.style5 .sw-click-to-tweet {background-color:#30394F;border-left: 10px solid #D34250;border-radius:0px;transition:all .25s linear;}
244
+ a.style5 .sw-click-to-tweet .sw-ctt-text {text-decoration: none;color: #FFFFFF; }
245
+ a.style5:hover .sw-click-to-tweet .sw-ctt-text {text-decoration: none;color: #FFFFFF;}
246
+ a.style5 .sw-click-to-tweet .sw-ctt-btn {text-decoration: none;color: #FFFFFF;}
247
+ a.style5:hover .sw-click-to-tweet .sw-ctt-btn {text-decoration: none;color: #FFFFFF;}
248
+ a.style5 .sw-click-to-tweet i.sw-twitter {color:#FFFFFF;}
249
+ /*Click to Tweet Style #6 */
250
+ a.sw_CTT.style6:hover .sw-click-to-tweet {border-left: 10px solid #D34250;transition:all .25s linear;background-color:#CED3DC;}
251
+ a.sw_CTT.style6 .sw-click-to-tweet {background-color:#EEEEEE;border-left: 10px solid #D34250;border-radius:0px;transition:all .25s linear;}
252
+ a.style6 .sw-click-to-tweet .sw-ctt-text {text-decoration: none;color: #30394F; }
253
+ a.style6:hover .sw-click-to-tweet .sw-ctt-text {text-decoration: none;color: #2A2D34;}
254
+ a.style6 .sw-click-to-tweet .sw-ctt-btn {text-decoration: none;color: #30394F;}
255
+ a.style6:hover .sw-click-to-tweet .sw-ctt-btn, a.style6:hover .sw-click-to-tweet i.sw-twitter {text-decoration: none;color: #2A2D34;}
256
+ a.style6 .sw-click-to-tweet i.sw-twitter {color:#30394F;}
257
+ /*Popular Posts Style #1*/
258
+ .sw_pop_style1 a.swPopularity {
259
+ font-size: 14px;
260
+ margin: 10px;
261
+ display: block;
262
+ }
263
+ .sw_pop_style1 a.swPopularity b {
264
+ font-weight: bold;
265
+ font-size: 18px;
266
+ line-height: 1.2;
267
+ margin: 0;
268
+ display: inline;
269
+ }
270
+ /* Need to work in a class for the .totes section of the swPopularity*/
fonts/sw-icon-font.eot ADDED
Binary file
fonts/sw-icon-font.svg ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" standalone="no"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
3
+ <svg xmlns="http://www.w3.org/2000/svg">
4
+ <metadata>Generated by Fontastic.me</metadata>
5
+ <defs>
6
+ <font id="social-warfare-icons" horiz-adv-x="512">
7
+ <font-face font-family="social-warfare-icons" units-per-em="512" ascent="480" descent="-32"/>
8
+ <missing-glyph horiz-adv-x="512" />
9
+
10
+ <glyph glyph-name="reddit" unicode="&#97;" d="M448 338c-19 0-38-10-51-26l-3-3c-31 21-72 33-117 37l21 64 56-13c3-27 25-48 54-48 30 0 54 24 54 54 0 31-24 55-54 55-21 0-38-12-48-29l-69 16c-8 1-16-3-19-11l-27-87c-50-1-95-16-128-37l-3 5c-13 15-31 24-50 24-35 0-64-29-64-64 0-27 18-51 43-61l11-4 0 3c0 0 0-2 0-2 0-75 90-136 202-136 110 0 200 61 202 136l11 3c27 8 45 34 45 61-2 34-31 63-66 63z m-40 86c11 0 19-10 19-19 0-11-9-21-19-21-11 0-19 10-19 21 0 9 8 19 19 19z m-355-178c-11 5-18 16-18 28 0 17 13 30 29 30 8 0 16-3 22-10l4-4c-15-13-24-29-31-45z m201-139c-92 0-168 47-168 104 0 58 76 104 168 104 93 0 168-46 168-104 0-57-75-104-168-104z m204 139l-8-3c-7 16-16 32-29 45l5 6c6 7 14 10 22 10 16 0 30-13 30-30-1-12-9-23-20-28z m-237-4c0 16-13 30-31 30-17 0-30-14-30-30 0-16 14-31 30-31 16 0 31 15 31 31z m101 30c-16 0-31-14-31-30 0-16 15-31 31-31 16 0 30 13 30 31-2 17-14 30-30 30z m-2-93c-5 0-8-1-11-5-10-9-27-14-53-14-26 0-42 5-53 14-6 7-17 7-22 0-3-3-5-6-5-11 0-5 2-8 5-11 16-16 40-24 75-24 34 0 59 8 75 24 3 3 5 6 5 11 0 5-2 8-5 11-3 4-6 5-11 5z"/>
11
+ <glyph glyph-name="pinterest" unicode="&#98;" d="M256 450c-107 0-194-87-194-194 0-78 48-147 116-178 0 13 0 31 3 45 3 16 25 106 25 106 0 0-6 13-6 30 0 29 16 50 37 50 17 0 25-13 25-29 0-18-11-45-17-69-5-21 9-37 30-37 37 0 61 47 61 103 0 41-29 73-80 73-59 0-94-43-94-92 0-18 4-29 12-39 4-5 5-6 4-11-2-3-4-13-4-16-1-5-4-6-9-5-27 11-40 40-40 74 0 54 46 120 137 120 74 0 122-53 122-111 0-75-42-132-104-132-21 0-40 11-46 24 0 0-12-45-15-53-5-15-13-31-19-42 18-5 35-8 54-8 108 0 194 87 194 194 2 110-85 197-192 197z"/>
12
+ <glyph glyph-name="periscope" unicode="&#99;" d="M258 464c-93 0-167-77-167-171 0-98 130-245 167-245 32 0 161 147 161 245 2 94-72 171-161 171z m1-261c-57 0-102 45-102 96 0 24 8 47 21 63 0-21 17-39 40-39 22 0 38 18 38 39 0 16-10 28-24 35 8 1 18 3 26 3 52 0 97-45 97-102 0-50-45-95-96-95z"/>
13
+ <glyph glyph-name="medium" unicode="&#101;" d="M493 389l-19 0c-7 0-16-10-16-16l0-232c0-7 9-15 16-15l19 0 0-54-170 0 0 54 35 0 0 242-1 0-83-299-64 0-82 299-2 0 0-245 36 0 0-54-143 0 0 54 18 0c8 0 17 8 17 15l0 233c0 7-9 16-17 16l-18 0 0 56 178 0 57-217 2 0 59 217 178 0z"/>
14
+ <glyph glyph-name="linkedin" unicode="&#102;" d="M115 443c-25 0-46-21-46-46 0-26 21-47 46-47 26 2 45 23 45 47 0 25-19 46-45 46z m-40-374l79 0 0 249-79 0z m282 257c0 0-63 5-77-41l0 33-78 0 0-249 78 0 0 133c0 4 2 54 48 54 43 0 40-58 40-58l0-128 77 0 0 144c-2-1 8 112-88 112z"/>
15
+ <glyph glyph-name="instagram" unicode="&#103;" d="M400 285l-32 0c2-10 3-19 3-29 0-64-51-115-115-115-64 0-115 51-115 115 0 10 1 19 3 29l-32 0 0-159c0-8 6-14 14-14l260 0c8 0 14 6 14 14z m0 101c0 8-6 14-14 14l-44 0c-8 0-14-6-14-14l0-44c0-8 6-14 14-14l44 0c8 0 14 6 14 14z m-144-58c-40 0-72-32-72-72 0-40 32-72 72-72 40 0 72 32 72 72 0 40-32 72-72 72m144-259l-288 0c-24 0-43 19-43 43l0 288c0 24 19 43 43 43l288 0c24 0 43-19 43-43l0-288c0-24-19-43-43-43"/>
16
+ <glyph glyph-name="google-plus" unicode="&#104;" d="M168 280l0-58 96 0c-5-24-29-72-96-72-58 0-102 48-102 106 0 58 44 106 102 106 34 0 54-15 67-26l45 43c-29 29-67 45-112 45-94 0-168-75-168-168 0-93 74-168 168-168 96 0 160 67 160 163 0 11 0 19-2 29z m344 0l-48 0 0 48-48 0 0-48-48 0 0-48 48 0 0-48 48 0 0 48 48 0"/>
17
+ <glyph glyph-name="flickr" unicode="&#105;" d="M510 256c0-66-52-118-118-118-66 0-118 52-118 118 0 66 52 118 118 118 66 0 118-52 118-118z m-270 0c0-66-53-118-118-118-66 0-120 52-120 118 0 66 52 118 118 118 66 0 120-52 120-118z"/>
18
+ <glyph glyph-name="facebook" unicode="&#106;" d="M288 48l0 190 64 0 10 74-74 0 0 48c0 21 6 37 37 37l40 0 0 64c-8 1-31 3-58 3-56 0-96-35-96-98l0-54-64 0 0-74 64 0 0-190z"/>
19
+ <glyph glyph-name="email" unicode="&#107;" d="M166 277l-152 120 0-275z m330 147l-480 0 240-184z m-173-162l-67-51-67 51-175-174 482 0z m21 13l154-153 0 273z"/>
20
+ <glyph glyph-name="ello" unicode="&#108;" d="M256 454c-109 0-198-89-198-198 0-109 89-198 198-198 109 0 198 89 198 198 0 109-89 198-198 198z m-3-321c-82 0-114 67-119 102-1 8 5 16 13 18 8 1 16-5 18-13 0-3 13-75 88-75 75 0 91 73 93 77 1 8 9 14 17 12 8-1 15-9 13-17-6-39-42-104-123-104z"/>
21
+ <glyph glyph-name="blogger" unicode="&#109;" d="M442 288l-4 6-4 5c-7 5-42 0-52 8-6 7-8 18-9 32-5 29-7 31-11 40-16 35-61 61-92 64l-83 0c-65 0-118-53-118-118l0-138c0-65 53-118 118-118l136 0c66 0 119 53 119 118z m-253 59l65 0c13 0 23-9 23-22 0-13-10-23-23-23l-65 0c-13 0-23 10-23 23 0 11 10 22 23 22z m134-181l-133 0c-12 0-22 10-22 23 0 13 10 22 22 22l133 0c13 0 23-9 23-22 0-13-12-23-23-23z"/>
22
+ <glyph glyph-name="rss" unicode="&#110;" d="M166 114c0-29-24-53-52-53-29 0-53 24-53 53 0 28 24 52 53 52 30 0 52-22 52-52z m-104 204l0-78c98-2 178-80 178-178l78 0c-1 141-115 255-256 256z m0 55c84 0 160-32 220-91 59-60 91-136 91-220l78 0c0 215-174 388-387 389l0-78z"/>
23
+ <glyph glyph-name="share" unicode="&#111;" d="M382 170c-16 0-30-7-41-16l-149 86c2 5 2 10 2 14 0 5 0 10-2 15l147 86c11-11 26-17 43-17 36 0 63 28 63 62 0 34-29 64-63 64-33 0-62-29-62-62 0-5 0-10 2-15l-148-86c-11 11-25 17-43 17-35 0-62-28-62-62 0-34 27-64 61-64 16 0 32 6 43 18l149-87c-2-5-2-9-2-14 0-34 27-61 61-61 33 0 61 27 61 61 0 33-26 61-60 61z"/>
24
+ <glyph glyph-name="social-warfare" unicode="&#112;" d="M138 354c3 12 28 67 88 100-96-14-170-97-170-196 0-26 5-52 14-74 4 3 8 5 13 5l74 14c13 3 17-3 14-16-8-29 8-46 37-46 29 0 58 17 59 33 7 53-179 42-129 180z m297-8c-5-5-9-10-17-12l-76-14c-12-3-17 3-14 14 5 24-10 40-38 40-24 0-44-14-45-27-8-46 182-46 134-184-5-13-37-73-109-105 104 6 188 92 188 198-2 32-10 62-23 90z"/>
25
+ <glyph glyph-name="stumble-upon" unicode="&#113;" d="M282 302l33-16 50 15 0 35c-2 59-50 106-109 106-59 0-107-47-109-106l0-158c0-15-11-26-25-26-15 0-26 11-26 26l0 67-85 0c0 0 0-67 0-69 0-61 50-110 111-110 60 0 108 48 108 108l0 157c0 15 12 26 26 26 14 0 26-11 26-26z m136-56l0-70c0-14-12-26-26-26-14 0-26 12-26 26l0 69-49-15-34 16 0-68c0-61 50-109 111-109 60 0 110 49 110 110 0 0 0 69 0 69l-86 0z"/>
26
+ <glyph glyph-name="tumblr" unicode="&#114;" d="M355 133c-65-29-73 24-73 24l0 131 78 0 0 70-78 0 0 106-64 0c0 0-8-94-82-115l0-61 46 0 0-136c0-67 56-104 116-104 59 0 78 26 78 26z"/>
27
+ <glyph glyph-name="twitter" unicode="&#115;" d="M491 402c-17-8-35-13-56-15 19 11 35 31 43 53-19-11-40-19-60-24-18 19-44 30-71 30-62 0-109-57-94-118-80 5-152 43-199 101-25-43-12-101 31-130-16 0-31 5-43 13-2-45 30-86 76-96-12-3-28-5-43-2 13-38 48-65 90-67-40-32-91-46-143-40 44-27 93-43 148-43 179 0 280 152 273 286 19 15 35 32 48 52z"/>
28
+ <glyph glyph-name="vimeo" unicode="&#116;" d="M11 354l19-26c0 0 42 32 55 16 14-16 65-211 83-248 16-32 58-74 104-43 46 30 198 160 227 315 27 154-184 122-206-13 56 34 86-14 57-67-28-53-54-88-68-88-15 0-24 35-40 98-16 64-16 180-84 168-64-13-147-112-147-112z"/>
29
+ <glyph glyph-name="vine" unicode="&#117;" d="M438 258c-11-4-20-4-30-4-53 0-93 37-93 101 0 32 13 48 29 48 16 0 27-14 27-45 0-17-5-35-8-46 0 0 16-29 61-19 10 21 14 48 14 72 0 64-32 101-92 101-61 0-98-48-98-109 0-63 29-115 77-139-21-40-45-76-72-103-48 58-91 136-109 288l-70 0c33-253 131-333 156-349 15-8 28-8 40-1 21 11 85 75 119 149 14 0 32 1 49 6z"/>
30
+ <glyph glyph-name="warfare-plugins" unicode="&#118;" d="M424 365l-32-163c-2-7 3-7 6 0l52 104c-4 20-13 41-26 59z m-155 86l-55-249c-1-7 4-7 7 0l120 233c-23 10-47 16-74 18 2 0 2 0 2-2z m38-240l-85-147c0 0-1-2-1-2 13-1 25-3 38-3 13 0 24 2 37 3 0 0 0 2 0 2l19 147c0 5-5 5-8 0z m-246 45c0-50 17-94 48-130l48 300c-58-34-96-98-96-170z"/>
31
+ <glyph glyph-name="youtube" unicode="&#119;" d="M365 437l-218 0c-123 0-142-7-142-127l0-108c0-120 19-127 142-127l216 0c123 0 143 7 143 127l0 108c1 120-18 127-141 127z m-160-271l0 188 142-95z"/>
32
+ <glyph glyph-name="yummly" unicode="&#120;" d="M91 430c2 7 8 12 13 15 19 13 42 21 64 19 19-2 34-11 37-34 3-14 0-28-3-43-8-30-16-61-24-91-2-6-2-11-2-18 0-8 5-12 13-12 9-2 17 0 25 3 15 3 28 9 40 16 2 1 4 3 4 5 3 19 6 36 9 56 3 19 7 36 10 56 1 12 5 24 6 36 0 4 0 8-1 13-2 5 0 7 3 8 9 5 21 7 32 3 9-1 14-8 14-17 0-10-1-19-3-31-3-20-6-40-11-60-3-21-8-44-11-64-4-21-8-44-12-64-1-8-3-18-4-26 0-2 0-3 1-3 35-5 71-15 103-29 4-3 11-3 17-5 5-1 7-3 7-6 0-8-2-15-7-23-8-11-21-16-35-11-10 3-18 8-26 13-19 11-38 18-60 21-2 0-5 0-7 0-1 0-3 0-3-3-3-20-10-37-18-53-6-13-16-26-27-35-11-10-24-15-38-16-3 0-7-2-10-2-3 0-6 0-9 0-2 0-4 0-4 0-14 2-28 8-38 19-11 15-13 31-10 47 5 27 21 48 45 62 21 11 43 18 66 21 1 0 3 0 3 3 2 5 2 10 3 14 2 7 2 12 3 18-3-2-4-3-6-3-26-15-53-21-83-18-15 2-26 8-32 21-7 13-8 26-5 38 6 28 14 56 22 84 8 16 12 30 15 44 1 12-2 20-16 15-10-2-18-8-24-15-2-3-5-3-8 0-7 5-10 10-13 16-2 4-3 7-5 12 0 1 0 3 0 4z m144-273c-17-3-32-8-45-21-6-6-9-14-9-24 0-10 8-16 17-13 8 2 15 7 20 13 6 10 9 19 12 30 4 4 4 10 5 15z"/>
33
+ <glyph glyph-name="whatsapp" unicode="&#121;" d="M400 402c-38 38-90 59-144 59-112 0-203-91-203-203 0-36 9-71 27-101l-29-106 109 29c29-16 62-24 98-24 112 0 203 91 203 203-2 53-23 104-61 143z m-142-312c-31 0-60 8-87 24l-6 3-64-16 17 62-4 7c-18 27-26 57-26 89 0 93 75 168 168 168 45 0 88-17 118-49 32-32 50-74 50-119 2-94-74-169-166-169z m91 126c-5 3-31 14-35 16-5 2-8 3-12-3-3-5-12-16-16-19-3-4-6-4-11-2-5 3-21 8-40 26-14 12-25 30-29 35-3 5 0 8 2 9 2 2 5 7 8 10 3 3 3 5 5 8 1 3 1 6 0 10-2 3-11 27-16 36-3 8-8 8-11 8-4 0-7 0-10 0-3 0-10-1-13-6-5-5-17-18-17-42 0-25 17-49 20-52 4-4 36-56 87-77 43-18 51-13 61-13 9 2 30 13 33 24 5 11 5 22 3 24 0 3-4 5-9 8z"/>
34
+ <glyph glyph-name="buffer" unicode="&#122;" d="M72 357l170-80c9-5 20-5 28 0l170 80c3 1 3 6 0 8l-168 80c-10 5-22 5-32 0l-170-80c-1-3-1-7 2-8z m368-98l-35 16c-7 3-15 3-23 0l-112-53c-9-4-20-4-28 0l-112 53c-7 3-15 3-21 0l-37-17c-3-2-3-7 0-8l170-80c9-5 20-5 28 0l170 80c3 3 3 8 0 9z m0-102l-35 16c-7 3-15 3-23 0l-112-53c-9-5-20-5-28 0l-112 53c-7 3-15 3-21 0l-37-18c-3-1-3-6 0-8l170-80c9-5 20-5 28 0l170 80c3 2 3 8 0 10z"/>
35
+ <glyph glyph-name="print" unicode="&#65;" d="M378 326l0 106-244 0 0-106-44 0 0-180 40 0 0-66 252 0 0 66 40 0 0 180z m-26-216l-192 0 0 36 192 0z m5 133l-202 0 0 168 202 0z m25-77c-3 0-4 0-8 2-1 0-3 2-3 2-1 0-1 1-3 1-2 2-2 2-3 3 0 0 0 2-2 2-1 2-1 3-3 5 0 1-2 5-2 6 0 13 10 23 23 23 13 0 22-10 22-23 0-13-8-21-21-21z m-44 204l-164 0 0-21 164 0z m0-37l-164 0 0-21 164 0z m0-39l-164 0 0-20 164 0z"/>
36
+ <glyph glyph-name="pocket" unicode="&#66;" d="M445 286l-157-150c-10-8-21-13-32-13-11 0-22 5-32 13l-157 150c-17 18-19 47-1 64 17 18 46 20 65 2l125-120 125 120c17 18 46 18 64-2 19-17 17-46 0-64z"/>
37
+ <glyph glyph-name="meerkat" unicode="&#100;" d="M205 384c-11 10-24 13-39 8-9-2-17-8-24-14-9-10-14-21-14-34 0-3 0-5 0-8 2-5 3-10 5-14 3-8 8-13 14-18 3-3 7-5 10-6 1-2 5-2 6 0 3 1 3 6 0 8-3 1-6 4-8 8-3 3-5 6-8 11-1 3-3 9-3 16 0 3 0 5 2 8 0 3 1 8 4 11 5 5 10 11 16 14 4 2 7 4 10 4 5 1 11 0 16-4 8-3 14-8 19-16 2-3 3-4 7-8 0 0 0-1 0-1 0-2 1-3 3-5 1-2 3 0 5 2 1 1 1 3 1 4 0 4-1 7-1 10-7 10-13 18-21 24z m219-26c-8 5-16 8-24 10-6 2-14 3-19 6-5 4-10 7-15 10-8 6-16 14-24 22-11 12-24 23-36 34-15 13-32 19-52 22-16 2-30 0-46-3-21-5-40-11-58-19-16-5-28-11-41-21-23-17-35-41-35-70 0-11 1-24 4-35 4-18 8-36 10-55 3-22 3-43 3-65 0-21 0-40-1-61 0-18-2-37-4-55 0-11-1-20-3-32l226 0c-2 4-3 7-5 10-10 19-19 40-29 59-6 13-11 27-13 42-1 11-1 22-1 32 0 14 1 29 5 43 1 6 4 10 9 10 5 0 10 1 15 1 11 2 22 2 33 2 24 1 48 9 69 24 6 5 13 9 19 14 5 3 10 8 13 13 6 11 10 22 10 35 4 13 0 23-10 27z m-24-52c-10-7-19-13-30-18-2 0-2 0-4 0-16 5-30 11-44 21-2 0-4 1-5 1-2 0-3-1-3-3 0-1 0-5 1-5 3-3 8-4 11-8 8-3 16-8 24-11 0 0 2 0 2 0-6-1-13-3-19-5-10-1-21-1-31-3-11-1-22-1-32-5-12-3-20-11-24-24-3-11-4-22-6-35 0-16 0-33 2-49 1-18 6-34 12-52 7-14 13-28 21-43l-163 0c0 2 0 2 0 3 2 26 3 53 5 79 0 13 0 25 1 37 0 19 0 38-1 56-2 16-3 32-7 48-1 12-4 24-6 36-3 10-5 20-5 29 0 18 8 32 21 43 10 8 22 15 34 20 16 8 33 14 51 19 11 3 21 5 32 5 19 0 37-7 53-20 14-11 27-24 41-38 11-11 23-21 35-29 5-3 12-6 18-8 0 0 2-1 2-1 4-13 11-26 17-37 0-2-1-2-3-3z m-94 80c-12 0-21-10-21-21 0-2 0-5 0-8-3 0-7 1-10 1-1 0-5 0-5-1 0-2 0-5 2-5 2-2 5-2 6-3 8-3 18-5 26-5 11 0 21 10 21 21 1 11-8 21-19 21z"/>
38
+ </font></defs></svg>
fonts/sw-icon-font.ttf ADDED
Binary file
fonts/sw-icon-font.woff ADDED
Binary file
functions/admin-page-class/admin-page-class.php ADDED
@@ -0,0 +1,3634 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Admin Page Class
4
+ *
5
+ * The Admin Page Class is used by including it in your plugin files and using its methods to
6
+ * create custom Admin Pages. It is meant to be very simple and
7
+ * straightforward.
8
+ *
9
+ * This class is derived from My-Meta-Box (https://github.com/bainternet/My-Meta-Box script) which is
10
+ * a class for creating custom meta boxes for WordPress.
11
+ *
12
+ *
13
+ * @version 1.2.8
14
+ * @copyright 2012 - 2013
15
+ * @author Ohad Raz (email: admin@bainternet.info)
16
+ * @link http://en.bainternet.info
17
+ *
18
+ * @license GNU General Public LIcense v3.0 - license.txt
19
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
22
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25
+ * THE SOFTWARE.
26
+ *
27
+ * @package Admin Page Class
28
+ *
29
+ * @Last Revised
30
+ */
31
+
32
+ if ( ! class_exists( 'BF_Admin_Page_Class') ) :
33
+
34
+ /**
35
+ * Admin Page Class
36
+ *
37
+ * @package Admin Page Class
38
+ * @since 0.1
39
+ *
40
+ * @todo Nothing.
41
+ */
42
+
43
+ class BF_Admin_Page_Class {
44
+
45
+ /**
46
+ * Contains all saved data for a page
47
+ *
48
+ * @access protected
49
+ * @var array
50
+ * @since 0.1
51
+ */
52
+ protected $_saved;
53
+
54
+ /**
55
+ * Contains all arguments needed to build the page itself
56
+ *
57
+ * @access protected
58
+ * @var array
59
+ * @since 0.1
60
+ */
61
+ protected $args;
62
+
63
+ /**
64
+ * Contains Options group name
65
+ * @access protected
66
+ * @var array
67
+ * @since 0.1
68
+ */
69
+ protected $option_group;
70
+
71
+ /**
72
+ * Contains all the information needed to build the form structure of the page
73
+ *
74
+ * @access public
75
+ * @var array
76
+ * @since 0.1
77
+ */
78
+ public $_fields;
79
+
80
+ /**
81
+ * True if the table is opened, false if it is not opened
82
+ *
83
+ * @access protected
84
+ * @var boolean
85
+ * @since 0.1
86
+ */
87
+ protected $table = false;
88
+
89
+ /**
90
+ * True if the tab div is opened, false if it is not opened
91
+ *
92
+ * @access protected
93
+ * @var boolean
94
+ * @since 0.1
95
+ */
96
+ protected $tab_div = false;
97
+
98
+ /**
99
+ * Contains the menu_slug for the current TopLeve-Menu
100
+ *
101
+ * @access public
102
+ * @var string
103
+ * @since 0.1
104
+ */
105
+ public $Top_Slug;
106
+
107
+ /**
108
+ * Contains the menu_slug for the current page
109
+ *
110
+ * @access public
111
+ * @var string
112
+ * @since 0.1
113
+ */
114
+ public $_Slug;
115
+
116
+ /**
117
+ * Contains all the information needed to build the Help tabs
118
+ *
119
+ * @access public
120
+ * @var array
121
+ * @since 0.1
122
+ */
123
+ public $_help_tabs;
124
+
125
+ /**
126
+ * Use html table row or div for each field, true for row, false for div
127
+ *
128
+ * @access public
129
+ * @var boolean
130
+ * @since 0.1
131
+ */
132
+ public $_div_or_row;
133
+
134
+ /**
135
+ * saved flag
136
+ * @var boolean
137
+ * @since 0.6
138
+ */
139
+ public $saved_flag = false;
140
+
141
+ /**
142
+ * use google fonts for typo filed?
143
+ * @var boolean
144
+ * @since 0.9.9
145
+ * @access public
146
+ */
147
+ public $google_fonts = false;
148
+
149
+ /**
150
+ * Holds used field types
151
+ * @var boolean
152
+ * @since 1.1.3
153
+ * @access public
154
+ */
155
+ public $field_types = array();
156
+
157
+ /**
158
+ * Holds validation Errors
159
+ * @var boolean
160
+ * @since 1.1.9
161
+ * @access public
162
+ */
163
+ public $errors = array();
164
+
165
+ /**
166
+ * Holds Errors flag
167
+ * @var boolean
168
+ * @since 1.1.9
169
+ * @access public
170
+ */
171
+ public $errors_flag = false;
172
+
173
+ /**
174
+ * data_type holds type of data (options, post_meta, tax_meta, user_meta)
175
+ * @var string
176
+ * @since
177
+ */
178
+ public $data_type = 'options';
179
+ /**
180
+ * Builds a new Page
181
+ * @param $args (string|mixed array) -
182
+ *
183
+ * Possible keys within $args:
184
+ * > menu (array|string) - (string) -> this the name of the parent Top-Level-Menu or a TopPage object to create
185
+ * this page as a sub menu to.
186
+ * (array) -> top - Slug for the New Top level Menu page to create.
187
+ * > page_title (string) - The name of this page (good for Top level and sub menu pages)
188
+ * > capability (string) (optional) - The capability needed to view the page (good for Top level and sub menu pages)
189
+ * > menu_title (string) - The name of the Top-Level-Menu (Top level Only)
190
+ * > menu_slug (string) - A unique string identifying your new menu (Top level Only)
191
+ * > icon_url (string) (optional) - URL to the icon, decorating the Top-Level-Menu (Top level Only)
192
+ * > position (string) (optional) - The position of the Menu in the ACP (Top level Only)
193
+ * > option_group (string) (required) - the name of the option to create in the database
194
+ *
195
+ *
196
+ */
197
+ public function __construct($args) {
198
+ if(is_array($args)) {
199
+ if (isset($args['option_group'])){
200
+ $this->option_group = $args['option_group'];
201
+ }
202
+ $this->args = $args;
203
+ } else {
204
+ $array['page_title'] = $args;
205
+ $this->args = $array;
206
+ }
207
+
208
+ //add hooks for export download
209
+ add_action('template_redirect',array($this, 'admin_redirect_download_files'));
210
+ add_filter('init', array($this,'add_query_var_vars'));
211
+
212
+ // If we are not in admin area exit.
213
+ if ( ! is_admin() )
214
+ return;
215
+
216
+ //load translation
217
+ $this->load_textdomain();
218
+
219
+ //set defaults
220
+ $this->_div_or_row = true;
221
+ $this->saved = false;
222
+ //store args
223
+ $this->args = $args;
224
+ //google_fonts
225
+ $this->google_fonts = isset($args['google_fonts'])? true : false;
226
+
227
+ //sub $menu
228
+ if(!is_array($args['menu'])) {
229
+ if(is_object($args['menu'])) {
230
+ $this->Top_Slug = $args['menu']->Top_Slug;
231
+ }else{
232
+ switch($args['menu']) {
233
+ case 'posts':
234
+ $this->Top_Slug = 'edit.php';
235
+ break;
236
+ case 'dashboard':
237
+ $this->Top_Slug = 'index.php';
238
+ break;
239
+ case 'media':
240
+ $this->Top_Slug = 'upload.php';
241
+ break;
242
+ case 'links':
243
+ $this->Top_Slug = 'link-manager.php';
244
+ break;
245
+ case 'pages':
246
+ $this->Top_Slug = 'edit.php?post_type=page';
247
+ break;
248
+ case 'comments':
249
+ $this->Top_Slug = 'edit-comments.php';
250
+ break;
251
+ case 'theme':
252
+ $this->Top_Slug = 'themes.php';
253
+ break;
254
+ case 'plugins':
255
+ $this->Top_Slug = 'plugins.php';
256
+ break;
257
+ case 'users':
258
+ $this->Top_Slug = 'users.php';
259
+ break;
260
+ case 'tools':
261
+ $this->Top_Slug = 'tools.php';
262
+ break;
263
+ case 'settings':
264
+ $this->Top_Slug = 'options-general.php';
265
+ break;
266
+ default:
267
+ if(post_type_exists($args['menu'])) {
268
+ $this->Top_Slug = 'edit.php?post_type='.$args['menu'];
269
+ } else {
270
+ $this->Top_Slug = $args['menu'];
271
+ }
272
+ }
273
+ }
274
+ add_action('admin_menu', array($this, 'AddMenuSubPage'));
275
+ }else{
276
+ //top page
277
+ $this->Top_Slug = $args['menu']['top'];
278
+ add_action('admin_menu', array($this, 'AddMenuTopPage'));
279
+ }
280
+
281
+
282
+ // Assign page values to local variables and add it's missed values.
283
+ $this->_Page_Config = $args;
284
+ $this->_fields = $this->_Page_Config['fields'];
285
+ $this->_Local_images = (isset($args['local_images'])) ? true : false;
286
+ $this->_div_or_row = (isset($args['div_or_row'])) ? $args['div_or_row'] : false;
287
+ $this->add_missed_values();
288
+ if (isset($args['use_with_theme'])){
289
+ if ($args['use_with_theme'] === true){
290
+ $this->SelfPath = get_stylesheet_directory_uri() . '/admin-page-class';
291
+ }elseif($args['use_with_theme'] === false){
292
+ $this->SelfPath = plugins_url( 'admin-page-class', plugin_basename( dirname( __FILE__ ) ) );
293
+ }else{
294
+ $this->SelfPath = $args['use_with_theme'];
295
+ }
296
+ }else{
297
+ $this->SelfPath = plugins_url( 'admin-page-class', plugin_basename( dirname( __FILE__ ) ) );
298
+ }
299
+
300
+ // Load common js, css files
301
+ // Must enqueue for all pages as we need js for the media upload, too.
302
+
303
+
304
+ //add_action('admin_head', array($this, 'loadScripts'));
305
+ add_filter('attribute_escape',array($this,'edit_insert_to_post_text'),10,2);
306
+
307
+ // Delete file via Ajax
308
+ add_action( 'wp_ajax_apc_delete_mupload', array( $this, 'wp_ajax_delete_image' ) );
309
+ //import export
310
+ add_action( 'wp_ajax_apc_import_'.$this->option_group, array( $this, 'import' ) );
311
+ add_action( 'wp_ajax_apc_export_'.$this->option_group, array( $this, 'export' ) );
312
+
313
+ //plupload ajax
314
+ add_action('wp_ajax_plupload_action', array( $this,"Handle_plupload_action"));
315
+
316
+ }
317
+
318
+
319
+ /**
320
+ * Does all the complicated stuff to build the menu and its first page
321
+ *
322
+ * @since 0.1
323
+ * @access public
324
+ */
325
+ public function AddMenuTopPage() {
326
+ $default = array(
327
+ 'capability' => 'edit_themes',
328
+ 'menu_title' => '',
329
+ 'id' => 'id',
330
+ 'icon_url' => SW_PLUGIN_DIR.'/images/socialwarfare-20x20.png',
331
+ 'position' => null
332
+ );
333
+
334
+ $this->args = array_merge($default, $this->args);
335
+ $id = add_menu_page($this->args['page_title'], $this->args['page_title'], $this->args['capability'], $this->args['id'], array($this, 'DisplayPage'), $this->args['icon_url'], $this->args['position']);
336
+ $page = add_submenu_page($id, $this->args['page_title'], $this->args['page_title'], $this->args['capability'], $this->args['id'], array($this, 'DisplayPage'));
337
+ if ($page){
338
+ $this->_Slug = $page;
339
+ // Adds my_help_tab when my_admin_page loads
340
+ add_action('load-'.$page, array($this,'Load_page_hooker'));
341
+ }
342
+ }
343
+
344
+ /**
345
+ * Does all the complicated stuff to build the page
346
+ *
347
+ * @since 0.1
348
+ * @access public
349
+ */
350
+ public function AddMenuSubPage() {
351
+ $default = array(
352
+ 'capability' => 'edit_themes',
353
+ );
354
+ $this->args = array_merge($default, $this->args);
355
+ $page = add_submenu_page($this->Top_Slug, $this->args['page_title'], $this->args['page_title'], $this->args['capability'], $this->createSlug(), array($this, 'DisplayPage'));
356
+ if ($page){
357
+ $this->_Slug = $page;
358
+ add_action('load-'.$page, array($this,'Load_page_hooker'));
359
+ }
360
+ }
361
+
362
+ /**
363
+ * loads scripts and styles for the page
364
+ *
365
+ * @author ohad raz
366
+ * @since 0.1
367
+ * @access public
368
+ */
369
+ public function Load_page_hooker(){
370
+ $page = $this->_Slug;
371
+ //help tabs
372
+ add_action('admin_head-'.$page, array($this,'admin_add_help_tab'));
373
+ //pluploader code
374
+ add_action('admin_head-'.$page, array($this,'plupload_head_js'));
375
+ //scripts and styles
376
+ add_action( 'admin_print_styles', array( $this, 'load_scripts_styles' ) );
377
+ //panel script
378
+ add_action('admin_footer-' . $page, array($this,'panel_script'));
379
+ //add mising scripts
380
+ //add_action('admin_enqueue_scripts',array($this,'Finish'));
381
+
382
+ if(isset($_POST['action']) && $_POST['action'] == 'save') {
383
+ $this->save();
384
+ $this->saved_flag = true;
385
+ }
386
+ }
387
+
388
+ public function plupload_head_js(){
389
+ if ($this->has_field('plupload')){
390
+ $plupload_init = array(
391
+ 'runtimes' => 'html5,silverlight,flash,html4',
392
+ 'browse_button' => 'plupload-browse-button', // will be adjusted per uploader
393
+ 'container' => 'plupload-upload-ui', // will be adjusted per uploader
394
+ 'drop_element' => 'drag-drop-area', // will be adjusted per uploader
395
+ 'file_data_name' => 'async-upload', // will be adjusted per uploader
396
+ 'multiple_queues' => true,
397
+ 'max_file_size' => wp_max_upload_size() . 'b',
398
+ 'url' => admin_url('admin-ajax.php'),
399
+ 'flash_swf_url' => includes_url('js/plupload/plupload.flash.swf'),
400
+ 'silverlight_xap_url' => includes_url('js/plupload/plupload.silverlight.xap'),
401
+ 'filters' => array(array('title' => __('Allowed Files','apc'), 'extensions' => '*')),
402
+ 'multipart' => true,
403
+ 'urlstream_upload' => true,
404
+ 'multi_selection' => false, // will be added per uploader
405
+ // additional post data to send to our ajax hook
406
+ 'multipart_params' => array(
407
+ '_ajax_nonce' => "", // will be added per uploader
408
+ 'action' => 'plupload_action', // the ajax action name
409
+ 'imgid' => 0 // will be added per uploader
410
+ )
411
+ );
412
+ echo '<script type="text/javascript">'."\n".'var base_plupload_config=';
413
+ echo json_encode($plupload_init)."\n".'</script>';
414
+ }
415
+ }
416
+
417
+ /**
418
+ * Creates an unique slug out of the page_title and the current menu_slug
419
+ *
420
+ * @since 0.1
421
+ * @access private
422
+ */
423
+ private function createSlug() {
424
+ $slug = $this->args['page_title'];
425
+ $slug = strtolower($slug);
426
+ $slug = str_replace(' ','_',$slug);
427
+ return $this->Top_Slug.'_'.$slug;
428
+ }
429
+
430
+ /** add Help Tab
431
+ *
432
+ * @since 0.1
433
+ * @access public
434
+ * @param $args (mixed|array) contains everything needed to build the field
435
+ *
436
+ * Possible keys within $args:
437
+ * > id (string) (required)- Tab ID. Must be HTML-safe and should be unique for this menu
438
+ * > title (string) (required)- Title for the tab.
439
+ * > content (string) (required)- Help tab content in plain text or HTML.
440
+ *
441
+
442
+ *
443
+ * Will only work on wordpres version 3.3 and up
444
+ */
445
+ public function HelpTab($args){
446
+ $this->_help_tabs[] = $args;
447
+ }
448
+
449
+ /* print Help Tabs for current screen
450
+ *
451
+ * @access public
452
+ * @since 0.1
453
+ * @author Ohad
454
+ *
455
+ * Will only work on wordpres version 3.3 and up
456
+ */
457
+ public function admin_add_help_tab(){
458
+ $screen = get_current_screen();
459
+ /*
460
+ * Check if current screen is My Admin Page
461
+ * Don't add help tab if it's not
462
+ */
463
+
464
+ if ( $screen->id != $this->_Slug )
465
+ return;
466
+ // Add help_tabs for current screen
467
+
468
+ foreach((array)$this->_help_tabs as $tab){
469
+
470
+ $screen->add_help_tab($tab);
471
+ }
472
+ }
473
+
474
+ /* print out panel Script
475
+ *
476
+ * @access public
477
+ * @since 0.1
478
+ */
479
+ public function panel_script(){
480
+ ?>
481
+ <script>
482
+
483
+ /* cookie stuff */
484
+ function setCookie(name,value,days) {
485
+ if (days) {
486
+ var date = new Date();
487
+ date.setTime(date.getTime()+(days*24*60*60*1000));
488
+ var expires = "; expires="+date.toGMTString();
489
+ }
490
+ else var expires = "";
491
+ document.cookie = name+"="+value+expires+"; path=/";
492
+ }
493
+
494
+ function getCookie(name) {
495
+ var nameEQ = name + "=";
496
+
497
+ var ca = document.cookie.split(";");
498
+ for(var i=0;i < ca.length;i++) {
499
+ var c = ca[i];
500
+ while (c.charAt(0)==' ') c = c.substring(1,c.length);
501
+ if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
502
+ }
503
+ return null;
504
+ }
505
+
506
+ function eraseCookie(name) {setCookie(name,"",-1);}
507
+
508
+ var last_tab = getCookie("apc_<?php echo $this->option_group; ?>last");
509
+ if (last_tab) {
510
+ var last_tab = last_tab;
511
+ }else{
512
+ var last_tab = null;
513
+ }
514
+ jQuery(document).ready(function() {
515
+ function show_tab(li){
516
+ if (!jQuery(li).hasClass("active_tab")){
517
+ //hide all
518
+ jQuery(".panel_menu li").removeClass("active_tab");
519
+ tab = jQuery(li).find("a").attr("href");
520
+ jQuery(".setingstab").fadeOut('slow',function() {
521
+ jQuery(li).addClass("active_tab");
522
+ jQuery(tab).fadeIn('slow');
523
+ });
524
+ setCookie("apc_<?php echo $this->option_group; ?>last",tab);
525
+ }
526
+ }
527
+ //hide all
528
+ jQuery(".setingstab").hide();
529
+
530
+ //set first_tab as active if no cookie found
531
+ if (last_tab == null){
532
+ jQuery(".panel_menu li:first").addClass("active_tab");
533
+ var tab = jQuery(".panel_menu li:first a").attr("href");
534
+ jQuery(tab).show();
535
+ }else{
536
+ show_tab(jQuery('[href="' + last_tab + '"]').parent());
537
+ }
538
+
539
+ //bind click on menu action to show the right tab.
540
+ jQuery(".panel_menu li").bind("click", function(event){
541
+ event.preventDefault()
542
+ show_tab(jQuery(this));
543
+
544
+ });
545
+ <?php
546
+ if ($this->has_Field('upload')){
547
+ ?>
548
+ function load_images_muploader(){
549
+ jQuery(".mupload_img_holder").each(function(i,v){
550
+ if (jQuery(this).next().next().val() != ""){
551
+ jQuery(this).append('<img src="' + jQuery(this).next().next().val() + '" style="height: 150px;width: 150px;" />');
552
+ jQuery(this).next().next().next().val("Delete");
553
+ jQuery(this).next().next().next().removeClass("apc_upload_image_button").addClass("apc_delete_image_button");
554
+ }
555
+ });
556
+ }
557
+ //upload button
558
+ var formfield1;
559
+ var formfield2;
560
+ jQuery("#image_button").click(function(e){
561
+ if(jQuery(this).hasClass("apc_upload_image_button")){
562
+ formfield1 = jQuery(this).prev();
563
+ formfield2 = jQuery(this).prev().prev();
564
+ tb_show("", "media-upload.php?type=image&amp;apc=insert_file&amp;TB_iframe=true");
565
+ return false;
566
+ }else{
567
+ var field_id = jQuery(this).attr("rel");
568
+ var at_id = jQuery(this).prev().prev();
569
+ var at_src = jQuery(this).prev();
570
+ var t_button = jQuery(this);
571
+ data = {
572
+ action: "apc_delete_mupload",
573
+ _wpnonce: $("#nonce-delete-mupload_" + field_id).val(),
574
+ field_id: field_id,
575
+ attachment_id: jQuery(at_id).val()
576
+ };
577
+
578
+ $.post(ajaxurl, data, function(response) {
579
+ if ("success" == response.status){
580
+ jQuery(t_button).val("Upload Image");
581
+ jQuery(t_button).removeClass("apc_delete_image_button").addClass("apc_upload_image_button");
582
+ //clear html values
583
+ jQuery(at_id).val("");
584
+ jQuery(at_src).val("");
585
+ jQuery(at_id).prev().html("");
586
+ load_images_muploader();
587
+ }else{
588
+ alert(response.message);
589
+ }
590
+ }, "json");
591
+ return false;
592
+ }
593
+ });
594
+
595
+
596
+
597
+ //store old send to editor function
598
+ window.restore_send_to_editor = window.send_to_editor;
599
+ //overwrite send to editor function
600
+ window.send_to_editor = function(html) {
601
+ imgurl = jQuery("img",html).attr("src");
602
+ img_calsses = jQuery("img",html).attr("class").split(" ");
603
+ att_id = "";
604
+ jQuery.each(img_calsses,function(i,val){
605
+ if (val.indexOf("wp-image") != -1){
606
+ att_id = val.replace("wp-image-", "");
607
+ }
608
+ });
609
+
610
+ jQuery(formfield2).val(att_id);
611
+ jQuery(formfield1).val(imgurl);
612
+ load_images_muploader();
613
+ tb_remove();
614
+ //restore old send to editor function
615
+ window.send_to_editor = window.restore_send_to_editor;
616
+ }
617
+ <?php
618
+ }
619
+ ?>
620
+ });
621
+ </script>
622
+ <?php
623
+ }
624
+
625
+
626
+
627
+ //rename insert to post button
628
+ /**
629
+ * edit_insert_to_post_text
630
+ *
631
+ * @author ohad raz
632
+ * @since 0.1
633
+ * @param string $input insert to post text
634
+ * @return string
635
+ */
636
+ public function edit_insert_to_post_text( $safe_text, $text ) {
637
+ if( is_admin() && 'Insert into Post' == $safe_text){
638
+ if (isset($_REQUEST['apc']) && 'insert_file' == $_REQUEST['apc'] )
639
+ return str_replace(__('Insert into Post'), __('Use this File','apc'), $safe_text);
640
+ else
641
+ return str_replace(__('Insert into Post'), __('Use this Image','apc'), $safe_text);
642
+ }
643
+ return $safe_text;
644
+ }
645
+
646
+ /* print out panel Style (deprecated)
647
+ *
648
+ * @access public
649
+ * @since 0.1
650
+ */
651
+ public function panel_style(){
652
+ //echo '<style></style>';
653
+ }
654
+
655
+ /**
656
+ * Outputs all the HTML needed for the new page
657
+ *
658
+ * @access public
659
+ * @param $args (mixed|array) contains everything needed to build the field
660
+ * @param $repeater (boolean)
661
+ * @since 0.1
662
+ */
663
+ public function DisplayPage() {
664
+ do_action('admin_page_class_before_page');
665
+ echo '<div class="wrap">';
666
+ echo '<form method="post" name="'.apply_filters('apc_form_name', 'admin_page_class',$this).'" class="'.apply_filters('apc_form_class', 'admin_page_class',$this).'" id="'.apply_filters('apc_form_id', 'admin_page_class',$this).'" action="" enctype="multipart/form-data">';
667
+ echo apply_filters('admin_page_class_before_title','');
668
+ $screen = get_current_screen();
669
+ $page = $screen->parent_base;
670
+ if($page == 'social-warfare'):
671
+ echo '<a target="_blank" href="http://warfareplugins.com/affiliates/"><img src="'.SW_PLUGIN_DIR.'/images/banner.jpg" class="swBanner" /></a>';
672
+ endif;
673
+
674
+ wp_nonce_field( basename(__FILE__), 'BF_Admin_Page_Class_nonce' );
675
+
676
+ if ($this->saved_flag){
677
+ echo '<div class="update-status">';
678
+ $this->errors = apply_filters('admin_page_class_errors', $this->errors,$this);
679
+ if (is_array($this->errors) && count($this->errors) > 0 ){
680
+ $this->errors_flag = true;
681
+ $this->displayErrors();
682
+ }else{
683
+ echo '<div class="alert alert-success"><button data-dismiss="alert" class="close" type="button">×</button><strong>'.__('Settings saved.','apc').'</strong></div>';
684
+ }
685
+ echo '</div>';
686
+ }
687
+
688
+
689
+ $saved = get_option($this->option_group);
690
+ $this->_saved = $saved;
691
+ $skip = array('title','paragraph','subtitle','TABS','CloseDiv','TABS_Listing','OpenTab','custom','import_export');
692
+
693
+ foreach($this->_fields as $field) {
694
+ if (!in_array($field['type'],$skip)){
695
+ if(!$this->table) {
696
+ if ($this->_div_or_row){
697
+ echo '<table class="form-table">';
698
+ $this->table = true;
699
+ }else{
700
+ echo '<div class="form-table">';
701
+ $this->table = true;
702
+ }
703
+ }
704
+ }else{
705
+ if($this->table) {
706
+ if ($this->_div_or_row){echo '</table>';}else{echo '</div>';}
707
+ $this->table = false;
708
+ }
709
+ }
710
+ $data = '';
711
+ if (isset($saved[$field['id']]))
712
+ $data = $saved[$field['id']];
713
+ if (isset($field['std']) && $data === '')
714
+ $data = $field['std'];
715
+
716
+ if (method_exists($this,'show_field_' . $field['type'])){
717
+ if ($this->_div_or_row){echo '<td>';}else{echo apply_filters('admin_page_class_field_container_open','<div class="sw_field">',$field);}
718
+ call_user_func ( array( $this, 'show_field_' . $field['type'] ), $field, $data );
719
+ if ($this->_div_or_row){echo '</td>';}else{echo apply_filters('admin_page_class_field_container_close','</div>',$field);}
720
+ }else{
721
+ switch($field['type']) {
722
+ case 'TABS':
723
+ echo '<div id="tabs">';
724
+ break;
725
+ case 'CloseDiv':
726
+ $this->tab_div = false;
727
+ echo '</div>';
728
+ break;
729
+ case 'TABS_Listing':
730
+ echo '<div class="panel_menu"><ul>';
731
+ foreach($field['links'] as $id => $name){
732
+ $extra_classes = strtolower(str_replace(' ','-',$name)).' '.strtolower(str_replace(' ','-',$id));
733
+ echo '<li class="'.apply_filters('APC_tab_li_extra_class',$extra_classes).'"><a class="nav_tab_link" href="#'.$id.'">'.$name.'</a></li>';
734
+ }
735
+ echo '</ul></div><div class="sections">';
736
+ break;
737
+ case 'OpenTab':
738
+ $this->tab_div = true;
739
+ echo '<div class="setingstab" id="'.$field['id'].'">';
740
+ do_action('admin_page_class_after_tab_open');
741
+ break;
742
+ case 'title':
743
+ echo '<h2>'.$field['label'].'</h2>';
744
+ break;
745
+ case 'subtitle':
746
+ echo '<h3>'.$field['label'].'</h3>';
747
+ break;
748
+ case 'paragraph':
749
+ echo '<p>'.$field['text'].'</p>';
750
+ break;
751
+ case 'repeater':
752
+ do_action('admin_page_class_before_repeater');
753
+ $this->output_repeater_fields($field,$data);
754
+ do_action('admin_page_class_after_repeater');
755
+ break;
756
+ case 'import_export':
757
+ $this->show_import_export();
758
+ do_action('admin_page_class_import_export_tab');
759
+ break;
760
+ }
761
+ }
762
+ if (!in_array($field['type'],$skip)){ echo '</tr>';}
763
+ }
764
+ if($this->table) echo '</table>';
765
+ if($this->tab_div) echo '</div>';
766
+ echo '</div><div style="clear:both"></div><div class="footer_wrap">
767
+ <div style="float:right;margin:32px 0 0 0">
768
+ <input type="submit" style="margin-left: 25px;" name="Submit" class="'.apply_filters('admin_page_class_submit_class', 'btn-info').' btn" value="'.esc_attr(__('Save Changes','apc')).'" />
769
+ <br><br>
770
+ </div>
771
+ <br style="clear:both"><br>
772
+ </div>';
773
+ echo '<input type="hidden" name="action" value="save" />';
774
+ echo '</form></div></div>';
775
+
776
+ do_action('admin_page_class_after_page');
777
+ }
778
+
779
+ /**
780
+ * Adds tabs current page
781
+ *
782
+ * @access public
783
+ * @param $args (mixed|array) contains everything needed to build the field
784
+ * @since 0.1
785
+ */
786
+ public function OpenTabs_container($text= null) {
787
+ $args['type'] = 'TABS';
788
+ $text = (null == $text)? '': $text;
789
+ $args['text'] = $text;
790
+ $args['id'] = 'TABS';
791
+ $args['std'] = '';
792
+ $this->SetField($args);
793
+ }
794
+
795
+ /**
796
+ * Close open Div
797
+ *
798
+ * @access public
799
+ * @param $args (mixed|array) contains everything needed to build the field
800
+ * @param $repeater (boolean)
801
+ * @since 0.1
802
+ */
803
+ public function CloseDiv_Container() {
804
+ $args['type'] = 'CloseDiv';
805
+ $args['id'] = 'CloseDiv';
806
+ $args['std'] = '';
807
+ $this->SetField($args);
808
+ }
809
+
810
+ /**
811
+ * Adds tabs listing in ul li
812
+ *
813
+ * @access public
814
+ * @param $args (mixed|array) contains everything needed to build the field
815
+ * @param $repeater (boolean)
816
+ * @since 0.1
817
+ */
818
+ public function TabsListing($args) {
819
+ $args['type'] = 'TABS_Listing';
820
+ $args['id'] = 'TABS_Listing';
821
+ $args['std'] = '';
822
+ $this->SetField($args);
823
+ }
824
+
825
+ /**
826
+ * Opens a Div
827
+ *
828
+ * @access public
829
+ * @param $args (mixed|array) contains everything needed to build the field
830
+ * @param $repeater (boolean)
831
+ * @since 0.1
832
+ */
833
+ public function OpenTab($name) {
834
+ $args['type'] = 'OpenTab';
835
+ $args['id'] = $name;
836
+ $args['std'] = '';
837
+ $this->SetField($args);
838
+ }
839
+
840
+ /**
841
+ * close a Div
842
+ *
843
+ * @access public
844
+ * @since 0.1
845
+ */
846
+ public function CloseTab() {
847
+ $args['type'] = 'CloseDiv';
848
+ $args['id'] = 'CloseDiv';
849
+ $args['std'] = '';
850
+ $this->SetField($args);
851
+ }
852
+
853
+ /**
854
+ * Does the repetive tasks of adding a field
855
+ *
856
+ * @param $args (mixed|array) contains everything needed to build the field
857
+ * @param $repeater (boolean)
858
+ * @since 0.1
859
+ *
860
+ * @access private
861
+ */
862
+ private function SetField($args) {
863
+ $default = array(
864
+ 'std' => '',
865
+ 'id' => ''
866
+ );
867
+ $args = array_merge($default, $args);
868
+ $this->buildOptions($args);
869
+ $this->_fields[] = $args;
870
+ }
871
+
872
+ /**
873
+ * Builds all the options with their std values
874
+ *
875
+ * @access public
876
+ * @param $args (mixed|array) contains everything needed to build the field
877
+ * @since 0.1
878
+ * @access private
879
+ */
880
+ private function buildOptions($args) {
881
+ $default = array(
882
+ 'std' => '',
883
+ 'id' => ''
884
+ );
885
+ $args = array_merge($default, $args);
886
+ $saved = get_option($this->option_group);
887
+ if (isset($saved[$args['id']])){
888
+ if($saved[$args['id']] === false) {
889
+ $saved[$args['id']] = $args['std'];
890
+ update_option($this->args['option_group'],$saved);
891
+ }
892
+ }
893
+ }
894
+
895
+ /**
896
+ * Adds a heading to the current page
897
+ *
898
+ * @access public
899
+ * @param $args (mixed|array) contains everything needed to build the field
900
+ * @param $repeater (boolean)
901
+ * @since 0.1
902
+ *
903
+ * @param string $label simply the text for your heading
904
+ */
905
+ public function Title($label,$repeater = false) {
906
+ $args['type'] = 'title';
907
+ $args['std'] = '';
908
+ $args['label'] = $label;
909
+ $args['id'] = 'title'.$label;
910
+ $this->SetField($args);
911
+ }
912
+
913
+ /**
914
+ * Adds a sub-heading to the current page
915
+ *
916
+ * @access public
917
+ * @param $args (mixed|array) contains everything needed to build the field
918
+ * @param $repeater (boolean)
919
+ * @since 0.1
920
+ *
921
+ * @param string $label simply the text for your heading
922
+ */
923
+ public function Subtitle($label,$repeater = false) {
924
+ $args['type'] = 'subtitle';
925
+ $args['label'] = $label;
926
+ $args['id'] = 'title'.$label;
927
+ $args['std'] = '';
928
+ $this->SetField($args);
929
+ }
930
+
931
+ /**
932
+ * Adds a paragraph to the current page
933
+ *
934
+ * @access public
935
+ * @param $args (mixed|array) contains everything needed to build the field
936
+ * @param $repeater (boolean)
937
+ * @since 0.1
938
+ *
939
+ * @param string $text the text you want to display
940
+ */
941
+ public function Paragraph($text,$repeater = false) {
942
+ $args['type'] = 'paragraph';
943
+ $args['text'] = $text;
944
+ $args['id'] = 'paragraph';
945
+ $args['std'] = '';
946
+ $this->SetField($args);
947
+ }
948
+
949
+
950
+ /**
951
+ * Load all Javascript and CSS
952
+ *
953
+ * @since 0.1
954
+ * @access public
955
+ */
956
+ public function load_scripts_styles() {
957
+
958
+ // Get Plugin Path
959
+ $plugin_path = $this->SelfPath;
960
+
961
+ //this replaces the ugly check fields methods calls
962
+ foreach (array('upload','color','date','time','code','select','editor','plupload') as $type) {
963
+ call_user_func ( array( $this, 'check_field_' . $type ));
964
+ }
965
+
966
+ wp_enqueue_script('common');
967
+ if ($this->has_Field('TABS')){
968
+ wp_print_scripts('jquery-ui-tabs');
969
+ }
970
+
971
+ // Enqueue admin page Style
972
+ wp_enqueue_style( 'Admin_Page_Class', $plugin_path . '/css/Admin_Page_Class.css' );
973
+ wp_enqueue_style('iphone_checkbox',$plugin_path. '/js/FancyCheckbox/FancyCheckbox.css');
974
+
975
+ // Enqueue admin page Scripts
976
+ wp_enqueue_script( 'Admin_Page_Class', $plugin_path . '/js/Admin_Page_Class.js', array( 'jquery' ), null, true );
977
+ wp_enqueue_script('iphone_checkbox',$plugin_path. '/js/FancyCheckbox/FancyCheckbox.js',array('jquery'),null,true);
978
+
979
+ wp_enqueue_script('utils');
980
+ wp_enqueue_script( 'jquery-ui-sortable' );
981
+ }
982
+
983
+
984
+ /**
985
+ * Check Field code editor
986
+ *
987
+ * @since 0.1
988
+ * @access public
989
+ */
990
+ public function check_field_code() {
991
+
992
+ if ( $this->has_field( 'code' ) && $this->is_edit_page() ) {
993
+ $plugin_path = $this->SelfPath;
994
+ // Enqueu codemirror js and css
995
+ wp_enqueue_style( 'at-code-css', $plugin_path .'/js/codemirror/codemirror.css',array(),null);
996
+ wp_enqueue_style( 'at-code-css-dark', $plugin_path .'/js/codemirror/solarizedDark.css',array(),null);
997
+ wp_enqueue_style( 'at-code-css-light', $plugin_path .'/js/codemirror/solarizedLight.css',array(),null);
998
+ wp_enqueue_script('at-code-js',$plugin_path .'/js/codemirror/codemirror.js',array('jquery'),false,true);
999
+ wp_enqueue_script('at-code-js-xml',$plugin_path .'/js/codemirror/xml.js',array('jquery'),false,true);
1000
+ wp_enqueue_script('at-code-js-javascript',$plugin_path .'/js/codemirror/javascript.js',array('jquery'),false,true);
1001
+ wp_enqueue_script('at-code-js-css',$plugin_path .'/js/codemirror/css.js',array('jquery'),false,true);
1002
+ wp_enqueue_script('at-code-js-clike',$plugin_path .'/js/codemirror/clike.js',array('jquery'),false,true);
1003
+ wp_enqueue_script('at-code-js-php',$plugin_path .'/js/codemirror/php.js',array('jquery'),false,true);
1004
+
1005
+ }
1006
+ }
1007
+
1008
+
1009
+
1010
+ /**
1011
+ * Check For editor field to enqueue editor scripts
1012
+ * @since 1.1.3
1013
+ * @access public
1014
+ */
1015
+ public function check_field_editor(){
1016
+ if ($this->has_Field('editor')){
1017
+ global $wp_version;
1018
+ if ( version_compare( $wp_version, '3.2.1' ) < 1 ) {
1019
+ wp_print_scripts('tiny_mce');
1020
+ wp_print_scripts('editor');
1021
+ wp_print_scripts('editor-functions');
1022
+ }
1023
+ }
1024
+ }
1025
+
1026
+ /**
1027
+ * Check For select field to enqueue Select2 #see http://goo.gl/3pjY8
1028
+ * @since 1.1.3
1029
+ * @access public
1030
+ */
1031
+ public function check_field_select(){
1032
+ if ($this->has_field_any(array('select','typo')) && $this->is_edit_page()) {
1033
+ $plugin_path = $this->SelfPath;
1034
+ // Enqueu JQuery chosen library, use proper version.
1035
+ wp_enqueue_style('at-multiselect-chosen-css', $plugin_path . '/js/select2/select2.css', array(), null);
1036
+
1037
+ wp_enqueue_script('at-multiselect-chosen-js', $plugin_path . '/js/select2/select2.js', array('jquery'), false, true);
1038
+ }
1039
+ }
1040
+
1041
+ /**
1042
+ * Check Field Plupload
1043
+ *
1044
+ * @since 0.9.7
1045
+ * @access public
1046
+ */
1047
+ public function check_field_plupload(){
1048
+ if ( $this->has_field( 'plupload' ) && $this->is_edit_page() ) {
1049
+ $plugin_path = $this->SelfPath;
1050
+ wp_enqueue_script('plupload-all');
1051
+ wp_register_script('myplupload', $plugin_path .'/js/plupload/myplupload.js', array('jquery'));
1052
+ wp_enqueue_script('myplupload');
1053
+ wp_register_style('myplupload', $plugin_path .'/js/plupload/myplupload.css');
1054
+ wp_enqueue_style('myplupload');
1055
+ }
1056
+ }
1057
+
1058
+
1059
+ /**
1060
+ * Check the Field Upload, Add needed Actions
1061
+ *
1062
+ * @since 0.1
1063
+ * @access public
1064
+ */
1065
+ public function check_field_upload() {
1066
+
1067
+ // Check if the field is an image or file. If not, return.
1068
+ if ( ! $this->has_field_any(array('image','file')) )
1069
+ return;
1070
+
1071
+ // Add data encoding type for file uploading.
1072
+ add_action( 'post_edit_form_tag', array( $this, 'add_enctype' ) );
1073
+
1074
+ if( wp_style_is( 'wp-color-picker', 'registered' ) ){ //since WordPress 3.5
1075
+ wp_enqueue_media();
1076
+ wp_enqueue_script('media-upload');
1077
+ }else{
1078
+ // Make upload feature work event when custom post type doesn't support 'editor'
1079
+ wp_enqueue_script( 'media-upload' );
1080
+ add_thickbox();
1081
+ wp_enqueue_script( 'jquery-ui-core' );
1082
+ wp_enqueue_script( 'jquery-ui-sortable' );
1083
+ }
1084
+
1085
+
1086
+ // Add filters for media upload.
1087
+ add_filter( 'media_upload_gallery', array( $this, 'insert_images' ) );
1088
+ add_filter( 'media_upload_library', array( $this, 'insert_images' ) );
1089
+ add_filter( 'media_upload_image', array( $this, 'insert_images' ) );
1090
+
1091
+ // Delete all attachments when delete custom post type.
1092
+ add_action( 'wp_ajax_at_delete_file', array( $this, 'delete_file' ) );
1093
+ add_action( 'wp_ajax_at_reorder_images', array( $this, 'reorder_images' ) );
1094
+ // Delete file via Ajax
1095
+ add_action( 'wp_ajax_at_delete_mupload', array( $this, 'wp_ajax_delete_image' ) );
1096
+ }
1097
+
1098
+ /**
1099
+ * Add data encoding type for file uploading
1100
+ *
1101
+ * @since 0.1
1102
+ * @access public
1103
+ */
1104
+ public function add_enctype () {
1105
+ echo ' enctype="multipart/form-data"';
1106
+ }
1107
+
1108
+ /**
1109
+ * Process images added to meta field.
1110
+ *
1111
+ * Modified from Faster Image Insert plugin.
1112
+ *
1113
+ * @return void
1114
+ * @author Cory Crowley
1115
+ */
1116
+ public function insert_images() {
1117
+
1118
+ // If post variables are empty, return.
1119
+ if ( ! isset( $_POST['at-insert'] ) || empty( $_POST['attachments'] ) )
1120
+ return;
1121
+
1122
+ // Security Check
1123
+ check_admin_referer( 'media-form' );
1124
+
1125
+ // Create Security Nonce
1126
+ $nonce = wp_create_nonce( 'at_ajax_delete' );
1127
+
1128
+ // Get Post Id and Field Id
1129
+ $id = $_POST['field_id'];
1130
+
1131
+ // Modify the insertion string
1132
+ $html = '';
1133
+ foreach( $_POST['attachments'] as $attachment_id => $attachment ) {
1134
+
1135
+ // Strip Slashes
1136
+ $attachment = stripslashes_deep( $attachment );
1137
+
1138
+ // If not selected or url is empty, continue in loop.
1139
+ if ( empty( $attachment['selected'] ) || empty( $attachment['url'] ) )
1140
+ continue;
1141
+
1142
+ $li = "<li id='item_{$attachment_id}'>";
1143
+ $li .= "<img src='{$attachment['url']}' alt='image_{$attachment_id}' />";
1144
+ //$li .= "<a title='" . __( 'Delete this image' ) . "' class='at-delete-file' href='#' rel='{$nonce}|{$post_id}|{$id}|{$attachment_id}'>" . __( 'Delete' ) . "</a>";
1145
+ $li .= "<a title='" . __( 'Delete this image','apc' ) . "' class='at-delete-file' href='#' rel='{$nonce}|{$post_id}|{$id}|{$attachment_id}'><img src='" . $this->SelfPath. "/images/delete-16.png' alt='" . __( 'Delete' ,'apc') . "' /></a>";
1146
+ $li .= "<input type='hidden' name='{$id}[]' value='{$attachment_id}' />";
1147
+ $li .= "</li>";
1148
+ $html .= $li;
1149
+
1150
+ } // End For Each
1151
+
1152
+ return media_send_to_editor( $html );
1153
+
1154
+ }
1155
+
1156
+ /**
1157
+ * Delete attachments associated with the post.
1158
+ *
1159
+ * @since 0.1
1160
+ * @access public
1161
+ *
1162
+ */
1163
+ public function delete_attachments( $post_id ) {
1164
+
1165
+ // Get Attachments
1166
+ $attachments = get_posts( array( 'numberposts' => -1, 'post_type' => 'attachment', 'post_parent' => $post_id ) );
1167
+
1168
+ // Loop through attachments, if not empty, delete it.
1169
+ if ( ! empty( $attachments ) ) {
1170
+ foreach ( $attachments as $att ) {
1171
+ wp_delete_attachment( $att->ID );
1172
+ }
1173
+ }
1174
+
1175
+ }
1176
+
1177
+
1178
+ /**
1179
+ * Ajax callback for deleting files.
1180
+ * Modified from a function used by "Verve Meta Boxes" plugin (http://goo.gl/LzYSq)
1181
+ * @since 0.1
1182
+ * @access public
1183
+ */
1184
+ public function wp_ajax_delete_image() {
1185
+ $field_id = isset( $_GET['field_id'] ) ? $_GET['field_id'] : 0;
1186
+ $attachment_id = isset( $_GET['attachment_id'] ) ? intval( $_GET['attachment_id'] ) : 0;
1187
+ $ok = false;
1188
+ $remove_meta_only = apply_filters("apc_delete_image",true);
1189
+ if (strpos($field_id, '[') === false){
1190
+ check_admin_referer( "at-delete-mupload_".urldecode($field_id));
1191
+ $temp = get_option($this->args['option_group']);
1192
+ unset($temp[$field_id]);
1193
+ update_option($this->args['option_group'],$temp);
1194
+ if (!$remove_meta_only)
1195
+ $ok = wp_delete_attachment( $attachment_id );
1196
+ else
1197
+ $ok = true;
1198
+ }else{
1199
+ $f = explode('[',urldecode($field_id));
1200
+ $f_fiexed = array();
1201
+ foreach ($f as $k => $v){
1202
+ $f[$k] = str_replace(']','',$v);
1203
+ }
1204
+ $temp = get_option($this->args['option_group']);
1205
+
1206
+ /**
1207
+ * repeater block
1208
+ * $f[0] = repeater id
1209
+ * $f[1] = repeater item number
1210
+ * $f[2] = actuall in repeater item image field id
1211
+ *
1212
+ * conditional block
1213
+ * $f[0] = conditional id
1214
+ * $f[1] = actuall in conditional block image field id
1215
+ */
1216
+ $saved = $temp[$f[0]];
1217
+ if (isset($f[2]) && isset($saved[$f[1]][$f[2]])){ //delete from repeater block
1218
+ unset($saved[$f[1]][$f[2]]);
1219
+ $temp[$f[0]] = $saved;
1220
+ update_option($this->args['option_group'],$temp);
1221
+ if (!$remove_meta_only)
1222
+ $ok = wp_delete_attachment( $attachment_id );
1223
+ else
1224
+ $ok = true;
1225
+ }elseif(isset($saved[$f[1]]['src'])){ //delete from conditional block
1226
+ unset($saved[$f[1]]);
1227
+ $temp[$f[0]] = $saved;
1228
+ update_option($this->args['option_group'],$temp);
1229
+ if (!$remove_meta_only)
1230
+ $ok = wp_delete_attachment( $attachment_id );
1231
+ else
1232
+ $ok = true;
1233
+ }
1234
+ }
1235
+
1236
+ if ( $ok ){
1237
+ echo json_encode( array('status' => 'success' ));
1238
+ die();
1239
+ }else{
1240
+ echo json_encode(array('message' => __( 'Cannot delete file. Something\'s wrong.','apc')));
1241
+ die();
1242
+ }
1243
+ }
1244
+
1245
+ /**
1246
+ * Ajax callback for reordering Images.
1247
+ *
1248
+ * @since 0.1
1249
+ * @access public
1250
+ */
1251
+ public function reorder_images() {
1252
+
1253
+ if ( ! isset( $_POST['data'] ) )
1254
+ die();
1255
+
1256
+ list( $order, $post_id, $key, $nonce ) = explode( '|', $_POST['data'] );
1257
+
1258
+ if ( ! wp_verify_nonce( $nonce, 'at_ajax_reorder' ) )
1259
+ die( '1' );
1260
+
1261
+ parse_str( $order, $items );
1262
+ $items = $items['item'];
1263
+ $order = 1;
1264
+ foreach ( $items as $item ) {
1265
+ wp_update_post( array( 'ID' => $item, 'post_parent' => $post_id, 'menu_order' => $order ) );
1266
+ $order++;
1267
+ }
1268
+
1269
+ die( '0' );
1270
+
1271
+ }
1272
+
1273
+ /**
1274
+ * Check Field Color
1275
+ *
1276
+ * @since 0.1
1277
+ * @access public
1278
+ */
1279
+ public function check_field_color() {
1280
+
1281
+ if ( $this->has_field_any(array('color' ,'typo' )) && $this->is_edit_page() ) {
1282
+ if( wp_style_is( 'wp-color-picker', 'registered' ) ) {
1283
+ wp_enqueue_style( 'wp-color-picker' );
1284
+ wp_enqueue_script( 'wp-color-picker' );
1285
+ }else{
1286
+ // Enqueu built-in script and style for color picker.
1287
+ wp_enqueue_style( 'farbtastic' );
1288
+ wp_enqueue_script( 'farbtastic' );
1289
+ }
1290
+ }
1291
+
1292
+ }
1293
+
1294
+ /**
1295
+ * Check Field Date
1296
+ *
1297
+ * @since 0.1
1298
+ * @access public
1299
+ */
1300
+ public function check_field_date() {
1301
+
1302
+ if ( $this->has_field( 'date' ) && $this->is_edit_page() ) {
1303
+ $plugin_path = $this->SelfPath;
1304
+ // Enqueu JQuery UI, use proper version.
1305
+ wp_enqueue_style( 'jquery-ui-css', $plugin_path.'/css/jquery-ui.css' );
1306
+ wp_enqueue_script( 'jquery-ui');
1307
+ wp_enqueue_script( 'jquery-ui-datepicker');
1308
+ }
1309
+
1310
+ }
1311
+
1312
+ /**
1313
+ * Check Field Time
1314
+ *
1315
+ * @since 0.1
1316
+ * @access public
1317
+ */
1318
+ public function check_field_time() {
1319
+
1320
+ if ( $this->has_field( 'time' ) && $this->is_edit_page() ) {
1321
+ $plugin_path = $this->SelfPath;
1322
+
1323
+ wp_enqueue_style( 'jquery-ui-css', $plugin_path.'/css/jquery-ui.css' );
1324
+ wp_enqueue_script( 'jquery-ui');
1325
+ wp_enqueue_script( 'at-timepicker', $plugin_path . '/js/time-and-date/jquery-ui-timepicker-addon.js', array( 'jquery-ui-slider','jquery-ui-datepicker' ), null, true );
1326
+
1327
+ }
1328
+
1329
+ }
1330
+
1331
+ /**
1332
+ * Add Meta Box for multiple post types.
1333
+ *
1334
+ * @since 0.1
1335
+ * @access public
1336
+ */
1337
+ public function add() {
1338
+
1339
+ // Loop through array
1340
+ foreach ( $this->_meta_box['pages'] as $page ) {
1341
+ add_meta_box( $this->_meta_box['id'], $this->_meta_box['title'], array( $this, 'show' ), $page, $this->_meta_box['context'], $this->_meta_box['priority'] );
1342
+ }
1343
+
1344
+ }
1345
+
1346
+ /**
1347
+ * Callback function to show fields in Page.
1348
+ *
1349
+ * @since 0.1
1350
+ * @access public
1351
+ */
1352
+ public function show() {
1353
+
1354
+ global $post;
1355
+ wp_nonce_field( basename(__FILE__), 'BF_Admin_Page_Class_nonce' );
1356
+ echo '<table class="form-table">';
1357
+ foreach ( $this->_fields as $field ) {
1358
+ $meta = get_post_meta( $post->ID, $field['id'], !$field['multiple'] );
1359
+ $meta = ( $meta !== '' ) ? $meta : $field['std'];
1360
+ if ('image' != $field['type'] && $field['type'] != 'repeater')
1361
+ $meta = is_array( $meta ) ? array_map( 'esc_attr', $meta ) : esc_attr( $meta );
1362
+ echo '<tr>';
1363
+
1364
+ // Call Separated methods for displaying each type of field.
1365
+ call_user_func ( array( $this, 'show_field_' . $field['type'] ), $field, $meta );
1366
+ echo '</tr>';
1367
+ }
1368
+ echo '</table>';
1369
+ }
1370
+
1371
+ /**
1372
+ * Show Repeater Fields.
1373
+ *
1374
+ * @param string $field
1375
+ * @param string $meta
1376
+ * @since 0.1
1377
+ * @modified at 0.4 added sortable option
1378
+ * @access public
1379
+ */
1380
+ public function show_field_repeater( $field, $meta ) {
1381
+ // Get Plugin Path
1382
+ $plugin_path = $this->SelfPath;
1383
+ $this->show_field_begin( $field, $meta );
1384
+ $class = '';
1385
+ if ($field['sortable'])
1386
+ $class = " repeater-sortable";
1387
+ $jsid = ltrim(strtolower(str_replace(' ','',$field['id'])), '0123456789');
1388
+ echo "<div class='at-repeat".$class."' id='{$jsid}'>";
1389
+
1390
+ $c = 0;
1391
+ $temp_div_row = $this->_div_or_row;
1392
+ $this->_div_or_row = true;
1393
+ $meta = isset($this->_saved[$field['id']])? $this->_saved[$field['id']]: '';
1394
+
1395
+ if (count($meta) > 0 && is_array($meta) ){
1396
+ foreach ($meta as $me){
1397
+ //for labling toggles
1398
+ $mmm = isset($me[$field['fields'][0]['id']])? $me[$field['fields'][0]['id']]: "";
1399
+ $mmm = (in_array($field['fields'][0]['type'],array('image','file'))? '' : $mmm);
1400
+ echo '<div class="at-repater-block">'.$mmm.'<br/><table class="repeater-table" style="display: none;">';
1401
+ if ($field['inline']){
1402
+ echo '<tr class="at-inline" VALIGN="top">';
1403
+ }
1404
+ foreach ($field['fields'] as $f){
1405
+ //reset var $id for repeater
1406
+ $id = '';
1407
+ $id = $field['id'].'['.$c.']['.$f['id'].']';
1408
+ $m = isset($me[$f['id']])? $me[$f['id']]: '';
1409
+ if ( $m !== '' ) {
1410
+ $m = $m;
1411
+ }else{
1412
+ $m = isset($f['std'])? $f['std'] : '';
1413
+ }
1414
+ if ('image' != $f['type'] && $f['type'] != 'repeater')
1415
+ $m = is_array( $m) ? array_map( 'esc_attr', $m ) : esc_attr( $m);
1416
+ if (in_array($f['type'],array('text','textarea')))
1417
+ $m = stripslashes($m);
1418
+ //set new id for field in array format
1419
+ $f['id'] = $id;
1420
+ if (!$field['inline']){
1421
+ echo '<tr>';
1422
+ }
1423
+ call_user_func ( array( $this, 'show_field_' . $f['type'] ), $f, $m);
1424
+ if (!$field['inline']){
1425
+ echo '</tr>';
1426
+ }
1427
+ }
1428
+ if ($field['inline']){
1429
+ echo '</tr>';
1430
+ }
1431
+ echo '</table>
1432
+ <span class="at-re-toggle"><img src="';
1433
+ if ($this->_Local_images){
1434
+ echo $plugin_path.'/images/edit.png';
1435
+ }else{
1436
+ echo 'http://i.imgur.com/ka0E2.png';
1437
+ }
1438
+ echo '" alt="Edit" title="Edit"/></span>
1439
+ <img src="';
1440
+ if ($this->_Local_images){
1441
+ echo $plugin_path.'/images/remove.png';
1442
+ }else{
1443
+ echo 'http://i.imgur.com/g8Duj.png';
1444
+ }
1445
+ echo '" alt="'.__('Remove','apc').'" title="'.__('Remove','apc').'" id="remove-'.$field['id'].'"></div>';
1446
+ $c = $c + 1;
1447
+
1448
+ }
1449
+ }
1450
+
1451
+ echo '<img src="';
1452
+ if ($this->_Local_images){
1453
+ echo $plugin_path.'/images/add.png';
1454
+ }else{
1455
+ echo 'http://i.imgur.com/w5Tuc.png';
1456
+ }
1457
+ echo '" alt="'.__('Add','apc').'" title="'.__('Add','apc').'" id="add-'.$jsid.'"><br/></div>';
1458
+
1459
+ //create all fields once more for js function and catch with object buffer
1460
+ ob_start();
1461
+ echo '<div class="at-repater-block"><table class="repeater-table">';
1462
+ if ($field['inline']){
1463
+ echo '<tr class="at-inline" VALIGN="top">';
1464
+ }
1465
+ foreach ($field['fields'] as $f){
1466
+ //reset var $id for repeater
1467
+ $id = '';
1468
+
1469
+ $id = $field['id'].'[CurrentCounter]['.$f['id'].']';
1470
+ $f['id'] = $id;
1471
+ if (!$field['inline']){
1472
+ echo '<tr>';
1473
+ }
1474
+ $m = isset($f['std'])? $f['std'] : '';
1475
+ call_user_func ( array( $this, 'show_field_' . $f['type'] ), $f, $m);
1476
+ if (!$field['inline']){
1477
+ echo '</tr>';
1478
+ }
1479
+ }
1480
+ if ($field['inline']){
1481
+ echo '</tr>';
1482
+ }
1483
+ echo '</table><img src="';
1484
+ if ($this->_Local_images){
1485
+ echo $plugin_path.'/images/remove.png';
1486
+ }else{
1487
+ echo 'http://i.imgur.com/g8Duj.png';
1488
+ }
1489
+
1490
+ echo '" alt="'.__('Remove','apc').'" title="'.__('Remove','apc').'" id="remove-'.$jsid.'"></div>';
1491
+ $counter = 'countadd_'.$jsid;
1492
+ $js_code = ob_get_clean ();
1493
+ $js_code = str_replace("'","\"",$js_code);
1494
+ $js_code = str_replace("CurrentCounter","' + ".$counter." + '",$js_code);
1495
+ echo '<script>
1496
+ jQuery(document).ready(function() {
1497
+ var '.$counter.' = '.$c.';
1498
+ jQuery("#add-'.$jsid.'").live(\'click\', function() {
1499
+ '.$counter.' = '.$counter.' + 1;
1500
+ jQuery(this).before(\''.$js_code.'\');
1501
+ update_repeater_fields();
1502
+ });
1503
+ jQuery("#remove-'.$jsid.'").live(\'click\', function() {
1504
+ jQuery(this).parent().remove();
1505
+ });
1506
+ });
1507
+ </script>';
1508
+ echo '<br/><style>
1509
+ .at-inline{line-height: 1 !important;}
1510
+ .at-inline .at-field{border: 0px !important;}
1511
+ .at-inline .at-label{margin: 0 0 1px !important;}
1512
+ .at-inline .at-text{width: 70px;}
1513
+ .at-inline .at-textarea{width: 100px; height: 75px;}
1514
+ .at-repater-block{background-color: #FFFFFF;border: 1px solid;margin: 2px;}
1515
+ </style>';
1516
+
1517
+ $this->_div_or_row = $temp_div_row;
1518
+ $this->show_field_end($field, $meta);
1519
+ }
1520
+
1521
+ /**
1522
+ * Begin Field.
1523
+ *
1524
+ * @param string $field
1525
+ * @param string $meta
1526
+ * @since 0.1
1527
+ * @access public
1528
+ */
1529
+ public function show_field_begin( $field, $meta) {
1530
+ if ($this->_div_or_row){
1531
+ echo "<td class='at-field'>";
1532
+ }
1533
+
1534
+ //check for errors
1535
+ if ($this->saved_flag && $this->errors_flag && isset($field['validate']) && isset($field['id']) && $this->has_error($field['id'])){
1536
+ echo '<div class="alert alert-error field-validation-error"><button data-dismiss="alert" class="close" type="button">×</button>';
1537
+ $ers = $this->getFieldErrors($field['id']);
1538
+ foreach ((array)$ers['m'] as $m) {
1539
+ echo "{$m}</br />";
1540
+ }
1541
+ echo '</div>';
1542
+ }
1543
+
1544
+ if ( $field['name'] != '' || $field['name'] != FALSE )
1545
+ echo "<div class='at-label'><label for='{$field['id']}'>{$field['name']}</label></div>";
1546
+ }
1547
+
1548
+ /**
1549
+ * End Field.
1550
+ *
1551
+ * @param string $field
1552
+ * @param string $meta
1553
+ * @since 0.1
1554
+ * @access public
1555
+ */
1556
+ public function show_field_end( $field, $meta=NULL ,$group = false) {
1557
+ if ( isset($field['desc']) && $field['desc'] != '' )
1558
+ echo "<div class='desc-field'>{$field['desc']}</div>";
1559
+
1560
+ if ($this->_div_or_row)
1561
+ echo "</td>";
1562
+
1563
+
1564
+ }
1565
+
1566
+ /**
1567
+ * Show Sortable Field
1568
+ * @author Ohad Raz
1569
+ * @since 0.4
1570
+ * @access public
1571
+ * @param (array) $field
1572
+ * @param (array) $meta
1573
+ * @return void
1574
+ */
1575
+ public function show_field_sortable( $field, $meta ) {
1576
+
1577
+ $this->show_field_begin( $field, $meta );
1578
+ $re = '<div class="at-sortable-con"><ul class="at-sortable">'."\n";
1579
+ $i = 0;
1580
+
1581
+ $array_check = array_diff_key($field['options'],$meta);
1582
+ $array_check_2 = array_intersect_key($meta,$field['options']);
1583
+
1584
+ // Check if a new option has been added
1585
+ if(is_array( $array_check ) || !empty($array_check) ) {
1586
+ $meta = array_merge( $meta , $array_check );
1587
+ $array_check_2 = array_merge( $array_check , $array_check_2);
1588
+ };
1589
+
1590
+ // Check if an option has been removed
1591
+ if( $array_check_2 != $meta ) {
1592
+ $meta = $array_check_2;
1593
+ };
1594
+
1595
+ if ( ! is_array( $meta ) || empty($meta) ){
1596
+ foreach ( $field['options'] as $value => $label ) {
1597
+ $re .= '<li class="widget-sort at-sort-item_'.$i.'">'.$label.'<input type="hidden" value="'.$label.'" name="'.$field['id'].'['.$value.']">'."\n";
1598
+ }
1599
+ }
1600
+ else{
1601
+ foreach ( $meta as $value => $label ) {
1602
+ $re .= '<li class="widget-sort at-sort-item_'.$i.'">'.$label.'<input type="hidden" value="'.$label.'" name="'.$field['id'].'['.$value.']">'."\n";
1603
+ }
1604
+ }
1605
+ $re .= '</ul>'."\n".'</div>'."\n";
1606
+ echo $re;
1607
+ $this->show_field_end( $field, $meta );
1608
+ }
1609
+
1610
+ /**
1611
+ * Show Field Text.
1612
+ *
1613
+ * @param string $field
1614
+ * @param string $meta
1615
+ * @since 0.1
1616
+ * @access public
1617
+ */
1618
+ public function show_field_text( $field, $meta) {
1619
+ $this->show_field_begin( $field, $meta );
1620
+ echo "<input type='text' class='at-text".(isset($field['class'])? " {$field['class']}": "")."' name='{$field['id']}' id='{$field['id']}' value='{$meta}' size='30' /><div class='clearfix'></div>";
1621
+ $this->show_field_end( $field, $meta );
1622
+ }
1623
+
1624
+ /**
1625
+ * Show Field Plupload.
1626
+ *
1627
+ * @param string $field
1628
+ * @param string $meta
1629
+ * @since 0.9.7
1630
+ * @access public
1631
+ */
1632
+ public function show_field_plupload( $field, $meta) {
1633
+
1634
+ $this->show_field_begin($field,$meta);
1635
+ $id = $field['id']; // this will be the name of form field. Image url(s) will be submitted in $_POST using this key. So if $id == “img1” then $_POST[“img1”] will have all the image urls
1636
+ $multiple = $field['multiple']; // allow multiple files upload
1637
+ $m1 = ($multiple)? 'plupload-upload-uic-multiple':'';
1638
+ $m2 = ($multiple)? 'plupload-thumbs-multiple':'';
1639
+ $width = $field['width']; // If you want to automatically resize all uploaded images then provide width here (in pixels)
1640
+ $height = $field['height']; // If you want to automatically resize all uploaded images then provide height here (in pixels)
1641
+ $html = '
1642
+ <input type="hidden" name="'.$id.'" id="'. $id.'" value="'.$meta .'" />
1643
+ <div class="plupload-upload-uic hide-if-no-js '.$m1.'" id="'.$id.'plupload-upload-ui">
1644
+ <input id="'.$id.'plupload-browse-button" type="button" value="'.__('Select Files','apc').'" class="button" />
1645
+ <span class="ajaxnonceplu" id="ajaxnonceplu'.wp_create_nonce($id . 'pluploadan').'"></span>';
1646
+ if ($width && $height){
1647
+ $html .= '<span class="plupload-resize"></span><span class="plupload-width" id="plupload-width'.$width.'"></span>
1648
+ <span class="plupload-height" id="plupload-height'.$height.'"></span>';
1649
+ }
1650
+ $html .= '<div class="filelist"></div>
1651
+ </div>
1652
+ <div class="plupload-thumbs '.$m2.'" id="'.$id.'plupload-thumbs">
1653
+ </div>
1654
+ <div class="clear"></div>';
1655
+ echo $html;
1656
+ $this->show_field_end($field,$meta);
1657
+ }
1658
+
1659
+ /**
1660
+ * Show Field code editor.
1661
+ *
1662
+ * @param string $field
1663
+ * @author Ohad Raz
1664
+ * @param string $meta
1665
+ * @since 0.1
1666
+ * @access public
1667
+ */
1668
+ public function show_field_code( $field, $meta) {
1669
+ $this->show_field_begin( $field, $meta );
1670
+ echo "<textarea class='code_text".(isset($field['class'])? " {$field['class']}": "")."' name='{$field['id']}' id='{$field['id']}' data-lang='{$field['syntax']}' data-theme='{$field['theme']}'>".stripslashes($meta)."</textarea>";
1671
+ $this->show_field_end( $field, $meta );
1672
+ }
1673
+
1674
+
1675
+ /**
1676
+ * Show Field hidden.
1677
+ *
1678
+ * @param string $field
1679
+ * @param string|mixed $meta
1680
+ * @since 0.1
1681
+ * @access public
1682
+ */
1683
+ public function show_field_hidden( $field, $meta) {
1684
+ echo "<input type='hidden' class='at-hidden".(isset($field['class'])? " {$field['class']}": "")."' name='{$field['id']}' id='{$field['id']}' value='{$meta}'/>";
1685
+ }
1686
+
1687
+ /**
1688
+ * Show Field Paragraph.
1689
+ *
1690
+ * @param string $field
1691
+ * @since 0.1
1692
+ * @access public
1693
+ */
1694
+ public function show_field_paragraph( $field) {
1695
+ echo '<p>'.$field['value'].'</p>';
1696
+ }
1697
+
1698
+ /**
1699
+ * Show Field Textarea.
1700
+ *
1701
+ * @param string $field
1702
+ * @param string $meta
1703
+ * @since 0.1
1704
+ * @access public
1705
+ */
1706
+ public function show_field_textarea( $field, $meta ) {
1707
+ $this->show_field_begin( $field, $meta );
1708
+ echo "<textarea class='at-textarea large-text".(isset($field['class'])? " {$field['class']}": "")."' name='{$field['id']}' id='{$field['id']}' cols='60' rows='10'>{$meta}</textarea>";
1709
+ $this->show_field_end( $field, $meta );
1710
+ }
1711
+
1712
+ /**
1713
+ * Show Field Select.
1714
+ *
1715
+ * @param string $field
1716
+ * @param string $meta
1717
+ * @since 0.1
1718
+ * @access public
1719
+ */
1720
+ public function show_field_select( $field, $meta ) {
1721
+
1722
+ if ( ! is_array( $meta ) )
1723
+ $meta = (array) $meta;
1724
+
1725
+ $this->show_field_begin( $field, $meta );
1726
+ echo "<select class='no-fancy at-select".(isset($field['class'])? " {$field['class']}": "")."' name='{$field['id']}" . ((isset($field['multiple']) && $field['multiple']) ? "[]' id='{$field['id']}' multiple='multiple'" : "'" ) . ">";
1727
+ foreach ( $field['options'] as $key => $value ) {
1728
+ echo "<option value='{$key}'" . selected( in_array( $key, $meta ), true, false ) . ">{$value}</option>";
1729
+ }
1730
+ echo "</select><div class='clearfix'></div>";
1731
+ $this->show_field_end( $field, $meta );
1732
+ }
1733
+
1734
+ /**
1735
+ * Show Radio Field.
1736
+ *
1737
+ * @param string $field
1738
+ * @param string $meta
1739
+ * @since 0.1
1740
+ * @access public
1741
+ */
1742
+ public function show_field_radio( $field, $meta ) {
1743
+
1744
+ if ( ! is_array( $meta ) )
1745
+ $meta = (array) $meta;
1746
+
1747
+ $this->show_field_begin( $field, $meta );
1748
+ foreach ( $field['options'] as $key => $value ) {
1749
+ echo "<input type='radio' class='at-radio".(isset($field['class'])? " {$field['class']}": "")."' name='{$field['id']}' value='{$key}'" . checked( in_array( $key, $meta ), true, false ) . " /> <span class='at-radio-label'>{$value}</span>";
1750
+ }
1751
+ $this->show_field_end( $field, $meta );
1752
+ }
1753
+
1754
+ /**
1755
+ * Show Checkbox Field.
1756
+ *
1757
+ * @param string $field
1758
+ * @param string $meta
1759
+ * @since 0.1
1760
+ * @access public
1761
+ */
1762
+ public function show_field_checkbox( $field, $meta ) {
1763
+
1764
+ $this->show_field_begin($field, $meta);
1765
+ $meta = ($meta == 'on')? true: $meta;
1766
+ echo "<input type='checkbox' class='rw-checkbox".(isset($field['class'])? " {$field['class']}": "")."' name='{$field['id']}' id='{$field['id']}'" . checked($meta, true, false) . " /><div class='clearfix'></div>";
1767
+ $this->show_field_end( $field, $meta );
1768
+ }
1769
+
1770
+ /**
1771
+ * Show conditinal Checkbox Field.
1772
+ *
1773
+ * @param string $field
1774
+ * @param string $meta
1775
+ * @since 0.5
1776
+ * @access public
1777
+ */
1778
+ public function show_field_cond( $field, $meta ) {
1779
+
1780
+ $this->show_field_begin($field, $meta);
1781
+ $checked = false;
1782
+ if (is_array($meta) && isset($meta['enabled']) && $meta['enabled'] == 'on'){
1783
+ $checked = true;
1784
+ }
1785
+ echo "<input type='checkbox' class='conditinal_control' name='{$field['id']}[enabled]' id='{$field['id']}'" . checked($checked, true, false) . " />";
1786
+ //start showing the fields
1787
+ $display = ($checked)? '' : ' style="display: none;"';
1788
+
1789
+ echo '<div class="conditinal_container"'.$display.'>';
1790
+ foreach ((array)$field['fields'] as $f){
1791
+ //reset var $id for cond
1792
+ $id = '';
1793
+ $id = $field['id'].'['.$f['id'].']';
1794
+ $m = '';
1795
+ $m = (isset($meta[$f['id']])) ? $meta[$f['id']]: '';
1796
+ $m = ( $m !== '' ) ? $m : (isset($f['std'])? $f['std'] : '');
1797
+ if ('image' != $f['type'] && $f['type'] != 'repeater')
1798
+ $m = is_array( $m) ? array_map( 'esc_attr', $m ) : esc_attr( $m);
1799
+ //set new id for field in array format
1800
+ $f['id'] = $id;
1801
+ call_user_func ( array( $this, 'show_field_' . $f['type'] ), $f, $m);
1802
+ }
1803
+ echo '</div>';
1804
+ $this->show_field_end( $field, $meta );
1805
+ }
1806
+
1807
+ /**
1808
+ * Show Wysiwig Field.
1809
+ *
1810
+ * @param string $field
1811
+ * @param string $meta
1812
+ * @since 0.1
1813
+ * @access public
1814
+ */
1815
+ public function show_field_wysiwyg( $field, $meta ) {
1816
+ $this->show_field_begin( $field, $meta );
1817
+ // Add TinyMCE script for WP version < 3.3
1818
+ global $wp_version;
1819
+
1820
+ if ( version_compare( $wp_version, '3.2.1' ) < 1 ) {
1821
+ echo "<textarea class='at-wysiwyg theEditor large-text".(isset($field['class'])? " {$field['class']}": "")."' name='{$field['id']}' id='{$field['id']}' cols='60' rows='10'>{$meta}</textarea>";
1822
+ }else{
1823
+ // Use new wp_editor() since WP 3.3
1824
+ wp_editor( stripslashes(stripslashes(html_entity_decode($meta))), $field['id'], array( 'editor_class' => 'at-wysiwyg'.(isset($field['class'])? " {$field['class']}": "")) );
1825
+ }
1826
+ $this->show_field_end( $field, $meta );
1827
+ }
1828
+
1829
+ /**
1830
+ * Show File Field.
1831
+ *
1832
+ * @param string $field
1833
+ * @param string $meta
1834
+ * @since 0.1
1835
+ * @access public
1836
+ */
1837
+ public function show_field_file( $field, $meta ) {
1838
+
1839
+ global $post;
1840
+
1841
+ if ( ! is_array( $meta ) )
1842
+ $meta = (array) $meta;
1843
+
1844
+ $this->show_field_begin( $field, $meta );
1845
+ echo "{$field['desc']}<br />";
1846
+
1847
+ if ( ! empty( $meta ) ) {
1848
+ $nonce = wp_create_nonce( 'at_ajax_delete' );
1849
+ echo '<div style="margin-bottom: 10px"><strong>' . __('Uploaded files','apc') . '</strong></div>';
1850
+ echo '<ol class="at-upload">';
1851
+ foreach ( $meta as $att ) {
1852
+ // if (wp_attachment_is_image($att)) continue; // what's image uploader for?
1853
+ echo "<li>" . wp_get_attachment_link( $att, '' , false, false, ' ' ) . " (<a class='at-delete-file' href='#' rel='{$nonce}|{$post->ID}|{$field['id']}|{$att}'>" . __( 'Delete' ,'apc') . "</a>)</li>";
1854
+ }
1855
+ echo '</ol>';
1856
+ }
1857
+
1858
+ // show form upload
1859
+ echo "<div class='at-file-upload-label'>";
1860
+ echo "<strong>" . __( 'Upload new files' ,'apc') . "</strong>";
1861
+ echo "</div>";
1862
+ echo "<div class='new-files'>";
1863
+ echo "<div class='file-input'>";
1864
+ echo "<input type='file' name='{$field['id']}[]' />";
1865
+ echo "</div><!-- End .file-input -->";
1866
+ echo "<a class='at-add-file button' href='#'>" . __( 'Add more files','apc' ) . "</a>";
1867
+ echo "</div><!-- End .new-files -->";
1868
+ echo "</td>";
1869
+ }
1870
+
1871
+
1872
+ public function show_field_media_manager($field,$meta){
1873
+ $this->show_field_begin( $field, $meta );
1874
+ $html = wp_nonce_field( "at-delete-mupload_{$field['id']}", "nonce-delete-mupload_".$field['id'], false, false );
1875
+ $height = (isset($field['preview_height']))? $field['preview_height'] : '150px';
1876
+ $width = (isset($field['preview_width']))? $field['preview_width'] : '150px';
1877
+ $multi = (isset($field['multiple']) && $field['multiple'] == true) ? 'true' : 'false';
1878
+ if (is_array($meta)){
1879
+ if(isset($meta[0]) && is_array($meta[0]))
1880
+ $meta = $meta[0];
1881
+ }
1882
+ if (is_array($meta) && isset($meta['src']) && $meta['src'] != ''){
1883
+ $html .= "<span class='mupload_img_holder' data-wi='".$width."' data-he='".$height."'><img src='".$meta['src']."' style='height: ".$height.";width: ".$width.";' /></span>";
1884
+ $html .= "<input type='hidden' name='".$field['id']."[id]' id='".$field['id']."[id]' value='".$meta['id']."' />";
1885
+ $html .= "<input type='hidden' name='".$field['id']."[src]' id='".$field['id']."[src]' value='".$meta['src']."' />";
1886
+ $html .= "<input class='at-delete_image_button button' type='button' rel='".$field['id']."' value='".__('Delete Image','apc')."' />";
1887
+ }else{
1888
+ $html .= "<span class='mupload_img_holder' data-wi='".$width."' data-he='".$height."' data-multi='".$multi."'></span>";
1889
+ $html .= "<input type='hidden' name='".$field['id']."[id]' id='".$field['id']."[id]' value='' />";
1890
+ $html .= "<input type='hidden' name='".$field['id']."[src]' id='".$field['id']."[src]' value='' />";
1891
+ $html .= "<input class='at-mm-upload_image_button button' type='button' rel='".$field['id']."' value='".__('Upload Image','apc')."' />";
1892
+ }
1893
+ echo $html;
1894
+ $this->show_field_end( $field, $meta );
1895
+ }
1896
+
1897
+ /**
1898
+ * Show Image Field.
1899
+ *
1900
+ * @param array $field
1901
+ * @param array $meta
1902
+ * @since 0.1
1903
+ * @access public
1904
+ */
1905
+ public function show_field_image( $field, $meta ) {
1906
+ $this->show_field_begin( $field, $meta );
1907
+ $html = wp_nonce_field( "at-delete-mupload_{$field['id']}", "nonce-delete-mupload_".$field['id'], false, false );
1908
+ $height = (isset($field['preview_height']))? $field['preview_height'] : '150px';
1909
+ $width = (isset($field['preview_width']))? $field['preview_width'] : '150px';
1910
+ $upload_type = (!function_exists('wp_enqueue_media')) ? 'tk' : 'mm';
1911
+ if (is_array($meta)){
1912
+ if(isset($meta[0]) && is_array($meta[0]))
1913
+ $meta = $meta[0];
1914
+ }
1915
+ if (is_array($meta) && isset($meta['src']) && $meta['src'] != ''){
1916
+ $html .= "<span class='mupload_img_holder' data-wi='".$width."' data-he='".$height."'><img src='".$meta['src']."' style='height: ".$height.";width: ".$width.";' /></span>";
1917
+ $html .= "<input type='hidden' name='".$field['id']."[id]' id='".$field['id']."[id]' value='".$meta['id']."' />";
1918
+ $html .= "<input type='hidden' name='".$field['id']."[src]' id='".$field['id']."[src]' value='".$meta['src']."' />";
1919
+ $html .= "<input class='at-delete_image_button button' type='button' data-u='".$upload_type."' rel='".$field['id']."' value='".__('Delete Image','apc')."' />";
1920
+ }else{
1921
+ $html .= "<span class='mupload_img_holder' data-wi='".$width."' data-he='".$height."'></span>";
1922
+ $html .= "<input type='hidden' name='".$field['id']."[id]' id='".$field['id']."[id]' value='' />";
1923
+ $html .= "<input type='hidden' name='".$field['id']."[src]' id='".$field['id']."[src]' value='' />";
1924
+ $html .= "<input class='at-upload_image_button button' type='button' data-u='".$upload_type."' rel='".$field['id']."' value='".__('Upload Image','apc')."' /><div class='clearfix'></div>";
1925
+ }
1926
+ echo $html;
1927
+ $this->show_field_end( $field, $meta );
1928
+ }
1929
+
1930
+ /**
1931
+ * Show Typography Field.
1932
+ *
1933
+ * @author Ohad Raz
1934
+ * @param array $field
1935
+ * @param array $meta
1936
+ * @since 0.3
1937
+ * @access public
1938
+ *
1939
+ * @last modified 0.4 - faster better selected handeling
1940
+ */
1941
+ public function show_field_typo( $field, $meta ) {
1942
+ $this->show_field_begin( $field, $meta );
1943
+ if (!is_array($meta)){
1944
+ $meta = array(
1945
+ 'size' => '',
1946
+ 'face' => '',
1947
+ 'style' => '',
1948
+ 'color' => '#',
1949
+ 'weight' => '',
1950
+ );
1951
+ }
1952
+ $html = '<select class="at-typography at-typography-size" name="' . esc_attr( $field['id'] . '[size]' ) . '" id="' . esc_attr( $field['id'] . '_size' ) . '">';
1953
+ $op = '';
1954
+ for ($i = 9; $i < 71; $i++) {
1955
+ $size = $i . 'px';
1956
+ $op .= '<option value="' . esc_attr( $size ) . '">' . esc_html( $size ) . '</option>';
1957
+ }
1958
+ if (isset($meta['size']))
1959
+ $op = str_replace('value="'.$meta['size'].'"', 'value="'.$meta['size'].'" selected="selected"', $op);
1960
+ $html .=$op. '</select>';
1961
+
1962
+ // Font Face
1963
+ $html .= '<select class="at-typography at-typography-face" name="' . esc_attr( $field['id'] .'[face]' ) . '" id="' . esc_attr( $field['id'] . '_face' ) . '">';
1964
+
1965
+ $faces = $this->get_fonts_family();
1966
+ $op = '';
1967
+ foreach ( $faces as $key => $face ) {
1968
+ $op .= '<option value="' . esc_attr( $key ) . '">' . esc_html( $face['name'] ) . '</option>';
1969
+ }
1970
+ if (isset($meta['face']))
1971
+ $op = str_replace('value="'.$meta['face'].'"', 'value="'.$meta['face'].'" selected="selected"', $op);
1972
+ $html .= $op. '</select>';
1973
+
1974
+ // Font Weight
1975
+ $html .= '<select class="at-typography at-typography-weight" name="' . esc_attr( $field['id'] .'[weight]' ) . '" id="' . esc_attr( $field['id'] . '_weight' ) . '">';
1976
+ $weights = $this->get_font_weight();
1977
+ $op = '';
1978
+ foreach ( $weights as $key => $label ) {
1979
+ $op .= '<option value="' . esc_attr( $key ) . '">' . esc_html( $label ) . '</option>';
1980
+ }
1981
+ if (isset($meta['weight']))
1982
+ $op = str_replace('value="'.$meta['weight'].'"', 'value="'.$meta['weight'].'" selected="selected"', $op);
1983
+ $html .= $op. '</select>';
1984
+
1985
+ /* Font Style */
1986
+ $html .= '<select class="at-typography at-typography-style" name="'.$field['id'].'[style]" id="'. $field['id'].'_style">';
1987
+ $styles = $this->get_font_style();
1988
+ $op = '';
1989
+ foreach ( $styles as $key => $style ) {
1990
+ $op .= '<option value="' . esc_attr( $key ) . '">'. $style .'</option>';
1991
+ }
1992
+ if (isset($meta['style']))
1993
+ $op = str_replace('value="'.$meta['style'].'"', 'value="'.$meta['style'].'" selected="selected"', $op);
1994
+ $html .= $op. '</select>';
1995
+
1996
+ // Font Color
1997
+ if( wp_style_is( 'wp-color-picker', 'registered' ) ) { //iris color picker since 3.5
1998
+ $html .= "<input class='at-color-iris' type='text' name='{$field['id']}[color]' id='{$field['id']}[color]' value='".$meta['color']."' size='8' />";
1999
+ }else{
2000
+ $html .= "<input class='at-color' type='text' name='".$field['id']."[color]' id='".$field['id']."[color]' value='".$meta['color'] ."' size='6' />";
2001
+ $html .= "<input type='button' class='at-color-select button' rel='".$field['id']."[color]' value='" . __( 'Select a color' ,'apc') . "'/>";
2002
+ $html .= "<div style='display:none' class='at-color-picker' rel='".$field['id']."[color]'></div>";
2003
+ }
2004
+
2005
+ echo $html;
2006
+ $this->show_field_end( $field, $meta );
2007
+ }
2008
+
2009
+ /**
2010
+ * Show Color Field.
2011
+ *
2012
+ * @param string $field
2013
+ * @param string $meta
2014
+ * @since 0.1
2015
+ * @access public
2016
+ */
2017
+ public function show_field_color( $field, $meta ) {
2018
+
2019
+ if ( empty( $meta ) )
2020
+ $meta = '#';
2021
+
2022
+ $this->show_field_begin( $field, $meta );
2023
+ if( wp_style_is( 'wp-color-picker', 'registered' ) ) { //iris color picker since 3.5
2024
+ echo "<input class='at-color-iris".(isset($field['class'])? " {$field['class']}": "")."' type='text' name='{$field['id']}' id='{$field['id']}' value='{$meta}' size='8' /><div class='clearfix'></div>";
2025
+ }else{
2026
+ echo "<input class='at-color".(isset($field['class'])? " {$field['class']}": "")."' type='text' name='{$field['id']}' id='{$field['id']}' value='{$meta}' size='8' />";
2027
+ echo "<input type='button' class='at-color-select button' rel='{$field['id']}' value='" . __( 'Select a color' ,'apc') . "'/>";
2028
+ echo "<div style='display:none' class='at-color-picker' rel='{$field['id']}'></div><div class='clearfix'></div>";
2029
+ }
2030
+ $this->show_field_end($field, $meta);
2031
+
2032
+ }
2033
+
2034
+ /**
2035
+ * Show Checkbox List Field
2036
+ *
2037
+ * @param string $field
2038
+ * @param string $meta
2039
+ * @since 0.1
2040
+ * @access public
2041
+ */
2042
+ public function show_field_checkbox_list( $field, $meta ) {
2043
+
2044
+ if ( ! is_array( $meta ) )
2045
+ $meta = (array) $meta;
2046
+
2047
+ $this->show_field_begin($field, $meta);
2048
+
2049
+ $html = array();
2050
+
2051
+ foreach ($field['options'] as $key => $value) {
2052
+ $html[] = "<label class='at-checkbox_list-label'><input type='checkbox' class='at-checkbox_list".(isset($field['class'])? " {$field['class']}": "")."' name='{$field['id']}[]' value='{$key}'" . checked( in_array( $key, $meta ), true, false ) . " />{$value}</label>";
2053
+ }
2054
+
2055
+ echo implode( '<br />' , $html );
2056
+
2057
+ $this->show_field_end($field, $meta);
2058
+
2059
+ }
2060
+
2061
+ /**
2062
+ * Show Date Field.
2063
+ *
2064
+ * @param string $field
2065
+ * @param string $meta
2066
+ * @since 0.1
2067
+ * @access public
2068
+ */
2069
+ public function show_field_date( $field, $meta ) {
2070
+ $this->show_field_begin( $field, $meta );
2071
+ echo "<input type='text' class='at-date".(isset($field['class'])? " {$field['class']}": "")."' name='{$field['id']}' id='{$field['id']}' rel='{$field['format']}' value='{$meta}' size='30' />";
2072
+ $this->show_field_end( $field, $meta );
2073
+ }
2074
+
2075
+ /**
2076
+ * Show time field.
2077
+ *
2078
+ * @param string $field
2079
+ * @param string $meta
2080
+ * @since 0.1
2081
+ * @access public
2082
+ */
2083
+ public function show_field_time( $field, $meta ) {
2084
+ $this->show_field_begin( $field, $meta );
2085
+ echo "<input type='text' class='at-time".(isset($field['class'])? " {$field['class']}": "")."' name='{$field['id']}' id='{$field['id']}' rel='{$field['format']}' value='{$meta}' size='30' />";
2086
+ $this->show_field_end( $field, $meta );
2087
+ }
2088
+
2089
+ /**
2090
+ * Show Posts field.
2091
+ * used creating a posts/pages/custom types checkboxlist or a select dropdown
2092
+ * @param string $field
2093
+ * @param string $meta
2094
+ * @since 0.1
2095
+ * @access public
2096
+ */
2097
+ public function show_field_posts($field, $meta) {
2098
+ global $post;
2099
+
2100
+ if (!is_array($meta)) $meta = (array) $meta;
2101
+ $this->show_field_begin($field, $meta);
2102
+ $options = $field['options'];
2103
+ $posts = get_posts($options['args']);
2104
+
2105
+ // checkbox_list
2106
+ if ('checkbox_list' == $options['type']) {
2107
+ foreach ($posts as $p) {
2108
+ if (isset($field['class']) && $field['class']== 'no-toggle')
2109
+ echo "<label class='at-posts-checkbox-label'><input type='checkbox' class='at-posts-checkbox".(isset($field['class'])? " {$field['class']}": "")."' name='{$field['id']}[]' value='$p->ID'" . checked(in_array($p->ID, $meta), true, false) . " /> {$p->post_title}</label>";
2110
+ else
2111
+ echo "{$p->post_title}<input type='checkbox' class='at-posts-checkbox".(isset($field['class'])? " {$field['class']}": "")."' name='{$field['id']}[]' value='$p->ID'" . checked(in_array($p->ID, $meta), true, false) . " />";
2112
+ }
2113
+ }
2114
+ // select
2115
+ else {
2116
+ echo "<select class='at-posts-select".(isset($field['class'])? " {$field['class']}": "")."' name='{$field['id']}" . ($field['multiple'] ? "[]' multiple='multiple' style='height:auto'" : "'") . ">";
2117
+ foreach ($posts as $p) {
2118
+ echo "<option value='$p->ID'" . selected(in_array($p->ID, $meta), true, false) . ">$p->post_title</option>";
2119
+ }
2120
+ echo "</select>";
2121
+ }
2122
+
2123
+ $this->show_field_end($field, $meta);
2124
+ }
2125
+
2126
+ /**
2127
+ * Show Taxonomy field.
2128
+ * used creating a category/tags/custom taxonomy checkboxlist or a select dropdown
2129
+ * @param string $field
2130
+ * @param string $meta
2131
+ * @since 0.1
2132
+ * @access public
2133
+ *
2134
+ * @uses get_terms()
2135
+ */
2136
+ public function show_field_taxonomy($field, $meta) {
2137
+ global $post;
2138
+
2139
+ if (!is_array($meta)) $meta = (array) $meta;
2140
+ $this->show_field_begin($field, $meta);
2141
+ $options = $field['options'];
2142
+ $terms = get_terms($options['taxonomy'], $options['args']);
2143
+
2144
+ // checkbox_list
2145
+ if ('checkbox_list' == $options['type']) {
2146
+ foreach ($terms as $term) {
2147
+ if (isset($field['class']) && $field['class'] == 'no-toggle')
2148
+ echo "<label class='at-tax-checkbox-label'><input type='checkbox' class='at-tax-checkbox".(isset($field['class'])? " {$field['class']}": "")."' name='{$field['id']}[]' value='$term->slug'" . checked(in_array($term->slug, $meta), true, false) . " /> {$term->name}</label>";
2149
+ else
2150
+ echo "{$term->name} <input type='checkbox' class='at-tax-checkbox".(isset($field['class'])? " {$field['class']}": "")."' name='{$field['id']}[]' value='$term->slug'" . checked(in_array($term->slug, $meta), true, false) . " />";
2151
+ }
2152
+ }
2153
+ // select
2154
+ else {
2155
+ echo "<select class='at-tax-select".(isset($field['class'])? " {$field['class']}": "")."' name='{$field['id']}" . ($field['multiple'] ? "[]' multiple='multiple' style='height:auto'" : "'") . ">";
2156
+ foreach ($terms as $term) {
2157
+ echo "<option value='$term->slug'" . selected(in_array($term->slug, $meta), true, false) . ">$term->name</option>";
2158
+ }
2159
+ echo "</select>";
2160
+ }
2161
+
2162
+ $this->show_field_end($field, $meta);
2163
+ }
2164
+
2165
+ /**
2166
+ * Show Role field.
2167
+ * used creating a Wordpress roles list checkboxlist or a select dropdown
2168
+ * @param string $field
2169
+ * @param string $meta
2170
+ * @since 0.1
2171
+ * @access public
2172
+ *
2173
+ * @uses global $wp_roles;
2174
+ * @uses checked();
2175
+ */
2176
+ public function show_field_WProle($field, $meta) {
2177
+ if (!is_array($meta)) $meta = (array) $meta;
2178
+ $this->show_field_begin($field, $meta);
2179
+ $options = $field['options'];
2180
+ global $wp_roles;
2181
+ if ( ! isset( $wp_roles ) )
2182
+ $wp_roles = new WP_Roles();
2183
+ $names = $wp_roles->get_names();
2184
+ if ($names){
2185
+ // checkbox_list
2186
+ if ('checkbox_list' == $options['type']) {
2187
+ foreach ($names as $n) {
2188
+ if (isset($field['class']) && $field['class'] == 'no-toggle')
2189
+ echo "<label class='at-posts-checkbox-label'><input type='checkbox' class='at-role-checkbox".(isset($field['class'])? " {$field['class']}": "")."' name='{$field['id']}[]' value='$n'" . checked(in_array($n, $meta), true, false) . " /> ".$n."</label>";
2190
+ else
2191
+ echo "{$n} <input type='checkbox' class='at-role-checkbox".(isset($field['class'])? " {$field['class']}": "")."' name='{$field['id']}[]' value='$n'" . checked(in_array($n, $meta), true, false) . " />";
2192
+ }
2193
+ }
2194
+ // select
2195
+ else {
2196
+ echo "<select class='at-role-select".(isset($field['class'])? " {$field['class']}": "")."' name='{$field['id']}" . ($field['multiple'] ? "[]' multiple='multiple' style='height:auto'" : "'") . ">";
2197
+ foreach ($names as $n) {
2198
+ echo "<option value='$n'" . selected(in_array($n, $meta), true, false) . ">$n</option>";
2199
+ }
2200
+ echo "</select>";
2201
+ }
2202
+ }
2203
+ $this->show_field_end($field, $meta);
2204
+ }
2205
+
2206
+ /**
2207
+ * Save Data from page
2208
+ *
2209
+ * @param string $repeater (false )
2210
+ * @since 0.1
2211
+ * @access public
2212
+ */
2213
+ public function save($repeater = false) {
2214
+ $saved = get_option($this->option_group);
2215
+ $this->_saved = $saved;
2216
+
2217
+ $post_data = isset($_POST)? $_POST : NULL;
2218
+
2219
+ If ($post_data == NULL) return;
2220
+
2221
+ $skip = array('title','paragraph','subtitle','TABS','CloseDiv','TABS_Listing','OpenTab','import_export');
2222
+
2223
+ //check nonce
2224
+ if ( ! check_admin_referer( basename( __FILE__ ), 'BF_Admin_Page_Class_nonce') )
2225
+ return;
2226
+
2227
+ foreach ( $this->_fields as $field ) {
2228
+ if(!in_array($field['type'],$skip)){
2229
+
2230
+ $name = $field['id'];
2231
+ $type = $field['type'];
2232
+ $old = isset($saved[$name])? $saved[$name]: NULL;
2233
+ $new = ( isset( $_POST[$name] ) ) ? $_POST[$name] : ( ( isset($field['multiple']) && $field['multiple']) ? array() : '' );
2234
+
2235
+
2236
+ //Validate and senitize meta value
2237
+ //issue #27
2238
+ $validationClass = apply_filters('apc_validattion_class_name', 'BF_Admin_Page_Class_Validate',$this);
2239
+ if ( class_exists( $validationClass ) && isset($field['validate_func']) && method_exists( $validationClass, $field['validate_func'] ) ) {
2240
+ $new = call_user_func( array( $validationClass, $field['validate_func'] ), $new ,$this);
2241
+ }
2242
+
2243
+ //native validation
2244
+ if (isset($field['validate'])){
2245
+ if (!$this->validate_field($field,$new))
2246
+ $new = $old;
2247
+ }
2248
+
2249
+
2250
+ // Call defined method to save meta value, if there's no methods, call common one.
2251
+ $save_func = 'save_field_' . $type;
2252
+ if ( method_exists( $this, $save_func ) ) {
2253
+ call_user_func( array( $this, 'save_field_' . $type ), $field, $old, $new );
2254
+ } else {
2255
+ $this->save_field( $field, $old, $new );
2256
+ }
2257
+
2258
+ }//END Skip
2259
+ } // End foreach
2260
+ update_option($this->args['option_group'],$this->_saved);
2261
+ }
2262
+
2263
+ /**
2264
+ * Common function for saving fields.
2265
+ *
2266
+ * @param string $field
2267
+ * @param string $old
2268
+ * @param string|mixed $new
2269
+ * @since 0.1
2270
+ * @access public
2271
+ */
2272
+ public function save_field( $field, $old, $new ) {
2273
+ $name = $field['id'];
2274
+ if(is_array($this->_saved) && isset($this->_saved[$name])):
2275
+ unset($this->_saved[$name]);
2276
+ endif;
2277
+ if ( $new === '' || $new === array() )
2278
+ return;
2279
+ if ( isset($field['multiple'] ) && $field['multiple'] && $field['type'] != 'plupload') {
2280
+ foreach ( $new as $add_new ) {
2281
+ $temp[] = $add_new;
2282
+ }
2283
+ $this->_saved[$name] = $temp;
2284
+ } else {
2285
+ $this->_saved[$name] = $new;
2286
+ }
2287
+ }
2288
+
2289
+ /**
2290
+ * function for saving image field.
2291
+ *
2292
+ * @param string $field
2293
+ * @param string $old
2294
+ * @param string|mixed $new
2295
+ * @since 0.1
2296
+ * @access public
2297
+ */
2298
+ public function save_field_image( $field, $old, $new ) {
2299
+ $name = $field['id'];
2300
+ unset($this->_saved[$name]);
2301
+ if ( $new === '' || $new === array() || $new['id'] == '' || $new['src'] == '')
2302
+ return;
2303
+
2304
+ $this->_saved[$name] = $new;
2305
+ }
2306
+
2307
+ /*
2308
+ * Save Wysiwyg Field.
2309
+ *
2310
+ * @param string $field
2311
+ * @param string $old
2312
+ * @param string $new
2313
+ * @since 0.1
2314
+ * @access public
2315
+ */
2316
+ public function save_field_wysiwyg( $field, $old, $new ) {
2317
+ $this->save_field( $field, $old, htmlentities($new) );
2318
+ }
2319
+
2320
+ /*
2321
+ * Save checkbox Field.
2322
+ *
2323
+ * @param string $field
2324
+ * @param string $old
2325
+ * @param string $new
2326
+ * @since 0.9
2327
+ * @access public
2328
+ */
2329
+ public function save_field_checkbox( $field, $old, $new ) {
2330
+ if ( $new === '' )
2331
+ $this->save_field( $field, $old, false );
2332
+ else
2333
+ $this->save_field( $field, $old, true );
2334
+ }
2335
+
2336
+ /**
2337
+ * Save repeater Fields.
2338
+ *
2339
+ * @param string $field
2340
+ * @param string|mixed $old
2341
+ * @param string|mixed $new
2342
+ * @since 0.1
2343
+ * @access public
2344
+ */
2345
+ public function save_field_repeater( $field, $old, $new ) {
2346
+ if (is_array($new) && count($new) > 0){
2347
+ foreach ($new as $n){
2348
+ foreach ( $field['fields'] as $f ) {
2349
+ $type = $f['type'];
2350
+ switch($type) {
2351
+ case 'wysiwyg':
2352
+ $n[$f['id']] = wpautop( $n[$f['id']] );
2353
+ break;
2354
+ case 'file':
2355
+ $n[$f['id']] = $this->save_field_file_repeater($f,'',$n[$f['id']]);
2356
+ break;
2357
+ default:
2358
+ break;
2359
+ }
2360
+ }
2361
+ if(!$this->is_array_empty($n))
2362
+ $temp[] = $n;
2363
+ }
2364
+ if (isset($temp) && count($temp) > 0 && !$this->is_array_empty($temp)){
2365
+ $this->_saved[$field['id']] = $temp;
2366
+ }else{
2367
+ if (isset($this->_saved[$field['id']]))
2368
+ unset($this->_saved[$field['id']]);
2369
+ }
2370
+ }else{
2371
+ // remove old meta if exists
2372
+ if (isset($this->_saved[$field['id']]))
2373
+ unset($this->_saved[$field['id']]);
2374
+ }
2375
+ }
2376
+
2377
+
2378
+
2379
+ /**
2380
+ * Add missed values for Page.
2381
+ *
2382
+ * @since 0.1
2383
+ * @access public
2384
+ */
2385
+ public function add_missed_values() {
2386
+
2387
+ // Default values for admin
2388
+ //$this->_meta_box = array_merge( array( 'context' => 'normal', 'priority' => 'high', 'pages' => array( 'post' ) ), $this->_meta_box );
2389
+
2390
+ // Default values for fields
2391
+ foreach ( $this->_fields as &$field ) {
2392
+
2393
+ $multiple = in_array( $field['type'], array( 'checkbox_list', 'file', 'image' ) );
2394
+ $std = $multiple ? array() : '';
2395
+ $format = 'date' == $field['type'] ? 'yy-mm-dd' : ( 'time' == $field['type'] ? 'hh:mm' : '' );
2396
+
2397
+ $field = array_merge( array( 'multiple' => $multiple, 'std' => $std, 'desc' => '', 'format' => $format, 'validate_func' => '' ), $field );
2398
+
2399
+ } // End foreach
2400
+
2401
+ }
2402
+
2403
+ /**
2404
+ * Check if field with $type exists.
2405
+ *
2406
+ * @param string $type
2407
+ * @since 0.1
2408
+ * @access public
2409
+ */
2410
+ public function has_field( $type ) {
2411
+ //faster search in single array.
2412
+ if (count($this->field_types) > 0){
2413
+ return in_array($type, $this->field_types);
2414
+ }
2415
+
2416
+ //run once over all fields and store the types in a local array
2417
+ $temp = array();
2418
+ foreach ($this->_fields as $field) {
2419
+ $temp[] = $field['type'];
2420
+ if ('repeater' == $field['type'] || 'cond' == $field['type']){
2421
+ foreach((array)$field["fields"] as $repeater_field) {
2422
+ $temp[] = $repeater_field["type"];
2423
+ }
2424
+ }
2425
+ }
2426
+
2427
+ //remove duplicates
2428
+ $this->field_types = array_unique($temp);
2429
+ //call this function one more time now that we have an array of field types
2430
+ return $this->has_field($type);
2431
+ }
2432
+
2433
+ /**
2434
+ * Check if any of the fields types exists
2435
+ *
2436
+ * @since 1.1.3
2437
+ * @access public
2438
+ * @param array $types array of field types
2439
+ * @return boolean
2440
+ */
2441
+ public function has_field_any($types){
2442
+ foreach ((array)$types as $t) {
2443
+ if ($this->has_field($t))
2444
+ return true;
2445
+ }
2446
+ return false;
2447
+ }
2448
+
2449
+ /**
2450
+ * Check if current page is edit page.
2451
+ *
2452
+ * @since 0.1
2453
+ * @access public
2454
+ */
2455
+ public function is_edit_page() {
2456
+ //global $pagenow;
2457
+ return true;
2458
+ //return in_array( $pagenow, array( 'post.php', 'post-new.php' ) );
2459
+ }
2460
+
2461
+ /**
2462
+ * Fixes the odd indexing of multiple file uploads.
2463
+ *
2464
+ * Goes from the format:
2465
+ * $_FILES['field']['key']['index']
2466
+ * to
2467
+ * The More standard and appropriate:
2468
+ * $_FILES['field']['index']['key']
2469
+ *
2470
+ * @param string $files
2471
+ * @since 0.1
2472
+ * @access public
2473
+ */
2474
+ public function fix_file_array( &$files ) {
2475
+
2476
+ $output = array();
2477
+
2478
+ foreach ( $files as $key => $list ) {
2479
+ foreach ( $list as $index => $value ) {
2480
+ $output[$index][$key] = $value;
2481
+ }
2482
+ }
2483
+
2484
+ return $files = $output;
2485
+
2486
+ }
2487
+
2488
+ /**
2489
+ * Get proper JQuery UI version.
2490
+ *
2491
+ * Used in order to not conflict with WP Admin Scripts.
2492
+ *
2493
+ * @since 0.1
2494
+ * @access public
2495
+ */
2496
+ public function get_jqueryui_ver() {
2497
+
2498
+ global $wp_version;
2499
+
2500
+ if ( version_compare( $wp_version, '3.1', '>=') ) {
2501
+ return '1.8.10';
2502
+ }
2503
+
2504
+ return '1.7.3';
2505
+
2506
+ }
2507
+
2508
+ /**
2509
+ * Add Field to page (generic function)
2510
+ * @author Ohad Raz
2511
+ * @since 0.1
2512
+ * @access public
2513
+ * @param $id string field id, i.e. the meta key
2514
+ * @param $args mixed|array
2515
+ */
2516
+ public function addField($id,$args){
2517
+ $new_field = array('id'=> $id,'std' => '','desc' => '','style' =>'');
2518
+ $new_field = array_merge($new_field, $args);
2519
+ $this->_fields[] = $new_field;
2520
+ }
2521
+
2522
+ /**
2523
+ * Add typography Field
2524
+ *
2525
+ * @author Ohad Raz
2526
+ * @since 0.3
2527
+ *
2528
+ * @access public
2529
+ *
2530
+ * @param $id string id of the field
2531
+ * @param $args mixed|array
2532
+ * @param boolean $repeater=false
2533
+ */
2534
+ public function addTypo($id,$args,$repeater=false){
2535
+ $new_field = array(
2536
+ 'type' => 'typo',
2537
+ 'id'=> $id,
2538
+ 'std' => array(
2539
+ 'size' => '12px',
2540
+ 'color' => '#000000',
2541
+ 'face' => 'arial',
2542
+ 'style' => 'normal',
2543
+ 'weight' => 'normal'
2544
+ ),
2545
+ 'desc' => '',
2546
+ 'style' =>'',
2547
+ 'name'=> 'Typography field'
2548
+ );
2549
+ $new_field = array_merge($new_field, $args);
2550
+ $this->_fields[] = $new_field;
2551
+ }
2552
+
2553
+ /**
2554
+ * Add Text Field to Page
2555
+ * @author Ohad Raz
2556
+ * @since 0.1
2557
+ * @access public
2558
+ * @param $id string field id, i.e. the meta key
2559
+ * @param $args mixed|array
2560
+ * 'name' => // field name/label string optional
2561
+ * 'desc' => // field description, string optional
2562
+ * 'std' => // default value, string optional
2563
+ * 'style' => // custom style for field, string optional
2564
+ * 'validate_func' => // validate function, string optional
2565
+ * @param $repeater bool is this a field inside a repeatr? true|false(default)
2566
+ */
2567
+ public function addText($id,$args,$repeater=false){
2568
+ $new_field = array('type' => 'text','id'=> $id,'std' => '','desc' => '','style' =>'','name' => 'Text Field');
2569
+ $new_field = array_merge($new_field, $args);
2570
+ if(false === $repeater){
2571
+ $this->_fields[] = $new_field;
2572
+ }else{
2573
+ return $new_field;
2574
+ }
2575
+ }
2576
+
2577
+ /**
2578
+ * Add Pluploader Field to Page
2579
+ * @author Ohad Raz
2580
+ * @since 0.9.7
2581
+ * @access public
2582
+ * @param $id string field id, i.e. the meta key
2583
+ * @param $args mixed|array
2584
+ * 'name' => // field name/label string optional
2585
+ * 'desc' => // field description, string optional
2586
+ * 'std' => // default value, string optional
2587
+ * 'style' => // custom style for field, string optional
2588
+ * 'validate_func' => // validate function, string optional
2589
+ * @param $repeater bool is this a field inside a repeatr? true|false(default)
2590
+ */
2591
+ public function addPlupload($id,$args,$repeater=false){
2592
+ $new_field = array('type' => 'plupload','id'=> $id,'std' => '','desc' => '','style' =>'','name' => 'PlUpload Field','width' => null, 'height' => null,'multiple' => false);
2593
+ $new_field = array_merge($new_field, $args);
2594
+ if(false === $repeater){
2595
+ $this->_fields[] = $new_field;
2596
+ }else{
2597
+ return $new_field;
2598
+ }
2599
+ }
2600
+
2601
+ /**
2602
+ * Add Hidden Field to Page
2603
+ * @author Ohad Raz
2604
+ * @since 0.1
2605
+ * @access public
2606
+ * @param $id string field id, i.e. the meta key
2607
+ * @param $args mixed|array
2608
+ * 'name' => // field name/label string optional
2609
+ * 'desc' => // field description, string optional
2610
+ * 'std' => // default value, string optional
2611
+ * 'style' => // custom style for field, string optional
2612
+ * 'validate_func' => // validate function, string optional
2613
+ * @param $repeater bool is this a field inside a repeatr? true|false(default)
2614
+ */
2615
+ public function addHidden($id,$args,$repeater=false){
2616
+ $new_field = array('type' => 'hidden','id'=> $id,'std' => '','desc' => '','style' =>'','name' => '');
2617
+ $new_field = array_merge($new_field, $args);
2618
+ if(false === $repeater){
2619
+ $this->_fields[] = $new_field;
2620
+ }else{
2621
+ return $new_field;
2622
+ }
2623
+ }
2624
+
2625
+ /**
2626
+ * Add code Editor to page
2627
+ * @author Ohad Raz
2628
+ * @since 0.1
2629
+ * @access public
2630
+ * @param $id string field id, i.e. the meta key
2631
+ * @param $args mixed|array
2632
+ * 'name' => // field name/label string optional
2633
+ * 'desc' => // field description, string optional
2634
+ * 'std' => // default value, string optional
2635
+ * 'style' => // custom style for field, string optional
2636
+ * 'syntax' => // syntax language to use in editor (php,javascript,css,html)
2637
+ * 'validate_func' => // validate function, string optional
2638
+ * @param $repeater bool is this a field inside a repeatr? true|false(default)
2639
+ */
2640
+ public function addCode($id,$args,$repeater=false){
2641
+ $new_field = array('type' => 'code','id'=> $id,'std' => '','desc' => '','style' =>'','name' => 'Code Editor Field','syntax' => 'php', 'theme' => 'default');
2642
+ $new_field = array_merge($new_field, (array)$args);
2643
+ if(false === $repeater){
2644
+ $this->_fields[] = $new_field;
2645
+ }else{
2646
+ return $new_field;
2647
+ }
2648
+ }
2649
+
2650
+ /**
2651
+ * Add Paragraph to Page
2652
+ * @author Ohad Raz
2653
+ * @since 0.1
2654
+ * @access public
2655
+ *
2656
+ * @param $p paragraph html
2657
+ * @param $repeater bool is this a field inside a repeatr? true|false(default)
2658
+ */
2659
+ public function addParagraph($p,$repeater=false){
2660
+ $new_field = array('type' => 'paragraph','id'=> '','value' => $p);
2661
+ if(false === $repeater){
2662
+ $this->_fields[] = $new_field;
2663
+ }else{
2664
+ return $new_field;
2665
+ }
2666
+ }
2667
+
2668
+ /**
2669
+ * Add Checkbox Field to Page
2670
+ * @author Ohad Raz
2671
+ * @since 0.1
2672
+ * @access public
2673
+ * @param $id string field id, i.e. the meta key
2674
+ * @param $args mixed|array
2675
+ * 'name' => // field name/label string optional
2676
+ * 'desc' => // field description, string optional
2677
+ * 'std' => // default value, string optional
2678
+ * 'validate_func' => // validate function, string optional
2679
+ * @param $repeater bool is this a field inside a repeatr? true|false(default)
2680
+ */
2681
+ public function addCheckbox($id,$args,$repeater=false){
2682
+ $new_field = array('type' => 'checkbox','id'=> $id,'std' => '','desc' => '','style' =>'','name' => 'Checkbox Field');
2683
+ $new_field = array_merge($new_field, $args);
2684
+ if(false === $repeater){
2685
+ $this->_fields[] = $new_field;
2686
+ }else{
2687
+ return $new_field;
2688
+ }
2689
+ }
2690
+
2691
+ /**
2692
+ * Add Checkbox conditional Field to Page
2693
+ * @author Ohad Raz
2694
+ * @since 0.5
2695
+ * @access public
2696
+ * @param $id string field id, i.e. the key
2697
+ * @param $args mixed|array
2698
+ * 'name' => // field name/label string optional
2699
+ * 'desc' => // field description, string optional
2700
+ * 'std' => // default value, string optional
2701
+ * 'validate_func' => // validate function, string optional
2702
+ * 'fields' => list of fields to show conditionally.
2703
+ * @param $repeater bool is this a field inside a repeatr? true|false(default)
2704
+ */
2705
+ public function addCondition($id,$args,$repeater=false){
2706
+ $new_field = array('type' => 'cond','id'=> $id,'std' => '','desc' => '','style' =>'','name' => 'Conditional Field','fields' => array());
2707
+ $new_field = array_merge($new_field, $args);
2708
+ if(false === $repeater){
2709
+ $this->_fields[] = $new_field;
2710
+ }else{
2711
+ return $new_field;
2712
+ }
2713
+ }
2714
+
2715
+ /**
2716
+ * Add CheckboxList Field to Page
2717
+ * @author Ohad Raz
2718
+ * @since 0.1
2719
+ * @access public
2720
+ * @param $id string field id, i.e. the meta key
2721
+ * @param $options (array) array of key => value pairs for select options
2722
+ * @param $args mixed|array
2723
+ * 'name' => // field name/label string optional
2724
+ * 'desc' => // field description, string optional
2725
+ * 'std' => // default value, string optional
2726
+ * 'validate_func' => // validate function, string optional
2727
+ * @param $repeater bool is this a field inside a repeatr? true|false(default)
2728
+ *
2729
+ * @return : remember to call: $checkbox_list = get_post_meta(get_the_ID(), 'meta_name', false);
2730
+ * which means the last param as false to get the values in an array
2731
+ */
2732
+ public function addCheckboxList($id,$options=array(),$args,$repeater=false){
2733
+ $new_field = array('type' => 'checkbox_list','id'=> $id,'std' => '','desc' => '','style' =>'','name' => 'Checkbox List Field','options' => $options, 'class' => '');
2734
+ $new_field = array_merge($new_field, $args);
2735
+ if(false === $repeater){
2736
+ $this->_fields[] = $new_field;
2737
+ }else{
2738
+ return $new_field;
2739
+ }
2740
+ }
2741
+
2742
+ /**
2743
+ * Add Textarea Field to Page
2744
+ * @author Ohad Raz
2745
+ * @since 0.1
2746
+ * @access public
2747
+ * @param $id string field id, i.e. the meta key
2748
+ * @param $args mixed|array
2749
+ * 'name' => // field name/label string optional
2750
+ * 'desc' => // field description, string optional
2751
+ * 'std' => // default value, string optional
2752
+ * 'style' => // custom style for field, string optional
2753
+ * 'validate_func' => // validate function, string optional
2754
+ * @param $repeater bool is this a field inside a repeatr? true|false(default)
2755
+ */
2756
+ public function addTextarea($id,$args,$repeater=false){
2757
+ $new_field = array('type' => 'textarea','id'=> $id,'std' => '','desc' => '','style' =>'','name' => 'Textarea Field');
2758
+ $new_field = array_merge($new_field, $args);
2759
+ if(false === $repeater){
2760
+ $this->_fields[] = $new_field;
2761
+ }else{
2762
+ return $new_field;
2763
+ }
2764
+ }
2765
+
2766
+ /**
2767
+ * Add Select Field to Page
2768
+ * @author Ohad Raz
2769
+ * @since 0.1
2770
+ * @access public
2771
+ * @param $id string field id, i.e. the meta key
2772
+ * @param $options (array) array of key => value pairs for select options
2773
+ * @param $args mixed|array
2774
+ * 'name' => // field name/label string optional
2775
+ * 'desc' => // field description, string optional
2776
+ * 'std' => // default value, (array) optional
2777
+ * 'multiple' => // select multiple values, optional. Default is false.
2778
+ * 'validate_func' => // validate function, string optional
2779
+ * @param $repeater bool is this a field inside a repeatr? true|false(default)
2780
+ */
2781
+ public function addSelect($id,$options,$args,$repeater=false){
2782
+ $new_field = array('type' => 'select','id'=> $id,'std' => array(),'desc' => '','style' =>'','name' => 'Select Field','multiple' => false,'options' => $options);
2783
+ $new_field = array_merge($new_field, $args);
2784
+ if(false === $repeater){
2785
+ $this->_fields[] = $new_field;
2786
+ }else{
2787
+ return $new_field;
2788
+ }
2789
+ }
2790
+
2791
+ /**
2792
+ * Add Sortable Field to Page
2793
+ * @author Ohad Raz
2794
+ * @since 0.4
2795
+ * @access public
2796
+ * @param $id string field id, i.e. the meta key
2797
+ * @param $options (array) array of key => value pairs for sortable options as value => label
2798
+ * @param $args mixed|array
2799
+ * 'name' => // field name/label string optional
2800
+ * 'desc' => // field description, string optional
2801
+ * 'std' => // default value, (array) optional
2802
+ * 'validate_func' => // validate function, string optional
2803
+ * @param $repeater bool is this a field inside a repeatr? true|false(default)
2804
+ */
2805
+ public function addSortable($id,$options,$args,$repeater=false){
2806
+ $new_field = array('type' => 'sortable','id'=> $id,'std' => array(),'desc' => '','style' =>'','name' => 'Select Field','multiple' => false,'options' => $options);
2807
+ $new_field = array_merge($new_field, $args);
2808
+ if(false === $repeater){
2809
+ $this->_fields[] = $new_field;
2810
+ }else{
2811
+ return $new_field;
2812
+ }
2813
+ }
2814
+
2815
+
2816
+ /**
2817
+ * Add Radio Field to Page
2818
+ * @author Ohad Raz
2819
+ * @since 0.1
2820
+ * @access public
2821
+ * @param $id string field id, i.e. the meta key
2822
+ * @param $options (array) array of key => value pairs for radio options
2823
+ * @param $args mixed|array
2824
+ * 'name' => // field name/label string optional
2825
+ * 'desc' => // field description, string optional
2826
+ * 'std' => // default value, string optional
2827
+ * 'validate_func' => // validate function, string optional
2828
+ * @param $repeater bool is this a field inside a repeatr? true|false(default)
2829
+ */
2830
+ public function addRadio($id,$options,$args,$repeater=false){
2831
+ $new_field = array('type' => 'radio','id'=> $id,'std' => array(),'desc' => '','style' =>'','name' => 'Radio Field','options' => $options,'multiple' => false);
2832
+ $new_field = array_merge($new_field, $args);
2833
+ if(false === $repeater){
2834
+ $this->_fields[] = $new_field;
2835
+ }else{
2836
+ return $new_field;
2837
+ }
2838
+ }
2839
+
2840
+ /**
2841
+ * Add Date Field to Page
2842
+ * @author Ohad Raz
2843
+ * @since 0.1
2844
+ * @access public
2845
+ * @param $id string field id, i.e. the meta key
2846
+ * @param $args mixed|array
2847
+ * 'name' => // field name/label string optional
2848
+ * 'desc' => // field description, string optional
2849
+ * 'std' => // default value, string optional
2850
+ * 'validate_func' => // validate function, string optional
2851
+ * 'format' => // date format, default yy-mm-dd. Optional. Default "'d MM, yy'" See more formats here: http://goo.gl/Wcwxn
2852
+ * @param $repeater bool is this a field inside a repeatr? true|false(default)
2853
+ */
2854
+ public function addDate($id,$args,$repeater=false){
2855
+ $new_field = array('type' => 'date','id'=> $id,'std' => '','desc' => '','format'=>'d MM, yy','name' => 'Date Field');
2856
+ $new_field = array_merge($new_field, $args);
2857
+ if(false === $repeater){
2858
+ $this->_fields[] = $new_field;
2859
+ }else{
2860
+ return $new_field;
2861
+ }
2862
+ }
2863
+
2864
+ /**
2865
+ * Add Time Field to Page
2866
+ * @author Ohad Raz
2867
+ * @since 0.1
2868
+ * @access public
2869
+ * @param $id string- field id, i.e. the meta key
2870
+ * @param $args mixed|array
2871
+ * 'name' => // field name/label string optional
2872
+ * 'desc' => // field description, string optional
2873
+ * 'std' => // default value, string optional
2874
+ * 'validate_func' => // validate function, string optional
2875
+ * 'format' => // time format, default hh:mm. Optional. See more formats here: http://goo.gl/83woX
2876
+ * @param $repeater bool is this a field inside a repeatr? true|false(default)
2877
+ */
2878
+ public function addTime($id,$args,$repeater=false){
2879
+ $new_field = array('type' => 'time','id'=> $id,'std' => '','desc' => '','format'=>'hh:mm','name' => 'Time Field');
2880
+ $new_field = array_merge($new_field, $args);
2881
+ if(false === $repeater){
2882
+ $this->_fields[] = $new_field;
2883
+ }else{
2884
+ return $new_field;
2885
+ }
2886
+ }
2887
+
2888
+ /**
2889
+ * Add Color Field to Page
2890
+ * @author Ohad Raz
2891
+ * @since 0.1
2892
+ * @access public
2893
+ * @param $id string field id, i.e. the meta key
2894
+ * @param $args mixed|array
2895
+ * 'name' => // field name/label string optional
2896
+ * 'desc' => // field description, string optional
2897
+ * 'std' => // default value, string optional
2898
+ * 'validate_func' => // validate function, string optional
2899
+ * @param $repeater bool is this a field inside a repeatr? true|false(default)
2900
+ */
2901
+ public function addColor($id,$args,$repeater=false){
2902
+ $new_field = array('type' => 'color','id'=> $id,'std' => '','desc' => '','name' => 'ColorPicker Field');
2903
+ $new_field = array_merge($new_field, $args);
2904
+ if(false === $repeater){
2905
+ $this->_fields[] = $new_field;
2906
+ }else{
2907
+ return $new_field;
2908
+ }
2909
+ }
2910
+
2911
+ /**
2912
+ * Add Image Field to Page
2913
+ * @author Ohad Raz
2914
+ * @since 0.1
2915
+ * @access public
2916
+ * @param $id string field id, i.e. the meta key
2917
+ * @param $args mixed|array
2918
+ * 'name' => // field name/label string optional
2919
+ * 'desc' => // field description, string optional
2920
+ * 'validate_func' => // validate function, string optional
2921
+ * @param $repeater bool is this a field inside a repeatr? true|false(default)
2922
+ */
2923
+ public function addImage($id,$args,$repeater=false){
2924
+ $new_field = array('type' => 'image','id'=> $id,'desc' => '','name' => 'Image Field');
2925
+ $new_field = array_merge($new_field, $args);
2926
+ if(false === $repeater){
2927
+ $this->_fields[] = $new_field;
2928
+ }else{
2929
+ return $new_field;
2930
+ }
2931
+ }
2932
+
2933
+
2934
+ /**
2935
+ * Add WYSIWYG Field to Page
2936
+ * @author Ohad Raz
2937
+ * @since 0.1
2938
+ * @access public
2939
+ * @param $id string field id, i.e. the meta key
2940
+ * @param $args mixed|array
2941
+ * 'name' => // field name/label string optional
2942
+ * 'desc' => // field description, string optional
2943
+ * 'std' => // default value, string optional
2944
+ * 'style' => // custom style for field, string optional Default 'width: 300px; height: 400px'
2945
+ * 'validate_func' => // validate function, string optional
2946
+ * @param $repeater bool is this a field inside a repeatr? true|false(default)
2947
+ */
2948
+ public function addWysiwyg($id,$args,$repeater=false){
2949
+ $new_field = array('type' => 'wysiwyg','id'=> $id,'std' => '','desc' => '','style' =>'width: 300px; height: 400px','name' => 'WYSIWYG Editor Field');
2950
+ $new_field = array_merge($new_field, $args);
2951
+ if(false === $repeater){
2952
+ $this->_fields[] = $new_field;
2953
+ }else{
2954
+ return $new_field;
2955
+ }
2956
+ }
2957
+
2958
+ /**
2959
+ * Add Taxonomy Field to Page
2960
+ * @author Ohad Raz
2961
+ * @since 0.1
2962
+ * @access public
2963
+ * @param $id string field id, i.e. the meta key
2964
+ * @param $options mixed|array options of taxonomy field
2965
+ * 'taxonomy' => // taxonomy name can be category,post_tag or any custom taxonomy default is category
2966
+ * 'type' => // how to show taxonomy? 'select' (default) or 'checkbox_list'
2967
+ * 'args' => // arguments to query taxonomy, see http://goo.gl/uAANN default ('hide_empty' => false)
2968
+ * @param $args mixed|array
2969
+ * 'name' => // field name/label string optional
2970
+ * 'desc' => // field description, string optional
2971
+ * 'std' => // default value, string optional
2972
+ * 'validate_func' => // validate function, string optional
2973
+ * @param $repeater bool is this a field inside a repeatr? true|false(default)
2974
+ */
2975
+ public function addTaxonomy($id,$options,$args,$repeater=false){
2976
+ $temp = array('taxonomy'=> 'category','type' => 'select','args'=> array('hide_empty' => 0));
2977
+ $options = array_merge($temp,$options);
2978
+ $new_field = array('type' => 'taxonomy','id'=> $id,'desc' => '','name' => 'Taxonomy Field','options'=> $options, 'multiple' => false);
2979
+ $new_field = array_merge($new_field, $args);
2980
+ if(false === $repeater){
2981
+ $this->_fields[] = $new_field;
2982
+ }else{
2983
+ return $new_field;
2984
+ }
2985
+ }
2986
+
2987
+ /**
2988
+ * Add WP_Roles Field to Page
2989
+ * @author Ohad Raz
2990
+ * @since 0.1
2991
+ * @access public
2992
+ * @param $id string field id, i.e. the meta key
2993
+ * @param $options mixed|array options of taxonomy field
2994
+ * 'type' => // how to show taxonomy? 'select' (default) or 'checkbox_list'
2995
+ * @param $args mixed|array
2996
+ * 'name' => // field name/label string optional
2997
+ * 'desc' => // field description, string optional
2998
+ * 'std' => // default value, string optional
2999
+ * 'validate_func' => // validate function, string optional
3000
+ * @param $repeater bool is this a field inside a repeatr? true|false(default)
3001
+ */
3002
+ public function addRoles($id,$options,$args,$repeater=false){
3003
+ $options = array_merge(array('type'=>'select'),$options);
3004
+ $new_field = array('type' => 'WProle','id'=> $id,'desc' => '','name' => 'WP Roles Field','options'=> $options, 'multiple' => false);
3005
+ $new_field = array_merge($new_field, $args);
3006
+ if(false === $repeater){
3007
+ $this->_fields[] = $new_field;
3008
+ }else{
3009
+ return $new_field;
3010
+ }
3011
+ }
3012
+
3013
+ /**
3014
+ * Add posts Field to Page
3015
+ * @author Ohad Raz
3016
+ * @since 0.1
3017
+ * @access public
3018
+ * @param $id string field id, i.e. the meta key
3019
+ * @param $options mixed|array options of taxonomy field
3020
+ * 'post_type' => // post type name, 'post' (default) 'page' or any custom post type
3021
+ * type' => // how to show posts? 'select' (default) or 'checkbox_list'
3022
+ * args' => // arguments to query posts, see http://goo.gl/is0yK default ('posts_per_page' => -1)
3023
+ * @param $args mixed|array
3024
+ * 'name' => // field name/label string optional
3025
+ * 'desc' => // field description, string optional
3026
+ * 'std' => // default value, string optional
3027
+ * 'validate_func' => // validate function, string optional
3028
+ * @param $repeater bool is this a field inside a repeatr? true|false(default)
3029
+ */
3030
+ public function addPosts($id,$options,$args,$repeater=false){
3031
+ $temp = array('type'=>'select','args'=>array('posts_per_page' => -1,'post_type' =>'post'));
3032
+ $options = array_merge($temp,$options);
3033
+ $new_field = array('type' => 'posts','id'=> $id,'desc' => '','name' => 'Posts Field','options'=> $options, 'multiple' => false);
3034
+ $new_field = array_merge($new_field, $args);
3035
+ if(false === $repeater){
3036
+ $this->_fields[] = $new_field;
3037
+ }else{
3038
+ return $new_field;
3039
+ }
3040
+ }
3041
+
3042
+ /**
3043
+ * Add repeater Field Block to Page
3044
+ * @author Ohad Raz
3045
+ * @since 0.1
3046
+ * @access public
3047
+ * @param $id string field id, i.e. the meta key
3048
+ * @param $args mixed|array
3049
+ * 'name' => // field name/label string optional
3050
+ * 'desc' => // field description, string optional
3051
+ * 'std' => // default value, string optional
3052
+ * 'style' => // custom style for field, string optional
3053
+ * 'validate_func' => // validate function, string optional
3054
+ * 'fields' => //fields to repeater
3055
+ * @modified 0.4 added sortable option
3056
+ */
3057
+ public function addRepeaterBlock($id,$args){
3058
+ $new_field = array('type' => 'repeater','id'=> $id,'name' => 'Reapeater Field','fields' => array(),'inline'=> false, 'sortable' => false);
3059
+ $new_field = array_merge($new_field, $args);
3060
+ $this->_fields[] = $new_field;
3061
+ }
3062
+
3063
+
3064
+ /**
3065
+ * Finish Declaration of Page
3066
+ * @author Ohad Raz
3067
+ * @since 0.1
3068
+ * @access public
3069
+ * @deprecated 1.1.8
3070
+ */
3071
+ public function Finish() {
3072
+ /*$this->add_missed_values();
3073
+ $this->check_field_upload();
3074
+ $this->check_field_plupload();
3075
+ $this->check_field_color();
3076
+ $this->check_field_date();
3077
+ $this->check_field_time();
3078
+ $this->check_field_code();*/
3079
+ }
3080
+
3081
+ /**
3082
+ * Helper function to check for empty arrays
3083
+ * @author Ohad Raz
3084
+ * @since 0.1
3085
+ * @access public
3086
+ * @param $args mixed|array
3087
+ */
3088
+ public function is_array_empty($array){
3089
+ if (!is_array($array))
3090
+ return true;
3091
+
3092
+ foreach ($array as $a){
3093
+ if (is_array($a)){
3094
+ foreach ($a as $sub_a){
3095
+ if (!empty($sub_a) && $sub_a != '')
3096
+ return false;
3097
+ }
3098
+ }else{
3099
+ if (!empty($a) && $a != '')
3100
+ return false;
3101
+ }
3102
+ }
3103
+ return true;
3104
+ }
3105
+
3106
+ /**
3107
+ * Get the list of avialable Fonts
3108
+ *
3109
+ * @author Ohad Raz
3110
+ * @since 0.3
3111
+ * @access public
3112
+ *
3113
+ * @return mixed|array
3114
+ */
3115
+ public function get_fonts_family($font = null) {
3116
+ $fonts = get_option('WP_EX_FONTS_LIST', $default = false);
3117
+ if ($fonts === false){
3118
+ $fonts = array(
3119
+ 'arial' => array(
3120
+ 'name' => 'Arial',
3121
+ 'css' => "font-family: Arial, sans-serif;",
3122
+ ),
3123
+ 'verdana' => array(
3124
+ 'name' => "Verdana, Geneva",
3125
+ 'css' => "font-family: Verdana, Geneva;",
3126
+ ),
3127
+ 'trebuchet' => array(
3128
+ 'name' => "Trebuchet",
3129
+ 'css' => "font-family: Trebuchet;",
3130
+ ),
3131
+ 'georgia' => array(
3132
+ 'name' => "Georgia",
3133
+ 'css' => "font-family: Georgia;",
3134
+ ),
3135
+ 'times' => array(
3136
+ 'name' => "Times New Roman",
3137
+ 'css' => "font-family: Times New Roman;",
3138
+ ),
3139
+ 'tahoma' => array(
3140
+ 'name' => "Tahoma, Geneva",
3141
+ 'css' => "font-family: Tahoma, Geneva;",
3142
+ ),
3143
+ 'palatino' => array(
3144
+ 'name' => "Palatino",
3145
+ 'css' => "font-family: Palatino;",
3146
+ ),
3147
+ 'helvetica' => array(
3148
+ 'name' => "Verdana, Geneva",
3149
+ 'css' => "font-family: Helvetica*;",
3150
+ ),
3151
+ );
3152
+ if ($this->google_fonts){
3153
+ $api_keys = array(
3154
+ 'AIzaSyDXgT0NYjLhDmUzdcxC5RITeEDimRmpq3s',
3155
+ 'AIzaSyD6j7CsUTblh29PAXN3NqxBjnN-5nuuFGU',
3156
+ 'AIzaSyB8Ua6XIfe-gqbkE8P3XL4spd0x8Ft7eWo',
3157
+ 'AIzaSyDJYYVPLT9JaoMPF8G5cFm1YjTZMjknizE',
3158
+ 'AIzaSyDXt6e2t_gCfhlSfY8ShpR9WpqjMsjEimU'
3159
+ );
3160
+ $k = rand(0,count($api_keys) -1 );
3161
+ $gs = wp_remote_get( 'https://www.googleapis.com/webfonts/v1/webfonts?sort=popularity&key='.$api_keys[$k] ,array('sslverify' => false));
3162
+ if(! is_wp_error( $gs ) ) {
3163
+ $fontsSeraliazed = $gs['body'];
3164
+ $fontArray = json_decode($gs['body']);
3165
+ $fontArray = $fontArray->items;
3166
+ foreach ( $fontArray as $f ){
3167
+ $key = strtolower(str_replace(" ", "_", $f->family));
3168
+ $fonts[$key] = array(
3169
+ 'name' => $f->family,
3170
+ 'import' => str_replace(" ","+",$f->family),
3171
+ 'css' => 'font-family: '.$f->family .';', //@import url(http://fonts.googleapis.com/css?family=
3172
+ );
3173
+ }
3174
+ }
3175
+ }
3176
+ update_option('WP_EX_FONTS_LIST',$fonts);
3177
+ }
3178
+ $fonts = apply_filters( 'WP_EX_available_fonts_family', $fonts );
3179
+ if ($font === null){
3180
+ return $fonts;
3181
+ }else{
3182
+ foreach ($fonts as $f => $value) {
3183
+ if ($f == $font)
3184
+ return $value;
3185
+ }
3186
+ }
3187
+ }
3188
+
3189
+ /**
3190
+ * Get list of font faces
3191
+ *
3192
+ * @author Ohad Raz
3193
+ * @since 0.3
3194
+ * @access public
3195
+ *
3196
+ * @return array
3197
+ */
3198
+ public function get_font_style(){
3199
+ $default = array(
3200
+ 'normal' => 'Normal',
3201
+ 'italic' => 'Italic',
3202
+ 'oblique ' => 'Oblique'
3203
+ );
3204
+ return apply_filters( 'BF_available_fonts_style', $default );
3205
+ }
3206
+
3207
+ /**
3208
+ * Get list of font wieght
3209
+ *
3210
+ * @author Ohad Raz
3211
+ * @since 0.9.9
3212
+ * @access public
3213
+ *
3214
+ * @return array
3215
+ */
3216
+ public function get_font_weight(){
3217
+ $default = array(
3218
+ 'normal' => 'Normal',
3219
+ 'bold' => 'Bold',
3220
+ 'bolder' => 'Bolder',
3221
+ 'lighter' => 'Lighter',
3222
+ '100' => '100',
3223
+ '200' => '200',
3224
+ '300' => '300',
3225
+ '400' => '400',
3226
+ '500' => '500',
3227
+ '600' => '600',
3228
+ '700' => '700',
3229
+ '800' => '800',
3230
+ '900' => '900',
3231
+ 'inherit' => 'Inherit'
3232
+ );
3233
+ return apply_filters( 'BF_available_fonts_weights', $default );
3234
+ }
3235
+
3236
+ /**
3237
+ * Export Import Functions
3238
+ */
3239
+
3240
+ /**
3241
+ * Add import export to Page
3242
+ * @author Ohad Raz
3243
+ * @since 0.8
3244
+ * @access public
3245
+ *
3246
+ * @return void
3247
+ */
3248
+ public function addImportExport(){
3249
+ $new_field = array('type' => 'import_export','id'=> '','value' => '');
3250
+ $this->_fields[] = $new_field;
3251
+ }
3252
+
3253
+
3254
+ public function show_import_export(){
3255
+ $this->show_field_begin(array('name' => ''),null);
3256
+ $ret ='
3257
+ <div class="apc_ie_panel field">
3258
+ <div style="padding 10px;" class="apc_export"><h3>'.__('Export','apc').'</h3>
3259
+ <p>'. __('To export saved settings click the Export button bellow and you will get the export Code in the box bellow, which you can later use to import.','apc').'</p>
3260
+ <div class="export_code">
3261
+ <label for="export_code">'. __('Export Code','apc').'</label><br/>
3262
+ <textarea id="export_code"></textarea>
3263
+ <input class="button-primary" type="button" value="'. __('Get Export','apc').'" id="apc_export_b" />'.$this->create_export_download_link().'
3264
+ <div class="export_status" style="display: none;"><img src="http://i.imgur.com/l4pWs.gif" alt="loading..."/></div>
3265
+ <div class="export_results alert" style="display: none;"></div>
3266
+ </div>
3267
+ </div>
3268
+ <div style="padding 10px;" class="apc_import"><h3>'.__('Import','apc').'</h3>
3269
+ <p>'. __('To Import saved settings paste the Export output in to the Import Code box bellow and click Import.','apc').'</p>
3270
+ <div class="import_code">
3271
+ <label for="import_code">'. __('Import Code','apc').'</label><br/>
3272
+ <textarea id="import_code"></textarea>
3273
+ <input class="button-primary" type="button" value="'. __('Import','apc').'" id="apc_import_b" />
3274
+ <div class="import_status" style="display: none;"><img src="http://i.imgur.com/l4pWs.gif" alt="loading..."/></div>
3275
+ <div class="import_results alert" style="display: none;"></div>
3276
+ </div>
3277
+ </div>
3278
+ <input type="hidden" id="option_group_name" value="'.$this->option_group.'" />
3279
+ <input type="hidden" id="apc_import_nonce" name="apc_Import" value="'.wp_create_nonce("apc_import").'" />
3280
+ <input type="hidden" id="apc_export_nonce" name="apc_export" value="'.wp_create_nonce("apc_export").'" />
3281
+ ';
3282
+ echo apply_filters('apc_import_export_panel',$ret);
3283
+ $this->show_field_end(array('name' => '','desc' => ''),null);
3284
+ }
3285
+
3286
+ /**
3287
+ * Ajax export
3288
+ *
3289
+ * @author Ohad Raz
3290
+ * @since 0.8
3291
+ * @access public
3292
+ *
3293
+ * @return json object
3294
+ */
3295
+ public function export(){
3296
+ check_ajax_referer( 'apc_export', 'seq' );
3297
+ if (!isset($_GET['group'])){
3298
+ $re['err'] = __('error in ajax request! (1)','apc');
3299
+ $re['nonce'] = wp_create_nonce("apc_export");
3300
+ echo json_encode($re);
3301
+ die();
3302
+ }
3303
+
3304
+ $options = get_option($this->option_group,false);
3305
+ if ($options !== false)
3306
+ $re['code']= "<!*!* START export Code !*!*>\n".base64_encode(serialize($options))."\n<!*!* END export Code !*!*>";
3307
+ else
3308
+ $re['err'] = __('error in ajax request! (2)','apc');
3309
+
3310
+ //update_nonce
3311
+ $re['nonce'] = wp_create_nonce("apc_export");
3312
+ echo json_encode($re);
3313
+ die();
3314
+
3315
+ }
3316
+
3317
+ /**
3318
+ * Ajax import
3319
+ *
3320
+ * @author Ohad Raz
3321
+ * @since 0.8
3322
+ * @access public
3323
+ *
3324
+ * @return json object
3325
+ */
3326
+ public function import(){
3327
+ check_ajax_referer( 'apc_import', 'seq' );
3328
+ if (!isset($_POST['imp'])){
3329
+ $re['err'] = __('error in ajax request! (3)','apc');
3330
+ $re['nonce'] = wp_create_nonce("apc_import");
3331
+ echo json_encode($re);
3332
+ die();
3333
+ }
3334
+ $import_code = $_POST['imp'];
3335
+ $import_code = str_replace("<!*!* START export Code !*!*>\n","",$import_code);
3336
+ $import_code = str_replace("\n<!*!* END export Code !*!*>","",$import_code);
3337
+ $import_code = base64_decode($import_code);
3338
+ $import_code = unserialize($import_code);
3339
+ if (is_array($import_code)){
3340
+ update_option($this->option_group,$import_code);
3341
+ $re['success']= __('Setting imported, make sure you ','apc'). '<input class="button-primary" type="button" value="'. __('Refresh this page','apc').'" id="apc_refresh_page_b" />';
3342
+ }else{
3343
+ $re['err'] = __('Could not import settings! (4)','apc');
3344
+ }
3345
+ //update_nonce
3346
+ $re['nonce'] = wp_create_nonce("apc_import");
3347
+ echo json_encode($re);
3348
+ die();
3349
+ }
3350
+
3351
+
3352
+ //then define the function that will take care of the actual download
3353
+ public function download_file($content = null, $file_name = null){
3354
+ if (! wp_verify_nonce($_REQUEST['nonce'], 'theme_export_options') )
3355
+ wp_die('Security check');
3356
+
3357
+ //here you get the options to export and set it as content, ex:
3358
+ $options= get_option($_REQUEST['option_group']);
3359
+ $content = "<!*!* START export Code !*!*>\n".base64_encode(serialize($options))."\n<!*!* END export Code !*!*>";
3360
+ $file_name = apply_filters('apc_theme_export_filename', 'options.txt');
3361
+ header('HTTP/1.1 200 OK');
3362
+
3363
+ if ( !current_user_can('edit_themes') )
3364
+ wp_die('<p>'.__('You do not have sufficient permissions to edit templates for this site.','apc').'</p>');
3365
+
3366
+ if ($content === null || $file_name === null){
3367
+ wp_die('<p>'.__('Error Downloading file.','apc').'</p>');
3368
+ }
3369
+ $fsize = strlen($content);
3370
+ header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
3371
+ header('Content-Description: File Transfer');
3372
+ header("Content-Disposition: attachment; filename=" . $file_name);
3373
+ header("Content-Length: ".$fsize);
3374
+ header("Expires: 0");
3375
+ header("Pragma: public");
3376
+ echo $content;
3377
+ exit;
3378
+ }
3379
+
3380
+ public function create_export_download_link($echo = false){
3381
+ $site_url = get_bloginfo('url');
3382
+ $args = array(
3383
+ 'theme_export_options' => 'safe_download',
3384
+ 'nonce' => wp_create_nonce('theme_export_options'),
3385
+ 'option_group' => $this->option_group
3386
+ );
3387
+ $export_url = add_query_arg($args, $site_url);
3388
+ if ($echo === true)
3389
+ echo '<a href="'.$export_url.'" target="_blank">'.__('Download Export','apc').'</a>';
3390
+ elseif ($echo == 'url')
3391
+ return $export_url;
3392
+ return '<a class="button-primary" href="'.$export_url.'" target="_blank">'.__('Download Export','apc').'</a>';
3393
+ }
3394
+
3395
+ //first add a new query var
3396
+ public function add_query_var_vars() {
3397
+ global $wp;
3398
+ $wp->add_query_var('theme_export_options');
3399
+ }
3400
+
3401
+ //then add a template redirect which looks for that query var and if found calls the download function
3402
+ public function admin_redirect_download_files(){
3403
+ global $wp;
3404
+ global $wp_query;
3405
+ //download theme export
3406
+ if (array_key_exists('theme_export_options', $wp->query_vars) && $wp->query_vars['theme_export_options'] == 'safe_download' && $this->option_group == $_REQUEST['option_group'] ){
3407
+ $this->download_file();
3408
+ die();
3409
+ }
3410
+ }
3411
+
3412
+ public function Handle_plupload_action(){
3413
+ // check ajax noonce
3414
+ $imgid = $_POST["imgid"];
3415
+ check_ajax_referer($imgid . 'pluploadan');
3416
+
3417
+ // handle file upload
3418
+ $status = wp_handle_upload($_FILES[$imgid . 'async-upload'], array('test_form' => true, 'action' => 'plupload_action'));
3419
+
3420
+ // send the uploaded file url in response
3421
+ echo $status['url'];
3422
+ exit;
3423
+ }
3424
+
3425
+ /**
3426
+ * load_textdomain
3427
+ * @author Ohad Raz
3428
+ * @since 1.0.9
3429
+ * @return void
3430
+ */
3431
+ public function load_textdomain(){
3432
+ //In themes/plugins/mu-plugins directory
3433
+ load_textdomain( 'apc', dirname(__FILE__) . '/lang/' . get_locale() .'.mo' );
3434
+ }
3435
+
3436
+ /**
3437
+ * Validation functions
3438
+ */
3439
+
3440
+ /**
3441
+ * validate field
3442
+ * @access public
3443
+ * @author Ohad Raz <admin@bainternet.info>
3444
+ * @since 1.1.9
3445
+ * @param array $field field data
3446
+ * @param mixed $meta value to validate
3447
+ * @return boolean
3448
+ */
3449
+ public function validate_field($field,$meta){
3450
+ if (!isset($field['validate']) || !is_array($field['validate'] ))
3451
+ return true;
3452
+
3453
+ $ret = true;
3454
+ foreach ($field['validate'] as $type => $args) {
3455
+ if (method_exists($this,'is_' . $type)){
3456
+ if (call_user_func ( array( $this, 'is_' . $type ), $meta ,$args['param']) === false){
3457
+ $this->errors_flag = true;
3458
+ $this->errors[$field['id']]['name'] = $field['name'];
3459
+ $this->errors[$field['id']]['m'][] = (isset($args['message'])? $args['message'] : __('Not Valid ','apc') . $type);
3460
+ $ret = false;
3461
+ }
3462
+ }
3463
+ }
3464
+ return $ret;
3465
+ }
3466
+
3467
+ /**
3468
+ * displayErrors function to print out validation errors.
3469
+ * @access public
3470
+ * @author Ohad Raz <admin@bainternet.info>
3471
+ * @since 1.1.9
3472
+ * @return void
3473
+ */
3474
+ public function displayErrors(){
3475
+ if ($this->errors_flag){
3476
+ echo '<div class="alert alert-error"><button data-dismiss="alert" class="close" type="button">×</button>';
3477
+ echo '<h4>'.__('Errors in saving changes', 'apc').'</h4>';
3478
+ foreach ($this->errors as $id => $arr) {
3479
+ echo "<strong>{$arr['name']}</strong>: ";
3480
+ foreach ($arr['m'] as $m) {
3481
+ echo "<br />&nbsp;&nbsp;&nbsp;&nbsp;{$m}";
3482
+ }
3483
+ echo '<br />';
3484
+ }
3485
+ echo '</div>';
3486
+ }
3487
+ }
3488
+
3489
+ /**
3490
+ * getFieldErrors return field errors
3491
+ * @access public
3492
+ * @author Ohad Raz <admin@bainternet.info>
3493
+ * @since 1.1.9
3494
+ * @param string $field_id
3495
+ * @return array
3496
+ */
3497
+ public function getFieldErrors($field_id){
3498
+ if ($this->errors_flag){
3499
+ if (isset($this->errors[$field_id]))
3500
+ return $this->errors[$field_id];
3501
+ }
3502
+ return __('Unkown Error','apc');
3503
+ }
3504
+
3505
+ /**
3506
+ * has_error check if a field has errors
3507
+ * @access public
3508
+ * @author Ohad Raz <admin@bainternet.info>
3509
+ * @since 1.1.9
3510
+ * @param string $field_id field ID
3511
+ * @return boolean
3512
+ */
3513
+ public function has_error($field_id){
3514
+ //exit if not saved or no validation errors
3515
+ if (!$this->saved_flag || !$this->errors_flag)
3516
+ return false;
3517
+ //check if this field has validation errors
3518
+ if (isset($this->errors[$field_id]))
3519
+ return true;
3520
+ return false;
3521
+ }
3522
+
3523
+ /**
3524
+ * valid email
3525
+ * @access public
3526
+ * @author Ohad Raz <admin@bainternet.info>
3527
+ * @since 1.1.9
3528
+ * @param string
3529
+ * @return boolean
3530
+ */
3531
+ public function is_email($val){
3532
+ return (bool)(preg_match("/^([a-z0-9+_-]+)(.[a-z0-9+_-]+)*@([a-z0-9-]+.)+[a-z]{2,6}$/ix",$val));
3533
+ }
3534
+
3535
+ /**
3536
+ * check a number optional -,+,. values
3537
+ * @access public
3538
+ * @author Ohad Raz <admin@bainternet.info>
3539
+ * @since 1.1.9
3540
+ * @param string
3541
+ * @return boolean
3542
+ */
3543
+ public function is_numeric($val){
3544
+ return (bool)preg_match('/^[-+]?[0-9]*.?[0-9]+$/', (int)$val);
3545
+ }
3546
+
3547
+ /**
3548
+ * check given number below value
3549
+ * @access public
3550
+ * @author Ohad Raz <admin@bainternet.info>
3551
+ * @since 1.1.9
3552
+ * @param string
3553
+ * @return boolean
3554
+ */
3555
+ public function is_minvalue($number,$max){
3556
+ return (bool)((int)$number > (int)$max);
3557
+ }
3558
+
3559
+ /**
3560
+ * check given number exceeds max values
3561
+ * @access public
3562
+ * @author Ohad Raz <admin@bainternet.info>
3563
+ * @since 1.1.9
3564
+ * @param string
3565
+ * @return boolean
3566
+ */
3567
+ public function is_maxvalue($number,$max){
3568
+ return ((int)$number < (int)$max);
3569
+ }
3570
+
3571
+ /**
3572
+ * Check the string length has minimum length
3573
+ * @access public
3574
+ * @author Ohad Raz <admin@bainternet.info>
3575
+ * @since 1.1.9
3576
+ * @param string
3577
+ * @return boolean
3578
+ */
3579
+ public function is_minlength($val, $min){
3580
+ return (strlen($val) >= (int)$min);
3581
+ }
3582
+
3583
+ /**
3584
+ * check string length exceeds maximum length
3585
+ * @access public
3586
+ * @author Ohad Raz <admin@bainternet.info>
3587
+ * @since 1.1.9
3588
+ * @param string
3589
+ * @return boolean
3590
+ */
3591
+ public function is_maxlength($val, $max){
3592
+ return (strlen($val) <= (int)$max);
3593
+ }
3594
+
3595
+ /**
3596
+ * check for exactly length of string
3597
+ * @access public
3598
+ * @author Ohad Raz <admin@bainternet.info>
3599
+ * @since 1.1.9
3600
+ * @param string
3601
+ * @return boolean
3602
+ */
3603
+ public function is_length($val, $length){
3604
+ return (strlen($val) == (int)$length);
3605
+ }
3606
+
3607
+ /**
3608
+ * Valid URL or web address
3609
+ * @access public
3610
+ * @author Ohad Raz <admin@bainternet.info>
3611
+ * @since 1.1.9
3612
+ * @param string
3613
+ * @return boolean
3614
+ */
3615
+ public function is_url($val){
3616
+ return (bool)preg_match('|^http(s)?://[a-z0-9-]+(.[a-z0-9-]+)*(:[0-9]+)?(/.*)?$|i', $val);
3617
+ }
3618
+
3619
+ /**
3620
+ * Matches alpha and numbers only
3621
+ * @access public
3622
+ * @author Ohad Raz <admin@bainternet.info>
3623
+ * @since 1.1.9
3624
+ * @param string
3625
+ * @return boolean
3626
+ */
3627
+ public function is_alphanumeric($val){
3628
+ return (bool)preg_match("/^([a-zA-Z0-9])+$/i", $val);
3629
+ }
3630
+
3631
+
3632
+ } // End Class
3633
+
3634
+ endif; // End Check Class Exists
functions/admin-page-class/css/Admin_Page_Class.css ADDED
@@ -0,0 +1,534 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * admin pages class
3
+ *
4
+ * CSS used for the admin pages class and other form items.
5
+ *
6
+ * Copyright 2011 Ohad Raz (admin@bainternet.info)
7
+ */
8
+
9
+ /* Common Rules for all fields.
10
+ ----------------------------------------------- */
11
+ form#admin_page_class { margin: 0; }
12
+ .form-table td.at-field {
13
+ border:1px solid #DDD;
14
+ padding:10px 10px 20px;
15
+ margin:0;
16
+ font-family:"HelveticaNeue-Light","Helvetica Neue Light","Helvetica Neue",Helvetica,Arial,sans-serif;
17
+ }
18
+ .at-label {
19
+ margin:0!important;
20
+ padding:5px 0 0;
21
+ font:20px/31px HelveticaNeue-Light,"Helvetica Neue Light","Helvetica Neue",Helvetica,Arial,sans-serif;
22
+ text-shadow:rgba(255,255,255,1) 0 1px 0;
23
+ width:auto;
24
+ float:left;
25
+ }
26
+
27
+ .at-radio-label {
28
+ padding-right:10px;
29
+ }
30
+
31
+ .at-file-upload-label {
32
+ clear:both;
33
+ margin:5px 0 5px 1px;
34
+ }
35
+
36
+ .wp-picker-container {
37
+ float:right;
38
+ width:260px;
39
+ }
40
+
41
+ /* Form Fields
42
+ ----------------------------------------------- */
43
+ .clearfix {
44
+ clear:both;
45
+ width:100%;
46
+ }
47
+
48
+ .postbox .at-field input,
49
+ .postbox .at-field textarea {
50
+ padding:5px;
51
+ line-height:18px;
52
+ }
53
+
54
+ .postbox .at-field input.at-color {
55
+ border:0;
56
+ -webkit-border-radius:5px;
57
+ -moz-border-radius:5px;
58
+ border-radius:5px;
59
+ margin-right:10px;
60
+ min-width:100px;
61
+ }
62
+
63
+ .at-field input:focus,
64
+ .at-field textarea:focus {
65
+ background:#fffff8;
66
+ }
67
+
68
+ #wpcontent select.at-select {
69
+ min-height:30px!important;
70
+ padding:5px;
71
+ display:block;
72
+ min-width:200px;
73
+ float:right;
74
+ }
75
+
76
+ .at-field .desc-field {
77
+ color:#AAA;
78
+ font-style:italic;
79
+ margin:5px 0 0 3px!important;
80
+ font-size:13px;
81
+ }
82
+
83
+ .desc-field {
84
+ background-color:#D9EDF7;
85
+ border:1px solid #BCE8F1;
86
+ color:#3A87AD;
87
+ padding:8px 35px 8px 14px;
88
+ border-radius:4px 4px 4px 4px;
89
+ margin-bottom:20px;
90
+ padding:8px 35px 8px 14px;
91
+ text-shadow:0 1px 0 rgba(255,255,255,0.5);
92
+ }
93
+
94
+ .at-field .wp_themeSkin table.mceLayout {
95
+ border:1px solid #DFDFDF;
96
+ }
97
+
98
+ #post-body .at-field .wp_themeSkin .mceStatusbar a.mceResize {
99
+ top:-25px;
100
+ }
101
+
102
+ /* Uploaded Images
103
+ ----------------------------------------------- */
104
+ .at-images li {
105
+ margin:5px 10px 0 0;
106
+ float:left;
107
+ width:150px;
108
+ height:150px;
109
+ text-align:center;
110
+ border:3px solid #ccc;
111
+ cursor:move;
112
+ position:relative;
113
+ -webkit-border-radius:3px;
114
+ -moz-border-radius:3px;
115
+ border-radius:3px;
116
+ }
117
+
118
+ .at-images img {
119
+ width:150px;
120
+ height:150px;
121
+ }
122
+
123
+ .at-images a {
124
+ position:absolute;
125
+ top:-12px;
126
+ right:-12px;
127
+ color:#fff;
128
+ font-weight:700;
129
+ padding:5px;
130
+ }
131
+
132
+ .at-images .at-delete-file img {
133
+ width:16px;
134
+ height:16px;
135
+ }
136
+
137
+ /* Upload Button
138
+ ----------------------------------------------- */
139
+ .at-upload-button {
140
+ float:left;
141
+ clear:both;
142
+ margin-top:10px;
143
+ }
144
+
145
+ .at-add-file {
146
+ float:left;
147
+ clear:both;
148
+ margin-top:10px;
149
+ }
150
+
151
+ /* Time Picker
152
+ ----------------------------------------------- */
153
+ .ui-timepicker-div {
154
+ font-size:.9em;
155
+ }
156
+
157
+ .ui-timepicker-div .ui-widget-header {
158
+ margin-bottom:8px;
159
+ }
160
+
161
+ .ui-timepicker-div dl {
162
+ text-align:left;
163
+ }
164
+
165
+ .ui-timepicker-div dl dt {
166
+ height:25px;
167
+ }
168
+
169
+ .ui-timepicker-div dl dd {
170
+ margin:-25px 0 10px 65px;
171
+ }
172
+
173
+ .ui-timepicker-div td {
174
+ font-size:90%;
175
+ }
176
+
177
+ #ui-datepicker-div {
178
+ display:none;
179
+ }
180
+
181
+ /* Repater Block
182
+ ----------------------------------------------- */
183
+ /* inline */
184
+ .at-inline label {
185
+ font-size:12px!important;
186
+ }
187
+
188
+ .at-inline textarea {
189
+ height:130px;
190
+ width:200px;
191
+ }
192
+
193
+ /* panel style
194
+ ----------------------------------------------- */
195
+ .wrap {
196
+ background:#fff;
197
+ border:1px solid #CCC;
198
+ margin:17px 0 40px;
199
+ width:800px;
200
+ border-radius:0;
201
+ }
202
+
203
+ .header_wrap {
204
+ padding:5px 20px 10px;
205
+ }
206
+
207
+ .footer_wrap {
208
+ padding:5px 20px 10px;
209
+ }
210
+
211
+ .panel_menu {
212
+ float:left;
213
+ width:160px;
214
+ }
215
+
216
+ .clearboth {
217
+ clear:both;
218
+ }
219
+
220
+ .f_row {
221
+ border-bottom:1px solid #F9F9F9;
222
+ }
223
+
224
+ .sections {
225
+ background:none repeat scroll 0 0 #FFF;
226
+ float:left;
227
+ margin-top:1px;
228
+ min-height:520px;
229
+ padding-bottom:10px;
230
+ width:624px;
231
+ padding-left:15px;
232
+ }
233
+
234
+ .sw_field {
235
+ padding:10px;
236
+ border-bottom:1px solid #E9EAEE;
237
+ }
238
+
239
+ .sections textarea {
240
+ background:-moz-linear-gradient(center top,#F9F9F9,#FFF) repeat scroll 0 0 transparent;
241
+ color:#333;
242
+ font-size:12px;
243
+ height:175px;
244
+ line-height:1.5em;
245
+ padding:4px;
246
+ width:390px;
247
+ }
248
+
249
+ .sections label {
250
+ clear:both;
251
+ display:block;
252
+ font-size:12px;
253
+ font-weight:700;
254
+ margin:0 0 10px;
255
+ width:100%;
256
+ }
257
+
258
+ .setingstab {
259
+ min-height:500px;
260
+ }
261
+
262
+ .sections input[type="text"],
263
+ .sections input[type="password"],
264
+ .sections input[type="number"],
265
+ .sections input[type="file"],
266
+ .sections select {
267
+ background:-moz-linear-gradient(center top,#F9F9F9,#FFF) repeat scroll 0 0 transparent;
268
+ color:#333;
269
+ font-size:12px;
270
+ line-height:1em;
271
+ padding:10px;
272
+ width:65%;
273
+ font-size:100%;
274
+ -webkit-border-radius: 4px;
275
+ -moz-border-radius: 4px;
276
+ border-radius: 4px;
277
+ box-shadow:none;
278
+ height:42px;
279
+ float:right;
280
+ }
281
+
282
+ .sections input[type="number"] {
283
+ width: 150px;
284
+ }
285
+
286
+ .nav_tab_link {
287
+ border:none;
288
+ -webkit-border-radius:0 4px 4px 0;
289
+ -moz-border-radius:0 4px 4px 0;
290
+ border-radius:0 4px 4px 0;
291
+ color:#444;
292
+ display:block;
293
+ font-size:12px;
294
+ line-height:1.5;
295
+ margin:0 6px -1px 0;
296
+ padding:10px 0 10px 20px;
297
+ text-decoration:none;
298
+ width:100%;
299
+ }
300
+
301
+ .nav_tab_link:hover {
302
+ background:#ee464f;
303
+ color:#fff;
304
+ font-weight:700;
305
+ -webkit-border-radius:0 4px 4px 0;
306
+ -moz-border-radius:0 4px 4px 0;
307
+ border-radius:0 4px 4px 0;
308
+ }
309
+
310
+ .description {
311
+ color:#999;
312
+ display:block;
313
+ float:right;
314
+ font-size:11px;
315
+ margin-top:-2px;
316
+ width:200px;
317
+ }
318
+
319
+ .active_tab {
320
+ background:#2f394f;
321
+ color:#fff;
322
+ font-weight:700;
323
+ -webkit-border-radius:0 4px 4px 0;
324
+ -moz-border-radius:0 4px 4px 0;
325
+ border-radius:0 4px 4px 0;
326
+ }
327
+
328
+ .active_tab a,.nav_tab_link:hover a {
329
+ color:#fff;
330
+ text-shadow:none;
331
+ -webkit-border-radius:0 4px 4px 0;
332
+ -moz-border-radius:0 4px 4px 0;
333
+ border-radius:0 4px 4px 0;
334
+ }
335
+
336
+ .editorcontainer {
337
+ -webkit-border-radius:6px;
338
+ border:1px solid #DEDEDE;
339
+ }
340
+
341
+ .btn,.btn-info,
342
+ .btn-primary,
343
+ .btn-warning {
344
+ color: #FFF;
345
+ padding: 10px 20px;
346
+ border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);
347
+ -webkit-border-radius:4px;
348
+ -moz-border-radius:4px;
349
+ border-radius:4px;
350
+ border-style:solid;
351
+ border-width:1px;
352
+ cursor:pointer;
353
+ display:inline-block;
354
+ line-height:18px;
355
+ padding: 10px 20px;
356
+ text-align:center;
357
+ }
358
+
359
+ .btn {
360
+ background-color:#FAFAFA;
361
+ background-image:-moz-linear-gradient(center top,#08C,#04C);
362
+ background-repeat:repeat-x;
363
+ }
364
+
365
+ .btn-info {
366
+ background-color:#2f394f;
367
+ background-image:-moz-linear-gradient(center top,#08C,#04C);
368
+ background-repeat:repeat-x;
369
+ }
370
+
371
+ .btn-primary {
372
+ background-color:#006DCC;
373
+ background-image:-moz-linear-gradient(center top,#08C,#04C);
374
+ background-repeat:repeat-x;
375
+ }
376
+
377
+ .btn-warning {
378
+ background-color:#FAA732;
379
+ background-image:-moz-linear-gradient(center top,#FBB450,#F89406);
380
+ background-repeat:repeat-x;
381
+ }
382
+
383
+ .btn:hover,
384
+ .btn-info:hover,
385
+ .btn-primary:hover {
386
+ background: #ee464f;
387
+ }
388
+
389
+ /* alerts */
390
+ .alert {
391
+ background-color:#FCF8E3;
392
+ border:1px solid #FBEED5;
393
+ margin-bottom:20px;
394
+ padding: 10px 35px 10px 14px;
395
+ text-shadow:0 1px 0 rgba(255,255,255,0.5);
396
+ }
397
+
398
+ .alert,.alert-heading {
399
+ color:#C09853;
400
+ }
401
+
402
+ .alert h4 {
403
+ font-size:17px;
404
+ margin:0;
405
+ }
406
+
407
+ .alert-success {
408
+ background-color:#DFF0D8;
409
+ border-color:#D6E9C6;
410
+ }
411
+
412
+ .alert-success,
413
+ .alert-success .alert-heading {
414
+ color:#468847;
415
+ }
416
+
417
+ .alert-danger,
418
+ .alert-error {
419
+ background-color:#ee464f;
420
+ border-color:#d34250;
421
+ color:#fff;
422
+ }
423
+
424
+ .alert .close {
425
+ line-height:20px;
426
+ position:relative;
427
+ right:-21px;
428
+ top:-2px;
429
+ }
430
+
431
+ button.close {
432
+ background:none repeat scroll 0 0 transparent;
433
+ border:0 none;
434
+ cursor:pointer;
435
+ padding:0;
436
+ }
437
+
438
+ .close {
439
+ color:#000;
440
+ float:right;
441
+ font-size:20px;
442
+ font-weight:700;
443
+ line-height:20px;
444
+ opacity:.2;
445
+ text-shadow:0 1px 0 #FFF;
446
+ }
447
+
448
+ /* Sort */
449
+ .widget-sort {
450
+ color: #fff;
451
+ background-color:#30394f;
452
+ border:1px dashed #fff;
453
+ -webkit-border-radius: 4px;
454
+ -moz-border-radius: 4px;
455
+ border-radius: 4px;
456
+ padding:10px;
457
+ text-align:center;
458
+ width:65%;
459
+ }
460
+
461
+ .ui-state-highlight {
462
+ background-color:#FFFFE0;
463
+ border-color:#E6DB55;
464
+ padding:14px;
465
+ width:60%;
466
+ }
467
+
468
+ .ui-sortable li {
469
+ cursor:move;
470
+ float:right;
471
+ }
472
+
473
+ .ui-sortable .at-repater-block {
474
+ cursor:move;
475
+ }
476
+
477
+ /* Typo field iris color picker */
478
+ .wp-picker-container {
479
+ height:20px;
480
+ margin-top: 10px;
481
+ }
482
+
483
+ /* issue #17 number 7 */
484
+ div.iris-picker {
485
+ z-index:100;
486
+ }
487
+
488
+ /* Select 2 typo field Fix*/
489
+ .at-typography-size {
490
+ width:11%;
491
+ }
492
+
493
+ .at-typography-face {
494
+ width:30%;
495
+ }
496
+
497
+ .hidden {
498
+ display:none;
499
+ }
500
+
501
+ .toplevel_page_social-warfare .sections {
502
+ width:624px!important;
503
+ max-width:624px!important;
504
+ }
505
+ .sw_loading_modal {
506
+ display: none;
507
+ position: fixed;
508
+ z-index: 100000;
509
+ top: 0;
510
+ left: 0;
511
+ height: 100%;
512
+ width: 100%;
513
+ background: rgba( 0, 0, 0, .9 ) url('../images/ajax-loader.gif') 50% 66% no-repeat;
514
+ }
515
+ .sw_loading_modal .sw_modal_message {
516
+ position:absolute;
517
+ top:33%;
518
+ font-size:150%;
519
+ width:100%;
520
+ color:white;
521
+ text-align:center;
522
+ }
523
+ .sw_loading_modal .sw_modal_message .sw_modal_subtitle {
524
+ font-size:85%;
525
+ }
526
+ body.sw_loading {
527
+ overflow: hidden;
528
+ }
529
+
530
+ /* Anytime the body has the loading class, our
531
+ modal element will be visible */
532
+ body.sw_loading .sw_loading_modal {
533
+ display: block;
534
+ }
functions/admin-page-class/css/images/ui-bg_flat_0_aaaaaa_40x100.png ADDED
Binary file
functions/admin-page-class/css/images/ui-bg_glass_55_fbf9ee_1x400.png ADDED
Binary file
functions/admin-page-class/css/images/ui-bg_glass_65_ffffff_1x400.png ADDED
Binary file
functions/admin-page-class/css/images/ui-bg_glass_75_dadada_1x400.png ADDED
Binary file
functions/admin-page-class/css/images/ui-bg_glass_75_e6e6e6_1x400.png ADDED
Binary file
functions/admin-page-class/css/images/ui-bg_glass_75_ffffff_1x400.png ADDED
Binary file
functions/admin-page-class/css/images/ui-bg_highlight-soft_75_cccccc_1x100.png ADDED
Binary file
functions/admin-page-class/css/images/ui-bg_inset-soft_95_fef1ec_1x100.png ADDED
Binary file
functions/admin-page-class/css/images/ui-icons_222222_256x240.png ADDED
Binary file
functions/admin-page-class/css/images/ui-icons_2e83ff_256x240.png ADDED
Binary file
functions/admin-page-class/css/images/ui-icons_454545_256x240.png ADDED
Binary file
functions/admin-page-class/css/images/ui-icons_888888_256x240.png ADDED
Binary file
functions/admin-page-class/css/images/ui-icons_cd0a0a_256x240.png ADDED
Binary file
functions/admin-page-class/css/images/ui-icons_f6cf3b_256x240.png ADDED
Binary file
functions/admin-page-class/css/jquery-ui.css ADDED
@@ -0,0 +1,1393 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * jQuery UI Bootstrap (0.22)
3
+ * http://addyosmani.github.com/jquery-ui-bootstrap
4
+ *
5
+ * Copyright 2012, Addy Osmani
6
+ * Dual licensed under the MIT or GPL Version 2 licenses.
7
+ *
8
+ * Portions copyright jQuery UI & Twitter Bootstrap
9
+ */
10
+
11
+
12
+ /* Layout helpers
13
+ ----------------------------------*/
14
+ .ui-helper-hidden { display: none; }
15
+ .ui-helper-hidden-accessible { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; }
16
+ .ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
17
+ .ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
18
+ .ui-helper-clearfix { display: inline-block; }
19
+ /* required comment for clearfix to work in Opera \*/
20
+ * html .ui-helper-clearfix { height:1%; }
21
+ .ui-helper-clearfix { display:block; }
22
+ /* end clearfix */
23
+ .ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
24
+
25
+
26
+
27
+ /* Interaction Cues
28
+ ----------------------------------*/
29
+ .ui-state-disabled { cursor: default !important; }
30
+
31
+
32
+ /* Icons
33
+ ----------------------------------*/
34
+
35
+ /* states and images */
36
+ .ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
37
+
38
+
39
+ /* Misc visuals
40
+ ----------------------------------*/
41
+
42
+ /* Overlays */
43
+ .ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
44
+
45
+
46
+ /*
47
+ * jQuery UI CSS Framework 1.8.16
48
+ *
49
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
50
+ * Dual licensed under the MIT or GPL Version 2 licenses.
51
+ * http://jquery.org/license
52
+ *
53
+ * http://docs.jquery.com/UI/Theming/API
54
+ *
55
+ * To view and modify this theme, visit http://jqueryui.com/themeroller/?ctl=themeroller
56
+ */
57
+
58
+
59
+ /* Component containers
60
+ ----------------------------------*/
61
+ .ui-widget { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size:13px; }
62
+ .ui-widget .ui-widget { font-size: 1em; }
63
+ .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 1em; }
64
+ .ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_75_ffffff_1x400.png) 50% 50% repeat-x; color: #404040; }
65
+ .ui-widget-content a { color: #404040; }
66
+ .ui-widget-header {
67
+ font-weight:bold;
68
+ border-color: #0064cd #0064cd #003f81;
69
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
70
+ border:1px solid #666;
71
+
72
+ }
73
+ .ui-widget-header a { color: #222222; }
74
+
75
+ /* Interaction states
76
+ ----------------------------------*/
77
+ .ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default {
78
+
79
+ background-color: #e6e6e6;
80
+ background-repeat: no-repeat;
81
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), color-stop(25%, #ffffff), to(#e6e6e6));
82
+ background-image: -webkit-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);
83
+ background-image: -moz-linear-gradient(top, #ffffff, #ffffff 25%, #e6e6e6);
84
+ background-image: -ms-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);
85
+ background-image: -o-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);
86
+ background-image: linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);
87
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0);
88
+
89
+ text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
90
+
91
+ color: #333;
92
+ font-size: 13px;
93
+ line-height: normal;
94
+ border: 1px solid #ccc;
95
+ border-bottom-color: #bbb;
96
+ -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
97
+ -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
98
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
99
+ -webkit-transition: 0.1s linear background-image;
100
+ -moz-transition: 0.1s linear background-image;
101
+ -ms-transition: 0.1s linear background-image;
102
+ -o-transition: 0.1s linear background-image;
103
+ transition: 0.1s linear background-image;
104
+ overflow: visible;
105
+
106
+ }
107
+
108
+
109
+ .ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; }
110
+ .ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus {
111
+ background-position: 0 -15px;
112
+ color: #333;
113
+ text-decoration: none;
114
+
115
+
116
+ }
117
+ .ui-state-hover a, .ui-state-hover a:hover, .ui-state-hover a:link, .ui-state-hover a:visited { color: #212121/*{fcHover}*/; text-decoration: none; }
118
+ .ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; font-weight: normal; color: #212121; }
119
+ .ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; }
120
+ .ui-widget :active { outline: none; }
121
+
122
+ /* Interaction Cues
123
+ ----------------------------------*/
124
+
125
+
126
+ .ui-state-highlight p, .ui-state-error p, .ui-state-default p{
127
+ font-size: 13px;
128
+ font-weight: normal;
129
+ line-height: 18px;
130
+ margin:7px 15px;
131
+ }
132
+ .ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {
133
+
134
+
135
+ position: relative;
136
+ margin-bottom: 18px;
137
+ color: #404040;
138
+ background-color: #eedc94;
139
+ background-repeat: repeat-x;
140
+ background-image: -khtml-gradient(linear, left top, left bottom, from(#fceec1), to(#eedc94));
141
+ background-image: -moz-linear-gradient(top, #fceec1, #eedc94);
142
+ background-image: -ms-linear-gradient(top, #fceec1, #eedc94);
143
+ background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fceec1), color-stop(100%, #eedc94));
144
+ background-image: -webkit-linear-gradient(top, #fceec1, #eedc94);
145
+ background-image: -o-linear-gradient(top, #fceec1, #eedc94);
146
+ background-image: linear-gradient(top, #fceec1, #eedc94);
147
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fceec1', endColorstr='#eedc94', GradientType=0);
148
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
149
+ border-color: #eedc94 #eedc94 #e4c652;
150
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
151
+ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
152
+ border-width: 1px;
153
+ border-style: solid;
154
+ -webkit-border-radius: 4px;
155
+ -moz-border-radius: 4px;
156
+ border-radius: 4px;
157
+ -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
158
+ -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
159
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
160
+
161
+
162
+ }
163
+ .ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
164
+ .ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {
165
+
166
+
167
+ position: relative;
168
+ margin-bottom: 18px;
169
+ color: #ffffff;
170
+ border-width: 1px;
171
+ border-style: solid;
172
+ -webkit-border-radius: 4px;
173
+ -moz-border-radius: 4px;
174
+ border-radius: 4px;
175
+ -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
176
+ -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
177
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
178
+ background-color: #c43c35;
179
+ background-repeat: repeat-x;
180
+ background-image: -khtml-gradient(linear, left top, left bottom, from(#ee5f5b), to(#c43c35));
181
+ background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);
182
+ background-image: -ms-linear-gradient(top, #ee5f5b, #c43c35);
183
+ background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ee5f5b), color-stop(100%, #c43c35));
184
+ background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);
185
+ background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);
186
+ background-image: linear-gradient(top, #ee5f5b, #c43c35);
187
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0);
188
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
189
+ border-color: #c43c35 #c43c35 #882a25;
190
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
191
+
192
+
193
+ }
194
+ .ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; }
195
+ .ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; }
196
+ .ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
197
+ .ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
198
+ .ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
199
+ .ui-state-disabled .ui-icon { filter:Alpha(Opacity=35); } /* For IE8 - See #6059 */
200
+
201
+
202
+ /* Icons
203
+ ----------------------------------*/
204
+
205
+ /* states and images */
206
+ .ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
207
+ .ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
208
+ .ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
209
+ .ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); }
210
+ .ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
211
+ .ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
212
+ .ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); }
213
+ .ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_f6cf3b_256x240.png); }
214
+
215
+ /* positioning */
216
+ .ui-icon-carat-1-n { background-position: 0 0; }
217
+ .ui-icon-carat-1-ne { background-position: -16px 0; }
218
+ .ui-icon-carat-1-e { background-position: -32px 0; }
219
+ .ui-icon-carat-1-se { background-position: -48px 0; }
220
+ .ui-icon-carat-1-s { background-position: -64px 0; }
221
+ .ui-icon-carat-1-sw { background-position: -80px 0; }
222
+ .ui-icon-carat-1-w { background-position: -96px 0; }
223
+ .ui-icon-carat-1-nw { background-position: -112px 0; }
224
+ .ui-icon-carat-2-n-s { background-position: -128px 0; }
225
+ .ui-icon-carat-2-e-w { background-position: -144px 0; }
226
+ .ui-icon-triangle-1-n { background-position: 0 -16px; }
227
+ .ui-icon-triangle-1-ne { background-position: -16px -16px; }
228
+ .ui-icon-triangle-1-e { background-position: -32px -16px; }
229
+ .ui-icon-triangle-1-se { background-position: -48px -16px; }
230
+ .ui-icon-triangle-1-s { background-position: -64px -16px; }
231
+ .ui-icon-triangle-1-sw { background-position: -80px -16px; }
232
+ .ui-icon-triangle-1-w { background-position: -96px -16px; }
233
+ .ui-icon-triangle-1-nw { background-position: -112px -16px; }
234
+ .ui-icon-triangle-2-n-s { background-position: -128px -16px; }
235
+ .ui-icon-triangle-2-e-w { background-position: -144px -16px; }
236
+ .ui-icon-arrow-1-n { background-position: 0 -32px; }
237
+ .ui-icon-arrow-1-ne { background-position: -16px -32px; }
238
+ .ui-icon-arrow-1-e { background-position: -32px -32px; }
239
+ .ui-icon-arrow-1-se { background-position: -48px -32px; }
240
+ .ui-icon-arrow-1-s { background-position: -64px -32px; }
241
+ .ui-icon-arrow-1-sw { background-position: -80px -32px; }
242
+ .ui-icon-arrow-1-w { background-position: -96px -32px; }
243
+ .ui-icon-arrow-1-nw { background-position: -112px -32px; }
244
+ .ui-icon-arrow-2-n-s { background-position: -128px -32px; }
245
+ .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
246
+ .ui-icon-arrow-2-e-w { background-position: -160px -32px; }
247
+ .ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
248
+ .ui-icon-arrowstop-1-n { background-position: -192px -32px; }
249
+ .ui-icon-arrowstop-1-e { background-position: -208px -32px; }
250
+ .ui-icon-arrowstop-1-s { background-position: -224px -32px; }
251
+ .ui-icon-arrowstop-1-w { background-position: -240px -32px; }
252
+ .ui-icon-arrowthick-1-n { background-position: 0 -48px; }
253
+ .ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
254
+ .ui-icon-arrowthick-1-e { background-position: -32px -48px; }
255
+ .ui-icon-arrowthick-1-se { background-position: -48px -48px; }
256
+ .ui-icon-arrowthick-1-s { background-position: -64px -48px; }
257
+ .ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
258
+ .ui-icon-arrowthick-1-w { background-position: -96px -48px; }
259
+ .ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
260
+ .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
261
+ .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
262
+ .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
263
+ .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
264
+ .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
265
+ .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
266
+ .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
267
+ .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
268
+ .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
269
+ .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
270
+ .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
271
+ .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
272
+ .ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
273
+ .ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
274
+ .ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
275
+ .ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
276
+ .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
277
+ .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
278
+ .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
279
+ .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
280
+ .ui-icon-arrow-4 { background-position: 0 -80px; }
281
+ .ui-icon-arrow-4-diag { background-position: -16px -80px; }
282
+ .ui-icon-extlink { background-position: -32px -80px; }
283
+ .ui-icon-newwin { background-position: -48px -80px; }
284
+ .ui-icon-refresh { background-position: -64px -80px; }
285
+ .ui-icon-shuffle { background-position: -80px -80px; }
286
+ .ui-icon-transfer-e-w { background-position: -96px -80px; }
287
+ .ui-icon-transferthick-e-w { background-position: -112px -80px; }
288
+ .ui-icon-folder-collapsed { background-position: 0 -96px; }
289
+ .ui-icon-folder-open { background-position: -16px -96px; }
290
+ .ui-icon-document { background-position: -32px -96px; }
291
+ .ui-icon-document-b { background-position: -48px -96px; }
292
+ .ui-icon-note { background-position: -64px -96px; }
293
+ .ui-icon-mail-closed { background-position: -80px -96px; }
294
+ .ui-icon-mail-open { background-position: -96px -96px; }
295
+ .ui-icon-suitcase { background-position: -112px -96px; }
296
+ .ui-icon-comment { background-position: -128px -96px; }
297
+ .ui-icon-person { background-position: -144px -96px; }
298
+ .ui-icon-print { background-position: -160px -96px; }
299
+ .ui-icon-trash { background-position: -176px -96px; }
300
+ .ui-icon-locked { background-position: -192px -96px; }
301
+ .ui-icon-unlocked { background-position: -208px -96px; }
302
+ .ui-icon-bookmark { background-position: -224px -96px; }
303
+ .ui-icon-tag { background-position: -240px -96px; }
304
+ .ui-icon-home { background-position: 0 -112px; }
305
+ .ui-icon-flag { background-position: -16px -112px; }
306
+ .ui-icon-calendar { background-position: -32px -112px; }
307
+ .ui-icon-cart { background-position: -48px -112px; }
308
+ .ui-icon-pencil { background-position: -64px -112px; }
309
+ .ui-icon-clock { background-position: -80px -112px; }
310
+ .ui-icon-disk { background-position: -96px -112px; }
311
+ .ui-icon-calculator { background-position: -112px -112px; }
312
+ .ui-icon-zoomin { background-position: -128px -112px; }
313
+ .ui-icon-zoomout { background-position: -144px -112px; }
314
+ .ui-icon-search { background-position: -160px -112px; }
315
+ .ui-icon-wrench { background-position: -176px -112px; }
316
+ .ui-icon-gear { background-position: -192px -112px; }
317
+ .ui-icon-heart { background-position: -208px -112px; }
318
+ .ui-icon-star { background-position: -224px -112px; }
319
+ .ui-icon-link { background-position: -240px -112px; }
320
+ .ui-icon-cancel { background-position: 0 -128px; }
321
+ .ui-icon-plus { background-position: -16px -128px; }
322
+ .ui-icon-plusthick { background-position: -32px -128px; }
323
+ .ui-icon-minus { background-position: -48px -128px; }
324
+ .ui-icon-minusthick { background-position: -64px -128px; }
325
+ .ui-icon-close { background-position: -80px -128px; }
326
+ .ui-icon-closethick { background-position: -96px -128px; }
327
+ .ui-icon-key { background-position: -112px -128px; }
328
+ .ui-icon-lightbulb { background-position: -128px -128px; }
329
+ .ui-icon-scissors { background-position: -144px -128px; }
330
+ .ui-icon-clipboard { background-position: -160px -128px; }
331
+ .ui-icon-copy { background-position: -176px -128px; }
332
+ .ui-icon-contact { background-position: -192px -128px; }
333
+ .ui-icon-image { background-position: -208px -128px; }
334
+ .ui-icon-video { background-position: -224px -128px; }
335
+ .ui-icon-script { background-position: -240px -128px; }
336
+ .ui-icon-alert { background-position: 0 -144px; }
337
+ .ui-icon-info { background-position: -16px -144px; }
338
+ .ui-icon-notice { background-position: -32px -144px; }
339
+ .ui-icon-help { background-position: -48px -144px; }
340
+ .ui-icon-check { background-position: -64px -144px; }
341
+ .ui-icon-bullet { background-position: -80px -144px; }
342
+ .ui-icon-radio-off { background-position: -96px -144px; }
343
+ .ui-icon-radio-on { background-position: -112px -144px; }
344
+ .ui-icon-pin-w { background-position: -128px -144px; }
345
+ .ui-icon-pin-s { background-position: -144px -144px; }
346
+ .ui-icon-play { background-position: 0 -160px; }
347
+ .ui-icon-pause { background-position: -16px -160px; }
348
+ .ui-icon-seek-next { background-position: -32px -160px; }
349
+ .ui-icon-seek-prev { background-position: -48px -160px; }
350
+ .ui-icon-seek-end { background-position: -64px -160px; }
351
+ .ui-icon-seek-start { background-position: -80px -160px; }
352
+ /* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
353
+ .ui-icon-seek-first { background-position: -80px -160px; }
354
+ .ui-icon-stop { background-position: -96px -160px; }
355
+ .ui-icon-eject { background-position: -112px -160px; }
356
+ .ui-icon-volume-off { background-position: -128px -160px; }
357
+ .ui-icon-volume-on { background-position: -144px -160px; }
358
+ .ui-icon-power { background-position: 0 -176px; }
359
+ .ui-icon-signal-diag { background-position: -16px -176px; }
360
+ .ui-icon-signal { background-position: -32px -176px; }
361
+ .ui-icon-battery-0 { background-position: -48px -176px; }
362
+ .ui-icon-battery-1 { background-position: -64px -176px; }
363
+ .ui-icon-battery-2 { background-position: -80px -176px; }
364
+ .ui-icon-battery-3 { background-position: -96px -176px; }
365
+ .ui-icon-circle-plus { background-position: 0 -192px; }
366
+ .ui-icon-circle-minus { background-position: -16px -192px; }
367
+ .ui-icon-circle-close { background-position: -32px -192px; }
368
+ .ui-icon-circle-triangle-e { background-position: -48px -192px; }
369
+ .ui-icon-circle-triangle-s { background-position: -64px -192px; }
370
+ .ui-icon-circle-triangle-w { background-position: -80px -192px; }
371
+ .ui-icon-circle-triangle-n { background-position: -96px -192px; }
372
+ .ui-icon-circle-arrow-e { background-position: -112px -192px; }
373
+ .ui-icon-circle-arrow-s { background-position: -128px -192px; }
374
+ .ui-icon-circle-arrow-w { background-position: -144px -192px; }
375
+ .ui-icon-circle-arrow-n { background-position: -160px -192px; }
376
+ .ui-icon-circle-zoomin { background-position: -176px -192px; }
377
+ .ui-icon-circle-zoomout { background-position: -192px -192px; }
378
+ .ui-icon-circle-check { background-position: -208px -192px; }
379
+ .ui-icon-circlesmall-plus { background-position: 0 -208px; }
380
+ .ui-icon-circlesmall-minus { background-position: -16px -208px; }
381
+ .ui-icon-circlesmall-close { background-position: -32px -208px; }
382
+ .ui-icon-squaresmall-plus { background-position: -48px -208px; }
383
+ .ui-icon-squaresmall-minus { background-position: -64px -208px; }
384
+ .ui-icon-squaresmall-close { background-position: -80px -208px; }
385
+ .ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
386
+ .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
387
+ .ui-icon-grip-solid-vertical { background-position: -32px -224px; }
388
+ .ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
389
+ .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
390
+ .ui-icon-grip-diagonal-se { background-position: -80px -224px; }
391
+
392
+
393
+ /* Misc visuals
394
+ ----------------------------------*/
395
+
396
+ /* Corner radius */
397
+ .ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -khtml-border-top-left-radius: 4px; border-top-left-radius: 4px; }
398
+ .ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -khtml-border-top-right-radius: 4px; border-top-right-radius: 4px; }
399
+ .ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -khtml-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; }
400
+ .ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; -khtml-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
401
+
402
+
403
+ /* Overlays */
404
+ .ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
405
+ .ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/*
406
+ * jQuery UI Resizable 1.8.16
407
+ *
408
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
409
+ * Dual licensed under the MIT or GPL Version 2 licenses.
410
+ * http://jquery.org/license
411
+ *
412
+ * http://docs.jquery.com/UI/Resizable#theming
413
+ */
414
+ .ui-resizable { position: relative;}
415
+ .ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block; }
416
+ .ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
417
+ .ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
418
+ .ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
419
+ .ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
420
+ .ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
421
+ .ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
422
+ .ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
423
+ .ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
424
+ .ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/*
425
+ * jQuery UI Selectable 1.8.16
426
+ *
427
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
428
+ * Dual licensed under the MIT or GPL Version 2 licenses.
429
+ * http://jquery.org/license
430
+ *
431
+ * http://docs.jquery.com/UI/Selectable#theming
432
+ */
433
+ .ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
434
+ /*
435
+ * jQuery UI Accordion 1.9.0
436
+ *
437
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
438
+ * Dual licensed under the MIT or GPL Version 2 licenses.
439
+ * http://jquery.org/license
440
+ *
441
+ * http://docs.jquery.com/UI/Accordion#theming
442
+ */
443
+ /* IE/Win - Fix animation bug - #4615 */
444
+ .ui-accordion { width: 100%; }
445
+ .ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; font-weight:bold; }
446
+ .ui-accordion .ui-accordion-li-fix { display: inline; }
447
+ .ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
448
+ .ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em 1.7em; }
449
+ .ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
450
+ .ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
451
+ .ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
452
+ .ui-accordion .ui-accordion-content-active { display: block; }
453
+ /*
454
+ * jQuery UI Autocomplete 1.8.16
455
+ *
456
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
457
+ * Dual licensed under the MIT or GPL Version 2 licenses.
458
+ * http://jquery.org/license
459
+ *
460
+ * http://docs.jquery.com/UI/Autocomplete#theming
461
+ */
462
+ .ui-autocomplete {
463
+ position: absolute;
464
+ top: 0;
465
+ left: 0;
466
+ cursor: default;
467
+ }
468
+
469
+ /* workarounds */
470
+ * html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
471
+
472
+ /*
473
+ * jQuery UI Menu 1.9.0
474
+ *
475
+ * Copyright 2012-10-11, AUTHORS.txt (http://jqueryui.com/about)
476
+ * Dual licensed under the MIT or GPL Version 2 licenses.
477
+ * http://jquery.org/license
478
+ *
479
+ * http://docs.jquery.com/UI/Menu#theming
480
+ */
481
+
482
+ .ui-menu { list-style:none; padding: 2px; margin: 0; display:block; float:left; outline: none; }
483
+ .ui-menu .ui-menu { margin-top: -3px; position: absolute; }
484
+ .ui-menu .ui-menu-item { margin: 0; padding: 0; zoom: 1;float: left;clear: left; width: 100%; }
485
+ .ui-menu .ui-menu-divider { margin: 5px -2px 5px -2px; height: 0; font-size: 0; line-height: 0; border-width: 1px 0 0 0; }
486
+ .ui-menu .ui-menu-item a { text-decoration: none; display: block; padding: 2px .4em; line-height: 1.5; zoom: 1; font-weight: normal; }
487
+ .ui-menu .ui-menu-item a.ui-state-focus,
488
+ .ui-menu .ui-menu-item a.ui-state-active {
489
+ font-weight: normal;
490
+ margin: 0;
491
+ color: #ffffff;
492
+ background: #0064cd;
493
+ background-color: #0064cd;
494
+ background-repeat: repeat-x;
495
+ background-image: -khtml-gradient(linear, left top, left bottom, from(#049cdb), to(#0064cd));
496
+ background-image: -moz-linear-gradient(top, #049cdb, #0064cd);
497
+ background-image: -ms-linear-gradient(top, #049cdb, #0064cd);
498
+ background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #049cdb), color-stop(100%, #0064cd));
499
+ background-image: -webkit-linear-gradient(top, #049cdb, #0064cd);
500
+ background-image: -o-linear-gradient(top, #049cdb, #0064cd);
501
+ background-image: linear-gradient(top, #049cdb, #0064cd);
502
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#049cdb', endColorstr='#0064cd', GradientType=0);
503
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
504
+ border-color: #0064cd #0064cd #003f81;
505
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
506
+ }
507
+ /* Fix problem with border in ui-state-active */
508
+ .ui-menu .ui-menu-item a.ui-state-active {
509
+ padding: 1px .4em;
510
+ }
511
+
512
+ .ui-menu .ui-state-disabled { font-weight: normal; margin: .4em 0 .2em; line-height: 1.5; }
513
+ .ui-menu .ui-state-disabled a { cursor: default; }
514
+
515
+ /* icon support */
516
+ .ui-menu-icons { position: relative; }
517
+ .ui-menu-icons .ui-menu-item a { position: relative; padding-left: 2em; }
518
+
519
+ /* left-aligned */
520
+ .ui-menu .ui-icon { position: absolute; top: .2em; left: .2em; }
521
+
522
+ /* right-aligned */
523
+ .ui-menu .ui-menu-icon { position: static; float: right; }
524
+
525
+ .ui-menu { width: 200px; margin-bottom: 2em; }
526
+
527
+ /*
528
+ * jQuery UI Button 1.8.16
529
+ *
530
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
531
+ * Dual licensed under the MIT or GPL Version 2 licenses.
532
+ * http://jquery.org/license
533
+ *
534
+ * http://docs.jquery.com/UI/Button#theming
535
+ */
536
+ .ui-button {
537
+
538
+ cursor: pointer;
539
+ display: inline-block;
540
+ background-color: #e6e6e6;
541
+ background-repeat: no-repeat;
542
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), color-stop(25%, #ffffff), to(#e6e6e6));
543
+ background-image: -webkit-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);
544
+ background-image: -moz-linear-gradient(top, #ffffff, #ffffff 25%, #e6e6e6);
545
+ background-image: -ms-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);
546
+ background-image: -o-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);
547
+ background-image: linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);
548
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0);
549
+ padding: 5px 14px 6px;
550
+ margin: 0;
551
+ text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
552
+ color: #333;
553
+ font-size: 13px;
554
+ line-height: normal;
555
+ border: 1px solid #ccc;
556
+ border-bottom-color: #bbb;
557
+
558
+ -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
559
+ -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
560
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
561
+ -webkit-transition: 0.1s linear background-image;
562
+ -moz-transition: 0.1s linear background-image;
563
+ -ms-transition: 0.1s linear background-image;
564
+ -o-transition: 0.1s linear background-image;
565
+ transition: 0.1s linear background-image;
566
+ overflow: visible;
567
+
568
+ } /* the overflow property removes extra width in IE */
569
+
570
+ .ui-button-primary {
571
+ color: #ffffff;
572
+ background-color: #0064cd;
573
+ background-repeat: repeat-x;
574
+ background-image: -khtml-gradient(linear, left top, left bottom, from(#049cdb), to(#0064cd));
575
+ background-image: -moz-linear-gradient(top, #049cdb, #0064cd);
576
+ background-image: -ms-linear-gradient(top, #049cdb, #0064cd);
577
+ background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #049cdb), color-stop(100%, #0064cd));
578
+ background-image: -webkit-linear-gradient(top, #049cdb, #0064cd);
579
+ background-image: -o-linear-gradient(top, #049cdb, #0064cd);
580
+ background-image: linear-gradient(top, #049cdb, #0064cd);
581
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#049cdb', endColorstr='#0064cd', GradientType=0);
582
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
583
+ border-color: #0064cd #0064cd #003f81;
584
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
585
+
586
+ }
587
+
588
+
589
+
590
+ .ui-button-success{
591
+ color:#ffffff;
592
+ background-color: #57a957;
593
+ background-repeat: repeat-x;
594
+ background-image: -khtml-gradient(linear, left top, left bottom, from(#62c462), to(#57a957));
595
+ background-image: -moz-linear-gradient(top, #62c462, #57a957);
596
+ background-image: -ms-linear-gradient(top, #62c462, #57a957);
597
+ background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #62c462), color-stop(100%, #57a957));
598
+ background-image: -webkit-linear-gradient(top, #62c462, #57a957);
599
+ background-image: -o-linear-gradient(top, #62c462, #57a957);
600
+ background-image: linear-gradient(top, #62c462, #57a957);
601
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0);
602
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
603
+ border-color: #57a957 #57a957 #3d773d;
604
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
605
+ }
606
+
607
+ .ui-button-error{
608
+ color:#ffffff;
609
+ background-color: #c43c35;
610
+ background-repeat: repeat-x;
611
+ background-image: -khtml-gradient(linear, left top, left bottom, from(#ee5f5b), to(#c43c35));
612
+ background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);
613
+ background-image: -ms-linear-gradient(top, #ee5f5b, #c43c35);
614
+ background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ee5f5b), color-stop(100%, #c43c35));
615
+ background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);
616
+ background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);
617
+ background-image: linear-gradient(top, #ee5f5b, #c43c35);
618
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0);
619
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
620
+ border-color: #c43c35 #c43c35 #882a25;
621
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
622
+ }
623
+
624
+ .ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
625
+ button.ui-button-icon-only { } /* button elements seem to need a little more width */
626
+ .ui-button-icons-only { width: 3.4em; }
627
+ button.ui-button-icons-only { width: 3.7em; }
628
+
629
+ /*button text element */
630
+
631
+ .ui-button .ui-button-text { display: block; }
632
+ .ui-button-text-only .ui-button-text { }
633
+ .ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; /*tempfix*/ display:none;}
634
+ .ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
635
+ .ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
636
+ .ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
637
+ /* no icon support for input elements, provide padding by default */
638
+ /* input.ui-button { padding: .4em 1em; } */
639
+
640
+ /*button icon element(s) */
641
+ .ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { top: 50%; margin-top:-3px; margin-bottom:3px; }
642
+ .ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
643
+ .ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
644
+ .ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
645
+ .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
646
+
647
+ /*button sets*/
648
+
649
+
650
+ .ui-buttonset { margin-right: 7px; }
651
+ .ui-buttonset .ui-state-active {
652
+ color: #ffffff;
653
+ background-color: #0064cd;
654
+ background-repeat: repeat-x;
655
+ background-image: -khtml-gradient(linear, left top, left bottom, from(#049cdb), to(#0064cd));
656
+ background-image: -moz-linear-gradient(top, #049cdb, #0064cd);
657
+ background-image: -ms-linear-gradient(top, #049cdb, #0064cd);
658
+ background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #049cdb), color-stop(100%, #0064cd));
659
+ background-image: -webkit-linear-gradient(top, #049cdb, #0064cd);
660
+ background-image: -o-linear-gradient(top, #049cdb, #0064cd);
661
+ background-image: linear-gradient(top, #049cdb, #0064cd);
662
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#049cdb', endColorstr='#0064cd', GradientType=0);
663
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
664
+ border-color: #0064cd #0064cd #003f81;
665
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
666
+ }
667
+ .ui-buttonset .ui-button { margin-left: 0; margin-right: -.4em; }
668
+
669
+ /* workarounds */
670
+ button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
671
+
672
+ /*
673
+ * jQuery UI spinner 1.9.0
674
+ *
675
+ * Copyright 2012-10-11, AUTHORS.txt (http://jqueryui.com/about)
676
+ * Dual licensed under the MIT or GPL Version 2 licenses.
677
+ * http://jquery.org/license
678
+ *
679
+ * http://docs.jquery.com/UI/Menu#theming
680
+ */
681
+
682
+ .ui-spinner { position:relative; display: inline-block; overflow: hidden; padding: 0; vertical-align: middle; }
683
+ .ui-spinner-input { border: none; background: none; padding: 0; margin: .2em 0; vertical-align: middle; margin-left: .4em; margin-right: 22px; }
684
+ .ui-spinner{}
685
+ .ui-spinner-button { width: 16px; height: 50%; font-size: .5em; padding: 0; margin: 0; text-align: center; position: absolute; cursor: default; display: block; overflow: hidden; right: 0; }
686
+ .ui-spinner a.ui-spinner-button { border-top: none; border-bottom: none; border-right: none; } /* more specificity required here to overide default borders */
687
+ .ui-spinner .ui-icon { position: absolute; margin-top: -8px; top: 50%; left: 0; } /* vertical centre icon */
688
+ .ui-spinner-up { top: 0; }
689
+ .ui-spinner-down { bottom: 0; }
690
+
691
+ /* TR overrides */
692
+ .ui-spinner .ui-icon-triangle-1-s {
693
+ /* need to fix icons sprite */
694
+ background-position:-65px -16px;
695
+ }
696
+
697
+ /*
698
+ * jQuery UI Dialog 1.8.16
699
+ *
700
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
701
+ * Dual licensed under the MIT or GPL Version 2 licenses.
702
+ * http://jquery.org/license
703
+ *
704
+ * http://docs.jquery.com/UI/Dialog#theming
705
+ */
706
+ .ui-dialog { position: absolute; top: 0; left: 0; padding: .2em; width: 300px; overflow: hidden; outline: 0; }
707
+ .ui-dialog .ui-dialog-titlebar { /*padding: .4em 1em;*/
708
+
709
+ position: relative;
710
+ padding:5px 15px;
711
+
712
+ border:0px 0px 0px 1px solid;
713
+ border-color: white;
714
+ padding: 5px 15px;
715
+ font-size: 18px;
716
+ text-decoration:none;
717
+ background:none;
718
+ -moz-border-radius-bottomright: 0px;
719
+ -webkit-border-bottom-right-radius: 0px;
720
+ -khtml-border-bottom-right-radius: 0px;
721
+
722
+ -moz-border-radius-bottomleft: 0px;
723
+ -webkit-border-bottom-left-radius: 0px;
724
+ -khtml-border-bottom-left-radius: 0px;
725
+ border-bottom-left-radius: 0px;
726
+
727
+ border-bottom:1px solid #ccc;
728
+
729
+ }
730
+ .ui-dialog .ui-dialog-title {
731
+ float: left;
732
+ color:#404040;
733
+ font-weight:bold;
734
+ margin-top:5px;
735
+ margin-bottom:5px;
736
+ padding:5px;
737
+
738
+ }
739
+ .ui-dialog .ui-dialog-titlebar-close {
740
+ position: absolute;
741
+ right: .3em;
742
+ top: 50%;
743
+ width: 19px;
744
+ margin: -10px 0 0 0;
745
+ padding: 1px;
746
+ height: 18px;
747
+ font-size: 20px;
748
+ font-weight: bold;
749
+ line-height: 13.5px;
750
+ text-shadow: 0 1px 0 #ffffff;
751
+ filter: alpha(opacity=25);
752
+ -khtml-opacity: 0.25;
753
+ -moz-opacity: 0.25;
754
+ opacity: 0.25;
755
+ }
756
+
757
+ .ui-dialog .ui-dialog-titlebar-close span {
758
+ display: block;
759
+ margin: 1px;
760
+ text-indent: 9999px;
761
+ }
762
+
763
+ .ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 1px; filter: alpha(opacity=90);
764
+ -khtml-opacity: 0.90;
765
+ -moz-opacity: 0.90;
766
+ opacity: 0.90; }
767
+
768
+ .ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
769
+
770
+ .ui-dialog .ui-dialog-buttonpane {
771
+ text-align: left;
772
+ border-width: 1px 0 0 0;
773
+ background-image: none;
774
+ margin: .5em 0 0 0;
775
+ background-color: #f5f5f5;
776
+ padding: 5px 15px 5px;
777
+ border-top: 1px solid #ddd;
778
+ -webkit-border-radius: 0 0 6px 6px;
779
+ -moz-border-radius: 0 0 6px 6px;
780
+ border-radius: 0 0 6px 6px;
781
+ -webkit-box-shadow: inset 0 1px 0 #ffffff;
782
+ -moz-box-shadow: inset 0 1px 0 #ffffff;
783
+ box-shadow: inset 0 1px 0 #ffffff;
784
+ zoom: 1;
785
+ margin-bottom: 0;
786
+
787
+ }
788
+ .ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
789
+ .ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
790
+ .ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
791
+ .ui-draggable .ui-dialog-titlebar { cursor: move; }
792
+
793
+ .ui-dialog-buttonpane .ui-dialog-buttonset .ui-button{
794
+ color: #ffffff;
795
+ background-color: #0064cd;
796
+ background-repeat: repeat-x;
797
+ background-image: -khtml-gradient(linear, left top, left bottom, from(#049cdb), to(#0064cd));
798
+ background-image: -moz-linear-gradient(top, #049cdb, #0064cd);
799
+ background-image: -ms-linear-gradient(top, #049cdb, #0064cd);
800
+ background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #049cdb), color-stop(100%, #0064cd));
801
+ background-image: -webkit-linear-gradient(top, #049cdb, #0064cd);
802
+ background-image: -o-linear-gradient(top, #049cdb, #0064cd);
803
+ background-image: linear-gradient(top, #049cdb, #0064cd);
804
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#049cdb', endColorstr='#0064cd', GradientType=0);
805
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
806
+ border-color: #0064cd #0064cd #003f81;
807
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
808
+ }
809
+ /*
810
+ * jQuery UI Slider 1.8.16
811
+ *
812
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
813
+ * Dual licensed under the MIT or GPL Version 2 licenses.
814
+ * http://jquery.org/license
815
+ *
816
+ * http://docs.jquery.com/UI/Slider#theming
817
+ */
818
+ .ui-slider { position: relative; text-align: left; }
819
+ .ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
820
+ .ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0;
821
+
822
+ color: #ffffff;
823
+ background-color: #0064cd;
824
+ background-repeat: repeat-x;
825
+ background-image: -khtml-gradient(linear, left top, left bottom, from(#049cdb), to(#0064cd));
826
+ background-image: -moz-linear-gradient(top, #049cdb, #0064cd);
827
+ background-image: -ms-linear-gradient(top, #049cdb, #0064cd);
828
+ background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #049cdb), color-stop(100%, #0064cd));
829
+ background-image: -webkit-linear-gradient(top, #049cdb, #0064cd);
830
+ background-image: -o-linear-gradient(top, #049cdb, #0064cd);
831
+ background-image: linear-gradient(top, #049cdb, #0064cd);
832
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#049cdb', endColorstr='#0064cd', GradientType=0);
833
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
834
+ border-color: #0064cd #0064cd #003f81;
835
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
836
+
837
+ }
838
+
839
+ .ui-slider-horizontal { height: .8em; }
840
+ .ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
841
+ .ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
842
+ .ui-slider-horizontal .ui-slider-range-min { left: 0; }
843
+ .ui-slider-horizontal .ui-slider-range-max { right: 0; }
844
+
845
+ .ui-slider-vertical { width: .8em; height: 100px; }
846
+ .ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
847
+ .ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
848
+ .ui-slider-vertical .ui-slider-range-min { bottom: 0; }
849
+ .ui-slider-vertical .ui-slider-range-max { top: 0; }
850
+
851
+ /*
852
+ * jQuery UI Tabs 1.9.2
853
+ *
854
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
855
+ * Dual licensed under the MIT or GPL Version 2 licenses.
856
+ * http://jquery.org/license
857
+ *
858
+ * http://jqueryui.com/tabs/
859
+ */
860
+ .ui-tabs .ui-tabs-nav{ background:none; border-color: #ddd;border-style: solid;border-width: 0 0 1px;}
861
+ .ui-tabs { position: relative; padding: .2em; zoom: 1; border:0px;} /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
862
+
863
+
864
+ .ui-tabs .ui-tabs-nav li:hover, .ui-tabs .ui-tabs-nav li a:hover{
865
+ background:whiteSmoke;
866
+ border-bottom:1px solid #ddd;
867
+ padding-bottom:0px;
868
+ color:#00438A;
869
+ }
870
+
871
+ .ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; border-bottom:1px solid #DDD; }
872
+ .ui-tabs .ui-tabs-nav li { text-decoration: none; list-style: none; float: left; position: relative; top: 1px; padding: 0px 0px 1px 0px; white-space: nowrap; background:none; border:0px; }
873
+
874
+ .ui-tabs-nav .ui-state-default{
875
+ -webkit-box-shadow: 0px 0px 0px #ffffff; /* Saf3-4, iOS 4.0.2 - 4.2, Android 2.3+ */
876
+ -moz-box-shadow: 0px 0px 0px #ffffff; /* FF3.5 - 3.6 */
877
+ box-shadow: 0px 0px 0px #ffffff; /* Opera 10.5, IE9, FF4+, Chrome 6+, iOS 5 */
878
+ }
879
+ .ui-tabs .ui-tabs-nav li a {
880
+ float: left;
881
+ text-decoration: none;
882
+ cursor: text;
883
+ padding: 0 15px;
884
+ margin-right: 2px;
885
+ line-height: 34px;
886
+ border: 1px solid transparent;
887
+ -webkit-border-radius: 4px 4px 0 0;
888
+ -moz-border-radius: 4px 4px 0 0;
889
+ border-radius: 4px 4px 0 0;
890
+
891
+
892
+ }
893
+
894
+ .ui-tabs .ui-tabs-nav li.ui-tabs-active { margin-bottom: 0; padding-bottom: 0px; outline:none;}
895
+ .ui-tabs .ui-tabs-nav li.ui-tabs-active , .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a {
896
+ background-color: #ffffff;
897
+ border: 1px solid #ddd;
898
+ border-bottom-color: #ffffff;
899
+ cursor: default;
900
+ color:gray;
901
+ outline:none;
902
+ }
903
+ .ui-tabs .ui-tabs-nav li.ui-tabs-active a{background-color: #ffffff;outline:none;border:none;}
904
+ .ui-tabs .ui-tabs-nav li.ui-tabs-active:hover{
905
+ background:#ffffff;
906
+ outline:none;
907
+ margin-bottom:0px;
908
+ }
909
+ .ui-tabs .ui-tabs-nav li.ui-tabs-active a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-tabs-loading a { cursor: text; }
910
+ .ui-tabs .ui-tabs-nav li a, .ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a { cursor: pointer; color:#0069D6; background:none; font-weight:normal; margin-bottom:-1px;}
911
+ /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
912
+ .ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
913
+ .ui-tabs-panel .ui-button{text-decoration:none;}
914
+ .ui-tabs .ui-tabs-hide { display: none !important; }
915
+
916
+
917
+ /* IE fix for background inheritance from ui-widget*/
918
+ .ui-tabs .ui-tabs-nav li{
919
+ filter:none;
920
+ }
921
+
922
+ /*
923
+ * jQuery UI Tooltip 1.9.0
924
+ *
925
+ * Copyright 2012-10-11, AUTHORS.txt (http://jqueryui.com/about)
926
+ * Dual licensed under the MIT or GPL Version 2 licenses.
927
+ * http://jquery.org/license
928
+ *
929
+ * http://jqueryui.com/tooltip/
930
+ */
931
+ .ui-tooltip {
932
+ padding:8px;
933
+ position:absolute;
934
+ z-index:9999;
935
+ max-width: 300px;
936
+ -o-box-shadow: 0 0 5px #ddd;
937
+ -moz-box-shadow: 0 0 5px #ddd;
938
+ -webkit-box-shadow: 0 0 5px #ddd;
939
+ /*box-shadow: 0 2px 5px #ddd;*/
940
+ box-shadow: inset 0 1px 0 #ffffff;
941
+ }
942
+ /* Fades and background-images don't work well together in IE6, drop the image */
943
+ * html .ui-tooltip {
944
+ background-image: none;
945
+ }
946
+ body .ui-tooltip { border-width:2px; }
947
+
948
+ /*
949
+ * jQuery UI Datepicker 1.9.0
950
+ *
951
+ * Copyright 2012-10-11, AUTHORS.txt (http://jqueryui.com/about)
952
+ * Dual licensed under the MIT or GPL Version 2 licenses.
953
+ * http://jquery.org/license
954
+ *
955
+ * http://jqueryui.com/datepicker/
956
+ */
957
+ .ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
958
+ .ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; border:0px; font-weight: bold; width: 100%; padding: 4px 0; background-color: #f5f5f5; color: #808080; }
959
+ .ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
960
+
961
+ .ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { /*top: 1px;*/ }
962
+ .ui-datepicker .ui-datepicker-prev { left:2px; }
963
+ .ui-datepicker .ui-datepicker-next { right:2px; }
964
+
965
+ .ui-datepicker .ui-datepicker-prev-hover { /*left:1px;*/ }
966
+ .ui-datepicker .ui-datepicker-next-hover { /*right:1px;*/ }
967
+
968
+ .ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
969
+ .ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
970
+ .ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
971
+ .ui-datepicker select.ui-datepicker-month-year {width: 100%;}
972
+ .ui-datepicker select.ui-datepicker-month,
973
+ .ui-datepicker select.ui-datepicker-year { width: 49%;}
974
+ .ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
975
+ .ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
976
+ .ui-datepicker td { border: 0; padding: 1px; }
977
+ .ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
978
+ .ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
979
+ .ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
980
+ .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
981
+
982
+ /* with multiple calendars */
983
+ .ui-datepicker.ui-datepicker-multi { width:auto; }
984
+ .ui-datepicker-multi .ui-datepicker-group { float:left; }
985
+ .ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
986
+ .ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
987
+ .ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
988
+ .ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
989
+ .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
990
+ .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
991
+ .ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
992
+ .ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }
993
+
994
+ /* RTL support */
995
+ .ui-datepicker-rtl { direction: rtl; }
996
+ .ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
997
+ .ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
998
+ .ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
999
+ .ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
1000
+ .ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
1001
+ .ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
1002
+ .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
1003
+ .ui-datepicker-rtl .ui-datepicker-group { float:right; }
1004
+ .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
1005
+ .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
1006
+
1007
+ /* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
1008
+ .ui-datepicker-cover {
1009
+ display: none; /*sorry for IE5*/
1010
+ display/**/: block; /*sorry for IE5*/
1011
+ position: absolute; /*must have*/
1012
+ z-index: -1; /*must have*/
1013
+ filter: mask(); /*must have*/
1014
+ top: -4px; /*must have*/
1015
+ left: -4px; /*must have*/
1016
+ width: 200px; /*must have*/
1017
+ height: 200px; /*must have*/
1018
+ }
1019
+
1020
+ .ui-datepicker th{
1021
+ font-weight: bold;
1022
+ color: gray;
1023
+ }
1024
+
1025
+ .ui-datepicker-today a:hover{
1026
+ background-color: #808080;
1027
+ color: #ffffff;
1028
+
1029
+ }
1030
+ .ui-datepicker-today a{
1031
+ background-color: #BFBFBF;
1032
+ cursor: pointer;
1033
+ padding: 0 4px;
1034
+ margin-bottom:0px;
1035
+
1036
+ }
1037
+
1038
+
1039
+ .ui-datepicker td a{
1040
+ margin-bottom:0px;
1041
+ border:0px;
1042
+ }
1043
+
1044
+ .ui-datepicker td:hover{
1045
+ color: #ffffff;
1046
+ }
1047
+
1048
+ .ui-datepicker td .ui-state-default {
1049
+ border:0px;
1050
+ background:none;
1051
+ margin-bottom:0px;
1052
+ padding:5px;
1053
+ color:gray;
1054
+ text-align: center;
1055
+ filter:none;
1056
+ }
1057
+
1058
+
1059
+ .ui-datepicker td .ui-state-active{
1060
+ background:#BFBFBF;
1061
+ margin-bottom:0px;
1062
+ font-size:normal;
1063
+ text-shadow: 0px;
1064
+ color: #ffffff;
1065
+ -webkit-border-radius: 4px;
1066
+ -moz-border-radius: 4px;
1067
+ border-radius: 4px;
1068
+ }
1069
+
1070
+ .ui-datepicker td .ui-state-hover {
1071
+ color: #ffffff;
1072
+ background: #0064cd;
1073
+ background-color: #0064cd;
1074
+ background-repeat: repeat-x;
1075
+ background-image: -khtml-gradient(linear, left top, left bottom, from(#049cdb), to(#0064cd));
1076
+ background-image: -moz-linear-gradient(top, #049cdb, #0064cd);
1077
+ background-image: -ms-linear-gradient(top, #049cdb, #0064cd);
1078
+ background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #049cdb), color-stop(100%, #0064cd));
1079
+ background-image: -webkit-linear-gradient(top, #049cdb, #0064cd);
1080
+ background-image: -o-linear-gradient(top, #049cdb, #0064cd);
1081
+ background-image: linear-gradient(top, #049cdb, #0064cd);
1082
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#049cdb', endColorstr='#0064cd', GradientType=0);
1083
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
1084
+ border-color: #0064cd #0064cd #003f81;
1085
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
1086
+ -webkit-border-radius: 4px;
1087
+ -moz-border-radius: 4px;
1088
+ -khtml-border-radius: 4px;
1089
+ border-radius: 4px;
1090
+ }
1091
+
1092
+ /*
1093
+ * jQuery UI Progressbar 1.8.16
1094
+ *
1095
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
1096
+ * Dual licensed under the MIT or GPL Version 2 licenses.
1097
+ * http://jquery.org/license
1098
+ *
1099
+ * http://docs.jquery.com/UI/Progressbar#theming
1100
+ */
1101
+ .ui-progressbar { height:2em; text-align: left; }
1102
+ .ui-progressbar .ui-progressbar-value {margin: -1px; height:100%;
1103
+
1104
+ /*this can be removed if ui-widget-header is blue*/
1105
+ color: #ffffff;
1106
+ background-color: #0064cd;
1107
+ background-repeat: repeat-x;
1108
+ background-image: -khtml-gradient(linear, left top, left bottom, from(#049cdb), to(#0064cd));
1109
+ background-image: -moz-linear-gradient(top, #049cdb, #0064cd);
1110
+ background-image: -ms-linear-gradient(top, #049cdb, #0064cd);
1111
+ background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #049cdb), color-stop(100%, #0064cd));
1112
+ background-image: -webkit-linear-gradient(top, #049cdb, #0064cd);
1113
+ background-image: -o-linear-gradient(top, #049cdb, #0064cd);
1114
+ background-image: linear-gradient(top, #049cdb, #0064cd);
1115
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#049cdb', endColorstr='#0064cd', GradientType=0);
1116
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
1117
+ border-color: #0064cd #0064cd #003f81;
1118
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
1119
+ }
1120
+
1121
+
1122
+
1123
+ /*** Input field styling from Bootstrap **/
1124
+ input, textarea {
1125
+ -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;
1126
+ -moz-transition: border linear 0.2s, box-shadow linear 0.2s;
1127
+ -ms-transition: border linear 0.2s, box-shadow linear 0.2s;
1128
+ -o-transition: border linear 0.2s, box-shadow linear 0.2s;
1129
+ transition: border linear 0.2s, box-shadow linear 0.2s;
1130
+ -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
1131
+ -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
1132
+ box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
1133
+ }
1134
+ input:focus, textarea:focus {
1135
+ outline: 0;
1136
+ border-color: rgba(82, 168, 236, 0.8);
1137
+ -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6);
1138
+ -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6);
1139
+ box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6);
1140
+ }
1141
+ input[type=file]:focus, input[type=checkbox]:focus, select:focus {
1142
+ -webkit-box-shadow: none;
1143
+ -moz-box-shadow: none;
1144
+ box-shadow: none;
1145
+ outline: 1px dotted #666;
1146
+ }
1147
+
1148
+ input[type="text"],
1149
+ input[type="password"],
1150
+ .ui-autocomplete-input,
1151
+ textarea,
1152
+ .uneditable-input {
1153
+ display: inline-block;
1154
+ padding: 4px;
1155
+ font-size: 13px;
1156
+ line-height: 18px;
1157
+ color: #808080;
1158
+ border: 1px solid #ccc;
1159
+ -webkit-border-radius: 3px;
1160
+ -moz-border-radius: 3px;
1161
+ border-radius: 3px;
1162
+ }
1163
+
1164
+
1165
+
1166
+ /**Toolbar**/
1167
+
1168
+ .ui-toolbar{
1169
+ padding: 7px 14px;
1170
+ margin: 0 0 18px;
1171
+ background-color: #f5f5f5;
1172
+ background-repeat: repeat-x;
1173
+ background-image: -khtml-gradient(linear, left top, left bottom, from(#ffffff), to(#f5f5f5));
1174
+ background-image: -moz-linear-gradient(top, #ffffff, #f5f5f5);
1175
+ background-image: -ms-linear-gradient(top, #ffffff, #f5f5f5);
1176
+ background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ffffff), color-stop(100%, #f5f5f5));
1177
+ background-image: -webkit-linear-gradient(top, #ffffff, #f5f5f5);
1178
+ background-image: -o-linear-gradient(top, #ffffff, #f5f5f5);
1179
+ background-image: linear-gradient(top, #ffffff, #f5f5f5);
1180
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f5f5f5', GradientType=0);
1181
+ border: 1px solid #ddd;
1182
+ -webkit-border-radius: 3px;
1183
+ -moz-border-radius: 3px;
1184
+ border-radius: 3px;
1185
+ -webkit-box-shadow: inset 0 1px 0 #ffffff;
1186
+ -moz-box-shadow: inset 0 1px 0 #ffffff;
1187
+ box-shadow: inset 0 1px 0 #ffffff;
1188
+ }
1189
+
1190
+
1191
+ /***Dialog fixes**/
1192
+
1193
+ .ui-dialog-buttonset .ui-button:nth-child(2){
1194
+ cursor: pointer;
1195
+ display: inline-block;
1196
+ background-color: #e6e6e6;
1197
+ background-repeat: no-repeat;
1198
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), color-stop(25%, #ffffff), to(#e6e6e6));
1199
+ background-image: -webkit-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);
1200
+ background-image: -moz-linear-gradient(top, #ffffff, #ffffff 25%, #e6e6e6);
1201
+ background-image: -ms-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);
1202
+ background-image: -o-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);
1203
+ background-image: linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);
1204
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0);
1205
+ padding: 5px 14px 6px;
1206
+ text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
1207
+ color: #333;
1208
+ font-size: 13px;
1209
+ line-height: normal;
1210
+ border: 1px solid #ccc;
1211
+ border-bottom-color: #bbb;
1212
+ -webkit-border-radius: 4px;
1213
+ -moz-border-radius: 4px;
1214
+ border-radius: 4px;
1215
+ -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
1216
+ -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
1217
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
1218
+ -webkit-transition: 0.1s linear all;
1219
+ -moz-transition: 0.1s linear all;
1220
+ -ms-transition: 0.1s linear all;
1221
+ -o-transition: 0.1s linear all;
1222
+ transition: 0.1s linear all;
1223
+ overflow: visible;
1224
+ }
1225
+
1226
+
1227
+
1228
+ /***Wijmo Theming**/
1229
+
1230
+ div.wijmo-wijmenu{
1231
+ padding:0 20px;
1232
+ background-color: #222;
1233
+ background-color: #222222;
1234
+ background-repeat: repeat-x;
1235
+ background-image: -khtml-gradient(linear, left top, left bottom, from(#333333), to(#222222));
1236
+ background-image: -moz-linear-gradient(top, #333333, #222222);
1237
+ background-image: -ms-linear-gradient(top, #333333, #222222);
1238
+ background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #333333), color-stop(100%, #222222));
1239
+ background-image: -webkit-linear-gradient(top, #333333, #222222);
1240
+ background-image: -o-linear-gradient(top, #333333, #222222);
1241
+ background-image: linear-gradient(top, #333333, #222222);
1242
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0);
1243
+ -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1);
1244
+ -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1);
1245
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1);
1246
+ }
1247
+
1248
+ .wijmo-wijmenu .ui-state-default{
1249
+ box-shadow: none;
1250
+ color:#BFBFBF;
1251
+ }
1252
+
1253
+ .wijmo-wijmenu .ui-state-default .wijmo-wijmenu-text{
1254
+ color:#BFBFBF;
1255
+ }
1256
+
1257
+ .wijmo-wijmenu .ui-state-hover{
1258
+ background: #444;
1259
+ background: rgba(255, 255, 255, 0.05);
1260
+ }
1261
+
1262
+ .wijmo-wijmenu .ui-state-hover .wijmo-wijmenu-text{
1263
+ color:#ffffff;
1264
+ }
1265
+
1266
+ div.wijmo-wijmenu .ui-widget-header h3{
1267
+ position: relative;
1268
+ margin-top:1px;
1269
+ padding:0;
1270
+ }
1271
+
1272
+ .wijmo-wijmenu h3 a{
1273
+ color: #FFFFFF;
1274
+ display: block;
1275
+ float: left;
1276
+ font-size: 20px;
1277
+ font-weight: 200;
1278
+ line-height: 1;
1279
+ margin-left: -20px;
1280
+ margin-top:1px;
1281
+ padding: 8px 20px 12px;
1282
+ }
1283
+
1284
+ .wijmo-wijmenu h3 a:hover{
1285
+ background-color: rgba(255, 255, 255, 0.05);
1286
+ color: #FFFFFF;
1287
+ text-decoration: none;
1288
+ }
1289
+
1290
+ .wijmo-wijmenu .ui-widget-header{
1291
+ border:0px;
1292
+ }
1293
+
1294
+ .wijmo-wijmenu .wijmo-wijmenu-parent .wijmo-wijmenu-child{
1295
+ padding: 0.3em 0;
1296
+ }
1297
+
1298
+ div.wijmo-wijmenu .wijmo-wijmenu-item .wijmo-wijmenu-child{
1299
+ background: #333;
1300
+ border:0;
1301
+ margin:0;
1302
+ padding: 6px 0;
1303
+ width:160px;
1304
+ -webkit-border-radius: 0 0 6px 6px;
1305
+ -moz-border-radius: 0 0 6px 6px;
1306
+ border-radius: 0 0 6px 6px;
1307
+ -webkit-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
1308
+ -moz-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
1309
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
1310
+ }
1311
+
1312
+ div.wijmo-wijmenu .wijmo-wijmenu-item{
1313
+ margin:0;
1314
+ border:0;
1315
+ }
1316
+
1317
+ .wijmo-wijmenu a.wijmo-wijmenu-link{
1318
+ margin:0;
1319
+ line-height: 19px;
1320
+ padding: 10px 10px 11px;
1321
+ border:0;
1322
+ -webkit-border-radius: 0;
1323
+ -moz-border-radius: 0;
1324
+ border-radius:0;
1325
+ }
1326
+
1327
+ div.wijmo-wijmenu .wijmo-wijmenu-child .wijmo-wijmenu-link{
1328
+ display:block;
1329
+ float:none;
1330
+ padding: 4px 15px;
1331
+ width:auto;
1332
+ }
1333
+
1334
+ div.wijmo-wijmenu .wijmo-wijmenu-child .wijmo-wijmenu-text
1335
+ {
1336
+ float:none;
1337
+ }
1338
+
1339
+ .wijmo-wijmenu .wijmo-wijmenu-item .wijmo-wijmenu-child .ui-state-hover {
1340
+ background: #191919;
1341
+ }
1342
+
1343
+ .wijmo-wijmenu .wijmo-wijmenu-item .wijmo-wijmenu-separator{
1344
+ padding: 5px 0;
1345
+ background-image: none;
1346
+ background-color: #222;
1347
+ border-top: 1px solid #444;
1348
+ border-bottom:0;
1349
+ border-left:0;
1350
+ border-right:0;
1351
+ }
1352
+
1353
+ .wijmo-wijmenu .wijmo-wijmenu-item input {
1354
+ -moz-transition: none 0s ease 0s;
1355
+ background-color: rgba(255, 255, 255, 0.3);
1356
+ border: 1px solid #111111;
1357
+ border-radius: 4px 4px 4px 4px;
1358
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1) inset, 0 1px 0 rgba(255, 255, 255, 0.25);
1359
+ color: rgba(255, 255, 255, 0.75);
1360
+ font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
1361
+ line-height: 1;
1362
+ margin: 5px 10px 0 10px;
1363
+ padding: 4px 9px;
1364
+ width:100px;
1365
+ }
1366
+
1367
+ .wijmo-wijmenu .wijmo-wijmenu-item input:hover {
1368
+ background-color: rgba(255, 255, 255, 0.5);
1369
+ color: #FFFFFF;
1370
+ }
1371
+
1372
+ .wijmo-wijmenu .wijmo-wijmenu-item input:focus {
1373
+ background-color: #FFFFFF;
1374
+ border: 0 none;
1375
+ box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
1376
+ color: #404040;
1377
+ outline: 0 none;
1378
+ padding: 5px 10px;
1379
+ text-shadow: 0 1px 0 #FFFFFF;
1380
+ }
1381
+
1382
+
1383
+ .wijmo-wijmenu .ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default {
1384
+ text-shadow:none;
1385
+ }
1386
+
1387
+
1388
+ .wijmo-wijmenu .ui-state-default{
1389
+ box-shadow: none;
1390
+ color:#BFBFBF;
1391
+ filter: none;
1392
+ }
1393
+
functions/admin-page-class/images/add.png ADDED
Binary file
functions/admin-page-class/images/ajax-loader.gif ADDED
Binary file
functions/admin-page-class/images/delete-16.png ADDED
Binary file
functions/admin-page-class/images/edit.png ADDED
Binary file
functions/admin-page-class/images/remove.png ADDED
Binary file
functions/admin-page-class/js/Admin_Page_Class.js ADDED
@@ -0,0 +1,1056 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Aadmin pages class
3
+ *
4
+ * JS used for the admin pages class and other form items.
5
+ *
6
+ * Copyright 2011 Ohad Raz (admin@bainternet.info)
7
+ * @since 1.0
8
+ */
9
+
10
+ var $ =jQuery.noConflict();
11
+ //code editor
12
+ var Ed_array = Array;
13
+ //upload button
14
+ var formfield1;
15
+ var formfield2;
16
+ var file_frame;
17
+
18
+ availableOptions = {
19
+ flatFresh: {
20
+ fullColor : 'Full Color',
21
+ lightGray : 'Light Gray',
22
+ mediumGray : 'Medium Gray',
23
+ darkGray : 'Dark Gray',
24
+ lgOutlines : 'Light Gray Outlines',
25
+ mdOutlines : 'Medium Gray Outlines',
26
+ dgOutlines : 'Dark Gray Outlines',
27
+ colorOutlines : 'Color Outlines',
28
+ customColor : 'Custom Color',
29
+ ccOutlines : 'Custom Color Outlines'
30
+ },
31
+ leaf: {
32
+ fullColor : 'Full Color',
33
+ lightGray : 'Light Gray',
34
+ mediumGray : 'Medium Gray',
35
+ darkGray : 'Dark Gray',
36
+ lgOutlines : 'Light Gray Outlines',
37
+ mdOutlines : 'Medium Gray Outlines',
38
+ dgOutlines : 'Dark Gray Outlines',
39
+ colorOutlines : 'Color Outlines',
40
+ customColor : 'Custom Color',
41
+ ccOutlines : 'Custom Color Outlines'
42
+ },
43
+ pill: {
44
+ fullColor : 'Full Color',
45
+ lightGray : 'Light Gray',
46
+ mediumGray : 'Medium Gray',
47
+ darkGray : 'Dark Gray',
48
+ lgOutlines : 'Light Gray Outlines',
49
+ mdOutlines : 'Medium Gray Outlines',
50
+ dgOutlines : 'Dark Gray Outlines',
51
+ colorOutlines : 'Color Outlines',
52
+ customColor : 'Custom Color',
53
+ ccOutlines : 'Custom Color Outlines'
54
+ },
55
+ threeDee: {
56
+ fullColor : 'Full Color',
57
+ lightGray : 'Light Gray',
58
+ mediumGray : 'Medium Gray',
59
+ darkGray : 'Dark Gray'
60
+ },
61
+ connected: {
62
+ fullColor : 'Full Color',
63
+ lightGray : 'Light Gray',
64
+ mediumGray : 'Medium Gray',
65
+ darkGray : 'Dark Gray',
66
+ lgOutlines : 'Light Gray Outlines',
67
+ mdOutlines : 'Medium Gray Outlines',
68
+ dgOutlines : 'Dark Gray Outlines',
69
+ colorOutlines : 'Color Outlines',
70
+ customColor : 'Custom Color',
71
+ ccOutlines : 'Custom Color Outlines'
72
+ },
73
+ shift: {
74
+ fullColor : 'Full Color',
75
+ lightGray : 'Light Gray',
76
+ mediumGray : 'Medium Gray',
77
+ darkGray : 'Dark Gray',
78
+ lgOutlines : 'Light Gray Outlines',
79
+ mdOutlines : 'Medium Gray Outlines',
80
+ dgOutlines : 'Dark Gray Outlines',
81
+ colorOutlines : 'Color Outlines',
82
+ customColor : 'Custom Color',
83
+ ccOutlines : 'Custom Color Outlines'
84
+ }
85
+ };
86
+
87
+ // Check if we are on the admin page
88
+ if(jQuery('select[name="visualTheme"]').length) {
89
+
90
+ // Update the items and previews on the initial page load
91
+ var visualTheme = jQuery('select[name="visualTheme"]').val();
92
+ var dColorSet = jQuery('select[name="dColorSet"]').val();
93
+ var iColorSet = jQuery('select[name="iColorSet"]').val();
94
+ var oColorSet = jQuery('select[name="oColorSet"]').val();
95
+ jQuery('select[name="dColorSet"] option, select[name="iColorSet"] option, select[name="oColorSet"] option').remove();
96
+ jQuery.each(availableOptions[visualTheme], function(index, value) {
97
+ if(index == dColorSet) {
98
+ jQuery('select[name="dColorSet"]').append('<option value="'+index+'" selected>'+value+'</option>');
99
+ } else {
100
+ jQuery('select[name="dColorSet"]').append('<option value="'+index+'">'+value+'</option>');
101
+ };
102
+ if(index == iColorSet) {
103
+ jQuery('select[name="iColorSet"]').append('<option value="'+index+'" selected>'+value+'</option>');
104
+ } else {
105
+ jQuery('select[name="iColorSet"]').append('<option value="'+index+'">'+value+'</option>');
106
+ };
107
+ if(index == oColorSet) {
108
+ jQuery('select[name="oColorSet"]').append('<option value="'+index+'" selected>'+value+'</option>');
109
+ } else {
110
+ jQuery('select[name="oColorSet"]').append('<option value="'+index+'">'+value+'</option>');
111
+ };
112
+
113
+
114
+ if(dColorSet == 'customColor' || dColorSet == 'ccOutlines' || iColorSet == 'customColor' || iColorSet == 'ccOutlines' || oColorSet == 'customColor' || oColorSet == 'ccOutlines' ) {
115
+ jQuery('h3.customColorLabel').parents('.sw_field').show();
116
+ jQuery('h3.customColorLabel').parents('.sw_field').next('.form-table').show();
117
+
118
+ updateCustomColor();
119
+
120
+ } else {
121
+ jQuery('h3.customColorLabel').parents('.sw_field').hide();
122
+ jQuery('h3.customColorLabel').parents('.sw_field').next('.form-table').hide();
123
+ };
124
+ });
125
+
126
+ // A function for updating the preview
127
+ function updateTheme() {
128
+ var visualTheme = jQuery('select[name="visualTheme"]').val();
129
+ var dColorSet = jQuery('select[name="dColorSet"]').val();
130
+ var iColorSet = jQuery('select[name="iColorSet"]').val();
131
+ var oColorSet = jQuery('select[name="oColorSet"]').val();
132
+ var buttonsClass = 'sw_'+visualTheme+' sw_d_'+dColorSet+' sw_i_'+iColorSet+' sw_o_'+oColorSet;
133
+ if(typeof lastClass === 'undefined'){
134
+ jQuery('.nc_socialPanel').removeClass('sw_flatFresh sw_d_fullColor sw_i_fullColor sw_o_fullColor').addClass(buttonsClass);
135
+ } else {
136
+ jQuery('.nc_socialPanel').removeClass(lastClass).addClass(buttonsClass);
137
+ };
138
+ lastClass = buttonsClass;
139
+ if(dColorSet == 'customColor' || dColorSet == 'ccOutlines' || iColorSet == 'customColor' || iColorSet == 'ccOutlines' || oColorSet == 'customColor' || oColorSet == 'ccOutlines' ) {
140
+ jQuery('h3.customColorLabel').parents('.sw_field').slideDown();
141
+ jQuery('h3.customColorLabel').parents('.sw_field').next('.form-table').slideDown();
142
+
143
+ updateCustomColor();
144
+
145
+
146
+ } else {
147
+ jQuery('h3.customColorLabel').parents('.sw_field').slideUp();
148
+ jQuery('h3.customColorLabel').parents('.sw_field').next('.form-table').slideUp();
149
+ };
150
+ };
151
+ setTimeout( updateTheme , 2000 );
152
+
153
+ // If the color set changes, update the preview with the function
154
+ jQuery('select[name="dColorSet"], select[name="iColorSet"], select[name="oColorSet"]').on('change', updateTheme);
155
+
156
+ // If the visual theme is updated, update the preview manually
157
+ jQuery('select[name="visualTheme"]').on('change', function() {
158
+
159
+ var visualTheme = jQuery('select[name="visualTheme"]').val();
160
+ var dColorSet = jQuery('select[name="dColorSet"]').val();
161
+ var iColorSet = jQuery('select[name="iColorSet"]').val();
162
+ var oColorSet = jQuery('select[name="oColorSet"]').val();
163
+
164
+ var i = 0;
165
+ var array = availableOptions[visualTheme];
166
+
167
+ var dColor = array.hasOwnProperty(dColorSet);
168
+ var iColor = array.hasOwnProperty(iColorSet);
169
+ var oColor = array.hasOwnProperty(oColorSet);
170
+
171
+ jQuery('select[name="dColorSet"] option, select[name="iColorSet"] option, select[name="oColorSet"] option').remove();
172
+ jQuery.each(availableOptions[visualTheme], function(index, value) {
173
+ if(index == dColorSet || (dColor == false && i == 0)) {
174
+ jQuery('select[name="dColorSet"]').append('<option value="'+index+'" selected>'+value+'</option>');
175
+ } else {
176
+ jQuery('select[name="dColorSet"]').append('<option value="'+index+'">'+value+'</option>');
177
+ };
178
+ if(index == iColorSet || (iColor == false && i == 0)) {
179
+ jQuery('select[name="iColorSet"]').append('<option value="'+index+'" selected>'+value+'</option>');
180
+ } else {
181
+ jQuery('select[name="iColorSet"]').append('<option value="'+index+'">'+value+'</option>');
182
+ };
183
+ if(index == oColorSet || (oColor == false && i == 0)) {
184
+ jQuery('select[name="oColorSet"]').append('<option value="'+index+'" selected>'+value+'</option>');
185
+ } else {
186
+ jQuery('select[name="oColorSet"]').append('<option value="'+index+'">'+value+'</option>');
187
+ };
188
+ ++i;
189
+ });
190
+
191
+ var buttonsClass = 'sw_'+visualTheme+' sw_d_'+dColorSet+' sw_i_'+iColorSet+' sw_o_'+oColorSet;
192
+ if(typeof lastClass === 'undefined'){
193
+ jQuery('.nc_socialPanel').removeClass('sw_flatFresh sw_d_fullColor sw_i_fullColor sw_o_fullColor').addClass(buttonsClass);
194
+ } else {
195
+ jQuery('.nc_socialPanel').removeClass(lastClass).addClass(buttonsClass);
196
+ };
197
+ lastClass = buttonsClass;
198
+ });
199
+ }
200
+
201
+
202
+
203
+ if(jQuery('input[name="minTotes"]').length) {
204
+ jQuery('input[name="minTotes"]').attr('type','number').attr('min','0').css({'float':'right','margin-top':'5px'});
205
+ };
206
+ jQuery('a.nav_tab_link').click( function() {
207
+ setTimeout( function() {
208
+ swSetWidths(true);
209
+ }, 1000);
210
+ });
211
+ function swUpdateScale() {
212
+ jQuery('.nc_socialPanel').css({width:'100%'});
213
+ var width = jQuery('.nc_socialPanel').width();
214
+ scale = jQuery('select[name="buttonSize"]').val();
215
+ align = jQuery('select[name="buttonFloat"]').val();
216
+ if((align == 'fullWidth' && scale != 1) || scale >= 1) {
217
+ newWidth = width / scale;
218
+ jQuery('.nc_socialPanel').css('cssText', 'width:'+newWidth+'px!important;');
219
+ jQuery('.nc_socialPanel').css({
220
+ 'transform':'scale('+scale+')',
221
+ 'transform-origin':'left'
222
+ });
223
+ } else if(align != 'fullWidth' && scale < 1) {
224
+ newWidth = width / scale;
225
+ jQuery('.nc_socialPanel').css({
226
+ 'transform':'scale('+scale+')',
227
+ 'transform-origin':align
228
+ });
229
+ }
230
+ swSetWidths(true);
231
+ }
232
+
233
+ function swShowAlignment() {
234
+ scale = jQuery('select[name="buttonSize"]').val();
235
+ if(scale >= 1) {
236
+ jQuery('select[name="buttonFloat"]').parents('.sw_field').slideUp();
237
+ } else {
238
+ jQuery('select[name="buttonFloat"]').parents('.sw_field').slideDown();
239
+ }
240
+ }
241
+
242
+ if(jQuery('select[name="buttonSize"]').length) {
243
+ swUpdateScale();
244
+ swShowAlignment();
245
+ jQuery('select[name="buttonSize"],select[name="buttonFloat"]').on('change',function() {
246
+ swUpdateScale();
247
+ swShowAlignment();
248
+ });
249
+ }
250
+
251
+ function swButtonFloatStyles() {
252
+ useExistingStyle = jQuery('div[rel="floatStyleSource"]').hasClass('on');
253
+ if(useExistingStyle) {
254
+ jQuery('select[name="sideDColorSet"]').parents('.sw_field').slideUp();
255
+ jQuery('select[name="sideIColorSet"]').parents('.sw_field').slideUp();
256
+ jQuery('select[name="sideOColorSet"]').parents('.sw_field').slideUp();
257
+ } else {
258
+ jQuery('select[name="sideDColorSet"]').parents('.sw_field').slideDown();
259
+ jQuery('select[name="sideIColorSet"]').parents('.sw_field').slideDown();
260
+ jQuery('select[name="sideOColorSet"]').parents('.sw_field').slideDown();
261
+ }
262
+ var option = jQuery('select[name="floatOption"]').val();
263
+ if(option == 'top' || option == 'bottom') {
264
+ jQuery('select[name="floatStyle"]').parents('.sw_field').slideUp();
265
+ jQuery('input[name="floatStyleSource"]').parents('.sw_field').slideUp();
266
+ jQuery('input[name="floatBgColor"]').parents('.sw_field').slideDown();
267
+ } else {
268
+ jQuery('select[name="floatStyle"]').parents('.sw_field').slideDown();
269
+ jQuery('input[name="floatStyleSource"]').parents('.sw_field').slideDown();
270
+ jQuery('input[name="floatBgColor"]').parents('.sw_field').slideUp();
271
+ }
272
+ }
273
+
274
+ if(jQuery('input[name="floatStyleSource"]').length) {
275
+ useExistingStyle = jQuery('input[name="floatStyleSource"]').val();
276
+ if(useExistingStyle) {
277
+ jQuery('select[name="sideDColorSet"]').parents('.sw_field').slideUp();
278
+ jQuery('select[name="sideIColorSet"]').parents('.sw_field').slideUp();
279
+ jQuery('select[name="sideOColorSet"]').parents('.sw_field').slideUp();
280
+ } else {
281
+ jQuery('select[name="sideDColorSet"]').parents('.sw_field').slideDown();
282
+ jQuery('select[name="sideIColorSet"]').parents('.sw_field').slideDown();
283
+ jQuery('select[name="sideOColorSet"]').parents('.sw_field').slideDown();
284
+ }
285
+ swButtonFloatStyles();
286
+ jQuery('input[name="floatStyleSource"], select[name="floatOption"]').on('change',function() {
287
+ swButtonFloatStyles();
288
+ });
289
+ }
290
+
291
+ oldColorCode = null;
292
+ if(jQuery('input[name="customColor"]').length) {
293
+ setInterval( function() {
294
+ newColorCode = jQuery('input[name="customColor"]').val();
295
+ if(newColorCode != oldColorCode) {
296
+ updateCustomColor();
297
+ };
298
+ oldColorCode = newColorCode;
299
+ } , 500);
300
+ }
301
+
302
+ function updateCustomColor() {
303
+ jQuery('style.sw_customColorStuff').remove();
304
+ var colorCode = jQuery('input[name="customColor"]').val();
305
+ customCSS = '';
306
+ if(dColorSet == 'customColor' || iColorSet == 'customColor' || oColorSet == 'customColor') {
307
+ var customCSS = '.nc_socialPanel.sw_d_customColor a, html body .nc_socialPanel.sw_i_customColor .nc_tweetContainer:hover a, body .nc_socialPanel.sw_o_customColor:hover a {color:white} .nc_socialPanel.sw_d_customColor .nc_tweetContainer, html body .nc_socialPanel.sw_i_customColor .nc_tweetContainer:hover, body .nc_socialPanel.sw_o_customColor:hover .nc_tweetContainer {background-color:'+colorCode+';border:1px solid '+colorCode+';}';
308
+ }
309
+ if(dColorSet == 'ccOutlines' || iColorSet == 'ccOutlines' || oColorSet == 'ccOutlines' ) {
310
+ var customCSS = customCSS+' .nc_socialPanel.sw_d_ccOutlines a, html body .nc_socialPanel.sw_i_ccOutlines .nc_tweetContainer:hover a, body .nc_socialPanel.sw_o_ccOutlines:hover a { color:'+colorCode+'; } .nc_socialPanel.sw_d_ccOutlines .nc_tweetContainer, html body .nc_socialPanel.sw_i_ccOutlines .nc_tweetContainer:hover, body .nc_socialPanel.sw_o_ccOutlines:hover .nc_tweetContainer { background:transparent; border:1px solid '+colorCode+'; }';
311
+ }
312
+
313
+ jQuery('head').append('<style type="text/css" class="sw_customColorStuff">'+customCSS+'</style>');
314
+ };
315
+
316
+ function sw_loading_screen() {
317
+ jQuery('body').addClass('sw_loading').append('<div class="sw_loading_modal"><div class="sw_modal_message">Processing Registration<br /><br /><span class="sw_modal_subtitle">Please Wait a Moment<span></div></div>');
318
+ }
319
+ function sw_clear_loading_screen() {
320
+ jQuery('body').removeClass('sw_loading');
321
+ jQuery('.sw_loading_modal').remove();
322
+ }
323
+
324
+ function update_ctt_demo() {
325
+ var current_style = jQuery('.sw_CTT').attr('data-style');
326
+ var new_style = jQuery('select[name="cttTheme"]').val();
327
+ jQuery('.sw_CTT').removeClass(current_style).addClass(new_style).attr('data-style',new_style);
328
+ }
329
+
330
+ jQuery(document).ready(function($) {
331
+
332
+ update_ctt_demo();
333
+ jQuery('select[name="cttTheme"]').on('change', function() {
334
+ update_ctt_demo();
335
+ });
336
+
337
+
338
+ jQuery('input[name="premiumCode"]').attr('readonly','readonly');
339
+ jQuery('input[name="regCode"]').parent('.sw_field').hide();
340
+ var premcode = jQuery('input#domain').attr('data-premcode');
341
+
342
+ // Check if we're in the middle of registering it
343
+ if(jQuery('input[name="premiumCode"]').val() == premcode && jQuery('.sw_not_registered').length) {
344
+ sw_loading_screen();
345
+ jQuery('form[name="admin_page_class"]').submit();
346
+
347
+ // Check if we're in the middle of unregistering it
348
+ } else if(jQuery('input[name="premiumCode"]').val() == '' && jQuery('.sw_registered').length ) {
349
+ sw_loading_screen();
350
+ jQuery('form[name="admin_page_class"]').submit();
351
+
352
+ // Check if the Premium code doesn't match
353
+ } else if (jQuery('input[name="premiumCode"]').val() != '' && jQuery('input[name="premiumCode"]').val() != premcode) {
354
+
355
+ sw_loading_screen();
356
+
357
+ // Fetch our variables
358
+ var regCode = jQuery('input[name="regCode"]').val();
359
+ var email = jQuery('input[name="emailAddress"]').val();
360
+ var domain = jQuery('input[name="domain"]').val();
361
+
362
+ // Creat the unregister url
363
+ url = ('https:' == document.location.protocol ? 'https:' : 'http:') + '//warfareplugins.com/registration-api/?activity=unregister&emailAddress='+email+'&premiumCode='+jQuery('input[name="premiumCode"]').val();
364
+
365
+ jQuery.get( url , function(data) {
366
+
367
+ url = ('https:' == document.location.protocol ? 'https:' : 'http:') + '//warfareplugins.com/registration-api/?activity=register&emailAddress='+email+'&domain='+domain+'&registrationCode='+regCode;
368
+ jQuery.get( url , function(subdata) {
369
+ var info = jQuery.parseJSON(subdata);
370
+ if(info['status'] == 'success') {
371
+ jQuery('input[name="premiumCode"]').val(info['premiumCode']);
372
+ jQuery('form[name="admin_page_class"]').submit();
373
+ } else {
374
+ jQuery('input[name="premiumCode"]').val('');
375
+ jQuery('form[name="admin_page_class"]').submit();
376
+ }
377
+ });
378
+
379
+
380
+ } );
381
+ };
382
+
383
+ jQuery('.activate[value="Register Plugin"]').on('click',function(e) {
384
+ e.preventDefault();
385
+ sw_loading_screen();
386
+ var regCode = jQuery('input[name="regCode"]').val();
387
+ var email = jQuery('input[name="emailAddress"]').val();
388
+ var domain = jQuery('input[name="domain"]').val();
389
+ url = ('https:' == document.location.protocol ? 'https:' : 'http:') + '//warfareplugins.com/registration-api/?activity=register&emailAddress='+email+'&domain='+domain+'&registrationCode='+regCode;
390
+
391
+ jQuery.get( url, function( data ) {
392
+ var object = jQuery.parseJSON(data);
393
+ if(object['status'] == 'failure') {
394
+ sw_clear_loading_screen();
395
+ alert('Failure: '+object['message']);
396
+ } else {
397
+ jQuery('input[name="premiumCode"]').val(object['premiumCode']);
398
+ jQuery('form[name="admin_page_class"]').submit();
399
+ }
400
+ });
401
+ });
402
+ jQuery('.deactivate[value="Unregister Plugin"]').on('click',function(e) {
403
+ e.preventDefault();
404
+ sw_loading_screen();
405
+ var regCode = jQuery('input[name="regCode"]').val();
406
+ var email = jQuery('input[name="emailAddress"]').val();
407
+ var domain = jQuery('input[name="domain"]').val();
408
+ url = ('https:' == document.location.protocol ? 'https:' : 'http:') + '//warfareplugins.com/registration-api/?activity=unregister&emailAddress='+email+'&domain='+domain+'&registrationCode='+regCode;
409
+ jQuery.get( url, function( data ) {
410
+ var object = $.parseJSON(data);
411
+ jQuery('input[name="premiumCode"]').val('');
412
+ jQuery('input[name="emailAddress"]').val('');
413
+ jQuery('form[name="admin_page_class"]').submit();
414
+ });
415
+ });
416
+ apc_init();
417
+ //editor rezise fix
418
+ jQuery(window).resize(function() {
419
+ jQuery.each(Ed_array, function() {
420
+ var ee = this;
421
+ $(ee.getScrollerElement()).width(100); // set this low enough
422
+ width = $(ee.getScrollerElement()).parent().width();
423
+ $(ee.getScrollerElement()).width(width); // set it to
424
+ ee.refresh();
425
+ });
426
+ });
427
+
428
+ ooIconsAdmin();
429
+
430
+ jQuery('select[name="orderOfIconsSelect"]').on('change',ooIconsAdmin);
431
+
432
+ }); //end ready
433
+
434
+ function ooIconsAdmin() {
435
+ var orderOfIconsSelect = jQuery('select[name="orderOfIconsSelect"]').val();
436
+ console.log(orderOfIconsSelect);
437
+ if(orderOfIconsSelect != 'manual') {
438
+ jQuery('input[name="newOrderOfIcons[twitter]"]').parents('.sw_field').slideUp();
439
+ } else {
440
+ jQuery('input[name="newOrderOfIcons[twitter]"]').parents('.sw_field').slideDown();
441
+ }
442
+ }
443
+
444
+
445
+ /**
446
+ * apc_init initate fields
447
+ * @since 1.2.2
448
+ * @return void
449
+ */
450
+ function apc_init(){
451
+ /**
452
+ * Code Editor Field
453
+ * @since 2.1
454
+ */
455
+ load_code_editor();
456
+ //iphone checkboxs
457
+ fancyCheckbox();
458
+ //select 2
459
+ fancySelect();
460
+ // repeater edit
461
+ $(".at-re-toggle").live('click', function() {$(this).prev().toggle('slow');});
462
+ /**
463
+ * Datepicker Field.
464
+ *
465
+ * @since 1.0
466
+ */
467
+ loadDatePicker();
468
+ /**
469
+ * Timepicker Field.
470
+ *
471
+ * @since 1.0
472
+ */
473
+ loadTimePicker();
474
+ /**
475
+ * Colorpicker Field.
476
+ *
477
+ * @since 1.0
478
+ * better handler for color picker with repeater fields support
479
+ * which now works both when button is clicked and when field gains focus.
480
+ */
481
+ loadColorPicker();
482
+ /**
483
+ * Add Files.
484
+ *
485
+ * @since 1.0
486
+ */
487
+ $('.at-add-file').click( function() {
488
+ var $first = $(this).parent().find('.file-input:first');
489
+ $first.clone().insertAfter($first).show();
490
+ return false;
491
+ });
492
+ /**
493
+ * Delete File.
494
+ *
495
+ * @since 1.0
496
+ */
497
+ $('.at-upload').delegate( '.at-delete-file', 'click' , function() {
498
+
499
+ var $this = $(this),
500
+ $parent = $this.parent(),
501
+ data = $this.attr('rel');
502
+
503
+ $.post( ajaxurl, { action: 'at_delete_file', data: data }, function(response) {
504
+ response == '0' ? ( alert( 'File has been successfully deleted.' ), $parent.remove() ) : alert( 'You do NOT have permission to delete this file.' );
505
+ });
506
+
507
+ return false;
508
+ });
509
+ /**
510
+ * initiate repeater sortable option
511
+ * since 0.4
512
+ */
513
+ $(".repeater-sortable").sortable();
514
+ /**
515
+ * initiate sortable fields option
516
+ * since 0.4
517
+ */
518
+ $(".at-sortable").sortable({placeholder: "ui-state-highlight"});
519
+ //new image upload field
520
+ load_images_muploader();
521
+ //delete img button
522
+ $('.at-delete_image_button').live('click', function(event){
523
+ event.preventDefault();
524
+ remove_image($(this));
525
+ return false;
526
+ });
527
+ //upload images
528
+ $('.at-upload_image_button').live('click',function(event){
529
+ event.preventDefault();
530
+ image_upload($(this));
531
+ return false;
532
+ });
533
+ /**
534
+ * listen for import button click
535
+ * @since 0.8
536
+ * @return void
537
+ */
538
+ $("#apc_import_b").live("click",function(){do_ajax_import_export('import');});
539
+ /**
540
+ * listen for export button click
541
+ * @since 0.8
542
+ * @return void
543
+ */
544
+ $("#apc_export_b").live("click",function(){do_ajax_import_export('export');});
545
+ //refresh page
546
+ $("#apc_refresh_page_b").live("click",function(){refresh_page();});
547
+ //status alert dismiss
548
+ $('[data-dismiss="alert"]').live("click",function(){$(this).parent().remove()});
549
+ }
550
+
551
+ /**
552
+ * loadColorPicker
553
+ * @since 1.2.2
554
+ * @return void
555
+ */
556
+ function loadColorPicker(){
557
+ if ($.farbtastic){//since WordPress 3.5
558
+ $('.at-color').live('focus', function() {
559
+ load_colorPicker($(this).next());
560
+ });
561
+
562
+ $('.at-color').live('focusout', function() {
563
+ hide_colorPicker($(this).next());
564
+ });
565
+
566
+ /**
567
+ * Select Color Field.
568
+ *
569
+ * @since 1.0
570
+ */
571
+ $('.at-color-select').live('click', function(){
572
+ if ($(this).next('div').css('display') == 'none')
573
+ load_colorPicker($(this));
574
+ else
575
+ hide_colorPicker($(this));
576
+ });
577
+
578
+ function load_colorPicker(ele){
579
+ colorPicker = $(ele).next('div');
580
+ input = $(ele).prev('input');
581
+
582
+ $.farbtastic($(colorPicker), function(a) { $(input).val(a).css('background', a); });
583
+
584
+ colorPicker.show();
585
+ //e.preventDefault();
586
+
587
+ //$(document).mousedown( function() { $(colorPicker).hide(); });
588
+ }
589
+
590
+ function hide_colorPicker(ele){
591
+ colorPicker = $(ele).next('div');
592
+ $(colorPicker).hide();
593
+ }
594
+ //issue #15
595
+ $('.at-color').each(function(){
596
+ var colo = $(this).val();
597
+ if (colo.length == 7)
598
+ $(this).css('background',colo);
599
+ });
600
+ }else{
601
+ if ($('.at-color-iris').length>0){
602
+ $('.at-color-iris').wpColorPicker();
603
+ }
604
+ }
605
+ }
606
+
607
+ /**
608
+ * loadDatePicker
609
+ * @since 1.2.2
610
+ * @return void
611
+ */
612
+ function loadDatePicker(){
613
+ $('.at-date').each( function() {
614
+ var $this = $(this),
615
+ format = $this.attr('rel');
616
+ $this.datepicker( { showButtonPanel: true, dateFormat: format } );
617
+ });
618
+ }
619
+
620
+ /**
621
+ * loadTimePicker
622
+ * @since 1.2.2
623
+ * @return void
624
+ */
625
+ function loadTimePicker(){
626
+ $('.at-time').each( function() {
627
+ var $this = $(this),
628
+ format = $this.attr('rel');
629
+ $this.timepicker( { showSecond: true, timeFormat: format } );
630
+ });
631
+ }
632
+
633
+ /**
634
+ * jQuery iphone style checkbox enable function
635
+ * @since 1.1.5
636
+ */
637
+ function fancyCheckbox(){
638
+ $(':checkbox').each(function (){
639
+ var $el = $(this);
640
+ if(! $el.hasClass('no-toggle')){
641
+ $el.FancyCheckbox();
642
+ if ($el.hasClass("conditinal_control")){
643
+ $el.live('change', function() {
644
+ var $el = $(this);
645
+ if($el.is(':checked'))
646
+ $el.next().next().show('fast');
647
+ else
648
+ $el.next().next().hide('fast');
649
+ });
650
+ }
651
+ }else{
652
+ if ($el.hasClass("conditinal_control")){
653
+ $el.live('change', function() {
654
+ var $el = $(this);
655
+ if($el.is(':checked'))
656
+ $el.next().show('fast');
657
+ else
658
+ $el.next().hide('fast');
659
+ });
660
+ }
661
+ }
662
+ });
663
+ }
664
+
665
+ /**
666
+ * Select 2 enable function
667
+ * @since 1.1.5
668
+ */
669
+ function fancySelect(){
670
+ $("select").each(function (){
671
+ if(! $(this).hasClass('no-fancy'))
672
+ $(this).select2();
673
+ });
674
+ }
675
+
676
+ /**
677
+ * remove_image description
678
+ * @since 1.2.2
679
+ * @param jQuery element object
680
+ * @return void
681
+ */
682
+ function remove_image(ele){
683
+ var $el = $(ele);
684
+ var field_id = $el.attr("rel");
685
+ var at_id = $el.prev().prev();
686
+ var at_src = $el.prev();
687
+ var t_button = $el;
688
+ data = {
689
+ action: 'apc_delete_mupload',
690
+ _wpnonce: $('#nonce-delete-mupload_' + field_id).val(),
691
+ field_id: field_id,
692
+ attachment_id: jQuery(at_id).val()
693
+ };
694
+
695
+ $.getJSON(ajaxurl, data, function(response) {
696
+ if ('success' == response.status){
697
+ $(t_button).val("Upload Image");
698
+ $(t_button).removeClass('at-delete_image_button').addClass('at-upload_image_button');
699
+ //clear html values
700
+ $(at_id).val('');
701
+ $(at_src).val('');
702
+ $(at_id).prev().html('');
703
+ load_images_muploader();
704
+ }else{
705
+ alert(response.message);
706
+ }
707
+ });
708
+ }
709
+
710
+ /**
711
+ * image_upload handle image upload
712
+ * @since 1.2.2
713
+ * @param jquery element object
714
+ * @return void
715
+ */
716
+ function image_upload(ele){
717
+ var $el = $(ele);
718
+ formfield1 = $el.prev();
719
+ formfield2 = $el.prev().prev();
720
+ if ($el.attr('data-u') == 'tk'){
721
+ tb_show('', 'media-upload.php?post_id=0&type=image&apc=apc&TB_iframe=true');
722
+ //store old send to editor function
723
+ window.restore_send_to_editor = window.send_to_editor;
724
+ //overwrite send to editor function
725
+ window.send_to_editor = function(html) {
726
+ imgurl = $('img',html).attr('src');
727
+ img_calsses = $('img',html).attr('class').split(" ");
728
+ att_id = '';
729
+ $.each(img_calsses,function(i,val){
730
+ if (val.indexOf("wp-image") != -1){
731
+ att_id = val.replace('wp-image-', "");
732
+ }
733
+ });
734
+
735
+ $(formfield2).val(att_id);
736
+ $(formfield1).val(imgurl);
737
+ load_images_muploader();
738
+ tb_remove();
739
+ //restore old send to editor function
740
+ window.send_to_editor = window.restore_send_to_editor;
741
+ }
742
+ }else{
743
+ // Uploading files since WordPress 3.5
744
+ // If the media frame already exists, reopen it.
745
+ if ( file_frame ) {
746
+ file_frame.open();
747
+ return;
748
+ }
749
+ // Create the media frame.
750
+ file_frame = wp.media.frames.file_frame = wp.media({
751
+ title: $el.data( 'uploader_title' ),
752
+ button: {
753
+ text: $el.data( 'uploader_button_text' ),
754
+ },
755
+ multiple: false // Set to true to allow multiple files to be selected
756
+ });
757
+ // When an image is selected, run a callback.
758
+ file_frame.on( 'select', function() {
759
+ // We set multiple to false so only get one image from the uploader
760
+ attachment = file_frame.state().get('selection').first().toJSON();
761
+ // Do something with attachment.id and/or attachment.url here
762
+ jQuery(formfield2).val(attachment.id);
763
+ jQuery(formfield1).val(attachment.url);
764
+ load_images_muploader();
765
+ });
766
+ // Finally, open the modal
767
+ file_frame.open();
768
+ }
769
+ }
770
+
771
+ /**
772
+ * load_images_muploader
773
+ * load images after upload
774
+ * @return void
775
+ */
776
+ function load_images_muploader(){
777
+ $(".mupload_img_holder").each(function(i,v){
778
+ if ($(this).next().next().val() != ''){
779
+ if (!$(this).children().size() > 0){
780
+ var h = $(this).attr('data-he');
781
+ var w = $(this).attr('data-wi');
782
+ $(this).append('<img src="' + $(this).next().next().val() + '" style="height: '+ h +';width: '+ w +';" />');
783
+ $(this).next().next().next().val("Delete");
784
+ $(this).next().next().next().removeClass('at-upload_image_button').addClass('at-delete_image_button');
785
+ }
786
+ }
787
+ });
788
+ }
789
+
790
+ /**
791
+ * load_code_editor loads code editors
792
+ * @since 1.2.2
793
+ * @return void
794
+ */
795
+ function load_code_editor(){
796
+ var e_d_count = 0;
797
+ $(".code_text").each(function() {
798
+ var lang = $(this).attr("data-lang");
799
+ //php application/x-httpd-php
800
+ //css text/css
801
+ //html text/html
802
+ //javascript text/javascript
803
+ switch(lang){
804
+ case 'php':
805
+ lang = 'application/x-httpd-php';
806
+ break;
807
+ case 'less':
808
+ case 'css':
809
+ lang = 'text/css';
810
+ break;
811
+ case 'html':
812
+ lang = 'text/html';
813
+ break;
814
+ case 'javascript':
815
+ lang = 'text/javascript';
816
+ break;
817
+ default:
818
+ lang = 'application/x-httpd-php';
819
+ }
820
+ var theme = $(this).attr("data-theme");
821
+ switch(theme){
822
+ case 'default':
823
+ theme = 'default';
824
+ break;
825
+ case 'light':
826
+ theme = 'solarizedLight';
827
+ break;
828
+ case 'dark':
829
+
830
+ theme = 'solarizedDark';;
831
+ break;
832
+ default:
833
+ theme = 'default';
834
+ }
835
+
836
+ var editor = CodeMirror.fromTextArea(document.getElementById($(this).attr('id')), {
837
+ lineNumbers: true,
838
+ matchBrackets: true,
839
+ mode: lang,
840
+ indentUnit: 4,
841
+ indentWithTabs: true,
842
+ enterMode: "keep",
843
+ tabMode: "shift"
844
+ });
845
+ editor.setOption("theme", theme);
846
+ $(editor.getScrollerElement()).width(100); // set this low enough
847
+ width = $(editor.getScrollerElement()).parent().width();
848
+ $(editor.getScrollerElement()).width(width); // set it to
849
+ editor.refresh();
850
+ Ed_array[e_d_count] = editor;
851
+ e_d_count++;
852
+ });
853
+ }
854
+
855
+ /***************************
856
+ * Import Export Functions *
857
+ * ************************/
858
+
859
+ /**
860
+ * do_ajax
861
+ *
862
+ * @author Ohad Raz <admin@bainternet.info>
863
+ * @since 0.8
864
+ * @param string which (import|export)
865
+ *
866
+ * @return void
867
+ */
868
+ function do_ajax_import_export(which){
869
+ before_ajax_import_export(which);
870
+ var group = jQuery("#option_group_name").val();
871
+ var seq_selector = "#apc_" + which + "_nonce";
872
+ var action_selctor = "apc_" + which + "_" + group;
873
+ jQuery.ajaxSetup({ cache: false });
874
+ if (which == 'export')
875
+ export_ajax_call(action_selctor,group,seq_selector,which);
876
+ else
877
+ import_ajax_call(action_selctor,group,seq_selector,which);
878
+ jQuery.ajaxSetup({ cache: true });
879
+ }
880
+
881
+ /**
882
+ * export_ajax_call make export ajax call
883
+ *
884
+ * @author Ohad Raz <admin@bainternet.info>
885
+ * @since 0.8
886
+ *
887
+ * @param string action
888
+ * @param string group
889
+ * @param string seq_selector
890
+ * @param string which
891
+ * @return void
892
+ */
893
+ function export_ajax_call(action,group,seq_selector,which){
894
+ jQuery.getJSON(ajaxurl,
895
+ {
896
+ group: group,
897
+ rnd: microtime(false), //hack to avoid request cache
898
+ action: action,
899
+ seq: jQuery(seq_selector).val()
900
+ },
901
+ function(data) {
902
+ if (data){
903
+ export_response(data);
904
+ }else{
905
+ alert("Something Went Wrong, try again later");
906
+ }
907
+ after_ajax_import_export(which);
908
+ }
909
+ );
910
+ }
911
+
912
+ /**
913
+ * import_ajax_call make import ajax call
914
+ *
915
+ * @author Ohad Raz <admin@bainternet.info>
916
+ * @since 0.8
917
+ *
918
+ * @param string action
919
+ * @param string group
920
+ * @param string seq_selector
921
+ * @param string which
922
+ * @return void
923
+ */
924
+ function import_ajax_call(action,group,seq_selector,which){
925
+ jQuery.post(ajaxurl,
926
+ {
927
+ group: group,
928
+ rnd: microtime(false), //hack to avoid request cache
929
+ action: action,
930
+ seq: jQuery(seq_selector).val(),
931
+ imp: jQuery("#import_code").val(),
932
+ },
933
+ function(data) {
934
+ if (data){
935
+ import_response(data);
936
+ }else{
937
+ alert("Something Went Wrong, try again later");
938
+ }
939
+ after_ajax_import_export(which);
940
+ },
941
+ "json"
942
+ );
943
+ }
944
+
945
+ /**
946
+ * before_ajax_import_export
947
+ *
948
+ * @author Ohad Raz <admin@bainternet.info>
949
+ * @since 0.8
950
+ * @param string which (import|export)
951
+ *
952
+ * @return void
953
+ */
954
+ function before_ajax_import_export(which){
955
+ jQuery(".import_status").hide("fast");
956
+ jQuery(".export_status").hide("fast");
957
+ jQuery(".export_results").html('').removeClass('alert-success').hide();
958
+ jQuery(".import_results").html('').removeClass('alert-success').hide();
959
+ if (which == 'import')
960
+ jQuery(".import_status").show("fast");
961
+ else
962
+ jQuery(".export_status").show("fast");
963
+ }
964
+
965
+ /**
966
+ * after_ajax_import_export
967
+ *
968
+ * @author Ohad Raz <admin@bainternet.info>
969
+ * @since 0.8
970
+ * @param string which (import|export)
971
+ *
972
+ * @return void
973
+ */
974
+ function after_ajax_import_export(which){
975
+ if (which == 'import')
976
+ jQuery(".import_status").hide("fast");
977
+ else
978
+ jQuery(".export_status").hide("fast");
979
+ }
980
+
981
+ /**
982
+ * export_reponse
983
+ *
984
+ * @author Ohad Raz <admin@bainternet.info>
985
+ * @since 0.8
986
+ * @param json data ajax response
987
+ * @return void
988
+ */
989
+ function export_response(data){
990
+ if (data.code)
991
+ jQuery('#export_code').val(data.code);
992
+ if (data.nonce)
993
+ jQuery("#apc_export_nonce").val(data.nonce);
994
+ if(data.err)
995
+ jQuery(".export_results").html(data.err).show('slow');
996
+ }
997
+
998
+ /**
999
+ * import_reponse
1000
+ *
1001
+ * @author Ohad Raz <admin@bainternet.info>
1002
+ * @since 0.8
1003
+ * @param json data ajax response
1004
+ *
1005
+ * @return void
1006
+ */
1007
+ function import_response(data){
1008
+ if (data.nonce)
1009
+ jQuery("#apc_import_nonce").val(data.nonce);
1010
+ if(data.err)
1011
+ jQuery(".import_results").html(data.err);
1012
+ if (data.success)
1013
+ jQuery(".import_results").html(data.success).addClass('alert-success').show('slow');
1014
+ }
1015
+
1016
+ /********************
1017
+ * Helper Functions *
1018
+ *******************/
1019
+
1020
+ /**
1021
+ * refresh_page
1022
+ * @since 0.8
1023
+ * @return void
1024
+ */
1025
+ function refresh_page(){
1026
+
1027
+ location.reload();
1028
+ }
1029
+
1030
+ /**
1031
+ * microtime used as hack to avoid ajax cache
1032
+ *
1033
+ * @author Ohad Raz <admin@bainternet.info>
1034
+ * @since 0.8
1035
+ * @param boolean get_as_float
1036
+ *
1037
+ * @return microtime as int or float
1038
+ */
1039
+ function microtime(get_as_float) {
1040
+ var now = new Date().getTime() / 1000;
1041
+ var s = parseInt(now);
1042
+ return (get_as_float) ? now : (Math.round((now - s) * 1000) / 1000) + " " + s;
1043
+ }
1044
+
1045
+ /**
1046
+ * Helper Function
1047
+ *
1048
+ * Get Query string value by name.
1049
+ *
1050
+ * @since 1.0
1051
+ */
1052
+ function get_query_var( name ) {
1053
+
1054
+ var match = RegExp('[?&]' + name + '=([^&#]*)').exec(location.href);
1055
+ return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
1056
+ }
functions/admin-page-class/js/FancyCheckbox/FancyCheckbox.css ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Checkbox style */
2
+ .iphone-style {
3
+ display: block;
4
+ width: 87px;
5
+ height: 28px;
6
+ background: url('images/on-off.png') no-repeat;
7
+ overflow: hidden;
8
+ cursor: pointer;
9
+ float: right;
10
+ margin-right: 0;
11
+ margin-top:10px;
12
+ border-radius:4px;
13
+ }
14
+ .firerift-style {
15
+ display: block;
16
+ width: 68px;
17
+ height: 28px;
18
+ background: url('images/firerift.png') no-repeat;
19
+ cursor: pointer;
20
+ }
21
+ .on {background-position: 0% 100%;}
22
+ .off {background-position: 100% 0%;}
23
+ .hidden{display: none !important;}
24
+ /* Checkbox style */
functions/admin-page-class/js/FancyCheckbox/FancyCheckbox.js ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Iphone styled checkboxes
3
+ * @author Ohad Raz http://en.bainternet.info
4
+ * @version 0.1
5
+ * @copyright 2012 Ohad Raz
6
+ */
7
+ ;(function ( $, window, document, undefined ) {
8
+ var options = {
9
+ style: "iphone", //iphone,firerift,
10
+ offClass: 'no-fancy', //class to disable elements with this class will not be fancy
11
+ };
12
+ var methods = {
13
+ init : function( settings ) {
14
+ if(options) {
15
+ $.extend(options,settings);
16
+ }
17
+
18
+ return this.each(function(){
19
+ var $elem = $(this);
20
+ methods.loadStyledCehckboxes($elem,options);
21
+ });
22
+ },
23
+
24
+ loadStyledCehckboxes: function($el, options){
25
+ var $ele = $el;
26
+ if ($ele.hasClass(options.offClass) || $ele.data('FancyCheckbox'))
27
+ return;
28
+ $ele.trigger('beforeLoad', $ele);
29
+ var thisID = $ele.attr('id');
30
+ var setClass = '';
31
+ switch(options.style) {
32
+ case "iphone":
33
+ setClass = "iphone-style";
34
+ break;
35
+ case "firerift":
36
+ setClass = "firerift-style";
37
+ break;
38
+ }
39
+ if($ele[0].checked == true){
40
+ setClass = setClass + ' on';
41
+ }else{
42
+ setClass = setClass + ' off';
43
+ }
44
+
45
+ $ele.addClass('hidden');
46
+ $ele.data('FancyCheckbox',true);
47
+
48
+ var d = $('<div>')
49
+ .addClass(setClass)
50
+ .attr('rel',thisID)
51
+ .html('&nbsp');
52
+ switch(options.style) {
53
+ case "iphone":
54
+ d.on('click',function(){methods.OnClickIphone($ele);});
55
+ break;
56
+ case "firerift":
57
+ d.on('click',function(){methods.OnClickfirerift($ele);});
58
+ break;
59
+ }
60
+ $ele.after(d);
61
+ $ele.trigger('afterLoad', $ele);
62
+ },
63
+
64
+ OnClickIphone: function($el) {
65
+ $el_Styled = $el.next();
66
+ $el.trigger('beforeChangeIphone', $el);
67
+ if($el[0].checked) {
68
+ methods.toggleOnOff($el,$el_Styled,false,true);
69
+ } else {
70
+ methods.toggleOnOff($el,$el_Styled,true,true);
71
+ }
72
+ $el.trigger('afterChangeIphone', $el);
73
+ },
74
+
75
+ OnClickfirerift: function($el) {
76
+ $el_Styled = $el.next();
77
+ $el.trigger('beforeChangeFirerift', $el);;
78
+ if($el[0].checked) {
79
+ methods.toggleOnOff($el,$el_Styled,false);
80
+ } else {
81
+ methods.toggleOnOff($el,$el_Styled,true);
82
+ }
83
+ $el.trigger('afterChangeFirerift', $el);
84
+ },
85
+
86
+ toggleOnOff: function ($el,$s,onOff,anim){
87
+ anim = anim || false;
88
+ if (onOff){
89
+ if (anim)
90
+ $s.animate({backgroundPosition: '0% 100%'});
91
+ $el[0].checked = true;
92
+ $s.removeClass('off').addClass('on');
93
+ }else{
94
+ if (anim)
95
+ $s.animate({backgroundPosition: '100% 0%'});
96
+ $el[0].checked = false;
97
+ $s.removeClass('on').addClass('off');
98
+ }
99
+ //keep original change event
100
+ $el.trigger("change", $el);
101
+ },
102
+
103
+ destroy: function(){
104
+ $(this).each(function(){
105
+ $el = $(this);
106
+ $el.next().remove();
107
+ $.removeData($el,'FancyCheckbox');
108
+ $el.removeClass('hidden');
109
+ });
110
+ }
111
+ };
112
+ $.fn.FancyCheckbox = function( method ) {
113
+ if ( methods[method] ) {
114
+ return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
115
+ } else if ( typeof method === 'object' || ! method ) {
116
+ return methods.init.apply( this, arguments );
117
+ } else {
118
+ $.error( 'Method ' + method + ' does not exist on jQuery.tooltip' );
119
+ }
120
+ };
121
+ })( jQuery, window, document );
functions/admin-page-class/js/FancyCheckbox/FancyCheckbox.min.css ADDED
@@ -0,0 +1 @@
 
1
+ .iphone-style{display:block;width:87px;height:28px;background:url('images/iphone.png') no-repeat;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;overflow:hidden;cursor:pointer}.firerift-style{display:block;width:68px;height:28px;background:url('images/firerift.png') no-repeat;cursor:pointer}.on{background-position:0 100%}.off{background-position:100% 0}.hidden{display:none!important;}
functions/admin-page-class/js/FancyCheckbox/FancyCheckbox.min.js ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ /**
2
+ * Iphone styled checkboxes
3
+ * @author Ohad Raz http://en.bainternet.info
4
+ * @version 0.1
5
+ * @copyright 2012 Ohad Raz
6
+ */
7
+ (function(e,t,n,r){var i={style:"iphone",offClass:"no-fancy"};var s={init:function(t){if(i){e.extend(i,t)}return this.each(function(){var t=e(this);s.loadStyledCehckboxes(t,i)})},loadStyledCehckboxes:function(t,n){var r=t;if(r.hasClass(n.offClass)||r.data("FancyCheckbox"))return;r.trigger("beforeLoad",r);var i=r.attr("id");var o="";switch(n.style){case"iphone":o="iphone-style";break;case"firerift":o="firerift-style";break}if(r[0].checked==true){o=o+" on"}else{o=o+" off"}r.addClass("hidden");r.data("FancyCheckbox",true);var u=e("<div>").addClass(o).attr("rel",i).html("&nbsp");switch(n.style){case"iphone":u.on("click",function(){s.OnClickIphone(r)});break;case"firerift":u.on("click",function(){s.OnClickfirerift(r)});break}r.after(u);r.trigger("afterLoad",r)},OnClickIphone:function(e){$el_Styled=e.next();e.trigger("beforeChangeIphone",e);if(e[0].checked){s.toggleOnOff(e,$el_Styled,false,true)}else{s.toggleOnOff(e,$el_Styled,true,true)}e.trigger("afterChangeIphone",e)},OnClickfirerift:function(e){$el_Styled=e.next();e.trigger("beforeChangeFirerift",e);if(e[0].checked){s.toggleOnOff(e,$el_Styled,false)}else{s.toggleOnOff(e,$el_Styled,true)}e.trigger("afterChangeFirerift",e)},toggleOnOff:function(e,t,n,r){r=r||false;if(n){if(r)t.animate({backgroundPosition:"0% 100%"});e[0].checked=true;t.removeClass("off").addClass("on")}else{if(r)t.animate({backgroundPosition:"100% 0%"});e[0].checked=false;t.removeClass("on").addClass("off")}e.trigger("change",e)},destroy:function(){e(this).each(function(){$el=e(this);$el.next().remove();e.removeData($el,"FancyCheckbox");$el.removeClass("hidden")})}};e.fn.FancyCheckbox=function(t){if(s[t]){return s[t].apply(this,Array.prototype.slice.call(arguments,1))}else if(typeof t==="object"||!t){return s.init.apply(this,arguments)}else{e.error("Method "+t+" does not exist on jQuery.tooltip")}}})(jQuery,window,document)
functions/admin-page-class/js/FancyCheckbox/images/firerift.png ADDED
Binary file
functions/admin-page-class/js/FancyCheckbox/images/iphone.png ADDED
Binary file
functions/admin-page-class/js/FancyCheckbox/images/on-off.png ADDED
Binary file
functions/admin-page-class/js/codemirror/clike.js ADDED
@@ -0,0 +1,234 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ CodeMirror.defineMode("clike", function(config, parserConfig) {
2
+ var indentUnit = config.indentUnit,
3
+ keywords = parserConfig.keywords || {},
4
+ blockKeywords = parserConfig.blockKeywords || {},
5
+ atoms = parserConfig.atoms || {},
6
+ hooks = parserConfig.hooks || {},
7
+ multiLineStrings = parserConfig.multiLineStrings;
8
+ var isOperatorChar = /[+\-*&%=<>!?|\/]/;
9
+
10
+ var curPunc;
11
+
12
+ function tokenBase(stream, state) {
13
+ var ch = stream.next();
14
+ if (hooks[ch]) {
15
+ var result = hooks[ch](stream, state);
16
+ if (result !== false) return result;
17
+ }
18
+ if (ch == '"' || ch == "'") {
19
+ state.tokenize = tokenString(ch);
20
+ return state.tokenize(stream, state);
21
+ }
22
+ if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
23
+ curPunc = ch;
24
+ return null
25
+ }
26
+ if (/\d/.test(ch)) {
27
+ stream.eatWhile(/[\w\.]/);
28
+ return "number";
29
+ }
30
+ if (ch == "/") {
31
+ if (stream.eat("*")) {
32
+ state.tokenize = tokenComment;
33
+ return tokenComment(stream, state);
34
+ }
35
+ if (stream.eat("/")) {
36
+ stream.skipToEnd();
37
+ return "comment";
38
+ }
39
+ }
40
+ if (isOperatorChar.test(ch)) {
41
+ stream.eatWhile(isOperatorChar);
42
+ return "operator";
43
+ }
44
+ stream.eatWhile(/[\w\$_]/);
45
+ var cur = stream.current();
46
+ if (keywords.propertyIsEnumerable(cur)) {
47
+ if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
48
+ return "keyword";
49
+ }
50
+ if (atoms.propertyIsEnumerable(cur)) return "atom";
51
+ return "word";
52
+ }
53
+
54
+ function tokenString(quote) {
55
+ return function(stream, state) {
56
+ var escaped = false, next, end = false;
57
+ while ((next = stream.next()) != null) {
58
+ if (next == quote && !escaped) {end = true; break;}
59
+ escaped = !escaped && next == "\\";
60
+ }
61
+ if (end || !(escaped || multiLineStrings))
62
+ state.tokenize = tokenBase;
63
+ return "string";
64
+ };
65
+ }
66
+
67
+ function tokenComment(stream, state) {
68
+ var maybeEnd = false, ch;
69
+ while (ch = stream.next()) {
70
+ if (ch == "/" && maybeEnd) {
71
+ state.tokenize = tokenBase;
72
+ break;
73
+ }
74
+ maybeEnd = (ch == "*");
75
+ }
76
+ return "comment";
77
+ }
78
+
79
+ function Context(indented, column, type, align, prev) {
80
+ this.indented = indented;
81
+ this.column = column;
82
+ this.type = type;
83
+ this.align = align;
84
+ this.prev = prev;
85
+ }
86
+ function pushContext(state, col, type) {
87
+ return state.context = new Context(state.indented, col, type, null, state.context);
88
+ }
89
+ function popContext(state) {
90
+ var t = state.context.type;
91
+ if (t == ")" || t == "]" || t == "}")
92
+ state.indented = state.context.indented;
93
+ return state.context = state.context.prev;
94
+ }
95
+
96
+ // Interface
97
+
98
+ return {
99
+ startState: function(basecolumn) {
100
+ return {
101
+ tokenize: null,
102
+ context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
103
+ indented: 0,
104
+ startOfLine: true
105
+ };
106
+ },
107
+
108
+ token: function(stream, state) {
109
+ var ctx = state.context;
110
+ if (stream.sol()) {
111
+ if (ctx.align == null) ctx.align = false;
112
+ state.indented = stream.indentation();
113
+ state.startOfLine = true;
114
+ }
115
+ if (stream.eatSpace()) return null;
116
+ curPunc = null;
117
+ var style = (state.tokenize || tokenBase)(stream, state);
118
+ if (style == "comment" || style == "meta") return style;
119
+ if (ctx.align == null) ctx.align = true;
120
+
121
+ if ((curPunc == ";" || curPunc == ":") && ctx.type == "statement") popContext(state);
122
+ else if (curPunc == "{") pushContext(state, stream.column(), "}");
123
+ else if (curPunc == "[") pushContext(state, stream.column(), "]");
124
+ else if (curPunc == "(") pushContext(state, stream.column(), ")");
125
+ else if (curPunc == "}") {
126
+ while (ctx.type == "statement") ctx = popContext(state);
127
+ if (ctx.type == "}") ctx = popContext(state);
128
+ while (ctx.type == "statement") ctx = popContext(state);
129
+ }
130
+ else if (curPunc == ctx.type) popContext(state);
131
+ else if (ctx.type == "}" || ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement"))
132
+ pushContext(state, stream.column(), "statement");
133
+ state.startOfLine = false;
134
+ return style;
135
+ },
136
+
137
+ indent: function(state, textAfter) {
138
+ if (state.tokenize != tokenBase && state.tokenize != null) return 0;
139
+ var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
140
+ if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
141
+ var closing = firstChar == ctx.type;
142
+ if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : indentUnit);
143
+ else if (ctx.align) return ctx.column + (closing ? 0 : 1);
144
+ else return ctx.indented + (closing ? 0 : indentUnit);
145
+ },
146
+
147
+ electricChars: "{}"
148
+ };
149
+ });
150
+
151
+ (function() {
152
+ function words(str) {
153
+ var obj = {}, words = str.split(" ");
154
+ for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
155
+ return obj;
156
+ }
157
+ var cKeywords = "auto if break int case long char register continue return default short do sizeof " +
158
+ "double static else struct entry switch extern typedef float union for unsigned " +
159
+ "goto while enum void const signed volatile";
160
+
161
+ function cppHook(stream, state) {
162
+ if (!state.startOfLine) return false;
163
+ stream.skipToEnd();
164
+ return "meta";
165
+ }
166
+
167
+ // C#-style strings where "" escapes a quote.
168
+ function tokenAtString(stream, state) {
169
+ var next;
170
+ while ((next = stream.next()) != null) {
171
+ if (next == '"' && !stream.eat('"')) {
172
+ state.tokenize = null;
173
+ break;
174
+ }
175
+ }
176
+ return "string";
177
+ }
178
+
179
+ CodeMirror.defineMIME("text/x-csrc", {
180
+ name: "clike",
181
+ keywords: words(cKeywords),
182
+ blockKeywords: words("case do else for if switch while struct"),
183
+ atoms: words("null"),
184
+ hooks: {"#": cppHook}
185
+ });
186
+ CodeMirror.defineMIME("text/x-c++src", {
187
+ name: "clike",
188
+ keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try bool explicit new " +
189
+ "static_cast typeid catch operator template typename class friend private " +
190
+ "this using const_cast inline public throw virtual delete mutable protected " +
191
+ "wchar_t"),
192
+ blockKeywords: words("catch class do else finally for if struct switch try while"),
193
+ atoms: words("true false null"),
194
+ hooks: {"#": cppHook}
195
+ });
196
+ CodeMirror.defineMIME("text/x-java", {
197
+ name: "clike",
198
+ keywords: words("abstract assert boolean break byte case catch char class const continue default " +
199
+ "do double else enum extends final finally float for goto if implements import " +
200
+ "instanceof int interface long native new package private protected public " +
201
+ "return short static strictfp super switch synchronized this throw throws transient " +
202
+ "try void volatile while"),
203
+ blockKeywords: words("catch class do else finally for if switch try while"),
204
+ atoms: words("true false null"),
205
+ hooks: {
206
+ "@": function(stream, state) {
207
+ stream.eatWhile(/[\w\$_]/);
208
+ return "meta";
209
+ }
210
+ }
211
+ });
212
+ CodeMirror.defineMIME("text/x-csharp", {
213
+ name: "clike",
214
+ keywords: words("abstract as base bool break byte case catch char checked class const continue decimal" +
215
+ " default delegate do double else enum event explicit extern finally fixed float for" +
216
+ " foreach goto if implicit in int interface internal is lock long namespace new object" +
217
+ " operator out override params private protected public readonly ref return sbyte sealed short" +
218
+ " sizeof stackalloc static string struct switch this throw try typeof uint ulong unchecked" +
219
+ " unsafe ushort using virtual void volatile while add alias ascending descending dynamic from get" +
220
+ " global group into join let orderby partial remove select set value var yield"),
221
+ blockKeywords: words("catch class do else finally for foreach if struct switch try while"),
222
+ atoms: words("true false null"),
223
+ hooks: {
224
+ "@": function(stream, state) {
225
+ if (stream.eat('"')) {
226
+ state.tokenize = tokenAtString;
227
+ return tokenAtString(stream, state);
228
+ }
229
+ stream.eatWhile(/[\w\$_]/);
230
+ return "meta";
231
+ }
232
+ }
233
+ });
234
+ }());
functions/admin-page-class/js/codemirror/codemirror.css ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .CodeMirror {
2
+ line-height: 1em;
3
+ font-family: monospace;
4
+ }
5
+
6
+ .CodeMirror-scroll {
7
+ overflow: auto;
8
+ height: 300px;
9
+ /* This is needed to prevent an IE[67] bug where the scrolled content
10
+ is visible outside of the scrolling box. */
11
+ position: relative;
12
+ }
13
+
14
+ .CodeMirror-gutter {
15
+ position: absolute; left: 0; top: 0;
16
+ z-index: 10;
17
+ background-color: #f7f7f7;
18
+ border-right: 1px solid #eee;
19
+ min-width: 2em;
20
+ height: 100%;
21
+ }
22
+ .CodeMirror-gutter-text {
23
+ color: #aaa;
24
+ text-align: right;
25
+ padding: .4em .2em .4em .4em;
26
+ white-space: pre !important;
27
+ }
28
+ .CodeMirror-lines {
29
+ padding: .4em;
30
+ }
31
+
32
+ .CodeMirror pre {
33
+ -moz-border-radius: 0;
34
+ -webkit-border-radius: 0;
35
+ -o-border-radius: 0;
36
+ border-radius: 0;
37
+ border-width: 0; margin: 0; padding: 0; background: transparent;
38
+ font-family: inherit;
39
+ font-size: inherit;
40
+ padding: 0; margin: 0;
41
+ white-space: pre;
42
+ word-wrap: normal;
43
+ }
44
+
45
+ .CodeMirror-wrap pre {
46
+ word-wrap: break-word;
47
+ white-space: pre-wrap;
48
+ }
49
+ .CodeMirror-wrap .CodeMirror-scroll {
50
+ overflow-x: hidden;
51
+ }
52
+
53
+ .CodeMirror textarea {
54
+ outline: none !important;
55
+ }
56
+
57
+ .CodeMirror pre.CodeMirror-cursor {
58
+ z-index: 10;
59
+ position: absolute;
60
+ visibility: hidden;
61
+ border-left: 1px solid black;
62
+ }
63
+ .CodeMirror-focused pre.CodeMirror-cursor {
64
+ visibility: visible;
65
+ }
66
+
67
+ div.CodeMirror-selected { background: #d9d9d9; }
68
+ .CodeMirror-focused div.CodeMirror-selected { background: #d7d4f0; }
69
+
70
+ .CodeMirror-searching {
71
+ background: #ffa;
72
+ background: rgba(255, 255, 0, .4);
73
+ }
74
+
75
+ /* Default theme */
76
+
77
+ .cm-s-default span.cm-keyword {color: #708;}
78
+ .cm-s-default span.cm-atom {color: #219;}
79
+ .cm-s-default span.cm-number {color: #164;}
80
+ .cm-s-default span.cm-def {color: #00f;}
81
+ .cm-s-default span.cm-variable {color: black;}
82
+ .cm-s-default span.cm-variable-2 {color: #05a;}
83
+ .cm-s-default span.cm-variable-3 {color: #085;}
84
+ .cm-s-default span.cm-property {color: black;}
85
+ .cm-s-default span.cm-operator {color: black;}
86
+ .cm-s-default span.cm-comment {color: #a50;}
87
+ .cm-s-default span.cm-string {color: #a11;}
88
+ .cm-s-default span.cm-string-2 {color: #f50;}
89
+ .cm-s-default span.cm-meta {color: #555;}
90
+ .cm-s-default span.cm-error {color: #f00;}
91
+ .cm-s-default span.cm-qualifier {color: #555;}
92
+ .cm-s-default span.cm-builtin {color: #30a;}
93
+ .cm-s-default span.cm-bracket {color: #cc7;}
94
+ .cm-s-default span.cm-tag {color: #170;}
95
+ .cm-s-default span.cm-attribute {color: #00c;}
96
+ .cm-s-default span.cm-header {color: #a0a;}
97
+ .cm-s-default span.cm-quote {color: #090;}
98
+ .cm-s-default span.cm-hr {color: #999;}
99
+ .cm-s-default span.cm-link {color: #00c;}
100
+
101
+ span.cm-header, span.cm-strong {font-weight: bold;}
102
+ span.cm-em {font-style: italic;}
103
+ span.cm-emstrong {font-style: italic; font-weight: bold;}
104
+ span.cm-link {text-decoration: underline;}
105
+
106
+ div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
107
+ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
functions/admin-page-class/js/codemirror/codemirror.js ADDED
@@ -0,0 +1,2817 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // CodeMirror version 2.21
2
+ //
3
+ // All functions that need access to the editor's state live inside
4
+ // the CodeMirror function. Below that, at the bottom of the file,
5
+ // some utilities are defined.
6
+
7
+ // CodeMirror is the only global var we claim
8
+ var CodeMirror = (function() {
9
+ // This is the function that produces an editor instance. It's
10
+ // closure is used to store the editor state.
11
+ function CodeMirror(place, givenOptions) {
12
+ // Determine effective options based on given values and defaults.
13
+ var options = {}, defaults = CodeMirror.defaults;
14
+ for (var opt in defaults)
15
+ if (defaults.hasOwnProperty(opt))
16
+ options[opt] = (givenOptions && givenOptions.hasOwnProperty(opt) ? givenOptions : defaults)[opt];
17
+
18
+ var targetDocument = options["document"];
19
+ // The element in which the editor lives.
20
+ var wrapper = targetDocument.createElement("div");
21
+ wrapper.className = "CodeMirror" + (options.lineWrapping ? " CodeMirror-wrap" : "");
22
+ // This mess creates the base DOM structure for the editor.
23
+ wrapper.innerHTML =
24
+ '<div style="overflow: hidden; position: relative; width: 3px; height: 0px;">' + // Wraps and hides input textarea
25
+ '<textarea style="position: absolute; padding: 0; width: 1px; height: 1em" wrap="off" ' +
26
+ 'autocorrect="off" autocapitalize="off"></textarea></div>' +
27
+ '<div class="CodeMirror-scroll" tabindex="-1">' +
28
+ '<div style="position: relative">' + // Set to the height of the text, causes scrolling
29
+ '<div style="position: relative">' + // Moved around its parent to cover visible view
30
+ '<div class="CodeMirror-gutter"><div class="CodeMirror-gutter-text"></div></div>' +
31
+ // Provides positioning relative to (visible) text origin
32
+ '<div class="CodeMirror-lines"><div style="position: relative; z-index: 0">' +
33
+ '<div style="position: absolute; width: 100%; height: 0; overflow: hidden; visibility: hidden; outline: 5px auto none"></div>' +
34
+ '<pre class="CodeMirror-cursor">&#160;</pre>' + // Absolutely positioned blinky cursor
35
+ '<div style="position: relative; z-index: -1"></div><div></div>' + // DIVs containing the selection and the actual code
36
+ '</div></div></div></div></div>';
37
+ if (place.appendChild) place.appendChild(wrapper); else place(wrapper);
38
+ // I've never seen more elegant code in my life.
39
+ var inputDiv = wrapper.firstChild, input = inputDiv.firstChild,
40
+ scroller = wrapper.lastChild, code = scroller.firstChild,
41
+ mover = code.firstChild, gutter = mover.firstChild, gutterText = gutter.firstChild,
42
+ lineSpace = gutter.nextSibling.firstChild, measure = lineSpace.firstChild,
43
+ cursor = measure.nextSibling, selectionDiv = cursor.nextSibling,
44
+ lineDiv = selectionDiv.nextSibling;
45
+ themeChanged();
46
+ // Needed to hide big blue blinking cursor on Mobile Safari
47
+ if (ios) input.style.width = "0px";
48
+ if (!webkit) lineSpace.draggable = true;
49
+ lineSpace.style.outline = "none";
50
+ if (options.tabindex != null) input.tabIndex = options.tabindex;
51
+ if (!options.gutter && !options.lineNumbers) gutter.style.display = "none";
52
+
53
+ // Check for problem with IE innerHTML not working when we have a
54
+ // P (or similar) parent node.
55
+ try { stringWidth("x"); }
56
+ catch (e) {
57
+ if (e.message.match(/runtime/i))
58
+ e = new Error("A CodeMirror inside a P-style element does not work in Internet Explorer. (innerHTML bug)");
59
+ throw e;
60
+ }
61
+
62
+ // Delayed object wrap timeouts, making sure only one is active. blinker holds an interval.
63
+ var poll = new Delayed(), highlight = new Delayed(), blinker;
64
+
65
+ // mode holds a mode API object. doc is the tree of Line objects,
66
+ // work an array of lines that should be parsed, and history the
67
+ // undo history (instance of History constructor).
68
+ var mode, doc = new BranchChunk([new LeafChunk([new Line("")])]), work, focused;
69
+ loadMode();
70
+ // The selection. These are always maintained to point at valid
71
+ // positions. Inverted is used to remember that the user is
72
+ // selecting bottom-to-top.
73
+ var sel = {from: {line: 0, ch: 0}, to: {line: 0, ch: 0}, inverted: false};
74
+ // Selection-related flags. shiftSelecting obviously tracks
75
+ // whether the user is holding shift.
76
+ var shiftSelecting, lastClick, lastDoubleClick, lastScrollPos = 0, draggingText,
77
+ overwrite = false, suppressEdits = false;
78
+ // Variables used by startOperation/endOperation to track what
79
+ // happened during the operation.
80
+ var updateInput, userSelChange, changes, textChanged, selectionChanged, leaveInputAlone,
81
+ gutterDirty, callbacks;
82
+ // Current visible range (may be bigger than the view window).
83
+ var displayOffset = 0, showingFrom = 0, showingTo = 0, lastSizeC = 0;
84
+ // bracketHighlighted is used to remember that a backet has been
85
+ // marked.
86
+ var bracketHighlighted;
87
+ // Tracks the maximum line length so that the horizontal scrollbar
88
+ // can be kept static when scrolling.
89
+ var maxLine = "", maxWidth, tabText = computeTabText();
90
+
91
+ // Initialize the content.
92
+ operation(function(){setValue(options.value || ""); updateInput = false;})();
93
+ var history = new History();
94
+
95
+ // Register our event handlers.
96
+ connect(scroller, "mousedown", operation(onMouseDown));
97
+ connect(scroller, "dblclick", operation(onDoubleClick));
98
+ connect(lineSpace, "dragstart", onDragStart);
99
+ connect(lineSpace, "selectstart", e_preventDefault);
100
+ // Gecko browsers fire contextmenu *after* opening the menu, at
101
+ // which point we can't mess with it anymore. Context menu is
102
+ // handled in onMouseDown for Gecko.
103
+ if (!gecko) connect(scroller, "contextmenu", onContextMenu);
104
+ connect(scroller, "scroll", function() {
105
+ lastScrollPos = scroller.scrollTop;
106
+ updateDisplay([]);
107
+ if (options.fixedGutter) gutter.style.left = scroller.scrollLeft + "px";
108
+ if (options.onScroll) options.onScroll(instance);
109
+ });
110
+ connect(window, "resize", function() {updateDisplay(true);});
111
+ connect(input, "keyup", operation(onKeyUp));
112
+ connect(input, "input", fastPoll);
113
+ connect(input, "keydown", operation(onKeyDown));
114
+ connect(input, "keypress", operation(onKeyPress));
115
+ connect(input, "focus", onFocus);
116
+ connect(input, "blur", onBlur);
117
+
118
+ connect(scroller, "dragenter", e_stop);
119
+ connect(scroller, "dragover", e_stop);
120
+ connect(scroller, "drop", operation(onDrop));
121
+ connect(scroller, "paste", function(){focusInput(); fastPoll();});
122
+ connect(input, "paste", fastPoll);
123
+ connect(input, "cut", operation(function(){
124
+ if (!options.readOnly) replaceSelection("");
125
+ }));
126
+
127
+ // IE throws unspecified error in certain cases, when
128
+ // trying to access activeElement before onload
129
+ var hasFocus; try { hasFocus = (targetDocument.activeElement == input); } catch(e) { }
130
+ if (hasFocus) setTimeout(onFocus, 20);
131
+ else onBlur();
132
+
133
+ function isLine(l) {return l >= 0 && l < doc.size;}
134
+ // The instance object that we'll return. Mostly calls out to
135
+ // local functions in the CodeMirror function. Some do some extra
136
+ // range checking and/or clipping. operation is used to wrap the
137
+ // call so that changes it makes are tracked, and the display is
138
+ // updated afterwards.
139
+ var instance = wrapper.CodeMirror = {
140
+ getValue: getValue,
141
+ setValue: operation(setValue),
142
+ getSelection: getSelection,
143
+ replaceSelection: operation(replaceSelection),
144
+ focus: function(){focusInput(); onFocus(); fastPoll();},
145
+ setOption: function(option, value) {
146
+ var oldVal = options[option];
147
+ options[option] = value;
148
+ if (option == "mode" || option == "indentUnit") loadMode();
149
+ else if (option == "readOnly" && value == "nocursor") {onBlur(); input.blur();}
150
+ else if (option == "readOnly" && !value) {resetInput(true);}
151
+ else if (option == "theme") themeChanged();
152
+ else if (option == "lineWrapping" && oldVal != value) operation(wrappingChanged)();
153
+ else if (option == "tabSize") operation(tabsChanged)();
154
+ if (option == "lineNumbers" || option == "gutter" || option == "firstLineNumber" || option == "theme")
155
+ updateDisplay(true);
156
+ },
157
+ getOption: function(option) {return options[option];},
158
+ undo: operation(undo),
159
+ redo: operation(redo),
160
+ indentLine: operation(function(n, dir) {
161
+ if (typeof dir != "string") {
162
+ if (dir == null) dir = options.smartIndent ? "smart" : "prev";
163
+ else dir = dir ? "add" : "subtract";
164
+ }
165
+ if (isLine(n)) indentLine(n, dir);
166
+ }),
167
+ indentSelection: operation(indentSelected),
168
+ historySize: function() {return {undo: history.done.length, redo: history.undone.length};},
169
+ clearHistory: function() {history = new History();},
170
+ matchBrackets: operation(function(){matchBrackets(true);}),
171
+ getTokenAt: operation(function(pos) {
172
+ pos = clipPos(pos);
173
+ return getLine(pos.line).getTokenAt(mode, getStateBefore(pos.line), pos.ch);
174
+ }),
175
+ getStateAfter: function(line) {
176
+ line = clipLine(line == null ? doc.size - 1: line);
177
+ return getStateBefore(line + 1);
178
+ },
179
+ cursorCoords: function(start){
180
+ if (start == null) start = sel.inverted;
181
+ return pageCoords(start ? sel.from : sel.to);
182
+ },
183
+ charCoords: function(pos){return pageCoords(clipPos(pos));},
184
+ coordsChar: function(coords) {
185
+ var off = eltOffset(lineSpace);
186
+ return coordsChar(coords.x - off.left, coords.y - off.top);
187
+ },
188
+ markText: operation(markText),
189
+ setBookmark: setBookmark,
190
+ setMarker: operation(addGutterMarker),
191
+ clearMarker: operation(removeGutterMarker),
192
+ setLineClass: operation(setLineClass),
193
+ hideLine: operation(function(h) {return setLineHidden(h, true);}),
194
+ showLine: operation(function(h) {return setLineHidden(h, false);}),
195
+ onDeleteLine: function(line, f) {
196
+ if (typeof line == "number") {
197
+ if (!isLine(line)) return null;
198
+ line = getLine(line);
199
+ }
200
+ (line.handlers || (line.handlers = [])).push(f);
201
+ return line;
202
+ },
203
+ lineInfo: lineInfo,
204
+ addWidget: function(pos, node, scroll, vert, horiz) {
205
+ pos = localCoords(clipPos(pos));
206
+ var top = pos.yBot, left = pos.x;
207
+ node.style.position = "absolute";
208
+ code.appendChild(node);
209
+ if (vert == "over") top = pos.y;
210
+ else if (vert == "near") {
211
+ var vspace = Math.max(scroller.offsetHeight, doc.height * textHeight()),
212
+ hspace = Math.max(code.clientWidth, lineSpace.clientWidth) - paddingLeft();
213
+ if (pos.yBot + node.offsetHeight > vspace && pos.y > node.offsetHeight)
214
+ top = pos.y - node.offsetHeight;
215
+ if (left + node.offsetWidth > hspace)
216
+ left = hspace - node.offsetWidth;
217
+ }
218
+ node.style.top = (top + paddingTop()) + "px";
219
+ node.style.left = node.style.right = "";
220
+ if (horiz == "right") {
221
+ left = code.clientWidth - node.offsetWidth;
222
+ node.style.right = "0px";
223
+ } else {
224
+ if (horiz == "left") left = 0;
225
+ else if (horiz == "middle") left = (code.clientWidth - node.offsetWidth) / 2;
226
+ node.style.left = (left + paddingLeft()) + "px";
227
+ }
228
+ if (scroll)
229
+ scrollIntoView(left, top, left + node.offsetWidth, top + node.offsetHeight);
230
+ },
231
+
232
+ lineCount: function() {return doc.size;},
233
+ clipPos: clipPos,
234
+ getCursor: function(start) {
235
+ if (start == null) start = sel.inverted;
236
+ return copyPos(start ? sel.from : sel.to);
237
+ },
238
+ somethingSelected: function() {return !posEq(sel.from, sel.to);},
239
+ setCursor: operation(function(line, ch, user) {
240
+ if (ch == null && typeof line.line == "number") setCursor(line.line, line.ch, user);
241
+ else setCursor(line, ch, user);
242
+ }),
243
+ setSelection: operation(function(from, to, user) {
244
+ (user ? setSelectionUser : setSelection)(clipPos(from), clipPos(to || from));
245
+ }),
246
+ getLine: function(line) {if (isLine(line)) return getLine(line).text;},
247
+ getLineHandle: function(line) {if (isLine(line)) return getLine(line);},
248
+ setLine: operation(function(line, text) {
249
+ if (isLine(line)) replaceRange(text, {line: line, ch: 0}, {line: line, ch: getLine(line).text.length});
250
+ }),
251
+ removeLine: operation(function(line) {
252
+ if (isLine(line)) replaceRange("", {line: line, ch: 0}, clipPos({line: line+1, ch: 0}));
253
+ }),
254
+ replaceRange: operation(replaceRange),
255
+ getRange: function(from, to) {return getRange(clipPos(from), clipPos(to));},
256
+
257
+ execCommand: function(cmd) {return commands[cmd](instance);},
258
+ // Stuff used by commands, probably not much use to outside code.
259
+ moveH: operation(moveH),
260
+ deleteH: operation(deleteH),
261
+ moveV: operation(moveV),
262
+ toggleOverwrite: function() {overwrite = !overwrite;},
263
+
264
+ posFromIndex: function(off) {
265
+ var lineNo = 0, ch;
266
+ doc.iter(0, doc.size, function(line) {
267
+ var sz = line.text.length + 1;
268
+ if (sz > off) { ch = off; return true; }
269
+ off -= sz;
270
+ ++lineNo;
271
+ });
272
+ return clipPos({line: lineNo, ch: ch});
273
+ },
274
+ indexFromPos: function (coords) {
275
+ if (coords.line < 0 || coords.ch < 0) return 0;
276
+ var index = coords.ch;
277
+ doc.iter(0, coords.line, function (line) {
278
+ index += line.text.length + 1;
279
+ });
280
+ return index;
281
+ },
282
+ scrollTo: function(x, y) {
283
+ if (x != null) scroller.scrollTop = x;
284
+ if (y != null) scroller.scrollLeft = y;
285
+ updateDisplay([]);
286
+ },
287
+
288
+ operation: function(f){return operation(f)();},
289
+ refresh: function(){
290
+ updateDisplay(true);
291
+ if (scroller.scrollHeight > lastScrollPos)
292
+ scroller.scrollTop = lastScrollPos;
293
+ },
294
+ getInputField: function(){return input;},
295
+ getWrapperElement: function(){return wrapper;},
296
+ getScrollerElement: function(){return scroller;},
297
+ getGutterElement: function(){return gutter;}
298
+ };
299
+
300
+ function getLine(n) { return getLineAt(doc, n); }
301
+ function updateLineHeight(line, height) {
302
+ gutterDirty = true;
303
+ var diff = height - line.height;
304
+ for (var n = line; n; n = n.parent) n.height += diff;
305
+ }
306
+
307
+ function setValue(code) {
308
+ var top = {line: 0, ch: 0};
309
+ updateLines(top, {line: doc.size - 1, ch: getLine(doc.size-1).text.length},
310
+ splitLines(code), top, top);
311
+ updateInput = true;
312
+ }
313
+ function getValue(code) {
314
+ var text = [];
315
+ doc.iter(0, doc.size, function(line) { text.push(line.text); });
316
+ return text.join("\n");
317
+ }
318
+
319
+ function onMouseDown(e) {
320
+ setShift(e_prop(e, "shiftKey"));
321
+ // Check whether this is a click in a widget
322
+ for (var n = e_target(e); n != wrapper; n = n.parentNode)
323
+ if (n.parentNode == code && n != mover) return;
324
+
325
+ // See if this is a click in the gutter
326
+ for (var n = e_target(e); n != wrapper; n = n.parentNode)
327
+ if (n.parentNode == gutterText) {
328
+ if (options.onGutterClick)
329
+ options.onGutterClick(instance, indexOf(gutterText.childNodes, n) + showingFrom, e);
330
+ return e_preventDefault(e);
331
+ }
332
+
333
+ var start = posFromMouse(e);
334
+
335
+ switch (e_button(e)) {
336
+ case 3:
337
+ if (gecko && !mac) onContextMenu(e);
338
+ return;
339
+ case 2:
340
+ if (start) setCursor(start.line, start.ch, true);
341
+ return;
342
+ }
343
+ // For button 1, if it was clicked inside the editor
344
+ // (posFromMouse returning non-null), we have to adjust the
345
+ // selection.
346
+ if (!start) {if (e_target(e) == scroller) e_preventDefault(e); return;}
347
+
348
+ if (!focused) onFocus();
349
+
350
+ var now = +new Date;
351
+ if (lastDoubleClick && lastDoubleClick.time > now - 400 && posEq(lastDoubleClick.pos, start)) {
352
+ e_preventDefault(e);
353
+ setTimeout(focusInput, 20);
354
+ return selectLine(start.line);
355
+ } else if (lastClick && lastClick.time > now - 400 && posEq(lastClick.pos, start)) {
356
+ lastDoubleClick = {time: now, pos: start};
357
+ e_preventDefault(e);
358
+ return selectWordAt(start);
359
+ } else { lastClick = {time: now, pos: start}; }
360
+
361
+ var last = start, going;
362
+ if (dragAndDrop && !options.readOnly && !posEq(sel.from, sel.to) &&
363
+ !posLess(start, sel.from) && !posLess(sel.to, start)) {
364
+ // Let the drag handler handle this.
365
+ if (webkit) lineSpace.draggable = true;
366
+ var up = connect(targetDocument, "mouseup", operation(function(e2) {
367
+ if (webkit) lineSpace.draggable = false;
368
+ draggingText = false;
369
+ up();
370
+ if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
371
+ e_preventDefault(e2);
372
+ setCursor(start.line, start.ch, true);
373
+ focusInput();
374
+ }
375
+ }), true);
376
+ draggingText = true;
377
+ return;
378
+ }
379
+ e_preventDefault(e);
380
+ setCursor(start.line, start.ch, true);
381
+
382
+ function extend(e) {
383
+ var cur = posFromMouse(e, true);
384
+ if (cur && !posEq(cur, last)) {
385
+ if (!focused) onFocus();
386
+ last = cur;
387
+ setSelectionUser(start, cur);
388
+ updateInput = false;
389
+ var visible = visibleLines();
390
+ if (cur.line >= visible.to || cur.line < visible.from)
391
+ going = setTimeout(operation(function(){extend(e);}), 150);
392
+ }
393
+ }
394
+
395
+ var move = connect(targetDocument, "mousemove", operation(function(e) {
396
+ clearTimeout(going);
397
+ e_preventDefault(e);
398
+ extend(e);
399
+ }), true);
400
+ var up = connect(targetDocument, "mouseup", operation(function(e) {
401
+ clearTimeout(going);
402
+ var cur = posFromMouse(e);
403
+ if (cur) setSelectionUser(start, cur);
404
+ e_preventDefault(e);
405
+ focusInput();
406
+ updateInput = true;
407
+ move(); up();
408
+ }), true);
409
+ }
410
+ function onDoubleClick(e) {
411
+ for (var n = e_target(e); n != wrapper; n = n.parentNode)
412
+ if (n.parentNode == gutterText) return e_preventDefault(e);
413
+ var start = posFromMouse(e);
414
+ if (!start) return;
415
+ lastDoubleClick = {time: +new Date, pos: start};
416
+ e_preventDefault(e);
417
+ selectWordAt(start);
418
+ }
419
+ function onDrop(e) {
420
+ e.preventDefault();
421
+ var pos = posFromMouse(e, true), files = e.dataTransfer.files;
422
+ if (!pos || options.readOnly) return;
423
+ if (files && files.length && window.FileReader && window.File) {
424
+ function loadFile(file, i) {
425
+ var reader = new FileReader;
426
+ reader.onload = function() {
427
+ text[i] = reader.result;
428
+ if (++read == n) {
429
+ pos = clipPos(pos);
430
+ operation(function() {
431
+ var end = replaceRange(text.join(""), pos, pos);
432
+ setSelectionUser(pos, end);
433
+ })();
434
+ }
435
+ };
436
+ reader.readAsText(file);
437
+ }
438
+ var n = files.length, text = Array(n), read = 0;
439
+ for (var i = 0; i < n; ++i) loadFile(files[i], i);
440
+ }
441
+ else {
442
+ try {
443
+ var text = e.dataTransfer.getData("Text");
444
+ if (text) {
445
+ var curFrom = sel.from, curTo = sel.to;
446
+ setSelectionUser(pos, pos);
447
+ if (draggingText) replaceRange("", curFrom, curTo);
448
+ replaceSelection(text);
449
+ focusInput();
450
+ }
451
+ }
452
+ catch(e){}
453
+ }
454
+ }
455
+ function onDragStart(e) {
456
+ var txt = getSelection();
457
+ // This will reset escapeElement
458
+ htmlEscape(txt);
459
+ e.dataTransfer.setDragImage(escapeElement, 0, 0);
460
+ e.dataTransfer.setData("Text", txt);
461
+ }
462
+ function handleKeyBinding(e) {
463
+ var name = keyNames[e_prop(e, "keyCode")], next = keyMap[options.keyMap].auto, bound, dropShift;
464
+ function handleNext() {
465
+ return next.call ? next.call(null, instance) : next;
466
+ }
467
+ if (name == null || e.altGraphKey) {
468
+ if (next) options.keyMap = handleNext();
469
+ return null;
470
+ }
471
+ if (e_prop(e, "altKey")) name = "Alt-" + name;
472
+ if (e_prop(e, "ctrlKey")) name = "Ctrl-" + name;
473
+ if (e_prop(e, "metaKey")) name = "Cmd-" + name;
474
+ if (e_prop(e, "shiftKey") &&
475
+ (bound = lookupKey("Shift-" + name, options.extraKeys, options.keyMap))) {
476
+ dropShift = true;
477
+ } else {
478
+ bound = lookupKey(name, options.extraKeys, options.keyMap);
479
+ }
480
+ if (typeof bound == "string") {
481
+ if (commands.propertyIsEnumerable(bound)) bound = commands[bound];
482
+ else bound = null;
483
+ }
484
+ if (next && (bound || !isModifierKey(e))) options.keyMap = handleNext();
485
+ if (!bound) return false;
486
+ var prevShift = shiftSelecting;
487
+ try {
488
+ if (options.readOnly) suppressEdits = true;
489
+ if (dropShift) shiftSelecting = null;
490
+ bound(instance);
491
+ } finally {
492
+ shiftSelecting = prevShift;
493
+ suppressEdits = false;
494
+ }
495
+ e_preventDefault(e);
496
+ return true;
497
+ }
498
+ var lastStoppedKey = null;
499
+ function onKeyDown(e) {
500
+ if (!focused) onFocus();
501
+ if (ie && e.keyCode == 27) { e.returnValue = false; }
502
+ if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;
503
+ var code = e_prop(e, "keyCode");
504
+ // IE does strange things with escape.
505
+ setShift(code == 16 || e_prop(e, "shiftKey"));
506
+ // First give onKeyEvent option a chance to handle this.
507
+ var handled = handleKeyBinding(e);
508
+ if (window.opera) {
509
+ lastStoppedKey = handled ? code : null;
510
+ // Opera has no cut event... we try to at least catch the key combo
511
+ if (!handled && code == 88 && e_prop(e, mac ? "metaKey" : "ctrlKey"))
512
+ replaceSelection("");
513
+ }
514
+ }
515
+ function onKeyPress(e) {
516
+ var keyCode = e_prop(e, "keyCode"), charCode = e_prop(e, "charCode");
517
+ if (window.opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
518
+ if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;
519
+ if (window.opera && !e.which && handleKeyBinding(e)) return;
520
+ if (options.electricChars && mode.electricChars && options.smartIndent && !options.readOnly) {
521
+ var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
522
+ if (mode.electricChars.indexOf(ch) > -1)
523
+ setTimeout(operation(function() {indentLine(sel.to.line, "smart");}), 75);
524
+ }
525
+ fastPoll();
526
+ }
527
+ function onKeyUp(e) {
528
+ if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;
529
+ if (e_prop(e, "keyCode") == 16) shiftSelecting = null;
530
+ }
531
+
532
+ function onFocus() {
533
+ if (options.readOnly == "nocursor") return;
534
+ if (!focused) {
535
+ if (options.onFocus) options.onFocus(instance);
536
+ focused = true;
537
+ if (wrapper.className.search(/\bCodeMirror-focused\b/) == -1)
538
+ wrapper.className += " CodeMirror-focused";
539
+ if (!leaveInputAlone) resetInput(true);
540
+ }
541
+ slowPoll();
542
+ restartBlink();
543
+ }
544
+ function onBlur() {
545
+ if (focused) {
546
+ if (options.onBlur) options.onBlur(instance);
547
+ focused = false;
548
+ if (bracketHighlighted)
549
+ operation(function(){
550
+ if (bracketHighlighted) { bracketHighlighted(); bracketHighlighted = null; }
551
+ })();
552
+ wrapper.className = wrapper.className.replace(" CodeMirror-focused", "");
553
+ }
554
+ clearInterval(blinker);
555
+ setTimeout(function() {if (!focused) shiftSelecting = null;}, 150);
556
+ }
557
+
558
+ // Replace the range from from to to by the strings in newText.
559
+ // Afterwards, set the selection to selFrom, selTo.
560
+ function updateLines(from, to, newText, selFrom, selTo) {
561
+ if (suppressEdits) return;
562
+ if (history) {
563
+ var old = [];
564
+ doc.iter(from.line, to.line + 1, function(line) { old.push(line.text); });
565
+ history.addChange(from.line, newText.length, old);
566
+ while (history.done.length > options.undoDepth) history.done.shift();
567
+ }
568
+ updateLinesNoUndo(from, to, newText, selFrom, selTo);
569
+ }
570
+ function unredoHelper(from, to, dir) {
571
+ var set = from.pop(), len = set ? set.length : 0, out = [];
572
+ for (var i = dir > 0 ? 0 : len - 1, e = dir > 0 ? len : -1; i != e; i += dir) {
573
+ var change = set[i];
574
+ var replaced = [], end = change.start + change.added;
575
+ doc.iter(change.start, end, function(line) { replaced.push(line.text); });
576
+ out.push({start: change.start, added: change.old.length, old: replaced});
577
+ var pos = clipPos({line: change.start + change.old.length - 1,
578
+ ch: editEnd(replaced[replaced.length-1], change.old[change.old.length-1])});
579
+ updateLinesNoUndo({line: change.start, ch: 0}, {line: end - 1, ch: getLine(end-1).text.length}, change.old, pos, pos);
580
+ }
581
+ updateInput = true;
582
+ to.push(out);
583
+ }
584
+ function undo() {unredoHelper(history.done, history.undone, -1);}
585
+ function redo() {unredoHelper(history.undone, history.done, 1);}
586
+
587
+ function updateLinesNoUndo(from, to, newText, selFrom, selTo) {
588
+ if (suppressEdits) return;
589
+ var recomputeMaxLength = false, maxLineLength = maxLine.length;
590
+ if (!options.lineWrapping)
591
+ doc.iter(from.line, to.line, function(line) {
592
+ if (line.text.length == maxLineLength) {recomputeMaxLength = true; return true;}
593
+ });
594
+ if (from.line != to.line || newText.length > 1) gutterDirty = true;
595
+
596
+ var nlines = to.line - from.line, firstLine = getLine(from.line), lastLine = getLine(to.line);
597
+ // First adjust the line structure, taking some care to leave highlighting intact.
598
+ if (from.ch == 0 && to.ch == 0 && newText[newText.length - 1] == "") {
599
+ // This is a whole-line replace. Treated specially to make
600
+ // sure line objects move the way they are supposed to.
601
+ var added = [], prevLine = null;
602
+ if (from.line) {
603
+ prevLine = getLine(from.line - 1);
604
+ prevLine.fixMarkEnds(lastLine);
605
+ } else lastLine.fixMarkStarts();
606
+ for (var i = 0, e = newText.length - 1; i < e; ++i)
607
+ added.push(Line.inheritMarks(newText[i], prevLine));
608
+ if (nlines) doc.remove(from.line, nlines, callbacks);
609
+ if (added.length) doc.insert(from.line, added);
610
+ } else if (firstLine == lastLine) {
611
+ if (newText.length == 1)
612
+ firstLine.replace(from.ch, to.ch, newText[0]);
613
+ else {
614
+ lastLine = firstLine.split(to.ch, newText[newText.length-1]);
615
+ firstLine.replace(from.ch, null, newText[0]);
616
+ firstLine.fixMarkEnds(lastLine);
617
+ var added = [];
618
+ for (var i = 1, e = newText.length - 1; i < e; ++i)
619
+ added.push(Line.inheritMarks(newText[i], firstLine));
620
+ added.push(lastLine);
621
+ doc.insert(from.line + 1, added);
622
+ }
623
+ } else if (newText.length == 1) {
624
+ firstLine.replace(from.ch, null, newText[0]);
625
+ lastLine.replace(null, to.ch, "");
626
+ firstLine.append(lastLine);
627
+ doc.remove(from.line + 1, nlines, callbacks);
628
+ } else {
629
+ var added = [];
630
+ firstLine.replace(from.ch, null, newText[0]);
631
+ lastLine.replace(null, to.ch, newText[newText.length-1]);
632
+ firstLine.fixMarkEnds(lastLine);
633
+ for (var i = 1, e = newText.length - 1; i < e; ++i)
634
+ added.push(Line.inheritMarks(newText[i], firstLine));
635
+ if (nlines > 1) doc.remove(from.line + 1, nlines - 1, callbacks);
636
+ doc.insert(from.line + 1, added);
637
+ }
638
+ if (options.lineWrapping) {
639
+ var perLine = scroller.clientWidth / charWidth() - 3;
640
+ doc.iter(from.line, from.line + newText.length, function(line) {
641
+ if (line.hidden) return;
642
+ var guess = Math.ceil(line.text.length / perLine) || 1;
643
+ if (guess != line.height) updateLineHeight(line, guess);
644
+ });
645
+ } else {
646
+ doc.iter(from.line, i + newText.length, function(line) {
647
+ var l = line.text;
648
+ if (l.length > maxLineLength) {
649
+ maxLine = l; maxLineLength = l.length; maxWidth = null;
650
+ recomputeMaxLength = false;
651
+ }
652
+ });
653
+ if (recomputeMaxLength) {
654
+ maxLineLength = 0; maxLine = ""; maxWidth = null;
655
+ doc.iter(0, doc.size, function(line) {
656
+ var l = line.text;
657
+ if (l.length > maxLineLength) {
658
+ maxLineLength = l.length; maxLine = l;
659
+ }
660
+ });
661
+ }
662
+ }
663
+
664
+ // Add these lines to the work array, so that they will be
665
+ // highlighted. Adjust work lines if lines were added/removed.
666
+ var newWork = [], lendiff = newText.length - nlines - 1;
667
+ for (var i = 0, l = work.length; i < l; ++i) {
668
+ var task = work[i];
669
+ if (task < from.line) newWork.push(task);
670
+ else if (task > to.line) newWork.push(task + lendiff);
671
+ }
672
+ var hlEnd = from.line + Math.min(newText.length, 500);
673
+ highlightLines(from.line, hlEnd);
674
+ newWork.push(hlEnd);
675
+ work = newWork;
676
+ startWorker(100);
677
+ // Remember that these lines changed, for updating the display
678
+ changes.push({from: from.line, to: to.line + 1, diff: lendiff});
679
+ var changeObj = {from: from, to: to, text: newText};
680
+ if (textChanged) {
681
+ for (var cur = textChanged; cur.next; cur = cur.next) {}
682
+ cur.next = changeObj;
683
+ } else textChanged = changeObj;
684
+
685
+ // Update the selection
686
+ function updateLine(n) {return n <= Math.min(to.line, to.line + lendiff) ? n : n + lendiff;}
687
+ setSelection(selFrom, selTo, updateLine(sel.from.line), updateLine(sel.to.line));
688
+
689
+ // Make sure the scroll-size div has the correct height.
690
+ if (scroller.clientHeight)
691
+ code.style.height = (doc.height * textHeight() + 2 * paddingTop()) + "px";
692
+ }
693
+
694
+ function replaceRange(code, from, to) {
695
+ from = clipPos(from);
696
+ if (!to) to = from; else to = clipPos(to);
697
+ code = splitLines(code);
698
+ function adjustPos(pos) {
699
+ if (posLess(pos, from)) return pos;
700
+ if (!posLess(to, pos)) return end;
701
+ var line = pos.line + code.length - (to.line - from.line) - 1;
702
+ var ch = pos.ch;
703
+ if (pos.line == to.line)
704
+ ch += code[code.length-1].length - (to.ch - (to.line == from.line ? from.ch : 0));
705
+ return {line: line, ch: ch};
706
+ }
707
+ var end;
708
+ replaceRange1(code, from, to, function(end1) {
709
+ end = end1;
710
+ return {from: adjustPos(sel.from), to: adjustPos(sel.to)};
711
+ });
712
+ return end;
713
+ }
714
+ function replaceSelection(code, collapse) {
715
+ replaceRange1(splitLines(code), sel.from, sel.to, function(end) {
716
+ if (collapse == "end") return {from: end, to: end};
717
+ else if (collapse == "start") return {from: sel.from, to: sel.from};
718
+ else return {from: sel.from, to: end};
719
+ });
720
+ }
721
+ function replaceRange1(code, from, to, computeSel) {
722
+ var endch = code.length == 1 ? code[0].length + from.ch : code[code.length-1].length;
723
+ var newSel = computeSel({line: from.line + code.length - 1, ch: endch});
724
+ updateLines(from, to, code, newSel.from, newSel.to);
725
+ }
726
+
727
+ function getRange(from, to) {
728
+ var l1 = from.line, l2 = to.line;
729
+ if (l1 == l2) return getLine(l1).text.slice(from.ch, to.ch);
730
+ var code = [getLine(l1).text.slice(from.ch)];
731
+ doc.iter(l1 + 1, l2, function(line) { code.push(line.text); });
732
+ code.push(getLine(l2).text.slice(0, to.ch));
733
+ return code.join("\n");
734
+ }
735
+ function getSelection() {
736
+ return getRange(sel.from, sel.to);
737
+ }
738
+
739
+ var pollingFast = false; // Ensures slowPoll doesn't cancel fastPoll
740
+ function slowPoll() {
741
+ if (pollingFast) return;
742
+ poll.set(options.pollInterval, function() {
743
+ startOperation();
744
+ readInput();
745
+ if (focused) slowPoll();
746
+ endOperation();
747
+ });
748
+ }
749
+ function fastPoll() {
750
+ var missed = false;
751
+ pollingFast = true;
752
+ function p() {
753
+ startOperation();
754
+ var changed = readInput();
755
+ if (!changed && !missed) {missed = true; poll.set(60, p);}
756
+ else {pollingFast = false; slowPoll();}
757
+ endOperation();
758
+ }
759
+ poll.set(20, p);
760
+ }
761
+
762
+ // Previnput is a hack to work with IME. If we reset the textarea
763
+ // on every change, that breaks IME. So we look for changes
764
+ // compared to the previous content instead. (Modern browsers have
765
+ // events that indicate IME taking place, but these are not widely
766
+ // supported or compatible enough yet to rely on.)
767
+ var prevInput = "";
768
+ function readInput() {
769
+ if (leaveInputAlone || !focused || hasSelection(input) || options.readOnly) return false;
770
+ var text = input.value;
771
+ if (text == prevInput) return false;
772
+ shiftSelecting = null;
773
+ var same = 0, l = Math.min(prevInput.length, text.length);
774
+ while (same < l && prevInput[same] == text[same]) ++same;
775
+ if (same < prevInput.length)
776
+ sel.from = {line: sel.from.line, ch: sel.from.ch - (prevInput.length - same)};
777
+ else if (overwrite && posEq(sel.from, sel.to))
778
+ sel.to = {line: sel.to.line, ch: Math.min(getLine(sel.to.line).text.length, sel.to.ch + (text.length - same))};
779
+ replaceSelection(text.slice(same), "end");
780
+ prevInput = text;
781
+ return true;
782
+ }
783
+ function resetInput(user) {
784
+ if (!posEq(sel.from, sel.to)) {
785
+ prevInput = "";
786
+ input.value = getSelection();
787
+ input.select();
788
+ } else if (user) prevInput = input.value = "";
789
+ }
790
+
791
+ function focusInput() {
792
+ if (options.readOnly != "nocursor") input.focus();
793
+ }
794
+
795
+ function scrollEditorIntoView() {
796
+ if (!cursor.getBoundingClientRect) return;
797
+ var rect = cursor.getBoundingClientRect();
798
+ // IE returns bogus coordinates when the instance sits inside of an iframe and the cursor is hidden
799
+ if (ie && rect.top == rect.bottom) return;
800
+ var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight);
801
+ if (rect.top < 0 || rect.bottom > winH) cursor.scrollIntoView();
802
+ }
803
+ function scrollCursorIntoView() {
804
+ var cursor = localCoords(sel.inverted ? sel.from : sel.to);
805
+ var x = options.lineWrapping ? Math.min(cursor.x, lineSpace.offsetWidth) : cursor.x;
806
+ return scrollIntoView(x, cursor.y, x, cursor.yBot);
807
+ }
808
+ function scrollIntoView(x1, y1, x2, y2) {
809
+ var pl = paddingLeft(), pt = paddingTop(), lh = textHeight();
810
+ y1 += pt; y2 += pt; x1 += pl; x2 += pl;
811
+ var screen = scroller.clientHeight, screentop = scroller.scrollTop, scrolled = false, result = true;
812
+ if (y1 < screentop) {scroller.scrollTop = Math.max(0, y1 - 2*lh); scrolled = true;}
813
+ else if (y2 > screentop + screen) {scroller.scrollTop = y2 + lh - screen; scrolled = true;}
814
+
815
+ var screenw = scroller.clientWidth, screenleft = scroller.scrollLeft;
816
+ var gutterw = options.fixedGutter ? gutter.clientWidth : 0;
817
+ if (x1 < screenleft + gutterw) {
818
+ if (x1 < 50) x1 = 0;
819
+ scroller.scrollLeft = Math.max(0, x1 - 10 - gutterw);
820
+ scrolled = true;
821
+ }
822
+ else if (x2 > screenw + screenleft - 3) {
823
+ scroller.scrollLeft = x2 + 10 - screenw;
824
+ scrolled = true;
825
+ if (x2 > code.clientWidth) result = false;
826
+ }
827
+ if (scrolled && options.onScroll) options.onScroll(instance);
828
+ return result;
829
+ }
830
+
831
+ function visibleLines() {
832
+ var lh = textHeight(), top = scroller.scrollTop - paddingTop();
833
+ var from_height = Math.max(0, Math.floor(top / lh));
834
+ var to_height = Math.ceil((top + scroller.clientHeight) / lh);
835
+ return {from: lineAtHeight(doc, from_height),
836
+ to: lineAtHeight(doc, to_height)};
837
+ }
838
+ // Uses a set of changes plus the current scroll position to
839
+ // determine which DOM updates have to be made, and makes the
840
+ // updates.
841
+ function updateDisplay(changes, suppressCallback) {
842
+ if (!scroller.clientWidth) {
843
+ showingFrom = showingTo = displayOffset = 0;
844
+ return;
845
+ }
846
+ // Compute the new visible window
847
+ var visible = visibleLines();
848
+ // Bail out if the visible area is already rendered and nothing changed.
849
+ if (changes !== true && changes.length == 0 && visible.from > showingFrom && visible.to < showingTo) return;
850
+ var from = Math.max(visible.from - 100, 0), to = Math.min(doc.size, visible.to + 100);
851
+ if (showingFrom < from && from - showingFrom < 20) from = showingFrom;
852
+ if (showingTo > to && showingTo - to < 20) to = Math.min(doc.size, showingTo);
853
+
854
+ // Create a range of theoretically intact lines, and punch holes
855
+ // in that using the change info.
856
+ var intact = changes === true ? [] :
857
+ computeIntact([{from: showingFrom, to: showingTo, domStart: 0}], changes);
858
+ // Clip off the parts that won't be visible
859
+ var intactLines = 0;
860
+ for (var i = 0; i < intact.length; ++i) {
861
+ var range = intact[i];
862
+ if (range.from < from) {range.domStart += (from - range.from); range.from = from;}
863
+ if (range.to > to) range.to = to;
864
+ if (range.from >= range.to) intact.splice(i--, 1);
865
+ else intactLines += range.to - range.from;
866
+ }
867
+ if (intactLines == to - from) return;
868
+ intact.sort(function(a, b) {return a.domStart - b.domStart;});
869
+
870
+ var th = textHeight(), gutterDisplay = gutter.style.display;
871
+ lineDiv.style.display = "none";
872
+ patchDisplay(from, to, intact);
873
+ lineDiv.style.display = gutter.style.display = "";
874
+
875
+ // Position the mover div to align with the lines it's supposed
876
+ // to be showing (which will cover the visible display)
877
+ var different = from != showingFrom || to != showingTo || lastSizeC != scroller.clientHeight + th;
878
+ // This is just a bogus formula that detects when the editor is
879
+ // resized or the font size changes.
880
+ if (different) lastSizeC = scroller.clientHeight + th;
881
+ showingFrom = from; showingTo = to;
882
+ displayOffset = heightAtLine(doc, from);
883
+ mover.style.top = (displayOffset * th) + "px";
884
+ if (scroller.clientHeight)
885
+ code.style.height = (doc.height * th + 2 * paddingTop()) + "px";
886
+
887
+ // Since this is all rather error prone, it is honoured with the
888
+ // only assertion in the whole file.
889
+ if (lineDiv.childNodes.length != showingTo - showingFrom)
890
+ throw new Error("BAD PATCH! " + JSON.stringify(intact) + " size=" + (showingTo - showingFrom) +
891
+ " nodes=" + lineDiv.childNodes.length);
892
+
893
+ if (options.lineWrapping) {
894
+ maxWidth = scroller.clientWidth;
895
+ var curNode = lineDiv.firstChild, heightChanged = false;
896
+ doc.iter(showingFrom, showingTo, function(line) {
897
+ if (!line.hidden) {
898
+ var height = Math.round(curNode.offsetHeight / th) || 1;
899
+ if (line.height != height) {
900
+ updateLineHeight(line, height);
901
+ gutterDirty = heightChanged = true;
902
+ }
903
+ }
904
+ curNode = curNode.nextSibling;
905
+ });
906
+ if (heightChanged)
907
+ code.style.height = (doc.height * th + 2 * paddingTop()) + "px";
908
+ } else {
909
+ if (maxWidth == null) maxWidth = stringWidth(maxLine);
910
+ if (maxWidth > scroller.clientWidth) {
911
+ lineSpace.style.width = maxWidth + "px";
912
+ // Needed to prevent odd wrapping/hiding of widgets placed in here.
913
+ code.style.width = "";
914
+ code.style.width = scroller.scrollWidth + "px";
915
+ } else {
916
+ lineSpace.style.width = code.style.width = "";
917
+ }
918
+ }
919
+ gutter.style.display = gutterDisplay;
920
+ if (different || gutterDirty) updateGutter();
921
+ updateSelection();
922
+ if (!suppressCallback && options.onUpdate) options.onUpdate(instance);
923
+ return true;
924
+ }
925
+
926
+ function computeIntact(intact, changes) {
927
+ for (var i = 0, l = changes.length || 0; i < l; ++i) {
928
+ var change = changes[i], intact2 = [], diff = change.diff || 0;
929
+ for (var j = 0, l2 = intact.length; j < l2; ++j) {
930
+ var range = intact[j];
931
+ if (change.to <= range.from && change.diff)
932
+ intact2.push({from: range.from + diff, to: range.to + diff,
933
+ domStart: range.domStart});
934
+ else if (change.to <= range.from || change.from >= range.to)
935
+ intact2.push(range);
936
+ else {
937
+ if (change.from > range.from)
938
+ intact2.push({from: range.from, to: change.from, domStart: range.domStart});
939
+ if (change.to < range.to)
940
+ intact2.push({from: change.to + diff, to: range.to + diff,
941
+ domStart: range.domStart + (change.to - range.from)});
942
+ }
943
+ }
944
+ intact = intact2;
945
+ }
946
+ return intact;
947
+ }
948
+
949
+ function patchDisplay(from, to, intact) {
950
+ // The first pass removes the DOM nodes that aren't intact.
951
+ if (!intact.length) lineDiv.innerHTML = "";
952
+ else {
953
+ function killNode(node) {
954
+ var tmp = node.nextSibling;
955
+ node.parentNode.removeChild(node);
956
+ return tmp;
957
+ }
958
+ var domPos = 0, curNode = lineDiv.firstChild, n;
959
+ for (var i = 0; i < intact.length; ++i) {
960
+ var cur = intact[i];
961
+ while (cur.domStart > domPos) {curNode = killNode(curNode); domPos++;}
962
+ for (var j = 0, e = cur.to - cur.from; j < e; ++j) {curNode = curNode.nextSibling; domPos++;}
963
+ }
964
+ while (curNode) curNode = killNode(curNode);
965
+ }
966
+ // This pass fills in the lines that actually changed.
967
+ var nextIntact = intact.shift(), curNode = lineDiv.firstChild, j = from;
968
+ var scratch = targetDocument.createElement("div"), newElt;
969
+ doc.iter(from, to, function(line) {
970
+ if (nextIntact && nextIntact.to == j) nextIntact = intact.shift();
971
+ if (!nextIntact || nextIntact.from > j) {
972
+ if (line.hidden) var html = scratch.innerHTML = "<pre></pre>";
973
+ else {
974
+ var html = '<pre>' + line.getHTML(tabText) + '</pre>';
975
+ // Kludge to make sure the styled element lies behind the selection (by z-index)
976
+ if (line.className)
977
+ html = '<div style="position: relative"><pre class="' + line.className +
978
+ '" style="position: absolute; left: 0; right: 0; top: 0; bottom: 0; z-index: -2">&#160;</pre>' + html + "</div>";
979
+ }
980
+ scratch.innerHTML = html;
981
+ lineDiv.insertBefore(scratch.firstChild, curNode);
982
+ } else {
983
+ curNode = curNode.nextSibling;
984
+ }
985
+ ++j;
986
+ });
987
+ }
988
+
989
+ function updateGutter() {
990
+ if (!options.gutter && !options.lineNumbers) return;
991
+ var hText = mover.offsetHeight, hEditor = scroller.clientHeight;
992
+ gutter.style.height = (hText - hEditor < 2 ? hEditor : hText) + "px";
993
+ var html = [], i = showingFrom;
994
+ doc.iter(showingFrom, Math.max(showingTo, showingFrom + 1), function(line) {
995
+ if (line.hidden) {
996
+ html.push("<pre></pre>");
997
+ } else {
998
+ var marker = line.gutterMarker;
999
+ var text = options.lineNumbers ? i + options.firstLineNumber : null;
1000
+ if (marker && marker.text)
1001
+ text = marker.text.replace("%N%", text != null ? text : "");
1002
+ else if (text == null)
1003
+ text = "\u00a0";
1004
+ html.push((marker && marker.style ? '<pre class="' + marker.style + '">' : "<pre>"), text);
1005
+ for (var j = 1; j < line.height; ++j) html.push("<br/>&#160;");
1006
+ html.push("</pre>");
1007
+ }
1008
+ ++i;
1009
+ });
1010
+ gutter.style.display = "none";
1011
+ gutterText.innerHTML = html.join("");
1012
+ var minwidth = String(doc.size).length, firstNode = gutterText.firstChild, val = eltText(firstNode), pad = "";
1013
+ while (val.length + pad.length < minwidth) pad += "\u00a0";
1014
+ if (pad) firstNode.insertBefore(targetDocument.createTextNode(pad), firstNode.firstChild);
1015
+ gutter.style.display = "";
1016
+ lineSpace.style.marginLeft = gutter.offsetWidth + "px";
1017
+ gutterDirty = false;
1018
+ }
1019
+ function updateSelection() {
1020
+ var collapsed = posEq(sel.from, sel.to);
1021
+ var fromPos = localCoords(sel.from, true);
1022
+ var toPos = collapsed ? fromPos : localCoords(sel.to, true);
1023
+ var headPos = sel.inverted ? fromPos : toPos, th = textHeight();
1024
+ var wrapOff = eltOffset(wrapper), lineOff = eltOffset(lineDiv);
1025
+ inputDiv.style.top = Math.max(0, Math.min(scroller.offsetHeight, headPos.y + lineOff.top - wrapOff.top)) + "px";
1026
+ inputDiv.style.left = Math.max(0, Math.min(scroller.offsetWidth, headPos.x + lineOff.left - wrapOff.left)) + "px";
1027
+ if (collapsed) {
1028
+ cursor.style.top = headPos.y + "px";
1029
+ cursor.style.left = (options.lineWrapping ? Math.min(headPos.x, lineSpace.offsetWidth) : headPos.x) + "px";
1030
+ cursor.style.display = "";
1031
+ selectionDiv.style.display = "none";
1032
+ } else {
1033
+ var sameLine = fromPos.y == toPos.y, html = "";
1034
+ function add(left, top, right, height) {
1035
+ html += '<div class="CodeMirror-selected" style="position: absolute; left: ' + left +
1036
+ 'px; top: ' + top + 'px; right: ' + right + 'px; height: ' + height + 'px"></div>';
1037
+ }
1038
+ if (sel.from.ch && fromPos.y >= 0) {
1039
+ var right = sameLine ? lineSpace.clientWidth - toPos.x : 0;
1040
+ add(fromPos.x, fromPos.y, right, th);
1041
+ }
1042
+ var middleStart = Math.max(0, fromPos.y + (sel.from.ch ? th : 0));
1043
+ var middleHeight = Math.min(toPos.y, lineSpace.clientHeight) - middleStart;
1044
+ if (middleHeight > 0.2 * th)
1045
+ add(0, middleStart, 0, middleHeight);
1046
+ if ((!sameLine || !sel.from.ch) && toPos.y < lineSpace.clientHeight - .5 * th)
1047
+ add(0, toPos.y, lineSpace.clientWidth - toPos.x, th);
1048
+ selectionDiv.innerHTML = html;
1049
+ cursor.style.display = "none";
1050
+ selectionDiv.style.display = "";
1051
+ }
1052
+ }
1053
+
1054
+ function setShift(val) {
1055
+ if (val) shiftSelecting = shiftSelecting || (sel.inverted ? sel.to : sel.from);
1056
+ else shiftSelecting = null;
1057
+ }
1058
+ function setSelectionUser(from, to) {
1059
+ var sh = shiftSelecting && clipPos(shiftSelecting);
1060
+ if (sh) {
1061
+ if (posLess(sh, from)) from = sh;
1062
+ else if (posLess(to, sh)) to = sh;
1063
+ }
1064
+ setSelection(from, to);
1065
+ userSelChange = true;
1066
+ }
1067
+ // Update the selection. Last two args are only used by
1068
+ // updateLines, since they have to be expressed in the line
1069
+ // numbers before the update.
1070
+ function setSelection(from, to, oldFrom, oldTo) {
1071
+ goalColumn = null;
1072
+ if (oldFrom == null) {oldFrom = sel.from.line; oldTo = sel.to.line;}
1073
+ if (posEq(sel.from, from) && posEq(sel.to, to)) return;
1074
+ if (posLess(to, from)) {var tmp = to; to = from; from = tmp;}
1075
+
1076
+ // Skip over hidden lines.
1077
+ if (from.line != oldFrom) from = skipHidden(from, oldFrom, sel.from.ch);
1078
+ if (to.line != oldTo) to = skipHidden(to, oldTo, sel.to.ch);
1079
+
1080
+ if (posEq(from, to)) sel.inverted = false;
1081
+ else if (posEq(from, sel.to)) sel.inverted = false;
1082
+ else if (posEq(to, sel.from)) sel.inverted = true;
1083
+
1084
+ sel.from = from; sel.to = to;
1085
+ selectionChanged = true;
1086
+ }
1087
+ function skipHidden(pos, oldLine, oldCh) {
1088
+ function getNonHidden(dir) {
1089
+ var lNo = pos.line + dir, end = dir == 1 ? doc.size : -1;
1090
+ while (lNo != end) {
1091
+ var line = getLine(lNo);
1092
+ if (!line.hidden) {
1093
+ var ch = pos.ch;
1094
+ if (ch > oldCh || ch > line.text.length) ch = line.text.length;
1095
+ return {line: lNo, ch: ch};
1096
+ }
1097
+ lNo += dir;
1098
+ }
1099
+ }
1100
+ var line = getLine(pos.line);
1101
+ if (!line.hidden) return pos;
1102
+ if (pos.line >= oldLine) return getNonHidden(1) || getNonHidden(-1);
1103
+ else return getNonHidden(-1) || getNonHidden(1);
1104
+ }
1105
+ function setCursor(line, ch, user) {
1106
+ var pos = clipPos({line: line, ch: ch || 0});
1107
+ (user ? setSelectionUser : setSelection)(pos, pos);
1108
+ }
1109
+
1110
+ function clipLine(n) {return Math.max(0, Math.min(n, doc.size-1));}
1111
+ function clipPos(pos) {
1112
+ if (pos.line < 0) return {line: 0, ch: 0};
1113
+ if (pos.line >= doc.size) return {line: doc.size-1, ch: getLine(doc.size-1).text.length};
1114
+ var ch = pos.ch, linelen = getLine(pos.line).text.length;
1115
+ if (ch == null || ch > linelen) return {line: pos.line, ch: linelen};
1116
+ else if (ch < 0) return {line: pos.line, ch: 0};
1117
+ else return pos;
1118
+ }
1119
+
1120
+ function findPosH(dir, unit) {
1121
+ var end = sel.inverted ? sel.from : sel.to, line = end.line, ch = end.ch;
1122
+ var lineObj = getLine(line);
1123
+ function findNextLine() {
1124
+ for (var l = line + dir, e = dir < 0 ? -1 : doc.size; l != e; l += dir) {
1125
+ var lo = getLine(l);
1126
+ if (!lo.hidden) { line = l; lineObj = lo; return true; }
1127
+ }
1128
+ }
1129
+ function moveOnce(boundToLine) {
1130
+ if (ch == (dir < 0 ? 0 : lineObj.text.length)) {
1131
+ if (!boundToLine && findNextLine()) ch = dir < 0 ? lineObj.text.length : 0;
1132
+ else return false;
1133
+ } else ch += dir;
1134
+ return true;
1135
+ }
1136
+ if (unit == "char") moveOnce();
1137
+ else if (unit == "column") moveOnce(true);
1138
+ else if (unit == "word") {
1139
+ var sawWord = false;
1140
+ for (;;) {
1141
+ if (dir < 0) if (!moveOnce()) break;
1142
+ if (isWordChar(lineObj.text.charAt(ch))) sawWord = true;
1143
+ else if (sawWord) {if (dir < 0) {dir = 1; moveOnce();} break;}
1144
+ if (dir > 0) if (!moveOnce()) break;
1145
+ }
1146
+ }
1147
+ return {line: line, ch: ch};
1148
+ }
1149
+ function moveH(dir, unit) {
1150
+ var pos = dir < 0 ? sel.from : sel.to;
1151
+ if (shiftSelecting || posEq(sel.from, sel.to)) pos = findPosH(dir, unit);
1152
+ setCursor(pos.line, pos.ch, true);
1153
+ }
1154
+ function deleteH(dir, unit) {
1155
+ if (!posEq(sel.from, sel.to)) replaceRange("", sel.from, sel.to);
1156
+ else if (dir < 0) replaceRange("", findPosH(dir, unit), sel.to);
1157
+ else replaceRange("", sel.from, findPosH(dir, unit));
1158
+ userSelChange = true;
1159
+ }
1160
+ var goalColumn = null;
1161
+ function moveV(dir, unit) {
1162
+ var dist = 0, pos = localCoords(sel.inverted ? sel.from : sel.to, true);
1163
+ if (goalColumn != null) pos.x = goalColumn;
1164
+ if (unit == "page") dist = Math.min(scroller.clientHeight, window.innerHeight || document.documentElement.clientHeight);
1165
+ else if (unit == "line") dist = textHeight();
1166
+ var target = coordsChar(pos.x, pos.y + dist * dir + 2);
1167
+ setCursor(target.line, target.ch, true);
1168
+ goalColumn = pos.x;
1169
+ }
1170
+
1171
+ function selectWordAt(pos) {
1172
+ var line = getLine(pos.line).text;
1173
+ var start = pos.ch, end = pos.ch;
1174
+ while (start > 0 && isWordChar(line.charAt(start - 1))) --start;
1175
+ while (end < line.length && isWordChar(line.charAt(end))) ++end;
1176
+ setSelectionUser({line: pos.line, ch: start}, {line: pos.line, ch: end});
1177
+ }
1178
+ function selectLine(line) {
1179
+ setSelectionUser({line: line, ch: 0}, {line: line, ch: getLine(line).text.length});
1180
+ }
1181
+ function indentSelected(mode) {
1182
+ if (posEq(sel.from, sel.to)) return indentLine(sel.from.line, mode);
1183
+ var e = sel.to.line - (sel.to.ch ? 0 : 1);
1184
+ for (var i = sel.from.line; i <= e; ++i) indentLine(i, mode);
1185
+ }
1186
+
1187
+ function indentLine(n, how) {
1188
+ if (!how) how = "add";
1189
+ if (how == "smart") {
1190
+ if (!mode.indent) how = "prev";
1191
+ else var state = getStateBefore(n);
1192
+ }
1193
+
1194
+ var line = getLine(n), curSpace = line.indentation(options.tabSize),
1195
+ curSpaceString = line.text.match(/^\s*/)[0], indentation;
1196
+ if (how == "prev") {
1197
+ if (n) indentation = getLine(n-1).indentation(options.tabSize);
1198
+ else indentation = 0;
1199
+ }
1200
+ else if (how == "smart") indentation = mode.indent(state, line.text.slice(curSpaceString.length), line.text);
1201
+ else if (how == "add") indentation = curSpace + options.indentUnit;
1202
+ else if (how == "subtract") indentation = curSpace - options.indentUnit;
1203
+ indentation = Math.max(0, indentation);
1204
+ var diff = indentation - curSpace;
1205
+
1206
+ if (!diff) {
1207
+ if (sel.from.line != n && sel.to.line != n) return;
1208
+ var indentString = curSpaceString;
1209
+ }
1210
+ else {
1211
+ var indentString = "", pos = 0;
1212
+ if (options.indentWithTabs)
1213
+ for (var i = Math.floor(indentation / options.tabSize); i; --i) {pos += options.tabSize; indentString += "\t";}
1214
+ while (pos < indentation) {++pos; indentString += " ";}
1215
+ }
1216
+
1217
+ replaceRange(indentString, {line: n, ch: 0}, {line: n, ch: curSpaceString.length});
1218
+ }
1219
+
1220
+ function loadMode() {
1221
+ mode = CodeMirror.getMode(options, options.mode);
1222
+ doc.iter(0, doc.size, function(line) { line.stateAfter = null; });
1223
+ work = [0];
1224
+ startWorker();
1225
+ }
1226
+ function gutterChanged() {
1227
+ var visible = options.gutter || options.lineNumbers;
1228
+ gutter.style.display = visible ? "" : "none";
1229
+ if (visible) gutterDirty = true;
1230
+ else lineDiv.parentNode.style.marginLeft = 0;
1231
+ }
1232
+ function wrappingChanged(from, to) {
1233
+ if (options.lineWrapping) {
1234
+ wrapper.className += " CodeMirror-wrap";
1235
+ var perLine = scroller.clientWidth / charWidth() - 3;
1236
+ doc.iter(0, doc.size, function(line) {
1237
+ if (line.hidden) return;
1238
+ var guess = Math.ceil(line.text.length / perLine) || 1;
1239
+ if (guess != 1) updateLineHeight(line, guess);
1240
+ });
1241
+ lineSpace.style.width = code.style.width = "";
1242
+ } else {
1243
+ wrapper.className = wrapper.className.replace(" CodeMirror-wrap", "");
1244
+ maxWidth = null; maxLine = "";
1245
+ doc.iter(0, doc.size, function(line) {
1246
+ if (line.height != 1 && !line.hidden) updateLineHeight(line, 1);
1247
+ if (line.text.length > maxLine.length) maxLine = line.text;
1248
+ });
1249
+ }
1250
+ changes.push({from: 0, to: doc.size});
1251
+ }
1252
+ function computeTabText() {
1253
+ for (var str = '<span class="cm-tab">', i = 0; i < options.tabSize; ++i) str += " ";
1254
+ return str + "</span>";
1255
+ }
1256
+ function tabsChanged() {
1257
+ tabText = computeTabText();
1258
+ updateDisplay(true);
1259
+ }
1260
+ function themeChanged() {
1261
+ scroller.className = scroller.className.replace(/\s*cm-s-\w+/g, "") +
1262
+ options.theme.replace(/(^|\s)\s*/g, " cm-s-");
1263
+ }
1264
+
1265
+ function TextMarker() { this.set = []; }
1266
+ TextMarker.prototype.clear = operation(function() {
1267
+ var min = Infinity, max = -Infinity;
1268
+ for (var i = 0, e = this.set.length; i < e; ++i) {
1269
+ var line = this.set[i], mk = line.marked;
1270
+ if (!mk || !line.parent) continue;
1271
+ var lineN = lineNo(line);
1272
+ min = Math.min(min, lineN); max = Math.max(max, lineN);
1273
+ for (var j = 0; j < mk.length; ++j)
1274
+ if (mk[j].set == this.set) mk.splice(j--, 1);
1275
+ }
1276
+ if (min != Infinity)
1277
+ changes.push({from: min, to: max + 1});
1278
+ });
1279
+ TextMarker.prototype.find = function() {
1280
+ var from, to;
1281
+ for (var i = 0, e = this.set.length; i < e; ++i) {
1282
+ var line = this.set[i], mk = line.marked;
1283
+ for (var j = 0; j < mk.length; ++j) {
1284
+ var mark = mk[j];
1285
+ if (mark.set == this.set) {
1286
+ if (mark.from != null || mark.to != null) {
1287
+ var found = lineNo(line);
1288
+ if (found != null) {
1289
+ if (mark.from != null) from = {line: found, ch: mark.from};
1290
+ if (mark.to != null) to = {line: found, ch: mark.to};
1291
+ }
1292
+ }
1293
+ }
1294
+ }
1295
+ }
1296
+ return {from: from, to: to};
1297
+ };
1298
+
1299
+ function markText(from, to, className) {
1300
+ from = clipPos(from); to = clipPos(to);
1301
+ var tm = new TextMarker();
1302
+ function add(line, from, to, className) {
1303
+ getLine(line).addMark(new MarkedText(from, to, className, tm.set));
1304
+ }
1305
+ if (from.line == to.line) add(from.line, from.ch, to.ch, className);
1306
+ else {
1307
+ add(from.line, from.ch, null, className);
1308
+ for (var i = from.line + 1, e = to.line; i < e; ++i)
1309
+ add(i, null, null, className);
1310
+ add(to.line, null, to.ch, className);
1311
+ }
1312
+ changes.push({from: from.line, to: to.line + 1});
1313
+ return tm;
1314
+ }
1315
+
1316
+ function setBookmark(pos) {
1317
+ pos = clipPos(pos);
1318
+ var bm = new Bookmark(pos.ch);
1319
+ getLine(pos.line).addMark(bm);
1320
+ return bm;
1321
+ }
1322
+
1323
+ function addGutterMarker(line, text, className) {
1324
+ if (typeof line == "number") line = getLine(clipLine(line));
1325
+ line.gutterMarker = {text: text, style: className};
1326
+ gutterDirty = true;
1327
+ return line;
1328
+ }
1329
+ function removeGutterMarker(line) {
1330
+ if (typeof line == "number") line = getLine(clipLine(line));
1331
+ line.gutterMarker = null;
1332
+ gutterDirty = true;
1333
+ }
1334
+
1335
+ function changeLine(handle, op) {
1336
+ var no = handle, line = handle;
1337
+ if (typeof handle == "number") line = getLine(clipLine(handle));
1338
+ else no = lineNo(handle);
1339
+ if (no == null) return null;
1340
+ if (op(line, no)) changes.push({from: no, to: no + 1});
1341
+ else return null;
1342
+ return line;
1343
+ }
1344
+ function setLineClass(handle, className) {
1345
+ return changeLine(handle, function(line) {
1346
+ if (line.className != className) {
1347
+ line.className = className;
1348
+ return true;
1349
+ }
1350
+ });
1351
+ }
1352
+ function setLineHidden(handle, hidden) {
1353
+ return changeLine(handle, function(line, no) {
1354
+ if (line.hidden != hidden) {
1355
+ line.hidden = hidden;
1356
+ updateLineHeight(line, hidden ? 0 : 1);
1357
+ var fline = sel.from.line, tline = sel.to.line;
1358
+ if (hidden && (fline == no || tline == no)) {
1359
+ var from = fline == no ? skipHidden({line: fline, ch: 0}, fline, 0) : sel.from;
1360
+ var to = tline == no ? skipHidden({line: tline, ch: 0}, tline, 0) : sel.to;
1361
+ setSelection(from, to);
1362
+ }
1363
+ return (gutterDirty = true);
1364
+ }
1365
+ });
1366
+ }
1367
+
1368
+ function lineInfo(line) {
1369
+ if (typeof line == "number") {
1370
+ if (!isLine(line)) return null;
1371
+ var n = line;
1372
+ line = getLine(line);
1373
+ if (!line) return null;
1374
+ }
1375
+ else {
1376
+ var n = lineNo(line);
1377
+ if (n == null) return null;
1378
+ }
1379
+ var marker = line.gutterMarker;
1380
+ return {line: n, handle: line, text: line.text, markerText: marker && marker.text,
1381
+ markerClass: marker && marker.style, lineClass: line.className};
1382
+ }
1383
+
1384
+ function stringWidth(str) {
1385
+ measure.innerHTML = "<pre><span>x</span></pre>";
1386
+ measure.firstChild.firstChild.firstChild.nodeValue = str;
1387
+ return measure.firstChild.firstChild.offsetWidth || 10;
1388
+ }
1389
+ // These are used to go from pixel positions to character
1390
+ // positions, taking varying character widths into account.
1391
+ function charFromX(line, x) {
1392
+ if (x <= 0) return 0;
1393
+ var lineObj = getLine(line), text = lineObj.text;
1394
+ function getX(len) {
1395
+ measure.innerHTML = "<pre><span>" + lineObj.getHTML(tabText, len) + "</span></pre>";
1396
+ return measure.firstChild.firstChild.offsetWidth;
1397
+ }
1398
+ var from = 0, fromX = 0, to = text.length, toX;
1399
+ // Guess a suitable upper bound for our search.
1400
+ var estimated = Math.min(to, Math.ceil(x / charWidth()));
1401
+ for (;;) {
1402
+ var estX = getX(estimated);
1403
+ if (estX <= x && estimated < to) estimated = Math.min(to, Math.ceil(estimated * 1.2));
1404
+ else {toX = estX; to = estimated; break;}
1405
+ }
1406
+ if (x > toX) return to;
1407
+ // Try to guess a suitable lower bound as well.
1408
+ estimated = Math.floor(to * 0.8); estX = getX(estimated);
1409
+ if (estX < x) {from = estimated; fromX = estX;}
1410
+ // Do a binary search between these bounds.
1411
+ for (;;) {
1412
+ if (to - from <= 1) return (toX - x > x - fromX) ? from : to;
1413
+ var middle = Math.ceil((from + to) / 2), middleX = getX(middle);
1414
+ if (middleX > x) {to = middle; toX = middleX;}
1415
+ else {from = middle; fromX = middleX;}
1416
+ }
1417
+ }
1418
+
1419
+ var tempId = Math.floor(Math.random() * 0xffffff).toString(16);
1420
+ function measureLine(line, ch) {
1421
+ if (ch == 0) return {top: 0, left: 0};
1422
+ var extra = "";
1423
+ // Include extra text at the end to make sure the measured line is wrapped in the right way.
1424
+ if (options.lineWrapping) {
1425
+ var end = line.text.indexOf(" ", ch + 2);
1426
+ extra = htmlEscape(line.text.slice(ch + 1, end < 0 ? line.text.length : end + (ie ? 5 : 0)));
1427
+ }
1428
+ measure.innerHTML = "<pre>" + line.getHTML(tabText, ch) +
1429
+ '<span id="CodeMirror-temp-' + tempId + '">' + htmlEscape(line.text.charAt(ch) || " ") + "</span>" +
1430
+ extra + "</pre>";
1431
+ var elt = document.getElementById("CodeMirror-temp-" + tempId);
1432
+ var top = elt.offsetTop, left = elt.offsetLeft;
1433
+ // Older IEs report zero offsets for spans directly after a wrap
1434
+ if (ie && top == 0 && left == 0) {
1435
+ var backup = document.createElement("span");
1436
+ backup.innerHTML = "x";
1437
+ elt.parentNode.insertBefore(backup, elt.nextSibling);
1438
+ top = backup.offsetTop;
1439
+ }
1440
+ return {top: top, left: left};
1441
+ }
1442
+ function localCoords(pos, inLineWrap) {
1443
+ var x, lh = textHeight(), y = lh * (heightAtLine(doc, pos.line) - (inLineWrap ? displayOffset : 0));
1444
+ if (pos.ch == 0) x = 0;
1445
+ else {
1446
+ var sp = measureLine(getLine(pos.line), pos.ch);
1447
+ x = sp.left;
1448
+ if (options.lineWrapping) y += Math.max(0, sp.top);
1449
+ }
1450
+ return {x: x, y: y, yBot: y + lh};
1451
+ }
1452
+ // Coords must be lineSpace-local
1453
+ function coordsChar(x, y) {
1454
+ if (y < 0) y = 0;
1455
+ var th = textHeight(), cw = charWidth(), heightPos = displayOffset + Math.floor(y / th);
1456
+ var lineNo = lineAtHeight(doc, heightPos);
1457
+ if (lineNo >= doc.size) return {line: doc.size - 1, ch: getLine(doc.size - 1).text.length};
1458
+ var lineObj = getLine(lineNo), text = lineObj.text;
1459
+ var tw = options.lineWrapping, innerOff = tw ? heightPos - heightAtLine(doc, lineNo) : 0;
1460
+ if (x <= 0 && innerOff == 0) return {line: lineNo, ch: 0};
1461
+ function getX(len) {
1462
+ var sp = measureLine(lineObj, len);
1463
+ if (tw) {
1464
+ var off = Math.round(sp.top / th);
1465
+ return Math.max(0, sp.left + (off - innerOff) * scroller.clientWidth);
1466
+ }
1467
+ return sp.left;
1468
+ }
1469
+ var from = 0, fromX = 0, to = text.length, toX;
1470
+ // Guess a suitable upper bound for our search.
1471
+ var estimated = Math.min(to, Math.ceil((x + innerOff * scroller.clientWidth * .9) / cw));
1472
+ for (;;) {
1473
+ var estX = getX(estimated);
1474
+ if (estX <= x && estimated < to) estimated = Math.min(to, Math.ceil(estimated * 1.2));
1475
+ else {toX = estX; to = estimated; break;}
1476
+ }
1477
+ if (x > toX) return {line: lineNo, ch: to};
1478
+ // Try to guess a suitable lower bound as well.
1479
+ estimated = Math.floor(to * 0.8); estX = getX(estimated);
1480
+ if (estX < x) {from = estimated; fromX = estX;}
1481
+ // Do a binary search between these bounds.
1482
+ for (;;) {
1483
+ if (to - from <= 1) return {line: lineNo, ch: (toX - x > x - fromX) ? from : to};
1484
+ var middle = Math.ceil((from + to) / 2), middleX = getX(middle);
1485
+ if (middleX > x) {to = middle; toX = middleX;}
1486
+ else {from = middle; fromX = middleX;}
1487
+ }
1488
+ }
1489
+ function pageCoords(pos) {
1490
+ var local = localCoords(pos, true), off = eltOffset(lineSpace);
1491
+ return {x: off.left + local.x, y: off.top + local.y, yBot: off.top + local.yBot};
1492
+ }
1493
+
1494
+ var cachedHeight, cachedHeightFor, measureText;
1495
+ function textHeight() {
1496
+ if (measureText == null) {
1497
+ measureText = "<pre>";
1498
+ for (var i = 0; i < 49; ++i) measureText += "x<br/>";
1499
+ measureText += "x</pre>";
1500
+ }
1501
+ var offsetHeight = lineDiv.clientHeight;
1502
+ if (offsetHeight == cachedHeightFor) return cachedHeight;
1503
+ cachedHeightFor = offsetHeight;
1504
+ measure.innerHTML = measureText;
1505
+ cachedHeight = measure.firstChild.offsetHeight / 50 || 1;
1506
+ measure.innerHTML = "";
1507
+ return cachedHeight;
1508
+ }
1509
+ var cachedWidth, cachedWidthFor = 0;
1510
+ function charWidth() {
1511
+ if (scroller.clientWidth == cachedWidthFor) return cachedWidth;
1512
+ cachedWidthFor = scroller.clientWidth;
1513
+ return (cachedWidth = stringWidth("x"));
1514
+ }
1515
+ function paddingTop() {return lineSpace.offsetTop;}
1516
+ function paddingLeft() {return lineSpace.offsetLeft;}
1517
+
1518
+ function posFromMouse(e, liberal) {
1519
+ var offW = eltOffset(scroller, true), x, y;
1520
+ // Fails unpredictably on IE[67] when mouse is dragged around quickly.
1521
+ try { x = e.clientX; y = e.clientY; } catch (e) { return null; }
1522
+ // This is a mess of a heuristic to try and determine whether a
1523
+ // scroll-bar was clicked or not, and to return null if one was
1524
+ // (and !liberal).
1525
+ if (!liberal && (x - offW.left > scroller.clientWidth || y - offW.top > scroller.clientHeight))
1526
+ return null;
1527
+ var offL = eltOffset(lineSpace, true);
1528
+ return coordsChar(x - offL.left, y - offL.top);
1529
+ }
1530
+ function onContextMenu(e) {
1531
+ var pos = posFromMouse(e);
1532
+ if (!pos || window.opera) return; // Opera is difficult.
1533
+ if (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to))
1534
+ operation(setCursor)(pos.line, pos.ch);
1535
+
1536
+ var oldCSS = input.style.cssText;
1537
+ inputDiv.style.position = "absolute";
1538
+ input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) +
1539
+ "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: white; " +
1540
+ "border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);";
1541
+ leaveInputAlone = true;
1542
+ var val = input.value = getSelection();
1543
+ focusInput();
1544
+ input.select();
1545
+ function rehide() {
1546
+ var newVal = splitLines(input.value).join("\n");
1547
+ if (newVal != val) operation(replaceSelection)(newVal, "end");
1548
+ inputDiv.style.position = "relative";
1549
+ input.style.cssText = oldCSS;
1550
+ leaveInputAlone = false;
1551
+ resetInput(true);
1552
+ slowPoll();
1553
+ }
1554
+
1555
+ if (gecko) {
1556
+ e_stop(e);
1557
+ var mouseup = connect(window, "mouseup", function() {
1558
+ mouseup();
1559
+ setTimeout(rehide, 20);
1560
+ }, true);
1561
+ }
1562
+ else {
1563
+ setTimeout(rehide, 50);
1564
+ }
1565
+ }
1566
+
1567
+ // Cursor-blinking
1568
+ function restartBlink() {
1569
+ clearInterval(blinker);
1570
+ var on = true;
1571
+ cursor.style.visibility = "";
1572
+ blinker = setInterval(function() {
1573
+ cursor.style.visibility = (on = !on) ? "" : "hidden";
1574
+ }, 650);
1575
+ }
1576
+
1577
+ var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"};
1578
+ function matchBrackets(autoclear) {
1579
+ var head = sel.inverted ? sel.from : sel.to, line = getLine(head.line), pos = head.ch - 1;
1580
+ var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)];
1581
+ if (!match) return;
1582
+ var ch = match.charAt(0), forward = match.charAt(1) == ">", d = forward ? 1 : -1, st = line.styles;
1583
+ for (var off = pos + 1, i = 0, e = st.length; i < e; i+=2)
1584
+ if ((off -= st[i].length) <= 0) {var style = st[i+1]; break;}
1585
+
1586
+ var stack = [line.text.charAt(pos)], re = /[(){}[\]]/;
1587
+ function scan(line, from, to) {
1588
+ if (!line.text) return;
1589
+ var st = line.styles, pos = forward ? 0 : line.text.length - 1, cur;
1590
+ for (var i = forward ? 0 : st.length - 2, e = forward ? st.length : -2; i != e; i += 2*d) {
1591
+ var text = st[i];
1592
+ if (st[i+1] != null && st[i+1] != style) {pos += d * text.length; continue;}
1593
+ for (var j = forward ? 0 : text.length - 1, te = forward ? text.length : -1; j != te; j += d, pos+=d) {
1594
+ if (pos >= from && pos < to && re.test(cur = text.charAt(j))) {
1595
+ var match = matching[cur];
1596
+ if (match.charAt(1) == ">" == forward) stack.push(cur);
1597
+ else if (stack.pop() != match.charAt(0)) return {pos: pos, match: false};
1598
+ else if (!stack.length) return {pos: pos, match: true};
1599
+ }
1600
+ }
1601
+ }
1602
+ }
1603
+ for (var i = head.line, e = forward ? Math.min(i + 100, doc.size) : Math.max(-1, i - 100); i != e; i+=d) {
1604
+ var line = getLine(i), first = i == head.line;
1605
+ var found = scan(line, first && forward ? pos + 1 : 0, first && !forward ? pos : line.text.length);
1606
+ if (found) break;
1607
+ }
1608
+ if (!found) found = {pos: null, match: false};
1609
+ var style = found.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket";
1610
+ var one = markText({line: head.line, ch: pos}, {line: head.line, ch: pos+1}, style),
1611
+ two = found.pos != null && markText({line: i, ch: found.pos}, {line: i, ch: found.pos + 1}, style);
1612
+ var clear = operation(function(){one.clear(); two && two.clear();});
1613
+ if (autoclear) setTimeout(clear, 800);
1614
+ else bracketHighlighted = clear;
1615
+ }
1616
+
1617
+ // Finds the line to start with when starting a parse. Tries to
1618
+ // find a line with a stateAfter, so that it can start with a
1619
+ // valid state. If that fails, it returns the line with the
1620
+ // smallest indentation, which tends to need the least context to
1621
+ // parse correctly.
1622
+ function findStartLine(n) {
1623
+ var minindent, minline;
1624
+ for (var search = n, lim = n - 40; search > lim; --search) {
1625
+ if (search == 0) return 0;
1626
+ var line = getLine(search-1);
1627
+ if (line.stateAfter) return search;
1628
+ var indented = line.indentation(options.tabSize);
1629
+ if (minline == null || minindent > indented) {
1630
+ minline = search - 1;
1631
+ minindent = indented;
1632
+ }
1633
+ }
1634
+ return minline;
1635
+ }
1636
+ function getStateBefore(n) {
1637
+ var start = findStartLine(n), state = start && getLine(start-1).stateAfter;
1638
+ if (!state) state = startState(mode);
1639
+ else state = copyState(mode, state);
1640
+ doc.iter(start, n, function(line) {
1641
+ line.highlight(mode, state, options.tabSize);
1642
+ line.stateAfter = copyState(mode, state);
1643
+ });
1644
+ if (start < n) changes.push({from: start, to: n});
1645
+ if (n < doc.size && !getLine(n).stateAfter) work.push(n);
1646
+ return state;
1647
+ }
1648
+ function highlightLines(start, end) {
1649
+ var state = getStateBefore(start);
1650
+ doc.iter(start, end, function(line) {
1651
+ line.highlight(mode, state, options.tabSize);
1652
+ line.stateAfter = copyState(mode, state);
1653
+ });
1654
+ }
1655
+ function highlightWorker() {
1656
+ var end = +new Date + options.workTime;
1657
+ var foundWork = work.length;
1658
+ while (work.length) {
1659
+ if (!getLine(showingFrom).stateAfter) var task = showingFrom;
1660
+ else var task = work.pop();
1661
+ if (task >= doc.size) continue;
1662
+ var start = findStartLine(task), state = start && getLine(start-1).stateAfter;
1663
+ if (state) state = copyState(mode, state);
1664
+ else state = startState(mode);
1665
+
1666
+ var unchanged = 0, compare = mode.compareStates, realChange = false,
1667
+ i = start, bail = false;
1668
+ doc.iter(i, doc.size, function(line) {
1669
+ var hadState = line.stateAfter;
1670
+ if (+new Date > end) {
1671
+ work.push(i);
1672
+ startWorker(options.workDelay);
1673
+ if (realChange) changes.push({from: task, to: i + 1});
1674
+ return (bail = true);
1675
+ }
1676
+ var changed = line.highlight(mode, state, options.tabSize);
1677
+ if (changed) realChange = true;
1678
+ line.stateAfter = copyState(mode, state);
1679
+ if (compare) {
1680
+ if (hadState && compare(hadState, state)) return true;
1681
+ } else {
1682
+ if (changed !== false || !hadState) unchanged = 0;
1683
+ else if (++unchanged > 3 && (!mode.indent || mode.indent(hadState, "") == mode.indent(state, "")))
1684
+ return true;
1685
+ }
1686
+ ++i;
1687
+ });
1688
+ if (bail) return;
1689
+ if (realChange) changes.push({from: task, to: i + 1});
1690
+ }
1691
+ if (foundWork && options.onHighlightComplete)
1692
+ options.onHighlightComplete(instance);
1693
+ }
1694
+ function startWorker(time) {
1695
+ if (!work.length) return;
1696
+ highlight.set(time, operation(highlightWorker));
1697
+ }
1698
+
1699
+ // Operations are used to wrap changes in such a way that each
1700
+ // change won't have to update the cursor and display (which would
1701
+ // be awkward, slow, and error-prone), but instead updates are
1702
+ // batched and then all combined and executed at once.
1703
+ function startOperation() {
1704
+ updateInput = userSelChange = textChanged = null;
1705
+ changes = []; selectionChanged = false; callbacks = [];
1706
+ }
1707
+ function endOperation() {
1708
+ var reScroll = false, updated;
1709
+ if (selectionChanged) reScroll = !scrollCursorIntoView();
1710
+ if (changes.length) updated = updateDisplay(changes, true);
1711
+ else {
1712
+ if (selectionChanged) updateSelection();
1713
+ if (gutterDirty) updateGutter();
1714
+ }
1715
+ if (reScroll) scrollCursorIntoView();
1716
+ if (selectionChanged) {scrollEditorIntoView(); restartBlink();}
1717
+
1718
+ if (focused && !leaveInputAlone &&
1719
+ (updateInput === true || (updateInput !== false && selectionChanged)))
1720
+ resetInput(userSelChange);
1721
+
1722
+ if (selectionChanged && options.matchBrackets)
1723
+ setTimeout(operation(function() {
1724
+ if (bracketHighlighted) {bracketHighlighted(); bracketHighlighted = null;}
1725
+ if (posEq(sel.from, sel.to)) matchBrackets(false);
1726
+ }), 20);
1727
+ var tc = textChanged, cbs = callbacks; // these can be reset by callbacks
1728
+ if (selectionChanged && options.onCursorActivity)
1729
+ options.onCursorActivity(instance);
1730
+ if (tc && options.onChange && instance)
1731
+ options.onChange(instance, tc);
1732
+ for (var i = 0; i < cbs.length; ++i) cbs[i](instance);
1733
+ if (updated && options.onUpdate) options.onUpdate(instance);
1734
+ }
1735
+ var nestedOperation = 0;
1736
+ function operation(f) {
1737
+ return function() {
1738
+ if (!nestedOperation++) startOperation();
1739
+ try {var result = f.apply(this, arguments);}
1740
+ finally {if (!--nestedOperation) endOperation();}
1741
+ return result;
1742
+ };
1743
+ }
1744
+
1745
+ for (var ext in extensions)
1746
+ if (extensions.propertyIsEnumerable(ext) &&
1747
+ !instance.propertyIsEnumerable(ext))
1748
+ instance[ext] = extensions[ext];
1749
+ return instance;
1750
+ } // (end of function CodeMirror)
1751
+
1752
+ // The default configuration options.
1753
+ CodeMirror.defaults = {
1754
+ value: "",
1755
+ mode: null,
1756
+ theme: "default",
1757
+ indentUnit: 2,
1758
+ indentWithTabs: false,
1759
+ smartIndent: true,
1760
+ tabSize: 4,
1761
+ keyMap: "default",
1762
+ extraKeys: null,
1763
+ electricChars: true,
1764
+ onKeyEvent: null,
1765
+ lineWrapping: false,
1766
+ lineNumbers: false,
1767
+ gutter: false,
1768
+ fixedGutter: false,
1769
+ firstLineNumber: 1,
1770
+ readOnly: false,
1771
+ onChange: null,
1772
+ onCursorActivity: null,
1773
+ onGutterClick: null,
1774
+ onHighlightComplete: null,
1775
+ onUpdate: null,
1776
+ onFocus: null, onBlur: null, onScroll: null,
1777
+ matchBrackets: false,
1778
+ workTime: 100,
1779
+ workDelay: 200,
1780
+ pollInterval: 100,
1781
+ undoDepth: 40,
1782
+ tabindex: null,
1783
+ document: window.document
1784
+ };
1785
+
1786
+ var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent);
1787
+ var mac = ios || /Mac/.test(navigator.platform);
1788
+ var win = /Win/.test(navigator.platform);
1789
+
1790
+ // Known modes, by name and by MIME
1791
+ var modes = {}, mimeModes = {};
1792
+ CodeMirror.defineMode = function(name, mode) {
1793
+ if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name;
1794
+ modes[name] = mode;
1795
+ };
1796
+ CodeMirror.defineMIME = function(mime, spec) {
1797
+ mimeModes[mime] = spec;
1798
+ };
1799
+ CodeMirror.getMode = function(options, spec) {
1800
+ if (typeof spec == "string" && mimeModes.hasOwnProperty(spec))
1801
+ spec = mimeModes[spec];
1802
+ if (typeof spec == "string")
1803
+ var mname = spec, config = {};
1804
+ else if (spec != null)
1805
+ var mname = spec.name, config = spec;
1806
+ var mfactory = modes[mname];
1807
+ if (!mfactory) {
1808
+ if (window.console) console.warn("No mode " + mname + " found, falling back to plain text.");
1809
+ return CodeMirror.getMode(options, "text/plain");
1810
+ }
1811
+ return mfactory(options, config || {});
1812
+ };
1813
+ CodeMirror.listModes = function() {
1814
+ var list = [];
1815
+ for (var m in modes)
1816
+ if (modes.propertyIsEnumerable(m)) list.push(m);
1817
+ return list;
1818
+ };
1819
+ CodeMirror.listMIMEs = function() {
1820
+ var list = [];
1821
+ for (var m in mimeModes)
1822
+ if (mimeModes.propertyIsEnumerable(m)) list.push({mime: m, mode: mimeModes[m]});
1823
+ return list;
1824
+ };
1825
+
1826
+ var extensions = CodeMirror.extensions = {};
1827
+ CodeMirror.defineExtension = function(name, func) {
1828
+ extensions[name] = func;
1829
+ };
1830
+
1831
+ var commands = CodeMirror.commands = {
1832
+ selectAll: function(cm) {cm.setSelection({line: 0, ch: 0}, {line: cm.lineCount() - 1});},
1833
+ killLine: function(cm) {
1834
+ var from = cm.getCursor(true), to = cm.getCursor(false), sel = !posEq(from, to);
1835
+ if (!sel && cm.getLine(from.line).length == from.ch) cm.replaceRange("", from, {line: from.line + 1, ch: 0});
1836
+ else cm.replaceRange("", from, sel ? to : {line: from.line});
1837
+ },
1838
+ deleteLine: function(cm) {var l = cm.getCursor().line; cm.replaceRange("", {line: l, ch: 0}, {line: l});},
1839
+ undo: function(cm) {cm.undo();},
1840
+ redo: function(cm) {cm.redo();},
1841
+ goDocStart: function(cm) {cm.setCursor(0, 0, true);},
1842
+ goDocEnd: function(cm) {cm.setSelection({line: cm.lineCount() - 1}, null, true);},
1843
+ goLineStart: function(cm) {cm.setCursor(cm.getCursor().line, 0, true);},
1844
+ goLineStartSmart: function(cm) {
1845
+ var cur = cm.getCursor();
1846
+ var text = cm.getLine(cur.line), firstNonWS = Math.max(0, text.search(/\S/));
1847
+ cm.setCursor(cur.line, cur.ch <= firstNonWS && cur.ch ? 0 : firstNonWS, true);
1848
+ },
1849
+ goLineEnd: function(cm) {cm.setSelection({line: cm.getCursor().line}, null, true);},
1850
+ goLineUp: function(cm) {cm.moveV(-1, "line");},
1851
+ goLineDown: function(cm) {cm.moveV(1, "line");},
1852
+ goPageUp: function(cm) {cm.moveV(-1, "page");},
1853
+ goPageDown: function(cm) {cm.moveV(1, "page");},
1854
+ goCharLeft: function(cm) {cm.moveH(-1, "char");},
1855
+ goCharRight: function(cm) {cm.moveH(1, "char");},
1856
+ goColumnLeft: function(cm) {cm.moveH(-1, "column");},
1857
+ goColumnRight: function(cm) {cm.moveH(1, "column");},
1858
+ goWordLeft: function(cm) {cm.moveH(-1, "word");},
1859
+ goWordRight: function(cm) {cm.moveH(1, "word");},
1860
+ delCharLeft: function(cm) {cm.deleteH(-1, "char");},
1861
+ delCharRight: function(cm) {cm.deleteH(1, "char");},
1862
+ delWordLeft: function(cm) {cm.deleteH(-1, "word");},
1863
+ delWordRight: function(cm) {cm.deleteH(1, "word");},
1864
+ indentAuto: function(cm) {cm.indentSelection("smart");},
1865
+ indentMore: function(cm) {cm.indentSelection("add");},
1866
+ indentLess: function(cm) {cm.indentSelection("subtract");},
1867
+ insertTab: function(cm) {cm.replaceSelection("\t", "end");},
1868
+ transposeChars: function(cm) {
1869
+ var cur = cm.getCursor(), line = cm.getLine(cur.line);
1870
+ if (cur.ch > 0 && cur.ch < line.length - 1)
1871
+ cm.replaceRange(line.charAt(cur.ch) + line.charAt(cur.ch - 1),
1872
+ {line: cur.line, ch: cur.ch - 1}, {line: cur.line, ch: cur.ch + 1});
1873
+ },
1874
+ newlineAndIndent: function(cm) {
1875
+ cm.replaceSelection("\n", "end");
1876
+ cm.indentLine(cm.getCursor().line);
1877
+ },
1878
+ toggleOverwrite: function(cm) {cm.toggleOverwrite();}
1879
+ };
1880
+
1881
+ var keyMap = CodeMirror.keyMap = {};
1882
+ keyMap.basic = {
1883
+ "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
1884
+ "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
1885
+ "Delete": "delCharRight", "Backspace": "delCharLeft", "Tab": "indentMore", "Shift-Tab": "indentLess",
1886
+ "Enter": "newlineAndIndent", "Insert": "toggleOverwrite"
1887
+ };
1888
+ // Note that the save and find-related commands aren't defined by
1889
+ // default. Unknown commands are simply ignored.
1890
+ keyMap.pcDefault = {
1891
+ "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo",
1892
+ "Ctrl-Home": "goDocStart", "Alt-Up": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Down": "goDocEnd",
1893
+ "Ctrl-Left": "goWordLeft", "Ctrl-Right": "goWordRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",
1894
+ "Ctrl-Backspace": "delWordLeft", "Ctrl-Delete": "delWordRight", "Ctrl-S": "save", "Ctrl-F": "find",
1895
+ "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
1896
+ fallthrough: "basic"
1897
+ };
1898
+ keyMap.macDefault = {
1899
+ "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",
1900
+ "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goWordLeft",
1901
+ "Alt-Right": "goWordRight", "Cmd-Left": "goLineStart", "Cmd-Right": "goLineEnd", "Alt-Backspace": "delWordLeft",
1902
+ "Ctrl-Alt-Backspace": "delWordRight", "Alt-Delete": "delWordRight", "Cmd-S": "save", "Cmd-F": "find",
1903
+ "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
1904
+ fallthrough: ["basic", "emacsy"]
1905
+ };
1906
+ keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;
1907
+ keyMap.emacsy = {
1908
+ "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
1909
+ "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
1910
+ "Ctrl-V": "goPageUp", "Shift-Ctrl-V": "goPageDown", "Ctrl-D": "delCharRight", "Ctrl-H": "delCharLeft",
1911
+ "Alt-D": "delWordRight", "Alt-Backspace": "delWordLeft", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars"
1912
+ };
1913
+
1914
+ function lookupKey(name, extraMap, map) {
1915
+ function lookup(name, map, ft) {
1916
+ var found = map[name];
1917
+ if (found != null) return found;
1918
+ if (ft == null) ft = map.fallthrough;
1919
+ if (ft == null) return map.catchall;
1920
+ if (typeof ft == "string") return lookup(name, keyMap[ft]);
1921
+ for (var i = 0, e = ft.length; i < e; ++i) {
1922
+ found = lookup(name, keyMap[ft[i]]);
1923
+ if (found != null) return found;
1924
+ }
1925
+ return null;
1926
+ }
1927
+ return extraMap ? lookup(name, extraMap, map) : lookup(name, keyMap[map]);
1928
+ }
1929
+ function isModifierKey(event) {
1930
+ var name = keyNames[e_prop(event, "keyCode")];
1931
+ return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod";
1932
+ }
1933
+
1934
+ CodeMirror.fromTextArea = function(textarea, options) {
1935
+ if (!options) options = {};
1936
+ options.value = textarea.value;
1937
+ if (!options.tabindex && textarea.tabindex)
1938
+ options.tabindex = textarea.tabindex;
1939
+
1940
+ function save() {textarea.value = instance.getValue();}
1941
+ if (textarea.form) {
1942
+ // Deplorable hack to make the submit method do the right thing.
1943
+ var rmSubmit = connect(textarea.form, "submit", save, true);
1944
+ if (typeof textarea.form.submit == "function") {
1945
+ var realSubmit = textarea.form.submit;
1946
+ function wrappedSubmit() {
1947
+ save();
1948
+ textarea.form.submit = realSubmit;
1949
+ textarea.form.submit();
1950
+ textarea.form.submit = wrappedSubmit;
1951
+ }
1952
+ textarea.form.submit = wrappedSubmit;
1953
+ }
1954
+ }
1955
+
1956
+ textarea.style.display = "none";
1957
+ var instance = CodeMirror(function(node) {
1958
+ textarea.parentNode.insertBefore(node, textarea.nextSibling);
1959
+ }, options);
1960
+ instance.save = save;
1961
+ instance.getTextArea = function() { return textarea; };
1962
+ instance.toTextArea = function() {
1963
+ save();
1964
+ textarea.parentNode.removeChild(instance.getWrapperElement());
1965
+ textarea.style.display = "";
1966
+ if (textarea.form) {
1967
+ rmSubmit();
1968
+ if (typeof textarea.form.submit == "function")
1969
+ textarea.form.submit = realSubmit;
1970
+ }
1971
+ };
1972
+ return instance;
1973
+ };
1974
+
1975
+ // Utility functions for working with state. Exported because modes
1976
+ // sometimes need to do this.
1977
+ function copyState(mode, state) {
1978
+ if (state === true) return state;
1979
+ if (mode.copyState) return mode.copyState(state);
1980
+ var nstate = {};
1981
+ for (var n in state) {
1982
+ var val = state[n];
1983
+ if (val instanceof Array) val = val.concat([]);
1984
+ nstate[n] = val;
1985
+ }
1986
+ return nstate;
1987
+ }
1988
+ CodeMirror.copyState = copyState;
1989
+ function startState(mode, a1, a2) {
1990
+ return mode.startState ? mode.startState(a1, a2) : true;
1991
+ }
1992
+ CodeMirror.startState = startState;
1993
+
1994
+ // The character stream used by a mode's parser.
1995
+ function StringStream(string, tabSize) {
1996
+ this.pos = this.start = 0;
1997
+ this.string = string;
1998
+ this.tabSize = tabSize || 8;
1999
+ }
2000
+ StringStream.prototype = {
2001
+ eol: function() {return this.pos >= this.string.length;},
2002
+ sol: function() {return this.pos == 0;},
2003
+ peek: function() {return this.string.charAt(this.pos);},
2004
+ next: function() {
2005
+ if (this.pos < this.string.length)
2006
+ return this.string.charAt(this.pos++);
2007
+ },
2008
+ eat: function(match) {
2009
+ var ch = this.string.charAt(this.pos);
2010
+ if (typeof match == "string") var ok = ch == match;
2011
+ else var ok = ch && (match.test ? match.test(ch) : match(ch));
2012
+ if (ok) {++this.pos; return ch;}
2013
+ },
2014
+ eatWhile: function(match) {
2015
+ var start = this.pos;
2016
+ while (this.eat(match)){}
2017
+ return this.pos > start;
2018
+ },
2019
+ eatSpace: function() {
2020
+ var start = this.pos;
2021
+ while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
2022
+ return this.pos > start;
2023
+ },
2024
+ skipToEnd: function() {this.pos = this.string.length;},
2025
+ skipTo: function(ch) {
2026
+ var found = this.string.indexOf(ch, this.pos);
2027
+ if (found > -1) {this.pos = found; return true;}
2028
+ },
2029
+ backUp: function(n) {this.pos -= n;},
2030
+ column: function() {return countColumn(this.string, this.start, this.tabSize);},
2031
+ indentation: function() {return countColumn(this.string, null, this.tabSize);},
2032
+ match: function(pattern, consume, caseInsensitive) {
2033
+ if (typeof pattern == "string") {
2034
+ function cased(str) {return caseInsensitive ? str.toLowerCase() : str;}
2035
+ if (cased(this.string).indexOf(cased(pattern), this.pos) == this.pos) {
2036
+ if (consume !== false) this.pos += pattern.length;
2037
+ return true;
2038
+ }
2039
+ }
2040
+ else {
2041
+ var match = this.string.slice(this.pos).match(pattern);
2042
+ if (match && consume !== false) this.pos += match[0].length;
2043
+ return match;
2044
+ }
2045
+ },
2046
+ current: function(){return this.string.slice(this.start, this.pos);}
2047
+ };
2048
+ CodeMirror.StringStream = StringStream;
2049
+
2050
+ function MarkedText(from, to, className, set) {
2051
+ this.from = from; this.to = to; this.style = className; this.set = set;
2052
+ }
2053
+ MarkedText.prototype = {
2054
+ attach: function(line) { this.set.push(line); },
2055
+ detach: function(line) {
2056
+ var ix = indexOf(this.set, line);
2057
+ if (ix > -1) this.set.splice(ix, 1);
2058
+ },
2059
+ split: function(pos, lenBefore) {
2060
+ if (this.to <= pos && this.to != null) return null;
2061
+ var from = this.from < pos || this.from == null ? null : this.from - pos + lenBefore;
2062
+ var to = this.to == null ? null : this.to - pos + lenBefore;
2063
+ return new MarkedText(from, to, this.style, this.set);
2064
+ },
2065
+ dup: function() { return new MarkedText(null, null, this.style, this.set); },
2066
+ clipTo: function(fromOpen, from, toOpen, to, diff) {
2067
+ if (this.from != null && this.from >= from)
2068
+ this.from = Math.max(to, this.from) + diff;
2069
+ if (this.to != null && this.to > from)
2070
+ this.to = to < this.to ? this.to + diff : from;
2071
+ if (fromOpen && to > this.from && (to < this.to || this.to == null))
2072
+ this.from = null;
2073
+ if (toOpen && (from < this.to || this.to == null) && (from > this.from || this.from == null))
2074
+ this.to = null;
2075
+ },
2076
+ isDead: function() { return this.from != null && this.to != null && this.from >= this.to; },
2077
+ sameSet: function(x) { return this.set == x.set; }
2078
+ };
2079
+
2080
+ function Bookmark(pos) {
2081
+ this.from = pos; this.to = pos; this.line = null;
2082
+ }
2083
+ Bookmark.prototype = {
2084
+ attach: function(line) { this.line = line; },
2085
+ detach: function(line) { if (this.line == line) this.line = null; },
2086
+ split: function(pos, lenBefore) {
2087
+ if (pos < this.from) {
2088
+ this.from = this.to = (this.from - pos) + lenBefore;
2089
+ return this;
2090
+ }
2091
+ },
2092
+ isDead: function() { return this.from > this.to; },
2093
+ clipTo: function(fromOpen, from, toOpen, to, diff) {
2094
+ if ((fromOpen || from < this.from) && (toOpen || to > this.to)) {
2095
+ this.from = 0; this.to = -1;
2096
+ } else if (this.from > from) {
2097
+ this.from = this.to = Math.max(to, this.from) + diff;
2098
+ }
2099
+ },
2100
+ sameSet: function(x) { return false; },
2101
+ find: function() {
2102
+ if (!this.line || !this.line.parent) return null;
2103
+ return {line: lineNo(this.line), ch: this.from};
2104
+ },
2105
+ clear: function() {
2106
+ if (this.line) {
2107
+ var found = indexOf(this.line.marked, this);
2108
+ if (found != -1) this.line.marked.splice(found, 1);
2109
+ this.line = null;
2110
+ }
2111
+ }
2112
+ };
2113
+
2114
+ // Line objects. These hold state related to a line, including
2115
+ // highlighting info (the styles array).
2116
+ function Line(text, styles) {
2117
+ this.styles = styles || [text, null];
2118
+ this.text = text;
2119
+ this.height = 1;
2120
+ this.marked = this.gutterMarker = this.className = this.handlers = null;
2121
+ this.stateAfter = this.parent = this.hidden = null;
2122
+ }
2123
+ Line.inheritMarks = function(text, orig) {
2124
+ var ln = new Line(text), mk = orig && orig.marked;
2125
+ if (mk) {
2126
+ for (var i = 0; i < mk.length; ++i) {
2127
+ if (mk[i].to == null && mk[i].style) {
2128
+ var newmk = ln.marked || (ln.marked = []), mark = mk[i];
2129
+ var nmark = mark.dup(); newmk.push(nmark); nmark.attach(ln);
2130
+ }
2131
+ }
2132
+ }
2133
+ return ln;
2134
+ }
2135
+ Line.prototype = {
2136
+ // Replace a piece of a line, keeping the styles around it intact.
2137
+ replace: function(from, to_, text) {
2138
+ var st = [], mk = this.marked, to = to_ == null ? this.text.length : to_;
2139
+ copyStyles(0, from, this.styles, st);
2140
+ if (text) st.push(text, null);
2141
+ copyStyles(to, this.text.length, this.styles, st);
2142
+ this.styles = st;
2143
+ this.text = this.text.slice(0, from) + text + this.text.slice(to);
2144
+ this.stateAfter = null;
2145
+ if (mk) {
2146
+ var diff = text.length - (to - from);
2147
+ for (var i = 0; i < mk.length; ++i) {
2148
+ var mark = mk[i];
2149
+ mark.clipTo(from == null, from || 0, to_ == null, to, diff);
2150
+ if (mark.isDead()) {mark.detach(this); mk.splice(i--, 1);}
2151
+ }
2152
+ }
2153
+ },
2154
+ // Split a part off a line, keeping styles and markers intact.
2155
+ split: function(pos, textBefore) {
2156
+ var st = [textBefore, null], mk = this.marked;
2157
+ copyStyles(pos, this.text.length, this.styles, st);
2158
+ var taken = new Line(textBefore + this.text.slice(pos), st);
2159
+ if (mk) {
2160
+ for (var i = 0; i < mk.length; ++i) {
2161
+ var mark = mk[i];
2162
+ var newmark = mark.split(pos, textBefore.length);
2163
+ if (newmark) {
2164
+ if (!taken.marked) taken.marked = [];
2165
+ taken.marked.push(newmark); newmark.attach(taken);
2166
+ }
2167
+ }
2168
+ }
2169
+ return taken;
2170
+ },
2171
+ append: function(line) {
2172
+ var mylen = this.text.length, mk = line.marked, mymk = this.marked;
2173
+ this.text += line.text;
2174
+ copyStyles(0, line.text.length, line.styles, this.styles);
2175
+ if (mymk) {
2176
+ for (var i = 0; i < mymk.length; ++i)
2177
+ if (mymk[i].to == null) mymk[i].to = mylen;
2178
+ }
2179
+ if (mk && mk.length) {
2180
+ if (!mymk) this.marked = mymk = [];
2181
+ outer: for (var i = 0; i < mk.length; ++i) {
2182
+ var mark = mk[i];
2183
+ if (!mark.from) {
2184
+ for (var j = 0; j < mymk.length; ++j) {
2185
+ var mymark = mymk[j];
2186
+ if (mymark.to == mylen && mymark.sameSet(mark)) {
2187
+ mymark.to = mark.to == null ? null : mark.to + mylen;
2188
+ if (mymark.isDead()) {
2189
+ mymark.detach(this);
2190
+ mk.splice(i--, 1);
2191
+ }
2192
+ continue outer;
2193
+ }
2194
+ }
2195
+ }
2196
+ mymk.push(mark);
2197
+ mark.attach(this);
2198
+ mark.from += mylen;
2199
+ if (mark.to != null) mark.to += mylen;
2200
+ }
2201
+ }
2202
+ },
2203
+ fixMarkEnds: function(other) {
2204
+ var mk = this.marked, omk = other.marked;
2205
+ if (!mk) return;
2206
+ for (var i = 0; i < mk.length; ++i) {
2207
+ var mark = mk[i], close = mark.to == null;
2208
+ if (close && omk) {
2209
+ for (var j = 0; j < omk.length; ++j)
2210
+ if (omk[j].sameSet(mark)) {close = false; break;}
2211
+ }
2212
+ if (close) mark.to = this.text.length;
2213
+ }
2214
+ },
2215
+ fixMarkStarts: function() {
2216
+ var mk = this.marked;
2217
+ if (!mk) return;
2218
+ for (var i = 0; i < mk.length; ++i)
2219
+ if (mk[i].from == null) mk[i].from = 0;
2220
+ },
2221
+ addMark: function(mark) {
2222
+ mark.attach(this);
2223
+ if (this.marked == null) this.marked = [];
2224
+ this.marked.push(mark);
2225
+ this.marked.sort(function(a, b){return (a.from || 0) - (b.from || 0);});
2226
+ },
2227
+ // Run the given mode's parser over a line, update the styles
2228
+ // array, which contains alternating fragments of text and CSS
2229
+ // classes.
2230
+ highlight: function(mode, state, tabSize) {
2231
+ var stream = new StringStream(this.text, tabSize), st = this.styles, pos = 0;
2232
+ var changed = false, curWord = st[0], prevWord;
2233
+ if (this.text == "" && mode.blankLine) mode.blankLine(state);
2234
+ while (!stream.eol()) {
2235
+ var style = mode.token(stream, state);
2236
+ var substr = this.text.slice(stream.start, stream.pos);
2237
+ stream.start = stream.pos;
2238
+ if (pos && st[pos-1] == style)
2239
+ st[pos-2] += substr;
2240
+ else if (substr) {
2241
+ if (!changed && (st[pos+1] != style || (pos && st[pos-2] != prevWord))) changed = true;
2242
+ st[pos++] = substr; st[pos++] = style;
2243
+ prevWord = curWord; curWord = st[pos];
2244
+ }
2245
+ // Give up when line is ridiculously long
2246
+ if (stream.pos > 5000) {
2247
+ st[pos++] = this.text.slice(stream.pos); st[pos++] = null;
2248
+ break;
2249
+ }
2250
+ }
2251
+ if (st.length != pos) {st.length = pos; changed = true;}
2252
+ if (pos && st[pos-2] != prevWord) changed = true;
2253
+ // Short lines with simple highlights return null, and are
2254
+ // counted as changed by the driver because they are likely to
2255
+ // highlight the same way in various contexts.
2256
+ return changed || (st.length < 5 && this.text.length < 10 ? null : false);
2257
+ },
2258
+ // Fetch the parser token for a given character. Useful for hacks
2259
+ // that want to inspect the mode state (say, for completion).
2260
+ getTokenAt: function(mode, state, ch) {
2261
+ var txt = this.text, stream = new StringStream(txt);
2262
+ while (stream.pos < ch && !stream.eol()) {
2263
+ stream.start = stream.pos;
2264
+ var style = mode.token(stream, state);
2265
+ }
2266
+ return {start: stream.start,
2267
+ end: stream.pos,
2268
+ string: stream.current(),
2269
+ className: style || null,
2270
+ state: state};
2271
+ },
2272
+ indentation: function(tabSize) {return countColumn(this.text, null, tabSize);},
2273
+ // Produces an HTML fragment for the line, taking selection,
2274
+ // marking, and highlighting into account.
2275
+ getHTML: function(tabText, endAt) {
2276
+ var html = [], first = true;
2277
+ function span(text, style) {
2278
+ if (!text) return;
2279
+ // Work around a bug where, in some compat modes, IE ignores leading spaces
2280
+ if (first && ie && text.charAt(0) == " ") text = "\u00a0" + text.slice(1);
2281
+ first = false;
2282
+ if (style) html.push('<span class="', style, '">', htmlEscape(text).replace(/\t/g, tabText), "</span>");
2283
+ else html.push(htmlEscape(text).replace(/\t/g, tabText));
2284
+ }
2285
+ var st = this.styles, allText = this.text, marked = this.marked;
2286
+ var len = allText.length;
2287
+ if (endAt != null) len = Math.min(endAt, len);
2288
+ function styleToClass(style) {
2289
+ if (!style) return null;
2290
+ return "cm-" + style.replace(/ +/g, " cm-");
2291
+ }
2292
+
2293
+ if (!allText && endAt == null)
2294
+ span(" ");
2295
+ else if (!marked || !marked.length)
2296
+ for (var i = 0, ch = 0; ch < len; i+=2) {
2297
+ var str = st[i], style = st[i+1], l = str.length;
2298
+ if (ch + l > len) str = str.slice(0, len - ch);
2299
+ ch += l;
2300
+ span(str, styleToClass(style));
2301
+ }
2302
+ else {
2303
+ var pos = 0, i = 0, text = "", style, sg = 0;
2304
+ var nextChange = marked[0].from || 0, marks = [], markpos = 0;
2305
+ function advanceMarks() {
2306
+ var m;
2307
+ while (markpos < marked.length &&
2308
+ ((m = marked[markpos]).from == pos || m.from == null)) {
2309
+ if (m.style != null) marks.push(m);
2310
+ ++markpos;
2311
+ }
2312
+ nextChange = markpos < marked.length ? marked[markpos].from : Infinity;
2313
+ for (var i = 0; i < marks.length; ++i) {
2314
+ var to = marks[i].to || Infinity;
2315
+ if (to == pos) marks.splice(i--, 1);
2316
+ else nextChange = Math.min(to, nextChange);
2317
+ }
2318
+ }
2319
+ var m = 0;
2320
+ while (pos < len) {
2321
+ if (nextChange == pos) advanceMarks();
2322
+ var upto = Math.min(len, nextChange);
2323
+ while (true) {
2324
+ if (text) {
2325
+ var end = pos + text.length;
2326
+ var appliedStyle = style;
2327
+ for (var j = 0; j < marks.length; ++j)
2328
+ appliedStyle = (appliedStyle ? appliedStyle + " " : "") + marks[j].style;
2329
+ span(end > upto ? text.slice(0, upto - pos) : text, appliedStyle);
2330
+ if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}
2331
+ pos = end;
2332
+ }
2333
+ text = st[i++]; style = styleToClass(st[i++]);
2334
+ }
2335
+ }
2336
+ }
2337
+ return html.join("");
2338
+ },
2339
+ cleanUp: function() {
2340
+ this.parent = null;
2341
+ if (this.marked)
2342
+ for (var i = 0, e = this.marked.length; i < e; ++i) this.marked[i].detach(this);
2343
+ }
2344
+ };
2345
+ // Utility used by replace and split above
2346
+ function copyStyles(from, to, source, dest) {
2347
+ for (var i = 0, pos = 0, state = 0; pos < to; i+=2) {
2348
+ var part = source[i], end = pos + part.length;
2349
+ if (state == 0) {
2350
+ if (end > from) dest.push(part.slice(from - pos, Math.min(part.length, to - pos)), source[i+1]);
2351
+ if (end >= from) state = 1;
2352
+ }
2353
+ else if (state == 1) {
2354
+ if (end > to) dest.push(part.slice(0, to - pos), source[i+1]);
2355
+ else dest.push(part, source[i+1]);
2356
+ }
2357
+ pos = end;
2358
+ }
2359
+ }
2360
+
2361
+ // Data structure that holds the sequence of lines.
2362
+ function LeafChunk(lines) {
2363
+ this.lines = lines;
2364
+ this.parent = null;
2365
+ for (var i = 0, e = lines.length, height = 0; i < e; ++i) {
2366
+ lines[i].parent = this;
2367
+ height += lines[i].height;
2368
+ }
2369
+ this.height = height;
2370
+ }
2371
+ LeafChunk.prototype = {
2372
+ chunkSize: function() { return this.lines.length; },
2373
+ remove: function(at, n, callbacks) {
2374
+ for (var i = at, e = at + n; i < e; ++i) {
2375
+ var line = this.lines[i];
2376
+ this.height -= line.height;
2377
+ line.cleanUp();
2378
+ if (line.handlers)
2379
+ for (var j = 0; j < line.handlers.length; ++j) callbacks.push(line.handlers[j]);
2380
+ }
2381
+ this.lines.splice(at, n);
2382
+ },
2383
+ collapse: function(lines) {
2384
+ lines.splice.apply(lines, [lines.length, 0].concat(this.lines));
2385
+ },
2386
+ insertHeight: function(at, lines, height) {
2387
+ this.height += height;
2388
+ this.lines.splice.apply(this.lines, [at, 0].concat(lines));
2389
+ for (var i = 0, e = lines.length; i < e; ++i) lines[i].parent = this;
2390
+ },
2391
+ iterN: function(at, n, op) {
2392
+ for (var e = at + n; at < e; ++at)
2393
+ if (op(this.lines[at])) return true;
2394
+ }
2395
+ };
2396
+ function BranchChunk(children) {
2397
+ this.children = children;
2398
+ var size = 0, height = 0;
2399
+ for (var i = 0, e = children.length; i < e; ++i) {
2400
+ var ch = children[i];
2401
+ size += ch.chunkSize(); height += ch.height;
2402
+ ch.parent = this;
2403
+ }
2404
+ this.size = size;
2405
+ this.height = height;
2406
+ this.parent = null;
2407
+ }
2408
+ BranchChunk.prototype = {
2409
+ chunkSize: function() { return this.size; },
2410
+ remove: function(at, n, callbacks) {
2411
+ this.size -= n;
2412
+ for (var i = 0; i < this.children.length; ++i) {
2413
+ var child = this.children[i], sz = child.chunkSize();
2414
+ if (at < sz) {
2415
+ var rm = Math.min(n, sz - at), oldHeight = child.height;
2416
+ child.remove(at, rm, callbacks);
2417
+ this.height -= oldHeight - child.height;
2418
+ if (sz == rm) { this.children.splice(i--, 1); child.parent = null; }
2419
+ if ((n -= rm) == 0) break;
2420
+ at = 0;
2421
+ } else at -= sz;
2422
+ }
2423
+ if (this.size - n < 25) {
2424
+ var lines = [];
2425
+ this.collapse(lines);
2426
+ this.children = [new LeafChunk(lines)];
2427
+ this.children[0].parent = this;
2428
+ }
2429
+ },
2430
+ collapse: function(lines) {
2431
+ for (var i = 0, e = this.children.length; i < e; ++i) this.children[i].collapse(lines);
2432
+ },
2433
+ insert: function(at, lines) {
2434
+ var height = 0;
2435
+ for (var i = 0, e = lines.length; i < e; ++i) height += lines[i].height;
2436
+ this.insertHeight(at, lines, height);
2437
+ },
2438
+ insertHeight: function(at, lines, height) {
2439
+ this.size += lines.length;
2440
+ this.height += height;
2441
+ for (var i = 0, e = this.children.length; i < e; ++i) {
2442
+ var child = this.children[i], sz = child.chunkSize();
2443
+ if (at <= sz) {
2444
+ child.insertHeight(at, lines, height);
2445
+ if (child.lines && child.lines.length > 50) {
2446
+ while (child.lines.length > 50) {
2447
+ var spilled = child.lines.splice(child.lines.length - 25, 25);
2448
+ var newleaf = new LeafChunk(spilled);
2449
+ child.height -= newleaf.height;
2450
+ this.children.splice(i + 1, 0, newleaf);
2451
+ newleaf.parent = this;
2452
+ }
2453
+ this.maybeSpill();
2454
+ }
2455
+ break;
2456
+ }
2457
+ at -= sz;
2458
+ }
2459
+ },
2460
+ maybeSpill: function() {
2461
+ if (this.children.length <= 10) return;
2462
+ var me = this;
2463
+ do {
2464
+ var spilled = me.children.splice(me.children.length - 5, 5);
2465
+ var sibling = new BranchChunk(spilled);
2466
+ if (!me.parent) { // Become the parent node
2467
+ var copy = new BranchChunk(me.children);
2468
+ copy.parent = me;
2469
+ me.children = [copy, sibling];
2470
+ me = copy;
2471
+ } else {
2472
+ me.size -= sibling.size;
2473
+ me.height -= sibling.height;
2474
+ var myIndex = indexOf(me.parent.children, me);
2475
+ me.parent.children.splice(myIndex + 1, 0, sibling);
2476
+ }
2477
+ sibling.parent = me.parent;
2478
+ } while (me.children.length > 10);
2479
+ me.parent.maybeSpill();
2480
+ },
2481
+ iter: function(from, to, op) { this.iterN(from, to - from, op); },
2482
+ iterN: function(at, n, op) {
2483
+ for (var i = 0, e = this.children.length; i < e; ++i) {
2484
+ var child = this.children[i], sz = child.chunkSize();
2485
+ if (at < sz) {
2486
+ var used = Math.min(n, sz - at);
2487
+ if (child.iterN(at, used, op)) return true;
2488
+ if ((n -= used) == 0) break;
2489
+ at = 0;
2490
+ } else at -= sz;
2491
+ }
2492
+ }
2493
+ };
2494
+
2495
+ function getLineAt(chunk, n) {
2496
+ while (!chunk.lines) {
2497
+ for (var i = 0;; ++i) {
2498
+ var child = chunk.children[i], sz = child.chunkSize();
2499
+ if (n < sz) { chunk = child; break; }
2500
+ n -= sz;
2501
+ }
2502
+ }
2503
+ return chunk.lines[n];
2504
+ }
2505
+ function lineNo(line) {
2506
+ if (line.parent == null) return null;
2507
+ var cur = line.parent, no = indexOf(cur.lines, line);
2508
+ for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) {
2509
+ for (var i = 0, e = chunk.children.length; ; ++i) {
2510
+ if (chunk.children[i] == cur) break;
2511
+ no += chunk.children[i].chunkSize();
2512
+ }
2513
+ }
2514
+ return no;
2515
+ }
2516
+ function lineAtHeight(chunk, h) {
2517
+ var n = 0;
2518
+ outer: do {
2519
+ for (var i = 0, e = chunk.children.length; i < e; ++i) {
2520
+ var child = chunk.children[i], ch = child.height;
2521
+ if (h < ch) { chunk = child; continue outer; }
2522
+ h -= ch;
2523
+ n += child.chunkSize();
2524
+ }
2525
+ return n;
2526
+ } while (!chunk.lines);
2527
+ for (var i = 0, e = chunk.lines.length; i < e; ++i) {
2528
+ var line = chunk.lines[i], lh = line.height;
2529
+ if (h < lh) break;
2530
+ h -= lh;
2531
+ }
2532
+ return n + i;
2533
+ }
2534
+ function heightAtLine(chunk, n) {
2535
+ var h = 0;
2536
+ outer: do {
2537
+ for (var i = 0, e = chunk.children.length; i < e; ++i) {
2538
+ var child = chunk.children[i], sz = child.chunkSize();
2539
+ if (n < sz) { chunk = child; continue outer; }
2540
+ n -= sz;
2541
+ h += child.height;
2542
+ }
2543
+ return h;
2544
+ } while (!chunk.lines);
2545
+ for (var i = 0; i < n; ++i) h += chunk.lines[i].height;
2546
+ return h;
2547
+ }
2548
+
2549
+ // The history object 'chunks' changes that are made close together
2550
+ // and at almost the same time into bigger undoable units.
2551
+ function History() {
2552
+ this.time = 0;
2553
+ this.done = []; this.undone = [];
2554
+ }
2555
+ History.prototype = {
2556
+ addChange: function(start, added, old) {
2557
+ this.undone.length = 0;
2558
+ var time = +new Date, cur = this.done[this.done.length - 1], last = cur && cur[cur.length - 1];
2559
+ var dtime = time - this.time;
2560
+ if (dtime > 400 || !last) {
2561
+ this.done.push([{start: start, added: added, old: old}]);
2562
+ } else if (last.start > start + added || last.start + last.added < start - last.added + last.old.length) {
2563
+ cur.push({start: start, added: added, old: old});
2564
+ } else {
2565
+ var oldoff = 0;
2566
+ if (start < last.start) {
2567
+ for (var i = last.start - start - 1; i >= 0; --i)
2568
+ last.old.unshift(old[i]);
2569
+ last.added += last.start - start;
2570
+ last.start = start;
2571
+ }
2572
+ else if (last.start < start) {
2573
+ oldoff = start - last.start;
2574
+ added += oldoff;
2575
+ }
2576
+ for (var i = last.added - oldoff, e = old.length; i < e; ++i)
2577
+ last.old.push(old[i]);
2578
+ if (last.added < added) last.added = added;
2579
+ }
2580
+ this.time = time;
2581
+ }
2582
+ };
2583
+
2584
+ function stopMethod() {e_stop(this);}
2585
+ // Ensure an event has a stop method.
2586
+ function addStop(event) {
2587
+ if (!event.stop) event.stop = stopMethod;
2588
+ return event;
2589
+ }
2590
+
2591
+ function e_preventDefault(e) {
2592
+ if (e.preventDefault) e.preventDefault();
2593
+ else e.returnValue = false;
2594
+ }
2595
+ function e_stopPropagation(e) {
2596
+ if (e.stopPropagation) e.stopPropagation();
2597
+ else e.cancelBubble = true;
2598
+ }
2599
+ function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);}
2600
+ CodeMirror.e_stop = e_stop;
2601
+ CodeMirror.e_preventDefault = e_preventDefault;
2602
+ CodeMirror.e_stopPropagation = e_stopPropagation;
2603
+
2604
+ function e_target(e) {return e.target || e.srcElement;}
2605
+ function e_button(e) {
2606
+ if (e.which) return e.which;
2607
+ else if (e.button & 1) return 1;
2608
+ else if (e.button & 2) return 3;
2609
+ else if (e.button & 4) return 2;
2610
+ }
2611
+
2612
+ // Allow 3rd-party code to override event properties by adding an override
2613
+ // object to an event object.
2614
+ function e_prop(e, prop) {
2615
+ var overridden = e.override && e.override.hasOwnProperty(prop);
2616
+ return overridden ? e.override[prop] : e[prop];
2617
+ }
2618
+
2619
+ // Event handler registration. If disconnect is true, it'll return a
2620
+ // function that unregisters the handler.
2621
+ function connect(node, type, handler, disconnect) {
2622
+ if (typeof node.addEventListener == "function") {
2623
+ node.addEventListener(type, handler, false);
2624
+ if (disconnect) return function() {node.removeEventListener(type, handler, false);};
2625
+ }
2626
+ else {
2627
+ var wrapHandler = function(event) {handler(event || window.event);};
2628
+ node.attachEvent("on" + type, wrapHandler);
2629
+ if (disconnect) return function() {node.detachEvent("on" + type, wrapHandler);};
2630
+ }
2631
+ }
2632
+ CodeMirror.connect = connect;
2633
+
2634
+ function Delayed() {this.id = null;}
2635
+ Delayed.prototype = {set: function(ms, f) {clearTimeout(this.id); this.id = setTimeout(f, ms);}};
2636
+
2637
+ // Detect drag-and-drop
2638
+ var dragAndDrop = function() {
2639
+ // IE8 has ondragstart and ondrop properties, but doesn't seem to
2640
+ // actually support ondragstart the way it's supposed to work.
2641
+ if (/MSIE [1-8]\b/.test(navigator.userAgent)) return false;
2642
+ var div = document.createElement('div');
2643
+ return "draggable" in div;
2644
+ }();
2645
+
2646
+ var gecko = /gecko\/\d{7}/i.test(navigator.userAgent);
2647
+ var ie = /MSIE \d/.test(navigator.userAgent);
2648
+ var webkit = /WebKit\//.test(navigator.userAgent);
2649
+
2650
+ var lineSep = "\n";
2651
+ // Feature-detect whether newlines in textareas are converted to \r\n
2652
+ (function () {
2653
+ var te = document.createElement("textarea");
2654
+ te.value = "foo\nbar";
2655
+ if (te.value.indexOf("\r") > -1) lineSep = "\r\n";
2656
+ }());
2657
+
2658
+ // Counts the column offset in a string, taking tabs into account.
2659
+ // Used mostly to find indentation.
2660
+ function countColumn(string, end, tabSize) {
2661
+ if (end == null) {
2662
+ end = string.search(/[^\s\u00a0]/);
2663
+ if (end == -1) end = string.length;
2664
+ }
2665
+ for (var i = 0, n = 0; i < end; ++i) {
2666
+ if (string.charAt(i) == "\t") n += tabSize - (n % tabSize);
2667
+ else ++n;
2668
+ }
2669
+ return n;
2670
+ }
2671
+
2672
+ function computedStyle(elt) {
2673
+ if (elt.currentStyle) return elt.currentStyle;
2674
+ return window.getComputedStyle(elt, null);
2675
+ }
2676
+
2677
+ // Find the position of an element by following the offsetParent chain.
2678
+ // If screen==true, it returns screen (rather than page) coordinates.
2679
+ function eltOffset(node, screen) {
2680
+ var bod = node.ownerDocument.body;
2681
+ var x = 0, y = 0, skipBody = false;
2682
+ for (var n = node; n; n = n.offsetParent) {
2683
+ var ol = n.offsetLeft, ot = n.offsetTop;
2684
+ // Firefox reports weird inverted offsets when the body has a border.
2685
+ if (n == bod) { x += Math.abs(ol); y += Math.abs(ot); }
2686
+ else { x += ol, y += ot; }
2687
+ if (screen && computedStyle(n).position == "fixed")
2688
+ skipBody = true;
2689
+ }
2690
+ var e = screen && !skipBody ? null : bod;
2691
+ for (var n = node.parentNode; n != e; n = n.parentNode)
2692
+ if (n.scrollLeft != null) { x -= n.scrollLeft; y -= n.scrollTop;}
2693
+ return {left: x, top: y};
2694
+ }
2695
+ // Use the faster and saner getBoundingClientRect method when possible.
2696
+ if (document.documentElement.getBoundingClientRect != null) eltOffset = function(node, screen) {
2697
+ // Take the parts of bounding client rect that we are interested in so we are able to edit if need be,
2698
+ // since the returned value cannot be changed externally (they are kept in sync as the element moves within the page)
2699
+ try { var box = node.getBoundingClientRect(); box = { top: box.top, left: box.left }; }
2700
+ catch(e) { box = {top: 0, left: 0}; }
2701
+ if (!screen) {
2702
+ // Get the toplevel scroll, working around browser differences.
2703
+ if (window.pageYOffset == null) {
2704
+ var t = document.documentElement || document.body.parentNode;
2705
+ if (t.scrollTop == null) t = document.body;
2706
+ box.top += t.scrollTop; box.left += t.scrollLeft;
2707
+ } else {
2708
+ box.top += window.pageYOffset; box.left += window.pageXOffset;
2709
+ }
2710
+ }
2711
+ return box;
2712
+ };
2713
+
2714
+ // Get a node's text content.
2715
+ function eltText(node) {
2716
+ return node.textContent || node.innerText || node.nodeValue || "";
2717
+ }
2718
+ function selectInput(node) {
2719
+ if (ios) { // Mobile Safari apparently has a bug where select() is broken.
2720
+ node.selectionStart = 0;
2721
+ node.selectionEnd = node.value.length;
2722
+ } else node.select();
2723
+ }
2724
+
2725
+ // Operations on {line, ch} objects.
2726
+ function posEq(a, b) {return a.line == b.line && a.ch == b.ch;}
2727
+ function posLess(a, b) {return a.line < b.line || (a.line == b.line && a.ch < b.ch);}
2728
+ function copyPos(x) {return {line: x.line, ch: x.ch};}
2729
+
2730
+ var escapeElement = document.createElement("pre");
2731
+ function htmlEscape(str) {
2732
+ escapeElement.textContent = str;
2733
+ return escapeElement.innerHTML;
2734
+ }
2735
+ // Recent (late 2011) Opera betas insert bogus newlines at the start
2736
+ // of the textContent, so we strip those.
2737
+ if (htmlEscape("a") == "\na")
2738
+ htmlEscape = function(str) {
2739
+ escapeElement.textContent = str;
2740
+ return escapeElement.innerHTML.slice(1);
2741
+ };
2742
+ // Some IEs don't preserve tabs through innerHTML
2743
+ else if (htmlEscape("\t") != "\t")
2744
+ htmlEscape = function(str) {
2745
+ escapeElement.innerHTML = "";
2746
+ escapeElement.appendChild(document.createTextNode(str));
2747
+ return escapeElement.innerHTML;
2748
+ };
2749
+ CodeMirror.htmlEscape = htmlEscape;
2750
+
2751
+ // Used to position the cursor after an undo/redo by finding the
2752
+ // last edited character.
2753
+ function editEnd(from, to) {
2754
+ if (!to) return 0;
2755
+ if (!from) return to.length;
2756
+ for (var i = from.length, j = to.length; i >= 0 && j >= 0; --i, --j)
2757
+ if (from.charAt(i) != to.charAt(j)) break;
2758
+ return j + 1;
2759
+ }
2760
+
2761
+ function indexOf(collection, elt) {
2762
+ if (collection.indexOf) return collection.indexOf(elt);
2763
+ for (var i = 0, e = collection.length; i < e; ++i)
2764
+ if (collection[i] == elt) return i;
2765
+ return -1;
2766
+ }
2767
+ function isWordChar(ch) {
2768
+ return /\w/.test(ch) || ch.toUpperCase() != ch.toLowerCase();
2769
+ }
2770
+
2771
+ // See if "".split is the broken IE version, if so, provide an
2772
+ // alternative way to split lines.
2773
+ var splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) {
2774
+ var pos = 0, nl, result = [];
2775
+ while ((nl = string.indexOf("\n", pos)) > -1) {
2776
+ result.push(string.slice(pos, string.charAt(nl-1) == "\r" ? nl - 1 : nl));
2777
+ pos = nl + 1;
2778
+ }
2779
+ result.push(string.slice(pos));
2780
+ return result;
2781
+ } : function(string){return string.split(/\r?\n/);};
2782
+ CodeMirror.splitLines = splitLines;
2783
+
2784
+ var hasSelection = window.getSelection ? function(te) {
2785
+ try { return te.selectionStart != te.selectionEnd; }
2786
+ catch(e) { return false; }
2787
+ } : function(te) {
2788
+ try {var range = te.ownerDocument.selection.createRange();}
2789
+ catch(e) {}
2790
+ if (!range || range.parentElement() != te) return false;
2791
+ return range.compareEndPoints("StartToEnd", range) != 0;
2792
+ };
2793
+
2794
+ CodeMirror.defineMode("null", function() {
2795
+ return {token: function(stream) {stream.skipToEnd();}};
2796
+ });
2797
+ CodeMirror.defineMIME("text/plain", "null");
2798
+
2799
+ var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
2800
+ 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
2801
+ 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
2802
+ 46: "Delete", 59: ";", 91: "Mod", 92: "Mod", 93: "Mod", 186: ";", 187: "=", 188: ",",
2803
+ 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\", 221: "]", 222: "'", 63276: "PageUp",
2804
+ 63277: "PageDown", 63275: "End", 63273: "Home", 63234: "Left", 63232: "Up", 63235: "Right",
2805
+ 63233: "Down", 63302: "Insert", 63272: "Delete"};
2806
+ CodeMirror.keyNames = keyNames;
2807
+ (function() {
2808
+ // Number keys
2809
+ for (var i = 0; i < 10; i++) keyNames[i + 48] = String(i);
2810
+ // Alphabetic keys
2811
+ for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i);
2812
+ // Function keys
2813
+ for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i;
2814
+ })();
2815
+
2816
+ return CodeMirror;
2817
+ })();
functions/admin-page-class/js/codemirror/css.js ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ CodeMirror.defineMode("css", function(config) {
2
+ var indentUnit = config.indentUnit, type;
3
+ function ret(style, tp) {type = tp; return style;}
4
+
5
+ function tokenBase(stream, state) {
6
+ var ch = stream.next();
7
+ if (ch == "@") {stream.eatWhile(/[\w\\\-]/); return ret("meta", stream.current());}
8
+ else if (ch == "/" && stream.eat("*")) {
9
+ state.tokenize = tokenCComment;
10
+ return tokenCComment(stream, state);
11
+ }
12
+ else if (ch == "<" && stream.eat("!")) {
13
+ state.tokenize = tokenSGMLComment;
14
+ return tokenSGMLComment(stream, state);
15
+ }
16
+ else if (ch == "=") ret(null, "compare");
17
+ else if ((ch == "~" || ch == "|") && stream.eat("=")) return ret(null, "compare");
18
+ else if (ch == "\"" || ch == "'") {
19
+ state.tokenize = tokenString(ch);
20
+ return state.tokenize(stream, state);
21
+ }
22
+ else if (ch == "#") {
23
+ stream.eatWhile(/[\w\\\-]/);
24
+ return ret("atom", "hash");
25
+ }
26
+ else if (ch == "!") {
27
+ stream.match(/^\s*\w*/);
28
+ return ret("keyword", "important");
29
+ }
30
+ else if (/\d/.test(ch)) {
31
+ stream.eatWhile(/[\w.%]/);
32
+ return ret("number", "unit");
33
+ }
34
+ else if (/[,.+>*\/]/.test(ch)) {
35
+ return ret(null, "select-op");
36
+ }
37
+ else if (/[;{}:\[\]]/.test(ch)) {
38
+ return ret(null, ch);
39
+ }
40
+ else {
41
+ stream.eatWhile(/[\w\\\-]/);
42
+ return ret("variable", "variable");
43
+ }
44
+ }
45
+
46
+ function tokenCComment(stream, state) {
47
+ var maybeEnd = false, ch;
48
+ while ((ch = stream.next()) != null) {
49
+ if (maybeEnd && ch == "/") {
50
+ state.tokenize = tokenBase;
51
+ break;
52
+ }
53
+ maybeEnd = (ch == "*");
54
+ }
55
+ return ret("comment", "comment");
56
+ }
57
+
58
+ function tokenSGMLComment(stream, state) {
59
+ var dashes = 0, ch;
60
+ while ((ch = stream.next()) != null) {
61
+ if (dashes >= 2 && ch == ">") {
62
+ state.tokenize = tokenBase;
63
+ break;
64
+ }
65
+ dashes = (ch == "-") ? dashes + 1 : 0;
66
+ }
67
+ return ret("comment", "comment");
68
+ }
69
+
70
+ function tokenString(quote) {
71
+ return function(stream, state) {
72
+ var escaped = false, ch;
73
+ while ((ch = stream.next()) != null) {
74
+ if (ch == quote && !escaped)
75
+ break;
76
+ escaped = !escaped && ch == "\\";
77
+ }
78
+ if (!escaped) state.tokenize = tokenBase;
79
+ return ret("string", "string");
80
+ };
81
+ }
82
+
83
+ return {
84
+ startState: function(base) {
85
+ return {tokenize: tokenBase,
86
+ baseIndent: base || 0,
87
+ stack: []};
88
+ },
89
+
90
+ token: function(stream, state) {
91
+ if (stream.eatSpace()) return null;
92
+ var style = state.tokenize(stream, state);
93
+
94
+ var context = state.stack[state.stack.length-1];
95
+ if (type == "hash" && context == "rule") style = "atom";
96
+ else if (style == "variable") {
97
+ if (context == "rule") style = "number";
98
+ else if (!context || context == "@media{") style = "tag";
99
+ }
100
+
101
+ if (context == "rule" && /^[\{\};]$/.test(type))
102
+ state.stack.pop();
103
+ if (type == "{") {
104
+ if (context == "@media") state.stack[state.stack.length-1] = "@media{";
105
+ else state.stack.push("{");
106
+ }
107
+ else if (type == "}") state.stack.pop();
108
+ else if (type == "@media") state.stack.push("@media");
109
+ else if (context == "{" && type != "comment") state.stack.push("rule");
110
+ return style;
111
+ },
112
+
113
+ indent: function(state, textAfter) {
114
+ var n = state.stack.length;
115
+ if (/^\}/.test(textAfter))
116
+ n -= state.stack[state.stack.length-1] == "rule" ? 2 : 1;
117
+ return state.baseIndent + n * indentUnit;
118
+ },
119
+
120
+ electricChars: "}"
121
+ };
122
+ });
123
+
124
+ CodeMirror.defineMIME("text/css", "css");
functions/admin-page-class/js/codemirror/javascript.js ADDED
@@ -0,0 +1,360 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ CodeMirror.defineMode("javascript", function(config, parserConfig) {
2
+ var indentUnit = config.indentUnit;
3
+ var jsonMode = parserConfig.json;
4
+
5
+ // Tokenizer
6
+
7
+ var keywords = function(){
8
+ function kw(type) {return {type: type, style: "keyword"};}
9
+ var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c");
10
+ var operator = kw("operator"), atom = {type: "atom", style: "atom"};
11
+ return {
12
+ "if": A, "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
13
+ "return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C,
14
+ "var": kw("var"), "const": kw("var"), "let": kw("var"),
15
+ "function": kw("function"), "catch": kw("catch"),
16
+ "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
17
+ "in": operator, "typeof": operator, "instanceof": operator,
18
+ "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom
19
+ };
20
+ }();
21
+
22
+ var isOperatorChar = /[+\-*&%=<>!?|]/;
23
+
24
+ function chain(stream, state, f) {
25
+ state.tokenize = f;
26
+ return f(stream, state);
27
+ }
28
+
29
+ function nextUntilUnescaped(stream, end) {
30
+ var escaped = false, next;
31
+ while ((next = stream.next()) != null) {
32
+ if (next == end && !escaped)
33
+ return false;
34
+ escaped = !escaped && next == "\\";
35
+ }
36
+ return escaped;
37
+ }
38
+
39
+ // Used as scratch variables to communicate multiple values without
40
+ // consing up tons of objects.
41
+ var type, content;
42
+ function ret(tp, style, cont) {
43
+ type = tp; content = cont;
44
+ return style;
45
+ }
46
+
47
+ function jsTokenBase(stream, state) {
48
+ var ch = stream.next();
49
+ if (ch == '"' || ch == "'")
50
+ return chain(stream, state, jsTokenString(ch));
51
+ else if (/[\[\]{}\(\),;\:\.]/.test(ch))
52
+ return ret(ch);
53
+ else if (ch == "0" && stream.eat(/x/i)) {
54
+ stream.eatWhile(/[\da-f]/i);
55
+ return ret("number", "number");
56
+ }
57
+ else if (/\d/.test(ch)) {
58
+ stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
59
+ return ret("number", "number");
60
+ }
61
+ else if (ch == "/") {
62
+ if (stream.eat("*")) {
63
+ return chain(stream, state, jsTokenComment);
64
+ }
65
+ else if (stream.eat("/")) {
66
+ stream.skipToEnd();
67
+ return ret("comment", "comment");
68
+ }
69
+ else if (state.reAllowed) {
70
+ nextUntilUnescaped(stream, "/");
71
+ stream.eatWhile(/[gimy]/); // 'y' is "sticky" option in Mozilla
72
+ return ret("regexp", "string-2");
73
+ }
74
+ else {
75
+ stream.eatWhile(isOperatorChar);
76
+ return ret("operator", null, stream.current());
77
+ }
78
+ }
79
+ else if (ch == "#") {
80
+ stream.skipToEnd();
81
+ return ret("error", "error");
82
+ }
83
+ else if (isOperatorChar.test(ch)) {
84
+ stream.eatWhile(isOperatorChar);
85
+ return ret("operator", null, stream.current());
86
+ }
87
+ else {
88
+ stream.eatWhile(/[\w\$_]/);
89
+ var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];
90
+ return (known && state.kwAllowed) ? ret(known.type, known.style, word) :
91
+ ret("variable", "variable", word);
92
+ }
93
+ }
94
+
95
+ function jsTokenString(quote) {
96
+ return function(stream, state) {
97
+ if (!nextUntilUnescaped(stream, quote))
98
+ state.tokenize = jsTokenBase;
99
+ return ret("string", "string");
100
+ };
101
+ }
102
+
103
+ function jsTokenComment(stream, state) {
104
+ var maybeEnd = false, ch;
105
+ while (ch = stream.next()) {
106
+ if (ch == "/" && maybeEnd) {
107
+ state.tokenize = jsTokenBase;
108
+ break;
109
+ }
110
+ maybeEnd = (ch == "*");
111
+ }
112
+ return ret("comment", "comment");
113
+ }
114
+
115
+ // Parser
116
+
117
+ var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true};
118
+
119
+ function JSLexical(indented, column, type, align, prev, info) {
120
+ this.indented = indented;
121
+ this.column = column;
122
+ this.type = type;
123
+ this.prev = prev;
124
+ this.info = info;
125
+ if (align != null) this.align = align;
126
+ }
127
+
128
+ function inScope(state, varname) {
129
+ for (var v = state.localVars; v; v = v.next)
130
+ if (v.name == varname) return true;
131
+ }
132
+
133
+ function parseJS(state, style, type, content, stream) {
134
+ var cc = state.cc;
135
+ // Communicate our context to the combinators.
136
+ // (Less wasteful than consing up a hundred closures on every call.)
137
+ cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc;
138
+
139
+ if (!state.lexical.hasOwnProperty("align"))
140
+ state.lexical.align = true;
141
+
142
+ while(true) {
143
+ var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;
144
+ if (combinator(type, content)) {
145
+ while(cc.length && cc[cc.length - 1].lex)
146
+ cc.pop()();
147
+ if (cx.marked) return cx.marked;
148
+ if (type == "variable" && inScope(state, content)) return "variable-2";
149
+ return style;
150
+ }
151
+ }
152
+ }
153
+
154
+ // Combinator utils
155
+
156
+ var cx = {state: null, column: null, marked: null, cc: null};
157
+ function pass() {
158
+ for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
159
+ }
160
+ function cont() {
161
+ pass.apply(null, arguments);
162
+ return true;
163
+ }
164
+ function register(varname) {
165
+ var state = cx.state;
166
+ if (state.context) {
167
+ cx.marked = "def";
168
+ for (var v = state.localVars; v; v = v.next)
169
+ if (v.name == varname) return;
170
+ state.localVars = {name: varname, next: state.localVars};
171
+ }
172
+ }
173
+
174
+ // Combinators
175
+
176
+ var defaultVars = {name: "this", next: {name: "arguments"}};
177
+ function pushcontext() {
178
+ if (!cx.state.context) cx.state.localVars = defaultVars;
179
+ cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};
180
+ }
181
+ function popcontext() {
182
+ cx.state.localVars = cx.state.context.vars;
183
+ cx.state.context = cx.state.context.prev;
184
+ }
185
+ function pushlex(type, info) {
186
+ var result = function() {
187
+ var state = cx.state;
188
+ state.lexical = new JSLexical(state.indented, cx.stream.column(), type, null, state.lexical, info)
189
+ };
190
+ result.lex = true;
191
+ return result;
192
+ }
193
+ function poplex() {
194
+ var state = cx.state;
195
+ if (state.lexical.prev) {
196
+ if (state.lexical.type == ")")
197
+ state.indented = state.lexical.indented;
198
+ state.lexical = state.lexical.prev;
199
+ }
200
+ }
201
+ poplex.lex = true;
202
+
203
+ function expect(wanted) {
204
+ return function expecting(type) {
205
+ if (type == wanted) return cont();
206
+ else if (wanted == ";") return pass();
207
+ else return cont(arguments.callee);
208
+ };
209
+ }
210
+
211
+ function statement(type) {
212
+ if (type == "var") return cont(pushlex("vardef"), vardef1, expect(";"), poplex);
213
+ if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex);
214
+ if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
215
+ if (type == "{") return cont(pushlex("}"), block, poplex);
216
+ if (type == ";") return cont();
217
+ if (type == "function") return cont(functiondef);
218
+ if (type == "for") return cont(pushlex("form"), expect("("), pushlex(")"), forspec1, expect(")"),
219
+ poplex, statement, poplex);
220
+ if (type == "variable") return cont(pushlex("stat"), maybelabel);
221
+ if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"),
222
+ block, poplex, poplex);
223
+ if (type == "case") return cont(expression, expect(":"));
224
+ if (type == "default") return cont(expect(":"));
225
+ if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"),
226
+ statement, poplex, popcontext);
227
+ return pass(pushlex("stat"), expression, expect(";"), poplex);
228
+ }
229
+ function expression(type) {
230
+ if (atomicTypes.hasOwnProperty(type)) return cont(maybeoperator);
231
+ if (type == "function") return cont(functiondef);
232
+ if (type == "keyword c") return cont(maybeexpression);
233
+ if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeoperator);
234
+ if (type == "operator") return cont(expression);
235
+ if (type == "[") return cont(pushlex("]"), commasep(expression, "]"), poplex, maybeoperator);
236
+ if (type == "{") return cont(pushlex("}"), commasep(objprop, "}"), poplex, maybeoperator);
237
+ return cont();
238
+ }
239
+ function maybeexpression(type) {
240
+ if (type.match(/[;\}\)\],]/)) return pass();
241
+ return pass(expression);
242
+ }
243
+
244
+ function maybeoperator(type, value) {
245
+ if (type == "operator" && /\+\+|--/.test(value)) return cont(maybeoperator);
246
+ if (type == "operator") return cont(expression);
247
+ if (type == ";") return;
248
+ if (type == "(") return cont(pushlex(")"), commasep(expression, ")"), poplex, maybeoperator);
249
+ if (type == ".") return cont(property, maybeoperator);
250
+ if (type == "[") return cont(pushlex("]"), expression, expect("]"), poplex, maybeoperator);
251
+ }
252
+ function maybelabel(type) {
253
+ if (type == ":") return cont(poplex, statement);
254
+ return pass(maybeoperator, expect(";"), poplex);
255
+ }
256
+ function property(type) {
257
+ if (type == "variable") {cx.marked = "property"; return cont();}
258
+ }
259
+ function objprop(type) {
260
+ if (type == "variable") cx.marked = "property";
261
+ if (atomicTypes.hasOwnProperty(type)) return cont(expect(":"), expression);
262
+ }
263
+ function commasep(what, end) {
264
+ function proceed(type) {
265
+ if (type == ",") return cont(what, proceed);
266
+ if (type == end) return cont();
267
+ return cont(expect(end));
268
+ }
269
+ return function commaSeparated(type) {
270
+ if (type == end) return cont();
271
+ else return pass(what, proceed);
272
+ };
273
+ }
274
+ function block(type) {
275
+ if (type == "}") return cont();
276
+ return pass(statement, block);
277
+ }
278
+ function vardef1(type, value) {
279
+ if (type == "variable"){register(value); return cont(vardef2);}
280
+ return cont();
281
+ }
282
+ function vardef2(type, value) {
283
+ if (value == "=") return cont(expression, vardef2);
284
+ if (type == ",") return cont(vardef1);
285
+ }
286
+ function forspec1(type) {
287
+ if (type == "var") return cont(vardef1, forspec2);
288
+ if (type == ";") return pass(forspec2);
289
+ if (type == "variable") return cont(formaybein);
290
+ return pass(forspec2);
291
+ }
292
+ function formaybein(type, value) {
293
+ if (value == "in") return cont(expression);
294
+ return cont(maybeoperator, forspec2);
295
+ }
296
+ function forspec2(type, value) {
297
+ if (type == ";") return cont(forspec3);
298
+ if (value == "in") return cont(expression);
299
+ return cont(expression, expect(";"), forspec3);
300
+ }
301
+ function forspec3(type) {
302
+ if (type != ")") cont(expression);
303
+ }
304
+ function functiondef(type, value) {
305
+ if (type == "variable") {register(value); return cont(functiondef);}
306
+ if (type == "(") return cont(pushlex(")"), pushcontext, commasep(funarg, ")"), poplex, statement, popcontext);
307
+ }
308
+ function funarg(type, value) {
309
+ if (type == "variable") {register(value); return cont();}
310
+ }
311
+
312
+ // Interface
313
+
314
+ return {
315
+ startState: function(basecolumn) {
316
+ return {
317
+ tokenize: jsTokenBase,
318
+ reAllowed: true,
319
+ kwAllowed: true,
320
+ cc: [],
321
+ lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
322
+ localVars: null,
323
+ context: null,
324
+ indented: 0
325
+ };
326
+ },
327
+
328
+ token: function(stream, state) {
329
+ if (stream.sol()) {
330
+ if (!state.lexical.hasOwnProperty("align"))
331
+ state.lexical.align = false;
332
+ state.indented = stream.indentation();
333
+ }
334
+ if (stream.eatSpace()) return null;
335
+ var style = state.tokenize(stream, state);
336
+ if (type == "comment") return style;
337
+ state.reAllowed = type == "operator" || type == "keyword c" || type.match(/^[\[{}\(,;:]$/);
338
+ state.kwAllowed = type != '.';
339
+ return parseJS(state, style, type, content, stream);
340
+ },
341
+
342
+ indent: function(state, textAfter) {
343
+ if (state.tokenize != jsTokenBase) return 0;
344
+ var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical,
345
+ type = lexical.type, closing = firstChar == type;
346
+ if (type == "vardef") return lexical.indented + 4;
347
+ else if (type == "form" && firstChar == "{") return lexical.indented;
348
+ else if (type == "stat" || type == "form") return lexical.indented + indentUnit;
349
+ else if (lexical.info == "switch" && !closing)
350
+ return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
351
+ else if (lexical.align) return lexical.column + (closing ? 0 : 1);
352
+ else return lexical.indented + (closing ? 0 : indentUnit);
353
+ },
354
+
355
+ electricChars: ":{}"
356
+ };
357
+ });
358
+
359
+ CodeMirror.defineMIME("text/javascript", "javascript");
360
+ CodeMirror.defineMIME("application/json", {name: "javascript", json: true});
functions/admin-page-class/js/codemirror/php.js ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function() {
2
+ function keywords(str) {
3
+ var obj = {}, words = str.split(" ");
4
+ for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
5
+ return obj;
6
+ }
7
+ function heredoc(delim) {
8
+ return function(stream, state) {
9
+ if (stream.match(delim)) state.tokenize = null;
10
+ else stream.skipToEnd();
11
+ return "string";
12
+ }
13
+ }
14
+ var phpConfig = {
15
+ name: "clike",
16
+ keywords: keywords("abstract and array as break case catch cfunction class clone const continue declare " +
17
+ "default do else elseif enddeclare endfor endforeach endif endswitch endwhile extends " +
18
+ "final for foreach function global goto if implements interface instanceof namespace " +
19
+ "new or private protected public static switch throw try use var while xor return" +
20
+ "die echo empty exit eval include include_once isset list require require_once print unset"),
21
+ blockKeywords: keywords("catch do else elseif for foreach if switch try while"),
22
+ atoms: keywords("true false null TRUE FALSE NULL"),
23
+ multiLineStrings: true,
24
+ hooks: {
25
+ "$": function(stream, state) {
26
+ stream.eatWhile(/[\w\$_]/);
27
+ return "variable-2";
28
+ },
29
+ "<": function(stream, state) {
30
+ if (stream.match(/<</)) {
31
+ stream.eatWhile(/[\w\.]/);
32
+ state.tokenize = heredoc(stream.current().slice(3));
33
+ return state.tokenize(stream, state);
34
+ }
35
+ return false;
36
+ },
37
+ "#": function(stream, state) {
38
+ stream.skipToEnd();
39
+ return "comment";
40
+ }
41
+ }
42
+ };
43
+
44
+ CodeMirror.defineMode("php", function(config, parserConfig) {
45
+ var htmlMode = CodeMirror.getMode(config, {name: "xml", htmlMode: true});
46
+ var jsMode = CodeMirror.getMode(config, "javascript");
47
+ var cssMode = CodeMirror.getMode(config, "css");
48
+ var phpMode = CodeMirror.getMode(config, phpConfig);
49
+
50
+ function dispatch(stream, state) { // TODO open PHP inside text/css
51
+ if (state.curMode == htmlMode) {
52
+ var style = htmlMode.token(stream, state.curState);
53
+ if (style == "meta" && /^<\?/.test(stream.current())) {
54
+ state.curMode = phpMode;
55
+ state.curState = state.php;
56
+ state.curClose = /^\?>/;
57
+ state.mode = 'php';
58
+ }
59
+ else if (style == "tag" && stream.current() == ">" && state.curState.context) {
60
+ if (/^script$/i.test(state.curState.context.tagName)) {
61
+ state.curMode = jsMode;
62
+ state.curState = jsMode.startState(htmlMode.indent(state.curState, ""));
63
+ state.curClose = /^<\/\s*script\s*>/i;
64
+ state.mode = 'javascript';
65
+ }
66
+ else if (/^style$/i.test(state.curState.context.tagName)) {
67
+ state.curMode = cssMode;
68
+ state.curState = cssMode.startState(htmlMode.indent(state.curState, ""));
69
+ state.curClose = /^<\/\s*style\s*>/i;
70
+ state.mode = 'css';
71
+ }
72
+ }
73
+ return style;
74
+ }
75
+ else if (stream.match(state.curClose, false)) {
76
+ state.curMode = htmlMode;
77
+ state.curState = state.html;
78
+ state.curClose = null;
79
+ state.mode = 'html';
80
+ return dispatch(stream, state);
81
+ }
82
+ else return state.curMode.token(stream, state.curState);
83
+ }
84
+
85
+ return {
86
+ startState: function() {
87
+ var html = htmlMode.startState();
88
+ return {html: html,
89
+ php: phpMode.startState(),
90
+ curMode: parserConfig.startOpen ? phpMode : htmlMode,
91
+ curState: parserConfig.startOpen ? phpMode.startState() : html,
92
+ curClose: parserConfig.startOpen ? /^\?>/ : null,
93
+ mode: parserConfig.startOpen ? 'php' : 'html'}
94
+ },
95
+
96
+ copyState: function(state) {
97
+ var html = state.html, htmlNew = CodeMirror.copyState(htmlMode, html),
98
+ php = state.php, phpNew = CodeMirror.copyState(phpMode, php), cur;
99
+ if (state.curState == html) cur = htmlNew;
100
+ else if (state.curState == php) cur = phpNew;
101
+ else cur = CodeMirror.copyState(state.curMode, state.curState);
102
+ return {html: htmlNew, php: phpNew, curMode: state.curMode, curState: cur,
103
+ curClose: state.curClose, mode: state.mode};
104
+ },
105
+
106
+ token: dispatch,
107
+
108
+ indent: function(state, textAfter) {
109
+ if ((state.curMode != phpMode && /^\s*<\//.test(textAfter)) ||
110
+ (state.curMode == phpMode && /^\?>/.test(textAfter)))
111
+ return htmlMode.indent(state.html, textAfter);
112
+ return state.curMode.indent(state.curState, textAfter);
113
+ },
114
+
115
+ electricChars: "/{}:"
116
+ }
117
+ });
118
+ CodeMirror.defineMIME("application/x-httpd-php", "php");
119
+ CodeMirror.defineMIME("application/x-httpd-php-open", {name: "php", startOpen: true});
120
+ CodeMirror.defineMIME("text/x-php", phpConfig);
121
+ })();
functions/admin-page-class/js/codemirror/solarizedDark.css ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .cm-s-solarizedDark { font:13px/1.4em Trebuchet, Verdana, sans-serif; background: #002b36; color: #839496; }
2
+ .cm-s-solarizedDark div.CodeMirror-selected { background: #0000FF !important; }
3
+ .cm-s-solarizedDark .CodeMirror-gutter { background: #FDF6E3; border-right: 7px solid #3E7087; min-width:2.5em; }
4
+ .cm-s-solarizedDark .CodeMirror-gutter-text { color: #586e75; }
5
+ .cm-s-solarizedDark .CodeMirror-cursor { border-left: 1px solid white !important; }
6
+
7
+ .cm-s-solarizedDark span.cm-comment { color: #586e75; font-style:italic; }
8
+ .cm-s-solarizedDark span.cm-atom { color: #F4C20B; }
9
+ .cm-s-solarizedDark span.cm-number, .cm-s-solarizedDark span.cm-attribute { color: #B58900; }
10
+ .cm-s-solarizedDark span.cm-keyword { color: #859900; }
11
+ .cm-s-solarizedDark span.cm-string { color: #2aa198; }
12
+ .cm-s-solarizedDark span.cm-meta { color: #859900; }
13
+ .cm-s-solarizedDark span.cm-variable-2, .cm-s-solarizedDark span.cm-tag { color: #268BD2; }
14
+ .cm-s-solarizedDark span.cm-variable-3, .cm-s-solarizedDark span.cm-def { color: #268BD2; }
15
+ .cm-s-solarizedDark span.cm-error { color: #AF2018; }
16
+ .cm-s-solarizedDark span.cm-bracket { color: #F0F; }
17
+ .cm-s-solarizedDark span.cm-link { color: #F4C20B; }
18
+ .cm-s-solarizedDark span.CodeMirror-matchingbracket { color:#F0F !important; }
19
+ .cm-s-solarizedDark span.cm-builtin, .cm-s-solarizedDark span.cm-special { color: #CB4B16; }
functions/admin-page-class/js/codemirror/solarizedLight.css ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .cm-s-solarizedLight { font:13px/1.4em Trebuchet, Verdana, sans-serif; background: #FDF6E3; color: #657B83; }
2
+ .cm-s-solarizedLight div.CodeMirror-selected { background: #0000FF !important; }
3
+ .cm-s-solarizedLight .CodeMirror-gutter { background: #002b36; border-right: 7px solid #3E7087; min-width:2.5em; }
4
+ .cm-s-solarizedLight .CodeMirror-gutter-text { color: #B58900; }
5
+ .cm-s-solarizedLight .CodeMirror-cursor { border-left: 1px solid white !important; }
6
+
7
+ .cm-s-solarizedLight span.cm-comment { color: #93A1A1; font-style:italic; }
8
+ .cm-s-solarizedLight span.cm-atom { color: #F4C20B; }
9
+ .cm-s-solarizedLight span.cm-number, .cm-s-solarizedLight span.cm-attribute { color: #B58900; }
10
+ .cm-s-solarizedLight span.cm-keyword { color: #859900; }
11
+ .cm-s-solarizedLight span.cm-string { color: #2AA198; }
12
+ .cm-s-solarizedLight span.cm-meta { color: #859900; }
13
+ .cm-s-solarizedLight span.cm-variable-2, .cm-s-solarizedLight span.cm-tag { color: #268BD2; }
14
+ .cm-s-solarizedLight span.cm-variable-3, .cm-s-solarizedLight span.cm-def { color: #268BD2; }
15
+ .cm-s-solarizedLight span.cm-error { color: #AF2018; }
16
+ .cm-s-solarizedLight span.cm-bracket { color: #F0F; }
17
+ .cm-s-solarizedLight span.cm-link { color: #F4C20B; }
18
+ .cm-s-solarizedLight span.CodeMirror-matchingbracket { color:#F0F !important; }
19
+ .cm-s-solarizedLight span.cm-builtin, .cm-s-solarizedLight span.cm-special { color: #CB4B16; }
functions/admin-page-class/js/codemirror/xml.js ADDED
@@ -0,0 +1,260 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ CodeMirror.defineMode("xml", function(config, parserConfig) {
2
+ var indentUnit = config.indentUnit;
3
+ var Kludges = parserConfig.htmlMode ? {
4
+ autoSelfClosers: {"br": true, "img": true, "hr": true, "link": true, "input": true,
5
+ "meta": true, "col": true, "frame": true, "base": true, "area": true},
6
+ doNotIndent: {"pre": true},
7
+ allowUnquoted: true
8
+ } : {autoSelfClosers: {}, doNotIndent: {}, allowUnquoted: false};
9
+ var alignCDATA = parserConfig.alignCDATA;
10
+
11
+ // Return variables for tokenizers
12
+ var tagName, type;
13
+
14
+ function inText(stream, state) {
15
+ function chain(parser) {
16
+ state.tokenize = parser;
17
+ return parser(stream, state);
18
+ }
19
+
20
+ var ch = stream.next();
21
+ if (ch == "<") {
22
+ if (stream.eat("!")) {
23
+ if (stream.eat("[")) {
24
+ if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>"));
25
+ else return null;
26
+ }
27
+ else if (stream.match("--")) return chain(inBlock("comment", "-->"));
28
+ else if (stream.match("DOCTYPE", true, true)) {
29
+ stream.eatWhile(/[\w\._\-]/);
30
+ return chain(doctype(1));
31
+ }
32
+ else return null;
33
+ }
34
+ else if (stream.eat("?")) {
35
+ stream.eatWhile(/[\w\._\-]/);
36
+ state.tokenize = inBlock("meta", "?>");
37
+ return "meta";
38
+ }
39
+ else {
40
+ type = stream.eat("/") ? "closeTag" : "openTag";
41
+ stream.eatSpace();
42
+ tagName = "";
43
+ var c;
44
+ while ((c = stream.eat(/[^\s\u00a0=<>\"\'\/?]/))) tagName += c;
45
+ state.tokenize = inTag;
46
+ return "tag";
47
+ }
48
+ }
49
+ else if (ch == "&") {
50
+ var ok;
51
+ if (stream.eat("#")) {
52
+ if (stream.eat("x")) {
53
+ ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";");
54
+ } else {
55
+ ok = stream.eatWhile(/[\d]/) && stream.eat(";");
56
+ }
57
+ } else {
58
+ ok = stream.eatWhile(/[\w]/) && stream.eat(";");
59
+ }
60
+ return ok ? "atom" : "error";
61
+ }
62
+ else {
63
+ stream.eatWhile(/[^&<]/);
64
+ return null;
65
+ }
66
+ }
67
+
68
+ function inTag(stream, state) {
69
+ var ch = stream.next();
70
+ if (ch == ">" || (ch == "/" && stream.eat(">"))) {
71
+ state.tokenize = inText;
72
+ type = ch == ">" ? "endTag" : "selfcloseTag";
73
+ return "tag";
74
+ }
75
+ else if (ch == "=") {
76
+ type = "equals";
77
+ return null;
78
+ }
79
+ else if (/[\'\"]/.test(ch)) {
80
+ state.tokenize = inAttribute(ch);
81
+ return state.tokenize(stream, state);
82
+ }
83
+ else {
84
+ stream.eatWhile(/[^\s\u00a0=<>\"\'\/?]/);
85
+ return "word";
86
+ }
87
+ }
88
+
89
+ function inAttribute(quote) {
90
+ return function(stream, state) {
91
+ while (!stream.eol()) {
92
+ if (stream.next() == quote) {
93
+ state.tokenize = inTag;
94
+ break;
95
+ }
96
+ }
97
+ return "string";
98
+ };
99
+ }
100
+
101
+ function inBlock(style, terminator) {
102
+ return function(stream, state) {
103
+ while (!stream.eol()) {
104
+ if (stream.match(terminator)) {
105
+ state.tokenize = inText;
106
+ break;
107
+ }
108
+ stream.next();
109
+ }
110
+ return style;
111
+ };
112
+ }
113
+ function doctype(depth) {
114
+ return function(stream, state) {
115
+ var ch;
116
+ while ((ch = stream.next()) != null) {
117
+ if (ch == "<") {
118
+ state.tokenize = doctype(depth + 1);
119
+ return state.tokenize(stream, state);
120
+ } else if (ch == ">") {
121
+ if (depth == 1) {
122
+ state.tokenize = inText;
123
+ break;
124
+ } else {
125
+ state.tokenize = doctype(depth - 1);
126
+ return state.tokenize(stream, state);
127
+ }
128
+ }
129
+ }
130
+ return "meta";
131
+ };
132
+ }
133
+
134
+ var curState, setStyle;
135
+ function pass() {
136
+ for (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i]);
137
+ }
138
+ function cont() {
139
+ pass.apply(null, arguments);
140
+ return true;
141
+ }
142
+
143
+ function pushContext(tagName, startOfLine) {
144
+ var noIndent = Kludges.doNotIndent.hasOwnProperty(tagName) || (curState.context && curState.context.noIndent);
145
+ curState.context = {
146
+ prev: curState.context,
147
+ tagName: tagName,
148
+ indent: curState.indented,
149
+ startOfLine: startOfLine,
150
+ noIndent: noIndent
151
+ };
152
+ }
153
+ function popContext() {
154
+ if (curState.context) curState.context = curState.context.prev;
155
+ }
156
+
157
+ function element(type) {
158
+ if (type == "openTag") {
159
+ curState.tagName = tagName;
160
+ return cont(attributes, endtag(curState.startOfLine));
161
+ } else if (type == "closeTag") {
162
+ var err = false;
163
+ if (curState.context) {
164
+ err = curState.context.tagName != tagName;
165
+ } else {
166
+ err = true;
167
+ }
168
+ if (err) setStyle = "error";
169
+ return cont(endclosetag(err));
170
+ }
171
+ return cont();
172
+ }
173
+ function endtag(startOfLine) {
174
+ return function(type) {
175
+ if (type == "selfcloseTag" ||
176
+ (type == "endTag" && Kludges.autoSelfClosers.hasOwnProperty(curState.tagName.toLowerCase())))
177
+ return cont();
178
+ if (type == "endTag") {pushContext(curState.tagName, startOfLine); return cont();}
179
+ return cont();
180
+ };
181
+ }
182
+ function endclosetag(err) {
183
+ return function(type) {
184
+ if (err) setStyle = "error";
185
+ if (type == "endTag") { popContext(); return cont(); }
186
+ setStyle = "error";
187
+ return cont(arguments.callee);
188
+ }
189
+ }
190
+
191
+ function attributes(type) {
192
+ if (type == "word") {setStyle = "attribute"; return cont(attributes);}
193
+ if (type == "equals") return cont(attvalue, attributes);
194
+ if (type == "string") {setStyle = "error"; return cont(attributes);}
195
+ return pass();
196
+ }
197
+ function attvalue(type) {
198
+ if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return cont();}
199
+ if (type == "string") return cont(attvaluemaybe);
200
+ return pass();
201
+ }
202
+ function attvaluemaybe(type) {
203
+ if (type == "string") return cont(attvaluemaybe);
204
+ else return pass();
205
+ }
206
+
207
+ return {
208
+ startState: function() {
209
+ return {tokenize: inText, cc: [], indented: 0, startOfLine: true, tagName: null, context: null};
210
+ },
211
+
212
+ token: function(stream, state) {
213
+ if (stream.sol()) {
214
+ state.startOfLine = true;
215
+ state.indented = stream.indentation();
216
+ }
217
+ if (stream.eatSpace()) return null;
218
+
219
+ setStyle = type = tagName = null;
220
+ var style = state.tokenize(stream, state);
221
+ state.type = type;
222
+ if ((style || type) && style != "comment") {
223
+ curState = state;
224
+ while (true) {
225
+ var comb = state.cc.pop() || element;
226
+ if (comb(type || style)) break;
227
+ }
228
+ }
229
+ state.startOfLine = false;
230
+ return setStyle || style;
231
+ },
232
+
233
+ indent: function(state, textAfter, fullLine) {
234
+ var context = state.context;
235
+ if ((state.tokenize != inTag && state.tokenize != inText) ||
236
+ context && context.noIndent)
237
+ return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0;
238
+ if (alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0;
239
+ if (context && /^<\//.test(textAfter))
240
+ context = context.prev;
241
+ while (context && !context.startOfLine)
242
+ context = context.prev;
243
+ if (context) return context.indent + indentUnit;
244
+ else return 0;
245
+ },
246
+
247
+ compareStates: function(a, b) {
248
+ if (a.indented != b.indented || a.tokenize != b.tokenize) return false;
249
+ for (var ca = a.context, cb = b.context; ; ca = ca.prev, cb = cb.prev) {
250
+ if (!ca || !cb) return ca == cb;
251
+ if (ca.tagName != cb.tagName) return false;
252
+ }
253
+ },
254
+
255
+ electricChars: "/"
256
+ };
257
+ });
258
+
259
+ CodeMirror.defineMIME("application/xml", "xml");
260
+ CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true});
functions/admin-page-class/js/plupload/myplupload.css ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .filelist {
2
+ width: 60%;
3
+ }
4
+ .filelist .file {
5
+ padding: 5px;
6
+ background: #ececec;
7
+ border: solid 1px #ccc;
8
+ margin-bottom: 4px;
9
+ }
10
+ .filelist .fileprogress {
11
+ width: 0%;
12
+ background: #B7C53D;
13
+ height: 5px;
14
+ }
15
+ .plupload-thumbs {
16
+
17
+ }
18
+ .plupload-thumbs .thumb {
19
+ width: 50px;
20
+ padding-right: 5px;
21
+ float: left;
22
+ }
23
+ .plupload-thumbs .thumb img {
24
+ width: 50px;
25
+ height: 50px;
26
+ }
27
+ .ui-sortable .thumb img {
28
+ cursor: pointer;
29
+ }
functions/admin-page-class/js/plupload/myplupload.js ADDED
@@ -0,0 +1,140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery.fn.exists = function () {
2
+ return jQuery(this).length > 0;
3
+ }
4
+ jQuery(document).ready(function($) {
5
+
6
+ if($(".plupload-upload-uic").exists()) {
7
+ var pconfig=false;
8
+ $(".plupload-upload-uic").each(function() {
9
+ var $this=$(this);
10
+ var id1=$this.attr("id");
11
+ var imgId=id1.replace("plupload-upload-ui", "");
12
+
13
+ plu_show_thumbs(imgId);
14
+
15
+ pconfig=JSON.parse(JSON.stringify(base_plupload_config));
16
+
17
+ pconfig["browse_button"] = imgId + pconfig["browse_button"];
18
+ pconfig["container"] = imgId + pconfig["container"];
19
+ pconfig["drop_element"] = imgId + pconfig["drop_element"];
20
+ pconfig["file_data_name"] = imgId + pconfig["file_data_name"];
21
+ pconfig["multipart_params"]["imgid"] = imgId;
22
+ pconfig["multipart_params"]["_ajax_nonce"] = $this.find(".ajaxnonceplu").attr("id").replace("ajaxnonceplu", "");
23
+
24
+ if($this.hasClass("plupload-upload-uic-multiple")) {
25
+ pconfig["multi_selection"]=true;
26
+ }
27
+
28
+ if($this.find(".plupload-resize").exists()) {
29
+ var w=parseInt($this.find(".plupload-width").attr("id").replace("plupload-width", ""));
30
+ var h=parseInt($this.find(".plupload-height").attr("id").replace("plupload-height", ""));
31
+ pconfig["resize"]={
32
+ width : w,
33
+ height : h,
34
+ quality : 90
35
+ };
36
+ }
37
+
38
+ var uploader = new plupload.Uploader(pconfig);
39
+
40
+ uploader.bind('Init', function(up){
41
+
42
+ });
43
+
44
+ uploader.init();
45
+
46
+ // a file was added in the queue
47
+ uploader.bind('FilesAdded', function(up, files){
48
+ $.each(files, function(i, file) {
49
+ $this.find('.filelist').append(
50
+ '<div class="file" id="' + file.id + '"><b>' +
51
+
52
+ file.name + '</b> (<span>' + plupload.formatSize(0) + '</span>/' + plupload.formatSize(file.size) + ') ' +
53
+ '<div class="fileprogress"></div></div>');
54
+ });
55
+
56
+ up.refresh();
57
+ up.start();
58
+ });
59
+
60
+ uploader.bind('UploadProgress', function(up, file) {
61
+
62
+ $('#' + file.id + " .fileprogress").width(file.percent + "%");
63
+ $('#' + file.id + " span").html(plupload.formatSize(parseInt(file.size * file.percent / 100)));
64
+ });
65
+
66
+ // a file was uploaded
67
+ uploader.bind('FileUploaded', function(up, file, response) {
68
+
69
+
70
+ $('#' + file.id).fadeOut();
71
+ response=response["response"]
72
+ // add url to the hidden field
73
+ if($this.hasClass("plupload-upload-uic-multiple")) {
74
+ // multiple
75
+ var v1=$.trim($("#" + imgId).val());
76
+ if(v1) {
77
+ v1 = v1 + "," + response;
78
+ }
79
+ else {
80
+ v1 = response;
81
+ }
82
+ $("#" + imgId).val(v1);
83
+ }
84
+ else {
85
+ // single
86
+ $("#" + imgId).val(response + "");
87
+ }
88
+
89
+ // show thumbs
90
+ plu_show_thumbs(imgId);
91
+ });
92
+
93
+
94
+
95
+ });
96
+ }
97
+ });
98
+
99
+ function plu_show_thumbs(imgId) {
100
+ var $=jQuery;
101
+ var thumbsC=$("#" + imgId + "plupload-thumbs");
102
+ thumbsC.html("");
103
+ // get urls
104
+ var imagesS=$("#"+imgId).val();
105
+ var images=imagesS.split(",");
106
+ for(var i=0; i<images.length; i++) {
107
+ if(images[i]) {
108
+ var thumb=$('<div class="thumb" id="thumb' + imgId + i + '"><img src="' + images[i] + '" alt="" /><div class="thumbi"><a id="thumbremovelink' + imgId + i + '" href="#">Remove</a></div> <div class="clear"></div></div>');
109
+ thumbsC.append(thumb);
110
+ thumb.find("a").click(function() {
111
+ var ki=$(this).attr("id").replace("thumbremovelink" + imgId , "");
112
+ ki=parseInt(ki);
113
+ var kimages=[];
114
+ imagesS=$("#"+imgId).val();
115
+ images=imagesS.split(",");
116
+ for(var j=0; j<images.length; j++) {
117
+ if(j != ki) {
118
+ kimages[kimages.length] = images[j];
119
+ }
120
+ }
121
+ $("#"+imgId).val(kimages.join());
122
+ plu_show_thumbs(imgId);
123
+ return false;
124
+ });
125
+ }
126
+ }
127
+ if(images.length > 1) {
128
+ thumbsC.sortable({
129
+ update: function(event, ui) {
130
+ var kimages=[];
131
+ thumbsC.find("img").each(function() {
132
+ kimages[kimages.length]=$(this).attr("src");
133
+ $("#"+imgId).val(kimages.join());
134
+ plu_show_thumbs(imgId);
135
+ });
136
+ }
137
+ });
138
+ thumbsC.disableSelection();
139
+ }
140
+ }
functions/admin-page-class/js/select2/LICENSE ADDED
@@ -0,0 +1,485 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright 2012 Igor Vaynberg
2
+
3
+ Version: @@ver@@ Timestamp: @@timestamp@@
4
+
5
+ This software is licensed under the Apache License, Version 2.0 (the "Apache License") or the GNU
6
+ General Public License version 2 (the "GPL License"). You may choose either license to govern your
7
+ use of this software only upon the condition that you accept all of the terms of either the Apache
8
+ License or the GPL License.
9
+
10
+ You may obtain a copy of the Apache License and the GPL License at:
11
+
12
+ http://www.apache.org/licenses/LICENSE-2.0
13
+ http://www.gnu.org/licenses/gpl-2.0.html
14
+
15
+ Unless required by applicable law or agreed to in writing, software distributed under the Apache License
16
+ or the GPL Licesnse is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
17
+ either express or implied. See the Apache License and the GPL License for the specific language governing
18
+ permissions and limitations under the Apache License and the GPL License.
19
+
20
+ LICENSE #1: Apache License, Version 2.0
21
+
22
+ LICENSE #2: GPL v2
23
+
24
+ ************************************************************
25
+
26
+ LICENSE #1:
27
+
28
+ Apache License
29
+ Version 2.0, January 2004
30
+ http://www.apache.org/licenses/
31
+
32
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
33
+
34
+ 1. Definitions.
35
+
36
+ "License" shall mean the terms and conditions for use, reproduction,
37
+ and distribution as defined by Sections 1 through 9 of this document.
38
+
39
+ "Licensor" shall mean the copyright owner or entity authorized by
40
+ the copyright owner that is granting the License.
41
+
42
+ "Legal Entity" shall mean the union of the acting entity and all
43
+ other entities that control, are controlled by, or are under common
44
+ control with that entity. For the purposes of this definition,
45
+ "control" means (i) the power, direct or indirect, to cause the
46
+ direction or management of such entity, whether by contract or
47
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
48
+ outstanding shares, or (iii) beneficial ownership of such entity.
49
+
50
+ "You" (or "Your") shall mean an individual or Legal Entity
51
+ exercising permissions granted by this License.
52
+
53
+ "Source" form shall mean the preferred form for making modifications,
54
+ including but not limited to software source code, documentation
55
+ source, and configuration files.
56
+
57
+ "Object" form shall mean any form resulting from mechanical
58
+ transformation or translation of a Source form, including but
59
+ not limited to compiled object code, generated documentation,
60
+ and conversions to other media types.
61
+
62
+ "Work" shall mean the work of authorship, whether in Source or
63
+ Object form, made available under the License, as indicated by a
64
+ copyright notice that is included in or attached to the work
65
+ (an example is provided in the Appendix below).
66
+
67
+ "Derivative Works" shall mean any work, whether in Source or Object
68
+ form, that is based on (or derived from) the Work and for which the
69
+ editorial revisions, annotations, elaborations, or other modifications
70
+ represent, as a whole, an original work of authorship. For the purposes
71
+ of this License, Derivative Works shall not include works that remain
72
+ separable from, or merely link (or bind by name) to the interfaces of,
73
+ the Work and Derivative Works thereof.
74
+
75
+ "Contribution" shall mean any work of authorship, including
76
+ the original version of the Work and any modifications or additions
77
+ to that Work or Derivative Works thereof, that is intentionally
78
+ submitted to Licensor for inclusion in the Work by the copyright owner
79
+ or by an individual or Legal Entity authorized to submit on behalf of
80
+ the copyright owner. For the purposes of this definition, "submitted"
81
+ means any form of electronic, verbal, or written communication sent
82
+ to the Licensor or its representatives, including but not limited to
83
+ communication on electronic mailing lists, source code control systems,
84
+ and issue tracking systems that are managed by, or on behalf of, the
85
+ Licensor for the purpose of discussing and improving the Work, but
86
+ excluding communication that is conspicuously marked or otherwise
87
+ designated in writing by the copyright owner as "Not a Contribution."
88
+
89
+ "Contributor" shall mean Licensor and any individual or Legal Entity
90
+ on behalf of whom a Contribution has been received by Licensor and
91
+ subsequently incorporated within the Work.
92
+
93
+ 2. Grant of Copyright License. Subject to the terms and conditions of
94
+ this License, each Contributor hereby grants to You a perpetual,
95
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
96
+ copyright license to reproduce, prepare Derivative Works of,
97
+ publicly display, publicly perform, sublicense, and distribute the
98
+ Work and such Derivative Works in Source or Object form.
99
+
100
+ 3. Grant of Patent License. Subject to the terms and conditions of
101
+ this License, each Contributor hereby grants to You a perpetual,
102
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
103
+ (except as stated in this section) patent license to make, have made,
104
+ use, offer to sell, sell, import, and otherwise transfer the Work,
105
+ where such license applies only to those patent claims licensable
106
+ by such Contributor that are necessarily infringed by their
107
+ Contribution(s) alone or by combination of their Contribution(s)
108
+ with the Work to which such Contribution(s) was submitted. If You
109
+ institute patent litigation against any entity (including a
110
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
111
+ or a Contribution incorporated within the Work constitutes direct
112
+ or contributory patent infringement, then any patent licenses
113
+ granted to You under this License for that Work shall terminate
114
+ as of the date such litigation is filed.
115
+
116
+ 4. Redistribution. You may reproduce and distribute copies of the
117
+ Work or Derivative Works thereof in any medium, with or without
118
+ modifications, and in Source or Object form, provided that You
119
+ meet the following conditions:
120
+
121
+ (a) You must give any other recipients of the Work or
122
+ Derivative Works a copy of this License; and
123
+
124
+ (b) You must cause any modified files to carry prominent notices
125
+ stating that You changed the files; and
126
+
127
+ (c) You must retain, in the Source form of any Derivative Works
128
+ that You distribute, all copyright, patent, trademark, and
129
+ attribution notices from the Source form of the Work,
130
+ excluding those notices that do not pertain to any part of
131
+ the Derivative Works; and
132
+
133
+ (d) If the Work includes a "NOTICE" text file as part of its
134
+ distribution, then any Derivative Works that You distribute must
135
+ include a readable copy of the attribution notices contained
136
+ within such NOTICE file, excluding those notices that do not
137
+ pertain to any part of the Derivative Works, in at least one
138
+ of the following places: within a NOTICE text file distributed
139
+ as part of the Derivative Works; within the Source form or
140
+ documentation, if provided along with the Derivative Works; or,
141
+ within a display generated by the Derivative Works, if and
142
+ wherever such third-party notices normally appear. The contents
143
+ of the NOTICE file are for informational purposes only and
144
+ do not modify the License. You may add Your own attribution
145
+ notices within Derivative Works that You distribute, alongside
146
+ or as an addendum to the NOTICE text from the Work, provided
147
+ that such additional attribution notices cannot be construed
148
+ as modifying the License.
149
+
150
+ You may add Your own copyright statement to Your modifications and
151
+ may provide additional or different license terms and conditions
152
+ for use, reproduction, or distribution of Your modifications, or
153
+ for any such Derivative Works as a whole, provided Your use,
154
+ reproduction, and distribution of the Work otherwise complies with
155
+ the conditions stated in this License.
156
+
157
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
158
+ any Contribution intentionally submitted for inclusion in the Work
159
+ by You to the Licensor shall be under the terms and conditions of
160
+ this License, without any additional terms or conditions.
161
+ Notwithstanding the above, nothing herein shall supersede or modify
162
+ the terms of any separate license agreement you may have executed
163
+ with Licensor regarding such Contributions.
164
+
165
+ 6. Trademarks. This License does not grant permission to use the trade
166
+ names, trademarks, service marks, or product names of the Licensor,
167
+ except as required for reasonable and customary use in describing the
168
+ origin of the Work and reproducing the content of the NOTICE file.
169
+
170
+ 7. Disclaimer of Warranty. Unless required by applicable law or
171
+ agreed to in writing, Licensor provides the Work (and each
172
+ Contributor provides its Contributions) on an "AS IS" BASIS,
173
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
174
+ implied, including, without limitation, any warranties or conditions
175
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
176
+ PARTICULAR PURPOSE. You are solely responsible for determining the
177
+ appropriateness of using or redistributing the Work and assume any
178
+ risks associated with Your exercise of permissions under this License.
179
+
180
+ 8. Limitation of Liability. In no event and under no legal theory,
181
+ whether in tort (including negligence), contract, or otherwise,
182
+ unless required by applicable law (such as deliberate and grossly
183
+ negligent acts) or agreed to in writing, shall any Contributor be
184
+ liable to You for damages, including any direct, indirect, special,
185
+ incidental, or consequential damages of any character arising as a
186
+ result of this License or out of the use or inability to use the
187
+ Work (including but not limited to damages for loss of goodwill,
188
+ work stoppage, computer failure or malfunction, or any and all
189
+ other commercial damages or losses), even if such Contributor
190
+ has been advised of the possibility of such damages.
191
+
192
+ 9. Accepting Warranty or Additional Liability. While redistributing
193
+ the Work or Derivative Works thereof, You may choose to offer,
194
+ and charge a fee for, acceptance of support, warranty, indemnity,
195
+ or other liability obligations and/or rights consistent with this
196
+ License. However, in accepting such obligations, You may act only
197
+ on Your own behalf and on Your sole responsibility, not on behalf
198
+ of any other Contributor, and only if You agree to indemnify,
199
+ defend, and hold each Contributor harmless for any liability
200
+ incurred by, or claims asserted against, such Contributor by reason
201
+ of your accepting any such warranty or additional liability.
202
+
203
+ ************************************************************
204
+
205
+ LICENSE #2:
206
+
207
+ GNU GENERAL PUBLIC LICENSE
208
+ Version 2, June 1991
209
+
210
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
211
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
212
+ Everyone is permitted to copy and distribute verbatim copies
213
+ of this license document, but changing it is not allowed.
214
+
215
+ Preamble
216
+
217
+ The licenses for most software are designed to take away your
218
+ freedom to share and change it. By contrast, the GNU General Public
219
+ License is intended to guarantee your freedom to share and change free
220
+ software--to make sure the software is free for all its users. This
221
+ General Public License applies to most of the Free Software
222
+ Foundation's software and to any other program whose authors commit to
223
+ using it. (Some other Free Software Foundation software is covered by
224
+ the GNU Lesser General Public License instead.) You can apply it to
225
+ your programs, too.
226
+
227
+ When we speak of free software, we are referring to freedom, not
228
+ price. Our General Public Licenses are designed to make sure that you
229
+ have the freedom to distribute copies of free software (and charge for
230
+ this service if you wish), that you receive source code or can get it
231
+ if you want it, that you can change the software or use pieces of it
232
+ in new free programs; and that you know you can do these things.
233
+
234
+ To protect your rights, we need to make restrictions that forbid
235
+ anyone to deny you these rights or to ask you to surrender the rights.
236
+ These restrictions translate to certain responsibilities for you if you
237
+ distribute copies of the software, or if you modify it.
238
+
239
+ For example, if you distribute copies of such a program, whether
240
+ gratis or for a fee, you must give the recipients all the rights that
241
+ you have. You must make sure that they, too, receive or can get the
242
+ source code. And you must show them these terms so they know their
243
+ rights.
244
+
245
+ We protect your rights with two steps: (1) copyright the software, and
246
+ (2) offer you this license which gives you legal permission to copy,
247
+ distribute and/or modify the software.
248
+
249
+ Also, for each author's protection and ours, we want to make certain
250
+ that everyone understands that there is no warranty for this free
251
+ software. If the software is modified by someone else and passed on, we
252
+ want its recipients to know that what they have is not the original, so
253
+ that any problems introduced by others will not reflect on the original
254
+ authors' reputations.
255
+
256
+ Finally, any free program is threatened constantly by software
257
+ patents. We wish to avoid the danger that redistributors of a free
258
+ program will individually obtain patent licenses, in effect making the
259
+ program proprietary. To prevent this, we have made it clear that any
260
+ patent must be licensed for everyone's free use or not licensed at all.
261
+
262
+ The precise terms and conditions for copying, distribution and
263
+ modification follow.
264
+
265
+ GNU GENERAL PUBLIC LICENSE
266
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
267
+
268
+ 0. This License applies to any program or other work which contains
269
+ a notice placed by the copyright holder saying it may be distributed
270
+ under the terms of this General Public License. The "Program", below,
271
+ refers to any such program or work, and a "work based on the Program"
272
+ means either the Program or any derivative work under copyright law:
273
+ that is to say, a work containing the Program or a portion of it,
274
+ either verbatim or with modifications and/or translated into another
275
+ language. (Hereinafter, translation is included without limitation in
276
+ the term "modification".) Each licensee is addressed as "you".
277
+
278
+ Activities other than copying, distribution and modification are not
279
+ covered by this License; they are outside its scope. The act of
280
+ running the Program is not restricted, and the output from the Program
281
+ is covered only if its contents constitute a work based on the
282
+ Program (independent of having been made by running the Program).
283
+ Whether that is true depends on what the Program does.
284
+
285
+ 1. You may copy and distribute verbatim copies of the Program's
286
+ source code as you receive it, in any medium, provided that you
287
+ conspicuously and appropriately publish on each copy an appropriate
288
+ copyright notice and disclaimer of warranty; keep intact all the
289
+ notices that refer to this License and to the absence of any warranty;
290
+ and give any other recipients of the Program a copy of this License
291
+ along with the Program.
292
+
293
+ You may charge a fee for the physical act of transferring a copy, and
294
+ you may at your option offer warranty protection in exchange for a fee.
295
+
296
+ 2. You may modify your copy or copies of the Program or any portion
297
+ of it, thus forming a work based on the Program, and copy and
298
+ distribute such modifications or work under the terms of Section 1
299
+ above, provided that you also meet all of these conditions:
300
+
301
+ a) You must cause the modified files to carry prominent notices
302
+ stating that you changed the files and the date of any change.
303
+
304
+ b) You must cause any work that you distribute or publish, that in
305
+ whole or in part contains or is derived from the Program or any
306
+ part thereof, to be licensed as a whole at no charge to all third
307
+ parties under the terms of this License.
308
+
309
+ c) If the modified program normally reads commands interactively
310
+ when run, you must cause it, when started running for such
311
+ interactive use in the most ordinary way, to print or display an
312
+ announcement including an appropriate copyright notice and a
313
+ notice that there is no warranty (or else, saying that you provide
314
+ a warranty) and that users may redistribute the program under
315
+ these conditions, and telling the user how to view a copy of this
316
+ License. (Exception: if the Program itself is interactive but
317
+ does not normally print such an announcement, your work based on
318
+ the Program is not required to print an announcement.)
319
+
320
+ These requirements apply to the modified work as a whole. If
321
+ identifiable sections of that work are not derived from the Program,
322
+ and can be reasonably considered independent and separate works in
323
+ themselves, then this License, and its terms, do not apply to those
324
+ sections when you distribute them as separate works. But when you
325
+ distribute the same sections as part of a whole which is a work based
326
+ on the Program, the distribution of the whole must be on the terms of
327
+ this License, whose permissions for other licensees extend to the
328
+ entire whole, and thus to each and every part regardless of who wrote it.
329
+
330
+ Thus, it is not the intent of this section to claim rights or contest
331
+ your rights to work written entirely by you; rather, the intent is to
332
+ exercise the right to control the distribution of derivative or
333
+ collective works based on the Program.
334
+
335
+ In addition, mere aggregation of another work not based on the Program
336
+ with the Program (or with a work based on the Program) on a volume of
337
+ a storage or distribution medium does not bring the other work under
338
+ the scope of this License.
339
+
340
+ 3. You may copy and distribute the Program (or a work based on it,
341
+ under Section 2) in object code or executable form under the terms of
342
+ Sections 1 and 2 above provided that you also do one of the following:
343
+
344
+ a) Accompany it with the complete corresponding machine-readable
345
+ source code, which must be distributed under the terms of Sections
346
+ 1 and 2 above on a medium customarily used for software interchange; or,
347
+
348
+ b) Accompany it with a written offer, valid for at least three
349
+ years, to give any third party, for a charge no more than your
350
+ cost of physically performing source distribution, a complete
351
+ machine-readable copy of the corresponding source code, to be
352
+ distributed under the terms of Sections 1 and 2 above on a medium
353
+ customarily used for software interchange; or,
354
+
355
+ c) Accompany it with the information you received as to the offer
356
+ to distribute corresponding source code. (This alternative is
357
+ allowed only for noncommercial distribution and only if you
358
+ received the program in object code or executable form with such
359
+ an offer, in accord with Subsection b above.)
360
+
361
+ The source code for a work means the preferred form of the work for
362
+ making modifications to it. For an executable work, complete source
363
+ code means all the source code for all modules it contains, plus any
364
+ associated interface definition files, plus the scripts used to
365
+ control compilation and installation of the executable. However, as a
366
+ special exception, the source code distributed need not include
367
+ anything that is normally distributed (in either source or binary
368
+ form) with the major components (compiler, kernel, and so on) of the
369
+ operating system on which the executable runs, unless that component
370
+ itself accompanies the executable.
371
+
372
+ If distribution of executable or object code is made by offering
373
+ access to copy from a designated place, then offering equivalent
374
+ access to copy the source code from the same place counts as
375
+ distribution of the source code, even though third parties are not
376
+ compelled to copy the source along with the object code.
377
+
378
+ 4. You may not copy, modify, sublicense, or distribute the Program
379
+ except as expressly provided under this License. Any attempt
380
+ otherwise to copy, modify, sublicense or distribute the Program is
381
+ void, and will automatically terminate your rights under this License.
382
+ However, parties who have received copies, or rights, from you under
383
+ this License will not have their licenses terminated so long as such
384
+ parties remain in full compliance.
385
+
386
+ 5. You are not required to accept this License, since you have not
387
+ signed it. However, nothing else grants you permission to modify or
388
+ distribute the Program or its derivative works. These actions are
389
+ prohibited by law if you do not accept this License. Therefore, by
390
+ modifying or distributing the Program (or any work based on the
391
+ Program), you indicate your acceptance of this License to do so, and
392
+ all its terms and conditions for copying, distributing or modifying
393
+ the Program or works based on it.
394
+
395
+ 6. Each time you redistribute the Program (or any work based on the
396
+ Program), the recipient automatically receives a license from the
397
+ original licensor to copy, distribute or modify the Program subject to
398
+ these terms and conditions. You may not impose any further
399
+ restrictions on the recipients' exercise of the rights granted herein.
400
+ You are not responsible for enforcing compliance by third parties to
401
+ this License.
402
+
403
+ 7. If, as a consequence of a court judgment or allegation of patent
404
+ infringement or for any other reason (not limited to patent issues),
405
+ conditions are imposed on you (whether by court order, agreement or
406
+ otherwise) that contradict the conditions of this License, they do not
407
+ excuse you from the conditions of this License. If you cannot
408
+ distribute so as to satisfy simultaneously your obligations under this
409
+ License and any other pertinent obligations, then as a consequence you
410
+ may not distribute the Program at all. For example, if a patent
411
+ license would not permit royalty-free redistribution of the Program by
412
+ all those who receive copies directly or indirectly through you, then
413
+ the only way you could satisfy both it and this License would be to
414
+ refrain entirely from distribution of the Program.
415
+
416
+ If any portion of this section is held invalid or unenforceable under
417
+ any particular circumstance, the balance of the section is intended to
418
+ apply and the section as a whole is intended to apply in other
419
+ circumstances.
420
+
421
+ It is not the purpose of this section to induce you to infringe any
422
+ patents or other property right claims or to contest validity of any
423
+ such claims; this section has the sole purpose of protecting the
424
+ integrity of the free software distribution system, which is
425
+ implemented by public license practices. Many people have made
426
+ generous contributions to the wide range of software distributed
427
+ through that system in reliance on consistent application of that
428
+ system; it is up to the author/donor to decide if he or she is willing
429
+ to distribute software through any other system and a licensee cannot
430
+ impose that choice.
431
+
432
+ This section is intended to make thoroughly clear what is believed to
433
+ be a consequence of the rest of this License.
434
+
435
+ 8. If the distribution and/or use of the Program is restricted in
436
+ certain countries either by patents or by copyrighted interfaces, the
437
+ original copyright holder who places the Program under this License
438
+ may add an explicit geographical distribution limitation excluding
439
+ those countries, so that distribution is permitted only in or among
440
+ countries not thus excluded. In such case, this License incorporates
441
+ the limitation as if written in the body of this License.
442
+
443
+ 9. The Free Software Foundation may publish revised and/or new versions
444
+ of the General Public License from time to time. Such new versions will
445
+ be similar in spirit to the present version, but may differ in detail to
446
+ address new problems or concerns.
447
+
448
+ Each version is given a distinguishing version number. If the Program
449
+ specifies a version number of this License which applies to it and "any
450
+ later version", you have the option of following the terms and conditions
451
+ either of that version or of any later version published by the Free
452
+ Software Foundation. If the Program does not specify a version number of
453
+ this License, you may choose any version ever published by the Free Software
454
+ Foundation.
455
+
456
+ 10. If you wish to incorporate parts of the Program into other free
457
+ programs whose distribution conditions are different, write to the author
458
+ to ask for permission. For software which is copyrighted by the Free
459
+ Software Foundation, write to the Free Software Foundation; we sometimes
460
+ make exceptions for this. Our decision will be guided by the two goals
461
+ of preserving the free status of all derivatives of our free software and
462
+ of promoting the sharing and reuse of software generally.
463
+
464
+ NO WARRANTY
465
+
466
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
467
+ FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
468
+ OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
469
+ PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
470
+ OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
471
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
472
+ TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
473
+ PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
474
+ REPAIR OR CORRECTION.
475
+
476
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
477
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
478
+ REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
479
+ INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
480
+ OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
481
+ TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
482
+ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
483
+ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
484
+ POSSIBILITY OF SUCH DAMAGES.
485
+
functions/admin-page-class/js/select2/select2-spinner.gif ADDED
Binary file
functions/admin-page-class/js/select2/select2.css ADDED
@@ -0,0 +1,533 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ Version: @@ver@@ Timestamp: @@timestamp@@
3
+ */
4
+ .select2-container {
5
+ position: relative;
6
+ display: inline-block;
7
+ /* inline-block for ie7 */
8
+ zoom: 1;
9
+ *display: inline;
10
+ vertical-align: top;
11
+ }
12
+
13
+ .select2-container,
14
+ .select2-drop,
15
+ .select2-search,
16
+ .select2-search input{
17
+ /*
18
+ Force border-box so that % widths fit the parent
19
+ container without overlap because of margin/padding.
20
+
21
+ More Info : http://www.quirksmode.org/css/box.html
22
+ */
23
+ -webkit-box-sizing: border-box; /* webkit */
24
+ -khtml-box-sizing: border-box; /* konqueror */
25
+ -moz-box-sizing: border-box; /* firefox */
26
+ -ms-box-sizing: border-box; /* ie */
27
+ box-sizing: border-box; /* css3 */
28
+ width:65%;
29
+ }
30
+
31
+ .select2-container .select2-choice {
32
+ display: block;
33
+ height: 26px;
34
+ padding: 0 0 0 8px;
35
+ overflow: hidden;
36
+ position: relative;
37
+
38
+ border: 1px solid #aaa;
39
+ white-space: nowrap;
40
+ line-height: 26px;
41
+ color: #444;
42
+ text-decoration: none;
43
+ border-radius:0;
44
+ background:#fff;
45
+ }
46
+
47
+ .select2-container.select2-drop-above .select2-choice {
48
+ border-bottom-color: #aaa;
49
+ }
50
+
51
+ .select2-container .select2-choice span {
52
+ margin-right: 26px;
53
+ display: block;
54
+ overflow: hidden;
55
+
56
+ white-space: nowrap;
57
+
58
+ -ms-text-overflow: ellipsis;
59
+ -o-text-overflow: ellipsis;
60
+ text-overflow: ellipsis;
61
+ }
62
+
63
+ .select2-container .select2-choice abbr {
64
+ display: block;
65
+ width: 12px;
66
+ height: 12px;
67
+ position: absolute;
68
+ right: 26px;
69
+ top: 8px;
70
+
71
+ font-size: 1px;
72
+ text-decoration: none;
73
+
74
+ border: 0;
75
+ background: url('select2.png') right top no-repeat;
76
+ cursor: pointer;
77
+ outline: 0;
78
+ }
79
+ .select2-container .select2-choice abbr:hover {
80
+ background-position: right -11px;
81
+ cursor: pointer;
82
+ }
83
+
84
+ .select2-drop {
85
+ width: 100%;
86
+ margin-top:-1px;
87
+ position: absolute;
88
+ z-index: 9999;
89
+ top: 100%;
90
+
91
+ background: #fff;
92
+ color: #000;
93
+ border: 1px solid #aaa;
94
+ border-top: 0;
95
+
96
+ box-shadow:none;
97
+ border-radius:0;
98
+ }
99
+
100
+ .select2-drop.select2-drop-above {
101
+ margin-top: 1px;
102
+ border-top: 1px solid #aaa;
103
+ border-bottom: 0;
104
+
105
+ -webkit-border-radius: 4px 4px 0 0;
106
+ -moz-border-radius: 4px 4px 0 0;
107
+ border-radius: 4px 4px 0 0;
108
+
109
+ -webkit-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
110
+ -moz-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
111
+ -o-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
112
+ box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
113
+ }
114
+
115
+ .select2-container .select2-choice div {
116
+ display: block;
117
+ width: 18px;
118
+ height: 100%;
119
+ position: absolute;
120
+ right: 0;
121
+ top: 0;
122
+
123
+ border-left: 1px solid #aaa;
124
+ -webkit-border-radius: 0 4px 4px 0;
125
+ -moz-border-radius: 0 4px 4px 0;
126
+ border-radius: 0 4px 4px 0;
127
+
128
+ -webkit-background-clip: padding-box;
129
+ -moz-background-clip: padding;
130
+ background-clip: padding-box;
131
+
132
+ background: #ccc;
133
+ background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #ccc), color-stop(0.6, #eee));
134
+ background-image: -webkit-linear-gradient(center bottom, #ccc 0%, #eee 60%);
135
+ background-image: -moz-linear-gradient(center bottom, #ccc 0%, #eee 60%);
136
+ background-image: -o-linear-gradient(bottom, #ccc 0%, #eee 60%);
137
+ background-image: -ms-linear-gradient(top, #cccccc 0%, #eeeeee 60%);
138
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#eeeeee', endColorstr = '#cccccc', GradientType = 0);
139
+ background-image: linear-gradient(top, #cccccc 0%, #eeeeee 60%);
140
+ }
141
+
142
+ .select2-container .select2-choice div b {
143
+ display: block;
144
+ width: 100%;
145
+ height: 100%;
146
+ background: url('select2.png') no-repeat 0 1px;
147
+ }
148
+
149
+ .select2-search {
150
+ display: inline-block;
151
+ width: 100%;
152
+ min-height: 26px;
153
+ margin: 0;
154
+ padding-left: 4px;
155
+ padding-right: 4px;
156
+
157
+ position: relative;
158
+ z-index: 10000;
159
+
160
+ white-space: nowrap;
161
+ }
162
+
163
+ .select2-search-hidden {
164
+ display: block;
165
+ position: absolute;
166
+ left: -10000px;
167
+ }
168
+
169
+ .select2-search input {
170
+ width: 100%;
171
+ height: auto !important;
172
+ min-height: 26px;
173
+ padding: 4px 20px 4px 5px;
174
+ margin: 0;
175
+
176
+ outline: 0;
177
+ font-family: sans-serif;
178
+ font-size: 1em;
179
+
180
+ border: 1px solid #aaa;
181
+ -webkit-border-radius: 0;
182
+ -moz-border-radius: 0;
183
+ border-radius: 0;
184
+
185
+ -webkit-box-shadow: none;
186
+ -moz-box-shadow: none;
187
+ box-shadow: none;
188
+ }
189
+
190
+ .select2-drop.select2-drop-above .select2-search input {
191
+ margin-top: 4px;
192
+ }
193
+
194
+ .select2-search input.select2-active {
195
+ background: #fff url('select2-spinner.gif') no-repeat 100%;
196
+ background: url('select2-spinner.gif') no-repeat 100%, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, white), color-stop(0.99, #eeeeee));
197
+ background: url('select2-spinner.gif') no-repeat 100%, -webkit-linear-gradient(center bottom, white 85%, #eeeeee 99%);
198
+ background: url('select2-spinner.gif') no-repeat 100%, -moz-linear-gradient(center bottom, white 85%, #eeeeee 99%);
199
+ background: url('select2-spinner.gif') no-repeat 100%, -o-linear-gradient(bottom, white 85%, #eeeeee 99%);
200
+ background: url('select2-spinner.gif') no-repeat 100%, -ms-linear-gradient(top, #ffffff 85%, #eeeeee 99%);
201
+ background: url('select2-spinner.gif') no-repeat 100%, linear-gradient(top, #ffffff 85%, #eeeeee 99%);
202
+ }
203
+
204
+ .select2-container-active .select2-choice,
205
+ .select2-container-active .select2-choices {
206
+ border: 1px solid #5897fb;
207
+ outline: none;
208
+
209
+ -webkit-box-shadow: 0 0 5px rgba(0,0,0,.3);
210
+ -moz-box-shadow: 0 0 5px rgba(0,0,0,.3);
211
+ -o-box-shadow: 0 0 5px rgba(0,0,0,.3);
212
+ box-shadow: 0 0 5px rgba(0,0,0,.3);
213
+ }
214
+
215
+ .select2-dropdown-open .select2-choice {
216
+ border: 1px solid #aaa;
217
+ border-bottom-color: transparent;
218
+ -webkit-box-shadow: 0 1px 0 #fff inset;
219
+ -moz-box-shadow: 0 1px 0 #fff inset;
220
+ -o-box-shadow: 0 1px 0 #fff inset;
221
+ box-shadow: 0 1px 0 #fff inset;
222
+
223
+ -webkit-border-bottom-left-radius: 0;
224
+ -moz-border-radius-bottomleft: 0;
225
+ border-bottom-left-radius: 0;
226
+
227
+ -webkit-border-bottom-right-radius: 0;
228
+ -moz-border-radius-bottomright: 0;
229
+ border-bottom-right-radius: 0;
230
+
231
+ background-color: #eee;
232
+ background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, white), color-stop(0.5, #eeeeee));
233
+ background-image: -webkit-linear-gradient(center bottom, white 0%, #eeeeee 50%);
234
+ background-image: -moz-linear-gradient(center bottom, white 0%, #eeeeee 50%);
235
+ background-image: -o-linear-gradient(bottom, white 0%, #eeeeee 50%);
236
+ background-image: -ms-linear-gradient(top, #ffffff 0%,#eeeeee 50%);
237
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#eeeeee', endColorstr='#ffffff',GradientType=0 );
238
+ background-image: linear-gradient(top, #ffffff 0%,#eeeeee 50%);
239
+ }
240
+
241
+ .select2-dropdown-open .select2-choice div {
242
+ background: transparent;
243
+ border-left: none;
244
+ filter: none;
245
+ }
246
+ .select2-dropdown-open .select2-choice div b {
247
+ background-position: -18px 1px;
248
+ }
249
+
250
+ /* results */
251
+ .select2-results {
252
+ max-height: 200px;
253
+ padding: 0 0 0 4px;
254
+ margin: 4px 4px 4px 0;
255
+ position: relative;
256
+ overflow-x: hidden;
257
+ overflow-y: auto;
258
+ }
259
+
260
+ .select2-results ul.select2-result-sub {
261
+ margin: 0;
262
+ }
263
+
264
+ .select2-results ul.select2-result-sub > li .select2-result-label { padding-left: 20px }
265
+ .select2-results ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 40px }
266
+ .select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 60px }
267
+ .select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 80px }
268
+ .select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 100px }
269
+ .select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 110px }
270
+ .select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 120px }
271
+
272
+ .select2-results li {
273
+ list-style: none;
274
+ display: list-item;
275
+ }
276
+
277
+ .select2-results li.select2-result-with-children > .select2-result-label {
278
+ font-weight: bold;
279
+ }
280
+
281
+ .select2-results .select2-result-label {
282
+ padding: 3px 7px 4px;
283
+ margin: 0;
284
+ cursor: pointer;
285
+ }
286
+
287
+ .select2-results .select2-highlighted {
288
+ background: #3875d7;
289
+ color: #fff;
290
+ }
291
+ .select2-results li em {
292
+ background: #feffde;
293
+ font-style: normal;
294
+ }
295
+ .select2-results .select2-highlighted em {
296
+ background: transparent;
297
+ }
298
+ .select2-results .select2-no-results,
299
+ .select2-results .select2-searching,
300
+ .select2-results .select2-selection-limit {
301
+ background: #f4f4f4;
302
+ display: list-item;
303
+ }
304
+
305
+ /*
306
+ disabled look for already selected choices in the results dropdown
307
+ .select2-results .select2-disabled.select2-highlighted {
308
+ color: #666;
309
+ background: #f4f4f4;
310
+ display: list-item;
311
+ cursor: default;
312
+ }
313
+ .select2-results .select2-disabled {
314
+ background: #f4f4f4;
315
+ display: list-item;
316
+ cursor: default;
317
+ }
318
+ */
319
+ .select2-results .select2-disabled {
320
+ display: none;
321
+ }
322
+
323
+ .select2-more-results.select2-active {
324
+ background: #f4f4f4 url('select2-spinner.gif') no-repeat 100%;
325
+ }
326
+
327
+ .select2-more-results {
328
+ background: #f4f4f4;
329
+ display: list-item;
330
+ }
331
+
332
+ /* disabled styles */
333
+
334
+ .select2-container.select2-container-disabled .select2-choice {
335
+ background-color: #f4f4f4;
336
+ background-image: none;
337
+ border: 1px solid #ddd;
338
+ cursor: default;
339
+ }
340
+
341
+ .select2-container.select2-container-disabled .select2-choice div {
342
+ background-color: #f4f4f4;
343
+ background-image: none;
344
+ border-left: 0;
345
+ }
346
+
347
+ .select2-container.select2-container-disabled .select2-choice abbr {
348
+ display: none
349
+ }
350
+
351
+
352
+ /* multiselect */
353
+
354
+ .select2-container-multi .select2-choices {
355
+ height: auto !important;
356
+ height: 1%;
357
+ margin: 0;
358
+ padding: 0;
359
+ position: relative;
360
+
361
+ border: 1px solid #aaa;
362
+ cursor: text;
363
+ overflow: hidden;
364
+
365
+ background-color: #fff;
366
+ background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff));
367
+ background-image: -webkit-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
368
+ background-image: -moz-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
369
+ background-image: -o-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
370
+ background-image: -ms-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
371
+ background-image: linear-gradient(top, #eeeeee 1%, #ffffff 15%);
372
+ }
373
+
374
+ .select2-locked {
375
+ padding: 3px 5px 3px 5px !important;
376
+ }
377
+
378
+ .select2-container-multi .select2-choices {
379
+ min-height: 26px;
380
+ }
381
+
382
+ .select2-container-multi.select2-container-active .select2-choices {
383
+ border: 1px solid #5897fb;
384
+ outline: none;
385
+
386
+ -webkit-box-shadow: 0 0 5px rgba(0,0,0,.3);
387
+ -moz-box-shadow: 0 0 5px rgba(0,0,0,.3);
388
+ -o-box-shadow: 0 0 5px rgba(0,0,0,.3);
389
+ box-shadow: 0 0 5px rgba(0,0,0,.3);
390
+ }
391
+ .select2-container-multi .select2-choices li {
392
+ float: left;
393
+ list-style: none;
394
+ }
395
+ .select2-container-multi .select2-choices .select2-search-field {
396
+ margin: 0;
397
+ padding: 0;
398
+ white-space: nowrap;
399
+ }
400
+
401
+ .select2-container-multi .select2-choices .select2-search-field input {
402
+ height: 15px;
403
+ padding: 5px;
404
+ margin: 1px 0;
405
+
406
+ font-family: sans-serif;
407
+ font-size: 100%;
408
+ color: #666;
409
+ outline: 0;
410
+ border: 0;
411
+ -webkit-box-shadow: none;
412
+ -moz-box-shadow: none;
413
+ -o-box-shadow: none;
414
+ box-shadow: none;
415
+ background: transparent !important;
416
+ }
417
+
418
+ .select2-container-multi .select2-choices .select2-search-field input.select2-active {
419
+ background: #fff url('select2-spinner.gif') no-repeat 100% !important;
420
+ }
421
+
422
+ .select2-default {
423
+ color: #999 !important;
424
+ }
425
+
426
+ .select2-container-multi .select2-choices .select2-search-choice {
427
+ padding: 3px 5px 3px 18px;
428
+ margin: 3px 0 3px 5px;
429
+ position: relative;
430
+
431
+ line-height: 13px;
432
+ color: #333;
433
+ cursor: default;
434
+ border: 1px solid #aaaaaa;
435
+
436
+ -webkit-border-radius: 3px;
437
+ -moz-border-radius: 3px;
438
+ border-radius: 3px;
439
+
440
+ -webkit-box-shadow: 0 0 2px #ffffff inset, 0 1px 0 rgba(0,0,0,0.05);
441
+ -moz-box-shadow: 0 0 2px #ffffff inset, 0 1px 0 rgba(0,0,0,0.05);
442
+ box-shadow: 0 0 2px #ffffff inset, 0 1px 0 rgba(0,0,0,0.05);
443
+
444
+ -webkit-background-clip: padding-box;
445
+ -moz-background-clip: padding;
446
+ background-clip: padding-box;
447
+
448
+ background-color: #e4e4e4;
449
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#eeeeee', endColorstr='#f4f4f4', GradientType=0 );
450
+ background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee));
451
+ background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
452
+ background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
453
+ background-image: -o-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
454
+ background-image: -ms-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
455
+ background-image: linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
456
+ }
457
+ .select2-container-multi .select2-choices .select2-search-choice span {
458
+ cursor: default;
459
+ }
460
+ .select2-container-multi .select2-choices .select2-search-choice-focus {
461
+ background: #d4d4d4;
462
+ }
463
+
464
+ .select2-search-choice-close {
465
+ display: block;
466
+ width: 12px;
467
+ height: 13px;
468
+ position: absolute;
469
+ right: 3px;
470
+ top: 4px;
471
+
472
+ font-size: 1px;
473
+ outline: none;
474
+ background: url('select2.png') right top no-repeat;
475
+ }
476
+
477
+ .select2-container-multi .select2-search-choice-close {
478
+ left: 3px;
479
+ }
480
+
481
+ .select2-container-multi .select2-choices .select2-search-choice .select2-search-choice-close:hover {
482
+ background-position: right -11px;
483
+ }
484
+ .select2-container-multi .select2-choices .select2-search-choice-focus .select2-search-choice-close {
485
+ background-position: right -11px;
486
+ }
487
+
488
+ /* disabled styles */
489
+ .select2-container-multi.select2-container-disabled .select2-choices{
490
+ background-color: #f4f4f4;
491
+ background-image: none;
492
+ border: 1px solid #ddd;
493
+ cursor: default;
494
+ }
495
+
496
+ .select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice {
497
+ padding: 3px 5px 3px 5px;
498
+ border: 1px solid #ddd;
499
+ background-image: none;
500
+ background-color: #f4f4f4;
501
+ }
502
+
503
+ .select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice .select2-search-choice-close {
504
+ display: none;
505
+ }
506
+ /* end multiselect */
507
+
508
+
509
+ .select2-result-selectable .select2-match,
510
+ .select2-result-unselectable .select2-result-selectable .select2-match {
511
+ text-decoration: underline;
512
+ }
513
+ .select2-result-unselectable .select2-match {
514
+ text-decoration: none;
515
+ }
516
+
517
+ .select2-offscreen {
518
+ position: absolute;
519
+ left: -10000px;
520
+ }
521
+
522
+ /* Retina-ize icons */
523
+
524
+ @media only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-resolution: 144dpi) {
525
+ .select2-search input, .select2-search-choice-close, .select2-container .select2-choice abbr, .select2-container .select2-choice div b {
526
+ background-image: url('select2x2.png') !important;
527
+ background-repeat: no-repeat !important;
528
+ background-size: 60px 40px !important;
529
+ }
530
+ .select2-search input {
531
+ background-position: 100% -21px !important;
532
+ }
533
+ }
functions/admin-page-class/js/select2/select2.js ADDED
@@ -0,0 +1,2446 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ Copyright 2012 Igor Vaynberg
3
+
4
+ Version: @@ver@@ Timestamp: @@timestamp@@
5
+
6
+ This software is licensed under the Apache License, Version 2.0 (the "Apache License") or the GNU
7
+ General Public License version 2 (the "GPL License"). You may choose either license to govern your
8
+ use of this software only upon the condition that you accept all of the terms of either the Apache
9
+ License or the GPL License.
10
+
11
+ You may obtain a copy of the Apache License and the GPL License at:
12
+
13
+ http://www.apache.org/licenses/LICENSE-2.0
14
+ http://www.gnu.org/licenses/gpl-2.0.html
15
+
16
+ Unless required by applicable law or agreed to in writing, software distributed under the
17
+ Apache License or the GPL Licesnse is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
18
+ CONDITIONS OF ANY KIND, either express or implied. See the Apache License and the GPL License for
19
+ the specific language governing permissions and limitations under the Apache License and the GPL License.
20
+ */
21
+ (function ($) {
22
+ if(typeof $.fn.each2 == "undefined"){
23
+ $.fn.extend({
24
+ /*
25
+ * 4-10 times faster .each replacement
26
+ * use it carefully, as it overrides jQuery context of element on each iteration
27
+ */
28
+ each2 : function (c) {
29
+ var j = $([0]), i = -1, l = this.length;
30
+ while (
31
+ ++i < l
32
+ && (j.context = j[0] = this[i])
33
+ && c.call(j[0], i, j) !== false //"this"=DOM, i=index, j=jQuery object
34
+ );
35
+ return this;
36
+ }
37
+ });
38
+ }
39
+ })(jQuery);
40
+
41
+ (function ($, undefined) {
42
+ "use strict";
43
+ /*global document, window, jQuery, console */
44
+
45
+ if (window.Select2 !== undefined) {
46
+ return;
47
+ }
48
+
49
+ var KEY, AbstractSelect2, SingleSelect2, MultiSelect2, nextUid, sizer,
50
+ lastMousePosition, $document;
51
+
52
+ KEY = {
53
+ TAB: 9,
54
+ ENTER: 13,
55
+ ESC: 27,
56
+ SPACE: 32,
57
+ LEFT: 37,
58
+ UP: 38,
59
+ RIGHT: 39,
60
+ DOWN: 40,
61
+ SHIFT: 16,
62
+ CTRL: 17,
63
+ ALT: 18,
64
+ PAGE_UP: 33,
65
+ PAGE_DOWN: 34,
66
+ HOME: 36,
67
+ END: 35,
68
+ BACKSPACE: 8,
69
+ DELETE: 46,
70
+ isArrow: function (k) {
71
+ k = k.which ? k.which : k;
72
+ switch (k) {
73
+ case KEY.LEFT:
74
+ case KEY.RIGHT:
75
+ case KEY.UP:
76
+ case KEY.DOWN:
77
+ return true;
78
+ }
79
+ return false;
80
+ },
81
+ isControl: function (e) {
82
+ var k = e.which;
83
+ switch (k) {
84
+ case KEY.SHIFT:
85
+ case KEY.CTRL:
86
+ case KEY.ALT:
87
+ return true;
88
+ }
89
+
90
+ if (e.metaKey) return true;
91
+
92
+ return false;
93
+ },
94
+ isFunctionKey: function (k) {
95
+ k = k.which ? k.which : k;
96
+ return k >= 112 && k <= 123;
97
+ }
98
+ };
99
+
100
+ $document = $(document);
101
+
102
+ nextUid=(function() { var counter=1; return function() { return counter++; }; }());
103
+
104
+ function indexOf(value, array) {
105
+ var i = 0, l = array.length, v;
106
+
107
+ if (typeof value === "undefined") {
108
+ return -1;
109
+ }
110
+
111
+ if (value.constructor === String) {
112
+ for (; i < l; i = i + 1) if (value.localeCompare(array[i]) === 0) return i;
113
+ } else {
114
+ for (; i < l; i = i + 1) {
115
+ v = array[i];
116
+ if (v.constructor === String) {
117
+ if (v.localeCompare(value) === 0) return i;
118
+ } else {
119
+ if (v === value) return i;
120
+ }
121
+ }
122
+ }
123
+ return -1;
124
+ }
125
+
126
+ /**
127
+ * Compares equality of a and b taking into account that a and b may be strings, in which case localeCompare is used
128
+ * @param a
129
+ * @param b
130
+ */
131
+ function equal(a, b) {
132
+ if (a === b) return true;
133
+ if (a === undefined || b === undefined) return false;
134
+ if (a === null || b === null) return false;
135
+ if (a.constructor === String) return a.localeCompare(b) === 0;
136
+ if (b.constructor === String) return b.localeCompare(a) === 0;
137
+ return false;
138
+ }
139
+
140
+ /**
141
+ * Splits the string into an array of values, trimming each value. An empty array is returned for nulls or empty
142
+ * strings
143
+ * @param string
144
+ * @param separator
145
+ */
146
+ function splitVal(string, separator) {
147
+ var val, i, l;
148
+ if (string === null || string.length < 1) return [];
149
+ val = string.split(separator);
150
+ for (i = 0, l = val.length; i < l; i = i + 1) val[i] = $.trim(val[i]);
151
+ return val;
152
+ }
153
+
154
+ function getSideBorderPadding(element) {
155
+ return element.outerWidth(false) - element.width();
156
+ }
157
+
158
+ function installKeyUpChangeEvent(element) {
159
+ var key="keyup-change-value";
160
+ element.bind("keydown", function () {
161
+ if ($.data(element, key) === undefined) {
162
+ $.data(element, key, element.val());
163
+ }
164
+ });
165
+ element.bind("keyup", function () {
166
+ var val= $.data(element, key);
167
+ if (val !== undefined && element.val() !== val) {
168
+ $.removeData(element, key);
169
+ element.trigger("keyup-change");
170
+ }
171
+ });
172
+ }
173
+
174
+ $document.bind("mousemove", function (e) {
175
+ lastMousePosition = {x: e.pageX, y: e.pageY};
176
+ });
177
+
178
+ /**
179
+ * filters mouse events so an event is fired only if the mouse moved.
180
+ *
181
+ * filters out mouse events that occur when mouse is stationary but
182
+ * the elements under the pointer are scrolled.
183
+ */
184
+ function installFilteredMouseMove(element) {
185
+ element.bind("mousemove", function (e) {
186
+ var lastpos = lastMousePosition;
187
+ if (lastpos === undefined || lastpos.x !== e.pageX || lastpos.y !== e.pageY) {
188
+ $(e.target).trigger("mousemove-filtered", e);
189
+ }
190
+ });
191
+ }
192
+
193
+ /**
194
+ * Debounces a function. Returns a function that calls the original fn function only if no invocations have been made
195
+ * within the last quietMillis milliseconds.
196
+ *
197
+ * @param quietMillis number of milliseconds to wait before invoking fn
198
+ * @param fn function to be debounced
199
+ * @param ctx object to be used as this reference within fn
200
+ * @return debounced version of fn
201
+ */
202
+ function debounce(quietMillis, fn, ctx) {
203
+ ctx = ctx || undefined;
204
+ var timeout;
205
+ return function () {
206
+ var args = arguments;
207
+ window.clearTimeout(timeout);
208
+ timeout = window.setTimeout(function() {
209
+ fn.apply(ctx, args);
210
+ }, quietMillis);
211
+ };
212
+ }
213
+
214
+ /**
215
+ * A simple implementation of a thunk
216
+ * @param formula function used to lazily initialize the thunk
217
+ * @return {Function}
218
+ */
219
+ function thunk(formula) {
220
+ var evaluated = false,
221
+ value;
222
+ return function() {
223
+ if (evaluated === false) { value = formula(); evaluated = true; }
224
+ return value;
225
+ };
226
+ };
227
+
228
+ function installDebouncedScroll(threshold, element) {
229
+ var notify = debounce(threshold, function (e) { element.trigger("scroll-debounced", e);});
230
+ element.bind("scroll", function (e) {
231
+ if (indexOf(e.target, element.get()) >= 0) notify(e);
232
+ });
233
+ }
234
+
235
+ function killEvent(event) {
236
+ event.preventDefault();
237
+ event.stopPropagation();
238
+ }
239
+ function killEventImmediately(event) {
240
+ event.preventDefault();
241
+ event.stopImmediatePropagation();
242
+ }
243
+
244
+ function measureTextWidth(e) {
245
+ if (!sizer){
246
+ var style = e[0].currentStyle || window.getComputedStyle(e[0], null);
247
+ sizer = $("<div></div>").css({
248
+ position: "absolute",
249
+ left: "-10000px",
250
+ top: "-10000px",
251
+ display: "none",
252
+ fontSize: style.fontSize,
253
+ fontFamily: style.fontFamily,
254
+ fontStyle: style.fontStyle,
255
+ fontWeight: style.fontWeight,
256
+ letterSpacing: style.letterSpacing,
257
+ textTransform: style.textTransform,
258
+ whiteSpace: "nowrap"
259
+ });
260
+ $("body").append(sizer);
261
+ }
262
+ sizer.text(e.val());
263
+ return sizer.width();
264
+ }
265
+
266
+ function markMatch(text, term, markup) {
267
+ var match=text.toUpperCase().indexOf(term.toUpperCase()),
268
+ tl=term.length;
269
+
270
+ if (match<0) {
271
+ markup.push(text);
272
+ return;
273
+ }
274
+
275
+ markup.push(text.substring(0, match));
276
+ markup.push("<span class='select2-match'>");
277
+ markup.push(text.substring(match, match + tl));
278
+ markup.push("</span>");
279
+ markup.push(text.substring(match + tl, text.length));
280
+ }
281
+
282
+ /**
283
+ * Produces an ajax-based query function
284
+ *
285
+ * @param options object containing configuration paramters
286
+ * @param options.transport function that will be used to execute the ajax request. must be compatible with parameters supported by $.ajax
287
+ * @param options.url url for the data
288
+ * @param options.data a function(searchTerm, pageNumber, context) that should return an object containing query string parameters for the above url.
289
+ * @param options.dataType request data type: ajax, jsonp, other datatatypes supported by jQuery's $.ajax function or the transport function if specified
290
+ * @param options.traditional a boolean flag that should be true if you wish to use the traditional style of param serialization for the ajax request
291
+ * @param options.quietMillis (optional) milliseconds to wait before making the ajaxRequest, helps debounce the ajax function if invoked too often
292
+ * @param options.results a function(remoteData, pageNumber) that converts data returned form the remote request to the format expected by Select2.
293
+ * The expected format is an object containing the following keys:
294
+ * results array of objects that will be used as choices
295
+ * more (optional) boolean indicating whether there are more results available
296
+ * Example: {results:[{id:1, text:'Red'},{id:2, text:'Blue'}], more:true}
297
+ */
298
+ function ajax(options) {
299
+ var timeout, // current scheduled but not yet executed request
300
+ requestSequence = 0, // sequence used to drop out-of-order responses
301
+ handler = null,
302
+ quietMillis = options.quietMillis || 100;
303
+
304
+ return function (query) {
305
+ window.clearTimeout(timeout);
306
+ timeout = window.setTimeout(function () {
307
+ requestSequence += 1; // increment the sequence
308
+ var requestNumber = requestSequence, // this request's sequence number
309
+ data = options.data, // ajax data function
310
+ transport = options.transport || $.ajax,
311
+ traditional = options.traditional || false,
312
+ type = options.type || 'GET'; // set type of request (GET or POST)
313
+
314
+ data = data.call(this, query.term, query.page, query.context);
315
+
316
+ if( null !== handler) { handler.abort(); }
317
+
318
+ handler = transport.call(null, {
319
+ url: options.url,
320
+ dataType: options.dataType,
321
+ data: data,
322
+ type: type,
323
+ traditional: traditional,
324
+ success: function (data) {
325
+ if (requestNumber < requestSequence) {
326
+ return;
327
+ }
328
+ // TODO 3.0 - replace query.page with query so users have access to term, page, etc.
329
+ var results = options.results(data, query.page);
330
+ query.callback(results);
331
+ }
332
+ });
333
+ }, quietMillis);
334
+ };
335
+ }
336
+
337
+ /**
338
+ * Produces a query function that works with a local array
339
+ *
340
+ * @param options object containing configuration parameters. The options parameter can either be an array or an
341
+ * object.
342
+ *
343
+ * If the array form is used it is assumed that it contains objects with 'id' and 'text' keys.
344
+ *
345
+ * If the object form is used ti is assumed that it contains 'data' and 'text' keys. The 'data' key should contain
346
+ * an array of objects that will be used as choices. These objects must contain at least an 'id' key. The 'text'
347
+ * key can either be a String in which case it is expected that each element in the 'data' array has a key with the
348
+ * value of 'text' which will be used to match choices. Alternatively, text can be a function(item) that can extract
349
+ * the text.
350
+ */
351
+ function local(options) {
352
+ var data = options, // data elements
353
+ dataText,
354
+ text = function (item) { return ""+item.text; }; // function used to retrieve the text portion of a data item that is matched against the search
355
+
356
+ if (!$.isArray(data)) {
357
+ text = data.text;
358
+ // if text is not a function we assume it to be a key name
359
+ if (!$.isFunction(text)) {
360
+ dataText = data.text; // we need to store this in a separate variable because in the next step data gets reset and data.text is no longer available
361
+ text = function (item) { return item[dataText]; };
362
+ }
363
+ data = data.results;
364
+ }
365
+
366
+ return function (query) {
367
+ var t = query.term, filtered = { results: [] }, process;
368
+ if (t === "") {
369
+ query.callback({results: data});
370
+ return;
371
+ }
372
+
373
+ process = function(datum, collection) {
374
+ var group, attr;
375
+ datum = datum[0];
376
+ if (datum.children) {
377
+ group = {};
378
+ for (attr in datum) {
379
+ if (datum.hasOwnProperty(attr)) group[attr]=datum[attr];
380
+ }
381
+ group.children=[];
382
+ $(datum.children).each2(function(i, childDatum) { process(childDatum, group.children); });
383
+ if (group.children.length || query.matcher(t, text(group))) {
384
+ collection.push(group);
385
+ }
386
+ } else {
387
+ if (query.matcher(t, text(datum))) {
388
+ collection.push(datum);
389
+ }
390
+ }
391
+ };
392
+
393
+ $(data).each2(function(i, datum) { process(datum, filtered.results); });
394
+ query.callback(filtered);
395
+ };
396
+ }
397
+
398
+ // TODO javadoc
399
+ function tags(data) {
400
+ // TODO even for a function we should probably return a wrapper that does the same object/string check as
401
+ // the function for arrays. otherwise only functions that return objects are supported.
402
+ if ($.isFunction(data)) {
403
+ return data;
404
+ }
405
+
406
+ // if not a function we assume it to be an array
407
+
408
+ return function (query) {
409
+ var t = query.term, filtered = {results: []};
410
+ $(data).each(function () {
411
+ var isObject = this.text !== undefined,
412
+ text = isObject ? this.text : this;
413
+ if (t === "" || query.matcher(t, text)) {
414
+ filtered.results.push(isObject ? this : {id: this, text: this});
415
+ }
416
+ });
417
+ query.callback(filtered);
418
+ };
419
+ }
420
+
421
+ /**
422
+ * Checks if the formatter function should be used.
423
+ *
424
+ * Throws an error if it is not a function. Returns true if it should be used,
425
+ * false if no formatting should be performed.
426
+ *
427
+ * @param formatter
428
+ */
429
+ function checkFormatter(formatter, formatterName) {
430
+ if ($.isFunction(formatter)) return true;
431
+ if (!formatter) return false;
432
+ throw new Error("formatterName must be a function or a falsy value");
433
+ }
434
+
435
+ function evaluate(val) {
436
+ return $.isFunction(val) ? val() : val;
437
+ }
438
+
439
+ function countResults(results) {
440
+ var count = 0;
441
+ $.each(results, function(i, item) {
442
+ if (item.children) {
443
+ count += countResults(item.children);
444
+ } else {
445
+ count++;
446
+ }
447
+ });
448
+ return count;
449
+ }
450
+
451
+ /**
452
+ * Default tokenizer. This function uses breaks the input on substring match of any string from the
453
+ * opts.tokenSeparators array and uses opts.createSearchChoice to create the choice object. Both of those
454
+ * two options have to be defined in order for the tokenizer to work.
455
+ *
456
+ * @param input text user has typed so far or pasted into the search field
457
+ * @param selection currently selected choices
458
+ * @param selectCallback function(choice) callback tho add the choice to selection
459
+ * @param opts select2's opts
460
+ * @return undefined/null to leave the current input unchanged, or a string to change the input to the returned value
461
+ */
462
+ function defaultTokenizer(input, selection, selectCallback, opts) {
463
+ var original = input, // store the original so we can compare and know if we need to tell the search to update its text
464
+ dupe = false, // check for whether a token we extracted represents a duplicate selected choice
465
+ token, // token
466
+ index, // position at which the separator was found
467
+ i, l, // looping variables
468
+ separator; // the matched separator
469
+
470
+ if (!opts.createSearchChoice || !opts.tokenSeparators || opts.tokenSeparators.length < 1) return undefined;
471
+
472
+ while (true) {
473
+ index = -1;
474
+
475
+ for (i = 0, l = opts.tokenSeparators.length; i < l; i++) {
476
+ separator = opts.tokenSeparators[i];
477
+ index = input.indexOf(separator);
478
+ if (index >= 0) break;
479
+ }
480
+
481
+ if (index < 0) break; // did not find any token separator in the input string, bail
482
+
483
+ token = input.substring(0, index);
484
+ input = input.substring(index + separator.length);
485
+
486
+ if (token.length > 0) {
487
+ token = opts.createSearchChoice(token, selection);
488
+ if (token !== undefined && token !== null && opts.id(token) !== undefined && opts.id(token) !== null) {
489
+ dupe = false;
490
+ for (i = 0, l = selection.length; i < l; i++) {
491
+ if (equal(opts.id(token), opts.id(selection[i]))) {
492
+ dupe = true; break;
493
+ }
494
+ }
495
+
496
+ if (!dupe) selectCallback(token);
497
+ }
498
+ }
499
+ }
500
+
501
+ if (original.localeCompare(input) != 0) return input;
502
+ }
503
+
504
+ /**
505
+ * blurs any Select2 container that has focus when an element outside them was clicked or received focus
506
+ *
507
+ * also takes care of clicks on label tags that point to the source element
508
+ */
509
+ $document.ready(function () {
510
+ $document.bind("mousedown touchend", function (e) {
511
+ var target = $(e.target).closest("div.select2-container").get(0), attr;
512
+ var targetDropdown = null;
513
+ if (target) {
514
+ $document.find("div.select2-container-active").each(function () {
515
+ if (this !== target) $(this).data("select2").blur();
516
+ });
517
+ targetDropdown = $(target).data('select2').dropdown.get(0);
518
+ }
519
+
520
+ // close any other active dropdowns
521
+ target = targetDropdown || $(e.target).closest("div.select2-drop").get(0);
522
+ $document.find("div.select2-drop-active").each(function () {
523
+ if (this !== target) $(this).data("select2").blur();
524
+ });
525
+
526
+ target=$(e.target);
527
+ attr = target.attr("for");
528
+ if ("LABEL" === e.target.tagName && attr && attr.length > 0) {
529
+ attr = attr.replace(/([\[\].])/g,'\\$1'); /* escapes [, ], and . so properly selects the id */
530
+ target = $("#"+attr);
531
+ target = target.data("select2");
532
+ if (target !== undefined) { target.focus(); e.preventDefault();}
533
+ }
534
+ });
535
+ });
536
+
537
+ /**
538
+ * Creates a new class
539
+ *
540
+ * @param superClass
541
+ * @param methods
542
+ */
543
+ function clazz(SuperClass, methods) {
544
+ var constructor = function () {};
545
+ constructor.prototype = new SuperClass;
546
+ constructor.prototype.constructor = constructor;
547
+ constructor.prototype.parent = SuperClass.prototype;
548
+ constructor.prototype = $.extend(constructor.prototype, methods);
549
+ return constructor;
550
+ }
551
+
552
+ AbstractSelect2 = clazz(Object, {
553
+
554
+ // abstract
555
+ bind: function (func) {
556
+ var self = this;
557
+ return function () {
558
+ func.apply(self, arguments);
559
+ };
560
+ },
561
+
562
+ // abstract
563
+ init: function (opts) {
564
+ var results, search, resultsSelector = ".select2-results";
565
+
566
+ // prepare options
567
+ this.opts = opts = this.prepareOpts(opts);
568
+
569
+ this.id=opts.id;
570
+
571
+ // destroy if called on an existing component
572
+ if (opts.element.data("select2") !== undefined &&
573
+ opts.element.data("select2") !== null) {
574
+ this.destroy();
575
+ }
576
+
577
+ this.enabled=true;
578
+ this.container = this.createContainer();
579
+
580
+ this.containerId="s2id_"+(opts.element.attr("id") || "autogen"+nextUid());
581
+ this.containerSelector="#"+this.containerId.replace(/([;&,\.\+\*\~':"\!\^#$%@\[\]\(\)=>\|])/g, '\\$1');
582
+ this.container.attr("id", this.containerId);
583
+
584
+ // cache the body so future lookups are cheap
585
+ this.body = thunk(function() { return opts.element.closest("body"); });
586
+
587
+ if (opts.element.attr("class") !== undefined) {
588
+ this.container.addClass(opts.element.attr("class").replace(/validate\[[\S ]+] ?/, ''));
589
+ }
590
+
591
+ this.container.css(evaluate(opts.containerCss));
592
+ this.container.addClass(evaluate(opts.containerCssClass));
593
+
594
+ // swap container for the element
595
+ this.opts.element
596
+ .data("select2", this)
597
+ .hide()
598
+ .before(this.container);
599
+ this.container.data("select2", this);
600
+
601
+ this.dropdown = this.container.find(".select2-drop");
602
+ this.dropdown.addClass(evaluate(opts.dropdownCssClass));
603
+ this.dropdown.data("select2", this);
604
+
605
+ this.results = results = this.container.find(resultsSelector);
606
+ this.search = search = this.container.find("input.select2-input");
607
+
608
+ search.attr("tabIndex", this.opts.element.attr("tabIndex"));
609
+
610
+ this.resultsPage = 0;
611
+ this.context = null;
612
+
613
+ // initialize the container
614
+ this.initContainer();
615
+ this.initContainerWidth();
616
+
617
+ installFilteredMouseMove(this.results);
618
+ this.dropdown.delegate(resultsSelector, "mousemove-filtered", this.bind(this.highlightUnderEvent));
619
+
620
+ installDebouncedScroll(80, this.results);
621
+ this.dropdown.delegate(resultsSelector, "scroll-debounced", this.bind(this.loadMoreIfNeeded));
622
+
623
+ // if jquery.mousewheel plugin is installed we can prevent out-of-bounds scrolling of results via mousewheel
624
+ if ($.fn.mousewheel) {
625
+ results.mousewheel(function (e, delta, deltaX, deltaY) {
626
+ var top = results.scrollTop(), height;
627
+ if (deltaY > 0 && top - deltaY <= 0) {
628
+ results.scrollTop(0);
629
+ killEvent(e);
630
+ } else if (deltaY < 0 && results.get(0).scrollHeight - results.scrollTop() + deltaY <= results.height()) {
631
+ results.scrollTop(results.get(0).scrollHeight - results.height());
632
+ killEvent(e);
633
+ }
634
+ });
635
+ }
636
+
637
+ installKeyUpChangeEvent(search);
638
+ search.bind("keyup-change", this.bind(this.updateResults));
639
+ search.bind("focus", function () { search.addClass("select2-focused"); if (search.val() === " ") search.val(""); });
640
+ search.bind("blur", function () { search.removeClass("select2-focused");});
641
+
642
+ this.dropdown.delegate(resultsSelector, "mouseup", this.bind(function (e) {
643
+ if ($(e.target).closest(".select2-result-selectable:not(.select2-disabled)").length > 0) {
644
+ this.highlightUnderEvent(e);
645
+ this.selectHighlighted(e);
646
+ } else {
647
+ this.focusSearch();
648
+ }
649
+ killEvent(e);
650
+ }));
651
+
652
+ // trap all mouse events from leaving the dropdown. sometimes there may be a modal that is listening
653
+ // for mouse events outside of itself so it can close itself. since the dropdown is now outside the select2's
654
+ // dom it will trigger the popup close, which is not what we want
655
+ this.dropdown.bind("click mouseup mousedown", function (e) { e.stopPropagation(); });
656
+
657
+ if ($.isFunction(this.opts.initSelection)) {
658
+ // initialize selection based on the current value of the source element
659
+ this.initSelection();
660
+
661
+ // if the user has provided a function that can set selection based on the value of the source element
662
+ // we monitor the change event on the element and trigger it, allowing for two way synchronization
663
+ this.monitorSource();
664
+ }
665
+
666
+ if (opts.element.is(":disabled") || opts.element.is("[readonly='readonly']")) this.disable();
667
+ },
668
+
669
+ // abstract
670
+ destroy: function () {
671
+ var select2 = this.opts.element.data("select2");
672
+ if (select2 !== undefined) {
673
+ select2.container.remove();
674
+ select2.dropdown.remove();
675
+ select2.opts.element
676
+ .removeData("select2")
677
+ .unbind(".select2")
678
+ .show();
679
+ }
680
+ },
681
+
682
+ // abstract
683
+ prepareOpts: function (opts) {
684
+ var element, select, idKey, ajaxUrl;
685
+
686
+ element = opts.element;
687
+
688
+ if (element.get(0).tagName.toLowerCase() === "select") {
689
+ this.select = select = opts.element;
690
+ }
691
+
692
+ if (select) {
693
+ // these options are not allowed when attached to a select because they are picked up off the element itself
694
+ $.each(["id", "multiple", "ajax", "query", "createSearchChoice", "initSelection", "data", "tags"], function () {
695
+ if (this in opts) {
696
+ throw new Error("Option '" + this + "' is not allowed for Select2 when attached to a <select> element.");
697
+ }
698
+ });
699
+ }
700
+
701
+ opts = $.extend({}, {
702
+ populateResults: function(container, results, query) {
703
+ var populate, data, result, children, id=this.opts.id, self=this;
704
+
705
+ populate=function(results, container, depth) {
706
+
707
+ var i, l, result, selectable, compound, node, label, innerContainer, formatted;
708
+ for (i = 0, l = results.length; i < l; i = i + 1) {
709
+
710
+ result=results[i];
711
+ selectable=id(result) !== undefined;
712
+ compound=result.children && result.children.length > 0;
713
+
714
+ node=$("<li></li>");
715
+ node.addClass("select2-results-dept-"+depth);
716
+ node.addClass("select2-result");
717
+ node.addClass(selectable ? "select2-result-selectable" : "select2-result-unselectable");
718
+ if (compound) { node.addClass("select2-result-with-children"); }
719
+ node.addClass(self.opts.formatResultCssClass(result));
720
+
721
+ label=$("<div></div>");
722
+ label.addClass("select2-result-label");
723
+
724
+ formatted=opts.formatResult(result, label, query);
725
+ if (formatted!==undefined) {
726
+ label.html(self.opts.escapeMarkup(formatted));
727
+ }
728
+
729
+ node.append(label);
730
+
731
+ if (compound) {
732
+
733
+ innerContainer=$("<ul></ul>");
734
+ innerContainer.addClass("select2-result-sub");
735
+ populate(result.children, innerContainer, depth+1);
736
+ node.append(innerContainer);
737
+ }
738
+
739
+ node.data("select2-data", result);
740
+ container.append(node);
741
+ }
742
+ };
743
+
744
+ populate(results, container, 0);
745
+ }
746
+ }, $.fn.select2.defaults, opts);
747
+
748
+ if (typeof(opts.id) !== "function") {
749
+ idKey = opts.id;
750
+ opts.id = function (e) { return e[idKey]; };
751
+ }
752
+
753
+ if (select) {
754
+ opts.query = this.bind(function (query) {
755
+ var data = { results: [], more: false },
756
+ term = query.term,
757
+ children, firstChild, process;
758
+
759
+ process=function(element, collection) {
760
+ var group;
761
+ if (element.is("option")) {
762
+ if (query.matcher(term, element.text(), element)) {
763
+ collection.push({id:element.attr("value"), text:element.text(), element: element.get(), css: element.attr("class")});
764
+ }
765
+ } else if (element.is("optgroup")) {
766
+ group={text:element.attr("label"), children:[], element: element.get(), css: element.attr("class")};
767
+ element.children().each2(function(i, elm) { process(elm, group.children); });
768
+ if (group.children.length>0) {
769
+ collection.push(group);
770
+ }
771
+ }
772
+ };
773
+
774
+ children=element.children();
775
+
776
+ // ignore the placeholder option if there is one
777
+ if (this.getPlaceholder() !== undefined && children.length > 0) {
778
+ firstChild = children[0];
779
+ if ($(firstChild).text() === "") {
780
+ children=children.not(firstChild);
781
+ }
782
+ }
783
+
784
+ children.each2(function(i, elm) { process(elm, data.results); });
785
+
786
+ query.callback(data);
787
+ });
788
+ // this is needed because inside val() we construct choices from options and there id is hardcoded
789
+ opts.id=function(e) { return e.id; };
790
+ opts.formatResultCssClass = function(data) { return data.css; }
791
+ } else {
792
+ if (!("query" in opts)) {
793
+ if ("ajax" in opts) {
794
+ ajaxUrl = opts.element.data("ajax-url");
795
+ if (ajaxUrl && ajaxUrl.length > 0) {
796
+ opts.ajax.url = ajaxUrl;
797
+ }
798
+ opts.query = ajax(opts.ajax);
799
+ } else if ("data" in opts) {
800
+ opts.query = local(opts.data);
801
+ } else if ("tags" in opts) {
802
+ opts.query = tags(opts.tags);
803
+ if (opts.createSearchChoice === undefined) {
804
+ opts.createSearchChoice = function (term) { return {id: term, text: term}; };
805
+ }
806
+ opts.initSelection = function (element, callback) {
807
+ var data = [];
808
+ $(splitVal(element.val(), opts.separator)).each(function () {
809
+ var id = this, text = this, tags=opts.tags;
810
+ if ($.isFunction(tags)) tags=tags();
811
+ $(tags).each(function() { if (equal(this.id, id)) { text = this.text; return false; } });
812
+ data.push({id: id, text: text});
813
+ });
814
+
815
+ callback(data);
816
+ };
817
+ }
818
+ }
819
+ }
820
+ if (typeof(opts.query) !== "function") {
821
+ throw "query function not defined for Select2 " + opts.element.attr("id");
822
+ }
823
+
824
+ return opts;
825
+ },
826
+
827
+ /**
828
+ * Monitor the original element for changes and update select2 accordingly
829
+ */
830
+ // abstract
831
+ monitorSource: function () {
832
+ this.opts.element.bind("change.select2", this.bind(function (e) {
833
+ if (this.opts.element.data("select2-change-triggered") !== true) {
834
+ this.initSelection();
835
+ }
836
+ }));
837
+ },
838
+
839
+ /**
840
+ * Triggers the change event on the source element
841
+ */
842
+ // abstract
843
+ triggerChange: function (details) {
844
+
845
+ details = details || {};
846
+ details= $.extend({}, details, { type: "change", val: this.val() });
847
+ // prevents recursive triggering
848
+ this.opts.element.data("select2-change-triggered", true);
849
+ this.opts.element.trigger(details);
850
+ this.opts.element.data("select2-change-triggered", false);
851
+
852
+ // some validation frameworks ignore the change event and listen instead to keyup, click for selects
853
+ // so here we trigger the click event manually
854
+ this.opts.element.click();
855
+
856
+ // ValidationEngine ignorea the change event and listens instead to blur
857
+ // so here we trigger the blur event manually if so desired
858
+ if (this.opts.blurOnChange)
859
+ this.opts.element.blur();
860
+ },
861
+
862
+
863
+ // abstract
864
+ enable: function() {
865
+ if (this.enabled) return;
866
+
867
+ this.enabled=true;
868
+ this.container.removeClass("select2-container-disabled");
869
+ this.opts.element.removeAttr("disabled");
870
+ },
871
+
872
+ // abstract
873
+ disable: function() {
874
+ if (!this.enabled) return;
875
+
876
+ this.close();
877
+
878
+ this.enabled=false;
879
+ this.container.addClass("select2-container-disabled");
880
+ this.opts.element.attr("disabled", "disabled");
881
+ },
882
+
883
+ // abstract
884
+ opened: function () {
885
+ return this.container.hasClass("select2-dropdown-open");
886
+ },
887
+
888
+ // abstract
889
+ positionDropdown: function() {
890
+ var offset = this.container.offset(),
891
+ height = this.container.outerHeight(false),
892
+ width = this.container.outerWidth(false),
893
+ dropHeight = this.dropdown.outerHeight(false),
894
+ viewPortRight = $(window).scrollLeft() + document.documentElement.clientWidth,
895
+ viewportBottom = $(window).scrollTop() + document.documentElement.clientHeight,
896
+ dropTop = offset.top + height,
897
+ dropLeft = offset.left,
898
+ enoughRoomBelow = dropTop + dropHeight <= viewportBottom,
899
+ enoughRoomAbove = (offset.top - dropHeight) >= this.body().scrollTop(),
900
+ dropWidth = this.dropdown.outerWidth(false),
901
+ enoughRoomOnRight = dropLeft + dropWidth <= viewPortRight,
902
+ aboveNow = this.dropdown.hasClass("select2-drop-above"),
903
+ bodyOffset,
904
+ above,
905
+ css;
906
+
907
+ // console.log("below/ droptop:", dropTop, "dropHeight", dropHeight, "sum", (dropTop+dropHeight)+" viewport bottom", viewportBottom, "enough?", enoughRoomBelow);
908
+ // console.log("above/ offset.top", offset.top, "dropHeight", dropHeight, "top", (offset.top-dropHeight), "scrollTop", this.body().scrollTop(), "enough?", enoughRoomAbove);
909
+
910
+ // fix positioning when body has an offset and is not position: static
911
+
912
+ if (this.body().css('position') !== 'static') {
913
+ bodyOffset = this.body().offset();
914
+ dropTop -= bodyOffset.top;
915
+ dropLeft -= bodyOffset.left;
916
+ }
917
+
918
+ // always prefer the current above/below alignment, unless there is not enough room
919
+
920
+ if (aboveNow) {
921
+ above = true;
922
+ if (!enoughRoomAbove && enoughRoomBelow) above = false;
923
+ } else {
924
+ above = false;
925
+ if (!enoughRoomBelow && enoughRoomAbove) above = true;
926
+ }
927
+
928
+ if (!enoughRoomOnRight) {
929
+ dropLeft = offset.left + width - dropWidth;
930
+ }
931
+
932
+ if (above) {
933
+ dropTop = offset.top - dropHeight;
934
+ this.container.addClass("select2-drop-above");
935
+ this.dropdown.addClass("select2-drop-above");
936
+ }
937
+ else {
938
+ this.container.removeClass("select2-drop-above");
939
+ this.dropdown.removeClass("select2-drop-above");
940
+ }
941
+
942
+ css = $.extend({
943
+ top: dropTop,
944
+ left: dropLeft,
945
+ width: width
946
+ }, evaluate(this.opts.dropdownCss));
947
+
948
+ this.dropdown.css(css);
949
+ },
950
+
951
+ // abstract
952
+ shouldOpen: function() {
953
+ var event;
954
+
955
+ if (this.opened()) return false;
956
+
957
+ event = $.Event("open");
958
+ this.opts.element.trigger(event);
959
+ return !event.isDefaultPrevented();
960
+ },
961
+
962
+ // abstract
963
+ clearDropdownAlignmentPreference: function() {
964
+ // clear the classes used to figure out the preference of where the dropdown should be opened
965
+ this.container.removeClass("select2-drop-above");
966
+ this.dropdown.removeClass("select2-drop-above");
967
+ },
968
+
969
+ /**
970
+ * Opens the dropdown
971
+ *
972
+ * @return {Boolean} whether or not dropdown was opened. This method will return false if, for example,
973
+ * the dropdown is already open, or if the 'open' event listener on the element called preventDefault().
974
+ */
975
+ // abstract
976
+ open: function () {
977
+
978
+ if (!this.shouldOpen()) return false;
979
+
980
+ window.setTimeout(this.bind(this.opening), 1);
981
+
982
+ return true;
983
+ },
984
+
985
+ /**
986
+ * Performs the opening of the dropdown
987
+ */
988
+ // abstract
989
+ opening: function() {
990
+ var cid = this.containerId, selector = this.containerSelector,
991
+ scroll = "scroll." + cid, resize = "resize." + cid;
992
+
993
+ this.container.parents().each(function() {
994
+ $(this).bind(scroll, function() {
995
+ var s2 = $(selector);
996
+ if (s2.length == 0) {
997
+ $(this).unbind(scroll);
998
+ }
999
+ s2.select2("close");
1000
+ });
1001
+ });
1002
+
1003
+ window.setTimeout(function() {
1004
+ // this is done inside a timeout because IE will sometimes fire a resize event while opening
1005
+ // the dropdown and that causes this handler to immediately close it. this way the dropdown
1006
+ // has a chance to fully open before we start listening to resize events
1007
+ $(window).bind(resize, function() {
1008
+ var s2 = $(selector);
1009
+ if (s2.length == 0) {
1010
+ $(window).unbind(resize);
1011
+ }
1012
+ s2.select2("close");
1013
+ })
1014
+ }, 10);
1015
+
1016
+ this.clearDropdownAlignmentPreference();
1017
+
1018
+ if (this.search.val() === " ") { this.search.val(""); }
1019
+
1020
+ this.container.addClass("select2-dropdown-open").addClass("select2-container-active");
1021
+
1022
+ this.updateResults(true);
1023
+
1024
+ if(this.dropdown[0] !== this.body().children().last()[0]) {
1025
+ this.dropdown.detach().appendTo(this.body());
1026
+ }
1027
+
1028
+ this.dropdown.show();
1029
+
1030
+ this.positionDropdown();
1031
+ this.dropdown.addClass("select2-drop-active");
1032
+
1033
+ this.ensureHighlightVisible();
1034
+
1035
+ this.focusSearch();
1036
+ },
1037
+
1038
+ // abstract
1039
+ close: function () {
1040
+ if (!this.opened()) return;
1041
+
1042
+ var self = this;
1043
+
1044
+ this.container.parents().each(function() {
1045
+ $(this).unbind("scroll." + self.containerId);
1046
+ });
1047
+ $(window).unbind("resize." + this.containerId);
1048
+
1049
+ this.clearDropdownAlignmentPreference();
1050
+
1051
+ this.dropdown.hide();
1052
+ this.container.removeClass("select2-dropdown-open").removeClass("select2-container-active");
1053
+ this.results.empty();
1054
+ this.clearSearch();
1055
+
1056
+ this.opts.element.trigger($.Event("close"));
1057
+ },
1058
+
1059
+ // abstract
1060
+ clearSearch: function () {
1061
+
1062
+ },
1063
+
1064
+ // abstract
1065
+ ensureHighlightVisible: function () {
1066
+ var results = this.results, children, index, child, hb, rb, y, more;
1067
+
1068
+ index = this.highlight();
1069
+
1070
+ if (index < 0) return;
1071
+
1072
+ if (index == 0) {
1073
+
1074
+ // if the first element is highlighted scroll all the way to the top,
1075
+ // that way any unselectable headers above it will also be scrolled
1076
+ // into view
1077
+
1078
+ results.scrollTop(0);
1079
+ return;
1080
+ }
1081
+
1082
+ children = results.find(".select2-result-selectable");
1083
+
1084
+ child = $(children[index]);
1085
+
1086
+ hb = child.offset().top + child.outerHeight(true);
1087
+
1088
+ // if this is the last child lets also make sure select2-more-results is visible
1089
+ if (index === children.length - 1) {
1090
+ more = results.find("li.select2-more-results");
1091
+ if (more.length > 0) {
1092
+ hb = more.offset().top + more.outerHeight(true);
1093
+ }
1094
+ }
1095
+
1096
+ rb = results.offset().top + results.outerHeight(true);
1097
+ if (hb > rb) {
1098
+ results.scrollTop(results.scrollTop() + (hb - rb));
1099
+ }
1100
+ y = child.offset().top - results.offset().top;
1101
+
1102
+ // make sure the top of the element is visible
1103
+ if (y < 0 && child.css('display') != 'none' ) {
1104
+ results.scrollTop(results.scrollTop() + y); // y is negative
1105
+ }
1106
+ },
1107
+
1108
+ // abstract
1109
+ moveHighlight: function (delta) {
1110
+ var choices = this.results.find(".select2-result-selectable"),
1111
+ index = this.highlight();
1112
+
1113
+ while (index > -1 && index < choices.length) {
1114
+ index += delta;
1115
+ var choice = $(choices[index]);
1116
+ if (choice.hasClass("select2-result-selectable") && !choice.hasClass("select2-disabled")) {
1117
+ this.highlight(index);
1118
+ break;
1119
+ }
1120
+ }
1121
+ },
1122
+
1123
+ // abstract
1124
+ highlight: function (index) {
1125
+ var choices = this.results.find(".select2-result-selectable").not(".select2-disabled");
1126
+
1127
+ if (arguments.length === 0) {
1128
+ return indexOf(choices.filter(".select2-highlighted")[0], choices.get());
1129
+ }
1130
+
1131
+ if (index >= choices.length) index = choices.length - 1;
1132
+ if (index < 0) index = 0;
1133
+
1134
+ choices.removeClass("select2-highlighted");
1135
+
1136
+ $(choices[index]).addClass("select2-highlighted");
1137
+ this.ensureHighlightVisible();
1138
+
1139
+ },
1140
+
1141
+ // abstract
1142
+ countSelectableResults: function() {
1143
+ return this.results.find(".select2-result-selectable").not(".select2-disabled").length;
1144
+ },
1145
+
1146
+ // abstract
1147
+ highlightUnderEvent: function (event) {
1148
+ var el = $(event.target).closest(".select2-result-selectable");
1149
+ if (el.length > 0 && !el.is(".select2-highlighted")) {
1150
+ var choices = this.results.find('.select2-result-selectable');
1151
+ this.highlight(choices.index(el));
1152
+ } else if (el.length == 0) {
1153
+ // if we are over an unselectable item remove al highlights
1154
+ this.results.find(".select2-highlighted").removeClass("select2-highlighted");
1155
+ }
1156
+ },
1157
+
1158
+ // abstract
1159
+ loadMoreIfNeeded: function () {
1160
+ var results = this.results,
1161
+ more = results.find("li.select2-more-results"),
1162
+ below, // pixels the element is below the scroll fold, below==0 is when the element is starting to be visible
1163
+ offset = -1, // index of first element without data
1164
+ page = this.resultsPage + 1,
1165
+ self=this,
1166
+ term=this.search.val(),
1167
+ context=this.context;
1168
+
1169
+ if (more.length === 0) return;
1170
+ below = more.offset().top - results.offset().top - results.height();
1171
+
1172
+ if (below <= 0) {
1173
+ more.addClass("select2-active");
1174
+ this.opts.query({
1175
+ term: term,
1176
+ page: page,
1177
+ context: context,
1178
+ matcher: this.opts.matcher,
1179
+ callback: this.bind(function (data) {
1180
+
1181
+ // ignore a response if the select2 has been closed before it was received
1182
+ if (!self.opened()) return;
1183
+
1184
+
1185
+ self.opts.populateResults.call(this, results, data.results, {term: term, page: page, context:context});
1186
+
1187
+ if (data.more===true) {
1188
+ more.detach().appendTo(results).text(self.opts.formatLoadMore(page+1));
1189
+ window.setTimeout(function() { self.loadMoreIfNeeded(); }, 10);
1190
+ } else {
1191
+ more.remove();
1192
+ }
1193
+ self.positionDropdown();
1194
+ self.resultsPage = page;
1195
+ })});
1196
+ }
1197
+ },
1198
+
1199
+ /**
1200
+ * Default tokenizer function which does nothing
1201
+ */
1202
+ tokenize: function() {
1203
+
1204
+ },
1205
+
1206
+ /**
1207
+ * @param initial whether or not this is the call to this method right after the dropdown has been opened
1208
+ */
1209
+ // abstract
1210
+ updateResults: function (initial) {
1211
+ var search = this.search, results = this.results, opts = this.opts, data, self=this, input;
1212
+
1213
+ // if the search is currently hidden we do not alter the results
1214
+ if (initial !== true && (this.showSearchInput === false || !this.opened())) {
1215
+ return;
1216
+ }
1217
+
1218
+ search.addClass("select2-active");
1219
+
1220
+ function postRender() {
1221
+ results.scrollTop(0);
1222
+ search.removeClass("select2-active");
1223
+ self.positionDropdown();
1224
+ }
1225
+
1226
+ function render(html) {
1227
+ results.html(self.opts.escapeMarkup(html));
1228
+ postRender();
1229
+ }
1230
+
1231
+ if (opts.maximumSelectionSize >=1) {
1232
+ data = this.data();
1233
+ if ($.isArray(data) && data.length >= opts.maximumSelectionSize && checkFormatter(opts.formatSelectionTooBig, "formatSelectionTooBig")) {
1234
+ render("<li class='select2-selection-limit'>" + opts.formatSelectionTooBig(opts.maximumSelectionSize) + "</li>");
1235
+ return;
1236
+ }
1237
+ }
1238
+
1239
+ if (search.val().length < opts.minimumInputLength) {
1240
+ if (checkFormatter(opts.formatInputTooShort, "formatInputTooShort")) {
1241
+ render("<li class='select2-no-results'>" + opts.formatInputTooShort(search.val(), opts.minimumInputLength) + "</li>");
1242
+ } else {
1243
+ render("");
1244
+ }
1245
+ return;
1246
+ }
1247
+ else if (opts.formatSearching()) {
1248
+ render("<li class='select2-searching'>" + opts.formatSearching() + "</li>");
1249
+ }
1250
+
1251
+ // give the tokenizer a chance to pre-process the input
1252
+ input = this.tokenize();
1253
+ if (input != undefined && input != null) {
1254
+ search.val(input);
1255
+ }
1256
+
1257
+ this.resultsPage = 1;
1258
+ opts.query({
1259
+ term: search.val(),
1260
+ page: this.resultsPage,
1261
+ context: null,
1262
+ matcher: opts.matcher,
1263
+ callback: this.bind(function (data) {
1264
+ var def; // default choice
1265
+
1266
+ // ignore a response if the select2 has been closed before it was received
1267
+ if (!this.opened()) return;
1268
+
1269
+ // save context, if any
1270
+ this.context = (data.context===undefined) ? null : data.context;
1271
+
1272
+ // create a default choice and prepend it to the list
1273
+ if (this.opts.createSearchChoice && search.val() !== "") {
1274
+ def = this.opts.createSearchChoice.call(null, search.val(), data.results);
1275
+ if (def !== undefined && def !== null && self.id(def) !== undefined && self.id(def) !== null) {
1276
+ if ($(data.results).filter(
1277
+ function () {
1278
+ return equal(self.id(this), self.id(def));
1279
+ }).length === 0) {
1280
+ data.results.unshift(def);
1281
+ }
1282
+ }
1283
+ }
1284
+
1285
+ if (data.results.length === 0 && checkFormatter(opts.formatNoMatches, "formatNoMatches")) {
1286
+ render("<li class='select2-no-results'>" + opts.formatNoMatches(search.val()) + "</li>");
1287
+ return;
1288
+ }
1289
+
1290
+ results.empty();
1291
+ self.opts.populateResults.call(this, results, data.results, {term: search.val(), page: this.resultsPage, context:null});
1292
+
1293
+ if (data.more === true && checkFormatter(opts.formatLoadMore, "formatLoadMore")) {
1294
+ results.append("<li class='select2-more-results'>" + self.opts.escapeMarkup(opts.formatLoadMore(this.resultsPage)) + "</li>");
1295
+ window.setTimeout(function() { self.loadMoreIfNeeded(); }, 10);
1296
+ }
1297
+
1298
+ this.postprocessResults(data, initial);
1299
+
1300
+ postRender();
1301
+ })});
1302
+ },
1303
+
1304
+ // abstract
1305
+ cancel: function () {
1306
+ this.close();
1307
+ },
1308
+
1309
+ // abstract
1310
+ blur: function () {
1311
+ this.close();
1312
+ this.container.removeClass("select2-container-active");
1313
+ this.dropdown.removeClass("select2-drop-active");
1314
+ // synonymous to .is(':focus'), which is available in jquery >= 1.6
1315
+ if (this.search[0] === document.activeElement) { this.search.blur(); }
1316
+ this.clearSearch();
1317
+ this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus");
1318
+ this.opts.element.triggerHandler("blur");
1319
+ },
1320
+
1321
+ // abstract
1322
+ focusSearch: function () {
1323
+ // need to do it here as well as in timeout so it works in IE
1324
+ this.search.show();
1325
+ this.search.focus();
1326
+
1327
+ /* we do this in a timeout so that current event processing can complete before this code is executed.
1328
+ this makes sure the search field is focussed even if the current event would blur it */
1329
+ window.setTimeout(this.bind(function () {
1330
+ // reset the value so IE places the cursor at the end of the input box
1331
+ this.search.show();
1332
+ this.search.focus();
1333
+ this.search.val(this.search.val());
1334
+ }), 10);
1335
+ },
1336
+
1337
+ // abstract
1338
+ selectHighlighted: function () {
1339
+ var index=this.highlight(),
1340
+ highlighted=this.results.find(".select2-highlighted").not(".select2-disabled"),
1341
+ data = highlighted.closest('.select2-result-selectable').data("select2-data");
1342
+ if (data) {
1343
+ highlighted.addClass("select2-disabled");
1344
+ this.highlight(index);
1345
+ this.onSelect(data);
1346
+ }
1347
+ },
1348
+
1349
+ // abstract
1350
+ getPlaceholder: function () {
1351
+ return this.opts.element.attr("placeholder") ||
1352
+ this.opts.element.attr("data-placeholder") || // jquery 1.4 compat
1353
+ this.opts.element.data("placeholder") ||
1354
+ this.opts.placeholder;
1355
+ },
1356
+
1357
+ /**
1358
+ * Get the desired width for the container element. This is
1359
+ * derived first from option `width` passed to select2, then
1360
+ * the inline 'style' on the original element, and finally
1361
+ * falls back to the jQuery calculated element width.
1362
+ */
1363
+ // abstract
1364
+ initContainerWidth: function () {
1365
+ function resolveContainerWidth() {
1366
+ var style, attrs, matches, i, l;
1367
+
1368
+ if (this.opts.width === "off") {
1369
+ return null;
1370
+ } else if (this.opts.width === "element"){
1371
+ return this.opts.element.outerWidth(false) === 0 ? 'auto' : this.opts.element.outerWidth(false) + 'px';
1372
+ } else if (this.opts.width === "copy" || this.opts.width === "resolve") {
1373
+ // check if there is inline style on the element that contains width
1374
+ style = this.opts.element.attr('style');
1375
+ if (style !== undefined) {
1376
+ attrs = style.split(';');
1377
+ for (i = 0, l = attrs.length; i < l; i = i + 1) {
1378
+ matches = attrs[i].replace(/\s/g, '')
1379
+ .match(/width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/);
1380
+ if (matches !== null && matches.length >= 1)
1381
+ return matches[1];
1382
+ }
1383
+ }
1384
+
1385
+ if (this.opts.width === "resolve") {
1386
+ // next check if css('width') can resolve a width that is percent based, this is sometimes possible
1387
+ // when attached to input type=hidden or elements hidden via css
1388
+ style = this.opts.element.css('width');
1389
+ if (style.indexOf("%") > 0) return style;
1390
+
1391
+ // finally, fallback on the calculated width of the element
1392
+ return (this.opts.element.outerWidth(false) === 0 ? 'auto' : this.opts.element.outerWidth(false) + 'px');
1393
+ }
1394
+
1395
+ return null;
1396
+ } else if ($.isFunction(this.opts.width)) {
1397
+ return this.opts.width();
1398
+ } else {
1399
+ return this.opts.width;
1400
+ }
1401
+ };
1402
+
1403
+ var width = resolveContainerWidth.call(this);
1404
+ if (width !== null) {
1405
+ this.container.attr("style", "width: "+width);
1406
+ }
1407
+ }
1408
+ });
1409
+
1410
+ SingleSelect2 = clazz(AbstractSelect2, {
1411
+
1412
+ // single
1413
+
1414
+ createContainer: function () {
1415
+ var container = $("<div></div>", {
1416
+ "class": "select2-container"
1417
+ }).html([
1418
+ " <a href='javascript:void(0)' onclick='return false;' class='select2-choice'>",
1419
+ " <span></span><abbr class='select2-search-choice-close' style='display:none;'></abbr>",
1420
+ " <div><b></b></div>" ,
1421
+ "</a>",
1422
+ " <div class='select2-drop select2-offscreen'>" ,
1423
+ " <div class='select2-search'>" ,
1424
+ " <input type='text' autocomplete='off' class='select2-input'/>" ,
1425
+ " </div>" ,
1426
+ " <ul class='select2-results'>" ,
1427
+ " </ul>" ,
1428
+ "</div>"].join(""));
1429
+ return container;
1430
+ },
1431
+
1432
+ // single
1433
+ opening: function () {
1434
+ this.search.show();
1435
+ this.parent.opening.apply(this, arguments);
1436
+ this.dropdown.removeClass("select2-offscreen");
1437
+ },
1438
+
1439
+ // single
1440
+ close: function () {
1441
+ if (!this.opened()) return;
1442
+ this.parent.close.apply(this, arguments);
1443
+ this.dropdown.removeAttr("style").addClass("select2-offscreen").insertAfter(this.selection).show();
1444
+ },
1445
+
1446
+ // single
1447
+ focus: function () {
1448
+ this.close();
1449
+ this.selection.focus();
1450
+ },
1451
+
1452
+ // single
1453
+ isFocused: function () {
1454
+ return this.selection[0] === document.activeElement;
1455
+ },
1456
+
1457
+ // single
1458
+ cancel: function () {
1459
+ this.parent.cancel.apply(this, arguments);
1460
+ this.selection.focus();
1461
+ },
1462
+
1463
+ // single
1464
+ initContainer: function () {
1465
+
1466
+ var selection,
1467
+ container = this.container,
1468
+ dropdown = this.dropdown,
1469
+ clickingInside = false;
1470
+
1471
+ this.selection = selection = container.find(".select2-choice");
1472
+
1473
+ this.search.bind("keydown", this.bind(function (e) {
1474
+ if (!this.enabled) return;
1475
+
1476
+ if (e.which === KEY.PAGE_UP || e.which === KEY.PAGE_DOWN) {
1477
+ // prevent the page from scrolling
1478
+ killEvent(e);
1479
+ return;
1480
+ }
1481
+
1482
+ if (this.opened()) {
1483
+ switch (e.which) {
1484
+ case KEY.UP:
1485
+ case KEY.DOWN:
1486
+ this.moveHighlight((e.which === KEY.UP) ? -1 : 1);
1487
+ killEvent(e);
1488
+ return;
1489
+ case KEY.TAB:
1490
+ case KEY.ENTER:
1491
+ this.selectHighlighted();
1492
+ killEvent(e);
1493
+ return;
1494
+ case KEY.ESC:
1495
+ this.cancel(e);
1496
+ killEvent(e);
1497
+ return;
1498
+ }
1499
+ } else {
1500
+
1501
+ if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) || e.which === KEY.ESC) {
1502
+ return;
1503
+ }
1504
+
1505
+ if (this.opts.openOnEnter === false && e.which === KEY.ENTER) {
1506
+ return;
1507
+ }
1508
+
1509
+ this.open();
1510
+
1511
+ if (e.which === KEY.ENTER) {
1512
+ // do not propagate the event otherwise we open, and propagate enter which closes
1513
+ return;
1514
+ }
1515
+ }
1516
+ }));
1517
+
1518
+ this.search.bind("focus", this.bind(function() {
1519
+ this.selection.attr("tabIndex", "-1");
1520
+ }));
1521
+ this.search.bind("blur", this.bind(function() {
1522
+ if (!this.opened()) this.container.removeClass("select2-container-active");
1523
+ window.setTimeout(this.bind(function() {
1524
+ // restore original tab index
1525
+ var ti=this.opts.element.attr("tabIndex") || 0;
1526
+ if (ti) {
1527
+ this.selection.attr("tabIndex", ti);
1528
+ } else {
1529
+ this.selection.removeAttr("tabIndex");
1530
+ }
1531
+ }), 10);
1532
+ }));
1533
+
1534
+ selection.delegate("abbr", "mousedown", this.bind(function (e) {
1535
+ if (!this.enabled) return;
1536
+ this.clear();
1537
+ killEventImmediately(e);
1538
+ this.close();
1539
+ this.triggerChange();
1540
+ this.selection.focus();
1541
+ }));
1542
+
1543
+ selection.bind("mousedown", this.bind(function (e) {
1544
+ clickingInside = true;
1545
+
1546
+ if (this.opened()) {
1547
+ this.close();
1548
+ this.selection.focus();
1549
+ } else if (this.enabled) {
1550
+ this.open();
1551
+ }
1552
+
1553
+ clickingInside = false;
1554
+ }));
1555
+
1556
+ dropdown.bind("mousedown", this.bind(function() { this.search.focus(); }));
1557
+
1558
+ selection.bind("focus", this.bind(function() {
1559
+ this.container.addClass("select2-container-active");
1560
+ // hide the search so the tab key does not focus on it
1561
+ this.search.attr("tabIndex", "-1");
1562
+ }));
1563
+
1564
+ selection.bind("blur", this.bind(function() {
1565
+ if (!this.opened()) {
1566
+ this.container.removeClass("select2-container-active");
1567
+ }
1568
+ window.setTimeout(this.bind(function() { this.search.attr("tabIndex", this.opts.element.attr("tabIndex") || 0); }), 10);
1569
+ }));
1570
+
1571
+ selection.bind("keydown", this.bind(function(e) {
1572
+ if (!this.enabled) return;
1573
+
1574
+ if (e.which == KEY.DOWN || e.which == KEY.UP
1575
+ || (e.which == KEY.ENTER && this.opts.openOnEnter)) {
1576
+ this.open();
1577
+ killEvent(e);
1578
+ return;
1579
+ }
1580
+
1581
+ if (e.which == KEY.DELETE || e.which == KEY.BACKSPACE) {
1582
+ if (this.opts.allowClear) {
1583
+ this.clear();
1584
+ }
1585
+ killEvent(e);
1586
+ return;
1587
+ }
1588
+ }));
1589
+ selection.bind("keypress", this.bind(function(e) {
1590
+ var key = String.fromCharCode(e.which);
1591
+ this.search.val(key);
1592
+ this.open();
1593
+ }));
1594
+
1595
+ this.setPlaceholder();
1596
+
1597
+ this.search.bind("focus", this.bind(function() {
1598
+ this.container.addClass("select2-container-active");
1599
+ }));
1600
+ },
1601
+
1602
+ // single
1603
+ clear: function() {
1604
+ this.opts.element.val("");
1605
+ this.selection.find("span").empty();
1606
+ this.selection.removeData("select2-data");
1607
+ this.setPlaceholder();
1608
+ },
1609
+
1610
+ /**
1611
+ * Sets selection based on source element's value
1612
+ */
1613
+ // single
1614
+ initSelection: function () {
1615
+ var selected;
1616
+ if (this.opts.element.val() === "" && this.opts.element.text() === "") {
1617
+ this.close();
1618
+ this.setPlaceholder();
1619
+ } else {
1620
+ var self = this;
1621
+ this.opts.initSelection.call(null, this.opts.element, function(selected){
1622
+ if (selected !== undefined && selected !== null) {
1623
+ self.updateSelection(selected);
1624
+ self.close();
1625
+ self.setPlaceholder();
1626
+ }
1627
+ });
1628
+ }
1629
+ },
1630
+
1631
+ // single
1632
+ prepareOpts: function () {
1633
+ var opts = this.parent.prepareOpts.apply(this, arguments);
1634
+
1635
+ if (opts.element.get(0).tagName.toLowerCase() === "select") {
1636
+ // install the selection initializer
1637
+ opts.initSelection = function (element, callback) {
1638
+ var selected = element.find(":selected");
1639
+ // a single select box always has a value, no need to null check 'selected'
1640
+ if ($.isFunction(callback))
1641
+ callback({id: selected.attr("value"), text: selected.text(), element:selected});
1642
+ };
1643
+ }
1644
+
1645
+ return opts;
1646
+ },
1647
+
1648
+ // single
1649
+ setPlaceholder: function () {
1650
+ var placeholder = this.getPlaceholder();
1651
+
1652
+ if (this.opts.element.val() === "" && placeholder !== undefined) {
1653
+
1654
+ // check for a first blank option if attached to a select
1655
+ if (this.select && this.select.find("option:first").text() !== "") return;
1656
+
1657
+ this.selection.find("span").html(this.opts.escapeMarkup(placeholder));
1658
+
1659
+ this.selection.addClass("select2-default");
1660
+
1661
+ this.selection.find("abbr").hide();
1662
+ }
1663
+ },
1664
+
1665
+ // single
1666
+ postprocessResults: function (data, initial) {
1667
+ var selected = 0, self = this, showSearchInput = true;
1668
+
1669
+ // find the selected element in the result list
1670
+
1671
+ this.results.find(".select2-result-selectable").each2(function (i, elm) {
1672
+ if (equal(self.id(elm.data("select2-data")), self.opts.element.val())) {
1673
+ selected = i;
1674
+ return false;
1675
+ }
1676
+ });
1677
+
1678
+ // and highlight it
1679
+
1680
+ this.highlight(selected);
1681
+
1682
+ // hide the search box if this is the first we got the results and there are a few of them
1683
+
1684
+ if (initial === true) {
1685
+ showSearchInput = this.showSearchInput = countResults(data.results) >= this.opts.minimumResultsForSearch;
1686
+ this.dropdown.find(".select2-search")[showSearchInput ? "removeClass" : "addClass"]("select2-search-hidden");
1687
+
1688
+ //add "select2-with-searchbox" to the container if search box is shown
1689
+ $(this.dropdown, this.container)[showSearchInput ? "addClass" : "removeClass"]("select2-with-searchbox");
1690
+ }
1691
+
1692
+ },
1693
+
1694
+ // single
1695
+ onSelect: function (data) {
1696
+ var old = this.opts.element.val();
1697
+
1698
+ this.opts.element.val(this.id(data));
1699
+ this.updateSelection(data);
1700
+ this.close();
1701
+ this.selection.focus();
1702
+
1703
+ if (!equal(old, this.id(data))) { this.triggerChange(); }
1704
+ },
1705
+
1706
+ // single
1707
+ updateSelection: function (data) {
1708
+
1709
+ var container=this.selection.find("span"), formatted;
1710
+
1711
+ this.selection.data("select2-data", data);
1712
+
1713
+ container.empty();
1714
+ formatted=this.opts.formatSelection(data, container);
1715
+ if (formatted !== undefined) {
1716
+ container.append(this.opts.escapeMarkup(formatted));
1717
+ }
1718
+
1719
+ this.selection.removeClass("select2-default");
1720
+
1721
+ if (this.opts.allowClear && this.getPlaceholder() !== undefined) {
1722
+ this.selection.find("abbr").show();
1723
+ }
1724
+ },
1725
+
1726
+ // single
1727
+ val: function () {
1728
+ var val, data = null, self = this;
1729
+
1730
+ if (arguments.length === 0) {
1731
+ return this.opts.element.val();
1732
+ }
1733
+
1734
+ val = arguments[0];
1735
+
1736
+ if (this.select) {
1737
+ this.select
1738
+ .val(val)
1739
+ .find(":selected").each2(function (i, elm) {
1740
+ data = {id: elm.attr("value"), text: elm.text()};
1741
+ return false;
1742
+ });
1743
+ this.updateSelection(data);
1744
+ this.setPlaceholder();
1745
+ this.triggerChange();
1746
+ } else {
1747
+ if (this.opts.initSelection === undefined) {
1748
+ throw new Error("cannot call val() if initSelection() is not defined");
1749
+ }
1750
+ // val is an id. !val is true for [undefined,null,'']
1751
+ if (!val) {
1752
+ this.clear();
1753
+ this.triggerChange();
1754
+ return;
1755
+ }
1756
+ this.opts.element.val(val);
1757
+ this.opts.initSelection(this.opts.element, function(data){
1758
+ self.opts.element.val(!data ? "" : self.id(data));
1759
+ self.updateSelection(data);
1760
+ self.setPlaceholder();
1761
+ self.triggerChange();
1762
+ });
1763
+ }
1764
+ },
1765
+
1766
+ // single
1767
+ clearSearch: function () {
1768
+ this.search.val("");
1769
+ },
1770
+
1771
+ // single
1772
+ data: function(value) {
1773
+ var data;
1774
+
1775
+ if (arguments.length === 0) {
1776
+ data = this.selection.data("select2-data");
1777
+ if (data == undefined) data = null;
1778
+ return data;
1779
+ } else {
1780
+ if (!value || value === "") {
1781
+ this.clear();
1782
+ } else {
1783
+ this.opts.element.val(!value ? "" : this.id(value));
1784
+ this.updateSelection(value);
1785
+ }
1786
+ }
1787
+ }
1788
+ });
1789
+
1790
+ MultiSelect2 = clazz(AbstractSelect2, {
1791
+
1792
+ // multi
1793
+ createContainer: function () {
1794
+ var container = $("<div></div>", {
1795
+ "class": "select2-container select2-container-multi"
1796
+ }).html([
1797
+ " <ul class='select2-choices'>",
1798
+ //"<li class='select2-search-choice'><span>California</span><a href="javascript:void(0)" class="select2-search-choice-close"></a></li>" ,
1799
+ " <li class='select2-search-field'>" ,
1800
+ " <input type='text' autocomplete='off' class='select2-input'>" ,
1801
+ " </li>" ,
1802
+ "</ul>" ,
1803
+ "<div class='select2-drop select2-drop-multi' style='display:none;'>" ,
1804
+ " <ul class='select2-results'>" ,
1805
+ " </ul>" ,
1806
+ "</div>"].join(""));
1807
+ return container;
1808
+ },
1809
+
1810
+ // multi
1811
+ prepareOpts: function () {
1812
+ var opts = this.parent.prepareOpts.apply(this, arguments);
1813
+
1814
+ // TODO validate placeholder is a string if specified
1815
+
1816
+ if (opts.element.get(0).tagName.toLowerCase() === "select") {
1817
+ // install sthe selection initializer
1818
+ opts.initSelection = function (element,callback) {
1819
+
1820
+ var data = [];
1821
+ element.find(":selected").each2(function (i, elm) {
1822
+ data.push({id: elm.attr("value"), text: elm.text(), element: elm});
1823
+ });
1824
+
1825
+ if ($.isFunction(callback))
1826
+ callback(data);
1827
+ };
1828
+ }
1829
+
1830
+ return opts;
1831
+ },
1832
+
1833
+ // multi
1834
+ initContainer: function () {
1835
+
1836
+ var selector = ".select2-choices", selection;
1837
+
1838
+ this.searchContainer = this.container.find(".select2-search-field");
1839
+ this.selection = selection = this.container.find(selector);
1840
+
1841
+ this.search.bind("keydown", this.bind(function (e) {
1842
+ if (!this.enabled) return;
1843
+
1844
+ if (e.which === KEY.BACKSPACE && this.search.val() === "") {
1845
+ this.close();
1846
+
1847
+ var choices,
1848
+ selected = selection.find(".select2-search-choice-focus");
1849
+ if (selected.length > 0) {
1850
+ this.unselect(selected.first());
1851
+ this.search.width(10);
1852
+ killEvent(e);
1853
+ return;
1854
+ }
1855
+
1856
+ choices = selection.find(".select2-search-choice:not(.select2-locked)");
1857
+ if (choices.length > 0) {
1858
+ choices.last().addClass("select2-search-choice-focus");
1859
+ }
1860
+ } else {
1861
+ selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus");
1862
+ }
1863
+
1864
+ if (this.opened()) {
1865
+ switch (e.which) {
1866
+ case KEY.UP:
1867
+ case KEY.DOWN:
1868
+ this.moveHighlight((e.which === KEY.UP) ? -1 : 1);
1869
+ killEvent(e);
1870
+ return;
1871
+ case KEY.ENTER:
1872
+ case KEY.TAB:
1873
+ this.selectHighlighted();
1874
+ killEvent(e);
1875
+ return;
1876
+ case KEY.ESC:
1877
+ this.cancel(e);
1878
+ killEvent(e);
1879
+ return;
1880
+ }
1881
+ }
1882
+
1883
+ if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e)
1884
+ || e.which === KEY.BACKSPACE || e.which === KEY.ESC) {
1885
+ return;
1886
+ }
1887
+
1888
+ if (this.opts.openOnEnter === false && e.which === KEY.ENTER) {
1889
+ return;
1890
+ }
1891
+
1892
+ this.open();
1893
+
1894
+ if (e.which === KEY.PAGE_UP || e.which === KEY.PAGE_DOWN) {
1895
+ // prevent the page from scrolling
1896
+ killEvent(e);
1897
+ }
1898
+ }));
1899
+
1900
+ this.search.bind("keyup", this.bind(this.resizeSearch));
1901
+
1902
+ this.search.bind("blur", this.bind(function(e) {
1903
+ this.container.removeClass("select2-container-active");
1904
+ this.search.removeClass("select2-focused");
1905
+ this.clearSearch();
1906
+ e.stopImmediatePropagation();
1907
+ }));
1908
+
1909
+ this.container.delegate(selector, "mousedown", this.bind(function (e) {
1910
+ if (!this.enabled) return;
1911
+ if ($(e.target).closest(".select2-search-choice").length > 0) {
1912
+ // clicked inside a select2 search choice, do not open
1913
+ return;
1914
+ }
1915
+ this.clearPlaceholder();
1916
+ this.open();
1917
+ this.focusSearch();
1918
+ e.preventDefault();
1919
+ }));
1920
+
1921
+ this.container.delegate(selector, "focus", this.bind(function () {
1922
+ if (!this.enabled) return;
1923
+ this.container.addClass("select2-container-active");
1924
+ this.dropdown.addClass("select2-drop-active");
1925
+ this.clearPlaceholder();
1926
+ }));
1927
+
1928
+ // set the placeholder if necessary
1929
+ this.clearSearch();
1930
+ },
1931
+
1932
+ // multi
1933
+ enable: function() {
1934
+ if (this.enabled) return;
1935
+
1936
+ this.parent.enable.apply(this, arguments);
1937
+
1938
+ this.search.removeAttr("disabled");
1939
+ },
1940
+
1941
+ // multi
1942
+ disable: function() {
1943
+ if (!this.enabled) return;
1944
+
1945
+ this.parent.disable.apply(this, arguments);
1946
+
1947
+ this.search.attr("disabled", true);
1948
+ },
1949
+
1950
+ // multi
1951
+ initSelection: function () {
1952
+ var data;
1953
+ if (this.opts.element.val() === "" && this.opts.element.text() === "") {
1954
+ this.updateSelection([]);
1955
+ this.close();
1956
+ // set the placeholder if necessary
1957
+ this.clearSearch();
1958
+ }
1959
+ if (this.select || this.opts.element.val() !== "") {
1960
+ var self = this;
1961
+ this.opts.initSelection.call(null, this.opts.element, function(data){
1962
+ if (data !== undefined && data !== null) {
1963
+ self.updateSelection(data);
1964
+ self.close();
1965
+ // set the placeholder if necessary
1966
+ self.clearSearch();
1967
+ }
1968
+ });
1969
+ }
1970
+ },
1971
+
1972
+ // multi
1973
+ clearSearch: function () {
1974
+ var placeholder = this.getPlaceholder();
1975
+
1976
+ if (placeholder !== undefined && this.getVal().length === 0 && this.search.hasClass("select2-focused") === false) {
1977
+ this.search.val(placeholder).addClass("select2-default");
1978
+ // stretch the search box to full width of the container so as much of the placeholder is visible as possible
1979
+ this.resizeSearch();
1980
+ } else {
1981
+ // we set this to " " instead of "" and later clear it on focus() because there is a firefox bug
1982
+ // that does not properly render the caret when the field starts out blank
1983
+ this.search.val(" ").width(10);
1984
+ }
1985
+ },
1986
+
1987
+ // multi
1988
+ clearPlaceholder: function () {
1989
+ if (this.search.hasClass("select2-default")) {
1990
+ this.search.val("").removeClass("select2-default");
1991
+ } else {
1992
+ // work around for the space character we set to avoid firefox caret bug
1993
+ if (this.search.val() === " ") this.search.val("");
1994
+ }
1995
+ },
1996
+
1997
+ // multi
1998
+ opening: function () {
1999
+ this.parent.opening.apply(this, arguments);
2000
+
2001
+ this.clearPlaceholder();
2002
+ this.resizeSearch();
2003
+ this.focusSearch();
2004
+ },
2005
+
2006
+ // multi
2007
+ close: function () {
2008
+ if (!this.opened()) return;
2009
+ this.parent.close.apply(this, arguments);
2010
+ },
2011
+
2012
+ // multi
2013
+ focus: function () {
2014
+ this.close();
2015
+ this.search.focus();
2016
+ },
2017
+
2018
+ // multi
2019
+ isFocused: function () {
2020
+ return this.search.hasClass("select2-focused");
2021
+ },
2022
+
2023
+ // multi
2024
+ updateSelection: function (data) {
2025
+ var ids = [], filtered = [], self = this;
2026
+
2027
+ // filter out duplicates
2028
+ $(data).each(function () {
2029
+ if (indexOf(self.id(this), ids) < 0) {
2030
+ ids.push(self.id(this));
2031
+ filtered.push(this);
2032
+ }
2033
+ });
2034
+ data = filtered;
2035
+
2036
+ this.selection.find(".select2-search-choice").remove();
2037
+ $(data).each(function () {
2038
+ self.addSelectedChoice(this);
2039
+ });
2040
+ self.postprocessResults();
2041
+ },
2042
+
2043
+ tokenize: function() {
2044
+ var input = this.search.val();
2045
+ input = this.opts.tokenizer(input, this.data(), this.bind(this.onSelect), this.opts);
2046
+ if (input != null && input != undefined) {
2047
+ this.search.val(input);
2048
+ if (input.length > 0) {
2049
+ this.open();
2050
+ }
2051
+ }
2052
+
2053
+ },
2054
+
2055
+ // multi
2056
+ onSelect: function (data) {
2057
+ this.addSelectedChoice(data);
2058
+ if (this.select || !this.opts.closeOnSelect) this.postprocessResults();
2059
+
2060
+ if (this.opts.closeOnSelect) {
2061
+ this.close();
2062
+ this.search.width(10);
2063
+ } else {
2064
+ if (this.countSelectableResults()>0) {
2065
+ this.search.width(10);
2066
+ this.resizeSearch();
2067
+ this.positionDropdown();
2068
+ } else {
2069
+ // if nothing left to select close
2070
+ this.close();
2071
+ }
2072
+ }
2073
+
2074
+ // since its not possible to select an element that has already been
2075
+ // added we do not need to check if this is a new element before firing change
2076
+ this.triggerChange({ added: data });
2077
+
2078
+ this.focusSearch();
2079
+ },
2080
+
2081
+ // multi
2082
+ cancel: function () {
2083
+ this.close();
2084
+ this.focusSearch();
2085
+ },
2086
+
2087
+ addSelectedChoice: function (data) {
2088
+ var enableChoice = !data.locked,
2089
+ enabledItem = $(
2090
+ "<li class='select2-search-choice'>" +
2091
+ " <div></div>" +
2092
+ " <a href='#' onclick='return false;' class='select2-search-choice-close' tabindex='-1'></a>" +
2093
+ "</li>"),
2094
+ disabledItem = $(
2095
+ "<li class='select2-search-choice select2-locked'>" +
2096
+ "<div></div>" +
2097
+ "</li>");
2098
+ var choice = enableChoice ? enabledItem : disabledItem,
2099
+ id = this.id(data),
2100
+ val = this.getVal(),
2101
+ formatted;
2102
+
2103
+ formatted=this.opts.formatSelection(data, choice.find("div"));
2104
+ if (formatted != undefined) {
2105
+ choice.find("div").replaceWith("<div>"+this.opts.escapeMarkup(formatted)+"</div>");
2106
+ }
2107
+
2108
+ if(enableChoice){
2109
+ choice.find(".select2-search-choice-close")
2110
+ .bind("mousedown", killEvent)
2111
+ .bind("click dblclick", this.bind(function (e) {
2112
+ if (!this.enabled) return;
2113
+
2114
+ $(e.target).closest(".select2-search-choice").fadeOut('fast', this.bind(function(){
2115
+ this.unselect($(e.target));
2116
+ this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus");
2117
+ this.close();
2118
+ this.focusSearch();
2119
+ })).dequeue();
2120
+ killEvent(e);
2121
+ })).bind("focus", this.bind(function () {
2122
+ if (!this.enabled) return;
2123
+ this.container.addClass("select2-container-active");
2124
+ this.dropdown.addClass("select2-drop-active");
2125
+ }));
2126
+ }
2127
+
2128
+ choice.data("select2-data", data);
2129
+ choice.insertBefore(this.searchContainer);
2130
+
2131
+ val.push(id);
2132
+ this.setVal(val);
2133
+ },
2134
+
2135
+ // multi
2136
+ unselect: function (selected) {
2137
+ var val = this.getVal(),
2138
+ data,
2139
+ index;
2140
+
2141
+ selected = selected.closest(".select2-search-choice");
2142
+
2143
+ if (selected.length === 0) {
2144
+ throw "Invalid argument: " + selected + ". Must be .select2-search-choice";
2145
+ }
2146
+
2147
+ data = selected.data("select2-data");
2148
+
2149
+ index = indexOf(this.id(data), val);
2150
+
2151
+ if (index >= 0) {
2152
+ val.splice(index, 1);
2153
+ this.setVal(val);
2154
+ if (this.select) this.postprocessResults();
2155
+ }
2156
+ selected.remove();
2157
+ this.triggerChange({ removed: data });
2158
+ },
2159
+
2160
+ // multi
2161
+ postprocessResults: function () {
2162
+ var val = this.getVal(),
2163
+ choices = this.results.find(".select2-result-selectable"),
2164
+ compound = this.results.find(".select2-result-with-children"),
2165
+ self = this;
2166
+
2167
+ choices.each2(function (i, choice) {
2168
+ var id = self.id(choice.data("select2-data"));
2169
+ if (indexOf(id, val) >= 0) {
2170
+ choice.addClass("select2-disabled").removeClass("select2-result-selectable");
2171
+ } else {
2172
+ choice.removeClass("select2-disabled").addClass("select2-result-selectable");
2173
+ }
2174
+ });
2175
+
2176
+ compound.each2(function(i, e) {
2177
+ if (!e.is('.select2-result-selectable') && e.find(".select2-result-selectable").length==0) { // FIX FOR HIRECHAL DATA
2178
+ e.addClass("select2-disabled");
2179
+ } else {
2180
+ e.removeClass("select2-disabled");
2181
+ }
2182
+ });
2183
+
2184
+ if (this.highlight() == -1){
2185
+ choices.each2(function (i, choice) {
2186
+ if (!choice.hasClass("select2-disabled") && choice.hasClass("select2-result-selectable")) {
2187
+ self.highlight(0);
2188
+ return false;
2189
+ }
2190
+ });
2191
+ }
2192
+
2193
+ },
2194
+
2195
+ // multi
2196
+ resizeSearch: function () {
2197
+
2198
+ var minimumWidth, left, maxWidth, containerLeft, searchWidth,
2199
+ sideBorderPadding = getSideBorderPadding(this.search);
2200
+
2201
+ minimumWidth = measureTextWidth(this.search) + 10;
2202
+
2203
+ left = this.search.offset().left;
2204
+
2205
+ maxWidth = this.selection.width();
2206
+ containerLeft = this.selection.offset().left;
2207
+
2208
+ searchWidth = maxWidth - (left - containerLeft) - sideBorderPadding;
2209
+ if (searchWidth < minimumWidth) {
2210
+ searchWidth = maxWidth - sideBorderPadding;
2211
+ }
2212
+
2213
+ if (searchWidth < 40) {
2214
+ searchWidth = maxWidth - sideBorderPadding;
2215
+ }
2216
+
2217
+ if (searchWidth <= 0) {
2218
+ searchWidth = minimumWidth
2219
+ }
2220
+
2221
+ this.search.width(searchWidth);
2222
+ },
2223
+
2224
+ // multi
2225
+ getVal: function () {
2226
+ var val;
2227
+ if (this.select) {
2228
+ val = this.select.val();
2229
+ return val === null ? [] : val;
2230
+ } else {
2231
+ val = this.opts.element.val();
2232
+ return splitVal(val, this.opts.separator);
2233
+ }
2234
+ },
2235
+
2236
+ // multi
2237
+ setVal: function (val) {
2238
+ var unique;
2239
+ if (this.select) {
2240
+ this.select.val(val);
2241
+ } else {
2242
+ unique = [];
2243
+ // filter out duplicates
2244
+ $(val).each(function () {
2245
+ if (indexOf(this, unique) < 0) unique.push(this);
2246
+ });
2247
+ this.opts.element.val(unique.length === 0 ? "" : unique.join(this.opts.separator));
2248
+ }
2249
+ },
2250
+
2251
+ // multi
2252
+ val: function () {
2253
+ var val, data = [], self=this;
2254
+
2255
+ if (arguments.length === 0) {
2256
+ return this.getVal();
2257
+ }
2258
+
2259
+ val = arguments[0];
2260
+
2261
+ if (!val) {
2262
+ this.opts.element.val("");
2263
+ this.updateSelection([]);
2264
+ this.clearSearch();
2265
+ this.triggerChange();
2266
+ return;
2267
+ }
2268
+
2269
+ // val is a list of ids
2270
+ this.setVal(val);
2271
+
2272
+ if (this.select) {
2273
+ this.select.find(":selected").each(function () {
2274
+ data.push({id: $(this).attr("value"), text: $(this).text()});
2275
+ });
2276
+ this.updateSelection(data);
2277
+ this.triggerChange();
2278
+ } else {
2279
+ if (this.opts.initSelection === undefined) {
2280
+ throw new Error("val() cannot be called if initSelection() is not defined")
2281
+ }
2282
+
2283
+ this.opts.initSelection(this.opts.element, function(data){
2284
+ var ids=$(data).map(self.id);
2285
+ self.setVal(ids);
2286
+ self.updateSelection(data);
2287
+ self.clearSearch();
2288
+ self.triggerChange();
2289
+ });
2290
+ }
2291
+ this.clearSearch();
2292
+ },
2293
+
2294
+ // multi
2295
+ onSortStart: function() {
2296
+ if (this.select) {
2297
+ throw new Error("Sorting of elements is not supported when attached to <select>. Attach to <input type='hidden'/> instead.");
2298
+ }
2299
+
2300
+ // collapse search field into 0 width so its container can be collapsed as well
2301
+ this.search.width(0);
2302
+ // hide the container
2303
+ this.searchContainer.hide();
2304
+ },
2305
+
2306
+ // multi
2307
+ onSortEnd:function() {
2308
+
2309
+ var val=[], self=this;
2310
+
2311
+ // show search and move it to the end of the list
2312
+ this.searchContainer.show();
2313
+ // make sure the search container is the last item in the list
2314
+ this.searchContainer.appendTo(this.searchContainer.parent());
2315
+ // since we collapsed the width in dragStarted, we resize it here
2316
+ this.resizeSearch();
2317
+
2318
+ // update selection
2319
+
2320
+ this.selection.find(".select2-search-choice").each(function() {
2321
+ val.push(self.opts.id($(this).data("select2-data")));
2322
+ });
2323
+ this.setVal(val);
2324
+ this.triggerChange();
2325
+ },
2326
+
2327
+ // multi
2328
+ data: function(values) {
2329
+ var self=this, ids;
2330
+ if (arguments.length === 0) {
2331
+ return this.selection
2332
+ .find(".select2-search-choice")
2333
+ .map(function() { return $(this).data("select2-data"); })
2334
+ .get();
2335
+ } else {
2336
+ if (!values) { values = []; }
2337
+ ids = $.map(values, function(e) { return self.opts.id(e)});
2338
+ this.setVal(ids);
2339
+ this.updateSelection(values);
2340
+ this.clearSearch();
2341
+ }
2342
+ }
2343
+ });
2344
+
2345
+ $.fn.select2 = function () {
2346
+
2347
+ var args = Array.prototype.slice.call(arguments, 0),
2348
+ opts,
2349
+ select2,
2350
+ value, multiple, allowedMethods = ["val", "destroy", "opened", "open", "close", "focus", "isFocused", "container", "onSortStart", "onSortEnd", "enable", "disable", "positionDropdown", "data"];
2351
+
2352
+ this.each(function () {
2353
+ if (args.length === 0 || typeof(args[0]) === "object") {
2354
+ opts = args.length === 0 ? {} : $.extend({}, args[0]);
2355
+ opts.element = $(this);
2356
+
2357
+ if (opts.element.get(0).tagName.toLowerCase() === "select") {
2358
+ multiple = opts.element.attr("multiple");
2359
+ } else {
2360
+ multiple = opts.multiple || false;
2361
+ if ("tags" in opts) {opts.multiple = multiple = true;}
2362
+ }
2363
+
2364
+ select2 = multiple ? new MultiSelect2() : new SingleSelect2();
2365
+ select2.init(opts);
2366
+ } else if (typeof(args[0]) === "string") {
2367
+
2368
+ if (indexOf(args[0], allowedMethods) < 0) {
2369
+ throw "Unknown method: " + args[0];
2370
+ }
2371
+
2372
+ value = undefined;
2373
+ select2 = $(this).data("select2");
2374
+ if (select2 === undefined) return;
2375
+ if (args[0] === "container") {
2376
+ value=select2.container;
2377
+ } else {
2378
+ value = select2[args[0]].apply(select2, args.slice(1));
2379
+ }
2380
+ if (value !== undefined) {return false;}
2381
+ } else {
2382
+ throw "Invalid arguments to select2 plugin: " + args;
2383
+ }
2384
+ });
2385
+ return (value === undefined) ? this : value;
2386
+ };
2387
+
2388
+ // plugin defaults, accessible to users
2389
+ $.fn.select2.defaults = {
2390
+ width: "copy",
2391
+ closeOnSelect: true,
2392
+ openOnEnter: true,
2393
+ containerCss: {},
2394
+ dropdownCss: {},
2395
+ containerCssClass: "",
2396
+ dropdownCssClass: "",
2397
+ formatResult: function(result, container, query) {
2398
+ var markup=[];
2399
+ markMatch(result.text, query.term, markup);
2400
+ return markup.join("");
2401
+ },
2402
+ formatSelection: function (data, container) {
2403
+ return data ? data.text : undefined;
2404
+ },
2405
+ formatResultCssClass: function(data) {return undefined;},
2406
+ formatNoMatches: function () { return "No matches found"; },
2407
+ formatInputTooShort: function (input, min) { var n = min - input.length; return "Please enter " + n + " more character" + (n == 1? "" : "s"); },
2408
+ formatSelectionTooBig: function (limit) { return "You can only select " + limit + " item" + (limit == 1 ? "" : "s"); },
2409
+ formatLoadMore: function (pageNumber) { return "Loading more results..."; },
2410
+ formatSearching: function () { return "Searching..."; },
2411
+ minimumResultsForSearch: 0,
2412
+ minimumInputLength: 0,
2413
+ maximumSelectionSize: 0,
2414
+ id: function (e) { return e.id; },
2415
+ matcher: function(term, text) {
2416
+ return text.toUpperCase().indexOf(term.toUpperCase()) >= 0;
2417
+ },
2418
+ separator: ",",
2419
+ tokenSeparators: [],
2420
+ tokenizer: defaultTokenizer,
2421
+ escapeMarkup: function (markup) {
2422
+ if (markup && typeof(markup) === "string") {
2423
+ return markup.replace(/&/g, "&amp;");
2424
+ }
2425
+ return markup;
2426
+ },
2427
+ blurOnChange: false
2428
+ };
2429
+
2430
+ // exports
2431
+ window.Select2 = {
2432
+ query: {
2433
+ ajax: ajax,
2434
+ local: local,
2435
+ tags: tags
2436
+ }, util: {
2437
+ debounce: debounce,
2438
+ markMatch: markMatch
2439
+ }, "class": {
2440
+ "abstract": AbstractSelect2,
2441
+ "single": SingleSelect2,
2442
+ "multi": MultiSelect2
2443
+ }
2444
+ };
2445
+
2446
+ }(jQuery));
functions/admin-page-class/js/select2/select2.png ADDED
Binary file
functions/admin-page-class/js/select2/select2x2.png ADDED
Binary file
functions/admin-page-class/js/time-and-date/jquery-ui-timepicker-addon.js ADDED
@@ -0,0 +1,1299 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * jQuery timepicker addon
3
+ * By: Trent Richardson [http://trentrichardson.com]
4
+ * Version 0.9.8
5
+ * Last Modified: 12/03/2011
6
+ *
7
+ * Copyright 2011 Trent Richardson
8
+ * Dual licensed under the MIT and GPL licenses.
9
+ * http://trentrichardson.com/Impromptu/GPL-LICENSE.txt
10
+ * http://trentrichardson.com/Impromptu/MIT-LICENSE.txt
11
+ *
12
+ * HERES THE CSS:
13
+ * .ui-timepicker-div .ui-widget-header { margin-bottom: 8px; }
14
+ * .ui-timepicker-div dl { text-align: left; }
15
+ * .ui-timepicker-div dl dt { height: 25px; margin-bottom: -25px; }
16
+ * .ui-timepicker-div dl dd { margin: 0 10px 10px 65px; }
17
+ * .ui-timepicker-div td { font-size: 90%; }
18
+ * .ui-tpicker-grid-label { background: none; border: none; margin: 0; padding: 0; }
19
+ */
20
+
21
+ (function($) {
22
+
23
+ $.extend($.ui, { timepicker: { version: "0.9.8" } });
24
+
25
+ /* Time picker manager.
26
+ Use the singleton instance of this class, $.timepicker, to interact with the time picker.
27
+ Settings for (groups of) time pickers are maintained in an instance object,
28
+ allowing multiple different settings on the same page. */
29
+
30
+ function Timepicker() {
31
+ this.regional = []; // Available regional settings, indexed by language code
32
+ this.regional[''] = { // Default regional settings
33
+ currentText: 'Now',
34
+ closeText: 'Done',
35
+ ampm: false,
36
+ amNames: ['AM', 'A'],
37
+ pmNames: ['PM', 'P'],
38
+ timeFormat: 'hh:mm tt',
39
+ timeSuffix: '',
40
+ timeOnlyTitle: 'Choose Time',
41
+ timeText: 'Time',
42
+ hourText: 'Hour',
43
+ minuteText: 'Minute',
44
+ secondText: 'Second',
45
+ millisecText: 'Millisecond',
46
+ timezoneText: 'Time Zone'
47
+ };
48
+ this._defaults = { // Global defaults for all the datetime picker instances
49
+ showButtonPanel: true,
50
+ timeOnly: false,
51
+ showHour: true,
52
+ showMinute: true,
53
+ showSecond: false,
54
+ showMillisec: false,
55
+ showTimezone: false,
56
+ showTime: true,
57
+ stepHour: 1,
58
+ stepMinute: 1,
59
+ stepSecond: 1,
60
+ stepMillisec: 1,
61
+ hour: 0,
62
+ minute: 0,
63
+ second: 0,
64
+ millisec: 0,
65
+ timezone: '+0000',
66
+ hourMin: 0,
67
+ minuteMin: 0,
68
+ secondMin: 0,
69
+ millisecMin: 0,
70
+ hourMax: 23,
71
+ minuteMax: 59,
72
+ secondMax: 59,
73
+ millisecMax: 999,
74
+ minDateTime: null,
75
+ maxDateTime: null,
76
+ onSelect: null,
77
+ hourGrid: 0,
78
+ minuteGrid: 0,
79
+ secondGrid: 0,
80
+ millisecGrid: 0,
81
+ alwaysSetTime: true,
82
+ separator: ' ',
83
+ altFieldTimeOnly: true,
84
+ showTimepicker: true,
85
+ timezoneIso8609: false,
86
+ timezoneList: null,
87
+ addSliderAccess: false,
88
+ sliderAccessArgs: null
89
+ };
90
+ $.extend(this._defaults, this.regional['']);
91
+ }
92
+
93
+ $.extend(Timepicker.prototype, {
94
+ $input: null,
95
+ $altInput: null,
96
+ $timeObj: null,
97
+ inst: null,
98
+ hour_slider: null,
99
+ minute_slider: null,
100
+ second_slider: null,
101
+ millisec_slider: null,
102
+ timezone_select: null,
103
+ hour: 0,
104
+ minute: 0,
105
+ second: 0,
106
+ millisec: 0,
107
+ timezone: '+0000',
108
+ hourMinOriginal: null,
109
+ minuteMinOriginal: null,
110
+ secondMinOriginal: null,
111
+ millisecMinOriginal: null,
112
+ hourMaxOriginal: null,
113
+ minuteMaxOriginal: null,
114
+ secondMaxOriginal: null,
115
+ millisecMaxOriginal: null,
116
+ ampm: '',
117
+ formattedDate: '',
118
+ formattedTime: '',
119
+ formattedDateTime: '',
120
+ timezoneList: null,
121
+
122
+ /* Override the default settings for all instances of the time picker.
123
+ @param settings object - the new settings to use as defaults (anonymous object)
124
+ @return the manager object */
125
+ setDefaults: function(settings) {
126
+ extendRemove(this._defaults, settings || {});
127
+ return this;
128
+ },
129
+
130
+ //########################################################################
131
+ // Create a new Timepicker instance
132
+ //########################################################################
133
+ _newInst: function($input, o) {
134
+ var tp_inst = new Timepicker(),
135
+ inlineSettings = {};
136
+
137
+ for (var attrName in this._defaults) {
138
+ var attrValue = $input.attr('time:' + attrName);
139
+ if (attrValue) {
140
+ try {
141
+ inlineSettings[attrName] = eval(attrValue);
142
+ } catch (err) {
143
+ inlineSettings[attrName] = attrValue;
144
+ }
145
+ }
146
+ }
147
+ tp_inst._defaults = $.extend({}, this._defaults, inlineSettings, o, {
148
+ beforeShow: function(input, dp_inst) {
149
+ if ($.isFunction(o.beforeShow))
150
+ o.beforeShow(input, dp_inst, tp_inst);
151
+ },
152
+ onChangeMonthYear: function(year, month, dp_inst) {
153
+ // Update the time as well : this prevents the time from disappearing from the $input field.
154
+ tp_inst._updateDateTime(dp_inst);
155
+ if ($.isFunction(o.onChangeMonthYear))
156
+ o.onChangeMonthYear.call($input[0], year, month, dp_inst, tp_inst);
157
+ },
158
+ onClose: function(dateText, dp_inst) {
159
+ if (tp_inst.timeDefined === true && $input.val() != '')
160
+ tp_inst._updateDateTime(dp_inst);
161
+ if ($.isFunction(o.onClose))
162
+ o.onClose.call($input[0], dateText, dp_inst, tp_inst);
163
+ },
164
+ timepicker: tp_inst // add timepicker as a property of datepicker: $.datepicker._get(dp_inst, 'timepicker');
165
+ });
166
+ tp_inst.amNames = $.map(tp_inst._defaults.amNames, function(val) { return val.toUpperCase() });
167
+ tp_inst.pmNames = $.map(tp_inst._defaults.pmNames, function(val) { return val.toUpperCase() });
168
+
169
+ if (tp_inst._defaults.timezoneList === null) {
170
+ var timezoneList = [];
171
+ for (var i = -11; i <= 12; i++)
172
+ timezoneList.push((i >= 0 ? '+' : '-') + ('0' + Math.abs(i).toString()).slice(-2) + '00');
173
+ if (tp_inst._defaults.timezoneIso8609)
174
+ timezoneList = $.map(timezoneList, function(val) {
175
+ return val == '+0000' ? 'Z' : (val.substring(0, 3) + ':' + val.substring(3));
176
+ });
177
+ tp_inst._defaults.timezoneList = timezoneList;
178
+ }
179
+
180
+ tp_inst.hour = tp_inst._defaults.hour;
181
+ tp_inst.minute = tp_inst._defaults.minute;
182
+ tp_inst.second = tp_inst._defaults.second;
183
+ tp_inst.millisec = tp_inst._defaults.millisec;
184
+ tp_inst.ampm = '';
185
+ tp_inst.$input = $input;
186
+
187
+ if (o.altField)
188
+ tp_inst.$altInput = $(o.altField)
189
+ .css({ cursor: 'pointer' })
190
+ .focus(function(){ $input.trigger("focus"); });
191
+
192
+ if(tp_inst._defaults.minDate==0 || tp_inst._defaults.minDateTime==0)
193
+ {
194
+ tp_inst._defaults.minDate=new Date();
195
+ }
196
+ if(tp_inst._defaults.maxDate==0 || tp_inst._defaults.maxDateTime==0)
197
+ {
198
+ tp_inst._defaults.maxDate=new Date();
199
+ }
200
+
201
+ // datepicker needs minDate/maxDate, timepicker needs minDateTime/maxDateTime..
202
+ if(tp_inst._defaults.minDate !== undefined && tp_inst._defaults.minDate instanceof Date)
203
+ tp_inst._defaults.minDateTime = new Date(tp_inst._defaults.minDate.getTime());
204
+ if(tp_inst._defaults.minDateTime !== undefined && tp_inst._defaults.minDateTime instanceof Date)
205
+ tp_inst._defaults.minDate = new Date(tp_inst._defaults.minDateTime.getTime());
206
+ if(tp_inst._defaults.maxDate !== undefined && tp_inst._defaults.maxDate instanceof Date)
207
+ tp_inst._defaults.maxDateTime = new Date(tp_inst._defaults.maxDate.getTime());
208
+ if(tp_inst._defaults.maxDateTime !== undefined && tp_inst._defaults.maxDateTime instanceof Date)
209
+ tp_inst._defaults.maxDate = new Date(tp_inst._defaults.maxDateTime.getTime());
210
+ return tp_inst;
211
+ },
212
+
213
+ //########################################################################
214
+ // add our sliders to the calendar
215
+ //########################################################################
216
+ _addTimePicker: function(dp_inst) {
217
+ var currDT = (this.$altInput && this._defaults.altFieldTimeOnly) ?
218
+ this.$input.val() + ' ' + this.$altInput.val() :
219
+ this.$input.val();
220
+
221
+ this.timeDefined = this._parseTime(currDT);
222
+ this._limitMinMaxDateTime(dp_inst, false);
223
+ this._injectTimePicker();
224
+ },
225
+
226
+ //########################################################################
227
+ // parse the time string from input value or _setTime
228
+ //########################################################################
229
+ _parseTime: function(timeString, withDate) {
230
+ var regstr = this._defaults.timeFormat.toString()
231
+ .replace(/h{1,2}/ig, '(\\d?\\d)')
232
+ .replace(/m{1,2}/ig, '(\\d?\\d)')
233
+ .replace(/s{1,2}/ig, '(\\d?\\d)')
234
+ .replace(/l{1}/ig, '(\\d?\\d?\\d)')
235
+ .replace(/t{1,2}/ig, this._getPatternAmpm())
236
+ .replace(/z{1}/ig, '(z|[-+]\\d\\d:?\\d\\d)?')
237
+ .replace(/\s/g, '\\s?') + this._defaults.timeSuffix + '$',
238
+ order = this._getFormatPositions(),
239
+ ampm = '',
240
+ treg;
241
+
242
+ if (!this.inst) this.inst = $.datepicker._getInst(this.$input[0]);
243
+
244
+ if (withDate || !this._defaults.timeOnly) {
245
+ // the time should come after x number of characters and a space.
246
+ // x = at least the length of text specified by the date format
247
+ var dp_dateFormat = $.datepicker._get(this.inst, 'dateFormat');
248
+ // escape special regex characters in the seperator
249
+ var specials = new RegExp("[.*+?|()\\[\\]{}\\\\]", "g");
250
+ regstr = '.{' + dp_dateFormat.length + ',}' + this._defaults.separator.replace(specials, "\\$&") + regstr;
251
+ }
252
+
253
+ treg = timeString.match(new RegExp(regstr, 'i'));
254
+
255
+ if (treg) {
256
+ if (order.t !== -1) {
257
+ if (treg[order.t] === undefined || treg[order.t].length === 0) {
258
+ ampm = '';
259
+ this.ampm = '';
260
+ } else {
261
+ ampm = $.inArray(treg[order.t].toUpperCase(), this.amNames) !== -1 ? 'AM' : 'PM';
262
+ this.ampm = this._defaults[ampm == 'AM' ? 'amNames' : 'pmNames'][0];
263
+ }
264
+ }
265
+
266
+ if (order.h !== -1) {
267
+ if (ampm == 'AM' && treg[order.h] == '12')
268
+ this.hour = 0; // 12am = 0 hour
269
+ else if (ampm == 'PM' && treg[order.h] != '12')
270
+ this.hour = (parseFloat(treg[order.h]) + 12).toFixed(0); // 12pm = 12 hour, any other pm = hour + 12
271
+ else this.hour = Number(treg[order.h]);
272
+ }
273
+
274
+ if (order.m !== -1) this.minute = Number(treg[order.m]);
275
+ if (order.s !== -1) this.second = Number(treg[order.s]);
276
+ if (order.l !== -1) this.millisec = Number(treg[order.l]);
277
+ if (order.z !== -1 && treg[order.z] !== undefined) {
278
+ var tz = treg[order.z].toUpperCase();
279
+ switch (tz.length) {
280
+ case 1: // Z
281
+ tz = this._defaults.timezoneIso8609 ? 'Z' : '+0000';
282
+ break;
283
+ case 5: // +hhmm
284
+ if (this._defaults.timezoneIso8609)
285
+ tz = tz.substring(1) == '0000'
286
+ ? 'Z'
287
+ : tz.substring(0, 3) + ':' + tz.substring(3);
288
+ break;
289
+ case 6: // +hh:mm
290
+ if (!this._defaults.timezoneIso8609)
291
+ tz = tz == 'Z' || tz.substring(1) == '00:00'
292
+ ? '+0000'
293
+ : tz.replace(/:/, '');
294
+ else if (tz.substring(1) == '00:00')
295
+ tz = 'Z';
296
+ break;
297
+ }
298
+ this.timezone = tz;
299
+ }
300
+
301
+ return true;
302
+
303
+ }
304
+ return false;
305
+ },
306
+
307
+ //########################################################################
308
+ // pattern for standard and localized AM/PM markers
309
+ //########################################################################
310
+ _getPatternAmpm: function() {
311
+ var markers = [];
312
+ o = this._defaults;
313
+ if (o.amNames)
314
+ $.merge(markers, o.amNames);
315
+ if (o.pmNames)
316
+ $.merge(markers, o.pmNames);
317
+ markers = $.map(markers, function(val) { return val.replace(/[.*+?|()\[\]{}\\]/g, '\\$&') });
318
+ return '(' + markers.join('|') + ')?';
319
+ },
320
+
321
+ //########################################################################
322
+ // figure out position of time elements.. cause js cant do named captures
323
+ //########################################################################
324
+ _getFormatPositions: function() {
325
+ var finds = this._defaults.timeFormat.toLowerCase().match(/(h{1,2}|m{1,2}|s{1,2}|l{1}|t{1,2}|z)/g),
326
+ orders = { h: -1, m: -1, s: -1, l: -1, t: -1, z: -1 };
327
+
328
+ if (finds)
329
+ for (var i = 0; i < finds.length; i++)
330
+ if (orders[finds[i].toString().charAt(0)] == -1)
331
+ orders[finds[i].toString().charAt(0)] = i + 1;
332
+
333
+ return orders;
334
+ },
335
+
336
+ //########################################################################
337
+ // generate and inject html for timepicker into ui datepicker
338
+ //########################################################################
339
+ _injectTimePicker: function() {
340
+ var $dp = this.inst.dpDiv,
341
+ o = this._defaults,
342
+ tp_inst = this,
343
+ // Added by Peter Medeiros:
344
+ // - Figure out what the hour/minute/second max should be based on the step values.
345
+ // - Example: if stepMinute is 15, then minMax is 45.
346
+ hourMax = parseInt((o.hourMax - ((o.hourMax - o.hourMin) % o.stepHour)) ,10),
347
+ minMax = parseInt((o.minuteMax - ((o.minuteMax - o.minuteMin) % o.stepMinute)) ,10),
348
+ secMax = parseInt((o.secondMax - ((o.secondMax - o.secondMin) % o.stepSecond)) ,10),
349
+ millisecMax = parseInt((o.millisecMax - ((o.millisecMax - o.millisecMin) % o.stepMillisec)) ,10),
350
+ dp_id = this.inst.id.toString().replace(/([^A-Za-z0-9_])/g, '');
351
+
352
+ // Prevent displaying twice
353
+ //if ($dp.find("div#ui-timepicker-div-"+ dp_id).length === 0) {
354
+ if ($dp.find("div#ui-timepicker-div-"+ dp_id).length === 0 && o.showTimepicker) {
355
+ var noDisplay = ' style="display:none;"',
356
+ html = '<div class="ui-timepicker-div" id="ui-timepicker-div-' + dp_id + '"><dl>' +
357
+ '<dt class="ui_tpicker_time_label" id="ui_tpicker_time_label_' + dp_id + '"' +
358
+ ((o.showTime) ? '' : noDisplay) + '>' + o.timeText + '</dt>' +
359
+ '<dd class="ui_tpicker_time" id="ui_tpicker_time_' + dp_id + '"' +
360
+ ((o.showTime) ? '' : noDisplay) + '></dd>' +
361
+ '<dt class="ui_tpicker_hour_label" id="ui_tpicker_hour_label_' + dp_id + '"' +
362
+ ((o.showHour) ? '' : noDisplay) + '>' + o.hourText + '</dt>',
363
+ hourGridSize = 0,
364
+ minuteGridSize = 0,
365
+ secondGridSize = 0,
366
+ millisecGridSize = 0,
367
+ size;
368
+
369
+ // Hours
370
+ html += '<dd class="ui_tpicker_hour"><div id="ui_tpicker_hour_' + dp_id + '"' +
371
+ ((o.showHour) ? '' : noDisplay) + '></div>';
372
+ if (o.showHour && o.hourGrid > 0) {
373
+ html += '<div style="padding-left: 1px"><table class="ui-tpicker-grid-label"><tr>';
374
+
375
+ for (var h = o.hourMin; h <= hourMax; h += parseInt(o.hourGrid,10)) {
376
+ hourGridSize++;
377
+ var tmph = (o.ampm && h > 12) ? h-12 : h;
378
+ if (tmph < 10) tmph = '0' + tmph;
379
+ if (o.ampm) {
380
+ if (h == 0) tmph = 12 +'a';
381
+ else if (h < 12) tmph += 'a';
382
+ else tmph += 'p';
383
+ }
384
+ html += '<td>' + tmph + '</td>';
385
+ }
386
+
387
+ html += '</tr></table></div>';
388
+ }
389
+ html += '</dd>';
390
+
391
+ // Minutes
392
+ html += '<dt class="ui_tpicker_minute_label" id="ui_tpicker_minute_label_' + dp_id + '"' +
393
+ ((o.showMinute) ? '' : noDisplay) + '>' + o.minuteText + '</dt>'+
394
+ '<dd class="ui_tpicker_minute"><div id="ui_tpicker_minute_' + dp_id + '"' +
395
+ ((o.showMinute) ? '' : noDisplay) + '></div>';
396
+
397
+ if (o.showMinute && o.minuteGrid > 0) {
398
+ html += '<div style="padding-left: 1px"><table class="ui-tpicker-grid-label"><tr>';
399
+
400
+ for (var m = o.minuteMin; m <= minMax; m += parseInt(o.minuteGrid,10)) {
401
+ minuteGridSize++;
402
+ html += '<td>' + ((m < 10) ? '0' : '') + m + '</td>';
403
+ }
404
+
405
+ html += '</tr></table></div>';
406
+ }
407
+ html += '</dd>';
408
+
409
+ // Seconds
410
+ html += '<dt class="ui_tpicker_second_label" id="ui_tpicker_second_label_' + dp_id + '"' +
411
+ ((o.showSecond) ? '' : noDisplay) + '>' + o.secondText + '</dt>'+
412
+ '<dd class="ui_tpicker_second"><div id="ui_tpicker_second_' + dp_id + '"'+
413
+ ((o.showSecond) ? '' : noDisplay) + '></div>';
414
+
415
+ if (o.showSecond && o.secondGrid > 0) {
416
+ html += '<div style="padding-left: 1px"><table><tr>';
417
+
418
+ for (var s = o.secondMin; s <= secMax; s += parseInt(o.secondGrid,10)) {
419
+ secondGridSize++;
420
+ html += '<td>' + ((s < 10) ? '0' : '') + s + '</td>';
421
+ }
422
+
423
+ html += '</tr></table></div>';
424
+ }
425
+ html += '</dd>';
426
+
427
+ // Milliseconds
428
+ html += '<dt class="ui_tpicker_millisec_label" id="ui_tpicker_millisec_label_' + dp_id + '"' +
429
+ ((o.showMillisec) ? '' : noDisplay) + '>' + o.millisecText + '</dt>'+
430
+ '<dd class="ui_tpicker_millisec"><div id="ui_tpicker_millisec_' + dp_id + '"'+
431
+ ((o.showMillisec) ? '' : noDisplay) + '></div>';
432
+
433
+ if (o.showMillisec && o.millisecGrid > 0) {
434
+ html += '<div style="padding-left: 1px"><table><tr>';
435
+
436
+ for (var l = o.millisecMin; l <= millisecMax; l += parseInt(o.millisecGrid,10)) {
437
+ millisecGridSize++;
438
+ html += '<td>' + ((l < 10) ? '0' : '') + l + '</td>';
439
+ }
440
+
441
+ html += '</tr></table></div>';
442
+ }
443
+ html += '</dd>';
444
+
445
+ // Timezone
446
+ html += '<dt class="ui_tpicker_timezone_label" id="ui_tpicker_timezone_label_' + dp_id + '"' +
447
+ ((o.showTimezone) ? '' : noDisplay) + '>' + o.timezoneText + '</dt>';
448
+ html += '<dd class="ui_tpicker_timezone" id="ui_tpicker_timezone_' + dp_id + '"' +
449
+ ((o.showTimezone) ? '' : noDisplay) + '></dd>';
450
+
451
+ html += '</dl></div>';
452
+ $tp = $(html);
453
+
454
+ // if we only want time picker...
455
+ if (o.timeOnly === true) {
456
+ $tp.prepend(
457
+ '<div class="ui-widget-header ui-helper-clearfix ui-corner-all">' +
458
+ '<div class="ui-datepicker-title">' + o.timeOnlyTitle + '</div>' +
459
+ '</div>');
460
+ $dp.find('.ui-datepicker-header, .ui-datepicker-calendar').hide();
461
+ }
462
+
463
+ this.hour_slider = $tp.find('#ui_tpicker_hour_'+ dp_id).slider({
464
+ orientation: "horizontal",
465
+ value: this.hour,
466
+ min: o.hourMin,
467
+ max: hourMax,
468
+ step: o.stepHour,
469
+ slide: function(event, ui) {
470
+ tp_inst.hour_slider.slider( "option", "value", ui.value);
471
+ tp_inst._onTimeChange();
472
+ }
473
+ });
474
+
475
+
476
+ // Updated by Peter Medeiros:
477
+ // - Pass in Event and UI instance into slide function
478
+ this.minute_slider = $tp.find('#ui_tpicker_minute_'+ dp_id).slider({
479
+ orientation: "horizontal",
480
+ value: this.minute,
481
+ min: o.minuteMin,
482
+ max: minMax,
483
+ step: o.stepMinute,
484
+ slide: function(event, ui) {
485
+ tp_inst.minute_slider.slider( "option", "value", ui.value);
486
+ tp_inst._onTimeChange();
487
+ }
488
+ });
489
+
490
+ this.second_slider = $tp.find('#ui_tpicker_second_'+ dp_id).slider({
491
+ orientation: "horizontal",
492
+ value: this.second,
493
+ min: o.secondMin,
494
+ max: secMax,
495
+ step: o.stepSecond,
496
+ slide: function(event, ui) {
497
+ tp_inst.second_slider.slider( "option", "value", ui.value);
498
+ tp_inst._onTimeChange();
499
+ }
500
+ });
501
+
502
+ this.millisec_slider = $tp.find('#ui_tpicker_millisec_'+ dp_id).slider({
503
+ orientation: "horizontal",
504
+ value: this.millisec,
505
+ min: o.millisecMin,
506
+ max: millisecMax,
507
+ step: o.stepMillisec,
508
+ slide: function(event, ui) {
509
+ tp_inst.millisec_slider.slider( "option", "value", ui.value);
510
+ tp_inst._onTimeChange();
511
+ }
512
+ });
513
+
514
+ this.timezone_select = $tp.find('#ui_tpicker_timezone_'+ dp_id).append('<select></select>').find("select");
515
+ $.fn.append.apply(this.timezone_select,
516
+ $.map(o.timezoneList, function(val, idx) {
517
+ return $("<option />")
518
+ .val(typeof val == "object" ? val.value : val)
519
+ .text(typeof val == "object" ? val.label : val);
520
+ })
521
+ );
522
+ this.timezone_select.val((typeof this.timezone != "undefined" && this.timezone != null && this.timezone != "") ? this.timezone : o.timezone);
523
+ this.timezone_select.change(function() {
524
+ tp_inst._onTimeChange();
525
+ });
526
+
527
+ // Add grid functionality
528
+ if (o.showHour && o.hourGrid > 0) {
529
+ size = 100 * hourGridSize * o.hourGrid / (hourMax - o.hourMin);
530
+
531
+ $tp.find(".ui_tpicker_hour table").css({
532
+ width: size + "%",
533
+ marginLeft: (size / (-2 * hourGridSize)) + "%",
534
+ borderCollapse: 'collapse'
535
+ }).find("td").each( function(index) {
536
+ $(this).click(function() {
537
+ var h = $(this).html();
538
+ if(o.ampm) {
539
+ var ap = h.substring(2).toLowerCase(),
540
+ aph = parseInt(h.substring(0,2), 10);
541
+ if (ap == 'a') {
542
+ if (aph == 12) h = 0;
543
+ else h = aph;
544
+ } else if (aph == 12) h = 12;
545
+ else h = aph + 12;
546
+ }
547
+ tp_inst.hour_slider.slider("option", "value", h);
548
+ tp_inst._onTimeChange();
549
+ tp_inst._onSelectHandler();
550
+ }).css({
551
+ cursor: 'pointer',
552
+ width: (100 / hourGridSize) + '%',
553
+ textAlign: 'center',
554
+ overflow: 'hidden'
555
+ });
556
+ });
557
+ }
558
+
559
+ if (o.showMinute && o.minuteGrid > 0) {
560
+ size = 100 * minuteGridSize * o.minuteGrid / (minMax - o.minuteMin);
561
+ $tp.find(".ui_tpicker_minute table").css({
562
+ width: size + "%",
563
+ marginLeft: (size / (-2 * minuteGridSize)) + "%",
564
+ borderCollapse: 'collapse'
565
+ }).find("td").each(function(index) {
566
+ $(this).click(function() {
567
+ tp_inst.minute_slider.slider("option", "value", $(this).html());
568
+ tp_inst._onTimeChange();
569
+ tp_inst._onSelectHandler();
570
+ }).css({
571
+ cursor: 'pointer',
572
+ width: (100 / minuteGridSize) + '%',
573
+ textAlign: 'center',
574
+ overflow: 'hidden'
575
+ });
576
+ });
577
+ }
578
+
579
+ if (o.showSecond && o.secondGrid > 0) {
580
+ $tp.find(".ui_tpicker_second table").css({
581
+ width: size + "%",
582
+ marginLeft: (size / (-2 * secondGridSize)) + "%",
583
+ borderCollapse: 'collapse'
584
+ }).find("td").each(function(index) {
585
+ $(this).click(function() {
586
+ tp_inst.second_slider.slider("option", "value", $(this).html());
587
+ tp_inst._onTimeChange();
588
+ tp_inst._onSelectHandler();
589
+ }).css({
590
+ cursor: 'pointer',
591
+ width: (100 / secondGridSize) + '%',
592
+ textAlign: 'center',
593
+ overflow: 'hidden'
594
+ });
595
+ });
596
+ }
597
+
598
+ if (o.showMillisec && o.millisecGrid > 0) {
599
+ $tp.find(".ui_tpicker_millisec table").css({
600
+ width: size + "%",
601
+ marginLeft: (size / (-2 * millisecGridSize)) + "%",
602
+ borderCollapse: 'collapse'
603
+ }).find("td").each(function(index) {
604
+ $(this).click(function() {
605
+ tp_inst.millisec_slider.slider("option", "value", $(this).html());
606
+ tp_inst._onTimeChange();
607
+ tp_inst._onSelectHandler();
608
+ }).css({
609
+ cursor: 'pointer',
610
+ width: (100 / millisecGridSize) + '%',
611
+ textAlign: 'center',
612
+ overflow: 'hidden'
613
+ });
614
+ });
615
+ }
616
+
617
+ var $buttonPanel = $dp.find('.ui-datepicker-buttonpane');
618
+ if ($buttonPanel.length) $buttonPanel.before($tp);
619
+ else $dp.append($tp);
620
+
621
+ this.$timeObj = $tp.find('#ui_tpicker_time_'+ dp_id);
622
+
623
+ if (this.inst !== null) {
624
+ var timeDefined = this.timeDefined;
625
+ this._onTimeChange();
626
+ this.timeDefined = timeDefined;
627
+ }
628
+
629
+ //Emulate datepicker onSelect behavior. Call on slidestop.
630
+ var onSelectDelegate = function() {
631
+ tp_inst._onSelectHandler();
632
+ };
633
+ this.hour_slider.bind('slidestop',onSelectDelegate);
634
+ this.minute_slider.bind('slidestop',onSelectDelegate);
635
+ this.second_slider.bind('slidestop',onSelectDelegate);
636
+ this.millisec_slider.bind('slidestop',onSelectDelegate);
637
+
638
+ // slideAccess integration: http://trentrichardson.com/2011/11/11/jquery-ui-sliders-and-touch-accessibility/
639
+ if (this._defaults.addSliderAccess){
640
+ var sliderAccessArgs = this._defaults.sliderAccessArgs;
641
+ setTimeout(function(){ // fix for inline mode
642
+ if($tp.find('.ui-slider-access').length == 0){
643
+ $tp.find('.ui-slider:visible').sliderAccess(sliderAccessArgs);
644
+
645
+ // fix any grids since sliders are shorter
646
+ var sliderAccessWidth = $tp.find('.ui-slider-access:eq(0)').outerWidth(true);
647
+ if(sliderAccessWidth){
648
+ $tp.find('table:visible').each(function(){
649
+ var $g = $(this),
650
+ oldWidth = $g.outerWidth(),
651
+ oldMarginLeft = $g.css('marginLeft').toString().replace('%',''),
652
+ newWidth = oldWidth - sliderAccessWidth,
653
+ newMarginLeft = ((oldMarginLeft * newWidth)/oldWidth) + '%';
654
+
655
+ $g.css({ width: newWidth, marginLeft: newMarginLeft });
656
+ });
657
+ }
658
+ }
659
+ },0);
660
+ }
661
+ // end slideAccess integration
662
+
663
+ }
664
+ },
665
+
666
+ //########################################################################
667
+ // This function tries to limit the ability to go outside the
668
+ // min/max date range
669
+ //########################################################################
670
+ _limitMinMaxDateTime: function(dp_inst, adjustSliders){
671
+ var o = this._defaults,
672
+ dp_date = new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay);
673
+
674
+ if(!this._defaults.showTimepicker) return; // No time so nothing to check here
675
+
676
+ if($.datepicker._get(dp_inst, 'minDateTime') !== null && $.datepicker._get(dp_inst, 'minDateTime') !== undefined && dp_date){
677
+ var minDateTime = $.datepicker._get(dp_inst, 'minDateTime'),
678
+ minDateTimeDate = new Date(minDateTime.getFullYear(), minDateTime.getMonth(), minDateTime.getDate(), 0, 0, 0, 0);
679
+
680
+ if(this.hourMinOriginal === null || this.minuteMinOriginal === null || this.secondMinOriginal === null || this.millisecMinOriginal === null){
681
+ this.hourMinOriginal = o.hourMin;
682
+ this.minuteMinOriginal = o.minuteMin;
683
+ this.secondMinOriginal = o.secondMin;
684
+ this.millisecMinOriginal = o.millisecMin;
685
+ }
686
+
687
+ if(dp_inst.settings.timeOnly || minDateTimeDate.getTime() == dp_date.getTime()) {
688
+ this._defaults.hourMin = minDateTime.getHours();
689
+ if (this.hour <= this._defaults.hourMin) {
690
+ this.hour = this._defaults.hourMin;
691
+ this._defaults.minuteMin = minDateTime.getMinutes();
692
+ if (this.minute <= this._defaults.minuteMin) {
693
+ this.minute = this._defaults.minuteMin;
694
+ this._defaults.secondMin = minDateTime.getSeconds();
695
+ } else if (this.second <= this._defaults.secondMin){
696
+ this.second = this._defaults.secondMin;
697
+ this._defaults.millisecMin = minDateTime.getMilliseconds();
698
+ } else {
699
+ if(this.millisec < this._defaults.millisecMin)
700
+ this.millisec = this._defaults.millisecMin;
701
+ this._defaults.millisecMin = this.millisecMinOriginal;
702
+ }
703
+ } else {
704
+ this._defaults.minuteMin = this.minuteMinOriginal;
705
+ this._defaults.secondMin = this.secondMinOriginal;
706
+ this._defaults.millisecMin = this.millisecMinOriginal;
707
+ }
708
+ }else{
709
+ this._defaults.hourMin = this.hourMinOriginal;
710
+ this._defaults.minuteMin = this.minuteMinOriginal;
711
+ this._defaults.secondMin = this.secondMinOriginal;
712
+ this._defaults.millisecMin = this.millisecMinOriginal;
713
+ }
714
+ }
715
+
716
+ if($.datepicker._get(dp_inst, 'maxDateTime') !== null && $.datepicker._get(dp_inst, 'maxDateTime') !== undefined && dp_date){
717
+ var maxDateTime = $.datepicker._get(dp_inst, 'maxDateTime'),
718
+ maxDateTimeDate = new Date(maxDateTime.getFullYear(), maxDateTime.getMonth(), maxDateTime.getDate(), 0, 0, 0, 0);
719
+
720
+ if(this.hourMaxOriginal === null || this.minuteMaxOriginal === null || this.secondMaxOriginal === null){
721
+ this.hourMaxOriginal = o.hourMax;
722
+ this.minuteMaxOriginal = o.minuteMax;
723
+ this.secondMaxOriginal = o.secondMax;
724
+ this.millisecMaxOriginal = o.millisecMax;
725
+ }
726
+
727
+ if(dp_inst.settings.timeOnly || maxDateTimeDate.getTime() == dp_date.getTime()){
728
+ this._defaults.hourMax = maxDateTime.getHours();
729
+ if (this.hour >= this._defaults.hourMax) {
730
+ this.hour = this._defaults.hourMax;
731
+ this._defaults.minuteMax = maxDateTime.getMinutes();
732
+ if (this.minute >= this._defaults.minuteMax) {
733
+ this.minute = this._defaults.minuteMax;
734
+ this._defaults.secondMax = maxDateTime.getSeconds();
735
+ } else if (this.second >= this._defaults.secondMax) {
736
+ this.second = this._defaults.secondMax;
737
+ this._defaults.millisecMax = maxDateTime.getMilliseconds();
738
+ } else {
739
+ if(this.millisec > this._defaults.millisecMax) this.millisec = this._defaults.millisecMax;
740
+ this._defaults.millisecMax = this.millisecMaxOriginal;
741
+ }
742
+ } else {
743
+ this._defaults.minuteMax = this.minuteMaxOriginal;
744
+ this._defaults.secondMax = this.secondMaxOriginal;
745
+ this._defaults.millisecMax = this.millisecMaxOriginal;
746
+ }
747
+ }else{
748
+ this._defaults.hourMax = this.hourMaxOriginal;
749
+ this._defaults.minuteMax = this.minuteMaxOriginal;
750
+ this._defaults.secondMax = this.secondMaxOriginal;
751
+ this._defaults.millisecMax = this.millisecMaxOriginal;
752
+ }
753
+ }
754
+
755
+ if(adjustSliders !== undefined && adjustSliders === true){
756
+ var hourMax = parseInt((this._defaults.hourMax - ((this._defaults.hourMax - this._defaults.hourMin) % this._defaults.stepHour)) ,10),
757
+ minMax = parseInt((this._defaults.minuteMax - ((this._defaults.minuteMax - this._defaults.minuteMin) % this._defaults.stepMinute)) ,10),
758
+ secMax = parseInt((this._defaults.secondMax - ((this._defaults.secondMax - this._defaults.secondMin) % this._defaults.stepSecond)) ,10),
759
+ millisecMax = parseInt((this._defaults.millisecMax - ((this._defaults.millisecMax - this._defaults.millisecMin) % this._defaults.stepMillisec)) ,10);
760
+
761
+ if(this.hour_slider)
762
+ this.hour_slider.slider("option", { min: this._defaults.hourMin, max: hourMax }).slider('value', this.hour);
763
+ if(this.minute_slider)
764
+ this.minute_slider.slider("option", { min: this._defaults.minuteMin, max: minMax }).slider('value', this.minute);
765
+ if(this.second_slider)
766
+ this.second_slider.slider("option", { min: this._defaults.secondMin, max: secMax }).slider('value', this.second);
767
+ if(this.millisec_slider)
768
+ this.millisec_slider.slider("option", { min: this._defaults.millisecMin, max: millisecMax }).slider('value', this.millisec);
769
+ }
770
+
771
+ },
772
+
773
+
774
+ //########################################################################
775
+ // when a slider moves, set the internal time...
776
+ // on time change is also called when the time is updated in the text field
777
+ //########################################################################
778
+ _onTimeChange: function() {
779
+ var hour = (this.hour_slider) ? this.hour_slider.slider('value') : false,
780
+ minute = (this.minute_slider) ? this.minute_slider.slider('value') : false,
781
+ second = (this.second_slider) ? this.second_slider.slider('value') : false,
782
+ millisec = (this.millisec_slider) ? this.millisec_slider.slider('value') : false,
783
+ timezone = (this.timezone_select) ? this.timezone_select.val() : false,
784
+ o = this._defaults;
785
+
786
+ if (typeof(hour) == 'object') hour = false;
787
+ if (typeof(minute) == 'object') minute = false;
788
+ if (typeof(second) == 'object') second = false;
789
+ if (typeof(millisec) == 'object') millisec = false;
790
+ if (typeof(timezone) == 'object') timezone = false;
791
+
792
+ if (hour !== false) hour = parseInt(hour,10);
793
+ if (minute !== false) minute = parseInt(minute,10);
794
+ if (second !== false) second = parseInt(second,10);
795
+ if (millisec !== false) millisec = parseInt(millisec,10);
796
+
797
+ var ampm = o[hour < 12 ? 'amNames' : 'pmNames'][0];
798
+
799
+ // If the update was done in the input field, the input field should not be updated.
800
+ // If the update was done using the sliders, update the input field.
801
+ var hasChanged = (hour != this.hour || minute != this.minute
802
+ || second != this.second || millisec != this.millisec
803
+ || (this.ampm.length > 0
804
+ && (hour < 12) != ($.inArray(this.ampm.toUpperCase(), this.amNames) !== -1))
805
+ || timezone != this.timezone);
806
+
807
+ if (hasChanged) {
808
+
809
+ if (hour !== false)this.hour = hour;
810
+ if (minute !== false) this.minute = minute;
811
+ if (second !== false) this.second = second;
812
+ if (millisec !== false) this.millisec = millisec;
813
+ if (timezone !== false) this.timezone = timezone;
814
+
815
+ if (!this.inst) this.inst = $.datepicker._getInst(this.$input[0]);
816
+
817
+ this._limitMinMaxDateTime(this.inst, true);
818
+ }
819
+ if (o.ampm) this.ampm = ampm;
820
+
821
+ this._formatTime();
822
+ if (this.$timeObj) this.$timeObj.text(this.formattedTime + o.timeSuffix);
823
+ this.timeDefined = true;
824
+ if (hasChanged) this._updateDateTime();
825
+ },
826
+
827
+ //########################################################################
828
+ // call custom onSelect.
829
+ // bind to sliders slidestop, and grid click.
830
+ //########################################################################
831
+ _onSelectHandler: function() {
832
+ var onSelect = this._defaults.onSelect;
833
+ var inputEl = this.$input ? this.$input[0] : null;
834
+ if (onSelect && inputEl) {
835
+ onSelect.apply(inputEl, [this.formattedDateTime, this]);
836
+ }
837
+ },
838
+
839
+ //########################################################################
840
+ // format the time all pretty...
841
+ //########################################################################
842
+ _formatTime: function(time, format, ampm) {
843
+ if (ampm == undefined) ampm = this._defaults.ampm;
844
+ time = time || { hour: this.hour, minute: this.minute, second: this.second, millisec: this.millisec, ampm: this.ampm, timezone: this.timezone };
845
+ var tmptime = (format || this._defaults.timeFormat).toString();
846
+
847
+ var hour = parseInt(time.hour, 10);
848
+ if (ampm) {
849
+ if (!$.inArray(time.ampm.toUpperCase(), this.amNames) !== -1)
850
+ hour = hour % 12;
851
+ if (hour === 0)
852
+ hour = 12;
853
+ }
854
+ tmptime = tmptime.replace(/(?:hh?|mm?|ss?|[tT]{1,2}|[lz])/g, function(match) {
855
+ switch (match.toLowerCase()) {
856
+ case 'hh': return ('0' + hour).slice(-2);
857
+ case 'h': return hour;
858
+ case 'mm': return ('0' + time.minute).slice(-2);
859
+ case 'm': return time.minute;
860
+ case 'ss': return ('0' + time.second).slice(-2);
861
+ case 's': return time.second;
862
+ case 'l': return ('00' + time.millisec).slice(-3);
863
+ case 'z': return time.timezone;
864
+ case 't': case 'tt':
865
+ if (ampm) {
866
+ var _ampm = time.ampm;
867
+ if (match.length == 1)
868
+ _ampm = _ampm.charAt(0);
869
+ return match.charAt(0) == 'T' ? _ampm.toUpperCase() : _ampm.toLowerCase();
870
+ }
871
+ return '';
872
+ }
873
+ });
874
+
875
+ if (arguments.length) return tmptime;
876
+ else this.formattedTime = tmptime;
877
+ },
878
+
879
+ //########################################################################
880
+ // update our input with the new date time..
881
+ //########################################################################
882
+ _updateDateTime: function(dp_inst) {
883
+ dp_inst = this.inst || dp_inst;
884
+ var dt = $.datepicker._daylightSavingAdjust(new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay)),
885
+ dateFmt = $.datepicker._get(dp_inst, 'dateFormat'),
886
+ formatCfg = $.datepicker._getFormatConfig(dp_inst),
887
+ timeAvailable = dt !== null && this.timeDefined;
888
+ this.formattedDate = $.datepicker.formatDate(dateFmt, (dt === null ? new Date() : dt), formatCfg);
889
+ var formattedDateTime = this.formattedDate;
890
+ if (dp_inst.lastVal !== undefined && (dp_inst.lastVal.length > 0 && this.$input.val().length === 0))
891
+ return;
892
+
893
+ if (this._defaults.timeOnly === true) {
894
+ formattedDateTime = this.formattedTime;
895
+ } else if (this._defaults.timeOnly !== true && (this._defaults.alwaysSetTime || timeAvailable)) {
896
+ formattedDateTime += this._defaults.separator + this.formattedTime + this._defaults.timeSuffix;
897
+ }
898
+
899
+ this.formattedDateTime = formattedDateTime;
900
+
901
+ if(!this._defaults.showTimepicker) {
902
+ this.$input.val(this.formattedDate);
903
+ } else if (this.$altInput && this._defaults.altFieldTimeOnly === true) {
904
+ this.$altInput.val(this.formattedTime);
905
+ this.$input.val(this.formattedDate);
906
+ } else if(this.$altInput) {
907
+ this.$altInput.val(formattedDateTime);
908
+ this.$input.val(formattedDateTime);
909
+ } else {
910
+ this.$input.val(formattedDateTime);
911
+ }
912
+
913
+ this.$input.trigger("change");
914
+ }
915
+
916
+ });
917
+
918
+ $.fn.extend({
919
+ //########################################################################
920
+ // shorthand just to use timepicker..
921
+ //########################################################################
922
+ timepicker: function(o) {
923
+ o = o || {};
924
+ var tmp_args = arguments;
925
+
926
+ if (typeof o == 'object') tmp_args[0] = $.extend(o, { timeOnly: true });
927
+
928
+ return $(this).each(function() {
929
+ $.fn.datetimepicker.apply($(this), tmp_args);
930
+ });
931
+ },
932
+
933
+ //########################################################################
934
+ // extend timepicker to datepicker
935
+ //########################################################################
936
+ datetimepicker: function(o) {
937
+ o = o || {};
938
+ var $input = this,
939
+ tmp_args = arguments;
940
+
941
+ if (typeof(o) == 'string'){
942
+ if(o == 'getDate')
943
+ return $.fn.datepicker.apply($(this[0]), tmp_args);
944
+ else
945
+ return this.each(function() {
946
+ var $t = $(this);
947
+ $t.datepicker.apply($t, tmp_args);
948
+ });
949
+ }
950
+ else
951
+ return this.each(function() {
952
+ var $t = $(this);
953
+ $t.datepicker($.timepicker._newInst($t, o)._defaults);
954
+ });
955
+ }
956
+ });
957
+
958
+ //########################################################################
959
+ // the bad hack :/ override datepicker so it doesnt close on select
960
+ // inspired: http://stackoverflow.com/questions/1252512/jquery-datepicker-prevent-closing-picker-when-clicking-a-date/1762378#1762378
961
+ //########################################################################
962
+ $.datepicker._base_selectDate = $.datepicker._selectDate;
963
+ $.datepicker._selectDate = function (id, dateStr) {
964
+ var inst = this._getInst($(id)[0]),
965
+ tp_inst = this._get(inst, 'timepicker');
966
+
967
+ if (tp_inst) {
968
+ tp_inst._limitMinMaxDateTime(inst, true);
969
+ inst.inline = inst.stay_open = true;
970
+ //This way the onSelect handler called from calendarpicker get the full dateTime
971
+ this._base_selectDate(id, dateStr);
972
+ inst.inline = inst.stay_open = false;
973
+ this._notifyChange(inst);
974
+ this._updateDatepicker(inst);
975
+ }
976
+ else this._base_selectDate(id, dateStr);
977
+ };
978
+
979
+ //#############################################################################################
980
+ // second bad hack :/ override datepicker so it triggers an event when changing the input field
981
+ // and does not redraw the datepicker on every selectDate event
982
+ //#############################################################################################
983
+ $.datepicker._base_updateDatepicker = $.datepicker._updateDatepicker;
984
+ $.datepicker._updateDatepicker = function(inst) {
985
+
986
+ // don't popup the datepicker if there is another instance already opened
987
+ var input = inst.input[0];
988
+ if($.datepicker._curInst &&
989
+ $.datepicker._curInst != inst &&
990
+ $.datepicker._datepickerShowing &&
991
+ $.datepicker._lastInput != input) {
992
+ return;
993
+ }
994
+
995
+ if (typeof(inst.stay_open) !== 'boolean' || inst.stay_open === false) {
996
+
997
+ this._base_updateDatepicker(inst);
998
+
999
+ // Reload the time control when changing something in the input text field.
1000
+ var tp_inst = this._get(inst, 'timepicker');
1001
+ if(tp_inst) tp_inst._addTimePicker(inst);
1002
+ }
1003
+ };
1004
+
1005
+ //#######################################################################################
1006
+ // third bad hack :/ override datepicker so it allows spaces and colon in the input field
1007
+ //#######################################################################################
1008
+ $.datepicker._base_doKeyPress = $.datepicker._doKeyPress;
1009
+ $.datepicker._doKeyPress = function(event) {
1010
+ var inst = $.datepicker._getInst(event.target),
1011
+ tp_inst = $.datepicker._get(inst, 'timepicker');
1012
+
1013
+ if (tp_inst) {
1014
+ if ($.datepicker._get(inst, 'constrainInput')) {
1015
+ var ampm = tp_inst._defaults.ampm,
1016
+ dateChars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat')),
1017
+ datetimeChars = tp_inst._defaults.timeFormat.toString()
1018
+ .replace(/[hms]/g, '')
1019
+ .replace(/TT/g, ampm ? 'APM' : '')
1020
+ .replace(/Tt/g, ampm ? 'AaPpMm' : '')
1021
+ .replace(/tT/g, ampm ? 'AaPpMm' : '')
1022
+ .replace(/T/g, ampm ? 'AP' : '')
1023
+ .replace(/tt/g, ampm ? 'apm' : '')
1024
+ .replace(/t/g, ampm ? 'ap' : '') +
1025
+ " " +
1026
+ tp_inst._defaults.separator +
1027
+ tp_inst._defaults.timeSuffix +
1028
+ (tp_inst._defaults.showTimezone ? tp_inst._defaults.timezoneList.join('') : '') +
1029
+ (tp_inst._defaults.amNames.join('')) +
1030
+ (tp_inst._defaults.pmNames.join('')) +
1031
+ dateChars,
1032
+ chr = String.fromCharCode(event.charCode === undefined ? event.keyCode : event.charCode);
1033
+ return event.ctrlKey || (chr < ' ' || !dateChars || datetimeChars.indexOf(chr) > -1);
1034
+ }
1035
+ }
1036
+
1037
+ return $.datepicker._base_doKeyPress(event);
1038
+ };
1039
+
1040
+ //#######################################################################################
1041
+ // Override key up event to sync manual input changes.
1042
+ //#######################################################################################
1043
+ $.datepicker._base_doKeyUp = $.datepicker._doKeyUp;
1044
+ $.datepicker._doKeyUp = function (event) {
1045
+ var inst = $.datepicker._getInst(event.target),
1046
+ tp_inst = $.datepicker._get(inst, 'timepicker');
1047
+
1048
+ if (tp_inst) {
1049
+ if (tp_inst._defaults.timeOnly && (inst.input.val() != inst.lastVal)) {
1050
+ try {
1051
+ $.datepicker._updateDatepicker(inst);
1052
+ }
1053
+ catch (err) {
1054
+ $.datepicker.log(err);
1055
+ }
1056
+ }
1057
+ }
1058
+
1059
+ return $.datepicker._base_doKeyUp(event);
1060
+ };
1061
+
1062
+ //#######################################################################################
1063
+ // override "Today" button to also grab the time.
1064
+ //#######################################################################################
1065
+ $.datepicker._base_gotoToday = $.datepicker._gotoToday;
1066
+ $.datepicker._gotoToday = function(id) {
1067
+ var inst = this._getInst($(id)[0]),
1068
+ $dp = inst.dpDiv;
1069
+ this._base_gotoToday(id);
1070
+ var now = new Date();
1071
+ var tp_inst = this._get(inst, 'timepicker');
1072
+ if (tp_inst._defaults.showTimezone && tp_inst.timezone_select) {
1073
+ var tzoffset = now.getTimezoneOffset(); // If +0100, returns -60
1074
+ var tzsign = tzoffset > 0 ? '-' : '+';
1075
+ tzoffset = Math.abs(tzoffset);
1076
+ var tzmin = tzoffset % 60
1077
+ tzoffset = tzsign + ('0' + (tzoffset - tzmin) / 60).slice(-2) + ('0' + tzmin).slice(-2);
1078
+ if (tp_inst._defaults.timezoneIso8609)
1079
+ tzoffset = tzoffset.substring(0, 3) + ':' + tzoffset.substring(3);
1080
+ tp_inst.timezone_select.val(tzoffset);
1081
+ }
1082
+ this._setTime(inst, now);
1083
+ $( '.ui-datepicker-today', $dp).click();
1084
+ };
1085
+
1086
+ //#######################################################################################
1087
+ // Disable & enable the Time in the datetimepicker
1088
+ //#######################################################################################
1089
+ $.datepicker._disableTimepickerDatepicker = function(target, date, withDate) {
1090
+ var inst = this._getInst(target),
1091
+ tp_inst = this._get(inst, 'timepicker');
1092
+ $(target).datepicker('getDate'); // Init selected[Year|Month|Day]
1093
+ if (tp_inst) {
1094
+ tp_inst._defaults.showTimepicker = false;
1095
+ tp_inst._updateDateTime(inst);
1096
+ }
1097
+ };
1098
+
1099
+ $.datepicker._enableTimepickerDatepicker = function(target, date, withDate) {
1100
+ var inst = this._getInst(target),
1101
+ tp_inst = this._get(inst, 'timepicker');
1102
+ $(target).datepicker('getDate'); // Init selected[Year|Month|Day]
1103
+ if (tp_inst) {
1104
+ tp_inst._defaults.showTimepicker = true;
1105
+ tp_inst._addTimePicker(inst); // Could be disabled on page load
1106
+ tp_inst._updateDateTime(inst);
1107
+ }
1108
+ };
1109
+
1110
+ //#######################################################################################
1111
+ // Create our own set time function
1112
+ //#######################################################################################
1113
+ $.datepicker._setTime = function(inst, date) {
1114
+ var tp_inst = this._get(inst, 'timepicker');
1115
+ if (tp_inst) {
1116
+ var defaults = tp_inst._defaults,
1117
+ // calling _setTime with no date sets time to defaults
1118
+ hour = date ? date.getHours() : defaults.hour,
1119
+ minute = date ? date.getMinutes() : defaults.minute,
1120
+ second = date ? date.getSeconds() : defaults.second,
1121
+ millisec = date ? date.getMilliseconds() : defaults.millisec;
1122
+
1123
+ //check if within min/max times..
1124
+ if ((hour < defaults.hourMin || hour > defaults.hourMax) || (minute < defaults.minuteMin || minute > defaults.minuteMax) || (second < defaults.secondMin || second > defaults.secondMax) || (millisec < defaults.millisecMin || millisec > defaults.millisecMax)) {
1125
+ hour = defaults.hourMin;
1126
+ minute = defaults.minuteMin;
1127
+ second = defaults.secondMin;
1128
+ millisec = defaults.millisecMin;
1129
+ }
1130
+
1131
+ tp_inst.hour = hour;
1132
+ tp_inst.minute = minute;
1133
+ tp_inst.second = second;
1134
+ tp_inst.millisec = millisec;
1135
+
1136
+ if (tp_inst.hour_slider) tp_inst.hour_slider.slider('value', hour);
1137
+ if (tp_inst.minute_slider) tp_inst.minute_slider.slider('value', minute);
1138
+ if (tp_inst.second_slider) tp_inst.second_slider.slider('value', second);
1139
+ if (tp_inst.millisec_slider) tp_inst.millisec_slider.slider('value', millisec);
1140
+
1141
+ tp_inst._onTimeChange();
1142
+ tp_inst._updateDateTime(inst);
1143
+ }
1144
+ };
1145
+
1146
+ //#######################################################################################
1147
+ // Create new public method to set only time, callable as $().datepicker('setTime', date)
1148
+ //#######################################################################################
1149
+ $.datepicker._setTimeDatepicker = function(target, date, withDate) {
1150
+ var inst = this._getInst(target),
1151
+ tp_inst = this._get(inst, 'timepicker');
1152
+
1153
+ if (tp_inst) {
1154
+ this._setDateFromField(inst);
1155
+ var tp_date;
1156
+ if (date) {
1157
+ if (typeof date == "string") {
1158
+ tp_inst._parseTime(date, withDate);
1159
+ tp_date = new Date();
1160
+ tp_date.setHours(tp_inst.hour, tp_inst.minute, tp_inst.second, tp_inst.millisec);
1161
+ }
1162
+ else tp_date = new Date(date.getTime());
1163
+ if (tp_date.toString() == 'Invalid Date') tp_date = undefined;
1164
+ this._setTime(inst, tp_date);
1165
+ }
1166
+ }
1167
+
1168
+ };
1169
+
1170
+ //#######################################################################################
1171
+ // override setDate() to allow setting time too within Date object
1172
+ //#######################################################################################
1173
+ $.datepicker._base_setDateDatepicker = $.datepicker._setDateDatepicker;
1174
+ $.datepicker._setDateDatepicker = function(target, date) {
1175
+ var inst = this._getInst(target),
1176
+ tp_date = (date instanceof Date) ? new Date(date.getTime()) : date;
1177
+
1178
+ this._updateDatepicker(inst);
1179
+ this._base_setDateDatepicker.apply(this, arguments);
1180
+ this._setTimeDatepicker(target, tp_date, true);
1181
+ };
1182
+
1183
+ //#######################################################################################
1184
+ // override getDate() to allow getting time too within Date object
1185
+ //#######################################################################################
1186
+ $.datepicker._base_getDateDatepicker = $.datepicker._getDateDatepicker;
1187
+ $.datepicker._getDateDatepicker = function(target, noDefault) {
1188
+ var inst = this._getInst(target),
1189
+ tp_inst = this._get(inst, 'timepicker');
1190
+
1191
+ if (tp_inst) {
1192
+ this._setDateFromField(inst, noDefault);
1193
+ var date = this._getDate(inst);
1194
+ if (date && tp_inst._parseTime($(target).val(), tp_inst.timeOnly)) date.setHours(tp_inst.hour, tp_inst.minute, tp_inst.second, tp_inst.millisec);
1195
+ return date;
1196
+ }
1197
+ return this._base_getDateDatepicker(target, noDefault);
1198
+ };
1199
+
1200
+ //#######################################################################################
1201
+ // override parseDate() because UI 1.8.14 throws an error about "Extra characters"
1202
+ // An option in datapicker to ignore extra format characters would be nicer.
1203
+ //#######################################################################################
1204
+ $.datepicker._base_parseDate = $.datepicker.parseDate;
1205
+ $.datepicker.parseDate = function(format, value, settings) {
1206
+ var date;
1207
+ try {
1208
+ date = this._base_parseDate(format, value, settings);
1209
+ } catch (err) {
1210
+ // Hack! The error message ends with a colon, a space, and
1211
+ // the "extra" characters. We rely on that instead of
1212
+ // attempting to perfectly reproduce the parsing algorithm.
1213
+ date = this._base_parseDate(format, value.substring(0,value.length-(err.length-err.indexOf(':')-2)), settings);
1214
+ }
1215
+ return date;
1216
+ };
1217
+
1218
+ //#######################################################################################
1219
+ // override formatDate to set date with time to the input
1220
+ //#######################################################################################
1221
+ $.datepicker._base_formatDate=$.datepicker._formatDate;
1222
+ $.datepicker._formatDate = function(inst, day, month, year){
1223
+ var tp_inst = this._get(inst, 'timepicker');
1224
+ if(tp_inst)
1225
+ {
1226
+ if(day)
1227
+ var b = this._base_formatDate(inst, day, month, year);
1228
+ tp_inst._updateDateTime(inst);
1229
+ return tp_inst.$input.val();
1230
+ }
1231
+ return this._base_formatDate(inst);
1232
+ }
1233
+
1234
+ //#######################################################################################
1235
+ // override options setter to add time to maxDate(Time) and minDate(Time). MaxDate
1236
+ //#######################################################################################
1237
+ $.datepicker._base_optionDatepicker = $.datepicker._optionDatepicker;
1238
+ $.datepicker._optionDatepicker = function(target, name, value) {
1239
+ var inst = this._getInst(target),
1240
+ tp_inst = this._get(inst, 'timepicker');
1241
+ if (tp_inst) {
1242
+ var min,max,onselect;
1243
+ if (typeof name == 'string') { // if min/max was set with the string
1244
+ if (name==='minDate' || name==='minDateTime' )
1245
+ min = value;
1246
+ else if (name==='maxDate' || name==='maxDateTime')
1247
+ max = value;
1248
+ else if (name==='onSelect')
1249
+ onselect=value;
1250
+ } else if (typeof name == 'object') { //if min/max was set with the JSON
1251
+ if(name.minDate)
1252
+ min = name.minDate;
1253
+ else if (name.minDateTime)
1254
+ min = name.minDateTime;
1255
+ else if (name.maxDate)
1256
+ max = name.maxDate;
1257
+ else if (name.maxDateTime)
1258
+ max = name.maxDateTime;
1259
+ }
1260
+ if(min){ //if min was set
1261
+ if(min==0)
1262
+ min=new Date();
1263
+ else
1264
+ min= new Date(min);
1265
+
1266
+ tp_inst._defaults.minDate = min;
1267
+ tp_inst._defaults.minDateTime = min;
1268
+ } else if (max){ //if max was set
1269
+ if(max==0)
1270
+ max=new Date();
1271
+ else
1272
+ max= new Date(max);
1273
+ tp_inst._defaults.maxDate = max;
1274
+ tp_inst._defaults.maxDateTime = max;
1275
+ }
1276
+ else if (onselect)
1277
+ tp_inst._defaults.onSelect=onselect;
1278
+ }
1279
+ if (value === undefined)
1280
+ return this._base_optionDatepicker(target, name);
1281
+ return this._base_optionDatepicker(target, name, value);
1282
+ };
1283
+
1284
+ //#######################################################################################
1285
+ // jQuery extend now ignores nulls!
1286
+ //#######################################################################################
1287
+ function extendRemove(target, props) {
1288
+ $.extend(target, props);
1289
+ for (var name in props)
1290
+ if (props[name] === null || props[name] === undefined)
1291
+ target[name] = props[name];
1292
+ return target;
1293
+ }
1294
+
1295
+ $.timepicker = new Timepicker(); // singleton instance
1296
+ $.timepicker.version = "0.9.8";
1297
+
1298
+ })(jQuery);
1299
+
functions/admin-page-class/lang/default.mo ADDED
Binary file
functions/admin-page-class/lang/default.po ADDED
@@ -0,0 +1,317 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: Admin Page Class\n"
4
+ "POT-Creation-Date: 2012-12-26 22:51+0200\n"
5
+ "PO-Revision-Date: 2012-12-26 22:51+0200\n"
6
+ "Last-Translator: BaInternet <admin@bainternet.info>\n"
7
+ "Language-Team: WP-EX\n"
8
+ "MIME-Version: 1.0\n"
9
+ "Content-Type: text/plain; charset=UTF-8\n"
10
+ "Content-Transfer-Encoding: 8bit\n"
11
+ "X-Generator: Poedit 1.5.4\n"
12
+ "X-Poedit-KeywordsList: __;_e\n"
13
+ "X-Poedit-Basepath: C:\\wamp\\www\\dev\\hebtest\\wp-content\\plugins\\Admin-"
14
+ "Page-Class\n"
15
+ "X-Poedit-SearchPath-0: C:\\wamp\\www\\dev\\hebtest\\wp-content\\plugins"
16
+ "\\Admin-Page-Class\n"
17
+
18
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:22
19
+ msgid "Demo Admin Page"
20
+ msgstr ""
21
+
22
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:42
23
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:64
24
+ msgid "Simple Options"
25
+ msgstr ""
26
+
27
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:43
28
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:99
29
+ msgid "Fancy Options"
30
+ msgstr ""
31
+
32
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:44
33
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:132
34
+ msgid "Editor Options"
35
+ msgstr ""
36
+
37
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:45
38
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:159
39
+ msgid "WordPress Options"
40
+ msgstr ""
41
+
42
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:46
43
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:183
44
+ msgid "Advanced Options"
45
+ msgstr ""
46
+
47
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:47
48
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:232
49
+ msgid "Import Export"
50
+ msgstr ""
51
+
52
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:66
53
+ msgid "This is a simple paragraph"
54
+ msgstr ""
55
+
56
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:68
57
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:192
58
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:206
59
+ msgid "My Text "
60
+ msgstr ""
61
+
62
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:70
63
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:193
64
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:207
65
+ msgid "My Textarea "
66
+ msgstr ""
67
+
68
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:72
69
+ msgid "My Checkbox "
70
+ msgstr ""
71
+
72
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:74
73
+ msgid "My select "
74
+ msgstr ""
75
+
76
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:76
77
+ msgid "My Radio Filed"
78
+ msgstr ""
79
+
80
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:101
81
+ msgid "My Typography"
82
+ msgstr ""
83
+
84
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:103
85
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:194
86
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:208
87
+ msgid "My Image "
88
+ msgstr ""
89
+
90
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:105
91
+ msgid "PlUpload Field"
92
+ msgstr ""
93
+
94
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:107
95
+ msgid "My Date "
96
+ msgstr ""
97
+
98
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:109
99
+ msgid "My Time "
100
+ msgstr ""
101
+
102
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:111
103
+ msgid "My Color "
104
+ msgstr ""
105
+
106
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:134
107
+ msgid "My wysiwyg Editor "
108
+ msgstr ""
109
+
110
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:136
111
+ msgid "Code Editor "
112
+ msgstr ""
113
+
114
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:161
115
+ msgid "My Taxonomy Select"
116
+ msgstr ""
117
+
118
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:163
119
+ msgid "My Posts Select"
120
+ msgstr ""
121
+
122
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:165
123
+ msgid "My Roles Select"
124
+ msgstr ""
125
+
126
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:167
127
+ msgid "My Taxonomy Checkboxes"
128
+ msgstr ""
129
+
130
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:169
131
+ msgid "My Posts Checkboxes"
132
+ msgstr ""
133
+
134
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:171
135
+ msgid "My Roles Checkboxes"
136
+ msgstr ""
137
+
138
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:186
139
+ msgid "My Sortable Field"
140
+ msgstr ""
141
+
142
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:200
143
+ msgid "This is a Repeater Block"
144
+ msgstr ""
145
+
146
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:216
147
+ msgid "Enable conditinal fields? "
148
+ msgstr ""
149
+
150
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:217
151
+ msgid ""
152
+ "<small>Turn ON if you want to enable the <strong>conditinal fields</strong>."
153
+ "</small>"
154
+ msgstr ""
155
+
156
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:248
157
+ msgid "My help tab title"
158
+ msgstr ""
159
+
160
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:249
161
+ msgid "This is my Help Tab content"
162
+ msgstr ""
163
+
164
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:253
165
+ msgid "My 2nd help tab title"
166
+ msgstr ""
167
+
168
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:259
169
+ msgid "This is my 2nd Help Tab content from a callback function"
170
+ msgstr ""
171
+
172
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:380
173
+ msgid "Allowed Files"
174
+ msgstr ""
175
+
176
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:615
177
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:617
178
+ msgid "Insert into Post"
179
+ msgstr ""
180
+
181
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:615
182
+ msgid "Use this File"
183
+ msgstr ""
184
+
185
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:617
186
+ msgid "Use this Image"
187
+ msgstr ""
188
+
189
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:649
190
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:744
191
+ msgid "Save Changes"
192
+ msgstr ""
193
+
194
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:656
195
+ msgid "Settings saved."
196
+ msgstr ""
197
+
198
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1119
199
+ msgid "Delete this image"
200
+ msgstr ""
201
+
202
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1119
203
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1822
204
+ msgid "Delete"
205
+ msgstr ""
206
+
207
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1214
208
+ msgid "Cannot delete file. Something's wrong."
209
+ msgstr ""
210
+
211
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1418
212
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1463
213
+ msgid "Remove"
214
+ msgstr ""
215
+
216
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1430
217
+ msgid "Add"
218
+ msgstr ""
219
+
220
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1610
221
+ msgid "Select Files"
222
+ msgstr ""
223
+
224
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1818
225
+ msgid "Uploaded files"
226
+ msgstr ""
227
+
228
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1829
229
+ msgid "Upload new files"
230
+ msgstr ""
231
+
232
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1835
233
+ msgid "Add more files"
234
+ msgstr ""
235
+
236
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1861
237
+ msgid "Delete Image"
238
+ msgstr ""
239
+
240
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1866
241
+ msgid "Upload Image"
242
+ msgstr ""
243
+
244
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1943
245
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1969
246
+ msgid "Select a color"
247
+ msgstr ""
248
+
249
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3177
250
+ msgid "Export"
251
+ msgstr ""
252
+
253
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3178
254
+ msgid ""
255
+ "To export saved settings click the Export button bellow and you will get the "
256
+ "export Code in the box bellow, which you can later use to import."
257
+ msgstr ""
258
+
259
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3180
260
+ msgid "Export Code"
261
+ msgstr ""
262
+
263
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3182
264
+ msgid "Get Export"
265
+ msgstr ""
266
+
267
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3187
268
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3192
269
+ msgid "Import"
270
+ msgstr ""
271
+
272
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3188
273
+ msgid ""
274
+ "To Import saved settings paste the Export output in to the Import Code box "
275
+ "bellow and click Import."
276
+ msgstr ""
277
+
278
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3190
279
+ msgid "Import Code"
280
+ msgstr ""
281
+
282
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3217
283
+ msgid "error in ajax request! (1)"
284
+ msgstr ""
285
+
286
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3227
287
+ msgid "error in ajax request! (2)"
288
+ msgstr ""
289
+
290
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3248
291
+ msgid "error in ajax request! (3)"
292
+ msgstr ""
293
+
294
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3260
295
+ msgid "Setting imported, make sure you "
296
+ msgstr ""
297
+
298
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3260
299
+ msgid "Refresh this page"
300
+ msgstr ""
301
+
302
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3262
303
+ msgid "Could not import settings! (4)"
304
+ msgstr ""
305
+
306
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3283
307
+ msgid "You do not have sufficient permissions to edit templates for this site."
308
+ msgstr ""
309
+
310
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3286
311
+ msgid "Error Downloading file."
312
+ msgstr ""
313
+
314
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3308
315
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3311
316
+ msgid "Download Export"
317
+ msgstr ""
functions/admin-page-class/lang/en_US.mo ADDED
Binary file
functions/admin-page-class/lang/en_US.po ADDED
@@ -0,0 +1,317 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: Admin Page Class\n"
4
+ "POT-Creation-Date: 2012-12-26 22:51+0200\n"
5
+ "PO-Revision-Date: 2012-12-26 22:51+0200\n"
6
+ "Last-Translator: BaInternet <admin@bainternet.info>\n"
7
+ "Language-Team: WP-EX\n"
8
+ "MIME-Version: 1.0\n"
9
+ "Content-Type: text/plain; charset=UTF-8\n"
10
+ "Content-Transfer-Encoding: 8bit\n"
11
+ "X-Generator: Poedit 1.5.4\n"
12
+ "X-Poedit-KeywordsList: __;_e\n"
13
+ "X-Poedit-Basepath: C:\\wamp\\www\\dev\\hebtest\\wp-content\\plugins\\Admin-"
14
+ "Page-Class\n"
15
+ "X-Poedit-SearchPath-0: C:\\wamp\\www\\dev\\hebtest\\wp-content\\plugins"
16
+ "\\Admin-Page-Class\n"
17
+
18
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:22
19
+ msgid "Demo Admin Page"
20
+ msgstr ""
21
+
22
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:42
23
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:64
24
+ msgid "Simple Options"
25
+ msgstr ""
26
+
27
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:43
28
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:99
29
+ msgid "Fancy Options"
30
+ msgstr ""
31
+
32
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:44
33
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:132
34
+ msgid "Editor Options"
35
+ msgstr ""
36
+
37
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:45
38
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:159
39
+ msgid "WordPress Options"
40
+ msgstr ""
41
+
42
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:46
43
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:183
44
+ msgid "Advanced Options"
45
+ msgstr ""
46
+
47
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:47
48
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:232
49
+ msgid "Import Export"
50
+ msgstr ""
51
+
52
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:66
53
+ msgid "This is a simple paragraph"
54
+ msgstr ""
55
+
56
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:68
57
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:192
58
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:206
59
+ msgid "My Text "
60
+ msgstr ""
61
+
62
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:70
63
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:193
64
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:207
65
+ msgid "My Textarea "
66
+ msgstr ""
67
+
68
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:72
69
+ msgid "My Checkbox "
70
+ msgstr ""
71
+
72
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:74
73
+ msgid "My select "
74
+ msgstr ""
75
+
76
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:76
77
+ msgid "My Radio Filed"
78
+ msgstr ""
79
+
80
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:101
81
+ msgid "My Typography"
82
+ msgstr ""
83
+
84
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:103
85
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:194
86
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:208
87
+ msgid "My Image "
88
+ msgstr ""
89
+
90
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:105
91
+ msgid "PlUpload Field"
92
+ msgstr ""
93
+
94
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:107
95
+ msgid "My Date "
96
+ msgstr ""
97
+
98
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:109
99
+ msgid "My Time "
100
+ msgstr ""
101
+
102
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:111
103
+ msgid "My Color "
104
+ msgstr ""
105
+
106
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:134
107
+ msgid "My wysiwyg Editor "
108
+ msgstr ""
109
+
110
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:136
111
+ msgid "Code Editor "
112
+ msgstr ""
113
+
114
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:161
115
+ msgid "My Taxonomy Select"
116
+ msgstr ""
117
+
118
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:163
119
+ msgid "My Posts Select"
120
+ msgstr ""
121
+
122
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:165
123
+ msgid "My Roles Select"
124
+ msgstr ""
125
+
126
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:167
127
+ msgid "My Taxonomy Checkboxes"
128
+ msgstr ""
129
+
130
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:169
131
+ msgid "My Posts Checkboxes"
132
+ msgstr ""
133
+
134
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:171
135
+ msgid "My Roles Checkboxes"
136
+ msgstr ""
137
+
138
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:186
139
+ msgid "My Sortable Field"
140
+ msgstr ""
141
+
142
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:200
143
+ msgid "This is a Repeater Block"
144
+ msgstr ""
145
+
146
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:216
147
+ msgid "Enable conditinal fields? "
148
+ msgstr ""
149
+
150
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:217
151
+ msgid ""
152
+ "<small>Turn ON if you want to enable the <strong>conditinal fields</strong>."
153
+ "</small>"
154
+ msgstr ""
155
+
156
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:248
157
+ msgid "My help tab title"
158
+ msgstr ""
159
+
160
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:249
161
+ msgid "This is my Help Tab content"
162
+ msgstr ""
163
+
164
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:253
165
+ msgid "My 2nd help tab title"
166
+ msgstr ""
167
+
168
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:259
169
+ msgid "This is my 2nd Help Tab content from a callback function"
170
+ msgstr ""
171
+
172
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:380
173
+ msgid "Allowed Files"
174
+ msgstr ""
175
+
176
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:615
177
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:617
178
+ msgid "Insert into Post"
179
+ msgstr ""
180
+
181
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:615
182
+ msgid "Use this File"
183
+ msgstr ""
184
+
185
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:617
186
+ msgid "Use this Image"
187
+ msgstr ""
188
+
189
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:649
190
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:744
191
+ msgid "Save Changes"
192
+ msgstr ""
193
+
194
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:656
195
+ msgid "Settings saved."
196
+ msgstr ""
197
+
198
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1119
199
+ msgid "Delete this image"
200
+ msgstr ""
201
+
202
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1119
203
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1822
204
+ msgid "Delete"
205
+ msgstr ""
206
+
207
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1214
208
+ msgid "Cannot delete file. Something's wrong."
209
+ msgstr ""
210
+
211
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1418
212
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1463
213
+ msgid "Remove"
214
+ msgstr ""
215
+
216
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1430
217
+ msgid "Add"
218
+ msgstr ""
219
+
220
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1610
221
+ msgid "Select Files"
222
+ msgstr ""
223
+
224
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1818
225
+ msgid "Uploaded files"
226
+ msgstr ""
227
+
228
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1829
229
+ msgid "Upload new files"
230
+ msgstr ""
231
+
232
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1835
233
+ msgid "Add more files"
234
+ msgstr ""
235
+
236
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1861
237
+ msgid "Delete Image"
238
+ msgstr ""
239
+
240
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1866
241
+ msgid "Upload Image"
242
+ msgstr ""
243
+
244
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1943
245
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1969
246
+ msgid "Select a color"
247
+ msgstr ""
248
+
249
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3177
250
+ msgid "Export"
251
+ msgstr ""
252
+
253
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3178
254
+ msgid ""
255
+ "To export saved settings click the Export button bellow and you will get the "
256
+ "export Code in the box bellow, which you can later use to import."
257
+ msgstr ""
258
+
259
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3180
260
+ msgid "Export Code"
261
+ msgstr ""
262
+
263
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3182
264
+ msgid "Get Export"
265
+ msgstr ""
266
+
267
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3187
268
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3192
269
+ msgid "Import"
270
+ msgstr ""
271
+
272
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3188
273
+ msgid ""
274
+ "To Import saved settings paste the Export output in to the Import Code box "
275
+ "bellow and click Import."
276
+ msgstr ""
277
+
278
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3190
279
+ msgid "Import Code"
280
+ msgstr ""
281
+
282
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3217
283
+ msgid "error in ajax request! (1)"
284
+ msgstr ""
285
+
286
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3227
287
+ msgid "error in ajax request! (2)"
288
+ msgstr ""
289
+
290
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3248
291
+ msgid "error in ajax request! (3)"
292
+ msgstr ""
293
+
294
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3260
295
+ msgid "Setting imported, make sure you "
296
+ msgstr ""
297
+
298
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3260
299
+ msgid "Refresh this page"
300
+ msgstr ""
301
+
302
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3262
303
+ msgid "Could not import settings! (4)"
304
+ msgstr ""
305
+
306
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3283
307
+ msgid "You do not have sufficient permissions to edit templates for this site."
308
+ msgstr ""
309
+
310
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3286
311
+ msgid "Error Downloading file."
312
+ msgstr ""
313
+
314
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3308
315
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3311
316
+ msgid "Download Export"
317
+ msgstr ""
functions/admin-page-class/lang/es_ES.mo ADDED
Binary file
functions/admin-page-class/lang/es_ES.po ADDED
@@ -0,0 +1,326 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: Admin Page Class\n"
4
+ "POT-Creation-Date: 2012-12-26 22:52+0200\n"
5
+ "PO-Revision-Date: 2012-12-26 22:52+0200\n"
6
+ "Last-Translator: BaInternet <admin@bainternet.info>\n"
7
+ "Language-Team: WP-EX\n"
8
+ "MIME-Version: 1.0\n"
9
+ "Content-Type: text/plain; charset=UTF-8\n"
10
+ "Content-Transfer-Encoding: 8bit\n"
11
+ "X-Generator: Poedit 1.5.4\n"
12
+ "X-Poedit-KeywordsList: __;_e\n"
13
+ "X-Poedit-Basepath: C:\\wamp\\www\\dev\\hebtest\\wp-content\\plugins\\Admin-"
14
+ "Page-Class\n"
15
+ "X-Poedit-SearchPath-0: C:\\wamp\\www\\dev\\hebtest\\wp-content\\plugins"
16
+ "\\Admin-Page-Class\n"
17
+
18
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:22
19
+ msgid "Demo Admin Page"
20
+ msgstr ""
21
+
22
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:42
23
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:64
24
+ msgid "Simple Options"
25
+ msgstr ""
26
+
27
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:43
28
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:99
29
+ msgid "Fancy Options"
30
+ msgstr ""
31
+
32
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:44
33
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:132
34
+ msgid "Editor Options"
35
+ msgstr ""
36
+
37
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:45
38
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:159
39
+ msgid "WordPress Options"
40
+ msgstr ""
41
+
42
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:46
43
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:183
44
+ msgid "Advanced Options"
45
+ msgstr ""
46
+
47
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:47
48
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:232
49
+ #, fuzzy
50
+ msgid "Import Export"
51
+ msgstr "Generar código"
52
+
53
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:66
54
+ msgid "This is a simple paragraph"
55
+ msgstr ""
56
+
57
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:68
58
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:192
59
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:206
60
+ msgid "My Text "
61
+ msgstr ""
62
+
63
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:70
64
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:193
65
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:207
66
+ msgid "My Textarea "
67
+ msgstr ""
68
+
69
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:72
70
+ msgid "My Checkbox "
71
+ msgstr ""
72
+
73
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:74
74
+ msgid "My select "
75
+ msgstr ""
76
+
77
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:76
78
+ msgid "My Radio Filed"
79
+ msgstr ""
80
+
81
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:101
82
+ msgid "My Typography"
83
+ msgstr ""
84
+
85
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:103
86
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:194
87
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:208
88
+ msgid "My Image "
89
+ msgstr ""
90
+
91
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:105
92
+ #, fuzzy
93
+ msgid "PlUpload Field"
94
+ msgstr "Archivos guardados"
95
+
96
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:107
97
+ msgid "My Date "
98
+ msgstr ""
99
+
100
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:109
101
+ msgid "My Time "
102
+ msgstr ""
103
+
104
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:111
105
+ msgid "My Color "
106
+ msgstr ""
107
+
108
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:134
109
+ msgid "My wysiwyg Editor "
110
+ msgstr ""
111
+
112
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:136
113
+ msgid "Code Editor "
114
+ msgstr ""
115
+
116
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:161
117
+ msgid "My Taxonomy Select"
118
+ msgstr ""
119
+
120
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:163
121
+ msgid "My Posts Select"
122
+ msgstr ""
123
+
124
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:165
125
+ msgid "My Roles Select"
126
+ msgstr ""
127
+
128
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:167
129
+ msgid "My Taxonomy Checkboxes"
130
+ msgstr ""
131
+
132
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:169
133
+ msgid "My Posts Checkboxes"
134
+ msgstr ""
135
+
136
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:171
137
+ msgid "My Roles Checkboxes"
138
+ msgstr ""
139
+
140
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:186
141
+ msgid "My Sortable Field"
142
+ msgstr ""
143
+
144
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:200
145
+ msgid "This is a Repeater Block"
146
+ msgstr ""
147
+
148
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:216
149
+ msgid "Enable conditinal fields? "
150
+ msgstr ""
151
+
152
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:217
153
+ msgid ""
154
+ "<small>Turn ON if you want to enable the <strong>conditinal fields</strong>."
155
+ "</small>"
156
+ msgstr ""
157
+
158
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:248
159
+ msgid "My help tab title"
160
+ msgstr ""
161
+
162
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:249
163
+ msgid "This is my Help Tab content"
164
+ msgstr ""
165
+
166
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:253
167
+ msgid "My 2nd help tab title"
168
+ msgstr ""
169
+
170
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:259
171
+ msgid "This is my 2nd Help Tab content from a callback function"
172
+ msgstr ""
173
+
174
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:380
175
+ msgid "Allowed Files"
176
+ msgstr "Archivos permitidos"
177
+
178
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:615
179
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:617
180
+ msgid "Insert into Post"
181
+ msgstr "Insertar en la Entrada"
182
+
183
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:615
184
+ msgid "Use this File"
185
+ msgstr "Usar este archivo"
186
+
187
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:617
188
+ msgid "Use this Image"
189
+ msgstr "Usar esta imagen"
190
+
191
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:649
192
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:744
193
+ msgid "Save Changes"
194
+ msgstr "Actualizar cambios"
195
+
196
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:656
197
+ msgid "Settings saved."
198
+ msgstr "Ajustes guardados."
199
+
200
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1119
201
+ msgid "Delete this image"
202
+ msgstr "Borrar esta imagem"
203
+
204
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1119
205
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1822
206
+ msgid "Delete"
207
+ msgstr "Borrar"
208
+
209
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1214
210
+ msgid "Cannot delete file. Something's wrong."
211
+ msgstr "Algo ha fallado al borrar el archivo."
212
+
213
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1418
214
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1463
215
+ msgid "Remove"
216
+ msgstr "Eliminar"
217
+
218
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1430
219
+ msgid "Add"
220
+ msgstr "Añadir"
221
+
222
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1610
223
+ msgid "Select Files"
224
+ msgstr "Seleccionar archivos"
225
+
226
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1818
227
+ msgid "Uploaded files"
228
+ msgstr "Archivos guardados"
229
+
230
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1829
231
+ msgid "Upload new files"
232
+ msgstr "Subir nuevos archivos"
233
+
234
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1835
235
+ msgid "Add more files"
236
+ msgstr "Añadir más archivos"
237
+
238
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1861
239
+ #, fuzzy
240
+ msgid "Delete Image"
241
+ msgstr "Borrar esta imagem"
242
+
243
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1866
244
+ #, fuzzy
245
+ msgid "Upload Image"
246
+ msgstr "Archivos guardados"
247
+
248
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1943
249
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1969
250
+ msgid "Select a color"
251
+ msgstr "Seleccionar un color"
252
+
253
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3177
254
+ msgid "Export"
255
+ msgstr "Exportar"
256
+
257
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3178
258
+ msgid ""
259
+ "To export saved settings click the Export button bellow and you will get the "
260
+ "export Code in the box bellow, which you can later use to import."
261
+ msgstr ""
262
+ "Para exportar los ajustes guardados, haz clic en el botón Exportar abajo y "
263
+ "tendras el código de exportación en la caja de texto, que puedes usar más "
264
+ "tarde para importar."
265
+
266
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3180
267
+ msgid "Export Code"
268
+ msgstr "Exportar código"
269
+
270
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3182
271
+ msgid "Get Export"
272
+ msgstr "Generar código"
273
+
274
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3187
275
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3192
276
+ msgid "Import"
277
+ msgstr "Importar"
278
+
279
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3188
280
+ msgid ""
281
+ "To Import saved settings paste the Export output in to the Import Code box "
282
+ "bellow and click Import."
283
+ msgstr ""
284
+ "Para importar los ajustes guardados, pega el código de Exportación en la "
285
+ "caja abajo y haz clic en Importar ."
286
+
287
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3190
288
+ msgid "Import Code"
289
+ msgstr "Importar código"
290
+
291
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3217
292
+ msgid "error in ajax request! (1)"
293
+ msgstr "Error en la solicitud de Ajax! (1)"
294
+
295
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3227
296
+ msgid "error in ajax request! (2)"
297
+ msgstr "Error en la solicitud de Ajax! (2)"
298
+
299
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3248
300
+ msgid "error in ajax request! (3)"
301
+ msgstr "Error en la solicitud de Ajax! (3)"
302
+
303
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3260
304
+ msgid "Setting imported, make sure you "
305
+ msgstr "Ajustes importados, asegurate"
306
+
307
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3260
308
+ msgid "Refresh this page"
309
+ msgstr "de actualizar esta página"
310
+
311
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3262
312
+ msgid "Could not import settings! (4)"
313
+ msgstr "No ha sido posible importar los ajustes! (4)"
314
+
315
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3283
316
+ msgid "You do not have sufficient permissions to edit templates for this site."
317
+ msgstr "No tienes suficientes permisos para editar plantillas en este sitio."
318
+
319
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3286
320
+ msgid "Error Downloading file."
321
+ msgstr "Error al descargar el archivo."
322
+
323
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3308
324
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3311
325
+ msgid "Download Export"
326
+ msgstr ""
functions/admin-page-class/lang/he_IL.mo ADDED
Binary file
functions/admin-page-class/lang/he_IL.po ADDED
@@ -0,0 +1,318 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: Admin Page Class\n"
4
+ "POT-Creation-Date: 2012-12-26 22:47+0200\n"
5
+ "PO-Revision-Date: 2012-12-26 22:47+0200\n"
6
+ "Last-Translator: BaInternet <admin@bainternet.info>\n"
7
+ "Language-Team: WP-EX\n"
8
+ "MIME-Version: 1.0\n"
9
+ "Content-Type: text/plain; charset=UTF-8\n"
10
+ "Content-Transfer-Encoding: 8bit\n"
11
+ "X-Generator: Poedit 1.5.4\n"
12
+ "X-Poedit-KeywordsList: __;_e\n"
13
+ "X-Poedit-Basepath: C:\\wamp\\www\\dev\\hebtest\\wp-content\\plugins\\Admin-"
14
+ "Page-Class\n"
15
+ "X-Poedit-SearchPath-0: C:\\wamp\\www\\dev\\hebtest\\wp-content\\plugins"
16
+ "\\Admin-Page-Class\n"
17
+
18
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:22
19
+ msgid "Demo Admin Page"
20
+ msgstr "עמוד ניהול לדוגמא"
21
+
22
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:42
23
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:64
24
+ msgid "Simple Options"
25
+ msgstr "שדות פשוטים"
26
+
27
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:43
28
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:99
29
+ msgid "Fancy Options"
30
+ msgstr "שדות מגונדרים"
31
+
32
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:44
33
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:132
34
+ msgid "Editor Options"
35
+ msgstr "שדות עורכים"
36
+
37
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:45
38
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:159
39
+ msgid "WordPress Options"
40
+ msgstr "שדות של וורדפרס"
41
+
42
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:46
43
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:183
44
+ msgid "Advanced Options"
45
+ msgstr "שדות מתקדמים"
46
+
47
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:47
48
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:232
49
+ msgid "Import Export"
50
+ msgstr "יבאו יצאו"
51
+
52
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:66
53
+ msgid "This is a simple paragraph"
54
+ msgstr "זאת פיסקה פשוטה"
55
+
56
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:68
57
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:192
58
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:206
59
+ msgid "My Text "
60
+ msgstr "שדה טקסט"
61
+
62
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:70
63
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:193
64
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:207
65
+ msgid "My Textarea "
66
+ msgstr "שגה טקסט גדול"
67
+
68
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:72
69
+ msgid "My Checkbox "
70
+ msgstr "שדה סימון"
71
+
72
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:74
73
+ msgid "My select "
74
+ msgstr "שדה בחירה"
75
+
76
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:76
77
+ msgid "My Radio Filed"
78
+ msgstr "שדה ברירה"
79
+
80
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:101
81
+ msgid "My Typography"
82
+ msgstr "שדה טיפוגרפיה"
83
+
84
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:103
85
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:194
86
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:208
87
+ msgid "My Image "
88
+ msgstr "שדה תמונה"
89
+
90
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:105
91
+ msgid "PlUpload Field"
92
+ msgstr "שדה תמונות מתקדם"
93
+
94
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:107
95
+ msgid "My Date "
96
+ msgstr "שדה תאריך"
97
+
98
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:109
99
+ msgid "My Time "
100
+ msgstr "שדה זמן"
101
+
102
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:111
103
+ msgid "My Color "
104
+ msgstr "שדה צבע"
105
+
106
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:134
107
+ msgid "My wysiwyg Editor "
108
+ msgstr "שדה עורך תוכן"
109
+
110
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:136
111
+ msgid "Code Editor "
112
+ msgstr "שדה עורך קוד"
113
+
114
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:161
115
+ msgid "My Taxonomy Select"
116
+ msgstr "שדה בחירת טקסונומיה"
117
+
118
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:163
119
+ msgid "My Posts Select"
120
+ msgstr "שדה פוסטים"
121
+
122
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:165
123
+ msgid "My Roles Select"
124
+ msgstr "שדה בחירת תפקידים"
125
+
126
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:167
127
+ msgid "My Taxonomy Checkboxes"
128
+ msgstr "שדה סימון טקסונומיה"
129
+
130
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:169
131
+ msgid "My Posts Checkboxes"
132
+ msgstr "שדה סימון פוסטים"
133
+
134
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:171
135
+ msgid "My Roles Checkboxes"
136
+ msgstr "שדה סימון תפקידים"
137
+
138
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:186
139
+ msgid "My Sortable Field"
140
+ msgstr "שדה מיון"
141
+
142
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:200
143
+ msgid "This is a Repeater Block"
144
+ msgstr "שדות חוזרים"
145
+
146
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:216
147
+ msgid "Enable conditinal fields? "
148
+ msgstr "שדות תנאי"
149
+
150
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:217
151
+ msgid ""
152
+ "<small>Turn ON if you want to enable the <strong>conditinal fields</strong>."
153
+ "</small>"
154
+ msgstr "הדלק להפעיל את השדות המותנים"
155
+
156
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:248
157
+ msgid "My help tab title"
158
+ msgstr "שם הטאב"
159
+
160
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:249
161
+ msgid "This is my Help Tab content"
162
+ msgstr "תוכן הטאב"
163
+
164
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:253
165
+ msgid "My 2nd help tab title"
166
+ msgstr "שם הטאב השני"
167
+
168
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:259
169
+ msgid "This is my 2nd Help Tab content from a callback function"
170
+ msgstr "תוכן הטאב השני שמגיע מפונקציה מקושרת"
171
+
172
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:380
173
+ msgid "Allowed Files"
174
+ msgstr "קבצים אפשריים"
175
+
176
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:615
177
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:617
178
+ msgid "Insert into Post"
179
+ msgstr "הכנס לפוטס"
180
+
181
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:615
182
+ msgid "Use this File"
183
+ msgstr "השתמש בקובץ זה"
184
+
185
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:617
186
+ msgid "Use this Image"
187
+ msgstr "השתמש בתמונה זאת"
188
+
189
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:649
190
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:744
191
+ msgid "Save Changes"
192
+ msgstr "שמור שינויים"
193
+
194
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:656
195
+ msgid "Settings saved."
196
+ msgstr "הגדרות נשמרו."
197
+
198
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1119
199
+ msgid "Delete this image"
200
+ msgstr "מחק תמונה זאת"
201
+
202
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1119
203
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1822
204
+ msgid "Delete"
205
+ msgstr "מחק"
206
+
207
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1214
208
+ msgid "Cannot delete file. Something's wrong."
209
+ msgstr "לא ניתן למחוק, שגיאה!"
210
+
211
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1418
212
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1463
213
+ msgid "Remove"
214
+ msgstr "הסר"
215
+
216
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1430
217
+ msgid "Add"
218
+ msgstr "הוסף"
219
+
220
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1610
221
+ msgid "Select Files"
222
+ msgstr "בחר קבצים"
223
+
224
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1818
225
+ msgid "Uploaded files"
226
+ msgstr "רבצים שהועלו"
227
+
228
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1829
229
+ msgid "Upload new files"
230
+ msgstr "העלה קבצים חדשים"
231
+
232
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1835
233
+ msgid "Add more files"
234
+ msgstr "הוסף קבצים"
235
+
236
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1861
237
+ #, fuzzy
238
+ msgid "Delete Image"
239
+ msgstr "מחק תמונה זאת"
240
+
241
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1866
242
+ msgid "Upload Image"
243
+ msgstr "העלה תמונה"
244
+
245
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1943
246
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1969
247
+ msgid "Select a color"
248
+ msgstr "בחר צבע"
249
+
250
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3177
251
+ msgid "Export"
252
+ msgstr "יצא"
253
+
254
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3178
255
+ msgid ""
256
+ "To export saved settings click the Export button bellow and you will get the "
257
+ "export Code in the box bellow, which you can later use to import."
258
+ msgstr "ליצא הגדרות הקלק על כפתור יצא"
259
+
260
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3180
261
+ msgid "Export Code"
262
+ msgstr "קוד יצוא"
263
+
264
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3182
265
+ msgid "Get Export"
266
+ msgstr "קוד יצאו"
267
+
268
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3187
269
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3192
270
+ msgid "Import"
271
+ msgstr "יבא"
272
+
273
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3188
274
+ msgid ""
275
+ "To Import saved settings paste the Export output in to the Import Code box "
276
+ "bellow and click Import."
277
+ msgstr "ליבא הגדרות הדבק את קוד היצוא בתיבה מתחת ולחץ על יבא."
278
+
279
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3190
280
+ msgid "Import Code"
281
+ msgstr "קוד יבוא"
282
+
283
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3217
284
+ msgid "error in ajax request! (1)"
285
+ msgstr "שגיאה (1)"
286
+
287
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3227
288
+ msgid "error in ajax request! (2)"
289
+ msgstr "שגיאה (2)"
290
+
291
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3248
292
+ msgid "error in ajax request! (3)"
293
+ msgstr "שגיאה (3)"
294
+
295
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3260
296
+ msgid "Setting imported, make sure you "
297
+ msgstr "הגדרות יובאו בהצלחה , אנא ודא"
298
+
299
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3260
300
+ msgid "Refresh this page"
301
+ msgstr "לרענן עמוד זה"
302
+
303
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3262
304
+ msgid "Could not import settings! (4)"
305
+ msgstr "שגיאה (4)"
306
+
307
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3283
308
+ msgid "You do not have sufficient permissions to edit templates for this site."
309
+ msgstr "אין לך הרשאות לבצע פעולה זאת"
310
+
311
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3286
312
+ msgid "Error Downloading file."
313
+ msgstr "שגיאה בהורדת הקובץ."
314
+
315
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3308
316
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3311
317
+ msgid "Download Export"
318
+ msgstr "שמור קובץ יצוא"
functions/admin-page-class/lang/pt_BR.mo ADDED
Binary file
functions/admin-page-class/lang/pt_BR.po ADDED
@@ -0,0 +1,326 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: Admin Page Class\n"
4
+ "POT-Creation-Date: 2012-12-26 22:53+0200\n"
5
+ "PO-Revision-Date: 2012-12-26 22:53+0200\n"
6
+ "Last-Translator: BaInternet <admin@bainternet.info>\n"
7
+ "Language-Team: WP-EX\n"
8
+ "MIME-Version: 1.0\n"
9
+ "Content-Type: text/plain; charset=UTF-8\n"
10
+ "Content-Transfer-Encoding: 8bit\n"
11
+ "X-Generator: Poedit 1.5.4\n"
12
+ "X-Poedit-KeywordsList: __;_e\n"
13
+ "X-Poedit-Basepath: C:\\wamp\\www\\dev\\hebtest\\wp-content\\plugins\\Admin-"
14
+ "Page-Class\n"
15
+ "X-Poedit-SearchPath-0: C:\\wamp\\www\\dev\\hebtest\\wp-content\\plugins"
16
+ "\\Admin-Page-Class\n"
17
+
18
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:22
19
+ msgid "Demo Admin Page"
20
+ msgstr ""
21
+
22
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:42
23
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:64
24
+ msgid "Simple Options"
25
+ msgstr ""
26
+
27
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:43
28
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:99
29
+ msgid "Fancy Options"
30
+ msgstr ""
31
+
32
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:44
33
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:132
34
+ msgid "Editor Options"
35
+ msgstr ""
36
+
37
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:45
38
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:159
39
+ msgid "WordPress Options"
40
+ msgstr ""
41
+
42
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:46
43
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:183
44
+ msgid "Advanced Options"
45
+ msgstr ""
46
+
47
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:47
48
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:232
49
+ #, fuzzy
50
+ msgid "Import Export"
51
+ msgstr "Gerar código"
52
+
53
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:66
54
+ msgid "This is a simple paragraph"
55
+ msgstr ""
56
+
57
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:68
58
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:192
59
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:206
60
+ msgid "My Text "
61
+ msgstr ""
62
+
63
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:70
64
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:193
65
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:207
66
+ msgid "My Textarea "
67
+ msgstr ""
68
+
69
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:72
70
+ msgid "My Checkbox "
71
+ msgstr ""
72
+
73
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:74
74
+ msgid "My select "
75
+ msgstr ""
76
+
77
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:76
78
+ msgid "My Radio Filed"
79
+ msgstr ""
80
+
81
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:101
82
+ msgid "My Typography"
83
+ msgstr ""
84
+
85
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:103
86
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:194
87
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:208
88
+ msgid "My Image "
89
+ msgstr ""
90
+
91
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:105
92
+ #, fuzzy
93
+ msgid "PlUpload Field"
94
+ msgstr "Arquivos guardados"
95
+
96
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:107
97
+ msgid "My Date "
98
+ msgstr ""
99
+
100
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:109
101
+ msgid "My Time "
102
+ msgstr ""
103
+
104
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:111
105
+ msgid "My Color "
106
+ msgstr ""
107
+
108
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:134
109
+ msgid "My wysiwyg Editor "
110
+ msgstr ""
111
+
112
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:136
113
+ msgid "Code Editor "
114
+ msgstr ""
115
+
116
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:161
117
+ msgid "My Taxonomy Select"
118
+ msgstr ""
119
+
120
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:163
121
+ msgid "My Posts Select"
122
+ msgstr ""
123
+
124
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:165
125
+ msgid "My Roles Select"
126
+ msgstr ""
127
+
128
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:167
129
+ msgid "My Taxonomy Checkboxes"
130
+ msgstr ""
131
+
132
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:169
133
+ msgid "My Posts Checkboxes"
134
+ msgstr ""
135
+
136
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:171
137
+ msgid "My Roles Checkboxes"
138
+ msgstr ""
139
+
140
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:186
141
+ msgid "My Sortable Field"
142
+ msgstr ""
143
+
144
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:200
145
+ msgid "This is a Repeater Block"
146
+ msgstr ""
147
+
148
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:216
149
+ msgid "Enable conditinal fields? "
150
+ msgstr ""
151
+
152
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:217
153
+ msgid ""
154
+ "<small>Turn ON if you want to enable the <strong>conditinal fields</strong>."
155
+ "</small>"
156
+ msgstr ""
157
+
158
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:248
159
+ msgid "My help tab title"
160
+ msgstr ""
161
+
162
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:249
163
+ msgid "This is my Help Tab content"
164
+ msgstr ""
165
+
166
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:253
167
+ msgid "My 2nd help tab title"
168
+ msgstr ""
169
+
170
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/class-usage-demo.php:259
171
+ msgid "This is my 2nd Help Tab content from a callback function"
172
+ msgstr ""
173
+
174
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:380
175
+ msgid "Allowed Files"
176
+ msgstr "Arquivos permitidos"
177
+
178
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:615
179
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:617
180
+ msgid "Insert into Post"
181
+ msgstr "Inserir no Post"
182
+
183
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:615
184
+ msgid "Use this File"
185
+ msgstr "Usar este arquivo"
186
+
187
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:617
188
+ msgid "Use this Image"
189
+ msgstr "Usar esta imagen"
190
+
191
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:649
192
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:744
193
+ msgid "Save Changes"
194
+ msgstr "Salvar"
195
+
196
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:656
197
+ msgid "Settings saved."
198
+ msgstr "Configurações guardadas."
199
+
200
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1119
201
+ msgid "Delete this image"
202
+ msgstr "Excluir esta imagem"
203
+
204
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1119
205
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1822
206
+ msgid "Delete"
207
+ msgstr "Excluir"
208
+
209
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1214
210
+ msgid "Cannot delete file. Something's wrong."
211
+ msgstr "Algo falhou ao excluir. "
212
+
213
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1418
214
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1463
215
+ msgid "Remove"
216
+ msgstr "Remover"
217
+
218
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1430
219
+ msgid "Add"
220
+ msgstr "Adicionar"
221
+
222
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1610
223
+ msgid "Select Files"
224
+ msgstr "Selecionar arquivos"
225
+
226
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1818
227
+ msgid "Uploaded files"
228
+ msgstr "Arquivos guardados"
229
+
230
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1829
231
+ msgid "Upload new files"
232
+ msgstr "Upload de novos arquivos"
233
+
234
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1835
235
+ msgid "Add more files"
236
+ msgstr "Adicionar mais arquivos"
237
+
238
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1861
239
+ #, fuzzy
240
+ msgid "Delete Image"
241
+ msgstr "Excluir esta imagem"
242
+
243
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1866
244
+ #, fuzzy
245
+ msgid "Upload Image"
246
+ msgstr "Arquivos guardados"
247
+
248
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1943
249
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:1969
250
+ msgid "Select a color"
251
+ msgstr "Selecione uma cor"
252
+
253
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3177
254
+ msgid "Export"
255
+ msgstr "Exportar"
256
+
257
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3178
258
+ msgid ""
259
+ "To export saved settings click the Export button bellow and you will get the "
260
+ "export Code in the box bellow, which you can later use to import."
261
+ msgstr ""
262
+ "Para exportar as configurações guardadas, clique no botão Exportar abaixo e "
263
+ "você terá o código de exportação na caixa de texto. Guarde e use para "
264
+ "importar posteriormente."
265
+
266
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3180
267
+ msgid "Export Code"
268
+ msgstr "Exportar código"
269
+
270
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3182
271
+ msgid "Get Export"
272
+ msgstr "Gerar código"
273
+
274
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3187
275
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3192
276
+ msgid "Import"
277
+ msgstr "Importar"
278
+
279
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3188
280
+ msgid ""
281
+ "To Import saved settings paste the Export output in to the Import Code box "
282
+ "bellow and click Import."
283
+ msgstr ""
284
+ "Para importar suas configurações guardadas, cole o código na caixa de texto "
285
+ "abaixo e clique Importar."
286
+
287
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3190
288
+ msgid "Import Code"
289
+ msgstr "Importar código"
290
+
291
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3217
292
+ msgid "error in ajax request! (1)"
293
+ msgstr "Erro na solicitação de Ajax! (1)"
294
+
295
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3227
296
+ msgid "error in ajax request! (2)"
297
+ msgstr "Erro na solicitação de Ajax! (2)"
298
+
299
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3248
300
+ msgid "error in ajax request! (3)"
301
+ msgstr "Erro na solicitação de Ajax! (3)"
302
+
303
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3260
304
+ msgid "Setting imported, make sure you "
305
+ msgstr "Configurações importadas, assegure-se de"
306
+
307
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3260
308
+ msgid "Refresh this page"
309
+ msgstr "atualizar esta página"
310
+
311
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3262
312
+ msgid "Could not import settings! (4)"
313
+ msgstr "Não foi possível importar as configurações! (4)"
314
+
315
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3283
316
+ msgid "You do not have sufficient permissions to edit templates for this site."
317
+ msgstr "Você não tem persmissões suficientes para editar modelos neste site."
318
+
319
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3286
320
+ msgid "Error Downloading file."
321
+ msgstr "Erro ao fazer download."
322
+
323
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3308
324
+ #: C:\wamp\www\dev\hebtest\wp-content\plugins\Admin-Page-Class/admin-page-class/admin-page-class.php:3311
325
+ msgid "Download Export"
326
+ msgstr ""
functions/bitly.php ADDED
@@ -0,0 +1,310 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*****************************************************************
4
+ * *
5
+ * Link Shortening & Analytics Functions *
6
+ * *
7
+ ******************************************************************/
8
+
9
+ // Enqueue the Bitly Shortener Hook
10
+ add_filter('sw_link_shortening' , 'sw_bitly_shortener' );
11
+ add_filter('sw_analytics' , 'sw_google_analytics' );
12
+
13
+
14
+ /*****************************************************************
15
+ * *
16
+ * The Google Analytics Filter Function *
17
+ * *
18
+ ******************************************************************/
19
+
20
+ function sw_google_analytics( $array ) {
21
+
22
+ // Fetch the user options
23
+ $options = sw_get_user_options();
24
+ $url = $array['url'];
25
+ $network = $array['network'];
26
+
27
+ // Check if Analytics have been enabled or not
28
+ if($options['googleAnalytics'] == true):
29
+ if (strpos($url,'?') !== false) :
30
+ $url = $url.urlencode('&utm_source='.$network.'&utm_medium='.$options['analyticsMedium'].'&utm_campaign='.$options['analyticsCampaign'].'');
31
+ else:
32
+ $url = $url.urlencode('?utm_source='.$network.'&utm_medium='.$options['analyticsMedium'].'&utm_campaign='.$options['analyticsCampaign'].'');
33
+ endif;
34
+ return $url;
35
+ else:
36
+ return $url;
37
+ endif;
38
+ }
39
+
40
+ /*****************************************************************
41
+ * *
42
+ * The Bitly Link Shortener Function *
43
+ * *
44
+ ******************************************************************/
45
+
46
+ // The Bitly Shortener Function called by the filter hook
47
+ function sw_bitly_shortener( $array ) {
48
+
49
+ $url = $array['url'];
50
+ $network = $array['network'];
51
+ $postID = $array['postID'];
52
+
53
+ // Fetch the User's Options
54
+ $options = sw_get_user_options();
55
+
56
+ // If Link shortening is activated....
57
+ if($options['linkShortening'] == true) :
58
+
59
+ // If Bitly is activated and we have all the appropriate credentials....
60
+ if($options['shorteningMethod'] == 'bitly' && isset($options['bitly_access_token'])):
61
+
62
+ // Collect our bitly login information
63
+ $access_token = $options['bitly_access_token'];
64
+
65
+ // If Google Analytics is Activated....
66
+ if($options['googleAnalytics'] == true):
67
+
68
+ // If the Cache is still fresh or a previous API request failed....
69
+ if(sw_is_cache_fresh($postID) == true || (isset($_GLOBALS['bitly_status']) && $_GLOBALS['bitly_status'] == 'failure') ):
70
+
71
+ // If the link has already been shortened....
72
+ $existingURL = get_post_meta($postID,'bitly_link_'.$network,true);
73
+ if($existingURL && sw_is_cache_fresh($postID) == true):
74
+ return $existingURL;
75
+
76
+ // If the link has NOT already been shortened
77
+ else:
78
+
79
+ // ....Return the normal URL
80
+ return $url;
81
+
82
+ endif;
83
+
84
+ // If the Cache is NOT fresh....
85
+ else:
86
+
87
+ // If the API provides a shortened URL...
88
+ $shortURL = sw_make_bitly_url( urldecode($url) , $network , $access_token );
89
+ if($shortURL):
90
+
91
+ // Store the link in the cache and return it to the buttons
92
+ delete_post_meta($postID,'bitly_link_'.$network);
93
+ update_post_meta($postID,'bitly_link_'.$network,$shortURL);
94
+ return $shortURL;
95
+
96
+ // If the API does not provide a shortened URL....
97
+ else:
98
+
99
+ // Set a variable we'll check to avoid multiple calls to bitly upon the first failure
100
+ $_GLOBALS['sw']['bitly_status'] = 'failure';
101
+
102
+ // Return the normal URL
103
+ return $url;
104
+
105
+ // End the check for a shortneing link from the API
106
+ endif;
107
+
108
+ // End the check for the cache being fresh
109
+ endif;
110
+
111
+ // If Google Analytics is NOT activated....
112
+ else:
113
+
114
+ // If the cache is fresh or if the API has failed already....
115
+ if(sw_is_cache_fresh($postID) == true || (isset($_GLOBALS['bitly_status']) && $_GLOBALS['bitly_status'] == 'failure')):
116
+
117
+ // If we have a shortened URL in the cache....
118
+ $existingURL = get_post_meta($postID,'bitly_link',true);
119
+ if($existingURL):
120
+
121
+ // Save the link in a constant for use in other parts of the loops
122
+ $_GLOBALS['sw']['links'][$postID] = $existingURL;
123
+
124
+ // Return the shortened URL
125
+ return $existingURL;
126
+
127
+ // If we don't have a shortlink in the cache....
128
+ else:
129
+
130
+ // Return the normal URL
131
+ return $url;
132
+
133
+ endif;
134
+
135
+ // If the cache is expired and needs to be rebuilt....
136
+ else:
137
+
138
+ // If we've already generated this link....
139
+ if(isset($_GLOBALS['sw']['links'][$postID])):
140
+
141
+ return $_GLOBALS['sw']['links'][$postID];
142
+
143
+ // If we've don't already have a generated link....
144
+ else:
145
+
146
+ // Use the bitly function to construct a shortened link
147
+ $shortURL = sw_make_bitly_url( urldecode($url) , $network , $access_token );
148
+
149
+ // If we got a shortened URL from their API....
150
+ if($shortURL):
151
+
152
+ // Save the link in a global so we can skip this part next time
153
+ $_GLOBALS['sw']['links'][$postID] = $shortURL;
154
+
155
+ // Delete the meta fields and then update to keep the database clean and up to date.
156
+ delete_post_meta($postID,'bitly_link_'.$network);
157
+ delete_post_meta($postID,'bitly_link');
158
+ update_post_meta($postID,'bitly_link',$shortURL);
159
+
160
+ // Return the short URL
161
+ return $shortURL;
162
+
163
+ // If didn't get a shortened URL from their API....
164
+ else:
165
+
166
+ // Set a variable we'll check to avoid multiple calls to bitly upon the first failure
167
+ $_GLOBALS['sw']['bitly_status'] = 'failure';
168
+
169
+ // Return the normal URL
170
+ return $url;
171
+
172
+ // End check for shorte URL from the API
173
+ endif;
174
+
175
+ // End check for link in the Global Variable
176
+ endif;
177
+
178
+ // End check for the cache freshness
179
+ endif;
180
+
181
+ // End check for Analytics
182
+ endif;
183
+
184
+ // If Bitly is not activated or we don't have the credentials provided....
185
+ else:
186
+
187
+ // Return the normal URL
188
+ return $url;
189
+
190
+ // End the check for bitly activation and credentials
191
+ endif;
192
+
193
+ // If link shortening is not activated....
194
+ else:
195
+
196
+ // Return the normal URL
197
+ return $url;
198
+
199
+ // End the check for link shortening being activated
200
+ endif;
201
+ }
202
+
203
+ function sw_make_bitly_url( $url , $network , $access_token) {
204
+
205
+ // Fetch the user's options
206
+ $options = sw_get_user_options();
207
+
208
+ /* Create a link to check if the permalink has already been shortened.
209
+ $bitly_lookup_url = 'https://api-ssl.bitly.com/v3/user/link_lookup?url='.urlencode($url).'&access_token='.$access_token;
210
+
211
+ // Fetch a response from the Bitly Lookup API
212
+ $bitly_lookup_response = sw_file_get_contents_curl( $bitly_lookup_url );
213
+
214
+ // Parse the JSON formatted response from the Bitly Lookup API
215
+ $bitly_lookup_response = json_decode( $bitly_lookup_response , true );
216
+
217
+ // If the lookup returned a valid, previously generated short link....
218
+ if( isset( $bitly_lookup_response['data']['link_lookup'][0]['link'] ) && true == false ):
219
+
220
+ // Store the short url to return to the plugin
221
+ $short_url = $bitly_lookup_response['data']['link_lookup'][0]['link'];
222
+
223
+ // If the lookup did not return a valid short link....
224
+ else:*/
225
+
226
+ // Set the format to json
227
+ $format='json';
228
+
229
+ // Create a link to reach the Bitly API
230
+ $bitly_api = 'https://api-ssl.bitly.com/v3/shorten?access_token='.$access_token.'&uri='.urlencode($url).'&format='.$format;
231
+
232
+ // Fetch a response from the Bitly Shortening API
233
+ $data = sw_file_get_contents_curl($bitly_api);
234
+
235
+ // Parse the JSON formated response into an array
236
+ $data = json_decode( $data , true);
237
+
238
+ // If the shortening succeeded....
239
+ if( isset ( $data['data']['url'] ) ) :
240
+
241
+ // Store the short URL to return to the plugin
242
+ $short_url = $data['data']['url'];
243
+
244
+ // If the shortening failed....
245
+ else:
246
+
247
+ // Return a status of false
248
+ $short_url = false;
249
+
250
+ endif;
251
+
252
+ // endif;
253
+
254
+ return $short_url;
255
+
256
+ }
257
+
258
+ /*****************************************************************
259
+ * *
260
+ * Apply the Link Shortening and Analytics Filters to the URL *
261
+ * *
262
+ ******************************************************************/
263
+
264
+ function sw_process_url( $url , $network , $postID) {
265
+
266
+ // $bitly_api = 'https://api-ssl.bitly.com/v3/link/lookup?url='.urlencode($url).'&login='.$login.'&apiKey='.$appkey;
267
+ // $data = sw_file_get_contents_curl($bitly_api);
268
+ // $data = json_decode($data);
269
+ // var_dump($data);
270
+
271
+ // Check to see if we've already shortened this link in another section of the loop.
272
+ // This will only be set if analytics are turned off and bitly is turned on.
273
+ // Since all links will be the same, this will be generated on the first request and
274
+ // then stored for immediate use on subsequent requests.
275
+ if(isset($_GLOBALS['sw']['links'][$postID])):
276
+ return $_GLOBALS['sw']['links'][$postID];
277
+ else:
278
+
279
+ // $options = sw_get_user_options();
280
+ $array['url'] = $url;
281
+ $array['network'] = $network;
282
+ $array['postID'] = $postID;
283
+ $array['url'] = apply_filters('sw_analytics' , $array);
284
+ $url = apply_filters('sw_link_shortening' , $array);
285
+ return $url;
286
+
287
+ endif;
288
+
289
+ }
290
+
291
+ /*****************************************************************
292
+ * *
293
+ * BITLY OAUTH TRIGGER RESPONSE *
294
+ * *
295
+ ******************************************************************/
296
+ add_action( 'wp_ajax_nopriv_sw_bitly_oauth', 'sw_bitly_oauth_callback' );
297
+ function sw_bitly_oauth_callback() {
298
+
299
+ // Fetch the User's Options Array
300
+ $sw_user_options = sw_get_user_options();
301
+
302
+ // Set the premium code to null
303
+ $sw_user_options['bitly_access_token'] = $_GET['access_token'];
304
+
305
+ // Update the options array with the premium code nulled
306
+ update_option('socialWarfareOptions',$sw_user_options);
307
+
308
+ echo admin_url( 'admin.php?page=social-warfare' );
309
+
310
+ };
functions/buttons-floating.php ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*****************************************************************
4
+ * *
5
+ * Side Fixed Floater Function *
6
+ * *
7
+ ******************************************************************/
8
+
9
+ function socialWarfareSideFloat() {
10
+
11
+ $postID = get_the_ID();
12
+ $options = sw_get_user_options();
13
+ $postType = get_post_type($postID);
14
+
15
+ if( is_singular('post') ):
16
+ $visibility = $options['floatLocationPost'];
17
+ elseif( is_singular('page') ):
18
+ $visibility = $options['floatlocationPage'];
19
+ elseif( is_singular() ):
20
+ $postType = get_post_type($postID);
21
+ if(isset($options['floatLocation'.$postType])):
22
+ $visilibity = $options['floatLocation'.$postType];
23
+ else:
24
+ $visibility = 'on';
25
+ endif;
26
+ else:
27
+ $visibility = 'on';
28
+ endif;
29
+
30
+ if( is_singular() && get_post_status($postID) == 'publish' && get_post_meta( $postID , 'nc_floatLocation' , true ) != 'off' && $visibility == 'on' && !is_home()):
31
+
32
+ // Get the options...or create them if they don't exist
33
+ wp_reset_query();
34
+
35
+ // Acquire the social stats from the networks
36
+ // Acquire the social stats from the networks
37
+ if(isset($array['url'])):
38
+ $buttonsArray['url'] = $array['url'];
39
+ else:
40
+ $buttonsArray['url'] = get_permalink( $postID );
41
+ endif;
42
+
43
+ if($options['float'] && is_singular()):
44
+ $floatOption = 'float'.ucfirst($options['floatOption']);
45
+ else:
46
+ $floatOption = 'floatNone';
47
+ endif;
48
+
49
+ $language = array();
50
+ $language = apply_filters('sw_languages',$language);
51
+
52
+ if($options['floatStyleSource'] == true):
53
+ $options['sideDColorSet'] = $options['dColorSet'];
54
+ $options['sideIColorSet'] = $options['iColorSet'];
55
+ $options['sideOColorSet'] = $options['oColorSet'];
56
+ endif;
57
+
58
+ // Setup the buttons array to pass into the 'sw_network_buttons' hook
59
+ $buttonsArray['shares'] = get_social_warfare_shares($postID);
60
+ $buttonsArray['language'] = apply_filters( 'sw_languages' , $language );
61
+ $buttonsArray['count'] = 0;
62
+ $buttonsArray['totes'] = 0;
63
+ $buttonsArray['options'] = $options;
64
+ if( $buttonsArray['options']['totes'] && $buttonsArray['shares']['totes'] >= $buttonsArray['options']['minTotes'] ) ++$buttonsArray['count'];
65
+ $buttonsArray['resource'] = array();
66
+ $buttonsArray['postID'] = $postID;
67
+ $buttonsArray = apply_filters( 'sw_network_buttons' , $buttonsArray );
68
+
69
+ // Create the social panel
70
+ $assets = '<div class="nc_socialPanelSide nc_socialPanel sw_'.$options['floatStyle'].' sw_d_'.$options['sideDColorSet'].' sw_i_'.$options['sideIColorSet'].' sw_o_'.$options['sideOColorSet'].' '.$options['sideReveal'].'" data-position="'.$options['locationPost'].'" data-float="'.$floatOption.'" data-count="'.$buttonsArray['count'].'" data-floatColor="'.$options['floatBgColor'].'" data-screen-width="'.$options['sw_float_scr_sz'].'" data-transition="'.$options['sideReveal'].'">';
71
+
72
+ // Display Total Shares if the Threshold has been met
73
+ if($options['totes'] && $buttonsArray['totes'] >= $options['minTotes']):
74
+ $assets .= '<div class="nc_tweetContainer totes totesalt" data-id="6" >';
75
+ $assets .= '<span class="sw_count">'.kilomega($buttonsArray['totes']).'</span><span class="sw_label"> '.$language['total'].'</span>';
76
+ $assets .= '</div>';
77
+ endif;
78
+
79
+ $i = 0;
80
+ if($options['orderOfIconsSelect'] == 'manual'):
81
+ foreach($options['newOrderOfIcons'] as $thisIcon => $status):
82
+ if(isset($buttonsArray['resource'][$thisIcon])):
83
+ $assets .= $buttonsArray['resource'][$thisIcon];
84
+ ++$i;
85
+ endif;
86
+ if ($i == 5) break;
87
+ endforeach;
88
+ elseif($options['orderOfIconsSelect'] == 'dynamicCount'):
89
+ arsort($buttonsArray['shares']);
90
+ foreach($buttonsArray['shares'] as $thisIcon => $status):
91
+ if(isset($buttonsArray['resource'][$thisIcon])):
92
+ $assets .= $buttonsArray['resource'][$thisIcon];
93
+ ++$i;
94
+ endif;
95
+ if ($i == 5) break;
96
+ endforeach;
97
+ endif;
98
+
99
+ // Close the Social Panel
100
+ $assets .= '</div>';
101
+
102
+ echo $assets;
103
+
104
+ endif;
105
+ }
functions/buttons-standard.php ADDED
@@ -0,0 +1,263 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*****************************************************************
4
+ * *
5
+ * THE SOCIAL WARFARE WRAPPER FUNCTION *
6
+ * *
7
+ ******************************************************************/
8
+ function socialWarfare( $content = false , $where = 'default' , $echo = true ) {
9
+
10
+ // Collect the deprecated fields and place them into an array
11
+ $array['content'] = $content;
12
+ $array['where'] = $where;
13
+ $array['echo'] = $echo;
14
+ $array['devs'] = true;
15
+
16
+ // Pass the array into the new function
17
+ return social_warfare($array);
18
+ }
19
+
20
+ /*****************************************************************
21
+ * *
22
+ * CACHe CHECKING FUNCTION *
23
+ * *
24
+ ******************************************************************/
25
+ function sw_is_cache_fresh( $postID , $output=false ) {
26
+
27
+ // Fetch the Options
28
+ $options = sw_get_user_options();
29
+
30
+ // Check if output is being forced or if legacy caching is enabled
31
+ if($output == false && $options['cacheMethod'] != 'legacy'):
32
+ if(isset($_GET['sw_cache']) && $_GET['sw_cache'] == 'rebuild'):
33
+ $freshCache = false;
34
+ else:
35
+ $freshCache = true;
36
+ endif;
37
+
38
+ else:
39
+ $postAge = floor(date('U') - get_post_time('U'));
40
+ if($postAge < (21 * 86400)){ $hours = 1; }
41
+ elseif($postAge < (60 * 86400)) { $hours = 4; }
42
+ else { $hours = 12; }
43
+
44
+ $time = floor(((date('U')/60)/60));
45
+ $lastChecked = get_post_meta($postID,'sw_cache_timestamp',true);
46
+
47
+ // Check if it's a crawl bot. If so, ONLY SERVE CACHED RESULTS FOR MAXIMUM SPEED
48
+ if (isset($_SERVER['HTTP_USER_AGENT']) && preg_match('/bot|crawl|slurp|spider/i', $_SERVER['HTTP_USER_AGENT'])):
49
+ $freshCache = true;
50
+
51
+ // Next, check if the cache is fresh or needs rebuilt
52
+ // Always be TRUE if we're not on a single.php otherwise we could end up
53
+ // Rebuilding multiple page caches which will cost a lot of time.
54
+ elseif(($lastChecked > ($time - $hours) && $lastChecked > 390000) || !is_singular()) :
55
+ $freshCache = true;
56
+ else:
57
+ $freshCache = false;
58
+ endif;
59
+ endif;
60
+ return $freshCache;
61
+ }
62
+
63
+
64
+ function sw_disable_subs() { return false; };
65
+ /*****************************************************************
66
+
67
+ THE SHARE BUTTONS FUNCTION:
68
+
69
+ This function accepts an array of parameters resulting in the
70
+ outputting of the Social Warfare Buttons.
71
+
72
+
73
+ ACCEPTED PARAMETERS :
74
+
75
+ content : The post content to which we append the buttons
76
+ : (string)
77
+
78
+ where : Used to overwrite the default location in relation to the content
79
+ : ( above | below | both | none )
80
+
81
+ echo : Used to print or store the variables.
82
+ : ( true | false )
83
+
84
+
85
+
86
+ ******************************************************************/
87
+ function social_warfare_buttons($array = array()) {
88
+
89
+ // Setup the default Array parameters
90
+ if(!isset($array['where'])) { $array['where'] = 'default'; }
91
+ if(!isset($array['echo'])) { $array['echo'] = true; }
92
+ if(!isset($array['content'])) { $array['content'] = false; }
93
+
94
+ // Get the options...or create them if they don't exist
95
+ if(isset($array['post_id'])):
96
+ $postID = $array['post_id'];
97
+ else:
98
+ $postID = get_the_ID();
99
+ endif;
100
+
101
+ $options = sw_get_user_options();
102
+
103
+ // Check to see if display location was specifically defined for this post
104
+ $specWhere = get_post_meta($postID,'nc_postLocation',true);
105
+ if( !$specWhere ) { $specWhere = 'default'; };
106
+
107
+ if($array['where'] == 'default'):
108
+ if($specWhere == 'default' || $specWhere == ''):
109
+ if( is_singular('post') ):
110
+ $array['where'] = $options['locationPost'];
111
+ elseif( is_singular('page') ):
112
+ $array['where'] = $options['locationPage'];
113
+ elseif( is_singular() ):
114
+ $postType = get_post_type($postID);
115
+ if(isset($options['location'.$postType])):
116
+ $array['where'] = $options['location'.$postType];
117
+ else:
118
+ $array['where'] = 'none';
119
+ endif;
120
+ else:
121
+ $postType = get_post_type($postID);
122
+ if(isset($options['location'.$postType])):
123
+ $array['where'] = $options['location'.$postType];
124
+ elseif($postType == 'post' || $postType == 'page'):
125
+ $array['where'] = $options['locationSite'];
126
+ else:
127
+ $array['where'] = 'none';
128
+ endif;
129
+ endif;
130
+ else:
131
+ $array['where'] = $specWhere;
132
+ endif;
133
+ endif;
134
+
135
+ // Disable the buttons on Buddy Press pages
136
+ if(function_exists('is_buddypress') && is_buddypress()):
137
+ return $array['content'];
138
+
139
+ // Disable the buttons if the location is set to "None / Manual"
140
+ elseif($array['where'] == 'none' && !isset($array['devs'])):
141
+ return $array['content'];
142
+
143
+ // Disable the button if we're not in the loop, unless there is no content which means the function was called by a developer.
144
+ elseif( (!is_main_query() || !in_the_loop()) && !isset($array['devs']) ):
145
+ return $array['content'];
146
+
147
+ // Don't do anything if we're in the admin section
148
+ elseif( is_admin() ):
149
+ return $array['content'];
150
+
151
+ // If all the checks pass, let's make us some buttons!
152
+ else:
153
+
154
+ // Set the options for the horizontal floating bar
155
+ if($options['float'] && is_singular()):
156
+ $floatOption = 'float'.ucfirst($options['floatOption']);
157
+ else:
158
+ $floatOption = 'floatNone';
159
+ endif;
160
+
161
+ // Disable the plugin on feeds, search results, and non-published content
162
+ if (!is_feed() && !is_search() && get_post_status($postID) == 'publish' ):
163
+
164
+ // Acquire the social stats from the networks
165
+ if(isset($array['url'])):
166
+ $buttonsArray['url'] = $array['url'];
167
+ else:
168
+ $buttonsArray['url'] = get_permalink( $postID );
169
+ endif;
170
+
171
+ $language = array();
172
+ $language = apply_filters('sw_languages',$language);
173
+
174
+ // Setup the buttons array to pass into the 'sw_network_buttons' hook
175
+ $buttonsArray['shares'] = get_social_warfare_shares($postID);
176
+ $buttonsArray['language'] = apply_filters( 'sw_languages' , $language );
177
+ $buttonsArray['count'] = 0;
178
+ $buttonsArray['totes'] = 0;
179
+ $buttonsArray['options'] = $options;
180
+ if( $buttonsArray['options']['totes'] && $buttonsArray['shares']['totes'] >= $buttonsArray['options']['minTotes'] ) ++$buttonsArray['count'];
181
+
182
+ $buttonsArray['resource'] = array();
183
+ $buttonsArray['postID'] = $postID;
184
+
185
+
186
+ // Disable the subtitles plugin to avoid letting them inject their subtitle into our share titles
187
+ if ( is_plugin_active( 'subtitles/subtitles.php' ) && class_exists ( 'Subtitles' ) ) :
188
+ remove_filter( 'the_title', array( Subtitles::getinstance() , 'the_subtitle' ), 10, 2 );
189
+ endif;
190
+
191
+ // This array will contain the HTML for all of the individual buttons
192
+ $buttonsArray = apply_filters( 'sw_network_buttons' , $buttonsArray );
193
+
194
+ // Create the social panel
195
+ $assets = '<div class="nc_socialPanel sw_'.$options['visualTheme'].' sw_d_'.$options['dColorSet'].' sw_i_'.$options['iColorSet'].' sw_o_'.$options['oColorSet'].'" data-position="'.$options['locationPost'].'" data-float="'.$floatOption.'" data-count="'.$buttonsArray['count'].'" data-floatColor="'.$options['floatBgColor'].'" data-scale="'.$options['buttonSize'].'" data-align="'.$options['buttonFloat'].'">';
196
+
197
+ // Setup the total shares count if it's on the left
198
+ if($options['totes'] && $options['swTotesFormat'] == 'totesAltLeft' && $buttonsArray['totes'] >= $options['minTotes']):
199
+ $assets .= '<div class="nc_tweetContainer totes totesalt" data-id="6" >';
200
+ $assets .= '<span class="sw_count">'.kilomega($buttonsArray['totes']).' <span class="sw_label">'.$language['total'].'</span></span>';
201
+ $assets .= '</div>';
202
+ endif;
203
+
204
+ // Sort the buttons according to the user's preferences
205
+ if($options['orderOfIconsSelect'] == 'manual'):
206
+ foreach($options['newOrderOfIcons'] as $thisIcon => $status):
207
+ if(isset($buttonsArray['resource'][$thisIcon])):
208
+ $assets .= $buttonsArray['resource'][$thisIcon];
209
+ endif;
210
+ endforeach;
211
+ elseif($options['orderOfIconsSelect'] == 'dynamicCount'):
212
+ arsort($buttonsArray['shares']);
213
+ foreach($buttonsArray['shares'] as $thisIcon => $status):
214
+ if(isset($buttonsArray['resource'][$thisIcon])):
215
+ $assets .= $buttonsArray['resource'][$thisIcon];
216
+ endif;
217
+ endforeach;
218
+ endif;
219
+
220
+ // Create the Total Shares Box if it's on the right
221
+ if( $options['totes'] && $options['swTotesFormat'] != 'totesAltLeft' && $buttonsArray['totes'] >= $options['minTotes']):
222
+ if($options['swTotesFormat'] == 'totes'):
223
+ $assets .= '<div class="nc_tweetContainer totes" data-id="6" >';
224
+ $assets .= '<span class="sw_count">'.kilomega($buttonsArray['totes']).' <span class="sw_label">'.$language['total'].'</span></span>';
225
+ $assets .= '</div>';
226
+ else:
227
+ $assets .= '<div class="nc_tweetContainer totes totesalt" data-id="6" >';
228
+ $assets .= '<span class="sw_count"><span class="sw_label">'.$language['total'].'</span> '.kilomega($buttonsArray['totes']).'</span>';
229
+ $assets .= '</div>';
230
+ endif;
231
+ endif;
232
+
233
+ // Close the Social Panel
234
+ $assets .= '</div>';
235
+
236
+ // Reset the cache timestamp if needed
237
+ if(sw_is_cache_fresh($postID) == false):
238
+ delete_post_meta($postID,'sw_cache_timestamp');
239
+ update_post_meta($postID,'sw_cache_timestamp',floor(((date('U')/60)/60)));
240
+ endif;
241
+
242
+ if($array['echo'] == false && $array['where'] != 'none'):
243
+ return $assets;
244
+ elseif($array['content'] === false):
245
+ echo $assets;
246
+ elseif($array['where'] == 'below'):
247
+ $content = $array['content'].''.$assets;
248
+ return $content;
249
+ elseif($array['where'] == 'above'):
250
+ $content = $assets.''.$array['content'];
251
+ return $content;
252
+ elseif($array['where'] == 'both'):
253
+ $content = $assets.''.$array['content'].''.$assets;
254
+ return $content;
255
+ elseif($array['where'] == 'none'):
256
+ return $array['content'];
257
+ endif;
258
+ else:
259
+ return $array['content'];
260
+ endif;
261
+
262
+ endif;
263
+ }
functions/click-to-tweet/assets/css/admin.css ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ i.mce-i-icon {
2
+ font: 400 20px/1 dashicons;
3
+ padding: 0;
4
+ vertical-align: top;
5
+ speak: none;
6
+ -webkit-font-smoothing: antialiased;
7
+ -moz-osx-font-smoothing: grayscale;
8
+ margin-left: -2px;
9
+ padding-right: 2px;
10
+ }
11
+ i.mce-i-icon:before {
12
+ color:#60a8dc;
13
+ }
functions/click-to-tweet/assets/css/style1.css ADDED
@@ -0,0 +1,174 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .sw-CTT {
2
+ display:block;
3
+ }
4
+ .sw-tweet-clear {
5
+ zoom: 1;
6
+ }
7
+ .sw-tweet-clear:after {
8
+ display: block;
9
+ visibility: hidden;
10
+ height: 0;
11
+ clear: both;
12
+ content: ".";
13
+ }
14
+ .sw-click-to-tweet {
15
+ display: block;
16
+ background-color: #fff;
17
+ margin: 0;
18
+ padding: 0;
19
+ position: relative;
20
+ border: 1px solid #dddddd;
21
+ -moz-border-radius: 4px;
22
+ border-radius: 4px;
23
+ padding: 15px 30px;
24
+ margin: 15px 0px;
25
+ zoom: 1;
26
+ }
27
+ .sw-click-to-tweet .clearfix {
28
+ zoom: 1;
29
+ }
30
+ .sw-click-to-tweet .clearfix:after {
31
+ display: block;
32
+ visibility: hidden;
33
+ height: 0;
34
+ clear: both;
35
+ content: ".";
36
+ }
37
+ .sw-click-to-tweet .clear {
38
+ clear: both;
39
+ }
40
+ .sw-click-to-tweet .f-left {
41
+ float: left;
42
+ display: inline-block;
43
+ position: relative;
44
+ }
45
+ .sw-click-to-tweet .f-right {
46
+ float: right;
47
+ display: inline-block;
48
+ position: relative;
49
+ }
50
+ .sw-click-to-tweet .list-reset {
51
+ list-style: none;
52
+ margin: 0;
53
+ padding: 0;
54
+ }
55
+ .sw-click-to-tweet .list-reset li {
56
+ list-style: none;
57
+ margin: 0;
58
+ padding: 0;
59
+ }
60
+ .sw-click-to-tweet .list-float {
61
+ zoom: 1;
62
+ }
63
+ .sw-click-to-tweet .list-float:after {
64
+ display: block;
65
+ visibility: hidden;
66
+ height: 0;
67
+ clear: both;
68
+ content: ".";
69
+ }
70
+ .sw-click-to-tweet .list-float li {
71
+ float: left;
72
+ display: inline-block;
73
+ }
74
+ .sw-click-to-tweet .kill-box-shadow {
75
+ box-shadow: none;
76
+ -webkit-box-shadow: none;
77
+ -moz-box-shadow: none;
78
+ }
79
+ .sw-click-to-tweet .alignright {
80
+ float: right;
81
+ margin-bottom: 10px;
82
+ margin-left: 10px;
83
+ text-align: right;
84
+ }
85
+ .sw-click-to-tweet .alignleft {
86
+ float: left;
87
+ margin-bottom: 10px;
88
+ margin-right: 10px;
89
+ text-align: right;
90
+ }
91
+ .sw-click-to-tweet:after {
92
+ content: ".";
93
+ display: block;
94
+ clear: both;
95
+ visibility: hidden;
96
+ line-height: 0;
97
+ height: 0;
98
+ }
99
+ .sw-click-to-tweet .sw-ctt-reset {
100
+ margin: 0;
101
+ padding: 0;
102
+ position: relative;
103
+ }
104
+ .sw-click-to-tweet:after {
105
+ display: block;
106
+ visibility: hidden;
107
+ height: 0;
108
+ clear: both;
109
+ content: ".";
110
+ }
111
+ .sw-click-to-tweet a {
112
+ text-decoration: none;
113
+ text-transform: none;
114
+ }
115
+ .sw-click-to-tweet a:hover {
116
+ text-decoration: none;
117
+ }
118
+ .sw-click-to-tweet .sw-ctt-text {
119
+ margin: 0;
120
+ padding: 0;
121
+ position: relative;
122
+ margin-bottom: 10px;
123
+ word-wrap: break-word;
124
+ }
125
+ a .sw-click-to-tweet .sw-ctt-text {
126
+ margin: 0;
127
+ padding: 0;
128
+ position: relative;
129
+ color: #999999;
130
+ font-size: 24px;
131
+ line-height: 140%;
132
+ text-transform: none;
133
+ font-weight: 500;
134
+ text-decoration: none;
135
+ text-transform: none;
136
+ display:block;
137
+ }
138
+ a:hover .sw-click-to-tweet .sw-ctt-text {
139
+ text-decoration: none;
140
+ color: #666666;
141
+ }
142
+ .sw-click-to-tweet .sw-ctt-btn {
143
+ margin: 0;
144
+ padding: 3px;
145
+ position: relative;
146
+ display: block;
147
+ text-transform: uppercase;
148
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
149
+ font-size: 12px;
150
+ font-weight: bold;
151
+ line-height: 100%;
152
+ color: #999999;
153
+ float: right;
154
+ padding-right: 24px;
155
+ text-decoration: none;
156
+ background: transparent url("//4.bp.blogspot.com/-Ku-iYrKVffw/VHjB2LFSO1I/AAAAAAAAEyI/NDiWlshts4M/s1600/twitter-little-bird.png") no-repeat right top;
157
+ }
158
+ a:hover .sw-click-to-tweet .sw-ctt-btn {
159
+ text-decoration: none;
160
+ color: #666666;
161
+ text-transform: uppercase;
162
+ }
163
+ .sw-click-to-tweet .sw-powered-by {
164
+ font-size: 10px;
165
+ color: #999999;
166
+ }
167
+ .sw-click-to-tweet .sw-powered-by a {
168
+ font-size: 10px;
169
+ color: #999999 !important;
170
+ }
171
+ .sw-click-to-tweet .sw-powered-by a:hover {
172
+ color: #999999 !important;
173
+ text-decoration: underline !important;
174
+ }
functions/click-to-tweet/assets/css/style2.css ADDED
@@ -0,0 +1,172 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .sw-tweet-clear {
2
+ zoom: 1;
3
+ }
4
+ .sw-tweet-clear:after {
5
+ display: block;
6
+ visibility: hidden;
7
+ height: 0;
8
+ clear: both;
9
+ content: ".";
10
+ }
11
+ .sw-click-to-tweet {
12
+ display: block;
13
+ background-color: #FFF;
14
+ margin: 0;
15
+ padding: 0;
16
+ position: relative;
17
+ border: 4px double #DDD;
18
+ -moz-border-radius: 0px;
19
+ border-radius: 0px;
20
+ padding: 30px 30px;
21
+ margin: 15px 0px;
22
+ zoom: 1;
23
+ }
24
+ .sw-click-to-tweet .clearfix {
25
+ zoom: 1;
26
+ }
27
+ .sw-click-to-tweet .clearfix:after {
28
+ display: block;
29
+ visibility: hidden;
30
+ height: 0;
31
+ clear: both;
32
+ content: ".";
33
+ }
34
+ .sw-click-to-tweet .clear {
35
+ clear: both;
36
+ }
37
+ .sw-click-to-tweet .f-left {
38
+ float: left;
39
+ display: inline-block;
40
+ position: relative;
41
+ }
42
+ .sw-click-to-tweet .f-right {
43
+ float: right;
44
+ display: inline-block;
45
+ position: relative;
46
+ }
47
+ .sw-click-to-tweet .list-reset {
48
+ list-style: none;
49
+ margin: 0;
50
+ padding: 0;
51
+ }
52
+ .sw-click-to-tweet .list-reset li {
53
+ list-style: none;
54
+ margin: 0;
55
+ padding: 0;
56
+ }
57
+ .sw-click-to-tweet .list-float {
58
+ zoom: 1;
59
+ }
60
+ .sw-click-to-tweet .list-float:after {
61
+ display: block;
62
+ visibility: hidden;
63
+ height: 0;
64
+ clear: both;
65
+ content: ".";
66
+ }
67
+ .sw-click-to-tweet .list-float li {
68
+ float: left;
69
+ display: inline-block;
70
+ }
71
+ .sw-click-to-tweet .kill-box-shadow {
72
+ box-shadow: none;
73
+ -webkit-box-shadow: none;
74
+ -moz-box-shadow: none;
75
+ }
76
+ .sw-click-to-tweet .alignright {
77
+ float: right;
78
+ margin-bottom: 10px;
79
+ margin-left: 10px;
80
+ text-align: right;
81
+ }
82
+ .sw-click-to-tweet .alignleft {
83
+ float: left;
84
+ margin-bottom: 10px;
85
+ margin-right: 10px;
86
+ text-align: right;
87
+ }
88
+ .sw-click-to-tweet:after {
89
+ content: ".";
90
+ display: block;
91
+ clear: both;
92
+ visibility: hidden;
93
+ line-height: 0;
94
+ height: 0;
95
+ }
96
+ .sw-click-to-tweet .sw-ctt-reset {
97
+ margin: 0;
98
+ padding: 0;
99
+ position: relative;
100
+ }
101
+ .sw-click-to-tweet:after {
102
+ display: block;
103
+ visibility: hidden;
104
+ height: 0;
105
+ clear: both;
106
+ content: ".";
107
+ }
108
+ .sw-click-to-tweet a {
109
+ text-decoration: none;
110
+ text-transform: none;
111
+ }
112
+ .sw-click-to-tweet a:hover {
113
+ text-decoration: none;
114
+ }
115
+ .sw-click-to-tweet .sw-ctt-text {
116
+ margin: 0;
117
+ padding: 0;
118
+ position: relative;
119
+ margin-bottom: 10px;
120
+ word-wrap: break-word;
121
+ }
122
+ a .sw-click-to-tweet .sw-ctt-text {
123
+ margin: 0;
124
+ padding: 0;
125
+ position: relative;
126
+ color: #777;
127
+ font-size: 24px;
128
+ line-height: 140%;
129
+ text-transform: none;
130
+ font-weight: 500;
131
+ text-decoration: none;
132
+ text-transform: none;
133
+ font-style: italic;
134
+ display:block;
135
+ }
136
+ a:hover .sw-click-to-tweet .sw-ctt-text {
137
+ text-decoration: none;
138
+ color: #666666;
139
+ }
140
+ .sw-click-to-tweet .sw-ctt-btn {
141
+ margin: 0;
142
+ padding: 3px;
143
+ position: relative;
144
+ display: block;
145
+ text-transform: uppercase;
146
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
147
+ font-size: 12px;
148
+ font-weight: bold;
149
+ line-height: 100%;
150
+ color: #999999;
151
+ float: right;
152
+ padding-right: 24px;
153
+ text-decoration: none;
154
+ background: transparent url("//4.bp.blogspot.com/-Ku-iYrKVffw/VHjB2LFSO1I/AAAAAAAAEyI/NDiWlshts4M/s1600/twitter-little-bird.png") no-repeat right top;
155
+ }
156
+ a:hover .sw-click-to-tweet .sw-ctt-btn{
157
+ text-decoration: none;
158
+ color: #666666;
159
+ text-transform: uppercase;
160
+ }
161
+ .sw-click-to-tweet .sw-powered-by {
162
+ font-size: 10px;
163
+ color: #999999;
164
+ }
165
+ .sw-click-to-tweet .sw-powered-by a {
166
+ font-size: 10px;
167
+ color: #999999 !important;
168
+ }
169
+ .sw-click-to-tweet .sw-powered-by a:hover {
170
+ color: #999999 !important;
171
+ text-decoration: underline !important;
172
+ }
functions/click-to-tweet/assets/css/style3.css ADDED
@@ -0,0 +1,164 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .sw-tweet-clear {
2
+ zoom: 1;
3
+ }
4
+ .sw-tweet-clear:after {
5
+ display: block;
6
+ visibility: hidden;
7
+ height: 0;
8
+ clear: both;
9
+ content: ".";
10
+ }
11
+ .sw-click-to-tweet {
12
+ display: block;
13
+ background-color: #60A8DC;
14
+ margin: 0;
15
+ padding: 0;
16
+ position: relative;
17
+ padding: 30px 30px;
18
+ margin: 15px 0px;
19
+ zoom: 1;
20
+ border-left:0px solid #60A8DC;
21
+ transition: all 0.3s ease-in-out;
22
+ }
23
+ .sw-click-to-tweet:hover {
24
+ background: #5696C4;
25
+ border-left: 10px solid #60A8DC;
26
+ transition: all 0.3s ease-in-out;
27
+ }
28
+ .sw-click-to-tweet .clearfix {
29
+ zoom: 1;
30
+ }
31
+ .sw-click-to-tweet .clearfix:after {
32
+ display: block;
33
+ visibility: hidden;
34
+ height: 0;
35
+ clear: both;
36
+ content: ".";
37
+ }
38
+ .sw-click-to-tweet .clear {
39
+ clear: both;
40
+ }
41
+ .sw-click-to-tweet .f-left {
42
+ float: left;
43
+ display: inline-block;
44
+ position: relative;
45
+ }
46
+ .sw-click-to-tweet .f-right {
47
+ float: right;
48
+ display: inline-block;
49
+ position: relative;
50
+ }
51
+ .sw-click-to-tweet .list-reset {
52
+ list-style: none;
53
+ margin: 0;
54
+ padding: 0;
55
+ }
56
+ .sw-click-to-tweet .list-reset li {
57
+ list-style: none;
58
+ margin: 0;
59
+ padding: 0;
60
+ }
61
+ .sw-click-to-tweet .list-float {
62
+ zoom: 1;
63
+ }
64
+ .sw-click-to-tweet .list-float:after {
65
+ display: block;
66
+ visibility: hidden;
67
+ height: 0;
68
+ clear: both;
69
+ content: ".";
70
+ }
71
+ .sw-click-to-tweet .list-float li {
72
+ float: left;
73
+ display: inline-block;
74
+ }
75
+ .sw-click-to-tweet .kill-box-shadow {
76
+ box-shadow: none;
77
+ -webkit-box-shadow: none;
78
+ -moz-box-shadow: none;
79
+ }
80
+ .sw-click-to-tweet .alignright {
81
+ float: right;
82
+ margin-bottom: 10px;
83
+ margin-left: 10px;
84
+ text-align: right;
85
+ }
86
+ .sw-click-to-tweet .alignleft {
87
+ float: left;
88
+ margin-bottom: 10px;
89
+ margin-right: 10px;
90
+ text-align: right;
91
+ }
92
+ .sw-click-to-tweet:after {
93
+ content: ".";
94
+ display: block;
95
+ clear: both;
96
+ visibility: hidden;
97
+ line-height: 0;
98
+ height: 0;
99
+ }
100
+ .sw-click-to-tweet .sw-ctt-reset {
101
+ margin: 0;
102
+ padding: 0;
103
+ position: relative;
104
+ }
105
+ .sw-click-to-tweet:after {
106
+ display: block;
107
+ visibility: hidden;
108
+ height: 0;
109
+ clear: both;
110
+ content: ".";
111
+ }
112
+ .sw-click-to-tweet a {
113
+ text-decoration: none;
114
+ text-transform: none;
115
+ }
116
+ .sw-click-to-tweet a:hover {
117
+ text-decoration: none;
118
+ }
119
+ .sw-click-to-tweet .sw-ctt-text {
120
+ margin: 0;
121
+ padding: 0;
122
+ position: relative;
123
+ margin-bottom: 10px;
124
+ word-wrap: break-word;
125
+ }
126
+ a .sw-click-to-tweet .sw-ctt-text {
127
+ margin: 0;
128
+ padding: 0;
129
+ position: relative;
130
+ color: #FFF;
131
+ font-size: 24px;
132
+ line-height: 140%;
133
+ text-transform: none;
134
+ font-weight: 500;
135
+ text-decoration: none;
136
+ text-transform: none;
137
+ font-style: italic;
138
+ display:block;
139
+ }
140
+ a:hover .sw-click-to-tweet .sw-ctt-text {
141
+ text-decoration: none;
142
+ color: #FFF;
143
+ }
144
+ .sw-click-to-tweet .sw-ctt-btn {
145
+ margin: 0;
146
+ padding: 3px;
147
+ position: relative;
148
+ display: block;
149
+ text-transform: uppercase;
150
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
151
+ font-size: 12px;
152
+ font-weight: bold;
153
+ line-height: 100%;
154
+ color: #FFF;
155
+ float: right;
156
+ padding-right: 24px;
157
+ text-decoration: none;
158
+ background: rgba(0, 0, 0, 0) url("//4.bp.blogspot.com/-JsBK9mPEjWo/VHjB2OUI-uI/AAAAAAAAEyA/NteFI3uXm9U/s1600/twitter-little-bird-white.png") no-repeat right top;
159
+ }
160
+ a:hover .sw-click-to-tweet .sw-ctt-btn {
161
+ text-decoration: none;
162
+ color: #FFF;
163
+ text-transform: uppercase;
164
+ }
functions/click-to-tweet/assets/css/style4.css ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .sw-CTT {
2
+ display:block;
3
+ }
4
+ .sw-tweet-clear {
5
+ zoom: 1;
6
+ }
7
+ .sw-tweet-clear:after {
8
+ display: block;
9
+ visibility: hidden;
10
+ height: 0;
11
+ clear: both;
12
+ content: ".";
13
+ }
14
+ .sw-click-to-tweet {
15
+ display: block;
16
+ background: #333;
17
+ margin: 0;
18
+ padding: 0;
19
+ position: relative;
20
+ padding: 30px 30px;
21
+ margin: 15px 0px;
22
+ zoom: 1;
23
+ border-left:0px solid #60A8DC;
24
+ border-left: 10px solid #C33;
25
+ transition: all 0.3s ease-in-out;
26
+ }
27
+ .sw-click-to-tweet:hover {
28
+ background: #222;
29
+ transition: all 0.3s ease-in-out;
30
+ }
31
+ .sw-click-to-tweet .clearfix {
32
+ zoom: 1;
33
+ }
34
+ .sw-click-to-tweet .clearfix:after {
35
+ display: block;
36
+ visibility: hidden;
37
+ height: 0;
38
+ clear: both;
39
+ content: ".";
40
+ }
41
+ .sw-click-to-tweet .clear {
42
+ clear: both;
43
+ }
44
+ .sw-click-to-tweet .f-left {
45
+ float: left;
46
+ display: inline-block;
47
+ position: relative;
48
+ }
49
+ .sw-click-to-tweet .f-right {
50
+ float: right;
51
+ display: inline-block;
52
+ position: relative;
53
+ }
54
+ .sw-click-to-tweet .list-reset {
55
+ list-style: none;
56
+ margin: 0;
57
+ padding: 0;
58
+ }
59
+ .sw-click-to-tweet .list-reset li {
60
+ list-style: none;
61
+ margin: 0;
62
+ padding: 0;
63
+ }
64
+ .sw-click-to-tweet .list-float {
65
+ zoom: 1;
66
+ }
67
+ .sw-click-to-tweet .list-float:after {
68
+ display: block;
69
+ visibility: hidden;
70
+ height: 0;
71
+ clear: both;
72
+ content: ".";
73
+ }
74
+ .sw-click-to-tweet .list-float li {
75
+ float: left;
76
+ display: inline-block;
77
+ }
78
+ .sw-click-to-tweet .kill-box-shadow {
79
+ box-shadow: none;
80
+ -webkit-box-shadow: none;
81
+ -moz-box-shadow: none;
82
+ }
83
+ .sw-click-to-tweet .alignright {
84
+ float: right;
85
+ margin-bottom: 10px;
86
+ margin-left: 10px;
87
+ text-align: right;
88
+ }
89
+ .sw-click-to-tweet .alignleft {
90
+ float: left;
91
+ margin-bottom: 10px;
92
+ margin-right: 10px;
93
+ text-align: right;
94
+ }
95
+ .sw-click-to-tweet:after {
96
+ content: ".";
97
+ display: block;
98
+ clear: both;
99
+ visibility: hidden;
100
+ line-height: 0;
101
+ height: 0;
102
+ }
103
+ .sw-click-to-tweet .sw-ctt-reset {
104
+ margin: 0;
105
+ padding: 0;
106
+ position: relative;
107
+ }
108
+ .sw-click-to-tweet:after {
109
+ display: block;
110
+ visibility: hidden;
111
+ height: 0;
112
+ clear: both;
113
+ content: ".";
114
+ }
115
+ a.sw_CTT {
116
+ text-decoration: none;
117
+ text-transform: none;
118
+ }
119
+ a.sw_CTT:hover {
120
+ text-decoration: none;
121
+ }
122
+ .sw-click-to-tweet .sw-ctt-text {
123
+ margin: 0;
124
+ padding: 0;
125
+ position: relative;
126
+ margin-bottom: 10px;
127
+ word-wrap: break-word;
128
+ }
129
+ a .sw-click-to-tweet .sw-ctt-text {
130
+ margin: 0;
131
+ padding: 0;
132
+ position: relative;
133
+ color: #FFF;
134
+ font-size: 24px;
135
+ line-height: 140%;
136
+ text-transform: none;
137
+ font-weight: 500;
138
+ text-decoration: none;
139
+ text-transform: none;
140
+ font-style: normal;
141
+ display:block;
142
+ }
143
+ a:hover .sw-click-to-tweet .sw-ctt-text {
144
+ text-decoration: none;
145
+ color: #FFF;
146
+ }
147
+ .sw-click-to-tweet .sw-ctt-btn {
148
+ margin: 0;
149
+ padding: 3px;
150
+ position: relative;
151
+ display: block;
152
+ text-transform: uppercase;
153
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
154
+ font-size: 12px;
155
+ font-weight: bold;
156
+ line-height: 100%;
157
+ color: #FFF;
158
+ float: right;
159
+ padding-right: 24px;
160
+ text-decoration: none;
161
+ background: rgba(0, 0, 0, 0) url("//4.bp.blogspot.com/-JsBK9mPEjWo/VHjB2OUI-uI/AAAAAAAAEyA/NteFI3uXm9U/s1600/twitter-little-bird-white.png") no-repeat right top;
162
+ }
163
+ .sw-click-to-tweet .sw-ctt-btn:hover {
164
+ text-decoration: none;
165
+ color: #FFF;
166
+ text-transform: uppercase;
167
+ }
functions/click-to-tweet/assets/css/styles.css ADDED
@@ -0,0 +1,170 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .tm-tweet-clear {
2
+ zoom: 1;
3
+ }
4
+ .tm-tweet-clear:after {
5
+ display: block;
6
+ visibility: hidden;
7
+ height: 0;
8
+ clear: both;
9
+ content: ".";
10
+ }
11
+ .tm-click-to-tweet {
12
+ display: block;
13
+ background-color: #fff;
14
+ margin: 0;
15
+ padding: 0;
16
+ position: relative;
17
+ border: 1px solid #dddddd;
18
+ -moz-border-radius: 4px;
19
+ border-radius: 4px;
20
+ padding: 15px 30px;
21
+ margin: 15px 0px;
22
+ zoom: 1;
23
+ }
24
+ .tm-click-to-tweet .clearfix {
25
+ zoom: 1;
26
+ }
27
+ .tm-click-to-tweet .clearfix:after {
28
+ display: block;
29
+ visibility: hidden;
30
+ height: 0;
31
+ clear: both;
32
+ content: ".";
33
+ }
34
+ .tm-click-to-tweet .clear {
35
+ clear: both;
36
+ }
37
+ .tm-click-to-tweet .f-left {
38
+ float: left;
39
+ display: inline-block;
40
+ position: relative;
41
+ }
42
+ .tm-click-to-tweet .f-right {
43
+ float: right;
44
+ display: inline-block;
45
+ position: relative;
46
+ }
47
+ .tm-click-to-tweet .list-reset {
48
+ list-style: none;
49
+ margin: 0;
50
+ padding: 0;
51
+ }
52
+ .tm-click-to-tweet .list-reset li {
53
+ list-style: none;
54
+ margin: 0;
55
+ padding: 0;
56
+ }
57
+ .tm-click-to-tweet .list-float {
58
+ zoom: 1;
59
+ }
60
+ .tm-click-to-tweet .list-float:after {
61
+ display: block;
62
+ visibility: hidden;
63
+ height: 0;
64
+ clear: both;
65
+ content: ".";
66
+ }
67
+ .tm-click-to-tweet .list-float li {
68
+ float: left;
69
+ display: inline-block;
70
+ }
71
+ .tm-click-to-tweet .kill-box-shadow {
72
+ box-shadow: none;
73
+ -webkit-box-shadow: none;
74
+ -moz-box-shadow: none;
75
+ }
76
+ .tm-click-to-tweet .alignright {
77
+ float: right;
78
+ margin-bottom: 10px;
79
+ margin-left: 10px;
80
+ text-align: right;
81
+ }
82
+ .tm-click-to-tweet .alignleft {
83
+ float: left;
84
+ margin-bottom: 10px;
85
+ margin-right: 10px;
86
+ text-align: right;
87
+ }
88
+ .tm-click-to-tweet:after {
89
+ content: ".";
90
+ display: block;
91
+ clear: both;
92
+ visibility: hidden;
93
+ line-height: 0;
94
+ height: 0;
95
+ }
96
+ .tm-click-to-tweet .tm-ctt-reset {
97
+ margin: 0;
98
+ padding: 0;
99
+ position: relative;
100
+ }
101
+ .tm-click-to-tweet:after {
102
+ display: block;
103
+ visibility: hidden;
104
+ height: 0;
105
+ clear: both;
106
+ content: ".";
107
+ }
108
+ .tm-click-to-tweet a {
109
+ text-decoration: none;
110
+ text-transform: none;
111
+ }
112
+ .tm-click-to-tweet a:hover {
113
+ text-decoration: none;
114
+ }
115
+ .tm-click-to-tweet .tm-ctt-text {
116
+ margin: 0;
117
+ padding: 0;
118
+ position: relative;
119
+ margin-bottom: 10px;
120
+ word-wrap: break-word;
121
+ }
122
+ .tm-click-to-tweet .tm-ctt-text a {
123
+ margin: 0;
124
+ padding: 0;
125
+ position: relative;
126
+ color: #999999;
127
+ font-size: 24px;
128
+ line-height: 140%;
129
+ text-transform: none;
130
+ font-weight: 500;
131
+ text-decoration: none;
132
+ text-transform: none;
133
+ }
134
+ .tm-click-to-tweet .tm-ctt-text a:hover {
135
+ text-decoration: none;
136
+ color: #666666;
137
+ }
138
+ .tm-click-to-tweet a.tm-ctt-btn {
139
+ margin: 0;
140
+ padding: 0;
141
+ position: relative;
142
+ display: block;
143
+ text-transform: uppercase;
144
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
145
+ font-size: 12px;
146
+ font-weight: bold;
147
+ line-height: 100%;
148
+ color: #999999;
149
+ float: right;
150
+ padding-right: 24px;
151
+ text-decoration: none;
152
+ background: transparent url(../img/twitter-little-bird.png) no-repeat right top;
153
+ }
154
+ .tm-click-to-tweet a.tm-ctt-btn:hover {
155
+ text-decoration: none;
156
+ color: #666666;
157
+ text-transform: uppercase;
158
+ }
159
+ .tm-click-to-tweet .tm-powered-by {
160
+ font-size: 10px;
161
+ color: #999999;
162
+ }
163
+ .tm-click-to-tweet .tm-powered-by a {
164
+ font-size: 10px;
165
+ color: #999999 !important;
166
+ }
167
+ .tm-click-to-tweet .tm-powered-by a:hover {
168
+ color: #999999 !important;
169
+ text-decoration: underline !important;
170
+ }
functions/click-to-tweet/assets/img/twitter-little-bird-button.png ADDED
Binary file
functions/click-to-tweet/assets/img/twitter-little-bird-white.png ADDED
Binary file
functions/click-to-tweet/assets/img/twitter-little-bird.png ADDED
Binary file
functions/click-to-tweet/assets/js/clickToTweet.js ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function() {
2
+ tinymce.PluginManager.add('clickToTweet', function( editor, url ) {
3
+ editor.addButton( 'clickToTweet', {
4
+ title: 'Click to Tweet by Social Warfare',
5
+ icon: 'sw sw sw-twitter',
6
+ onclick: function() {
7
+ editor.windowManager.open( {
8
+ title: 'Build Your "Click to Tweet"',
9
+ class: 'sw_ctt',
10
+ body: [
11
+ {
12
+ type: 'textbox',
13
+ multiline: true,
14
+ style: 'height:50px',
15
+ name: 'tweet',
16
+ label: 'The Tweet that will be sent out on Twitter.',
17
+ onkeyup: function() {
18
+ var value = jQuery('.mce-first textarea').val();
19
+ var strLength = value.length;
20
+ var handle = jQuery('#socialWarfare .twitterID label').html();
21
+ if(typeof handle === 'undefined') {
22
+ var remaining = 140 - value.length - 23;
23
+ } else {
24
+ var remaining = 140 - value.length - handle.length - 23 - 6;
25
+ }
26
+ if(remaining > 1 || remaining == 0) {
27
+ jQuery('.tweetCounter').css({'color':'green'}).text(remaining + ' characters');
28
+ } else if (remaining == 1) {
29
+ jQuery('.tweetCounter').css({'color':'green'}).text(remaining + ' character');
30
+ } else if (remaining < 0) {
31
+ jQuery('.tweetCounter').css({'color':'red'}).text(remaining + ' characters');
32
+ }
33
+ },
34
+ class: 'tweetCounting'
35
+ },
36
+ {
37
+ type: 'label',
38
+ name: 'someHelpText',
39
+ onPostRender : function() {
40
+ var value = jQuery('.mce-first textarea').val();
41
+ var strLength = value.length;
42
+ var handle = jQuery('#socialWarfare .twitterID label').html();
43
+ if(typeof handle === 'undefined') {
44
+ var remaining = 140 - value.length - 23;
45
+ } else {
46
+ var remaining = 140 - value.length - handle.length - 23 - 6;
47
+ }
48
+ this.getEl().innerHTML =
49
+ '<span style="float:right;">You have <span class="tweetCounter" style="color:green">'+remaining+' characters</span> remaining.</span>';},
50
+ text: ''},
51
+ {
52
+ type: 'textbox',
53
+ multiline: true,
54
+ style: 'height:50px',
55
+ name: 'quote',
56
+ label: 'The quote as it will appear in your article.'
57
+ },{
58
+ type: 'label',
59
+ name: 'someHelpText2',
60
+ onPostRender : function() {
61
+ this.getEl().innerHTML =
62
+ '<div style="width:650px;">&nbsp;</div>';},
63
+ text: ''},
64
+
65
+ {type: 'listbox',
66
+ name: 'theme',
67
+ label: 'Visual Theme',
68
+ 'values': [
69
+ {text: 'Default', value: 'default'},
70
+ {text: 'Send Her My Love', value: 'style1'},
71
+ {text: 'Roll With The Changes', value: 'style2'},
72
+ {text: 'Free Bird', value: 'style3'},
73
+ {text: 'Don\'t Stop Believin\'', value: 'style4'},
74
+ {text: 'Thunderstruck', value: 'style5'},
75
+ {text: 'Livin\' On A Prayer', value: 'style6'},
76
+ ],
77
+ },
78
+ ],
79
+ onsubmit: function( e ) {
80
+ var value = jQuery('.mce-first textarea').val();
81
+ var strLength = value.length;
82
+ var remaining = 117 - strLength;
83
+ if(e.data.tweet === '' || e.data.quote === '') {
84
+ editor.windowManager.alert('Please, fill in both fields.');
85
+ return false;
86
+ } else if(remaining < 0) {
87
+ editor.windowManager.alert('You have too many characters in your tweet.');
88
+ return false;
89
+ }
90
+ if(e.data.theme == 'default') {
91
+ editor.insertContent( '[clickToTweet tweet="' + e.data.tweet.replace(/"/g,'\'') + '" quote="' + e.data.quote.replace(/"/g,'\'') + '"]');
92
+ } else {
93
+ editor.insertContent( '[clickToTweet tweet="' + e.data.tweet.replace(/"/g,'\'') + '" quote="' + e.data.quote.replace(/"/g,'\'') + '" theme="'+ e.data.theme +'"]');
94
+ }
95
+ }
96
+ });
97
+ }
98
+ });
99
+ });
100
+ })();
functions/click-to-tweet/assets/js/tmclicktotweet_plugin.js ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function() {
2
+ tinymce.create('tinymce.plugins.TMClickToTweet', {
3
+ init: function(ed, url) {
4
+ ed.addButton('tmclicktotweet', {
5
+ title: 'tmclicktotweet.quickaddd',
6
+ image: url.replace("/js", "") + '/img/twitter-little-bird-button.png',
7
+ onclick: function() {
8
+ var m = prompt("Click To Tweet", "Enter your tweets");
9
+ if (m != null && m != 'undefined' && m != 'Enter your tweets' && m != '') ed.execCommand('mceInsertContent', false, '[Tweet "' + m + '"]');
10
+ }
11
+ });
12
+ },
13
+ createControl: function(n, cm) {
14
+ return null;
15
+ },
16
+ getInfo: function() {
17
+ return {
18
+ longname: "Click To Tweet by Todaymade",
19
+ author: 'Todaymade',
20
+ authorurl: 'http://coschedule.com/',
21
+ infourl: 'http://coschedule.com/click-to-tweet',
22
+ version: "1.0"
23
+ };
24
+ }
25
+ });
26
+ tinymce.PluginManager.add('tmclicktotweet', tinymce.plugins.TMClickToTweet);
27
+ })();
functions/click-to-tweet/clickToTweet.php ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! class_exists( 'clickToTweet' ) ) {
4
+
5
+ class clickToTweet {
6
+
7
+ public function __construct() {
8
+ $this->clickToTweet();
9
+ }
10
+
11
+ public function clickToTweet() {
12
+ register_activation_hook( __FILE__, array( __CLASS__, 'activation' ) );
13
+ register_deactivation_hook( __FILE__, array( __CLASS__, 'deactivation' ) );
14
+
15
+ if(is_admin()) {
16
+ $this->register_admin_hooks();
17
+ }
18
+ }
19
+
20
+ public function debug($array) {
21
+ echo '<pre>';
22
+ print_r($array);
23
+ echo '</pre>';
24
+ }
25
+
26
+ public function activation() {
27
+ register_uninstall_hook( __FILE__, array( __CLASS__, 'uninstall' ) );
28
+ }
29
+
30
+ public function deactivation() {
31
+
32
+ }
33
+
34
+ public function register_admin_hooks() {
35
+ add_filter('tiny_mce_version', array($this, 'refresh_mce'));
36
+ add_action('init', array($this, 'tinymce_button'));
37
+ }
38
+
39
+ public function tinymce_button() {
40
+ if (!current_user_can('edit_posts') && !current_user_can('edit_pages')) {
41
+ return;
42
+ }
43
+
44
+ if (get_user_option('rich_editing') == 'true') {
45
+ add_filter('mce_external_plugins', array($this, 'tinymce_register_plugin'));
46
+ add_filter('mce_buttons', array($this, 'tinymce_register_button'));
47
+ }
48
+ }
49
+
50
+ public function tinymce_register_button($buttons) {
51
+ array_push($buttons, "|", "clickToTweet");
52
+ return $buttons;
53
+ }
54
+
55
+ public function tinymce_register_plugin($plugin_array) {
56
+ $plugin_array['clickToTweet'] = plugins_url( '/assets/js/clickToTweet.js', __FILE__);
57
+ return $plugin_array;
58
+ }
59
+
60
+ public function register_settings() {
61
+ register_setting('tmclicktotweet-options', 'twitter-handle', array($this, 'validate_settings'));
62
+ }
63
+
64
+ public function validate_settings($input) {
65
+ return str_replace('@', '', strip_tags(stripslashes($input)));
66
+ }
67
+
68
+ public function refresh_mce($ver) {
69
+ $ver += 3;
70
+ return $ver;
71
+ }
72
+ }
73
+
74
+ new clickToTweet();
75
+
76
+ }
77
+
78
+ function clickToTweetShortcode( $atts ){
79
+ $url = sw_process_url( get_permalink() , 'twitter' , get_the_ID() );
80
+ $options = sw_get_user_options();
81
+ $user_twitter_handle = get_post_meta( get_the_ID() , 'sw_twitter_username' , true );
82
+ if(!$user_twitter_handle):
83
+ $user_twitter_handle = $options['twitterID'];
84
+ endif;
85
+
86
+ if(isset($atts['theme']) && $atts['theme'] != 'default'):
87
+ $theme = $atts['theme'];
88
+ else:
89
+ $theme = $options['cttTheme'];
90
+ endif;
91
+
92
+ return '
93
+ <div class="sw-tweet-clear"></div>
94
+ <a class="sw_CTT '.$theme.'" href="https://twitter.com/share?text='.urlencode(html_entity_decode($atts['tweet'], ENT_COMPAT, 'UTF-8')).'&url='.$url.''.($options['twitterID'] ? '&via='.$options['twitterID'] : '').'" data-link="https://twitter.com/share?text='.urlencode(html_entity_decode($atts['tweet'], ENT_COMPAT, 'UTF-8')).'&url='.$url.''.($user_twitter_handle ? '&via='.$user_twitter_handle : '').'" target="_blank"><span class="sw-click-to-tweet"><span class="sw-ctt-text">'.$atts['quote'].'</span><span class="sw-ctt-btn">Click To Tweet<i class="sw sw-twitter"></i></span></span></a>';
95
+ }
96
+
97
+ add_shortcode( 'clickToTweet', 'clickToTweetShortcode' );
98
+
99
+ ?>
functions/curl_functions.php ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*****************************************************************
3
+ * *
4
+ * cURL - A Function to Process cURL requests *
5
+ * *
6
+ ******************************************************************/
7
+
8
+ function sw_fetch_shares_via_curl_multi($data, $options = array()) {
9
+
10
+ // array of curl handles
11
+ $curly = array();
12
+ // data to be returned
13
+ $result = array();
14
+
15
+ // multi handle
16
+ $mh = curl_multi_init();
17
+
18
+ // loop through $data and create curl handles
19
+ // then add them to the multi-handle
20
+
21
+ foreach ($data as $id => $d) {
22
+
23
+ if($d !== 0 || $id == 'googlePlus'):
24
+
25
+ $curly[$id] = curl_init();
26
+
27
+ if($id == 'googlePlus'):
28
+
29
+ curl_setopt($curly[$id], CURLOPT_URL, "https://clients6.google.com/rpc");
30
+ curl_setopt($curly[$id], CURLOPT_POST, true);
31
+ curl_setopt($curly[$id], CURLOPT_SSL_VERIFYPEER, false);
32
+ curl_setopt($curly[$id], CURLOPT_POSTFIELDS, '[{"method":"pos.plusones.get","id":"p","params":{"nolog":true,"id":"'.rawurldecode($d).'","source":"widget","userId":"@viewer","groupId":"@self"},"jsonrpc":"2.0","key":"p","apiVersion":"v1"}]');
33
+ curl_setopt($curly[$id], CURLOPT_RETURNTRANSFER, true);
34
+ curl_setopt($curly[$id], CURLOPT_HTTPHEADER, array('Content-type: application/json'));
35
+
36
+ else:
37
+
38
+ $url = (is_array($d) && !empty($d['url'])) ? $d['url'] : $d;
39
+ curl_setopt($curly[$id], CURLOPT_URL, $url);
40
+ curl_setopt($curly[$id], CURLOPT_HEADER, 0);
41
+ curl_setopt($curly[$id], CURLOPT_RETURNTRANSFER, 1);
42
+ curl_setopt($curly[$id], CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
43
+ curl_setopt($curly[$id], CURLOPT_FAILONERROR, 0);
44
+ curl_setopt($curly[$id], CURLOPT_FOLLOWLOCATION, 0);
45
+ curl_setopt($curly[$id], CURLOPT_RETURNTRANSFER,1);
46
+ curl_setopt($curly[$id], CURLOPT_SSL_VERIFYPEER, false);
47
+ curl_setopt($curly[$id], CURLOPT_SSL_VERIFYHOST, false);
48
+ curl_setopt($curly[$id], CURLOPT_TIMEOUT, 5);
49
+ curl_setopt($curly[$id], CURLOPT_CONNECTTIMEOUT, 5);
50
+ curl_setopt($curly[$id], CURLOPT_NOSIGNAL, 1);
51
+ curl_setopt($curly[$id], CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
52
+ // curl_setopt($curly[$id], CURLOPT_SSLVERSION, CURL_SSLVERSION_SSLv3);
53
+
54
+ endif;
55
+
56
+ // extra options?
57
+ if (!empty($options)) {
58
+ curl_setopt_array($curly[$id], $options);
59
+ }
60
+
61
+ curl_multi_add_handle($mh, $curly[$id]);
62
+
63
+ endif;
64
+ }
65
+
66
+ // execute the handles
67
+ $running = NULL;
68
+ do {
69
+ curl_multi_exec($mh, $running);
70
+ } while($running > 0);
71
+
72
+
73
+ // get content and remove handles
74
+ foreach($curly as $id => $c) {
75
+ $result[$id] = curl_multi_getcontent($c);
76
+ curl_multi_remove_handle($mh, $c);
77
+ }
78
+
79
+ // all done
80
+ curl_multi_close($mh);
81
+
82
+ return $result;
83
+ }
84
+
85
+ function sw_file_get_contents_curl($url){
86
+ $ch=curl_init();
87
+ curl_setopt($ch, CURLOPT_URL, $url);
88
+ curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
89
+ curl_setopt($ch, CURLOPT_FAILONERROR, 0);
90
+ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
91
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
92
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
93
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
94
+ curl_setopt($ch, CURLOPT_TIMEOUT, 5);
95
+ curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
96
+ curl_setopt($ch, CURLOPT_NOSIGNAL, 1);
97
+ curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
98
+ $cont = @curl_exec($ch);
99
+ $curl_errno = curl_errno($ch);
100
+ curl_close($ch);
101
+ if ($curl_errno > 0) {
102
+ return 0;
103
+ }
104
+ return $cont;
105
+ }
106
+
functions/excerpt.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*****************************************************************
4
+ * *
5
+ * AN EXCERPT FUNCTION *
6
+ * *
7
+ ******************************************************************/
8
+
9
+ // A function to process the excerpts for descriptions
10
+ function sw_get_excerpt_by_id($post_id){
11
+
12
+ // Check if the post has an excerpt
13
+ if(has_excerpt()):
14
+ $the_post = get_post($post_id); //Gets post ID
15
+ $the_excerpt = $the_post->post_excerpt;
16
+
17
+ // If not, let's create an excerpt
18
+ else:
19
+ $the_post = get_post($post_id); //Gets post ID
20
+ $the_excerpt = $the_post->post_content; //Gets post_content to be used as a basis for the excerpt
21
+ endif;
22
+
23
+ $excerpt_length = 100; //Sets excerpt length by word count
24
+ $the_excerpt = strip_tags(strip_shortcodes($the_excerpt)); //Strips tags and images
25
+
26
+ $the_excerpt = str_replace(']]>', ']]&gt;', $the_excerpt);
27
+ $the_excerpt = strip_tags($the_excerpt);
28
+ $excerpt_length = apply_filters('excerpt_length', 100);
29
+ $excerpt_more = apply_filters('excerpt_more', ' ' . '[...]');
30
+ $words = preg_split("/[\n\r\t ]+/", $the_excerpt, $excerpt_length + 1, PREG_SPLIT_NO_EMPTY);
31
+
32
+ if(count($words) > $excerpt_length) :
33
+ array_pop($words);
34
+ // array_push($words, '…');
35
+ $the_excerpt = implode(' ', $words);
36
+ endif;
37
+
38
+ $the_excerpt = preg_replace( "/\r|\n/", "", $the_excerpt );
39
+
40
+ return $the_excerpt;
41
+ }
functions/header-meta-tags.php ADDED
@@ -0,0 +1,660 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Queue up our hook function
4
+ add_action( 'wp_head' , 'sw_add_header_meta' , 1 );
5
+
6
+ /*****************************************************************
7
+ * *
8
+ * Curly Quote Converter *
9
+ * *
10
+ ******************************************************************/
11
+ function convert_smart_quotes($content) {
12
+ $content = str_replace('"', '\'', $content);
13
+ $content = str_replace('&#8220;', '\'', $content);
14
+ $content = str_replace('&#8221;', '\'', $content);
15
+ $content = str_replace('&#8216;', '\'', $content);
16
+ $content = str_replace('&#8217;', '\'', $content);
17
+ return $content;
18
+ }
19
+ /*****************************************************************
20
+ * *
21
+ * Easy Hook Remover *
22
+ * *
23
+ ******************************************************************/
24
+ function sw_remove_filter($hook_name = '', $method_name = '', $priority = 0 ) {
25
+ global $wp_filter;
26
+
27
+ // Take only filters on right hook name and priority
28
+ if ( !isset($wp_filter[$hook_name][$priority]) || !is_array($wp_filter[$hook_name][$priority]) )
29
+ return false;
30
+
31
+ // Loop on filters registered
32
+ foreach( (array) $wp_filter[$hook_name][$priority] as $unique_id => $filter_array ) {
33
+ // Test if filter is an array ! (always for class/method)
34
+ if ( isset($filter_array['function']) && is_array($filter_array['function']) ) {
35
+ // Test if object is a class and method is equal to param !
36
+ if ( is_object($filter_array['function'][0]) && get_class($filter_array['function'][0]) && $filter_array['function'][1] == $method_name ) {
37
+ unset($wp_filter[$hook_name][$priority][$unique_id]);
38
+ }
39
+ }
40
+
41
+ }
42
+
43
+ return false;
44
+ }
45
+
46
+ /*****************************************************************
47
+ * *
48
+ * HEADER META DATA *
49
+ * *
50
+ ******************************************************************/
51
+
52
+ // This is the hook function we're adding the header
53
+ function sw_add_header_meta() {
54
+
55
+ $info['postID'] = get_the_ID();
56
+
57
+ // Cache some resource for fewer queries on subsequent page loads
58
+ if(sw_is_cache_fresh($info['postID']) == false):
59
+
60
+ // Check if an image ID has been provided
61
+ $info['imageID'] = get_post_meta( $info['postID'] , 'nc_ogImage' , true );
62
+ if($info['imageID']):
63
+ $info['imageURL'] = wp_get_attachment_url( $info['imageID'] );
64
+ delete_post_meta($info['postID'],'sw_open_graph_image_url');
65
+ update_post_meta($info['postID'],'sw_open_graph_image_url',$info['imageURL']);
66
+ else:
67
+ $info['imageURL'] = wp_get_attachment_url( get_post_thumbnail_id( $info['postID'] ) );
68
+ delete_post_meta($info['postID'],'sw_open_thumbnail_url');
69
+ update_post_meta($info['postID'],'sw_open_thumbnail_url' , $info['imageURL']);
70
+ delete_post_meta($info['postID'],'sw_open_graph_image_url');
71
+ endif;
72
+
73
+ // Cache the Twitter Handle
74
+ $user_twitter_handle = get_the_author_meta( 'sw_twitter' , sw_get_author($info['postID']));
75
+ if($user_twitter_handle):
76
+ delete_post_meta($info['postID'],'sw_twitter_username');
77
+ update_post_meta($info['postID'],'sw_twitter_username',$user_twitter_handle);
78
+ else:
79
+ delete_post_meta($info['postID'],'sw_twitter_username');
80
+ endif;
81
+
82
+ else:
83
+
84
+ // Check if we have a cached Open Graph Image URL
85
+ $info['imageURL'] = get_post_meta( $info['postID'] , 'sw_open_graph_image_url' , true );
86
+
87
+ // If not, let's check to see if we have an ID to generate one
88
+ if(!$info['imageURL']):
89
+
90
+ // Check for an Open Graph Image ID
91
+ $info['imageID'] = get_post_meta( $info['postID'] , 'nc_ogImage' , true );
92
+ if($info['imageID']):
93
+
94
+ // If we find one, let's convert it to a link and cache it for next time
95
+ $info['imageURL'] = wp_get_attachment_url( $info['imageID'] );
96
+ delete_post_meta($info['postID'],'sw_open_graph_image_url');
97
+ update_post_meta($info['postID'],'sw_open_graph_image_url',$info['imageURL']);
98
+
99
+ else:
100
+
101
+ // If we don't find one, let's save the URL of the thumbnail in case we need it
102
+ $thumbnail_image = get_post_meta($info['postID'],'sw_open_thumbnail_url' , true);
103
+ endif;
104
+ endif;
105
+
106
+
107
+ $user_twitter_handle = get_post_meta( $info['postID'] , 'sw_twitter_username' , true );
108
+
109
+ endif;
110
+
111
+ // Create the image Open Graph Meta Tag
112
+ $info['postID'] = get_the_ID();
113
+ $info['title'] = htmlspecialchars( get_post_meta( $info['postID'] , 'nc_ogTitle' , true ) );
114
+ $info['description'] = htmlspecialchars( get_post_meta( $info['postID'] , 'nc_ogDescription' , true ) );
115
+ $info['sw_fb_author'] = htmlspecialchars( get_post_meta( $info['postID'] , 'sw_fb_author' , true ) );
116
+ $info['sw_user_options'] = sw_get_user_options();
117
+ $info['user_twitter_handle'] = $user_twitter_handle;
118
+ $info['header_output'] = '';
119
+
120
+ $info = apply_filters( 'sw_meta_tags' , $info );
121
+
122
+ if($info['header_output']):
123
+ echo PHP_EOL .'<!-- Open Graph Meta Tags & Twitter Card generated by Social Warfare v'.SW_VERSION.' http://warfareplugins.com -->';
124
+ echo $info['header_output'];
125
+ echo PHP_EOL .'<!-- Open Graph Meta Tags & Twitter Card generated by Social Warfare v'.SW_VERSION.' http://warfareplugins.com -->'. PHP_EOL . PHP_EOL;
126
+ endif;
127
+ }
128
+
129
+ /*****************************************************************
130
+ * *
131
+ * Queue Up our Open Graph Hooks *
132
+ * *
133
+ ******************************************************************/
134
+
135
+ // Queue up our hook function
136
+ add_filter( 'sw_meta_tags' , 'sw_open_graph_tags' , 1 );
137
+ add_filter( 'sw_meta_tags' , 'sw_add_twitter_card' , 2 );
138
+ add_filter( 'sw_meta_tags' , 'sw_frame_buster' , 3 );
139
+ add_filter( 'sw_meta_tags' , 'sw_output_custom_color' , 4 );
140
+ add_filter( 'sw_meta_tags' , 'sw_output_font_css' , 5 );
141
+ add_filter( 'sw_meta_tags' , 'sw_output_cache_trigger' , 6 );
142
+ add_filter( 'sw_meta_tags' , 'sw_cache_rebuild_rel_canonical' , 7 );
143
+ add_action( 'admin_head' , 'sw_output_font_css' , 10);
144
+
145
+ // Disable Simple Podcast Press Open Graph tags
146
+ if ( is_plugin_active( 'simple-podcast-press/simple-podcast-press.php' ) ) {
147
+ global $ob_wp_simplepodcastpress;
148
+ remove_action( 'wp_head' , array( $ob_wp_simplepodcastpress , 'spp_open_graph') , 1);
149
+ }
150
+
151
+ /*****************************************************************
152
+ * *
153
+ * Open Graph Tags *
154
+ * *
155
+ * Dev Notes: If the user specifies an Open Graph tag, *
156
+ * we're going to develop a complete set of tags. Order *
157
+ * of preference for each tag is as follows: *
158
+ * 1. Did they fill out our open graph field? *
159
+ * 2. Did they fill out Yoast's social field? *
160
+ * 3. Did they fill out Yoast's SEO field? *
161
+ * 4. We'll just auto-generate the field from the post. *
162
+ ******************************************************************/
163
+
164
+ function sw_open_graph_tags($info) {
165
+
166
+ // We only modify the Open Graph tags on single blog post pages
167
+ if(is_singular()):
168
+
169
+ // If Yoast Open Graph is activated, we only output Open Graph tags if the user has filled out at least one field
170
+ // Then we'll work along with Yoast to make sure all fields get filled properly
171
+ if(defined('WPSEO_VERSION')):
172
+ global $wpseo_og;
173
+ $yoast_og_setting = has_action( 'wpseo_head', array( $wpseo_og, 'opengraph' ));
174
+ else:
175
+ $yoast_og_setting = false;
176
+ endif;
177
+
178
+ if(
179
+ (isset($info['title']) && $info['title']) ||
180
+ (isset($info['description']) && $info['description']) ||
181
+ (isset($info['imageURL']) && $info['imageURL']) ||
182
+ !$yoast_og_setting
183
+ ):
184
+
185
+ /*****************************************************************
186
+ * *
187
+ * YOAST SEO: It rocks, so let's coordinate with it *
188
+ * *
189
+ ******************************************************************/
190
+
191
+ // Check if Yoast Exists so we can coordinate output with their plugin accordingly
192
+ if (defined('WPSEO_VERSION')):
193
+
194
+ // Collect their Social Descriptions as backups if they're not defined in ours
195
+ $yoast_og_title = get_post_meta( $info['postID'] , '_yoast_wpseo_opengraph-title' , true );
196
+ $yoast_og_description = get_post_meta( $info['postID'] , '_yoast_wpseo_opengraph-description' , true );
197
+ $yoast_og_image = get_post_meta( $info['postID'] , '_yoast_wpseo_opengraph-image' , true );
198
+
199
+ // Collect their SEO fields as 3rd string backups in case we need them
200
+ $yoast_seo_title = get_post_meta( $info['postID'] , '_yoast_wpseo_title' , true );
201
+ $yoast_seo_description = get_post_meta( $info['postID'] , '_yoast_wpseo_metadesc' , true );
202
+
203
+ // Cancel their output if ours have been defined so we don't have two sets of tags
204
+ global $wpseo_og;
205
+ remove_action( 'wpseo_head', array( $wpseo_og, 'opengraph' ), 30 );
206
+
207
+ // Fetch the WPSEO_SOCIAL Values
208
+ $wpseo_social = get_option( 'wpseo_social' );
209
+
210
+ endif;
211
+
212
+ // Add all our Open Graph Tags to the Return Header Output
213
+ $info['header_output'] .= PHP_EOL .'<meta property="og:type" content="article" /> ';
214
+
215
+ /*****************************************************************
216
+ * *
217
+ * JETPACK: If ours are enabled, disable theirs *
218
+ * *
219
+ ******************************************************************/
220
+
221
+ if ( class_exists( 'JetPack' ) ) :
222
+ add_filter( 'jetpack_enable_opengraph', '__return_false', 99 );
223
+ add_filter( 'jetpack_enable_open_graph', '__return_false', 99 );
224
+ endif;
225
+
226
+ /*****************************************************************
227
+ * *
228
+ * OPEN GRAPH TITLE *
229
+ * *
230
+ ******************************************************************/
231
+
232
+ // Open Graph Title: Create an open graph title meta tag
233
+ if($info['title']):
234
+
235
+ // If the user defined an social media title, let's use it.
236
+ $info['header_output'] .= PHP_EOL .'<meta property="og:title" content="'.$info['title'].'" />';
237
+
238
+ elseif(isset($yoast_og_title) && $yoast_og_title):
239
+
240
+ // If the user defined an title over in Yoast, let's use it.
241
+ $info['header_output'] .= PHP_EOL .'<meta property="og:title" content="'.$yoast_og_title.'" />';
242
+
243
+ elseif(isset($yoast_seo_title) && $yoast_seo_title):
244
+
245
+ // If the user defined an title over in Yoast, let's use it.
246
+ $info['header_output'] .= PHP_EOL .'<meta property="og:title" content="'.$yoast_seo_title.'" />';
247
+
248
+ else:
249
+
250
+ // If nothing else is defined, let's use the post title
251
+ $info['header_output'] .= PHP_EOL .'<meta property="og:title" content="'.convert_smart_quotes(htmlspecialchars_decode(get_the_title())).'" />';
252
+
253
+ endif;
254
+
255
+ /*****************************************************************
256
+ * *
257
+ * OPEN GRAPH DESCRIPTION *
258
+ * *
259
+ ******************************************************************/
260
+
261
+ // Open Graph Description: Create an open graph description meta tag
262
+ if($info['description']):
263
+
264
+ // If the user defined an social media description, let's use it.
265
+ $info['header_output'] .= PHP_EOL .'<meta property="og:description" content="'.$info['description'].'" />';
266
+
267
+ elseif(isset($yoast_og_description) && $yoast_og_description):
268
+
269
+ // If the user defined an description over in Yoast, let's use it.
270
+ $info['header_output'] .= PHP_EOL .'<meta property="og:description" content="'.$yoast_og_description.'" />';
271
+
272
+ elseif(isset($yoast_seo_description) && $yoast_seo_description):
273
+
274
+ // If the user defined an description over in Yoast, let's use it.
275
+ $info['header_output'] .= PHP_EOL .'<meta property="og:description" content="'.$yoast_seo_description.'" />';
276
+
277
+ else:
278
+
279
+ // If nothing else is defined, let's use the post excerpt
280
+ $info['header_output'] .= PHP_EOL .'<meta property="og:description" content="'.convert_smart_quotes(htmlspecialchars_decode(sw_get_excerpt_by_id($info['postID']))).'" />';
281
+
282
+ endif;
283
+
284
+ /*****************************************************************
285
+ * *
286
+ * OPEN GRAPH IMAGE *
287
+ * *
288
+ ******************************************************************/
289
+
290
+ // Open Graph Image: Create an open graph image meta tag
291
+ if($info['imageURL']):
292
+
293
+ // If the user defined an image, let's use it.
294
+ $info['header_output'] .= PHP_EOL .'<meta property="og:image" content="'.$info['imageURL'].'" />';
295
+
296
+ elseif(isset($yoast_og_image) && $yoast_og_image):
297
+
298
+ // If the user defined an image over in Yoast, let's use it.
299
+ $info['header_output'] .= PHP_EOL .'<meta property="og:image" content="'.$yoast_og_image.'" />';
300
+
301
+ else:
302
+
303
+ // If nothing else is defined, let's use the post Thumbnail as long as we have the URL cached
304
+ $og_image = get_post_meta( $info['postID'] , 'sw_open_thumbnail_url' , true );
305
+ if($og_image):
306
+ $info['header_output'] .= PHP_EOL .'<meta property="og:image" content="'.$og_image.'" />';
307
+ endif;
308
+
309
+ endif;
310
+
311
+ /*****************************************************************
312
+ * *
313
+ * OPEN GRAPH URL & Site Name *
314
+ * *
315
+ ******************************************************************/
316
+
317
+ $info['header_output'] .= PHP_EOL .'<meta property="og:url" content="'.get_permalink().'" />';
318
+ $info['header_output'] .= PHP_EOL .'<meta property="og:site_name" content="'.get_bloginfo('name').'" />';
319
+
320
+ /*****************************************************************
321
+ * *
322
+ * OPEN GRAPH AUTHOR *
323
+ * *
324
+ ******************************************************************/
325
+
326
+ // Add the Facebook Author URL
327
+ if( get_the_author_meta ( 'sw_fb_author' , sw_get_author($info['postID'])) ):
328
+
329
+ // Output the Facebook Author URL
330
+ $facebook_author = get_the_author_meta ( 'sw_fb_author' , sw_get_author($info['postID']));
331
+ $info['header_output'] .= PHP_EOL .'<meta property="article:author" content="'.$facebook_author.'" />';
332
+
333
+ elseif( get_the_author_meta ( 'facebook' , sw_get_author($info['postID'])) && defined('WPSEO_VERSION')):
334
+
335
+ // Output the Facebook Author URL
336
+ $facebook_author = get_the_author_meta ( 'facebook' , sw_get_author($info['postID']));
337
+ $info['header_output'] .= PHP_EOL .'<meta property="article:author" content="'.$facebook_author.'" />';
338
+
339
+ endif;
340
+
341
+ /*****************************************************************
342
+ * *
343
+ * OPEN GRAPH PUBLISHER *
344
+ * *
345
+ ******************************************************************/
346
+
347
+ // If they have a Facebook Publisher URL in our settings...
348
+ if(isset($info['sw_user_options']['facebookPublisherUrl']) && $info['sw_user_options']['facebookPublisherUrl'] != ''):
349
+
350
+ // Output the Publisher URL
351
+ $info['header_output'] .= PHP_EOL .'<meta property="article:publisher" content="'.$info['sw_user_options']['facebookPublisherUrl'].'" />';
352
+
353
+ // If they have a Facebook Publisher URL in Yoast's settings...
354
+ elseif(isset($wpseo_social) && isset($wpseo_social['facebook_site']) && $wpseo_social['facebook_site'] != ''):
355
+
356
+ // Output the Publisher URL
357
+ $info['header_output'] .= PHP_EOL .'<meta property="article:publisher" content="'.$wpseo_social['facebook_site'].'" />';
358
+ endif;
359
+
360
+ $info['header_output'] .= PHP_EOL .'<meta property="article:published_time" content="'.get_post_time('c').'" />';
361
+ $info['header_output'] .= PHP_EOL .'<meta property="article:modified_time" content="'.get_post_modified_time('c').'" />';
362
+ $info['header_output'] .= PHP_EOL .'<meta property="og:updated_time" content="'.get_post_modified_time('c').'" />';
363
+
364
+ /*****************************************************************
365
+ * *
366
+ * OPEN GRAPH APP ID *
367
+ * *
368
+ ******************************************************************/
369
+
370
+ // If the Facebook APP ID is in our settings...
371
+ if(isset($info['sw_user_options']['facebookAppID']) && $info['sw_user_options']['facebookAppID'] != ''):
372
+
373
+ // Output the Facebook APP ID
374
+ $info['header_output'] .= PHP_EOL .'<meta property="fb:app_id" content="'.$info['sw_user_options']['facebookAppID'].'" />';
375
+
376
+ // If the Facebook APP ID is set in Yoast's settings...
377
+ elseif(isset($wpseo_social) && isset($wpseo_social['fbadminapp']) && $wpseo_social['fbadminapp'] != ''):
378
+
379
+ // Output the Facebook APP ID
380
+ $info['header_output'] .= PHP_EOL .'<meta property="fb:app_id" content="'.$wpseo_social['fbadminapp'].'" />';
381
+
382
+ else:
383
+
384
+ // Output the Facebook APP ID
385
+ $info['header_output'] .= PHP_EOL .'<meta property="fb:app_id" content="529576650555031" />';
386
+
387
+ endif;
388
+
389
+ endif;
390
+ endif;
391
+
392
+ // Return the variable containing our information for the meta tags
393
+ return $info;
394
+
395
+ }
396
+
397
+ /*****************************************************************
398
+ * *
399
+ * TWITTER CARDS *
400
+ * *
401
+ * Dev Notes: If the user has Twitter cards turned on, we *
402
+ * need to generate them, but we also like Yoast so we'll *
403
+ * pay attention to their settings as well. Here's the order *
404
+ * of preference for each field: *
405
+ * 1. Did the user fill out the Social Media field? *
406
+ * 2. Did the user fill out the Yoast Twitter Field? *
407
+ * 3. Did the user fill out the Yoast SEO field? *
408
+ * 4. We'll auto generate something logical from the post. *
409
+ * *
410
+ ******************************************************************/
411
+
412
+ function sw_add_twitter_card($info) {
413
+ if(is_singular()):
414
+ // Check if Twitter Cards are Activated
415
+ if($info['sw_user_options']['sw_twitter_card']):
416
+
417
+ /*****************************************************************
418
+ * *
419
+ * YOAST SEO: It rocks, so let's coordinate with it *
420
+ * *
421
+ ******************************************************************/
422
+
423
+ // Check if Yoast Exists so we can coordinate output with their plugin accordingly
424
+ if (defined('WPSEO_VERSION')):
425
+
426
+ // Collect their Social Descriptions as backups if they're not defined in ours
427
+ $yoast_twitter_title = get_post_meta( $info['postID'] , '_yoast_wpseo_twitter-title' , true );
428
+ $yoast_twitter_description = get_post_meta( $info['postID'] , '_yoast_wpseo_twitter-description' , true );
429
+ $yoast_twitter_image = get_post_meta( $info['postID'] , '_yoast_wpseo_twitter-image' , true );
430
+
431
+ // Collect their SEO fields as 3rd string backups in case we need them
432
+ $yoast_seo_title = get_post_meta( $info['postID'] , '_yoast_wpseo_title' , true );
433
+ $yoast_seo_description = get_post_meta( $info['postID'] , '_yoast_wpseo_metadesc' , true );
434
+
435
+ // Cancel their output if ours have been defined so we don't have two sets of tags
436
+ remove_action( 'wpseo_head' , array( 'WPSEO_Twitter' , 'get_instance' ) , 40 );
437
+
438
+ endif;
439
+
440
+ /*****************************************************************
441
+ * *
442
+ * JET PACK: If ours are activated, disable theirs *
443
+ * *
444
+ ******************************************************************/
445
+
446
+ if ( class_exists( 'JetPack' ) ) :
447
+
448
+ add_filter( 'jetpack_disable_twitter_cards', '__return_true', 99 );
449
+
450
+ endif;
451
+
452
+ /*****************************************************************
453
+ * *
454
+ * TWITTER TITLE *
455
+ * *
456
+ ******************************************************************/
457
+
458
+ // If the user defined a Social Media title, use it, otherwise check for Yoast's
459
+ if(!$info['title'] && isset($yoast_twitter_title) && $yoast_twitter_title):
460
+
461
+ $info['title'] = $yoast_twitter_title;
462
+
463
+ // If not title has been defined, let's check the SEO description as a 3rd string option
464
+ elseif(!$info['title'] && isset($yoast_seo_title) && $yoast_seo_title):
465
+
466
+ $info['title'] = $yoast_seo_title;
467
+
468
+ // If not title has been defined, let's use the post title
469
+ elseif(!$info['title']):
470
+
471
+ $info['title'] = convert_smart_quotes(htmlspecialchars_decode( get_the_title() ));
472
+
473
+ endif;
474
+
475
+ /*****************************************************************
476
+ * *
477
+ * TWITTER DESCRIPTION *
478
+ * *
479
+ ******************************************************************/
480
+
481
+ // Open Graph Description
482
+ if(!$info['description'] && isset($yoast_twitter_description) && $yoast_twitter_description):
483
+
484
+ $info['description'] = $yoast_twitter_description;
485
+
486
+ // If not title has been defined, let's check the SEO description as a 3rd string option
487
+ elseif(!$info['description'] && isset($yoast_seo_description) && $yoast_seo_description):
488
+
489
+ $info['description'] = $yoast_seo_description;
490
+
491
+ // If not, then let's use the excerpt
492
+ elseif(!$info['description']):
493
+
494
+ $info['description'] = convert_smart_quotes(htmlspecialchars_decode( sw_get_excerpt_by_id( $info['postID'] )) );
495
+
496
+ endif;
497
+
498
+ /*****************************************************************
499
+ * *
500
+ * TWITTER IMAGE *
501
+ * *
502
+ ******************************************************************/
503
+
504
+ // Open Graph Description
505
+ if(!$info['imageURL'] && isset($yoast_twitter_image) && $yoast_twitter_image):
506
+
507
+ $info['imageURL'] = $yoast_twitter_image;
508
+
509
+ else:
510
+
511
+ // If nothing else is defined, let's use the post Thumbnail as long as we have the URL cached
512
+ $twitter_image = get_post_meta( $info['postID'] , 'sw_open_thumbnail_url' , true );
513
+ if($twitter_image):
514
+ $info['imageURL'] = $twitter_image;
515
+ endif;
516
+
517
+ endif;
518
+
519
+ /*****************************************************************
520
+ * *
521
+ * PUT IT ALL TOGETHER *
522
+ * *
523
+ ******************************************************************/
524
+
525
+ // Check if we have everything we need for a large image summary card
526
+ if($info['imageURL']):
527
+ $info['header_output'] .= PHP_EOL .'<meta name="twitter:card" content="summary_large_image">';
528
+ $info['header_output'] .= PHP_EOL .'<meta name="twitter:title" content="'.$info['title'].'">';
529
+ $info['header_output'] .= PHP_EOL .'<meta name="twitter:description" content="'.$info['description'].'">';
530
+ $info['header_output'] .= PHP_EOL .'<meta name="twitter:image" content="'.$info['imageURL'].'">';
531
+ if($info['sw_user_options']['twitterID']):
532
+ $info['header_output'] .= PHP_EOL .'<meta name="twitter:site" content="@'.$info['sw_user_options']['twitterID'].'">';
533
+ endif;
534
+ if($info['user_twitter_handle']):
535
+ $info['header_output'] .= PHP_EOL .'<meta name="twitter:creator" content="@'.str_replace('@','',$info['user_twitter_handle']).'">';
536
+ endif;
537
+
538
+ // Otherwise create a small summary card
539
+ else:
540
+ $info['header_output'] .= PHP_EOL .'<meta name="twitter:card" content="summary">';
541
+ $info['header_output'] .= PHP_EOL .'<meta name="twitter:title" content="'.str_replace('"','\'',$info['title']).'">';
542
+ $info['header_output'] .= PHP_EOL .'<meta name="twitter:description" content="'.str_replace('"','\'',$info['description']).'">';
543
+ if($info['sw_user_options']['twitterID']):
544
+ $info['header_output'] .= PHP_EOL .'<meta name="twitter:site" content="@'.$info['sw_user_options']['twitterID'].'">';
545
+ endif;
546
+ if($info['user_twitter_handle']):
547
+ $info['header_output'] .= PHP_EOL .'<meta name="twitter:creator" content="@'.str_replace('@','',$info['user_twitter_handle']).'">';
548
+ endif;
549
+ endif;
550
+
551
+ endif;
552
+ endif;
553
+ return $info;
554
+ }
555
+
556
+ /*****************************************************************
557
+ * *
558
+ * Frame Buster *
559
+ * *
560
+ ******************************************************************/
561
+
562
+ function sw_frame_buster($info) {
563
+ if($info['sw_user_options']['sniplyBuster'] == true):
564
+ $info['header_output'] .= PHP_EOL.'<script type="text/javascript">function parentIsEvil() { var html = null; try { var doc = top.location.pathname; } catch(err){ }; if(typeof doc === "undefined") { return true } else { return false }; }; if (parentIsEvil()) { top.location = self.location.href; };var url = "'.get_permalink().'";if(url.indexOf("stfi.re") != -1) { var canonical = ""; var links = document.getElementsByTagName("link"); for (var i = 0; i < links.length; i ++) { if (links[i].getAttribute("rel") === "canonical") { canonical = links[i].getAttribute("href")}}; canonical = canonical.replace("?sfr=1", "");top.location = canonical; console.log(canonical);};</script>';
565
+ endif;
566
+ return $info;
567
+ }
568
+
569
+ /*****************************************************************
570
+ * *
571
+ * CUSTOM COLORS *
572
+ * *
573
+ ******************************************************************/
574
+
575
+ function sw_output_custom_color($info) {
576
+ if($info['sw_user_options']['dColorSet'] == 'customColor' || $info['sw_user_options']['iColorSet'] == 'customColor' || $info['sw_user_options']['oColorSet'] == 'customColor'):
577
+ $info['header_output'] .= PHP_EOL.'<style type="text/css">.nc_socialPanel.sw_d_customColor a, html body .nc_socialPanel.sw_i_customColor .nc_tweetContainer:hover a, body .nc_socialPanel.sw_o_customColor:hover a {color:white} .nc_socialPanel.sw_d_customColor .nc_tweetContainer, html body .nc_socialPanel.sw_i_customColor .nc_tweetContainer:hover, body .nc_socialPanel.sw_o_customColor:hover .nc_tweetContainer {background-color:'.$info['sw_user_options']['customColor'].';border:1px solid '.$info['sw_user_options']['customColor'].';} </style>';
578
+ endif;
579
+
580
+ if($info['sw_user_options']['dColorSet'] == 'ccOutlines' || $info['sw_user_options']['iColorSet'] == 'ccOutlines' || $info['sw_user_options']['oColorSet'] == 'ccOutlines'):
581
+ $info['header_output'] .= PHP_EOL.'<style type="text/css">.nc_socialPanel.sw_d_ccOutlines a, html body .nc_socialPanel.sw_i_ccOutlines .nc_tweetContainer:hover a, body .nc_socialPanel.sw_o_ccOutlines:hover a { color:'.$info['sw_user_options']['customColor'].'; }
582
+ .nc_socialPanel.sw_d_ccOutlines .nc_tweetContainer, html body .nc_socialPanel.sw_i_ccOutlines .nc_tweetContainer:hover, body .nc_socialPanel.sw_o_ccOutlines:hover .nc_tweetContainer { background:transparent; border:1px solid '.$info['sw_user_options']['customColor'].'; } </style>';
583
+
584
+ endif;
585
+ return $info;
586
+ }
587
+
588
+ /*****************************************************************
589
+ * *
590
+ * CACHE REBUILD TRIGGER *
591
+ * *
592
+ ******************************************************************/
593
+ function sw_output_cache_trigger($info) {
594
+ // Check if we're on a single post page, the cache is expired, and they're using the updated cache rebuild method
595
+ if(is_singular() && sw_is_cache_fresh( get_the_ID() , true ) == false && $info['sw_user_options']['cacheMethod'] != 'legacy'):
596
+
597
+ // Make sure we're not on a WooCommerce Account Page
598
+ if(is_plugin_active( 'woocommerce/woocommerce.php' ) && is_account_page()):
599
+ return $info;
600
+
601
+ // Trigger the cache rebuild
602
+ else:
603
+ $url = get_permalink();
604
+ $info['header_output'] .= PHP_EOL.'<script type="text/javascript">var sw_buttons_exist = !!document.getElementsByClassName("nc_socialPanel"); if(sw_buttons_exist == true) { document.addEventListener("DOMContentLoaded", function(event) { var SW_CACHE_URL = "'.$url.'"; if(SW_CACHE_URL.indexOf("?") > -1) { SW_CACHE_URL += "&sw_cache=rebuild"; } else { SW_CACHE_URL += "?sw_cache=rebuild"; }; var xhr = new XMLHttpRequest(); xhr.open("GET",SW_CACHE_URL,true); xhr.send(); });}</script>';
605
+ endif;
606
+ endif;
607
+ // Return the array so the world doesn't explode
608
+ return $info;
609
+ }
610
+ /*****************************************************************
611
+ * *
612
+ * CACHE REBUILD REL CANONICAL *
613
+ * *
614
+ ******************************************************************/
615
+ function sw_cache_rebuild_rel_canonical($info) {
616
+
617
+ // Fetch the Permalink
618
+ $url = get_permalink();
619
+
620
+ // Check to see if the cache is currently being rebuilt
621
+ if(isset($_GET['sw_cache']) && $_GET['sw_cache'] == 'rebuild'):
622
+
623
+ // Use a rel canonical so everyone knows this is not a real page
624
+ $info['header_output'] .= '<link rel="canonical" href="'.$url.'">';
625
+ endif;
626
+
627
+ // Return the array so the world doesn't explode
628
+ return $info;
629
+ }
630
+ /*****************************************************************
631
+ * *
632
+ * ICON FONT CSS *
633
+ * *
634
+ ******************************************************************/
635
+ function sw_output_font_css($info=array()) {
636
+ if(is_admin()):
637
+
638
+ // Echo it if we're using the Admin Head Hook
639
+ echo '<style>@font-face {font-family: "sw-icon-font";src:url("'.SW_PLUGIN_DIR.'/fonts/sw-icon-font.eot?ver='.SW_VERSION.'");src:url("'.SW_PLUGIN_DIR.'/fonts/sw-icon-font.eot?ver='.SW_VERSION.'#iefix") format("embedded-opentype"),url("'.SW_PLUGIN_DIR.'/fonts/sw-icon-font.woff?ver='.SW_VERSION.'") format("woff"),
640
+ url("'.SW_PLUGIN_DIR.'/fonts/sw-icon-font.ttf?ver='.SW_VERSION.'") format("truetype"),url("'.SW_PLUGIN_DIR.'/fonts/sw-icon-font.svg?ver='.SW_VERSION.'#1445203416") format("svg");font-weight: normal;font-style: normal;}</style>';
641
+ else:
642
+
643
+ // Add it to our array if we're using the frontend Head Hook
644
+ $info['header_output'] .= PHP_EOL.'<style>@font-face {font-family: "sw-icon-font";src:url("'.SW_PLUGIN_DIR.'/fonts/sw-icon-font.eot?ver='.SW_VERSION.'");src:url("'.SW_PLUGIN_DIR.'/fonts/sw-icon-font.eot?ver='.SW_VERSION.'#iefix") format("embedded-opentype"),url("'.SW_PLUGIN_DIR.'/fonts/sw-icon-font.woff?ver='.SW_VERSION.'") format("woff"), url("'.SW_PLUGIN_DIR.'/fonts/sw-icon-font.ttf?ver='.SW_VERSION.'") format("truetype"),url("'.SW_PLUGIN_DIR.'/fonts/sw-icon-font.svg?ver='.SW_VERSION.'#1445203416") format("svg");font-weight: normal;font-style: normal;}</style>';
645
+
646
+ return $info;
647
+ endif;
648
+ }
649
+ /*****************************************************************
650
+ * *
651
+ * Click Tracking *
652
+ * *
653
+ ******************************************************************/
654
+ function sw_click_tracking() {
655
+ $sw_options = sw_get_user_options();
656
+ if( $sw_options['sw_click_tracking'] == 1 ):
657
+ echo '<script>if (typeof ga == "function") { jQuery(document).on("click",".nc_tweet",function(event) {var network = jQuery(this).parents(".nc_tweetContainer").attr("data-network");ga("send", "event", "social_media", "sw_" + network + "_share" );});}</script>';
658
+ endif;
659
+ }
660
+ add_action( 'wp_footer', 'sw_click_tracking' );
functions/kilomega.php ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*****************************************************************
4
+ * *
5
+ * ROUND TO THE APPROPRATE THOUSANDS *
6
+ * *
7
+ ******************************************************************/
8
+ function kilomega( $val ) {
9
+
10
+ // Fetch the user assigned options
11
+ $options = sw_get_user_options();
12
+
13
+ // Check if we even have a value to format
14
+ if($val):
15
+
16
+ // Check if the value is less than 1,000....
17
+ if( $val < 1000 ):
18
+
19
+ // If less than 1,000 just format and kick it back
20
+ return number_format($val);
21
+
22
+ // Check if the value is greater than 1,000 and less than 1,000,000....
23
+ elseif( $val < 1000000):
24
+
25
+ // Start by deviding the value by 1,000
26
+ $val = intval($val) / 1000;
27
+
28
+ // If the decimal separator is a period
29
+ if($options['sw_decimal_separator'] == 'period'):
30
+
31
+ // Then format the number to the appropriate number of decimals
32
+ return number_format($val,$options['swDecimals'],'.',',').'K';
33
+
34
+ // If the decimal separator is a comma
35
+ else:
36
+
37
+ // Then format the number to the appropriate number of decimals
38
+ return number_format($val,$options['swDecimals'],',','.').'K';
39
+
40
+ endif;
41
+
42
+ // Check if the value is greater than 1,000,000....
43
+ else:
44
+
45
+ // Start by deviding the value by 1,000,000
46
+ $val = intval($val) / 1000000;
47
+
48
+ // If the decimal separator is a period
49
+ if($options['sw_decimal_separator'] == 'period'):
50
+
51
+ // Then format the number to the appropriate number of decimals
52
+ return number_format($val,$options['swDecimals'],'.',',').'M';
53
+
54
+ // If the decimal separator is a comma
55
+ else:
56
+
57
+ // Then format the number to the appropriate number of decimals
58
+ return number_format($val,$options['swDecimals'],',','.').'M';
59
+
60
+ endif;
61
+
62
+ endif;
63
+
64
+ // If there is no value, return a zero
65
+ else:
66
+
67
+ return 0;
68
+
69
+ endif;
70
+ }
functions/languages.php ADDED
@@ -0,0 +1,216 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ /****************************************************************************************
5
+ * *
6
+ * Enqueue the Filters for the Available Languages *
7
+ * *
8
+ *****************************************************************************************/
9
+
10
+ add_filter('sw_languages','sw_en_language',0);
11
+
12
+ /****************************************************************************************
13
+ * *
14
+ * English *
15
+ * *
16
+ *****************************************************************************************/
17
+
18
+ function sw_en_language($language) {
19
+
20
+ $language['googlePlus'] = '+1';
21
+ $language['twitter'] = 'Tweet';
22
+ $language['facebook'] = 'Share';
23
+ $language['pinterest'] = 'Pin';
24
+ $language['linkedIn'] = 'Share';
25
+ $language['tumblr'] = 'Share';
26
+ $language['stumbleupon'] = 'Stumble';
27
+ $language['reddit'] = 'Reddit';
28
+ $language['email'] = 'Email';
29
+ $language['yummly'] = 'Yum';
30
+ $language['whatsapp'] = 'WhatsApp';
31
+ $language['pocket'] = 'Pocket';
32
+ $language['buffer'] = 'Buffer';
33
+ $language['total'] = 'Shares';
34
+
35
+ // Return the Languages Array or the world will explode
36
+ return $language;
37
+ }
38
+
39
+
40
+ /****************************************************************************************
41
+ * *
42
+ * German *
43
+ * *
44
+ *****************************************************************************************/
45
+
46
+ // Add the terms to the buttons
47
+ add_filter('sw_languages','sw_de_language');
48
+ function sw_de_language($language) {
49
+ if(sw_get_single_option('language') == 'de'):
50
+ $language['googlePlus'] = '+1';
51
+ $language['twitter'] = 'Twittern';
52
+ $language['facebook'] = 'Teilen';
53
+ $language['pinterest'] = 'Pin';
54
+ $language['linkedIn'] = 'Teilen';
55
+ $language['total'] = 'Alle Shares';
56
+ endif;
57
+ return $language;
58
+ }
59
+
60
+ /****************************************************************************************
61
+ * *
62
+ * Russian *
63
+ * *
64
+ *****************************************************************************************/
65
+
66
+ // Add the terms to the buttons
67
+ add_filter('sw_languages','sw_ru_language');
68
+ function sw_ru_language($language) {
69
+ if(sw_get_single_option('language') == 'ru'):
70
+ $language['googlePlus'] = '+1';
71
+ $language['twitter'] = 'Tвитнуть';
72
+ $language['facebook'] = 'Поделиться';
73
+ $language['pinterest'] = 'Pin';
74
+ $language['linkedIn'] = 'Поделиться';
75
+ $language['total'] = 'Поделились';
76
+ endif;
77
+ return $language;
78
+ }
79
+
80
+ /****************************************************************************************
81
+ * *
82
+ * Ukrainian *
83
+ * *
84
+ *****************************************************************************************/
85
+
86
+ // Add the terms to the buttons
87
+ add_filter('sw_languages','sw_uk_language');
88
+ function sw_uk_language($language) {
89
+ if(sw_get_single_option('language') == 'uk'):
90
+ $language['googlePlus'] = '+1';
91
+ $language['twitter'] = 'Tвітнути';
92
+ $language['facebook'] = 'Поділитися';
93
+ $language['pinterest'] = 'Pin';
94
+ $language['linkedIn'] = 'Поділитися';
95
+ $language['total'] = 'Поділилися';
96
+ endif;
97
+ return $language;
98
+ }
99
+
100
+ /****************************************************************************************
101
+ * *
102
+ * Dutch *
103
+ * *
104
+ *****************************************************************************************/
105
+
106
+ // Add the terms to the buttons
107
+ add_filter('sw_languages','sw_nl_language');
108
+ function sw_nl_language($language) {
109
+ if(sw_get_single_option('language') == 'nl'):
110
+ $language['googlePlus'] = '+1';
111
+ $language['twitter'] = 'Twitteren';
112
+ $language['facebook'] = 'Delen';
113
+ $language['pinterest'] = 'Pin';
114
+ $language['linkedIn'] = 'Delen';
115
+ $language['total'] = 'Alle Shares';
116
+ endif;
117
+ return $language;
118
+ }
119
+
120
+ /****************************************************************************************
121
+ * *
122
+ * French *
123
+ * *
124
+ *****************************************************************************************/
125
+
126
+ // Add the terms to the buttons
127
+ add_filter('sw_languages','sw_fr_language');
128
+ function sw_fr_language($language) {
129
+ if(sw_get_single_option('language') == 'fr'):
130
+ $language['googlePlus'] = '+1';
131
+ $language['twitter'] = 'Tweetez';
132
+ $language['facebook'] = 'Partagez';
133
+ $language['pinterest'] = 'Pin';
134
+ $language['linkedIn'] = 'Partagez';
135
+ $language['total'] = 'Partages';
136
+ endif;
137
+ return $language;
138
+ }
139
+
140
+ /****************************************************************************************
141
+ * *
142
+ * Portuguese *
143
+ * *
144
+ *****************************************************************************************/
145
+
146
+ // Add the terms to the buttons
147
+ add_filter('sw_languages','sw_pt_language');
148
+ function sw_pt_language($language) {
149
+ if(sw_get_single_option('language') == 'pt'):
150
+ $language['googlePlus'] = '+1';
151
+ $language['twitter'] = 'Tweetar';
152
+ $language['facebook'] = 'Partilhar';
153
+ $language['pinterest'] = 'Pin';
154
+ $language['linkedIn'] = 'Partilhar';
155
+ $language['tumblr'] = 'Partilhar';
156
+ $language['stumbleupon'] = 'Stumble';
157
+ $language['reddit'] = 'Reddit';
158
+ $language['email'] = 'Enviar e-mail';
159
+ $language['yummly'] = 'Yum';
160
+ $language['whatsapp'] = 'WhatsApp';
161
+ $language['total'] = 'Total de partilhas';
162
+ endif;
163
+ return $language;
164
+ }
165
+
166
+ /****************************************************************************************
167
+ * *
168
+ * Danish *
169
+ * *
170
+ *****************************************************************************************/
171
+ // Add the terms to the buttons
172
+ add_filter('sw_languages','sw_da_language');
173
+ function sw_da_language($language) {
174
+ if(sw_get_single_option('language') == 'da'):
175
+ $language['googlePlus'] = '+1';
176
+ $language['twitter'] = 'Tweet';
177
+ $language['facebook'] = 'Del';
178
+ $language['pinterest'] = 'Pin';
179
+ $language['linkedIn'] = 'Del';
180
+ $language['tumblr'] = 'Del';
181
+ $language['stumbleupon'] = 'Stumble';
182
+ $language['reddit'] = 'Reddit';
183
+ $language['email'] = 'E-mail';
184
+ $language['yummly'] = 'Yum';
185
+ $language['whatsapp'] = 'WhatsApp';
186
+ $language['total'] = 'Delinger i alt';
187
+ endif;
188
+ return $language;
189
+ }
190
+
191
+ /****************************************************************************************
192
+ * *
193
+ * Italian *
194
+ * *
195
+ *****************************************************************************************/
196
+ // Add the terms to the buttons
197
+ add_filter('sw_languages','sw_it_language');
198
+ function sw_it_language($language) {
199
+ if(sw_get_single_option('language') == 'it'):
200
+ $language['googlePlus'] = '+1';
201
+ $language['twitter'] = 'Twitta';
202
+ $language['facebook'] = 'Condividi';
203
+ $language['pinterest'] = 'Pin';
204
+ $language['linkedIn'] = 'Condividi';
205
+ $language['tumblr'] = 'Condividi';
206
+ $language['stumbleupon'] = 'Stumble';
207
+ $language['reddit'] = 'Reddit';
208
+ $language['email'] = 'Email';
209
+ $language['yummly'] = 'Yum';
210
+ $language['whatsapp'] = 'WhatsApp';
211
+ $language['pocket'] = 'Pocket';
212
+ $language['buffer'] = 'Buffer';
213
+ $language['total'] = 'Condivisioni';
214
+ endif;
215
+ return $language;
216
+ }
functions/mobile-detection.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*******************************************************
4
+ * *
5
+ * Mobile device detection *
6
+ * *
7
+ ********************************************************/
8
+ if( !function_exists('sw_mobile_detection') ){
9
+ function sw_mobile_detection(){
10
+ return preg_match("/(android|avantgo|blackberry|bolt|boost|cricket|docomo|fone|hiptop|mini|mobi|palm|phone|pie|tablet|up\.browser|up\.link|webos|wos)/i", $_SERVER["HTTP_USER_AGENT"]);
11
+ }
12
+ }
functions/options-fetch.php ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $sw_user_options = get_option('socialWarfareOptions');
3
+ function sw_get_user_options() {
4
+ global $sw_user_options;
5
+
6
+ // Reset the Order of Icons Options
7
+ if (isset($sw_user_options['orderOfIcons'])):
8
+ unset($sw_user_options['orderOfIcons']);
9
+ update_option('socialWarfareOptions',$sw_user_options);
10
+ endif;
11
+
12
+ // Force the plugin off on certain post types
13
+ $sw_user_options['locationattachment'] = 'none';
14
+ $sw_user_options['locationrevision'] = 'none';
15
+ $sw_user_options['nav_menu_item'] = 'none';
16
+ $sw_user_options['shop_order'] = 'none';
17
+ $sw_user_options['shop_order_refund'] = 'none';
18
+ $sw_user_options['shop_coupon'] = 'none';
19
+ $sw_user_options['shop_webhook'] = 'none';
20
+
21
+ // Set defaults for everthing
22
+ if(!isset($sw_user_options['locationPost'])) { $sw_user_options['locationPost'] = 'both'; };
23
+ if(!isset($sw_user_options['locationPage'])) { $sw_user_options['locationPage'] = 'both'; };
24
+ if(!isset($sw_user_options['language'])) { $sw_user_options['language'] = 'en'; };
25
+ if(!isset($sw_user_options['locationSite'])) { $sw_user_options['locationSite'] = 'both'; };
26
+
27
+ // Default Buttons to Display
28
+ if(!isset($sw_user_options['googlePlus'])) { $sw_user_options['googlePlus'] = true; };
29
+ if(!isset($sw_user_options['twitter'])) { $sw_user_options['twitter'] = true; };
30
+ if(!isset($sw_user_options['facebook'])) { $sw_user_options['facebook'] = true; };
31
+ if(!isset($sw_user_options['pinterest'])) { $sw_user_options['pinterest'] = true; };
32
+ if(!isset($sw_user_options['linkedIn'])) { $sw_user_options['linkedIn'] = true; };
33
+ if(!isset($sw_user_options['yummly'])) { $sw_user_options['yummly'] = false; };
34
+ if(!isset($sw_user_options['email'])) { $sw_user_options['email'] = false; };
35
+ if(!isset($sw_user_options['whatsapp'])) { $sw_user_options['whatsapp'] = false; };
36
+ if(!isset($sw_user_options['tumblr'])) { $sw_user_options['tumblr'] = false; };
37
+ if(!isset($sw_user_options['reddit'])) { $sw_user_options['reddit'] = false; };
38
+ if(!isset($sw_user_options['stumbleupon'])) { $sw_user_options['stumbleupon'] = false; };
39
+ if(!isset($sw_user_options['pocket'])) { $sw_user_options['pocket'] = false; };
40
+ if(!isset($sw_user_options['buffer'])) { $sw_user_options['buffer'] = false; };
41
+
42
+ if(!isset($sw_user_options['totes'])) { $sw_user_options['totes'] = true; };
43
+ if(!isset($sw_user_options['totesEach'])) { $sw_user_options['totesEach'] = true; };
44
+ if(!isset($sw_user_options['twitterID'])) { $sw_user_options['twitterID'] = false; };
45
+ if(!isset($sw_user_options['sw_twitter_card'])) { $sw_user_options['sw_twitter_card'] = true; };
46
+ if(!isset($sw_user_options['visualTheme'])) { $sw_user_options['visualTheme'] = 'style1'; };
47
+ if(!isset($sw_user_options['dColorSet'])) { $sw_user_options['dColorSet'] = 'fullColor';};
48
+ if(!isset($sw_user_options['iColorSet'])) { $sw_user_options['iColorSet'] = 'fullColor';};
49
+ if(!isset($sw_user_options['oColorSet'])) { $sw_user_options['oColorSet'] = 'fullColor';};
50
+ if(!isset($sw_user_options['sideDColorSet'])) { $sw_user_options['sideDColorSet'] = 'fullColor';};
51
+ if(!isset($sw_user_options['sideIColorSet'])) { $sw_user_options['sideIColorSet'] = 'fullColor';};
52
+ if(!isset($sw_user_options['sideOColorSet'])) { $sw_user_options['sideOColorSet'] = 'fullColor';};
53
+ if(!isset($sw_user_options['floatStyleSource'])) { $sw_user_options['floatStyleSource'] = true;};
54
+ if(!isset($sw_user_options['buttonSize'])) { $sw_user_options['buttonSize'] = 1;};
55
+ if(!isset($sw_user_options['buttonFloat'])) { $sw_user_options['buttonFloat'] = 'fullWidth';};
56
+ if(!isset($sw_user_options['sideReveal'])) { $sw_user_options['sideReveal'] = 'slide';};
57
+ if(!isset($sw_user_options['sw_float_scr_sz'])) { $sw_user_options['sw_float_scr_sz'] = 1100;};
58
+ if(!isset($sw_user_options['cttTheme'])) { $sw_user_options['cttTheme'] = 'style1'; };
59
+ if(!isset($sw_user_options['twitter_shares'])) { $sw_user_options['twitter_shares'] = false; };
60
+ if(!isset($sw_user_options['float'])) { $sw_user_options['float'] = true; };
61
+ if(!isset($sw_user_options['floatOption'])) { $sw_user_options['floatOption'] = 'bottom'; };
62
+ if(!isset($sw_user_options['floatBgColor'])) { $sw_user_options['floatBgColor'] = '#ffffff';};
63
+ if(!isset($sw_user_options['floatStyle'])) { $sw_user_options['floatStyle'] = 'default';};
64
+ if(!isset($sw_user_options['customColor'])) { $sw_user_options['customColor'] = '#000000';};
65
+ if(!isset($sw_user_options['recover_shares'])) { $sw_user_options['recover_shares'] = false; };
66
+ if(!isset($sw_user_options['recovery_format'])) { $sw_user_options['recovery_format'] = 'unchanged'; };
67
+ if(!isset($sw_user_options['recovery_protocol'])) { $sw_user_options['recovery_protocol'] = 'unchanged'; };
68
+ if(!isset($sw_user_options['recovery_prefix'])) { $sw_user_options['recovery_prefix'] = 'unchanged'; };
69
+ if(!isset($sw_user_options['swDecimals'])) { $sw_user_options['swDecimals'] = 0; };
70
+ if(!isset($sw_user_options['sw_decimal_separator'])) { $sw_user_options['sw_decimal_separator'] = 'period';};
71
+ if(!isset($sw_user_options['swTotesFormat'])) { $sw_user_options['swTotesFormat'] = 'totesalt'; };
72
+ if($sw_user_options['swTotesFormat'] == 'totes') { $sw_user_options['swTotesFormat'] = 'totesalt'; };
73
+ if(!isset($sw_user_options['googleAnalytics'])) { $sw_user_options['googleAnalytics'] = false; };
74
+ if(!isset($sw_user_options['dashboardShares'])) { $sw_user_options['dashboardShares'] = true; };
75
+ if(!isset($sw_user_options['linkShortening'])) { $sw_user_options['linkShortening'] = false; };
76
+ if(!isset($sw_user_options['shorteningMethod'])) { $sw_user_options['shorteningMethod'] = 'warfareLinks'; };
77
+ if(!isset($sw_user_options['minTotes'])) { $sw_user_options['minTotes'] = 0; };
78
+ if(!isset($sw_user_options['cacheMethod'])) { $sw_user_options['cacheMethod'] = 'advanced'; };
79
+ if(!isset($sw_user_options['rawNumbers'])) { $sw_user_options['rawNumbers'] = false; };
80
+ if(!isset($sw_user_options['notShowing'])) { $sw_user_options['notShowing'] = false; };
81
+ if(!isset($sw_user_options['visualEditorBug'])) { $sw_user_options['visualEditorBug'] = false; };
82
+ if(!isset($sw_user_options['loopFix'])) { $sw_user_options['loopFix'] = false; };
83
+ if(!isset($sw_user_options['sniplyBuster'])) { $sw_user_options['sniplyBuster'] = false; };
84
+ if(!isset($sw_user_options['googleAnalytics'])) { $sw_user_options['googleAnalytics'] = true; };
85
+ if(!isset($sw_user_options['analyticsMedium'])) { $sw_user_options['analyticsMedium'] = 'social'; };
86
+ if(!isset($sw_user_options['analyticsCampaign'])) { $sw_user_options['analyticsCampaign'] = 'SocialWarfare'; };
87
+ if(!isset($sw_user_options['sw_click_tracking'])) { $sw_user_options['sw_click_tracking'] = false; };
88
+ if(!isset($sw_user_options['orderOfIconsSelect'])) { $sw_user_options['orderOfIconsSelect'] = 'manual'; };
89
+ if(!isset($sw_user_options['newOrderOfIcons'])) { $sw_user_options['newOrderOfIcons'] = array(
90
+ "twitter" => "Twitter",
91
+ "linkedIn" => "LinkedIn",
92
+ "pinterest" => "Pinterest",
93
+ "facebook" => "Facebook",
94
+ "googlePlus" => "Google Plus"
95
+ );
96
+ };
97
+ return $sw_user_options;
98
+ }
99
+ function sw_get_single_option($key) {
100
+ $option = sw_get_user_options();
101
+ return $option[$key];
102
+ }
functions/options-page.php ADDED
@@ -0,0 +1,1284 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Include the Admin Page Class files
4
+ require_once('admin-page-class/admin-page-class.php');
5
+
6
+ /****************************************************************************************
7
+ * *
8
+ * One Options Array to Rule Them All *
9
+ * *
10
+ *****************************************************************************************/
11
+
12
+ // Create all of the options in one giant array
13
+ $sw_options = array(
14
+
15
+ // The Options Page Configuration
16
+ 'config' => array(
17
+ 'menu'=> array('top' => 'social-warfare'), // sub page to settings page
18
+ 'page_title' => 'Social Warfare', // The name of this page
19
+ 'capability' => 'update_plugins', // The capability needed to view the page
20
+ 'option_group' => 'socialWarfareOptions', // the name of the option to create in the database
21
+ 'id' => 'social-warfare', // Page id, unique per page
22
+ 'fields' => array(), // list of fields (can be added by field arrays)
23
+ 'local_images' => false, // Use local or hosted images (meta box images for add/remove)
24
+ 'use_with_theme' => false
25
+ ),
26
+
27
+ // A List of Options Page Tabs and Their Titles
28
+ 'tabs' => array(
29
+ 'links' => array(
30
+ )
31
+ ),
32
+
33
+ // A list of options in each of the options tabs
34
+ 'options' => array()
35
+ );
36
+
37
+ /****************************************************************************************
38
+ * *
39
+ * The Social Warfare Social Identity Settings *
40
+ * *
41
+ *****************************************************************************************/
42
+ function sw_options_social_identity($sw_options) {
43
+
44
+ // Declare the Options Tab and Tab Name
45
+ $sw_options['tabs']['links']['socialIdentity'] = 'Social Identity';
46
+
47
+ // Declare the content that goes on this options page
48
+ $sw_options['options']['socialIdentity'] = array(
49
+ 'twitterHandleDescription' => array(
50
+ 'type' => 'paragraph',
51
+ 'content' => '<h3>Would you like to be mentioned in tweets?</h3><br />If so, please provide your Twitter username WITHOUT the @ symbol.'
52
+ ),
53
+ 'twitterID' => array(
54
+ 'type' => 'textbox',
55
+ 'content' => 'Twitter Username'
56
+ ),
57
+ 'facebookPublisherDescription' => array(
58
+ 'type' => 'paragraph',
59
+ 'content' => '<h3>Would you like to activate Facebook Publisher tags?</h3><br />If so, please provide your Facebook page URL. If you would like to add the Author tag instead, just be sure to add your Facebook profile URL to your User profile. '
60
+ ),
61
+ 'facebookPublisherUrl' => array(
62
+ 'type' => 'textbox',
63
+ 'content' => 'Facebook Page URL'
64
+ ),
65
+ 'facebookAppID' => array(
66
+ 'type' => 'textbox',
67
+ 'content' => 'App ID'
68
+ ),
69
+ 'pinterestUserDescription' => array(
70
+ 'type' => 'paragraph',
71
+ 'content' => '<h3>Would you like to be mentioned in Pins?</h3><br />If so, please provide your Pinterest username WITHOUT the @ symbol.'
72
+ ),
73
+ 'pinterestID' => array(
74
+ 'type' => 'textbox',
75
+ 'content' => 'Pinterest Username'
76
+ )
77
+ );
78
+ return $sw_options;
79
+ }
80
+
81
+ /****************************************************************************************
82
+ * *
83
+ * The Social Warfare Display Settings *
84
+ * *
85
+ *****************************************************************************************/
86
+ function sw_options_display_settings($sw_options) {
87
+
88
+ // Declare the Options Tab and Tab Name
89
+ $sw_options['tabs']['links']['displaySettings'] = 'Display Settings';
90
+
91
+ // Declare the content that goes on this options page
92
+ $sw_options['options']['displaySettings'] = array(
93
+ 'displaySettingsTitle' => array(
94
+ 'type' => 'title',
95
+ 'content' => 'Display Settings'
96
+ ),
97
+ 'displaySettingsDescription' => array(
98
+ 'type' => 'paragraph',
99
+ 'content' => 'Welcome to Social Warfare! Get ready to dominate the world\'s social networks. This is the page where you\'ll select which social media icons to display, where to display them, and in what order.'
100
+ ),
101
+ 'language' => array(
102
+ 'type' => 'select',
103
+ 'name' => 'Language',
104
+ 'content' => array(
105
+ 'da' => 'Danish',
106
+ 'nl' => 'Dutch',
107
+ 'en' => 'English',
108
+ 'fr' => 'French',
109
+ 'de' => 'German',
110
+ 'it' => 'Italian',
111
+ 'pt' => 'Portuguese',
112
+ 'ru' => 'Russian',
113
+ 'uk' => 'Ukrainian'
114
+ ),
115
+ 'default' => 'en'
116
+ ),
117
+ 'sw_twitter_card' => array(
118
+ 'type' => 'checkbox',
119
+ 'content' => 'Activate Twitter Cards?',
120
+ 'default' => 1
121
+ ),
122
+ 'iconDisplayInfo' => array(
123
+ 'type' => 'paragraph',
124
+ 'content' => '<h3>Which social media buttons would you like to display?</h3>'
125
+ ),
126
+ 'googlePlus' => array(
127
+ 'type' => 'checkbox',
128
+ 'content' => 'Google+',
129
+ 'default' => 1
130
+ ),
131
+ 'twitter' => array(
132
+ 'type' => 'checkbox',
133
+ 'content' => 'Twitter',
134
+ 'default' => 1
135
+ ),
136
+ 'facebook' => array(
137
+ 'type' => 'checkbox',
138
+ 'content' => 'Facebook',
139
+ 'default' => 1
140
+ ),
141
+ 'pinterest' => array(
142
+ 'type' => 'checkbox',
143
+ 'content' => 'Pinterest',
144
+ 'default' => 1
145
+ ),
146
+ 'linkedIn' => array(
147
+ 'type' => 'checkbox',
148
+ 'content' => 'LinkedIn',
149
+ 'default' => 1
150
+ ),
151
+ 'totes' => array(
152
+ 'type' => 'checkbox',
153
+ 'content' => 'Show Total Shares',
154
+ 'default' => 1
155
+ ),
156
+ 'totesEach' => array(
157
+ 'type' => 'checkbox',
158
+ 'content' => 'Show Individual Button Counts',
159
+ 'default' => 1
160
+ ),
161
+ 'minTotes' => array(
162
+ 'type' => 'textbox',
163
+ 'content' => 'Minimum Number of shares required before showing counts?',
164
+ 'default' => 0
165
+ ),
166
+ 'orderOfIconsDescription' => array(
167
+ 'type' => 'paragraph',
168
+ 'content' => '<h3>In what order should we place your share buttons?</h3><br />Simply drag and drop the social platforms to indicate the order in which you want them displayed.'
169
+ ),
170
+ 'orderOfIconsSelect' => array(
171
+ 'type' => 'select',
172
+ 'name' => 'Order of Icons',
173
+ 'content' => array(
174
+ 'manual' => 'Manually Order by My Preference',
175
+ 'dynamicCount' => 'Dynamically Order Buttons by Share Counts',
176
+ ),
177
+ 'default' => 'manual'
178
+ ),
179
+ 'newOrderOfIcons' => array(
180
+ 'type' => 'sortable',
181
+ 'name' => 'Order Your Icons',
182
+ 'content' => array(
183
+ 'googlePlus' => 'Google+',
184
+ 'twitter' => 'Twitter',
185
+ 'facebook' => 'Facebook',
186
+ 'pinterest' => 'Pinterest',
187
+ 'linkedIn' => 'LinkedIn'
188
+ )
189
+ )
190
+ );
191
+ return $sw_options;
192
+ }
193
+ /****************************************************************************************
194
+ * *
195
+ * The Social Warfare Display Locations *
196
+ * *
197
+ *****************************************************************************************/
198
+
199
+ // A function to add display locations to the array
200
+ function sw_options_display_locations($sw_options) {
201
+
202
+ // Declare the Display Settings tab and tab name
203
+ $sw_options['tabs']['links']['displayLocations'] = 'Display Locations';
204
+
205
+ // Default locations available (ARRAY)
206
+ $contentLocations = array(
207
+ 'above'=>'Above the Content',
208
+ 'below' => 'Below the Content',
209
+ 'both' => 'Both Above and Below the Content',
210
+ 'none' => 'None/Manual Placement'
211
+ );
212
+
213
+ // Add the options to this tab
214
+ $sw_options['options']['displayLocations'] = array(
215
+ 'displayLocationsTitle' => array(
216
+ 'type' => 'title',
217
+ 'content' => 'Display Locations'
218
+ ),
219
+ 'displayLocationsDescription' => array(
220
+ 'type' => 'paragraph',
221
+ 'content' => '<h3>Where would you like to display your horizontal share buttons?</h3>If you select \'None/Manual Placement\' you can add the social warfare plugin by adding \'social_warfare()\' to your themes files or shortcode [social_warfare] in posts or pages at the specific location that you want it to appear.'
222
+ ),
223
+ 'locationPost' => array(
224
+ 'type' => 'select',
225
+ 'name' => 'Location on Posts',
226
+ 'content' => $contentLocations,
227
+ 'default' => 'both'
228
+ ),
229
+ 'locationPage' => array(
230
+ 'type' => 'select',
231
+ 'name' => 'Location on Pages',
232
+ 'content' => $contentLocations,
233
+ 'default' => 'both'
234
+ ),
235
+ 'locationSite' => array(
236
+ 'type' => 'select',
237
+ 'name' => 'Location Sitewide',
238
+ 'content' => $contentLocations,
239
+ 'default' => 'both'
240
+ )
241
+ );
242
+
243
+ // Get the post Types
244
+ $postTypes = get_post_types();
245
+
246
+ // Unset the post types that don't matter
247
+ if(isset($postTypes['post'])) unset($postTypes['post']);
248
+ if(isset($postTypes['page'])) unset($postTypes['page']);
249
+ if(isset($postTypes['attachment'])) unset($postTypes['attachment']);
250
+ if(isset($postTypes['revision'])) unset($postTypes['revision']);
251
+ if(isset($postTypes['nav_menu_item'])) unset($postTypes['nav_menu_item']);
252
+ if(isset($postTypes['nf_sub'])) unset($postTypes['nf_sub']);
253
+ if(isset($postTypes['shop_order'])) unset($postTypes['shop_order']);
254
+ if(isset($postTypes['shop_order_refund'])) unset($postTypes['shop_order_refund']);
255
+ if(isset($postTypes['shop_coupon'])) unset($postTypes['shop_coupon']);
256
+ if(isset($postTypes['shop_webhook'])) unset($postTypes['shop_webhook']);
257
+
258
+ if(!empty($postTypes)):
259
+
260
+ // Loop through the Custom Post Type Options
261
+ foreach($postTypes as $postType):
262
+ $sw_options['options']['displayLocations']['location'.$postType] = array(
263
+ 'type' => 'select',
264
+ 'name' => 'Location on '.$postType.' Posts',
265
+ 'content' => $contentLocations,
266
+ 'default' => 'both'
267
+ );
268
+ endforeach;
269
+ endif;
270
+
271
+ $sw_options['options']['displayLocations']['floatLocationsDescription'] = array(
272
+ 'type' => 'paragraph',
273
+ 'content' => '<h3>Custom Post Type Placements for Vertical Floating Buttons (If Activated)</h3>These are the the same options as above, but now you get to choose where you want the vertical floating buttons to be turned off or on.'
274
+ );
275
+
276
+ $sw_options['options']['displayLocations']['floatLocationPost'] = array(
277
+ 'type' => 'select',
278
+ 'name' => 'Location on Posts',
279
+ 'content' => array(
280
+ 'on' => 'On',
281
+ 'off' => 'Off',
282
+ ),
283
+ 'default' => 'both'
284
+ );
285
+ $sw_options['options']['displayLocations']['floatlocationPage'] = array(
286
+ 'type' => 'select',
287
+ 'name' => 'Location on Pages',
288
+ 'content' => array(
289
+ 'on' => 'On',
290
+ 'off' => 'Off',
291
+ ),
292
+ 'default' => 'both'
293
+ );
294
+
295
+ if(!empty($postTypes)):
296
+
297
+ // Loop through the Custom Post Type Options
298
+ foreach($postTypes as $postType):
299
+ $sw_options['options']['displayLocations']['floatLocation'.$postType] = array(
300
+ 'type' => 'select',
301
+ 'name' => 'Location on '.$postType.' Posts',
302
+ 'content' => array(
303
+ 'on' => 'On',
304
+ 'off' => 'Off',
305
+ ),
306
+ 'default' => 'On'
307
+ );
308
+ endforeach;
309
+ endif;
310
+
311
+ // Return the options values
312
+ return $sw_options;
313
+
314
+ }
315
+ /****************************************************************************************
316
+ * *
317
+ * The Social Warfare Visual Options *
318
+ * *
319
+ *****************************************************************************************/
320
+
321
+ function sw_options_visual_options($sw_options) {
322
+
323
+ // Declare the Display Settings tab and tab name
324
+ $sw_options['tabs']['links']['visualOptions'] = 'Visual Options';
325
+
326
+ $sw_options['options']['visualOptions'] = array(
327
+ 'visualOptionsTitle' => array(
328
+ 'type' => 'title',
329
+ 'content' => 'Visual Options'
330
+ ),
331
+ 'visualTheme' => array(
332
+ 'type' => 'select',
333
+ 'name' => 'Button Shape',
334
+ 'content' => array(
335
+ 'flatFresh' => 'Flat & Fresh',
336
+ 'leaf' => 'A Leaf on the Wind',
337
+ 'shift' => 'Shift',
338
+ 'pill' => 'Pills',
339
+ 'threeDee' => 'Three-Dee',
340
+ 'connected' => 'Connected'
341
+ ),
342
+ 'default' => 'flatFresh'
343
+ ),
344
+ 'dColorSet' => array(
345
+ 'type' => 'select',
346
+ 'name' => 'Default Color Set',
347
+ 'content' => array(
348
+ 'fullColor' => 'Full Color',
349
+ 'lightGray' => 'Light Gray',
350
+ 'mediumGray' => 'Medium Gray',
351
+ 'darkGray' => 'Dark Gray',
352
+ 'lgOutlines' => 'Light Gray Outlines',
353
+ 'mdOutlines' => 'Medium Gray Outlines',
354
+ 'dgOutlines' => 'Dark Gray Outlines',
355
+ 'colorOutlines' => 'Color Outlines',
356
+ 'customColor' => 'Custom Color',
357
+ 'ccOutlines' => 'Custom Color Outlines'
358
+ ),
359
+ 'default' => 'fullColor'
360
+ ),
361
+ 'iColorSet' => array(
362
+ 'type' => 'select',
363
+ 'name' => 'Individual Hover Color Set',
364
+ 'content' => array(
365
+ 'fullColor' => 'Full Color',
366
+ 'lightGray' => 'Light Gray',
367
+ 'mediumGray' => 'Medium Gray',
368
+ 'darkGray' => 'Dark Gray',
369
+ 'lgOutlines' => 'Light Gray Outlines',
370
+ 'mdOutlines' => 'Medium Gray Outlines',
371
+ 'dgOutlines' => 'Dark Gray Outlines',
372
+ 'colorOutlines' => 'Color Outlines',
373
+ 'customColor' => 'Custom Color',
374
+ 'ccOutlines' => 'Custom Color Outlines'
375
+ ),
376
+ 'default' => 'fullColor'
377
+ ),
378
+ 'oColorSet' => array(
379
+ 'type' => 'select',
380
+ 'name' => 'Other Buttons Hover Color Set',
381
+ 'content' => array(
382
+ 'fullColor' => 'Full Color',
383
+ 'lightGray' => 'Light Gray',
384
+ 'mediumGray' => 'Medium Gray',
385
+ 'darkGray' => 'Dark Gray',
386
+ 'lgOutlines' => 'Light Gray Outlines',
387
+ 'mdOutlines' => 'Medium Gray Outlines',
388
+ 'dgOutlines' => 'Dark Gray Outlines',
389
+ 'colorOutlines' => 'Color Outlines',
390
+ 'customColor' => 'Custom Color',
391
+ 'ccOutlines' => 'Custom Color Outlines'
392
+ ),
393
+ 'default' => 'fullColor'
394
+ ),
395
+ 'buttonSize' => array(
396
+ 'type' => 'select',
397
+ 'name' => 'Button Size',
398
+ 'content' => array(
399
+ '1.4' => '140%',
400
+ '1.3' => '130%',
401
+ '1.2' => '120%',
402
+ '1.1' => '110%',
403
+ '1' => '100%',
404
+ '0.9' => '90%',
405
+ '0.8' => '80%',
406
+ '0.7' => '70%'
407
+ ),
408
+ 'default' => '1'
409
+ ),
410
+ 'buttonFloat' => array(
411
+ 'type' => 'select',
412
+ 'name' => 'Button Alignment (When Scaled)',
413
+ 'content' => array(
414
+ 'fullWidth' => 'Full Width',
415
+ 'left' => 'Left',
416
+ 'right' => 'Right',
417
+ 'center' => 'Center'
418
+ ),
419
+ 'default' => 'fullWidth'
420
+ ),
421
+ 'customColorDescription' => array(
422
+ 'type' => 'paragraph',
423
+ 'content' => '<h3 class="customColorLabel">Custom Color Selector</h3>Select your own custom color for the sharing buttons. You must have selected one of the "Custom Color" options in the "Color Set" drop down for this setting to have any effect. Please note that there is no dynamic preview above for the custom color setting...yet.'
424
+ ),
425
+ 'customColor' => array(
426
+ 'type' => 'colorselect',
427
+ 'name' => 'Custom Buttons Color',
428
+ 'default' => '#ffffff'
429
+ ),
430
+ 'buttonsPreview' => array(
431
+ 'type' => 'paragraph',
432
+ 'content' => '<div class="nc_socialPanel sw_flatFresh sw_d_fullColor sw_i_fullColor sw_o_fullColor" data-position="both" data-float="floatBottom" data-count="6" data-floatColor="#ffffff" data-scale="1" data-align="fullWidth"><div class="nc_tweetContainer googlePlus" data-id="2"><a target="_blank" href="https://plus.google.com/share?url=http%3A%2F%2Fwfa.re%2F1W28voz" data-link="https://plus.google.com/share?url=http%3A%2F%2Fwfa.re%2F1W28voz" class="nc_tweet"><span class="iconFiller"><span class="spaceManWilly"><i class="sw sw-google-plus"></i><span class="sw_share"> +1</span></span></span><span class="sw_count">1.2K</span></a></div><div class="nc_tweetContainer twitter" data-id="3"><a href="https://twitter.com/share?original_referer=/&text=Ultimate+Social+Share+%23WordPress+plugin%21+Beautiful%2C+super+fast+%26+more+http%3A%2F%2Fwarfareplugins.com+pic.twitter.com%2FA2zcCJwZtO&url=/&via=WarfarePlugins" data-link="https://twitter.com/share?original_referer=/&text=Ultimate+Social+Share+%23WordPress+plugin%21+Beautiful%2C+super+fast+%26+more+http%3A%2F%2Fwarfareplugins.com+pic.twitter.com%2FA2zcCJwZtO&url=/&via=WarfarePlugins" class="nc_tweet"><span class="iconFiller"><span class="spaceManWilly"><i class="sw sw-twitter"></i><span class="sw_share"> Tweet</span></span></span><span class="sw_count">280</span></a></div><div class="nc_tweetContainer nc_pinterest" data-id="6"><a data-link="https://pinterest.com/pin/create/button/?url=https://warfareplugins.com/&media=https%3A%2F%2Fwarfareplugins.com%2Fwp-content%2Fuploads%2Fget-content-shared-735x1102.jpg&description=Customize+your+Pinterest+sharing+options%2C+create+easy+%22click+to+tweet%22+buttons+within+your+blog+posts%2C+beautiful+sharing+buttons+and+more.+Social+Warfare+is+the+ultimate+social+sharing+arsenal+for+WordPress%21" class="nc_tweet" data-count="0"><span class="iconFiller"><span class="spaceManWilly" style="width:55px;"><i class="sw sw-pinterest"></i><span class="sw_share"> Pin</span></span></span><span class="sw_count">104</span></a></div><div class="nc_tweetContainer fb" data-id="4"><a target="_blank" href="http://www.facebook.com/share.php?u=http%3A%2F%2Fwfa.re%2F1W28vov" data-link="http://www.facebook.com/share.php?u=http%3A%2F%2Fwfa.re%2F1W28vov" class="nc_tweet"><span class="iconFiller"><span class="spaceManWilly"><i class="sw sw-facebook"></i><span class="sw_share"> Share</span></span></span><span class="sw_count">157</span></a></div><div class="nc_tweetContainer linkedIn" data-id="5"><a target="_blank" href="https://www.linkedin.com/cws/share?url=http%3A%2F%2Fwfa.re%2F1W28twH" data-link="https://www.linkedin.com/cws/share?url=http%3A%2F%2Fwfa.re%2F1W28twH" class="nc_tweet"><span class="iconFiller"><span class="spaceManWilly"><i class="sw sw-linkedin"></i><span class="sw_share"> Share</span></span></span><span class="sw_count">51</span></a></div><div class="nc_tweetContainer totes totesalt" data-id="6" ><span class="sw_count"><span class="sw_label">Total Shares</span> 1.8K</span></div></div>'
433
+ ),
434
+ 'decimalOptionDescription' => array(
435
+ 'type' => 'paragraph',
436
+ 'content' => 'Select the number of decimals to display on numbers greater than 1,000. Zero will display as 3K shares. One will display as 3.2K shares. Two will display as 3.24K Shares. We recommend one.'
437
+ ),
438
+ 'swDecimals' => array(
439
+ 'type' => 'select',
440
+ 'name' => 'Decimals',
441
+ 'content' => array(
442
+ '0' => 'Zero',
443
+ '1' => 'One',
444
+ '2' => 'Two'
445
+ ),
446
+ 'default' => '0'
447
+ ),
448
+ 'sw_decimal_separator' => array(
449
+ 'type' => 'select',
450
+ 'name' => 'Decimal Separator',
451
+ 'content' => array(
452
+ 'period' => 'Period',
453
+ 'comma' => 'Comma'
454
+ ),
455
+ 'default' => 'period'
456
+ ),
457
+ 'swTotesFormat' => array(
458
+ 'type' => 'select',
459
+ 'name' => 'Total Count Alignment',
460
+ 'content' => array(
461
+ 'totesAlt' => 'Right',
462
+ 'totesAltLeft' => 'Left'
463
+ ),
464
+ 'default' => 'totesAlt'
465
+ )
466
+ );
467
+
468
+ // Return the options value
469
+ return $sw_options;
470
+
471
+ }
472
+
473
+ /****************************************************************************************
474
+ * *
475
+ * The Social Warfare Floating Buttons *
476
+ * *
477
+ *****************************************************************************************/
478
+
479
+ function sw_options_floating_buttons($sw_options) {
480
+
481
+ // Declare the Display Settings tab and tab name
482
+ $sw_options['tabs']['links']['floatingButtons'] = 'Floating Buttons';
483
+
484
+ $sw_options['options']['floatingButtons'] = array(
485
+ 'floatingButtonsTitle' => array(
486
+ 'type' => 'title',
487
+ 'content' => 'Floating Share Buttons'
488
+ ),
489
+ 'float' => array(
490
+ 'type' => 'checkbox',
491
+ 'content' => 'Floating Share Buttons?',
492
+ 'default' => '1'
493
+ ),
494
+ 'floatOption' => array(
495
+ 'type' => 'select',
496
+ 'name' => 'Float Position',
497
+ 'content' => array(
498
+ 'top' => 'Top of the Page',
499
+ 'bottom' => 'Bottom of the Page',
500
+ 'left' => 'On the left side of the page'
501
+ ),
502
+ 'default' => 'bottom'
503
+ ),
504
+ 'floatStyle' => array(
505
+ 'type' => 'select',
506
+ 'name' => 'Float Style',
507
+ 'content' => array(
508
+ 'default' => 'Buttons',
509
+ 'boxed' => 'Boxes'
510
+ ),
511
+ 'default' => 'default'
512
+ ),
513
+ 'floatStyleSource' => array(
514
+ 'type' => 'checkbox',
515
+ 'content' => 'Style the buttons the same as the horizontal ones?',
516
+ 'default' => '1'
517
+ ),
518
+ 'sideDColorSet' => array(
519
+ 'type' => 'select',
520
+ 'name' => 'Default Color Set',
521
+ 'content' => array(
522
+ 'fullColor' => 'Full Color',
523
+ 'lightGray' => 'Light Gray',
524
+ 'mediumGray' => 'Medium Gray',
525
+ 'darkGray' => 'Dark Gray',
526
+ 'lgOutlines' => 'Light Gray Outlines',
527
+ 'mdOutlines' => 'Medium Gray Outlines',
528
+ 'dgOutlines' => 'Dark Gray Outlines',
529
+ 'colorOutlines' => 'Color Outlines',
530
+ 'customColor' => 'Custom Color',
531
+ 'ccOutlines' => 'Custom Color Outlines'
532
+ ),
533
+ 'default' => 'fullColor'
534
+ ),
535
+ 'sideIColorSet' => array(
536
+ 'type' => 'select',
537
+ 'name' => 'Individual Hover Color Set',
538
+ 'content' => array(
539
+ 'fullColor' => 'Full Color',
540
+ 'lightGray' => 'Light Gray',
541
+ 'mediumGray' => 'Medium Gray',
542
+ 'darkGray' => 'Dark Gray',
543
+ 'lgOutlines' => 'Light Gray Outlines',
544
+ 'mdOutlines' => 'Medium Gray Outlines',
545
+ 'dgOutlines' => 'Dark Gray Outlines',
546
+ 'colorOutlines' => 'Color Outlines',
547
+ 'customColor' => 'Custom Color',
548
+ 'ccOutlines' => 'Custom Color Outlines'
549
+ ),
550
+ 'default' => 'fullColor'
551
+ ),
552
+ 'sideOColorSet' => array(
553
+ 'type' => 'select',
554
+ 'name' => 'Other Buttons Hover Color Set',
555
+ 'content' => array(
556
+ 'fullColor' => 'Full Color',
557
+ 'lightGray' => 'Light Gray',
558
+ 'mediumGray' => 'Medium Gray',
559
+ 'darkGray' => 'Dark Gray',
560
+ 'lgOutlines' => 'Light Gray Outlines',
561
+ 'mdOutlines' => 'Medium Gray Outlines',
562
+ 'dgOutlines' => 'Dark Gray Outlines',
563
+ 'colorOutlines' => 'Color Outlines',
564
+ 'customColor' => 'Custom Color',
565
+ 'ccOutlines' => 'Custom Color Outlines'
566
+ ),
567
+ 'default' => 'fullColor'
568
+ ),
569
+ 'sideReveal' => array(
570
+ 'type' => 'select',
571
+ 'name' => 'Hide & Seek Transition',
572
+ 'content' => array(
573
+ 'slide' => 'Slide In / Slide Out',
574
+ 'fade' => 'Fade In / Fade Out'
575
+ ),
576
+ 'default' => 'slide'
577
+ ),
578
+ 'floatBgColor' => array(
579
+ 'type' => 'colorselect',
580
+ 'name' => 'Floating Background Color',
581
+ 'default' => '#ffffff'
582
+ ),
583
+ 'sw_float_scr_sz_description' => array(
584
+ 'type' => 'paragraph',
585
+ 'content' => 'Normally we use the width of the horizontal buttons located in the content to determine where the edge of the content area is located. This allows us to determine if there is enough space in the left margin to display the vertically stacked buttons. However, if you have the left floating buttons on a post or page without any horizontal buttons, this number will be used to determine at what screen sizes we should hide the floating buttons.'
586
+ ),
587
+ 'sw_float_scr_sz' => array(
588
+ 'type' => 'textbox',
589
+ 'content' => 'Minimum Screen Width',
590
+ 'default' => '1100'
591
+ )
592
+ );
593
+
594
+ return $sw_options;
595
+
596
+ }
597
+
598
+ /****************************************************************************************
599
+ * *
600
+ * The Social Warfare Link Shortening *
601
+ * *
602
+ *****************************************************************************************/
603
+
604
+ function sw_options_link_shortening($sw_options) {
605
+
606
+ $sw_user_options = sw_get_user_options();
607
+
608
+ // Establish the redirect URL for Bitly oAuth 2
609
+ $admin_ajax = admin_url( 'admin-ajax.php' );
610
+
611
+ if(isset($sw_user_options['bitly_access_token']) && $sw_user_options['bitly_access_token'] != ''):
612
+
613
+ $bitly_message = '<span style="color:green;">Authentication:</span> You have successfully authenticated Bitly for shortlinks. You may, however, switch to a different Bitly account if you\'d like.<br /><a class="button button-large" href="https://bitly.com/oauth/authorize?client_id=96c9b292c5503211b68cf4ab53f6e2f4b6d0defb&state='.$admin_ajax.'&redirect_uri=https://warfareplugins.com/bitly_oauth.php">Activate A Different Bitly Account</a>';
614
+
615
+ else:
616
+
617
+ $bitly_message = '<span style="color:red;">Authentication:</span> You must authorize Social Warfare to create short links in order for link-shortening to work.<br /><a class="button button-large" href="https://bitly.com/oauth/authorize?client_id=96c9b292c5503211b68cf4ab53f6e2f4b6d0defb&state='.$admin_ajax.'&redirect_uri=https://warfareplugins.com/bitly_oauth.php">Activate Bitly Link Shortening</a>';
618
+
619
+ endif;
620
+
621
+ // Declare the Display Settings tab and tab name
622
+ $sw_options['tabs']['links']['linkShortening'] = 'Link Shortening';
623
+
624
+ $sw_options['options']['linkShortening'] = array(
625
+ 'linkShorteningTitle' => array(
626
+ 'type' => 'title',
627
+ 'content' => 'Link Shortening'
628
+ ),
629
+ 'linkShortening' => array(
630
+ 'type' => 'checkbox',
631
+ 'content' => 'Activate Link Shortening?',
632
+ 'default' => false
633
+ ),
634
+ 'shorteningMethod' => array(
635
+ 'type' => 'select',
636
+ 'name' => 'Shortening Format',
637
+ 'content' => array(
638
+ 'bitly' => 'bit.ly'
639
+ ),
640
+ 'default' => 'bitly'
641
+ ),
642
+ 'bitly_oauth' => array(
643
+ 'type' => 'paragraph',
644
+ 'content' => $bitly_message
645
+ )
646
+ );
647
+
648
+ return $sw_options;
649
+
650
+ };
651
+ /****************************************************************************************
652
+ * *
653
+ * The Social Warfare Analytics *
654
+ * *
655
+ *****************************************************************************************/
656
+
657
+ function sw_options_analytics($sw_options) {
658
+
659
+ // Add the Analytics Tab and Tab Name
660
+ $sw_options['tabs']['links']['analytics'] = 'Analytics';
661
+
662
+ // Add the Analytics Options Arrays
663
+ $sw_options['options']['analytics'] = array(
664
+ 'analyticsTitle' => array(
665
+ 'type' => 'title',
666
+ 'content' => 'Analytics'
667
+ ),
668
+ 'analyticsDescription' => array(
669
+ 'type' => 'paragraph',
670
+ 'content' => 'This page will allow you to activate analytics tracking for links that are shared via the Social Warfare buttons. This will allow you to see exactly how much traffic is being driven to your site as a direct result of the plugin.'
671
+ ),
672
+ 'googleAnalytics' => array(
673
+ 'type' => 'checkbox',
674
+ 'content' => 'Activate Google Analytics Tracking?',
675
+ 'default' => 0
676
+ ),
677
+ 'analyticsMedium' => array(
678
+ 'type' => 'textbox',
679
+ 'content' => 'Analytics Medium',
680
+ 'default' => 'social'
681
+ ),
682
+ 'analyticsCampaign' => array(
683
+ 'type' => 'textbox',
684
+ 'content' => 'Analytics Campaign',
685
+ 'default' => 'SocialWarfare'
686
+ ),
687
+ 'sw_click_tracking' => array(
688
+ 'type' => 'checkbox',
689
+ 'content' => 'Activate Google Analytics Event Tracking for button clicks?',
690
+ 'default' => false
691
+ )
692
+ );
693
+
694
+ return $sw_options;
695
+ }
696
+ /****************************************************************************************
697
+ * *
698
+ * The Social Warfare Frame Buster *
699
+ * *
700
+ *****************************************************************************************/
701
+
702
+ function sw_options_frame_buster($sw_options) {
703
+
704
+ // Declare the Display Settings tab and tab name
705
+ $sw_options['tabs']['links']['frameBuster'] = 'Frame Buster';
706
+
707
+ $sw_options['options']['frameBuster'] = array(
708
+ 'frameBusterTitle' => array(
709
+ 'type' => 'title',
710
+ 'content' => 'Frame Buster'
711
+ ),
712
+ 'frameBusterParagraph' => array(
713
+ 'type' => 'paragraph',
714
+ 'content' => 'Frame Buster checks if your site is being displayed inside of a frame like Sniply or Start A Fire. If it is being displayed inside of a frame, the plugin will redirect to the page on your own domain, removing third party ads and calls to action.'
715
+ ),
716
+ 'sniplyBuster' => array(
717
+ 'type' => 'checkbox',
718
+ 'content' => 'Activate Frame Buster?',
719
+ 'default' => 0
720
+ )
721
+ );
722
+
723
+ return $sw_options;
724
+
725
+ };
726
+ /****************************************************************************************
727
+ * *
728
+ * The Social Warfare Click to Tweet *
729
+ * *
730
+ *****************************************************************************************/
731
+
732
+ function sw_options_clicktotweet($sw_options) {
733
+
734
+ // Add the Click to Tweet Tab and Tab Name
735
+ $sw_options['tabs']['links']['clicktotweet'] = 'Click to Tweet';
736
+
737
+ // Add the Click to Tweet Options Arrays
738
+ $sw_options['options']['clicktotweet'] = array(
739
+ 'clicktotweetTitle' => array(
740
+ 'type' => 'title',
741
+ 'content' => 'Click to Tweet'
742
+ ),
743
+ 'clicktotweetDescription' => array(
744
+ 'type' => 'paragraph',
745
+ 'content' => 'View the available visual styles below and then use this drop down to select the one that you would like to use on your site. If you have suggestions for new styles, please let us know.'
746
+ ),
747
+ 'cttTheme' => array(
748
+ 'type' => 'select',
749
+ 'name' => 'Visual Theme',
750
+ 'content' => array(
751
+ 'style1' => 'Send Her My Love',
752
+ 'style2' => 'Roll With The Changes',
753
+ 'style3' => 'Free Bird',
754
+ 'style4' => 'Don\'t Stop Believin\'',
755
+ 'style5' => 'Thunderstruck',
756
+ 'style6' => 'Livin\' On A Prayer',
757
+ 'none' => 'None - Create Your Own CSS In Your Theme'),
758
+ 'default' => 'style1'
759
+ ),
760
+ 'cttPreview' => array(
761
+ 'type' => 'paragraph',
762
+ 'content' => '<a class="sw_CTT style1" data-style="style1" href="https://twitter.com/share?text=We+couldn%27t+find+one+social+sharing+plugin+that+met+all+of+our+needs%2C+so+we+built+it+ourselves.&amp;url=http://warfareplugins.com&amp;via=warfareplugins" data-link="https://twitter.com/share?text=We+couldn%27t+find+one+social+sharing+plugin+that+met+all+of+our+needs%2C+so+we+built+it+ourselves.&amp;url=http://wfa.re/1PtqdNM&amp;via=WarfarePlugins" target="_blank"><span class="sw-click-to-tweet"><span class="sw-ctt-text">We couldn\'t find one social sharing plugin that met all of our needs, so we built it ourselves.</span><span class="sw-ctt-btn">Click To Tweet<i class="sw sw-twitter"></i></span></span></a>'
763
+ )
764
+ );
765
+
766
+ return $sw_options;
767
+ }
768
+ /****************************************************************************************
769
+ * *
770
+ * Twitter Share Counts *
771
+ * *
772
+ *****************************************************************************************/
773
+
774
+ function sw_options_tweet_counts($sw_options) {
775
+
776
+ // Add the Click to Tweet Tab and Tab Name
777
+ $sw_options['tabs']['links']['tweet_counts'] = 'Tweet Counts';
778
+
779
+ // Add the Click to Tweet Options Arrays
780
+ $sw_options['options']['tweet_counts'] = array(
781
+ 'twitter_shares_title' => array(
782
+ 'type' => 'title',
783
+ 'content' => 'Activate Tweet Counts'
784
+ ),
785
+ 'twitter_shares_description' => array(
786
+ 'type' => 'paragraph',
787
+ 'content' => 'In order to reinstate the ability to display and record tweet counts we\'ve partnered with New Share Counts. Here\'s what you need to do:<br /><br />1. <a target="_blank" href="http://newsharecounts.com" class="button">Click here to visit NewShareCounts.com</a><br /><br />2. At NewShareCounts.com, Enter your domain and click the "Sign in with Twitter" button.<br /><br /><img src="'.SW_PLUGIN_DIR.'/images/new_share_counts.png" ><br /><br />3. Flip the switch below to "ON" and then "Save Changes"'
788
+ ),
789
+ 'twitter_shares' => array(
790
+ 'type' => 'checkbox',
791
+ 'content' => 'Activate Twitter Shares?',
792
+ 'default' => false
793
+ )
794
+ );
795
+
796
+ return $sw_options;
797
+ }
798
+ /****************************************************************************************
799
+ * *
800
+ * Recover Shares *
801
+ * *
802
+ *****************************************************************************************/
803
+
804
+ function sw_options_recover_shares($sw_options) {
805
+
806
+ // Add the Recover Shares Tab and Tab Name
807
+ $sw_options['tabs']['links']['recover_shares'] = 'Share Recovery';
808
+
809
+ // Add the Recover Shares Options Arrays
810
+ $sw_options['options']['recover_shares'] = array(
811
+ 'recover_sharesTitle' => array(
812
+ 'type' => 'title',
813
+ 'content' => 'Share Counts Recovery'
814
+ ),
815
+ 'recoverSharesDescription' => array(
816
+ 'type' => 'paragraph',
817
+ 'content' => 'If you\'ve ever used a different URL format than you are currently using, this feature can be used to recover the share counts from those other URLs. Simply turn this features on and then select the URL pattern that you used along with the previous protocol. Once active, the plugin will begin to fetch shares for both the current URL pattern and the former one. It will add them together and display the new total. <br /><br />NOTE: It may take up to 24 hours for all the share counts to update to their combined totals. <br /><br />For information about each type of URL format <a target="_blank" href="https://codex.wordpress.org/Settings_Permalinks_Screen">Click Here</a>'
818
+ ),
819
+ 'recover_shares' => array(
820
+ 'type' => 'checkbox',
821
+ 'content' => 'Activate Share Count Recovery?',
822
+ 'default' => false
823
+ ),
824
+ 'recoverSharesDescription2' => array(
825
+ 'type' => 'paragraph',
826
+ 'content' => 'For any part of your permalink scheme that you have not changed, set the toggle to "UNCHANGED"'
827
+ ),
828
+ 'recovery_format' => array(
829
+ 'type' => 'select',
830
+ 'name' => 'Previous URL Format',
831
+ 'content' => array(
832
+ 'unchanged' => 'Unchanged',
833
+ 'default' => 'Plain',
834
+ 'day_and_name' => 'Day and Name',
835
+ 'month_and_name' => 'Month and Name',
836
+ 'numeric' => 'Numeric',
837
+ 'post_name' => 'Post Name',
838
+ 'custom' => 'Custom'
839
+ ),
840
+ 'default' => 'unchanged'
841
+ ),
842
+ 'recoverSharesDescription3' => array(
843
+ 'type' => 'paragraph',
844
+ 'content' => 'Select custom above to check shares for your own custom permalink structure. <a href="https://codex.wordpress.org/Using_Permalinks">Click Here</a> for WordPress permalink pattern information.'
845
+ ),
846
+ 'recovery_custom_format' => array(
847
+ 'type' => 'textbox',
848
+ 'content' => 'Custom Permalink Format',
849
+ 'default' => ''
850
+ ),
851
+ 'recovery_protocol' => array(
852
+ 'type' => 'select',
853
+ 'name' => 'Previous Connection Protocol',
854
+ 'content' => array(
855
+ 'unchanged' => 'Unchanged',
856
+ 'http' => 'http',
857
+ 'https' => 'https'
858
+ ),
859
+ 'default' => 'unchanged'
860
+ ),
861
+ 'recovery_prefix' => array(
862
+ 'type' => 'select',
863
+ 'name' => 'Previous Domain Prefix',
864
+ 'content' => array(
865
+ 'unchanged' => 'Unchanged',
866
+ 'www' => 'www',
867
+ 'nonwww' => 'non-www'
868
+ ),
869
+ 'default' => 'unchanged'
870
+ ),
871
+ 'recoverSharesDescription4' => array(
872
+ 'type' => 'paragraph',
873
+ 'content' => 'If you\'re blog is currently on a subdomain, but the previous version was not, enter your subdomain here, and we\'ll strip it out when we check the alternate version for shares.'
874
+ ),
875
+ 'recovery_subdomain' => array(
876
+ 'type' => 'textbox',
877
+ 'content' => 'Subdomain',
878
+ 'default' => ''
879
+ )
880
+ );
881
+
882
+ return $sw_options;
883
+
884
+ }
885
+ /****************************************************************************************
886
+ * *
887
+ * Rare Bugs & Their Fixes *
888
+ * *
889
+ *****************************************************************************************/
890
+
891
+ function sw_options_rare_bug_fixes($sw_options) {
892
+
893
+ // Declare the Display Settings tab and tab name
894
+ $sw_options['tabs']['links']['bugFixes'] = 'Rare Configurations';
895
+
896
+ $sw_options['options']['bugFixes'] = array(
897
+ 'visualOptionsBugFixTitle' => array(
898
+ 'type' => 'title',
899
+ 'content' => 'Rare Configuration Bugs & Their Fixes'
900
+ ),
901
+ 'rareBugsDescription' => array(
902
+ 'type' => 'paragraph',
903
+ 'content' => 'In some very rare cases, we\'ve encountered a few bugs that when fixed, end up creating bugs on other platforms. So instead of creating a universal fix for these issues, we have created the following options to be used on specific sites where the themes or plugins require the fix.'
904
+ ),
905
+ 'rawNumbersDescription' => array(
906
+ 'type' => 'paragraph',
907
+ 'content' => '<h3>Raw Share Information in Shares</h3>In some rare instances, raw share numbers and share information show up in front of the description when being shared. If this is happening on your site, simply activate this feature and the issue will go away. Most networks like Facebook will cache the information that they scraped from your page. As such, you can force a rescrape of your page by going to the following URL to see if it is indeed fixed: <a href="https://developers.facebook.com/tools/debug/" target="_blank">Facebook Open Graph Debugger.</a>'
908
+ ),
909
+ 'rawNumbers' => array(
910
+ 'type' => 'checkbox',
911
+ 'content' => 'Is raw share information displaying when sharing posts?',
912
+ 'default' => '0'
913
+ ),
914
+ 'visualEditorBugDescription' => array(
915
+ 'type' => 'paragraph',
916
+ 'content' => '<h3>Visual Editors</h3>If your theme (or a plugin) has you using a Visual Editor rather than the default WordPress post editor and if the buttons are not displaying properly or are doing something unusual then activating this option should fix you right up.'
917
+ ),
918
+ 'visualEditorBug' => array(
919
+ 'type' => 'checkbox',
920
+ 'content' => 'Are you using a visual editor that causes buttons to not behave?',
921
+ 'default' => '0'
922
+ ),
923
+ 'loopFixDescription' => array(
924
+ 'type' => 'paragraph',
925
+ 'content' => '<h3>Shares in Widget Areas</h3>If shares buttons are showing up in sidebar widgets or in related posts where a mini-loop of posts is being displayed and you want them turned off, activating this option should fix you right up.'
926
+ ),
927
+ 'loopFix' => array(
928
+ 'type' => 'checkbox',
929
+ 'content' => 'Are shares showing up on related posts or in widget areas?',
930
+ 'default' => '0'
931
+ ),
932
+ 'cacheMethodDescription' => array(
933
+ 'type' => 'paragraph',
934
+ 'content' => '<h3>Caching Method</h3>In order to supercharge the speed of the Social Warfare plugin, we only fetch new share counts every so often. When we do eventually fetch the share counts, we never do it while the page is loading. The first page load after the cache is expired sends a trigger back to the server to fetch updated numbers. However, if a site gets very little traffic, these cache rebuilds won\'t be triggered often. Instead, you may want to go ahead and fetch the share counts during the actual page load. This can add 1 to 3 seconds of additional time to the page loads when a page load is initiated with an expired cache that needs refreshed.'
935
+ ),
936
+ 'cacheMethod' => array(
937
+ 'type' => 'select',
938
+ 'name' => 'Cache Rebuild Method',
939
+ 'content' => array(
940
+ 'advanced' => 'Advanced Cache Triggering',
941
+ 'legacy' => 'Legacy Cache Rebuilding during Page Loads'
942
+ ),
943
+ 'default' => 'advanced'
944
+ )
945
+ );
946
+ return $sw_options;
947
+ }
948
+ /****************************************************************************************
949
+ * *
950
+ * The Social Warfare Registration *
951
+ * *
952
+ *****************************************************************************************/
953
+
954
+ function sw_options_registration($sw_options) {
955
+
956
+ // Add the Registration Tab and Tab Name
957
+ $sw_options['tabs']['links']['registration'] = 'Registration';
958
+
959
+ // Add the Registration Options Arrays
960
+ $sw_options['options']['registration'] = array(
961
+ 'registrationTitle' => array(
962
+ 'type' => 'title',
963
+ 'content' => 'Premium Registration'
964
+ )
965
+ );
966
+
967
+ $homeURL = get_home_url();
968
+ $regCode = md5($homeURL);
969
+
970
+ if(is_sw_registered()):
971
+ $sw_options['options']['registration']['registrationNotice'] = array(
972
+ 'type' => 'paragraph',
973
+ 'content' => '<span style="color:green" class="sw_registration_span sw_registered"><b>This copy of Social Warfare IS registered.</b></span>'
974
+ );
975
+ else:
976
+ $sw_options['options']['registration']['registrationNotice'] = array(
977
+ 'type' => 'paragraph',
978
+ 'content' => '<span style="color:#ed464f" class="sw_registration_span sw_not_registered"><b>This copy of Social Warfare IS NOT registered.</b></span>'
979
+ );
980
+ endif;
981
+
982
+ $sw_options['options']['registration']['registrationInstructions'] = array(
983
+ 'type' => 'paragraph',
984
+ 'content' => '
985
+ 1. Enter Your Email.<br />
986
+ 2. Click on the "Register Plugin" button.<br />
987
+ 3. Watch the magic.<br /><br />'
988
+ );
989
+
990
+ $sw_options['options']['registration']['registrationCode'] = array(
991
+ 'type' => 'paragraph',
992
+ 'content' => '
993
+ <div class="at-label"><label for="regCode">Registration Code</label></div><input type="text" class="at-text" name="regCode" id="regCode" value="'.$regCode.'" size="30" readonly><input type="hidden" class="at-text" name="domain" id="domain" value="'.$homeURL.'" size="30" readonly data-premcode="'.md5(md5($homeURL)).'"><div class="clearfix"></div>
994
+ '
995
+ );
996
+
997
+ $sw_options['options']['registration']['emailAddress'] = array(
998
+ 'type' => 'textbox',
999
+ 'content' => 'Email Address'
1000
+ );
1001
+
1002
+ $sw_options['options']['registration']['premiumCode'] = array(
1003
+ 'type' => 'textbox',
1004
+ 'content' => 'Premium Code'
1005
+ );
1006
+
1007
+ $sw_options['options']['registration']['registrationActivateButton'] = array(
1008
+ 'type' => 'paragraph',
1009
+ 'content' => '<input type="submit" class="activate btn-info" value="Register Plugin" />'
1010
+ );
1011
+
1012
+ $sw_options['options']['registration']['unregisterInstructions'] = array(
1013
+ 'type' => 'paragraph',
1014
+ 'content' => 'To unregister the plugin from this site, simply click the "Unregister Plugin" button below. This will disable it\'s functionality on this site, but will free up your license, allowing you to register this plugin to a different domain.'
1015
+ );
1016
+
1017
+ $sw_options['options']['registration']['unregisterButtons'] = array(
1018
+ 'type' => 'paragraph',
1019
+ 'content' => '<input type="submit" class="deactivate btn-info" value="Unregister Plugin" />'
1020
+ );
1021
+
1022
+ return $sw_options;
1023
+
1024
+ }
1025
+
1026
+ /****************************************************************************************
1027
+ * *
1028
+ * The Social Warfare System Status *
1029
+ * *
1030
+ *****************************************************************************************/
1031
+
1032
+ function sw_options_system_status($sw_options) {
1033
+
1034
+ // Add the System Status Tab and Tab Name
1035
+ $sw_options['tabs']['links']['systemstatus'] = 'System Status';
1036
+
1037
+ // Add the System Status Options Arrays
1038
+ $sw_options['options']['systemstatus'] = array(
1039
+ 'systemStatusTitle' => array(
1040
+ 'type' => 'title',
1041
+ 'content' => 'System Status'
1042
+ )
1043
+ );
1044
+
1045
+ if ( ! function_exists( 'get_plugins' ) ) {
1046
+ require_once ABSPATH . 'wp-admin/includes/plugin.php';
1047
+ }
1048
+ $plugins = get_plugins();
1049
+ $pluginList = '';
1050
+ foreach ($plugins as $plugin):
1051
+ $pluginList .= '<tr><td><b>'.$plugin['Name'].'</b></td><td>'.$plugin['Version'].'</td></tr>';
1052
+ endforeach;
1053
+
1054
+ if ( function_exists('fsockopen') ) :
1055
+ $fsockopen = '<span style="color:green;">Enabled</span>';
1056
+ else :
1057
+ $fsockopen = '<span style="color:red;">Disabled</span>';
1058
+ endif;
1059
+
1060
+ if ( function_exists('curl_version') ) :
1061
+ $curl_version = curl_version();
1062
+ $curl_status = '<span style="color:green;">Enabled: v'.$curl_version['version'].'</span>';
1063
+ else :
1064
+ $curl_status = '<span style="color:red;">Disabled</span>';
1065
+ endif;
1066
+
1067
+ $theme = wp_get_theme();
1068
+
1069
+ $sw_options['options']['systemstatus']['systemStatusOutput'] = array(
1070
+ 'type' => 'paragraph',
1071
+ 'content' => '
1072
+ <p>Please include all of the information on this page when reporting bugs or glitches. This will help us to more quickly identify any conflicts that may be interfering with the functioning of this plugin.</p>
1073
+ <table style="width:100%;">
1074
+ <tr><td><h2>Environment Statuses</h2></td><td></td></tr>
1075
+ <tr><td><b>Home URL</b></td><td>'.get_home_url().'</td></tr>
1076
+ <tr><td><b>Site URL</b></td><td>'.get_site_url().'</td></tr>
1077
+ <tr><td><b>WordPress Version</b></td><td>'.get_bloginfo('version').'</td></tr>
1078
+ <tr><td><b>PHP Version</b></td><td>'.phpversion().'</td></tr>
1079
+ <tr><td><b>WP Memory Limit</b></td><td>'.WP_MEMORY_LIMIT.'</td></tr>
1080
+ <tr><td><b>Social Warfare Version</b></td><td>'.SW_VERSION.'</td></tr>
1081
+ <tr><td><h2>Connection Statuses</h2></td><td></td></tr>
1082
+ <tr><td><b>fsockopen</b></td><td>'.$fsockopen.'</td></tr>
1083
+ <tr><td><b>cURL</b></td><td>'.$curl_status.'</td></tr>
1084
+ <tr><td><h2>Plugin Statuses</h2></td><td></td></tr>
1085
+ <tr><td><b>Theme Name</b></td><td>'.$theme['Name'].'</td></tr>
1086
+ <tr><td><b>Theme Version</b></td><td>'.$theme['Version'].'</td></tr>
1087
+ <tr><td><b>Active Plugins</b></td><td></td></tr>
1088
+ <tr><td><b>Number of Active Plugins</b></td><td>'.count($plugins).'</td></tr>
1089
+ '.$pluginList.'
1090
+
1091
+ </table>
1092
+ '
1093
+ );
1094
+
1095
+ return $sw_options;
1096
+
1097
+ };
1098
+
1099
+ /****************************************************************************************
1100
+ * *
1101
+ * Queue up the Options Filters *
1102
+ * *
1103
+ *****************************************************************************************/
1104
+
1105
+ add_filter('sw_options', 'sw_options_display_settings' , 1 );
1106
+ add_filter('sw_options', 'sw_options_visual_options' , 2 );
1107
+ add_filter('sw_options', 'sw_options_display_locations' , 3 );
1108
+ add_filter('sw_options', 'sw_options_floating_buttons' , 4 );
1109
+ add_filter('sw_options', 'sw_options_clicktotweet' , 5 );
1110
+ add_filter('sw_options', 'sw_options_tweet_counts' , 6 );
1111
+ add_filter('sw_options', 'sw_options_social_identity' , 7 );
1112
+ add_filter('sw_options', 'sw_options_link_shortening' , 8 );
1113
+ add_filter('sw_options', 'sw_options_analytics' , 9 );
1114
+ add_filter('sw_options', 'sw_options_frame_buster' , 10);
1115
+ add_filter('sw_options', 'sw_options_recover_shares' , 11);
1116
+ add_filter('sw_options', 'sw_options_rare_bug_fixes' , 12);
1117
+ add_filter('sw_options', 'sw_options_registration' , 99);
1118
+ add_filter('sw_options', 'sw_options_system_status' , 100);
1119
+
1120
+ /****************************************************************************************
1121
+ * *
1122
+ * The Social Warfare Options Function - Process the Options Array! *
1123
+ * *
1124
+ *****************************************************************************************/
1125
+
1126
+ // Queue up the Social Warfare options hook
1127
+ add_action('init' , 'sw_optionsClass' , 20);
1128
+
1129
+ // The Options Function which relies on the Options Array above
1130
+ function sw_optionsClass() {
1131
+
1132
+ // Fetch the Options Array - This is the sw_options filter hook
1133
+ global $sw_options;
1134
+ $sw_options = apply_filters('sw_options',$sw_options);
1135
+
1136
+ // Initiate the Options Class with the config settings in the array
1137
+ $options_panel = new BF_Admin_Page_Class($sw_options['config']);
1138
+
1139
+ // Open the Options Tabs Container
1140
+ $options_panel->OpenTabs_container('');
1141
+
1142
+ // Execute the list of options tabs
1143
+ $options_panel->TabsListing($sw_options['tabs']);
1144
+
1145
+ // Loop through the options tabs and build the options page
1146
+ foreach($sw_options['options'] as $tabName => $tabOptions):
1147
+ $options_panel->OpenTab($tabName);
1148
+
1149
+ // Loop through and output the options for this tab
1150
+ foreach($tabOptions as $key => $option):
1151
+
1152
+ // TITLE - Add a Title
1153
+ if($option['type'] == 'title'):
1154
+ $options_panel->Title($option['content']);
1155
+ endif;
1156
+
1157
+ // PARAGRAPH - Add a Paragraph of Information
1158
+ if($option['type'] == 'paragraph'):
1159
+ $options_panel->addParagraph($option['content']);
1160
+ endif;
1161
+
1162
+ // TEXTBOX - Add a Textbox option
1163
+ if($option['type'] == 'textbox'):
1164
+ if(isset($option['default'])):
1165
+ $options_panel->addText($key,array('name' => $option['content'], 'std' => $option['default']));
1166
+ else:
1167
+ $options_panel->addText($key,array('name' => $option['content']));
1168
+ endif;
1169
+ endif;
1170
+
1171
+ // CHECKBOX - Add a checkbox option
1172
+ if($option['type'] == 'checkbox'):
1173
+ $options_panel->addCheckbox($key,array('name' => $option['content'], $key => $key, 'std' => $option['default']));
1174
+ endif;
1175
+
1176
+ // SORTABLE - Add a sortable option
1177
+ if($option['type'] == 'sortable'):
1178
+ $options_panel->addSortable(
1179
+ $key,
1180
+ $option['content'],
1181
+ array('name' => $option['name'])
1182
+ );
1183
+ endif;
1184
+
1185
+ // SELECT - Add a select option
1186
+ if($option['type'] == 'select'):
1187
+ $options_panel->addSelect(
1188
+ $key,
1189
+ $option['content'],
1190
+ array(
1191
+ 'name' => $option['name'],
1192
+ 'std' => $option['default']
1193
+ )
1194
+ );
1195
+ endif;
1196
+
1197
+ // COLOROPTION - Add a color picker
1198
+ if($option['type'] == 'colorselect'):
1199
+ $options_panel->addColor(
1200
+ $key,
1201
+ array(
1202
+ 'name'=> $option['name'],
1203
+ 'std' => $option['default']
1204
+ )
1205
+ );
1206
+ endif;
1207
+
1208
+ endforeach;
1209
+
1210
+ // Close the tab and move on to the next one
1211
+ $options_panel->CloseTab();
1212
+ endforeach;
1213
+ };
1214
+
1215
+ /****************************************************************************************
1216
+ * *
1217
+ * The Social Warfare Add Option(s) After Hook Function *
1218
+ * *
1219
+ *****************************************************************************************/
1220
+
1221
+ function sw_add_option_after($sw_options,$tabName,$optionName,$newOptionArray) {
1222
+
1223
+ // Locate the index of the option you want to insert next to
1224
+ $keyIndex = array_search(
1225
+ $optionName,
1226
+ array_keys( $sw_options['options'][$tabName] )
1227
+ );
1228
+
1229
+ // Split the array at the location of the option above
1230
+ $first_array = array_splice (
1231
+ $sw_options['options'][$tabName],
1232
+ 0,
1233
+ $keyIndex+1
1234
+ );
1235
+
1236
+ // Merge the two parts of the split array with your option added in the middle
1237
+ $sw_options['options'][$tabName] = array_merge (
1238
+ $first_array,
1239
+ $newOptionArray,
1240
+ $sw_options['options'][$tabName]
1241
+ );
1242
+
1243
+ // Return the option array or the world will explode
1244
+ return $sw_options;
1245
+
1246
+ }
1247
+
1248
+ function sw_add_language_option($sw_options,$langName,$langCode) {
1249
+
1250
+ // Add our new language to the options page
1251
+ $sw_options['options']['displaySettings']['language']['content'][$langCode] = $langName;
1252
+
1253
+ // Return the option array or the world will explode
1254
+ return $sw_options;
1255
+
1256
+ }
1257
+
1258
+ function sw_add_network_option($sw_options,$newOptionArray) {
1259
+ // Locate the index of the option you want to insert next to
1260
+ $keyIndex = array_search(
1261
+ 'iconDisplayInfo',
1262
+ array_keys( $sw_options['options']['displaySettings'] )
1263
+ );
1264
+
1265
+ // Split the array at the location of the option above
1266
+ $first_array = array_splice (
1267
+ $sw_options['options']['displaySettings'],
1268
+ 0,
1269
+ $keyIndex+1
1270
+ );
1271
+
1272
+ // Merge the two parts of the split array with your option added in the middle
1273
+ $sw_options['options']['displaySettings'] = array_merge (
1274
+ $first_array,
1275
+ $newOptionArray,
1276
+ $sw_options['options']['displaySettings']
1277
+ );
1278
+
1279
+ $key = key($newOptionArray);
1280
+ $sw_options['options']['displaySettings']['newOrderOfIcons']['content'][$key] = $newOptionArray[$key]['content'];
1281
+
1282
+ // Return the option array or the world will explode
1283
+ return $sw_options;
1284
+ }
functions/permalinks.php ADDED
@@ -0,0 +1,285 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*****************************************************************
4
+
5
+ CHECK FOR ALTERNATE VERSION OF THE PERMALINK
6
+
7
+ ******************************************************************/
8
+ function get_alternate_permalink($format) {
9
+
10
+ // Setup the Default Permalink Structure
11
+ if($format == 'Default'):
12
+ $domain = get_site_url();
13
+ $id = get_the_ID();
14
+ $url = $domain.'/?p='.$id;
15
+
16
+ // Setup the "Day and name" Permalink Structure
17
+ elseif($format == 'Day and name'):
18
+ $domain = get_site_url();
19
+ $date = get_the_date('Y/m/d');
20
+ $slug = basename(get_permalink());
21
+ $url = $domain.'/'.$date.'/'.$slug.'/';
22
+
23
+ // Setup the "Month and name" Permalink Structure
24
+ elseif($format == 'Month and name'):
25
+ $domain = get_site_url();
26
+ $date = get_the_date('Y/m');
27
+ $slug = basename(get_permalink());
28
+ $url = $domain.'/'.$date.'/'.$slug.'/';
29
+
30
+ // Setup the "Numeric" Permalink Structure
31
+ elseif($format == 'Numeric'):
32
+ $domain = get_site_url();
33
+ $id = get_the_ID();
34
+ $url = $domain.'/archives/'.$id.'/';
35
+
36
+ // Setup the "Post name" Permalink Structure
37
+ elseif($format == 'Post Name'):
38
+ $domain = get_site_url();
39
+ $slug = basename(get_permalink());
40
+ $url = $domain.'/'.$slug.'/';
41
+
42
+ endif;
43
+
44
+ return $url;
45
+
46
+ }
47
+
48
+ /*****************************************************************
49
+
50
+ GENERATE THE ALTERNATE PERMALINK
51
+
52
+ ******************************************************************/
53
+ function sw_get_alternate_permalink($format,$protocol,$id,$prefix) {
54
+
55
+ // Setup the Default Permalink Structure
56
+ if($format == 'default'):
57
+ $domain = get_site_url();
58
+ $url = $domain.'/?p='.$id;
59
+
60
+ // Setup the "Day and name" Permalink Structure
61
+ elseif($format == 'day_and_name'):
62
+ $domain = get_site_url();
63
+ $date = get_the_date('Y/m/d',$id);
64
+ $slug = basename(get_permalink($id));
65
+ $url = $domain.'/'.$date.'/'.$slug.'/';
66
+
67
+ // Setup the "Month and name" Permalink Structure
68
+ elseif($format == 'month_and_name'):
69
+ $domain = get_site_url();
70
+ $date = get_the_date('Y/m',$id);
71
+ $slug = basename(get_permalink($id));
72
+ $url = $domain.'/'.$date.'/'.$slug.'/';
73
+
74
+ // Setup the "Numeric" Permalink Structure
75
+ elseif($format == 'numeric'):
76
+ $domain = get_site_url();
77
+ $url = $domain.'/archives/'.$id.'/';
78
+
79
+ // Setup the "Post name" Permalink Structure
80
+ elseif($format == 'post_name'):
81
+ $domain = get_site_url();
82
+ $post_data = get_post($id, ARRAY_A);
83
+ $slug = $post_data['post_name'];
84
+ $url = $domain.'/'.$slug.'/';
85
+ elseif($format == 'unchanged'):
86
+ $url = get_permalink($id);
87
+ endif;
88
+
89
+ // Check and Adjust the Protocol setting
90
+ if($protocol == 'unchanged'):
91
+ elseif($protocol == 'https' && strpos($url,'https') === false):
92
+ $url = str_replace('http','https',$url);
93
+ elseif($protocol == 'http' && strpos($url,'https') !== false):
94
+ $url = str_replace('https','http',$url);
95
+ endif;
96
+
97
+ // Check and Adjust the Prefix setting
98
+ if($prefix == 'unchanged'):
99
+ elseif($prefix == 'www' && strpos($url,'www') === false):
100
+ $url = str_replace('http://','http://www.',$url);
101
+ $url = str_replace('https://','https://www.',$url);
102
+ elseif($prefix == 'nonwww' && strpos($url,'www') !== false):
103
+ $url = str_replace('http://www.','http://',$url);
104
+ $url = str_replace('https://www.','https://',$url);
105
+ endif;
106
+
107
+ return $url;
108
+
109
+ }
110
+
111
+ function sw_get_alt_permalink( $post = 0, $leavename = false ) {
112
+
113
+ // Fetch the Social Warfare user's options
114
+ $sw_user_options = sw_get_user_options();
115
+
116
+ $rewritecode = array(
117
+ '%year%',
118
+ '%monthnum%',
119
+ '%day%',
120
+ '%hour%',
121
+ '%minute%',
122
+ '%second%',
123
+ $leavename? '' : '%postname%',
124
+ '%post_id%',
125
+ '%category%',
126
+ '%author%',
127
+ $leavename? '' : '%pagename%',
128
+ );
129
+
130
+ if ( is_object( $post ) && isset( $post->filter ) && 'sample' == $post->filter ) {
131
+ $sample = true;
132
+ } else {
133
+ $post = get_post( $post );
134
+ $sample = false;
135
+ }
136
+
137
+ if ( empty($post->ID) )
138
+ return false;
139
+
140
+ if ( $post->post_type == 'page' )
141
+ return get_page_link($post, $leavename, $sample);
142
+ elseif ( $post->post_type == 'attachment' )
143
+ return get_attachment_link( $post, $leavename );
144
+ elseif ( in_array($post->post_type, get_post_types( array('_builtin' => false) ) ) )
145
+ return get_post_permalink($post, $leavename, $sample);
146
+
147
+ // Build the structure
148
+ $structure = $sw_user_options['recovery_format'];
149
+
150
+ if($structure == 'custom'):
151
+ $permalink = $sw_user_options['recovery_custom_format'];
152
+ elseif($structure == 'unchanged'):
153
+ $permalink = get_option('permalink_structure');
154
+ elseif($structure == 'default'):
155
+ $permalink ='';
156
+ elseif($structure == 'day_and_name'):
157
+ $permalink ='/%year%/%monthnum%/%day%/%postname%/';
158
+ elseif($structure == 'month_and_name'):
159
+ $permalink ='/%year%/%monthnum%/%postname%/';
160
+ elseif($structure == 'numeric'):
161
+ $permalink ='/archives/%post_id%';
162
+ elseif($structure == 'post_name'):
163
+ $permalink ='/%postname%/';
164
+ else:
165
+ $permalink = get_option('permalink_structure');
166
+ endif;
167
+
168
+
169
+
170
+
171
+ /**
172
+ * Filter the permalink structure for a post before token replacement occurs.
173
+ *
174
+ * Only applies to posts with post_type of 'post'.
175
+ *
176
+ * @since 3.0.0
177
+ *
178
+ * @param string $permalink The site's permalink structure.
179
+ * @param WP_Post $post The post in question.
180
+ * @param bool $leavename Whether to keep the post name.
181
+ */
182
+ $permalink = apply_filters( 'pre_post_link', $permalink, $post, $leavename );
183
+
184
+ if ( '' != $permalink && !in_array( $post->post_status, array( 'draft', 'pending', 'auto-draft', 'future' ) ) ) {
185
+ $unixtime = strtotime($post->post_date);
186
+
187
+ $category = '';
188
+ if ( strpos($permalink, '%category%') !== false ) {
189
+ $cats = get_the_category($post->ID);
190
+ if ( $cats ) {
191
+ usort($cats, '_usort_terms_by_ID'); // order by ID
192
+
193
+ /**
194
+ * Filter the category that gets used in the %category% permalink token.
195
+ *
196
+ * @since 3.5.0
197
+ *
198
+ * @param stdClass $cat The category to use in the permalink.
199
+ * @param array $cats Array of all categories associated with the post.
200
+ * @param WP_Post $post The post in question.
201
+ */
202
+ $category_object = apply_filters( 'post_link_category', $cats[0], $cats, $post );
203
+
204
+ $category_object = get_term( $category_object, 'category' );
205
+ $category = $category_object->slug;
206
+ if ( $parent = $category_object->parent )
207
+ $category = get_category_parents($parent, false, '/', true) . $category;
208
+ }
209
+ // show default category in permalinks, without
210
+ // having to assign it explicitly
211
+ if ( empty($category) ) {
212
+ $default_category = get_term( get_option( 'default_category' ), 'category' );
213
+ $category = is_wp_error( $default_category ) ? '' : $default_category->slug;
214
+ }
215
+ }
216
+
217
+ $author = '';
218
+ if ( strpos($permalink, '%author%') !== false ) {
219
+ $authordata = get_userdata($post->post_author);
220
+ $author = $authordata->user_nicename;
221
+ }
222
+
223
+ $date = explode(" ",date('Y m d H i s', $unixtime));
224
+ $rewritereplace =
225
+ array(
226
+ $date[0],
227
+ $date[1],
228
+ $date[2],
229
+ $date[3],
230
+ $date[4],
231
+ $date[5],
232
+ $post->post_name,
233
+ $post->ID,
234
+ $category,
235
+ $author,
236
+ $post->post_name,
237
+ );
238
+ $permalink = home_url( str_replace($rewritecode, $rewritereplace, $permalink) );
239
+
240
+ if($structure != 'custom'):
241
+ $permalink = user_trailingslashit($permalink, 'single');
242
+ endif;
243
+
244
+ } else { // if they're not using the fancy permalink option
245
+ $permalink = home_url('?p=' . $post->ID);
246
+ }
247
+
248
+ /**
249
+ * Filter the permalink for a post.
250
+ *
251
+ * Only applies to posts with post_type of 'post'.
252
+ *
253
+ * @since 1.5.0
254
+ *
255
+ * @param string $permalink The post's permalink.
256
+ * @param WP_Post $post The post in question.
257
+ * @param bool $leavename Whether to keep the post name.
258
+ */
259
+ $url = apply_filters( 'post_link', $permalink, $post, $leavename );
260
+
261
+ // Filter the Protocol
262
+ if($sw_user_options['recovery_protocol'] == 'https' && strpos($url,'https') === false):
263
+ $url = str_replace('http','https',$url);
264
+ elseif($sw_user_options['recovery_protocol'] == 'http' && strpos($url,'https') !== false):
265
+ $url = str_replace('https','http',$url);
266
+ endif;
267
+
268
+ // Filter the prefix
269
+ if($sw_user_options['recovery_prefix'] == 'unchanged'):
270
+ elseif($sw_user_options['recovery_prefix'] == 'www' && strpos($url,'www') === false):
271
+ $url = str_replace('http://','http://www.',$url);
272
+ $url = str_replace('https://','https://www.',$url);
273
+ elseif($sw_user_options['recovery_prefix'] == 'nonwww' && strpos($url,'www') !== false):
274
+ $url = str_replace('http://www.','http://',$url);
275
+ $url = str_replace('https://www.','https://',$url);
276
+ endif;
277
+
278
+ // Filter out the subdomain
279
+ if(isset($sw_user_options['recovery_subdomain']) && $sw_user_options['recovery_subdomain'] != ''):
280
+ $url = str_replace($sw_user_options['recovery_subdomain'] . '.' , '' , $url);
281
+ endif;
282
+
283
+ return $url;
284
+
285
+ }
functions/post-options.php ADDED
@@ -0,0 +1,175 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*****************************************************************
4
+
5
+ SETUP THE POST EDITOR OPTIONS
6
+
7
+ ******************************************************************/
8
+
9
+ function sw_get_post_types() {
10
+
11
+ // Get the post Types
12
+ $postTypes = get_post_types();
13
+
14
+ // Unset the post types that don't matter
15
+ if(isset($postTypes['post'])) unset($postTypes['post']);
16
+ if(isset($postTypes['page'])) unset($postTypes['page']);
17
+ if(isset($postTypes['attachment'])) unset($postTypes['attachment']);
18
+ if(isset($postTypes['revision'])) unset($postTypes['revision']);
19
+ if(isset($postTypes['nav_menu_item'])) unset($postTypes['nav_menu_item']);
20
+ if(isset($postTypes['nf_sub'])) unset($postTypes['nf_sub']);
21
+ if(isset($postTypes['shop_order'])) unset($postTypes['shop_order']);
22
+ if(isset($postTypes['shop_order_refund'])) unset($postTypes['shop_order_refund']);
23
+ if(isset($postTypes['shop_coupon'])) unset($postTypes['shop_coupon']);
24
+ if(isset($postTypes['shop_webhook'])) unset($postTypes['shop_webhook']);
25
+
26
+ return $postTypes;
27
+
28
+ };
29
+
30
+ add_filter( 'rwmb_meta_boxes', 'nc_register_meta_boxes' );
31
+ function nc_register_meta_boxes( $meta_boxes )
32
+ {
33
+
34
+ // Setup the prefix to avoid conflicts
35
+ $prefix = 'nc_';
36
+ $options = sw_get_user_options();
37
+ $postTypes = sw_get_post_types();
38
+ foreach($postTypes as $key => $value):
39
+ $postType[] = $key;
40
+ endforeach;
41
+ $postType[] = 'page';
42
+ $postType[] = 'post';
43
+
44
+ // Setup our meta box using an array
45
+ $meta_boxes[0] = array(
46
+ 'id' => 'socialWarfare',
47
+ 'title' => 'Social Warfare Custom Options',
48
+ 'pages' => $postType,
49
+ 'context' => 'normal',
50
+ 'priority' => 'high',
51
+ 'fields' => array(
52
+
53
+ // Setup the social media image
54
+ array(
55
+ 'name' => '<span class="dashicons dashicons-share"></span> Social Media Image',
56
+ 'desc' => 'Add an image that is optimized for maximum exposure on Facebook, Google+ and LinkedIn. We recommend 1200px by 628px.',
57
+ 'id' => $prefix . 'ogImage',
58
+ 'type' => 'image_advanced',
59
+ 'clone' => false,
60
+ 'class' => $prefix . 'ogImageWrapper',
61
+ 'max_file_uploads' => 1
62
+ ),
63
+
64
+ // Setup the social media title
65
+ array(
66
+ 'name' => '<span class="dashicons dashicons-share"></span> Social Media Title',
67
+ 'desc' => 'Add a title that will populate the open graph meta tag which will be used when users share your content onto Facebook, LinkedIn, and Google+. If nothing is provided here, we will use the post title as a backup.',
68
+ 'id' => $prefix . 'ogTitle',
69
+ 'type' => 'textarea',
70
+ 'class' => $prefix . 'ogTitleWrapper',
71
+ 'clone' => false,
72
+ ),
73
+
74
+ // Setup the social media description
75
+ array(
76
+ 'name' => '<span class="dashicons dashicons-share"></span> Social Media Description',
77
+ 'desc' => 'Add a description that will populate the open graph meta tag which will be used when users share your content onto Facebook, LinkedIn, and Google Plus.',
78
+ 'id' => $prefix . 'ogDescription',
79
+ 'class' => $prefix . 'ogDescriptionWrapper',
80
+ 'type' => 'textarea',
81
+ 'clone' => false,
82
+ ),
83
+
84
+ // Divider
85
+ array(
86
+ 'name' => 'divider',
87
+ 'id' => 'divider',
88
+ 'type' => 'divider'
89
+ ),
90
+
91
+ // Setup the pinterest optimized image
92
+ array(
93
+ 'name' => '<i class="sw sw-pinterest"></i> Pinterest Image',
94
+ 'desc' => 'Add an image that is optimized for maximum exposure on Pinterest. We recommend using an image that is formated in a 2:3 aspect ratio like 735x1100.',
95
+ 'id' => $prefix . 'pinterestImage',
96
+ 'class' => $prefix . 'pinterestImageWrapper',
97
+ 'type' => 'image_advanced',
98
+ 'clone' => false,
99
+ 'max_file_uploads' => 1
100
+ ),
101
+
102
+ // Setup the pinterest description
103
+ array(
104
+ 'name' => '<i class="sw sw-pinterest"></i> Pinterest Description',
105
+ 'desc' => 'Place a customized message that will be used when this post is shared on Pinterest. Leave this blank to use the title of the post.',
106
+ 'id' => $prefix . 'pinterestDescription',
107
+ 'class' => $prefix . 'pinterestDescriptionWrapper',
108
+ 'type' => 'textarea',
109
+ 'clone' => false,
110
+ ),
111
+
112
+ // Setup the Custom Tweet box
113
+ array(
114
+ 'name' => '<i class="sw sw-twitter"></i> Custom Tweet',
115
+ 'desc' => 'If this is left blank your post title will be used. '.($options['twitterID'] ? 'Based on your username (@'.str_replace('@','',$options['twitterID']).'), <span class="tweetLinkSection">a link being added,</span> and the current content above' : '<span ="tweetLinkSection">Based on a link being added, and</span> the current content above').', your tweet has <span class="counterNumber">140</span> characters remaining.',
116
+ 'id' => $prefix . 'customTweet',
117
+ 'class' => $prefix . 'customTweetWrapper',
118
+ 'type' => 'textarea',
119
+ 'clone' => false,
120
+ ),
121
+
122
+ // Set up the location on post options
123
+ array(
124
+ 'name' => '<span class="dashicons dashicons-randomize"></span> Horizontal Buttons Location',
125
+ 'desc' => 'Where would you like to have the share buttons displayed on this post? Leave this option on "default" to use the settings you have selected on the Social Warfare settings page.',
126
+ 'id' => $prefix . 'postLocation',
127
+ 'class' => $prefix . 'postLocationWrapper',
128
+ 'type' => 'select',
129
+ 'options' => array(
130
+ 'default' => 'Default',
131
+ 'above'=>'Above the Content',
132
+ 'below' => 'Below the Content',
133
+ 'both' => 'Both Above and Below the Content',
134
+ 'none' => 'None/Manual Placement'),
135
+ 'clone' => false,
136
+ 'std' => 'default'
137
+ )
138
+ )
139
+ );
140
+
141
+
142
+ $meta_boxes[0]['fields'][] = array(
143
+ 'name' => '<span class="dashicons dashicons-randomize"></span> Side Floating Buttons Location',
144
+ 'desc' => 'Do you wish to have the floating sidebar buttons on this post?',
145
+ 'id' => $prefix . 'floatLocation',
146
+ 'class' => $prefix . 'floatLocationWrapper',
147
+ 'type' => 'select',
148
+ 'options' => array(
149
+ 'default' => 'Default',
150
+ 'on' => 'On',
151
+ 'off'=> 'Off'
152
+ ),
153
+ 'clone' => false,
154
+ 'std' => 'default'
155
+
156
+ );
157
+
158
+ $meta_boxes[0]['fields'][] = array(
159
+ 'name' => 'divider2',
160
+ 'id' => 'divider2',
161
+ 'type' => 'divider'
162
+ );
163
+
164
+ // Twitter ID
165
+ $meta_boxes[0]['fields'][] =array(
166
+ 'name' => $options['twitterID'],
167
+ 'id' => 'twitterID',
168
+ 'class' => 'twitterIDWrapper',
169
+ 'type' => 'hidden',
170
+ 'std' => $options['twitterID']
171
+ );
172
+
173
+ // Return the meta boxes
174
+ return $meta_boxes;
175
+ }
functions/profile-fields.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Queue up our profile field functions
4
+ add_action( 'show_user_profile', 'sw_show_user_profile_fields' );
5
+ add_action( 'edit_user_profile', 'sw_show_user_profile_fields' );
6
+ add_action( 'personal_options_update', 'sw_save_user_profile_fields' );
7
+ add_action( 'edit_user_profile_update', 'sw_save_user_profile_fields' );
8
+
9
+ // Display the new option on the user profile edit page
10
+ function sw_show_user_profile_fields( $user ) {
11
+ echo '<h3>Social Warfare Fields</h3>';
12
+ echo '<table class="form-table">';
13
+ echo '<tr>';
14
+ echo '<th><label for="twitter">Twitter Username</label></th>';
15
+ echo '<td>';
16
+ echo '<input type="text" name="sw_twitter" id="sw_twitter" value="'.esc_attr( get_the_author_meta( 'sw_twitter' , $user->ID ) ).'" class="regular-text" />';
17
+ echo '<br /><span class="description">Please enter your Twitter username (without the @ symbol).</span>';
18
+ echo '</td>';
19
+ echo '</tr>';
20
+ echo '<tr>';
21
+ echo '<th><label for="facebook_author">Facebook Author URL</label></th>';
22
+ echo '<td>';
23
+ echo '<input type="text" name="sw_fb_author" id="sw_fb_author" value="'.esc_attr( get_the_author_meta( 'sw_fb_author' , $user->ID ) ).'" class="regular-text" />';
24
+ echo '<br /><span class="description">Please enter the URL of your Facebok profile.</span>';
25
+ echo '</td>';
26
+ echo '</tr>';
27
+
28
+ echo '</table>';
29
+ }
30
+
31
+ // Save our fields when the page is udpated
32
+ function sw_save_user_profile_fields( $user_id ) {
33
+
34
+ if ( !current_user_can( 'edit_user', $user_id ) )
35
+ return false;
36
+
37
+ /* Copy and paste this line for additional fields. Make sure to change 'twitter' to the field ID. */
38
+ update_usermeta( $user_id, 'sw_twitter', $_POST['sw_twitter'] );
39
+ update_usermeta( $user_id, 'sw_fb_author', $_POST['sw_fb_author'] );
40
+ }
41
+
42
+ function sw_get_author( $post_id = 0 ){
43
+ $post = get_post( $post_id );
44
+ return $post->post_author;
45
+ }
functions/registration.php ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*****************************************************************
4
+
5
+ CHECK FOR PREMIUM ACTIVATION
6
+
7
+ ******************************************************************/
8
+ function is_sw_registered() {
9
+
10
+ // Fetch the User's Options Array
11
+ $sw_user_options = sw_get_user_options();
12
+
13
+ // Create a Registration Code from the Domain Name
14
+ $regCode = md5(get_home_url());
15
+
16
+ // If the Premium Code is currently set....
17
+ if(isset($sw_user_options['premiumCode']) && md5($regCode) == $sw_user_options['premiumCode']):
18
+
19
+ // It's registered
20
+ return true;
21
+
22
+ // IF the premium code doesn't match....
23
+ else:
24
+
25
+ // It's not registered
26
+ return false;
27
+
28
+ endif;
29
+ }
30
+
31
+ /*****************************************************************
32
+
33
+ ADMIN NOTICE
34
+
35
+ ******************************************************************/
36
+ function sw_admin_notice() {
37
+ if(!is_sw_registered()):
38
+ echo '<div class="notice is-dismissable sw_register_admin_notice"><p>Your copy of Social Warfare is not registered. Navigate to the <a href="/wp-admin/admin.php?page=social-warfare"><b>Social Warfare Settings Page</b></a> and select the "Register" tab to register now! You can view and manage your purchased licences on the <a target="_blank" href="https://warfareplugins.com/my-account/">My Account</a> page of the Warfare Plugins website. If you have any issues, please contact us and we\'ll be happy to help.</p></div>';
39
+ endif;
40
+ }
41
+ // add_action( 'admin_notices', 'sw_admin_notice' );
42
+
43
+ /*****************************************************************
44
+
45
+ CHECK WARFARE PLUGINS SERVER
46
+
47
+ ******************************************************************/
48
+
49
+ // A function to check if the site is registered at our server
50
+ function sw_check_registration_status() {
51
+
52
+
53
+ // Fetch the User's Options Array
54
+ $sw_user_options = sw_get_user_options();
55
+
56
+ // Fetch URL of the home page
57
+ $homeURL = get_home_url();
58
+
59
+ // Create a Registration Code from the Domain Name
60
+ $regCode = md5($homeURL);
61
+
62
+ // IF the plugin thinks that it is already registered....
63
+ if(is_sw_registered()):
64
+
65
+ // Construct the request URL
66
+ $url = 'https://warfareplugins.com/registration-api/?activity=check_registration&emailAddress='.$sw_user_options['emailAddress'].'&domain='.$homeURL.'&registrationCode='.md5($homeURL);
67
+
68
+ // Send the link and load the response
69
+ $response = sw_file_get_contents_curl($url);
70
+
71
+ // If the response is negative, unregister the plugin....
72
+ if($response == 'false'):
73
+
74
+ // Set the premium code to null
75
+ $sw_user_options['premiumCode'] = '';
76
+
77
+ // Update the options array with the premium code nulled
78
+ update_option('socialWarfareOptions',$sw_user_options);
79
+
80
+ endif;
81
+
82
+ // If the codes didn't match, but a premium code does exist
83
+ elseif(isset($sw_user_options['premiumCode'])):
84
+
85
+ // Attemp to unregister this from the Warfare Plugins Server
86
+ $url = 'https://warfareplugins.com/registration-api/?activity=unregister&emailAddress='.$sw_user_options['emailAddress'].'&premiumCode='.$sw_user_options['premiumCode'];
87
+
88
+ // Parse the response
89
+ $response = sw_file_get_contents_curl($url);
90
+ $response = json_decode($response,true);
91
+
92
+ // If it unregistered, let's try to auto-reregister it....
93
+ if($response['status'] == 'Success'):
94
+
95
+ // Attempt to reregister it
96
+ $url = 'https://warfareplugins.com/registration-api/?activity=register&emailAddress='.$sw_user_options['emailAddress'].'&domain='.get_home_url().'&registrationCode='.$regCode;
97
+
98
+ // Parse the response
99
+ $response = sw_file_get_contents_curl($url);
100
+ $response = json_decode($response,true);
101
+
102
+ // IF the registration attempt was successful....
103
+ if($response['status'] == 'Success'):
104
+
105
+ // Save our updated options
106
+ $sw_user_options['premiumCode'] == $response['premiumCode'];
107
+
108
+ // Update the options storing in our new updated Premium Code
109
+ update_option('socialWarfareOptions',$sw_user_options);
110
+
111
+ return true;
112
+
113
+ // IF the registration attempt was NOT successful
114
+ else:
115
+
116
+ // Set the premium code to null
117
+ $sw_user_options['premiumCode'] = '';
118
+
119
+ // Update the options array with the premium code nulled
120
+ update_option('socialWarfareOptions',$sw_user_options);
121
+
122
+ return false;
123
+
124
+ endif;
125
+
126
+ // IF it wasn't able to unregister
127
+ else:
128
+
129
+ // Set the premium code to null
130
+ $sw_user_options['premiumCode'] = '';
131
+
132
+ // Update the options array with the premium code nulled
133
+ update_option('socialWarfareOptions',$sw_user_options);
134
+
135
+ return false;
136
+
137
+ endif;
138
+
139
+ endif;
140
+ }
141
+
142
+
143
+
144
+
145
+
146
+
147
+
functions/share-count-class.php ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*****************************************************************
4
+ * *
5
+ * cURL - A Function to Process cURL requests *
6
+ * *
7
+ ******************************************************************/
8
+
9
+ function sw_file_get_contents_curl($url){
10
+ $ch=curl_init();
11
+ curl_setopt($ch, CURLOPT_URL, $url);
12
+ curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
13
+ curl_setopt($ch, CURLOPT_FAILONERROR, 0);
14
+ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
15
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
16
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
17
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
18
+ curl_setopt($ch, CURLOPT_TIMEOUT, 5);
19
+ curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
20
+ curl_setopt($ch, CURLOPT_NOSIGNAL, 1);
21
+ curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
22
+ $cont = @curl_exec($ch);
23
+ $curl_errno = curl_errno($ch);
24
+ if ($curl_errno > 0) {
25
+ return 0;
26
+ }
27
+ return $cont;
28
+ }
29
+
30
+ /*****************************************************************
31
+ * *
32
+ * Twitter - A Function to Fetch Twitter Shares *
33
+ * *
34
+ ******************************************************************/
35
+
36
+ function sw_fetch_twitter_shares($url) {
37
+ $url = rawurlencode($url);
38
+ $json_string = sw_file_get_contents_curl('https://urls.api.twitter.com/1/urls/count.json?url=' . $url);
39
+ $json = json_decode($json_string, true);
40
+ return isset($json['count'])?intval($json['count']):0;
41
+ }
42
+
43
+ /*****************************************************************
44
+ * *
45
+ * Facebook - A Function to Fetch Facebook Shares *
46
+ * *
47
+ ******************************************************************/
48
+
49
+ function sw_fetch_facebook_shares($url) {
50
+ $url = rawurlencode($url);
51
+ $json_string = sw_file_get_contents_curl('https://api.facebook.com/restserver.php?method=links.getStats&format=json&urls='.$url);
52
+ $json = json_decode($json_string, true);
53
+ return isset($json[0]['total_count'])?intval($json[0]['total_count']):0;
54
+ }
55
+
56
+ /*****************************************************************
57
+ * *
58
+ * GooglePlus - A Function to Fetch GooglePlus Shares *
59
+ * *
60
+ ******************************************************************/
61
+
62
+ function sw_fetch_googlePlus_shares($url) {
63
+ $url = rawurlencode($url);
64
+ $curl = curl_init();
65
+ curl_setopt($curl, CURLOPT_URL, "https://clients6.google.com/rpc");
66
+ curl_setopt($curl, CURLOPT_POST, true);
67
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
68
+ curl_setopt($curl, CURLOPT_POSTFIELDS, '[{"method":"pos.plusones.get","id":"p","params":{"nolog":true,"id":"'.rawurldecode($url).'","source":"widget","userId":"@viewer","groupId":"@self"},"jsonrpc":"2.0","key":"p","apiVersion":"v1"}]');
69
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
70
+ curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-type: application/json'));
71
+ $curl_results = curl_exec ($curl);
72
+ curl_close ($curl);
73
+ $json = json_decode($curl_results, true);
74
+ return isset($json[0]['result']['metadata']['globalCounts']['count'])?intval( $json[0]['result']['metadata']['globalCounts']['count'] ):0;
75
+ }
76
+
77
+ /*****************************************************************
78
+ * *
79
+ * Pinterest - A Function to Fetch Pinterest Shares *
80
+ * *
81
+ ******************************************************************/
82
+
83
+ function sw_fetch_pinterest_shares($url) {
84
+ $url = rawurlencode($url);
85
+ $return_data = sw_file_get_contents_curl('https://api.pinterest.com/v1/urls/count.json?url='.$url);
86
+ $json_string = preg_replace('/^receiveCount\((.*)\)$/', "\\1", $return_data);
87
+ $json = json_decode($json_string, true);
88
+ return isset($json['count'])?intval($json['count']):0;
89
+ }
90
+
91
+ /*****************************************************************
92
+ * *
93
+ * LinkedIn - A Function to Fetch LinkedIn Shares *
94
+ * *
95
+ ******************************************************************/
96
+
97
+ function sw_fetch_linkedIn_shares($url) {
98
+ $url = rawurlencode($url);
99
+ $json_string = sw_file_get_contents_curl('https://www.linkedin.com/countserv/count/share?url='.$url.'&format=json');
100
+ $json = json_decode($json_string, true);
101
+ return isset($json['count'])?intval($json['count']):0;
102
+ }
functions/share-count-function.php ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*****************************************************************
4
+ * *
5
+ * FUNCTION TO FETCH ALL THE NETWORK SHARES *
6
+ * *
7
+ ******************************************************************/
8
+ function get_social_warfare_shares($postID) {
9
+
10
+ // Set the initial options
11
+ $options = sw_get_user_options();
12
+ $url = get_permalink( $postID );
13
+ // $url = 'https://youtu.be/jjK1aUU2Dx4';
14
+
15
+ /*****************************************************************
16
+ * *
17
+ * Check the Cache *
18
+ * *
19
+ ******************************************************************/
20
+
21
+ $freshCache = sw_is_cache_fresh($postID);
22
+ // $freshCache = false;
23
+
24
+ /*****************************************************************
25
+ * *
26
+ * Setup the Networks Array that we'll loop through *
27
+ * *
28
+ ******************************************************************/
29
+
30
+ // Initiate the ShareCount class
31
+ $shares['totes'] = 0;
32
+
33
+ // Queue up the networks that are available
34
+ $availableNetworks = $options['newOrderOfIcons'];
35
+ $networks = array();
36
+ foreach($availableNetworks as $key => $value):
37
+ if($options[$key]) $networks[] = $key;
38
+ endforeach;
39
+
40
+ /*****************************************************************
41
+ * *
42
+ * Loop through the Networks *
43
+ * *
44
+ ******************************************************************/
45
+
46
+ // Loop through the networks and fetch their share counts
47
+ foreach($networks as $network):
48
+
49
+ // Check if this network is even activated
50
+ if( $options[$network] ):
51
+
52
+ // Check if we can used the cached share numbers
53
+ if($freshCache == true):
54
+ $shares[$network] = get_post_meta($postID,'_'.$network.'_shares',true);
55
+
56
+ // If cache is expired, fetch new and update the cache
57
+ else:
58
+ $old_shares[$network] = get_post_meta($postID,'_'.$network.'_shares',true);
59
+ $share_links[$network] = call_user_func('sw_'.$network.'_request_link',$url);
60
+ endif;
61
+ endif;
62
+ endforeach;
63
+
64
+ // Recover Shares From Previously Used URL Patterns
65
+ if($options['recover_shares'] == true && $freshCache == false):
66
+
67
+ $alternateURL = sw_get_alt_permalink($postID);
68
+ $alternateURL = apply_filters('sw_recovery_filter',$alternateURL);
69
+
70
+ // Debug the Alternate URL being checked
71
+ if(isset($_GET['sw_recovery_debug']) && $_GET['sw_recovery_debug'] == true):
72
+ echo $alternateURL;
73
+ endif;
74
+
75
+ foreach($networks as $network):
76
+
77
+ // Check if this network is even activated
78
+ if( $options[$network] ):
79
+
80
+ $old_share_links[$network] = call_user_func('sw_'.$network.'_request_link',$alternateURL);
81
+
82
+ endif;
83
+
84
+ endforeach;
85
+ endif;
86
+
87
+ if($freshCache == true):
88
+ if(get_post_meta($postID,'_totes',true)) :
89
+ $shares['totes'] = get_post_meta($postID,'_totes',true);
90
+ else:
91
+ $shares['totes'] = 0;
92
+ endif;
93
+ else:
94
+
95
+ // Fetch all the share counts asyncrounously
96
+ $raw_shares_array = sw_fetch_shares_via_curl_multi($share_links);
97
+ if($options['recover_shares'] == true):
98
+ $old_raw_shares_array = sw_fetch_shares_via_curl_multi($old_share_links);
99
+ endif;
100
+
101
+ foreach($networks as $network):
102
+
103
+ // Check if this network is even activated
104
+ if( $options[$network] ):
105
+
106
+ if(!isset($raw_shares_array[$network])) $raw_shares_array[$network] = 0;
107
+ if(!isset($old_raw_shares_array[$network])) $old_raw_shares_array[$network] = 0;
108
+
109
+ $shares[$network] = call_user_func('sw_format_'.$network.'_response',$raw_shares_array[$network]);
110
+ if($options['recover_shares'] == true):
111
+ $recovered_shares[$network] = call_user_func('sw_format_'.$network.'_response',$old_raw_shares_array[$network]);
112
+ if($shares[$network] != $recovered_shares[$network]):
113
+ $shares[$network] = $shares[$network] + $recovered_shares[$network];
114
+ endif;
115
+ endif;
116
+ if($shares[$network] <= $old_shares[$network]):
117
+ $shares[$network] = $old_shares[$network];
118
+ else:
119
+ delete_post_meta($postID,'_'.$network.'_shares');
120
+ update_post_meta($postID,'_'.$network.'_shares',$shares[$network]);
121
+ endif;
122
+ $shares['totes'] += $shares[$network];
123
+
124
+ endif;
125
+
126
+ endforeach;
127
+ endif;
128
+
129
+ /*****************************************************************
130
+ * *
131
+ * Update the Cache and Return the Share Counts *
132
+ * *
133
+ ******************************************************************/
134
+
135
+ if($freshCache != true):
136
+
137
+ // Clean out the previously used custom meta fields
138
+ delete_post_meta($postID,'_totes');
139
+
140
+ // Add the new data to the custom meta fields
141
+ update_post_meta($postID,'_totes',$shares['totes']);
142
+
143
+ endif;
144
+
145
+ // Return the share counts
146
+ return $shares;
147
+
148
+ }
functions/social-networks/buffer.php ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*****************************************************************
4
+ * *
5
+ * #1: Add the On / Off Switch and Sortable Option *
6
+ * *
7
+ ******************************************************************/
8
+ add_filter('sw_options', 'sw_buffer_options_function',20);
9
+ function sw_buffer_options_function($sw_options) {
10
+
11
+ // Create the new option in a variable to be inserted
12
+ $buffer = array(
13
+ 'buffer' => array(
14
+ 'type' => 'checkbox',
15
+ 'content' => 'Buffer',
16
+ 'default' => false
17
+ )
18
+ );
19
+
20
+ // Call the function that adds the On / Off Switch and Sortable Option
21
+ return sw_add_network_option($sw_options,$buffer);
22
+
23
+ };
24
+ /*****************************************************************
25
+ * *
26
+ * #2: Add it to global network array *
27
+ * *
28
+ ******************************************************************/
29
+ // Queue up your filter to be ran on the sw_options hook.
30
+ add_filter('sw_add_networks', 'sw_buffer_network');
31
+
32
+ // Create the function that will filter the options
33
+ function sw_buffer_network($networks) {
34
+
35
+ // Add your network to the existing network array
36
+ $networks[] = 'buffer';
37
+
38
+ // Be sure to return the modified options array or the world will explode
39
+ return $networks;
40
+ };
41
+ /*****************************************************************
42
+ * *
43
+ * #3: Generate the API Share Count Request URL *
44
+ * *
45
+ ******************************************************************/
46
+ function sw_buffer_request_link($url) {
47
+ $request_url = 'https://api.bufferapp.com/1/links/shares.json?url='.$url;
48
+ return $request_url;
49
+ }
50
+ /*****************************************************************
51
+ * *
52
+ * #4: Parse the Response to get the share count *
53
+ * *
54
+ ******************************************************************/
55
+ function sw_format_buffer_response($response) {
56
+ $response = json_decode($response, true);
57
+ return isset($response['shares'])?intval($response['shares']):0;
58
+ }
59
+ /*****************************************************************
60
+ * *
61
+ * #5: Create the Button HTML *
62
+ * *
63
+ ******************************************************************/
64
+ add_filter('sw_network_buttons', 'sw_buffer_button_html',10);
65
+ function sw_buffer_button_html($array) {
66
+
67
+ // If we've already generated this button, just use our existing html
68
+ if(isset($_GLOBALS['sw']['buttons'][$array['postID']]['buffer'])):
69
+ $array['resource']['buffer'] = $_GLOBALS['sw']['buttons'][$array['postID']]['buffer'];
70
+
71
+ // If not, let's check if Buffer is activated and create the button HTML
72
+ elseif( $array['options']['buffer'] ):
73
+
74
+ // Collect the Title
75
+ $title = get_post_meta( $array['postID'] , 'nc_ogTitle' , true );
76
+ if(!$title):
77
+ $title = get_the_title();
78
+ endif;
79
+
80
+ $array['totes'] += $array['shares']['buffer'];
81
+ ++$array['count'];
82
+
83
+ $array['resource']['buffer'] = '<div class="nc_tweetContainer sw_buffer" data-id="'.$array['count'].'" data-network="buffer">';
84
+ $link = urlencode(urldecode(sw_process_url( $array['url'] , 'buffer' , $array['postID'] )));
85
+ $array['resource']['buffer'] .= '<a target="_blank" href="http://bufferapp.com/add?url='.$link.'&text='.urlencode($title).'" data-link="http://bufferapp.com/add?url='.$link.'&text='.urlencode($title).'" class="nc_tweet buffer_link">';
86
+ if($array['options']['totesEach'] && $array['shares']['totes'] >= $array['options']['minTotes'] && $array['shares']['buffer'] > 0):
87
+ $array['resource']['buffer'] .= '<span class="iconFiller">';
88
+ $array['resource']['buffer'] .= '<span class="spaceManWilly">';
89
+ $array['resource']['buffer'] .= '<i class="sw sw-buffer"></i>';
90
+ $array['resource']['buffer'] .= '<span class="sw_share"> '.$array['language']['buffer'].'</span>';
91
+ $array['resource']['buffer'] .= '</span></span>';
92
+ $array['resource']['buffer'] .= '<span class="sw_count">'.kilomega($array['shares']['buffer']).'</span>';
93
+ else:
94
+ $array['resource']['buffer'] .= '<span class="sw_count sw_hide"><span class="iconFiller"><span class="spaceManWilly"><i class="sw sw-buffer"></i><span class="sw_share"> '.$array['language']['buffer'].'</span></span></span></span>';
95
+ endif;
96
+ $array['resource']['buffer'] .= '</a>';
97
+ $array['resource']['buffer'] .= '</div>';
98
+
99
+ // Store these buttons so that we don't have to generate them for each set
100
+ $_GLOBALS['sw']['buttons'][$array['postID']]['buffer'] = $array['resource']['buffer'];
101
+
102
+ endif;
103
+
104
+ return $array;
105
+
106
+ };
functions/social-networks/email.php ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*****************************************************************
4
+ * *
5
+ * #1: Add the On / Off Switch and Sortable Option *
6
+ * *
7
+ ******************************************************************/
8
+ add_filter('sw_options', 'sw_email_options_function',20);
9
+ function sw_email_options_function($sw_options) {
10
+
11
+ // Create the new option in a variable to be inserted
12
+ $email = array(
13
+ 'email' => array(
14
+ 'type' => 'checkbox',
15
+ 'content' => 'Email',
16
+ 'default' => 0
17
+ )
18
+ );
19
+
20
+ // Call the function that adds the On / Off Switch and Sortable Option
21
+ return sw_add_network_option($sw_options,$email);
22
+
23
+ };
24
+ /*****************************************************************
25
+ * *
26
+ * #2: Add it to global network array *
27
+ * *
28
+ ******************************************************************/
29
+ // Queue up your filter to be ran on the sw_options hook.
30
+ add_filter('sw_add_networks', 'sw_email_network');
31
+
32
+ // Create the function that will filter the options
33
+ function sw_email_network($networks) {
34
+
35
+ // Add your network to the existing network array
36
+ $networks[] = 'email';
37
+
38
+ // Be sure to return the modified options array or the world will explode
39
+ return $networks;
40
+ };
41
+ /*****************************************************************
42
+ * *
43
+ * #3: Generate the API Share Count Request URL *
44
+ * *
45
+ ******************************************************************/
46
+ function sw_email_request_link($url) {
47
+ return 0;
48
+ }
49
+ /*****************************************************************
50
+ * *
51
+ * #4: Parse the Response to get the share count *
52
+ * *
53
+ ******************************************************************/
54
+ function sw_format_email_response($response) {
55
+ return 0;
56
+ }
57
+ /*****************************************************************
58
+ * *
59
+ * #5: Create the Button HTML *
60
+ * *
61
+ ******************************************************************/
62
+ add_filter('sw_network_buttons', 'sw_email_button_html',10);
63
+ function sw_email_button_html($array) {
64
+
65
+ if( $array['options']['email'] ):
66
+
67
+ // Collect the Title
68
+ $title = get_post_meta( $array['postID'] , 'nc_ogTitle' , true );
69
+ if(!$title):
70
+ $title = get_the_title();
71
+ endif;
72
+
73
+ // Collect the Description
74
+ $description = get_post_meta( $array['postID'] , 'nc_ogDescription' , true );
75
+ if(!$description):
76
+ $description = sw_get_excerpt_by_id($array['postID']);
77
+ endif;
78
+ ++$array['count'];
79
+
80
+ $array['resource']['email'] = '<div class="nc_tweetContainer sw_email" data-id="'.$array['count'].'" data-network="email">';
81
+ $link = urlencode(urldecode(sw_process_url( $array['url'] , 'email' , $array['postID'] )));
82
+ $array['resource']['email'] .= '<a href="mailto:?subject='.rawurlencode($title).'&body='.rawurlencode($description).rawurlencode(' Read here: ') .$link.'" class="nc_tweet">';
83
+ $array['resource']['email'] .= '<span class="sw_count sw_hide"><span class="iconFiller"><span class="spaceManWilly"><i class="sw sw-email"></i><span class="sw_share"> '.$array['language']['email'].'</span></span></span></span>';
84
+ $array['resource']['email'] .= '</a>';
85
+ $array['resource']['email'] .= '</div>';
86
+
87
+ endif;
88
+
89
+ return $array;
90
+
91
+ };
functions/social-networks/facebook.php ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*****************************************************************
4
+ * *
5
+ * #1: Add the On / Off Switch and Sortable Option *
6
+ * *
7
+ ******************************************************************/
8
+ add_filter('sw_options', 'sw_facebook_options_function',20);
9
+ function sw_facebook_options_function($sw_options) {
10
+
11
+ // Create the new option in a variable to be inserted
12
+ $facebook = array(
13
+ 'facebook' => array(
14
+ 'type' => 'checkbox',
15
+ 'content' => 'Facebook',
16
+ 'default' => 1
17
+ )
18
+ );
19
+
20
+ // Call the function that adds the On / Off Switch and Sortable Option
21
+ return sw_add_network_option($sw_options,$facebook);
22
+
23
+ };
24
+ /*****************************************************************
25
+ * *
26
+ * #2: Add it to global network array *
27
+ * *
28
+ ******************************************************************/
29
+ // Queue up your filter to be ran on the sw_options hook.
30
+ add_filter('sw_add_networks', 'sw_facebook_network');
31
+
32
+ // Create the function that will filter the options
33
+ function sw_facebook_network($networks) {
34
+
35
+ // Add your network to the existing network array
36
+ $networks[] = 'facebook';
37
+
38
+ // Be sure to return the modified options array or the world will explode
39
+ return $networks;
40
+ };
41
+ /*****************************************************************
42
+ * *
43
+ * #3: Generate the API Share Count Request URL *
44
+ * *
45
+ ******************************************************************/
46
+ function sw_facebook_request_link($url) {
47
+ $request_url = 'https://api.facebook.com/restserver.php?method=links.getStats&format=json&urls='.$url;
48
+ return $request_url;
49
+ }
50
+ /*****************************************************************
51
+ * *
52
+ * #4: Parse the Response to get the share count *
53
+ * *
54
+ ******************************************************************/
55
+ function sw_format_facebook_response($response) {
56
+ $response = json_decode($response, true);
57
+ return isset($response[0]['total_count'])?intval($response[0]['total_count']):0;
58
+ }
59
+ /*****************************************************************
60
+ * *
61
+ * #5: Create the Button HTML *
62
+ * *
63
+ ******************************************************************/
64
+ add_filter('sw_network_buttons', 'sw_facebook_button_html',10);
65
+ function sw_facebook_button_html($array) {
66
+
67
+ // If we've already generated this button, just use our existing html
68
+ if(isset($_GLOBALS['sw']['buttons'][$array['postID']]['facebook'])):
69
+ $array['resource']['facebook'] = $_GLOBALS['sw']['buttons'][$array['postID']]['facebook'];
70
+
71
+ // If not, let's check if Facebook is activated and create the button HTML
72
+ elseif( $array['options']['facebook'] ):
73
+
74
+ $array['totes'] += $array['shares']['facebook'];
75
+ ++$array['count'];
76
+
77
+ $array['resource']['facebook'] = '<div class="nc_tweetContainer fb" data-id="'.$array['count'].'" data-network="facebook">';
78
+ $link = urlencode(urldecode(sw_process_url( $array['url'] , 'facebook' , $array['postID'] )));
79
+ $array['resource']['facebook'] .= '<a target="_blank" href="http://www.facebook.com/share.php?u='.$link.'" data-link="http://www.facebook.com/share.php?u='.$link.'" class="nc_tweet">';
80
+ if($array['options']['totesEach'] && $array['shares']['totes'] >= $array['options']['minTotes'] && $array['shares']['facebook'] > 0):
81
+ $array['resource']['facebook'] .= '<span class="iconFiller">';
82
+ $array['resource']['facebook'] .= '<span class="spaceManWilly">';
83
+ $array['resource']['facebook'] .= '<i class="sw sw-facebook"></i>';
84
+ $array['resource']['facebook'] .= '<span class="sw_share"> '.$array['language']['facebook'].'</span>';
85
+ $array['resource']['facebook'] .= '</span></span>';
86
+ $array['resource']['facebook'] .= '<span class="sw_count">'.kilomega($array['shares']['facebook']).'</span>';
87
+ else:
88
+ $array['resource']['facebook'] .= '<span class="sw_count sw_hide"><span class="iconFiller"><span class="spaceManWilly"><i class="sw sw-facebook"></i><span class="sw_share"> '.$array['language']['facebook'].'</span></span></span></span>';
89
+ endif;
90
+ $array['resource']['facebook'] .= '</a>';
91
+ $array['resource']['facebook'] .= '</div>';
92
+
93
+ // Store these buttons so that we don't have to generate them for each set
94
+ $_GLOBALS['sw']['buttons'][$array['postID']]['facebook'] = $array['resource']['facebook'];
95
+
96
+ endif;
97
+
98
+ return $array;
99
+
100
+ };
functions/social-networks/googlePlus.php ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*****************************************************************
4
+ * *
5
+ * #1: Add the On / Off Switch and Sortable Option *
6
+ * *
7
+ ******************************************************************/
8
+ add_filter('sw_options', 'sw_googlePlus_options_function',20);
9
+ function sw_googlePlus_options_function($sw_options) {
10
+
11
+ // Create the new option in a variable to be inserted
12
+ $googlePlus = array(
13
+ 'googlePlus' => array(
14
+ 'type' => 'checkbox',
15
+ 'content' => 'Google Plus',
16
+ 'default' => 1
17
+ )
18
+ );
19
+
20
+ // Call the function that adds the On / Off Switch and Sortable Option
21
+ return sw_add_network_option($sw_options,$googlePlus);
22
+
23
+ };
24
+ /*****************************************************************
25
+ * *
26
+ * #2: Add it to global network array *
27
+ * *
28
+ ******************************************************************/
29
+ // Queue up your filter to be ran on the sw_options hook.
30
+ add_filter('sw_add_networks', 'sw_googlePlus_network');
31
+
32
+ // Create the function that will filter the options
33
+ function sw_googlePlus_network($networks) {
34
+
35
+ // Add your network to the existing network array
36
+ $networks[] = 'googlePlus';
37
+
38
+ // Be sure to return the modified options array or the world will explode
39
+ return $networks;
40
+ };
41
+ /*****************************************************************
42
+ * *
43
+ * #3: Generate the API Share Count Request URL *
44
+ * *
45
+ ******************************************************************/
46
+ function sw_googlePlus_request_link($url) {
47
+ return $url;
48
+ }
49
+ /*****************************************************************
50
+ * *
51
+ * #4: Parse the Response to get the share count *
52
+ * *
53
+ ******************************************************************/
54
+ function sw_format_googlePlus_response($response) {
55
+ $response = json_decode($response, true);
56
+ return isset($response[0]['result']['metadata']['globalCounts']['count'])?intval( $response[0]['result']['metadata']['globalCounts']['count'] ):0;
57
+ }
58
+ /*****************************************************************
59
+ * *
60
+ * #5: Create the Button HTML *
61
+ * *
62
+ ******************************************************************/
63
+ add_filter('sw_network_buttons', 'sw_googlePlus_button_html',10);
64
+ function sw_googlePlus_button_html($array) {
65
+
66
+ // If we've already generated this button, just use our existing html
67
+ if(isset($_GLOBALS['sw']['buttons'][$array['postID']]['googlePlus'])):
68
+ $array['resource']['googlePlus'] = $_GLOBALS['sw']['buttons'][$array['postID']]['googlePlus'];
69
+
70
+ // If not, let's check if Facebook is activated and create the button HTML
71
+ elseif( $array['options']['googlePlus'] ):
72
+
73
+ $array['totes'] += $array['shares']['googlePlus'];
74
+ ++$array['count'];
75
+
76
+ $array['resource']['googlePlus'] = '<div class="nc_tweetContainer googlePlus" data-id="'.$array['count'].'" data-network="google_plus">';
77
+ $link = urlencode(urldecode(sw_process_url( $array['url'] , 'googlePlus' , $array['postID'] )));
78
+ $array['resource']['googlePlus'] .= '<a target="_blank" href="https://plus.google.com/share?url='.$link.'" data-link="https://plus.google.com/share?url='.$link.'" class="nc_tweet">';
79
+ if($array['options']['totesEach'] && $array['shares']['totes'] >= $array['options']['minTotes'] && $array['shares']['googlePlus'] > 0):
80
+ $array['resource']['googlePlus'] .= '<span class="iconFiller">';
81
+ $array['resource']['googlePlus'] .= '<span class="spaceManWilly">';
82
+ $array['resource']['googlePlus'] .= '<i class="sw sw-google-plus"></i>';
83
+ $array['resource']['googlePlus'] .= '<span class="sw_share"> '.$array['language']['googlePlus'].'</span>';
84
+ $array['resource']['googlePlus'] .= '</span></span>';
85
+ $array['resource']['googlePlus'] .= '<span class="sw_count">'.kilomega($array['shares']['googlePlus']).'</span>';
86
+ else:
87
+ $array['resource']['googlePlus'] .= '<span class="sw_count sw_hide"><span class="iconFiller"><span class="spaceManWilly"><i class="sw sw-google-plus"></i><span class="sw_share"> '.$array['language']['googlePlus'].'</span></span></span></span>';
88
+ endif;
89
+ $array['resource']['googlePlus'] .= '</a>';
90
+ $array['resource']['googlePlus'] .= '</div>';
91
+
92
+ // Store these buttons so that we don't have to generate them for each set
93
+ $_GLOBALS['sw']['buttons'][$array['postID']]['googlePlus'] = $array['resource']['googlePlus'];
94
+
95
+ endif;
96
+
97
+ return $array;
98
+
99
+ };
functions/social-networks/linkedIn.php ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*****************************************************************
4
+ * *
5
+ * #1: Add the On / Off Switch and Sortable Option *
6
+ * *
7
+ ******************************************************************/
8
+ add_filter('sw_options', 'sw_linkedIn_options_function',20);
9
+ function sw_linkedIn_options_function($sw_options) {
10
+
11
+ // Create the new option in a variable to be inserted
12
+ $linkedIn = array(
13
+ 'linkedIn' => array(
14
+ 'type' => 'checkbox',
15
+ 'content' => 'LinkedIn',
16
+ 'default' => 1
17
+ )
18
+ );
19
+
20
+ // Call the function that adds the On / Off Switch and Sortable Option
21
+ return sw_add_network_option($sw_options,$linkedIn);
22
+
23
+ };
24
+ /*****************************************************************
25
+ * *
26
+ * #2: Add it to global network array *
27
+ * *
28
+ ******************************************************************/
29
+ // Queue up your filter to be ran on the sw_options hook.
30
+ add_filter('sw_add_networks', 'sw_linkedIn_network');
31
+
32
+ // Create the function that will filter the options
33
+ function sw_linkedIn_network($networks) {
34
+
35
+ // Add your network to the existing network array
36
+ $networks[] = 'linkedIn';
37
+
38
+ // Be sure to return the modified options array or the world will explode
39
+ return $networks;
40
+ };
41
+ /*****************************************************************
42
+ * *
43
+ * #3: Generate the API Share Count Request URL *
44
+ * *
45
+ ******************************************************************/
46
+ function sw_linkedIn_request_link($url) {
47
+ $request_url = 'https://www.linkedin.com/countserv/count/share?url='.$url.'&format=json';
48
+ return $request_url;
49
+ }
50
+ /*****************************************************************
51
+ * *
52
+ * #4: Parse the Response to get the share count *
53
+ * *
54
+ ******************************************************************/
55
+ function sw_format_linkedIn_response($response) {
56
+ $response = json_decode($response, true);
57
+ return isset($response['count'])?intval($response['count']):0;
58
+ }
59
+ /*****************************************************************
60
+ * *
61
+ * #5: Create the Button HTML *
62
+ * *
63
+ ******************************************************************/
64
+ add_filter('sw_network_buttons', 'sw_linkedIn_button_html',10);
65
+ function sw_linkedIn_button_html($array) {
66
+
67
+ // If we've already generated this button, just use our existing html
68
+ if(isset($_GLOBALS['sw']['buttons'][$array['postID']]['linkedIn'])):
69
+ $array['resource']['linkedIn'] = $_GLOBALS['sw']['buttons'][$array['postID']]['linkedIn'];
70
+
71
+ // If not, let's check if Facebook is activated and create the button HTML
72
+ elseif( $array['options']['linkedIn'] ):
73
+
74
+ $array['totes'] += $array['shares']['linkedIn'];
75
+ ++$array['count'];
76
+
77
+ $array['resource']['linkedIn'] = '<div class="nc_tweetContainer linkedIn" data-id="'.$array['count'].'" data-network="linked_in">';
78
+ $link = urlencode(urldecode(sw_process_url( $array['url'] , 'linkedIn' , $array['postID'] )));
79
+ $array['resource']['linkedIn'] .= '<a target="_blank" href="https://www.linkedin.com/cws/share?url='.$link.'" data-link="https://www.linkedin.com/cws/share?url='.$link.'" class="nc_tweet">';
80
+ if($array['options']['totesEach'] && $array['shares']['totes'] >= $array['options']['minTotes'] && $array['shares']['linkedIn'] > 0):
81
+ $array['resource']['linkedIn'] .= '<span class="iconFiller">';
82
+ $array['resource']['linkedIn'] .= '<span class="spaceManWilly">';
83
+ $array['resource']['linkedIn'] .= '<i class="sw sw-linkedin"></i>';
84
+ $array['resource']['linkedIn'] .= '<span class="sw_share"> '.$array['language']['linkedIn'].'</span>';
85
+ $array['resource']['linkedIn'] .= '</span></span>';
86
+ $array['resource']['linkedIn'] .= '<span class="sw_count">'.kilomega($array['shares']['linkedIn']).'</span>';
87
+ else:
88
+ $array['resource']['linkedIn'] .= '<span class="sw_count sw_hide"><span class="iconFiller"><span class="spaceManWilly"><i class="sw sw-linkedin"></i><span class="sw_share"> '.$array['language']['linkedIn'].'</span></span></span></span>';
89
+ endif;
90
+ $array['resource']['linkedIn'] .= '</a>';
91
+ $array['resource']['linkedIn'] .= '</div>';
92
+
93
+ // Store these buttons so that we don't have to generate them for each set
94
+ $_GLOBALS['sw']['buttons'][$array['postID']]['linkedIn'] = $array['resource']['linkedIn'];
95
+
96
+ endif;
97
+
98
+ return $array;
99
+
100
+ };
functions/social-networks/pinterest.php ADDED
@@ -0,0 +1,157 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*****************************************************************
4
+ * *
5
+ * #1: Add the On / Off Switch and Sortable Option *
6
+ * *
7
+ ******************************************************************/
8
+ add_filter('sw_options', 'sw_pinterest_options_function',20);
9
+ function sw_pinterest_options_function($sw_options) {
10
+
11
+ // Create the new option in a variable to be inserted
12
+ $pinterest = array(
13
+ 'pinterest' => array(
14
+ 'type' => 'checkbox',
15
+ 'content' => 'Pinterest',
16
+ 'default' => 1
17
+ )
18
+ );
19
+
20
+ // Call the function that adds the On / Off Switch and Sortable Option
21
+ return sw_add_network_option($sw_options,$pinterest);
22
+
23
+ };
24
+ /*****************************************************************
25
+ * *
26
+ * #2: Add it to global network array *
27
+ * *
28
+ ******************************************************************/
29
+ // Queue up your filter to be ran on the sw_options hook.
30
+ add_filter('sw_add_networks', 'sw_pinterest_network');
31
+
32
+ // Create the function that will filter the options
33
+ function sw_pinterest_network($networks) {
34
+
35
+ // Add your network to the existing network array
36
+ $networks[] = 'pinterest';
37
+
38
+ // Be sure to return the modified options array or the world will explode
39
+ return $networks;
40
+ };
41
+ /*****************************************************************
42
+ * *
43
+ * #3: Generate the API Share Count Request URL *
44
+ * *
45
+ ******************************************************************/
46
+ function sw_pinterest_request_link($url) {
47
+ $url = rawurlencode($url);
48
+ $request_url = 'https://api.pinterest.com/v1/urls/count.json?url='.$url;
49
+ return $request_url;
50
+ }
51
+ /*****************************************************************
52
+ * *
53
+ * #4: Parse the Response to get the share count *
54
+ * *
55
+ ******************************************************************/
56
+ function sw_format_pinterest_response($response) {
57
+ $response = preg_replace('/^receiveCount\((.*)\)$/', "\\1", $response);
58
+ $response = json_decode($response,true);
59
+ return isset($response['count'])?intval($response['count']):0;
60
+ }
61
+ /*****************************************************************
62
+ * *
63
+ * #5: Create the Button HTML *
64
+ * *
65
+ ******************************************************************/
66
+ add_filter('sw_network_buttons', 'sw_pinterest_button_html',10);
67
+ function sw_pinterest_button_html($array) {
68
+
69
+ // If we've already generated this button, just use our existing html
70
+ if(isset($_GLOBALS['sw']['buttons'][$array['postID']]['pinterest'])):
71
+ $array['resource']['pinterest'] = $_GLOBALS['sw']['buttons'][$array['postID']]['pinterest'];
72
+
73
+ // If not, let's check if Facebook is activated and create the button HTML
74
+ elseif( $array['options']['pinterest'] ):
75
+
76
+ $array['totes'] += $array['shares']['pinterest'];
77
+ ++$array['count'];
78
+
79
+
80
+ $pi = get_post_meta( $array['postID'] , 'nc_pinterestImage' , true);
81
+
82
+ if(sw_is_cache_fresh($array['postID']) == false):
83
+
84
+ // Check if an image ID has been provided
85
+ $array['imageID'] = get_post_meta( $array['postID'] , 'nc_pinterestImage' , true );
86
+ if($array['imageID']):
87
+ $array['imageURL'] = wp_get_attachment_url( $array['imageID'] );
88
+ delete_post_meta($array['postID'],'sw_pinterest_image_url');
89
+ update_post_meta($array['postID'],'sw_pinterest_image_url',$array['imageURL']);
90
+ else:
91
+ $array['imageURL'] = wp_get_attachment_url( get_post_thumbnail_id( $array['postID'] ) );
92
+ delete_post_meta($array['postID'],'sw_pinterest_image_url');
93
+ endif;
94
+
95
+ else:
96
+
97
+ // Check if we have a cached Open Graph Image URL
98
+ $array['imageURL'] = get_post_meta( $array['postID'] , 'sw_pinterest_image_url' , true );
99
+
100
+ // If not, let's check to see if we have an ID to generate one
101
+ if(!$array['imageURL']):
102
+
103
+ // Check for an Open Graph Image ID
104
+ $array['imageID'] = get_post_meta( $array['postID'] , 'nc_pinterestImage' , true );
105
+ if($array['imageID']):
106
+
107
+ // If we find one, let's convert it to a link and cache it for next time
108
+ $array['imageURL'] = wp_get_attachment_url( $array['imageID'] );
109
+ delete_post_meta($array['postID'],'sw_pinterest_image_url');
110
+ update_post_meta($array['postID'],'sw_pinterest_image_url',$array['imageURL']);
111
+ else:
112
+
113
+ // If we don't find one, let's see if we can use a post thumbnail
114
+ $array['imageURL'] = wp_get_attachment_url( get_post_thumbnail_id( $array['postID'] ) );
115
+ endif;
116
+ endif;
117
+ endif;
118
+
119
+ $pd = get_post_meta( $array['postID'] , 'nc_pinterestDescription' , true );
120
+ if($array['imageURL']):
121
+ $pi = '&media='.urlencode(html_entity_decode($array['imageURL'],ENT_COMPAT, 'UTF-8'));
122
+ else:
123
+ $pi = '';
124
+ endif;
125
+
126
+ $pinterestLink = $array['url'];
127
+ $title = strip_tags(get_the_title($array['postID']));
128
+ $title = str_replace('|','',$title);
129
+
130
+ if($pi != ''):
131
+ $a = '<a data-link="https://pinterest.com/pin/create/button/?url='.$pinterestLink.''.$pi.'&description='.($pd != '' ? urlencode(html_entity_decode($pd, ENT_COMPAT, 'UTF-8')) : urlencode(html_entity_decode($title, ENT_COMPAT, 'UTF-8'))).'" class="nc_tweet" data-count="0">';
132
+ else:
133
+ $a = '<a onClick="var e=document.createElement(\'script\');e.setAttribute(\'type\',\'text/javascript\');e.setAttribute(\'charset\',\'UTF-8\');e.setAttribute(\'src\',\'//assets.pinterest.com/js/pinmarklet.js?r=\'+Math.random()*99999999);document.body.appendChild(e);" class="nc_tweet noPop">';
134
+ endif;
135
+ $array['resource']['pinterest'] = '<div class="nc_tweetContainer nc_pinterest" data-id="'.$array['count'].'" data-network="pinterest">';
136
+ $array['resource']['pinterest'] .= $a;
137
+ if($array['options']['totesEach'] && $array['totes'] >= $array['options']['minTotes'] && $array['shares']['pinterest'] > 0):
138
+ $array['resource']['pinterest'] .= '<span class="iconFiller">';
139
+ $array['resource']['pinterest'] .= '<span class="spaceManWilly" style="width:55px;">';
140
+ $array['resource']['pinterest'] .= '<i class="sw sw-pinterest"></i>';
141
+ $array['resource']['pinterest'] .= '<span class="sw_share"> '.$array['language']['pinterest'].'</span>';
142
+ $array['resource']['pinterest'] .= '</span></span>';
143
+ $array['resource']['pinterest'] .= '<span class="sw_count">'.kilomega($array['shares']['pinterest']).'</span>';
144
+ else:
145
+ $array['resource']['pinterest'] .= '<span class="sw_count sw_hide"><span class="iconFiller"><span class="spaceManWilly" style="width:55px;"><i class="sw sw-pinterest"></i><span class="sw_share"> '.$array['language']['pinterest'].'</span></span></span></span>';
146
+ endif;
147
+ $array['resource']['pinterest'] .= '</a>';
148
+ $array['resource']['pinterest'] .= '</div>';
149
+
150
+ // Store these buttons so that we don't have to generate them for each set
151
+ $_GLOBALS['sw']['buttons'][$array['postID']]['pinterest'] = $array['resource']['pinterest'];
152
+
153
+ endif;
154
+
155
+ return $array;
156
+
157
+ };
functions/social-networks/pocket.php ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*****************************************************************
4
+ * *
5
+ * #1: Add the On / Off Switch and Sortable Option *
6
+ * *
7
+ ******************************************************************/
8
+ add_filter('sw_options', 'sw_pocket_options_function',20);
9
+ function sw_pocket_options_function($sw_options) {
10
+
11
+ // Create the new option in a variable to be inserted
12
+ $pocket = array(
13
+ 'pocket' => array(
14
+ 'type' => 'checkbox',
15
+ 'content' => 'Pocket',
16
+ 'default' => false
17
+ )
18
+ );
19
+
20
+ // Call the function that adds the On / Off Switch and Sortable Option
21
+ return sw_add_network_option($sw_options,$pocket);
22
+
23
+ };
24
+ /*****************************************************************
25
+ * *
26
+ * #2: Add it to global network array *
27
+ * *
28
+ ******************************************************************/
29
+ // Queue up your filter to be ran on the sw_options hook.
30
+ add_filter('sw_add_networks', 'sw_pocket_network');
31
+
32
+ // Create the function that will filter the options
33
+ function sw_pocket_network($networks) {
34
+
35
+ // Add your network to the existing network array
36
+ $networks[] = 'pocket';
37
+
38
+ // Be sure to return the modified options array or the world will explode
39
+ return $networks;
40
+ };
41
+ /*****************************************************************
42
+ * *
43
+ * #3: Generate the API Share Count Request URL *
44
+ * *
45
+ ******************************************************************/
46
+ function sw_pocket_request_link($url) {
47
+ return 0;
48
+ }
49
+ /*****************************************************************
50
+ * *
51
+ * #4: Parse the Response to get the share count *
52
+ * *
53
+ ******************************************************************/
54
+ function sw_format_pocket_response($response) {
55
+ return 0;
56
+ }
57
+ /*****************************************************************
58
+ * *
59
+ * #5: Create the Button HTML *
60
+ * *
61
+ ******************************************************************/
62
+ add_filter('sw_network_buttons', 'sw_pocket_button_html',10);
63
+ function sw_pocket_button_html($array) {
64
+
65
+ if( $array['options']['pocket'] ):
66
+
67
+ // Collect the Title
68
+ $title = get_post_meta( $array['postID'] , 'nc_ogTitle' , true );
69
+ if(!$title):
70
+ $title = get_the_title();
71
+ endif;
72
+
73
+ ++$array['count'];
74
+
75
+ $array['resource']['pocket'] = '<div class="nc_tweetContainer sw_pocket" data-id="'.$array['count'].'" data-network="pocket">';
76
+ $link = urlencode(urldecode(sw_process_url( $array['url'] , 'pocket' , $array['postID'] )));
77
+ $array['resource']['pocket'] .= '<a href="https://getpocket.com/save?url='.$link.'&title='.$title.'" data-link="https://getpocket.com/save?url='.$link.'&title='.$title.'" class="nc_tweet">';
78
+ $array['resource']['pocket'] .= '<span class="sw_count sw_hide"><span class="iconFiller"><span class="spaceManWilly"><i class="sw sw-pocket"></i><span class="sw_share"> '.$array['language']['pocket'].'</span></span></span></span>';
79
+ $array['resource']['pocket'] .= '</a>';
80
+ $array['resource']['pocket'] .= '</div>';
81
+
82
+ endif;
83
+
84
+ return $array;
85
+
86
+ };
functions/social-networks/reddit.php ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*****************************************************************
4
+ * *
5
+ * #1: Add the On / Off Switch and Sortable Option *
6
+ * *
7
+ ******************************************************************/
8
+ add_filter('sw_options', 'sw_reddit_options_function',20);
9
+ function sw_reddit_options_function($sw_options) {
10
+
11
+ // Create the new option in a variable to be inserted
12
+ $reddit = array(
13
+ 'reddit' => array(
14
+ 'type' => 'checkbox',
15
+ 'content' => 'Reddit',
16
+ 'default' => 0
17
+ )
18
+ );
19
+
20
+ // Call the function that adds the On / Off Switch and Sortable Option
21
+ return sw_add_network_option($sw_options,$reddit);
22
+
23
+ };
24
+ /*****************************************************************
25
+ * *
26
+ * #2: Add it to global network array *
27
+ * *
28
+ ******************************************************************/
29
+ // Queue up your filter to be ran on the sw_options hook.
30
+ add_filter('sw_add_networks', 'sw_reddit_network');
31
+
32
+ // Create the function that will filter the options
33
+ function sw_reddit_network($networks) {
34
+
35
+ // Add your network to the existing network array
36
+ $networks[] = 'reddit';
37
+
38
+ // Be sure to return the modified options array or the world will explode
39
+ return $networks;
40
+ };
41
+ /*****************************************************************
42
+ * *
43
+ * #3: Generate the API Share Count Request URL *
44
+ * *
45
+ ******************************************************************/
46
+ function sw_reddit_request_link($url) {
47
+
48
+ // Create the API request link
49
+ $request_url = 'https://www.reddit.com/api/info.json?url='.$url;
50
+
51
+ // Return the constructed link to the Social Warfare Plugin
52
+ return $request_url;
53
+ }
54
+ /*****************************************************************
55
+ * *
56
+ * #4: Parse the Response to get the share count *
57
+ * *
58
+ ******************************************************************/
59
+ function sw_format_reddit_response($response) {
60
+
61
+ // Parse the JSON response into an associative array
62
+ $response = json_decode($response, true);
63
+ $score = 0;
64
+
65
+ // Check to ensure that there was a response
66
+ if(isset($response) && isset($response['data']) && isset($response['data']['children'])):
67
+
68
+ // Loop through each post on reddit adding the score to our total
69
+ foreach($response['data']['children'] as $child):
70
+ $score += (int) $child['data']['score'];
71
+ endforeach;
72
+ endif;
73
+
74
+ // Return the score to Social Warfare for caching and presentation
75
+ return $score;
76
+ }
77
+ /*****************************************************************
78
+ * *
79
+ * #5: Create the Button HTML *
80
+ * *
81
+ ******************************************************************/
82
+ add_filter('sw_network_buttons', 'sw_reddit_button_html',10);
83
+ function sw_reddit_button_html($array) {
84
+
85
+ // If we've already generated this button, just use our existing html
86
+ if(isset($_GLOBALS['sw']['buttons'][$array['postID']]['reddit'])):
87
+ $array['resource']['reddit'] = $_GLOBALS['sw']['buttons'][$array['postID']]['reddit'];
88
+
89
+ // If not, let's check if Facebook is activated and create the button HTML
90
+ elseif( isset($array['options']['reddit']) && $array['options']['reddit'] ):
91
+
92
+ if(isset($array['shares']['reddit'])):
93
+ $array['totes'] += $array['shares']['reddit'];
94
+ endif;
95
+ ++$array['count'];
96
+
97
+ // Collect the Title
98
+ $title = get_post_meta( $array['postID'] , 'nc_ogTitle' , true );
99
+ if(!$title):
100
+ $title = get_the_title();
101
+ endif;
102
+
103
+ $array['resource']['reddit'] = '<div class="nc_tweetContainer sw_reddit" data-id="'.$array['count'].'" data-network="reddit">';
104
+ $link = $array['url'];
105
+ $array['resource']['reddit'] .= '<a target="_blank" href="https://www.reddit.com/submit?url='.$link.'&title='.urlencode($title).'" data-link="https://www.reddit.com/submit?url='.$link.'&title='.urlencode($title).'" class="nc_tweet">';
106
+ if($array['options']['totesEach'] && $array['shares']['totes'] >= $array['options']['minTotes'] && isset($array['shares']['reddit']) && $array['shares']['reddit'] > 0):
107
+ $array['resource']['reddit'] .= '<span class="iconFiller">';
108
+ $array['resource']['reddit'] .= '<span class="spaceManWilly">';
109
+ $array['resource']['reddit'] .= '<i class="sw sw-reddit"></i>';
110
+ $array['resource']['reddit'] .= '<span class="sw_share"> '.$array['language']['reddit'].'</span>';
111
+ $array['resource']['reddit'] .= '</span></span>';
112
+ $array['resource']['reddit'] .= '<span class="sw_count">'.kilomega($array['shares']['reddit']).'</span>';
113
+ else:
114
+ $array['resource']['reddit'] .= '<span class="sw_count sw_hide"><span class="iconFiller"><span class="spaceManWilly"><i class="sw sw-reddit"></i><span class="sw_share"> '.$array['language']['reddit'].'</span></span></span></span>';
115
+ endif;
116
+ $array['resource']['reddit'] .= '</a>';
117
+ $array['resource']['reddit'] .= '</div>';
118
+
119
+ // Store these buttons so that we don't have to generate them for each set
120
+ $_GLOBALS['sw']['buttons'][$array['postID']]['reddit'] = $array['resource']['reddit'];
121
+
122
+ endif;
123
+
124
+ return $array;
125
+
126
+ };
functions/social-networks/stumbleupon.php ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*****************************************************************
4
+ * *
5
+ * #1: Add the On / Off Switch and Sortable Option *
6
+ * *
7
+ ******************************************************************/
8
+ add_filter('sw_options', 'sw_stumbleupon_options_function',20);
9
+ function sw_stumbleupon_options_function($sw_options) {
10
+
11
+ // Create the new option in a variable to be inserted
12
+ $stumbleupon = array(
13
+ 'stumbleupon' => array(
14
+ 'type' => 'checkbox',
15
+ 'content' => 'StumbleUpon',
16
+ 'default' => 0
17
+ )
18
+ );
19
+
20
+ // Call the function that adds the On / Off Switch and Sortable Option
21
+ return sw_add_network_option($sw_options,$stumbleupon);
22
+
23
+ };
24
+ /*****************************************************************
25
+ * *
26
+ * #2: Add it to global network array *
27
+ * *
28
+ ******************************************************************/
29
+ // Queue up your filter to be ran on the sw_options hook.
30
+ add_filter('sw_add_networks', 'sw_stumbleupon_network');
31
+
32
+ // Create the function that will filter the options
33
+ function sw_stumbleupon_network($networks) {
34
+
35
+ // Add your network to the existing network array
36
+ $networks[] = 'stumbleupon';
37
+
38
+ // Be sure to return the modified options array or the world will explode
39
+ return $networks;
40
+ };
41
+ /*****************************************************************
42
+ * *
43
+ * #3: Generate the API Share Count Request URL *
44
+ * *
45
+ ******************************************************************/
46
+ function sw_stumbleupon_request_link($url) {
47
+ $request_url = 'https://www.stumbleupon.com/services/1.01/badge.getinfo?url=' . $url;
48
+ return $request_url;
49
+ }
50
+ /*****************************************************************
51
+ * *
52
+ * #4: Parse the Response to get the share count *
53
+ * *
54
+ ******************************************************************/
55
+ function sw_format_stumbleupon_response($response) {
56
+ $response = json_decode($response, true);
57
+ return isset($response['result']['views'])?intval($response['result']['views']):0;
58
+ }
59
+ /*****************************************************************
60
+ * *
61
+ * #5: Create the Button HTML *
62
+ * *
63
+ ******************************************************************/
64
+ add_filter('sw_network_buttons', 'sw_stumbleupon_button_html',10);
65
+ function sw_stumbleupon_button_html($array) {
66
+
67
+ // If we've already generated this button, just use our existing html
68
+ if(isset($_GLOBALS['sw']['buttons'][$array['postID']]['stumbleupon'])):
69
+ $array['resource']['stumbleupon'] = $_GLOBALS['sw']['buttons'][$array['postID']]['stumbleupon'];
70
+
71
+ // If not, let's check if Facebook is activated and create the button HTML
72
+ elseif( isset($array['options']['stumbleupon']) && $array['options']['stumbleupon'] ):
73
+
74
+ if(isset($array['shares']['stumbleupon'])):
75
+ $array['totes'] += $array['shares']['stumbleupon'];
76
+ endif;
77
+ ++$array['count'];
78
+
79
+ // Collect the Title
80
+ $title = get_post_meta( $array['postID'] , 'nc_ogTitle' , true );
81
+ if(!$title):
82
+ $title = get_the_title();
83
+ endif;
84
+
85
+ $array['resource']['stumbleupon'] = '<div class="nc_tweetContainer sw_stumbleupon" data-id="'.$array['count'].'" data-network="stumble_upon">';
86
+ $link = $array['url'];
87
+ $array['resource']['stumbleupon'] .= '<a target="_blank" href="http://www.stumbleupon.com/submit?url='.$link.'&title='.urlencode($title).'" data-link="http://www.stumbleupon.com/submit?url='.$link.'&title='.urlencode($title).'" class="nc_tweet">';
88
+ if($array['options']['totesEach'] && $array['shares']['totes'] >= $array['options']['minTotes'] && isset($array['shares']['stumbleupon']) && $array['shares']['stumbleupon'] > 0):
89
+ $array['resource']['stumbleupon'] .= '<span class="iconFiller">';
90
+ $array['resource']['stumbleupon'] .= '<span class="spaceManWilly">';
91
+ $array['resource']['stumbleupon'] .= '<i class="sw sw-stumbleupon"></i>';
92
+ $array['resource']['stumbleupon'] .= '<span class="sw_share"> '.$array['language']['stumbleupon'].'</span>';
93
+ $array['resource']['stumbleupon'] .= '</span></span>';
94
+ $array['resource']['stumbleupon'] .= '<span class="sw_count">'.kilomega($array['shares']['stumbleupon']).'</span>';
95
+ else:
96
+ $array['resource']['stumbleupon'] .= '<span class="sw_count sw_hide"><span class="iconFiller"><span class="spaceManWilly"><i class="sw sw-stumbleupon"></i><span class="sw_share"> '.$array['language']['stumbleupon'].'</span></span></span></span>';
97
+ endif;
98
+ $array['resource']['stumbleupon'] .= '</a>';
99
+ $array['resource']['stumbleupon'] .= '</div>';
100
+
101
+ // Store these buttons so that we don't have to generate them for each set
102
+ $_GLOBALS['sw']['buttons'][$array['postID']]['stumbleupon'] = $array['resource']['stumbleupon'];
103
+
104
+ endif;
105
+
106
+ return $array;
107
+
108
+ };
functions/social-networks/tumblr.php ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*****************************************************************
4
+ * *
5
+ * #1: Add the On / Off Switch and Sortable Option *
6
+ * *
7
+ ******************************************************************/
8
+ add_filter('sw_options', 'sw_tumblr_options_function',20);
9
+ function sw_tumblr_options_function($sw_options) {
10
+
11
+ // Create the new option in a variable to be inserted
12
+ $tumblr = array(
13
+ 'tumblr' => array(
14
+ 'type' => 'checkbox',
15
+ 'content' => 'Tumblr',
16
+ 'default' => 0
17
+ )
18
+ );
19
+ // Call the function that adds the On / Off Switch and Sortable Option
20
+ return sw_add_network_option($sw_options,$tumblr);
21
+ };
22
+ /*****************************************************************
23
+ * *
24
+ * #2: Add it to global network array *
25
+ * *
26
+ ******************************************************************/
27
+ // Queue up your filter to be ran on the sw_options hook.
28
+ add_filter('sw_add_networks', 'sw_tumblr_network');
29
+
30
+ // Create the function that will filter the options
31
+ function sw_tumblr_network($networks) {
32
+
33
+ // Add your network to the existing network array
34
+ $networks[] = 'tumblr';
35
+
36
+ // Be sure to return the modified options array or the world will explode
37
+ return $networks;
38
+ };
39
+ /*****************************************************************
40
+ * *
41
+ * #3: Generate the API Share Count Request URL *
42
+ * *
43
+ ******************************************************************/
44
+ function sw_tumblr_request_link($url) {
45
+ $request_url = 'https://api.tumblr.com/v2/share/stats?url=' . $url;
46
+ return $request_url;
47
+ }
48
+ /*****************************************************************
49
+ * *
50
+ * #4: Parse the Response to get the share count *
51
+ * *
52
+ ******************************************************************/
53
+ function sw_format_tumblr_response($response) {
54
+ $response = json_decode($response, true);
55
+ return isset($response['response']['note_count'])?intval($response['response']['note_count']):0;
56
+ }
57
+ /*****************************************************************
58
+ * *
59
+ * #5: Create the Button HTML *
60
+ * *
61
+ ******************************************************************/
62
+ add_filter('sw_network_buttons', 'sw_tumblr_button_html',10);
63
+ function sw_tumblr_button_html($array) {
64
+
65
+ // If we've already generated this button, just use our existing html
66
+ if(isset($_GLOBALS['sw']['buttons'][$array['postID']]['tumblr'])):
67
+ $array['resource']['tumblr'] = $_GLOBALS['sw']['buttons'][$array['postID']]['tumblr'];
68
+
69
+ // If not, let's check if Facebook is activated and create the button HTML
70
+ elseif( isset($array['options']['tumblr']) && $array['options']['tumblr'] ):
71
+
72
+ $array['totes'] += $array['shares']['tumblr'];
73
+ ++$array['count'];
74
+
75
+ // Collect the Title
76
+ $title = get_post_meta( $array['postID'] , 'nc_ogTitle' , true );
77
+ if(!$title):
78
+ $title = get_the_title();
79
+ endif;
80
+
81
+ // Collect the Description
82
+ $description = get_post_meta( $array['postID'] , 'nc_ogDescription' , true );
83
+
84
+ $array['resource']['tumblr'] = '<div class="nc_tweetContainer sw_tumblr" data-id="'.$array['count'].'" data-network="tumblr">';
85
+ $link = urlencode(urldecode(sw_process_url( $array['url'] , 'tumblr' , $array['postID'] )));
86
+ $array['resource']['tumblr'] .= '<a target="_blank" href="http://www.tumblr.com/share/link?url='.$link.'&name='.urlencode($title).($description ? '&description=' : '').urlencode($description).'" data-link="http://www.tumblr.com/share/link?url='.$link.'&name='.urlencode($title).($description ? '&description=' : '').urlencode($description).'" class="nc_tweet">';
87
+ if($array['options']['totesEach'] && $array['shares']['totes'] >= $array['options']['minTotes'] && $array['shares']['tumblr'] > 0):
88
+ $array['resource']['tumblr'] .= '<span class="iconFiller">';
89
+ $array['resource']['tumblr'] .= '<span class="spaceManWilly">';
90
+ $array['resource']['tumblr'] .= '<i class="sw sw-tumblr"></i>';
91
+ $array['resource']['tumblr'] .= '<span class="sw_share"> '.$array['language']['tumblr'].'</span>';
92
+ $array['resource']['tumblr'] .= '</span></span>';
93
+ $array['resource']['tumblr'] .= '<span class="sw_count">'.kilomega($array['shares']['tumblr']).'</span>';
94
+ else:
95
+ $array['resource']['tumblr'] .= '<span class="sw_count sw_hide"><span class="iconFiller"><span class="spaceManWilly"><i class="sw sw-tumblr"></i><span class="sw_share"> '.$array['language']['tumblr'].'</span></span></span></span>';
96
+ endif;
97
+ $array['resource']['tumblr'] .= '</a>';
98
+ $array['resource']['tumblr'] .= '</div>';
99
+
100
+ // Store these buttons so that we don't have to generate them for each set
101
+ $_GLOBALS['sw']['buttons'][$array['postID']]['tumblr'] = $array['resource']['tumblr'];
102
+
103
+ endif;
104
+
105
+ return $array;
106
+
107
+ };
functions/social-networks/twitter.php ADDED
@@ -0,0 +1,172 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*****************************************************************
4
+ * *
5
+ * #1: Add the On / Off Switch and Sortable Option *
6
+ * *
7
+ ******************************************************************/
8
+ add_filter('sw_options', 'sw_twitter_options_function',20);
9
+ function sw_twitter_options_function($sw_options) {
10
+
11
+ // Create the new option in a variable to be inserted
12
+ $twitter = array(
13
+ 'twitter' => array(
14
+ 'type' => 'checkbox',
15
+ 'content' => 'Twitter',
16
+ 'default' => 1
17
+ )
18
+ );
19
+
20
+ // Call the function that adds the On / Off Switch and Sortable Option
21
+ return sw_add_network_option($sw_options,$twitter);
22
+
23
+ };
24
+ /*****************************************************************
25
+ * *
26
+ * #2: Add it to global network array *
27
+ * *
28
+ ******************************************************************/
29
+ // Queue up your filter to be ran on the sw_options hook.
30
+ add_filter('sw_add_networks', 'sw_twitter_network');
31
+
32
+ // Create the function that will filter the options
33
+ function sw_twitter_network($networks) {
34
+
35
+ // Add your network to the existing network array
36
+ $networks[] = 'twitter';
37
+
38
+ // Be sure to return the modified options array or the world will explode
39
+ return $networks;
40
+ };
41
+ /*****************************************************************
42
+ * *
43
+ * #3: Generate the API Share Count Request URL *
44
+ * *
45
+ ******************************************************************/
46
+ function sw_twitter_request_link($url) {
47
+
48
+ // Fetch the user's options
49
+ $sw_user_options = sw_get_user_options();
50
+
51
+ // If the user has enabled Twitter shares....
52
+ if($sw_user_options['twitter_shares']):
53
+
54
+ // Return the correct Twitter JSON endpoint URL
55
+ $request_url = 'http://public.newsharecounts.com/count.json?url=' . $url;
56
+
57
+ // Debugging
58
+ if(isset($_GET['sw_twitter_debug']) && $_GET['sw_twitter_debug'] == true):
59
+ echo '<b>Request URL:</b> '.$request_url.'<br />';
60
+ endif;
61
+
62
+ return $request_url;
63
+
64
+ // If the user has not enabled Twitter shares....
65
+ else:
66
+
67
+ // Return nothing so we don't run an API call
68
+ return 0;
69
+
70
+ endif;
71
+ }
72
+ /*****************************************************************
73
+ * *
74
+ * #4: Parse the Response to get the share count *
75
+ * *
76
+ ******************************************************************/
77
+ function sw_format_twitter_response($response) {
78
+
79
+ // Fetch the user's options
80
+ $sw_user_options = sw_get_user_options();
81
+
82
+ // If the user has enabled Twitter shares....
83
+ if($sw_user_options['twitter_shares']):
84
+
85
+ // Debugging
86
+ if(isset($_GET['sw_twitter_debug']) && $_GET['sw_twitter_debug'] == true):
87
+ echo '<b>Response:</b> '.$response.'<br />';
88
+ endif;
89
+
90
+ // Parse the response to get the actual number
91
+ $response = json_decode($response, true);
92
+
93
+ return isset($response['count'])?intval($response['count']):0;
94
+
95
+ // If the user has not enabled Twitter shares....
96
+ else:
97
+
98
+ // Return the number 0
99
+ return 0;
100
+
101
+ endif;
102
+ }
103
+ /*****************************************************************
104
+ * *
105
+ * #5: Create the Button HTML *
106
+ * *
107
+ ******************************************************************/
108
+ add_filter('sw_network_buttons', 'sw_twitter_button_html',10);
109
+ function sw_twitter_button_html($array) {
110
+
111
+ // If we've already generated this button, just use our existing html
112
+ if(isset($_GLOBALS['sw']['buttons'][$array['postID']]['twitter'])):
113
+ $array['resource']['twitter'] = $_GLOBALS['sw']['buttons'][$array['postID']]['twitter'];
114
+
115
+ // If not, let's check if Facebook is activated and create the button HTML
116
+ elseif( isset($array['options']['twitter']) && $array['options']['twitter'] ):
117
+
118
+ $array['totes'] += $array['shares']['twitter'];
119
+ ++$array['count'];
120
+
121
+ $title = strip_tags(get_the_title($array['postID']));
122
+ $title = str_replace('|','',$title);
123
+ $ct = get_post_meta( $array['postID'] , 'nc_customTweet' , true );
124
+
125
+
126
+ $ct = ($ct != '' ? urlencode(html_entity_decode($ct, ENT_COMPAT, 'UTF-8')) : urlencode(html_entity_decode($title, ENT_COMPAT, 'UTF-8')));
127
+ $twitterLink = sw_process_url( $array['url'] , 'twitter' , $array['postID'] );
128
+ if (strpos($ct,'http') !== false) : $urlParam = '&url=/'; else: $urlParam = '&url='.$twitterLink; endif;
129
+
130
+ if(sw_is_cache_fresh($array['postID']) == false):
131
+ $user_twitter_handle = get_the_author_meta( 'sw_twitter' , sw_get_author($array['postID']));
132
+ if($user_twitter_handle):
133
+ delete_post_meta($array['postID'],'sw_twitter_username');
134
+ update_post_meta($array['postID'],'sw_twitter_username',$user_twitter_handle);
135
+ else:
136
+ delete_post_meta($array['postID'],'sw_twitter_username');
137
+ endif;
138
+ else:
139
+ $user_twitter_handle = get_post_meta( $array['postID'] , 'sw_twitter_username' , true );
140
+ endif;
141
+
142
+ if($user_twitter_handle):
143
+ $viaText = '&via='.str_replace('@','',$user_twitter_handle);
144
+ elseif($array['options']['twitterID']):
145
+ $viaText = '&via='.str_replace('@','',$array['options']['twitterID']);
146
+ else:
147
+ $viaText = '';
148
+ endif;
149
+
150
+ $array['resource']['twitter'] = '<div class="nc_tweetContainer twitter" data-id="'.$array['count'].'" data-network="twitter">';
151
+ $array['resource']['twitter'] .= '<a href="https://twitter.com/share?original_referer=/&text='.$ct.''.$urlParam.''.$viaText.'" data-link="https://twitter.com/share?original_referer=/&text='.$ct.''.$urlParam.''.$viaText.'" class="nc_tweet">';
152
+ if($array['options']['totesEach'] && $array['totes'] >= $array['options']['minTotes'] && $array['shares']['twitter'] > 0):
153
+ $array['resource']['twitter'] .= '<span class="iconFiller">';
154
+ $array['resource']['twitter'] .= '<span class="spaceManWilly">';
155
+ $array['resource']['twitter'] .= '<i class="sw sw-twitter"></i>';
156
+ $array['resource']['twitter'] .= '<span class="sw_share"> '.$array['language']['twitter'].'</span>';
157
+ $array['resource']['twitter'] .= '</span></span>';
158
+ $array['resource']['twitter'] .= '<span class="sw_count">'.kilomega($array['shares']['twitter']).'</span>';
159
+ else:
160
+ $array['resource']['twitter'] .= '<span class="sw_count sw_hide"><span class="iconFiller"><span class="spaceManWilly"><i class="sw sw-twitter"></i><span class="sw_share"> '.$array['language']['twitter'].'</span></span></span></span>';
161
+ endif;
162
+ $array['resource']['twitter'] .= '</a>';
163
+ $array['resource']['twitter'] .= '</div>';
164
+
165
+ // Store these buttons so that we don't have to generate them for each set
166
+ $_GLOBALS['sw']['buttons'][$array['postID']]['twitter'] = $array['resource']['twitter'];
167
+
168
+ endif;
169
+
170
+ return $array;
171
+
172
+ };
functions/social-networks/whatsapp.php ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*****************************************************************
4
+ * *
5
+ * #1: Add the On / Off Switch and Sortable Option *
6
+ * *
7
+ ******************************************************************/
8
+ add_filter('sw_options', 'sw_whatsapp_options_function',20);
9
+ function sw_whatsapp_options_function($sw_options) {
10
+
11
+ // Create the new option in a variable to be inserted
12
+ $whatsapp = array(
13
+ 'whatsapp' => array(
14
+ 'type' => 'checkbox',
15
+ 'content' => 'WhatsApp',
16
+ 'default' => 0
17
+ )
18
+ );
19
+
20
+ // Call the function that adds the On / Off Switch and Sortable Option
21
+ return sw_add_network_option($sw_options,$whatsapp);
22
+
23
+ };
24
+ /*****************************************************************
25
+ * *
26
+ * #2: Add it to global network array *
27
+ * *
28
+ ******************************************************************/
29
+ // Queue up your filter to be ran on the sw_options hook.
30
+ add_filter('sw_add_networks', 'sw_whatsapp_network');
31
+
32
+ // Create the function that will filter the options
33
+ function sw_whatsapp_network($networks) {
34
+
35
+ // Add your network to the existing network array
36
+ $networks[] = 'whatsapp';
37
+
38
+ // Be sure to return the modified options array or the world will explode
39
+ return $networks;
40
+ };
41
+ /*****************************************************************
42
+ * *
43
+ * #3: Generate the API Share Count Request URL *
44
+ * *
45
+ ******************************************************************/
46
+ function sw_whatsapp_request_link($url) {
47
+ $request_url = 'https://api.facebook.com/restserver.php?method=links.getStats&format=json&urls='.$url;
48
+ return 0;
49
+ }
50
+ /*****************************************************************
51
+ * *
52
+ * #4: Parse the Response to get the share count *
53
+ * *
54
+ ******************************************************************/
55
+ function sw_format_whatsapp_response($response) {
56
+ // $response = json_decode($response, true);
57
+ // return isset($response[0]['total_count'])?intval($response[0]['total_count']):0;
58
+ return 0;
59
+ }
60
+ /*****************************************************************
61
+ * *
62
+ * #5: Create the Button HTML *
63
+ * *
64
+ ******************************************************************/
65
+ add_filter('sw_network_buttons', 'sw_whatsapp_button_html',10);
66
+ function sw_whatsapp_button_html($array) {
67
+
68
+ // If we've already generated this button, just use our existing html
69
+ if(isset($_GLOBALS['sw']['buttons'][$array['postID']]['whatsapp'])):
70
+ $array['resource']['whatsapp'] = $_GLOBALS['sw']['buttons'][$array['postID']]['whatsapp'];
71
+
72
+ // If not, let's check if WhatsApp is activated and create the button HTML
73
+ elseif( $array['options']['whatsapp'] && sw_mobile_detection() ):
74
+
75
+ $array['totes'] += $array['shares']['whatsapp'];
76
+ ++$array['count'];
77
+
78
+ $array['resource']['whatsapp'] = '<div class="nc_tweetContainer sw_whatsapp" data-id="'.$array['count'].'" data-network="whatsapp">';
79
+ $link = urlencode(urldecode(sw_process_url( $array['url'] , 'whatsapp' , $array['postID'] )));
80
+ $array['resource']['whatsapp'] .= '<a target="_blank" href="whatsapp://send?text='.$link.'" class="nc_tweet" data-action="share/whatsapp/share">';
81
+ if($array['options']['totesEach'] && $array['shares']['totes'] >= $array['options']['minTotes'] && $array['shares']['whatsapp'] > 0):
82
+ $array['resource']['whatsapp'] .= '<span class="iconFiller">';
83
+ $array['resource']['whatsapp'] .= '<span class="spaceManWilly">';
84
+ $array['resource']['whatsapp'] .= '<i class="sw sw-whatsapp"></i>';
85
+ $array['resource']['whatsapp'] .= '<span class="sw_share"> '.$array['language']['whatsapp'].'</span>';
86
+ $array['resource']['whatsapp'] .= '</span></span>';
87
+ $array['resource']['whatsapp'] .= '<span class="sw_count">'.kilomega($array['shares']['whatsapp']).'</span>';
88
+ else:
89
+ $array['resource']['whatsapp'] .= '<span class="sw_count sw_hide"><span class="iconFiller"><span class="spaceManWilly"><i class="sw sw-whatsapp"></i><span class="sw_share"> '.$array['language']['whatsapp'].'</span></span></span></span>';
90
+ endif;
91
+ $array['resource']['whatsapp'] .= '</a>';
92
+ $array['resource']['whatsapp'] .= '</div>';
93
+
94
+ // Store these buttons so that we don't have to generate them for each set
95
+ $_GLOBALS['sw']['buttons'][$array['postID']]['whatsapp'] = $array['resource']['whatsapp'];
96
+
97
+ endif;
98
+
99
+ return $array;
100
+
101
+ };
functions/social-networks/yummly.php ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*****************************************************************
4
+ * *
5
+ * #1: Add the On / Off Switch and Sortable Option *
6
+ * *
7
+ ******************************************************************/
8
+ add_filter('sw_options', 'sw_yummly_options_function',20);
9
+ function sw_yummly_options_function($sw_options) {
10
+
11
+ // Create the new option in a variable to be inserted
12
+ $yummly = array(
13
+ 'yummly' => array(
14
+ 'type' => 'checkbox',
15
+ 'content' => 'Yummly',
16
+ 'default' => 0
17
+ )
18
+ );
19
+
20
+ // Call the function that adds the On / Off Switch and Sortable Option
21
+ return sw_add_network_option($sw_options,$yummly);
22
+
23
+ };
24
+ /*****************************************************************
25
+ * *
26
+ * #2: Add it to global network array *
27
+ * *
28
+ ******************************************************************/
29
+ // Queue up your filter to be ran on the sw_options hook.
30
+ add_filter('sw_add_networks', 'sw_yummly_network');
31
+
32
+ // Create the function that will filter the options
33
+ function sw_yummly_network($networks) {
34
+
35
+ // Add your network to the existing network array
36
+ $networks[] = 'yummly';
37
+
38
+ // Be sure to return the modified options array or the world will explode
39
+ return $networks;
40
+ };
41
+ /*****************************************************************
42
+ * *
43
+ * #3: Generate the API Share Count Request URL *
44
+ * *
45
+ ******************************************************************/
46
+ function sw_yummly_request_link($url) {
47
+ $request_url = 'http://www.yummly.com/services/yum-count?url=' . $url;
48
+ return $request_url;
49
+ }
50
+ /*****************************************************************
51
+ * *
52
+ * #4: Parse the Response to get the share count *
53
+ * *
54
+ ******************************************************************/
55
+ function sw_format_yummly_response($response) {
56
+ $response = json_decode($response, true);
57
+ return isset($response['count'])?intval($response['count']):0;
58
+ }
59
+ /*****************************************************************
60
+ * *
61
+ * #5: Create the Button HTML *
62
+ * *
63
+ ******************************************************************/
64
+ add_filter('sw_network_buttons', 'sw_yummly_button_html',10);
65
+ function sw_yummly_button_html($array) {
66
+
67
+ // If we've already generated this button, just use our existing html
68
+ if(isset($_GLOBALS['sw']['buttons'][$array['postID']]['yummly'])):
69
+ $array['resource']['yummly'] = $_GLOBALS['sw']['buttons'][$array['postID']]['yummly'];
70
+
71
+ // If not, let's check if Yummly is activated and create the button HTML
72
+ elseif( $array['options']['yummly'] ):
73
+
74
+ $array['totes'] += $array['shares']['yummly'];
75
+ ++$array['count'];
76
+
77
+ // Let's create a title
78
+ if(get_post_meta( $array['postID'] , 'nc_ogTitle' , true )):
79
+
80
+ // If the user defined an social media title, let's use it.
81
+ $title = urlencode(urldecode(get_post_meta( $array['postID'] , 'nc_ogTitle' , true )));
82
+
83
+ else:
84
+
85
+ // Otherwise we'll use the default post title
86
+ $title = urlencode(urldecode(get_the_title()));
87
+
88
+ endif;
89
+
90
+ if(get_post_meta($array['postID'],'sw_open_graph_image_url')):
91
+ $image = urlencode(urldecode(get_post_meta($array['postID'],'sw_open_graph_image_url',true)));
92
+ else:
93
+ $image = urlencode(urldecode(get_post_meta($array['postID'],'sw_open_thumbnail_url',true)));
94
+ endif;
95
+
96
+ $array['resource']['yummly'] = '<div class="nc_tweetContainer sw_yummly" data-id="'.$array['count'].'" data-network="yummly">';
97
+ // $link = urlencode(urldecode(sw_process_url( $array['url'] , 'yummly' , $array['postID'] )));
98
+ $link = $array['url'];
99
+ $array['resource']['yummly'] .= '<a target="_blank" href="http://www.yummly.com/urb/verify?url='.$link.'&title='.$title.'&image='.$image.'&yumtype=button" data-link="http://www.yummly.com/urb/verify?url='.$link.'&title='.$title.'&image='.$image.'&yumtype=button" class="nc_tweet">';
100
+ if($array['options']['totesEach'] && $array['shares']['totes'] >= $array['options']['minTotes'] && $array['shares']['yummly'] > 0):
101
+ $array['resource']['yummly'] .= '<span class="iconFiller">';
102
+ $array['resource']['yummly'] .= '<span class="spaceManWilly">';
103
+ $array['resource']['yummly'] .= '<i class="sw sw-yummly"></i>';
104
+ $array['resource']['yummly'] .= '<span class="sw_share"> '.$array['language']['yummly'].'</span>';
105
+ $array['resource']['yummly'] .= '</span></span>';
106
+ $array['resource']['yummly'] .= '<span class="sw_count">'.kilomega($array['shares']['yummly']).'</span>';
107
+ else:
108
+ $array['resource']['yummly'] .= '<span class="sw_count sw_hide"><span class="iconFiller"><span class="spaceManWilly"><i class="sw sw-yummly"></i><span class="sw_share"> '.$array['language']['yummly'].'</span></span></span></span>';
109
+ endif;
110
+ $array['resource']['yummly'] .= '</a>';
111
+ $array['resource']['yummly'] .= '</div>';
112
+
113
+ // Store these buttons so that we don't have to generate them for each set
114
+ $_GLOBALS['sw']['buttons'][$array['postID']]['yummly'] = $array['resource']['yummly'];
115
+
116
+ endif;
117
+
118
+ return $array;
119
+
120
+ };
functions/sw-shortcode-generator.js ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function() {
2
+ tinymce.PluginManager.add('sw_shortcode_generator', function( editor, url ) {
3
+ editor.addButton( 'sw_shortcode_generator', {
4
+ title: 'Social Warfare Buttons',
5
+ icon: 'sw sw sw-social-warfare',
6
+ onclick: function() {
7
+ editor.windowManager.open( {
8
+ title: 'Insert Social Warfare Buttons',
9
+ body: [
10
+ {
11
+ type: 'listbox',
12
+ name: 'reflection',
13
+ label: 'Should the buttons reflect this post or another one?',
14
+ 'values': [
15
+ {text: 'This Post', value: 'default'},
16
+ {text: 'A Different Post', value: 'alt'}
17
+ ],
18
+ onselect: function( v ) {
19
+ if(this.value() == 'alt') {
20
+ jQuery('.mce-postid').parent().parent().slideDown();
21
+ } else {
22
+ jQuery('.mce-postid').parent().parent().slideUp();
23
+ }
24
+ }
25
+ },
26
+ {
27
+ type: 'textbox',
28
+ multiline: false,
29
+ name: 'postID',
30
+ classes: 'postid',
31
+ label: 'The ID of the post or page to reflect:'
32
+ },
33
+ ],
34
+ onPostRender : function() {
35
+ jQuery('.mce-postid').parent().parent().slideUp();
36
+ jQuery('.mce-title').prepend('<i class="sw sw-social-warfare"></i>');
37
+ },
38
+ onsubmit: function( e ) {
39
+ if(e.data.reflection == 'alt' && e.data.postID != '') {
40
+ editor.insertContent( '[social_warfare post_id="' + e.data.postID + '"]');
41
+ } else {
42
+ editor.insertContent( '[social_warfare]');
43
+ }
44
+ }
45
+ });
46
+ }
47
+ });
48
+ });
49
+ })();
functions/sw-shortcode-generator.php ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! class_exists( 'sw_shortcode_generator' ) ) {
4
+
5
+ class sw_shortcode_generator {
6
+
7
+ public function __construct() {
8
+ $this->sw_shortcode_generator();
9
+ }
10
+
11
+ public function sw_shortcode_generator() {
12
+ register_activation_hook( __FILE__, array( __CLASS__, 'activation' ) );
13
+ register_deactivation_hook( __FILE__, array( __CLASS__, 'deactivation' ) );
14
+
15
+ if(is_admin()) {
16
+ $this->register_admin_hooks();
17
+ }
18
+ }
19
+
20
+ public function debug($array) {
21
+ echo '<pre>';
22
+ print_r($array);
23
+ echo '</pre>';
24
+ }
25
+
26
+ public function activation() {
27
+ register_uninstall_hook( __FILE__, array( __CLASS__, 'uninstall' ) );
28
+ }
29
+
30
+ public function deactivation() {
31
+
32
+ }
33
+
34
+ public function register_admin_hooks() {
35
+ add_filter('tiny_mce_version', array($this, 'refresh_mce'));
36
+ add_action('init', array($this, 'tinymce_button'));
37
+ }
38
+
39
+ public function tinymce_button() {
40
+ if (!current_user_can('edit_posts') && !current_user_can('edit_pages')) {
41
+ return;
42
+ }
43
+
44
+ if (get_user_option('rich_editing') == 'true') {
45
+ add_filter('mce_external_plugins', array($this, 'tinymce_register_plugin'));
46
+ add_filter('mce_buttons', array($this, 'tinymce_register_button'));
47
+ }
48
+ }
49
+
50
+ public function tinymce_register_button($buttons) {
51
+ array_push($buttons, "|", "sw_shortcode_generator");
52
+ return $buttons;
53
+ }
54
+
55
+ public function tinymce_register_plugin($plugin_array) {
56
+ $plugin_array['sw_shortcode_generator'] = plugins_url( '/sw-shortcode-generator.js', __FILE__);
57
+ return $plugin_array;
58
+ }
59
+
60
+ public function refresh_mce($ver) {
61
+ $ver += 3;
62
+ return $ver;
63
+ }
64
+ }
65
+
66
+ new sw_shortcode_generator();
67
+
68
+ }
functions/updates/composer.json ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "yahnis-elsts/plugin-update-checker",
3
+ "type": "library",
4
+ "description": "A custom update checker for WordPress plugins. Useful if you can't host your plugin in the official WP plugin repository but still want it to support automatic plugin updates.",
5
+ "keywords": ["wordpress", "plugin updates", "automatic updates"],
6
+ "homepage": "https://github.com/YahnisElsts/plugin-update-checker/",
7
+ "license": "MIT",
8
+ "authors": [
9
+ {
10
+ "name": "Yahnis Elsts",
11
+ "email": "whiteshadow@w-shadow.com",
12
+ "homepage": "http://w-shadow.com/",
13
+ "role": "Developer"
14
+ }
15
+ ],
16
+ "require": {
17
+ "php": ">=5.2.0"
18
+ }
19
+ }
functions/updates/css/puc-debug-bar.css ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .puc-debug-bar-panel pre {
2
+ margin-top: 0;
3
+ }
4
+
5
+ /* Style the debug data table to match "widefat" table style used by WordPress. */
6
+ table.puc-debug-data {
7
+ width: 100%;
8
+ clear: both;
9
+ margin: 0;
10
+
11
+ border-spacing: 0;
12
+ background-color: #f9f9f9;
13
+
14
+ border-radius: 3px;
15
+ border: 1px solid #dfdfdf;
16
+ border-collapse: separate;
17
+ }
18
+
19
+ table.puc-debug-data * {
20
+ word-wrap: break-word;
21
+ }
22
+
23
+ table.puc-debug-data th {
24
+ width: 11em;
25
+ padding: 7px 7px 8px;
26
+ text-align: left;
27
+
28
+ font-family: "Georgia", "Times New Roman", "Bitstream Charter", "Times", serif;
29
+ font-weight: 400;
30
+ font-size: 14px;
31
+ line-height: 1.3em;
32
+ text-shadow: rgba(255, 255, 255, 0.804) 0 1px 0;
33
+ }
34
+
35
+ table.puc-debug-data td, table.puc-debug-data th {
36
+ border-width: 1px 0;
37
+ border-style: solid;
38
+
39
+ border-top-color: #fff;
40
+ border-bottom-color: #dfdfdf;
41
+
42
+ text-transform: none;
43
+ }
44
+
45
+ table.puc-debug-data td {
46
+ color: #555;
47
+ font-size: 12px;
48
+ padding: 4px 7px 2px;
49
+ vertical-align: top;
50
+ }
51
+
52
+ .puc-ajax-response {
53
+ border: 1px solid #dfdfdf;
54
+ border-radius: 3px;
55
+ padding: 0.5em;
56
+ margin: 5px 0;
57
+ background-color: white;
58
+ }
59
+
60
+ .puc-ajax-nonce {
61
+ display: none;
62
+ }
functions/updates/debug-bar-panel.php ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( !class_exists('PluginUpdateCheckerPanel', false) && class_exists('Debug_Bar_Panel', false) ) {
4
+
5
+ /**
6
+ * A Debug Bar panel for the plugin update checker.
7
+ */
8
+ class PluginUpdateCheckerPanel extends Debug_Bar_Panel {
9
+ /** @var PluginUpdateChecker */
10
+ private $updateChecker;
11
+
12
+ private $responseBox = '<div class="puc-ajax-response" style="display: none;"></div>';
13
+
14
+ public function __construct($updateChecker) {
15
+ $this->updateChecker = $updateChecker;
16
+ $title = sprintf(
17
+ '<span id="puc-debug-menu-link-%s">PUC (%s)</span>',
18
+ esc_attr($this->updateChecker->slug),
19
+ $this->updateChecker->slug
20
+ );
21
+ parent::Debug_Bar_Panel($title);
22
+ }
23
+
24
+ public function render() {
25
+ printf(
26
+ '<div class="puc-debug-bar-panel" id="puc-debug-bar-panel_%1$s" data-slug="%1$s" data-nonce="%2$s">',
27
+ esc_attr($this->updateChecker->slug),
28
+ esc_attr(wp_create_nonce('puc-ajax'))
29
+ );
30
+
31
+ $this->displayConfiguration();
32
+ $this->displayStatus();
33
+ $this->displayCurrentUpdate();
34
+
35
+ echo '</div>';
36
+ }
37
+
38
+ private function displayConfiguration() {
39
+ echo '<h3>Configuration</h3>';
40
+ echo '<table class="puc-debug-data">';
41
+ $this->row('Plugin file', htmlentities($this->updateChecker->pluginFile));
42
+ $this->row('Slug', htmlentities($this->updateChecker->slug));
43
+ $this->row('DB option', htmlentities($this->updateChecker->optionName));
44
+
45
+ $requestInfoButton = '';
46
+ if ( function_exists('get_submit_button') ) {
47
+ $requestInfoButton = get_submit_button('Request Info', 'secondary', 'puc-request-info-button', false, array('id' => 'puc-request-info-button-' . $this->updateChecker->slug));
48
+ }
49
+ $this->row('Metadata URL', htmlentities($this->updateChecker->metadataUrl) . ' ' . $requestInfoButton . $this->responseBox);
50
+
51
+ $scheduler = $this->updateChecker->scheduler;
52
+ if ( $scheduler->checkPeriod > 0 ) {
53
+ $this->row('Automatic checks', 'Every ' . $scheduler->checkPeriod . ' hours');
54
+ } else {
55
+ $this->row('Automatic checks', 'Disabled');
56
+ }
57
+
58
+ if ( isset($scheduler->throttleRedundantChecks) ) {
59
+ if ( $scheduler->throttleRedundantChecks && ($scheduler->checkPeriod > 0) ) {
60
+ $this->row(
61
+ 'Throttling',
62
+ sprintf(
63
+ 'Enabled. If an update is already available, check for updates every %1$d hours instead of every %2$d hours.',
64
+ $scheduler->throttledCheckPeriod,
65
+ $scheduler->checkPeriod
66
+ )
67
+ );
68
+ } else {
69
+ $this->row('Throttling', 'Disabled');
70
+ }
71
+ }
72
+ echo '</table>';
73
+ }
74
+
75
+ private function displayStatus() {
76
+ echo '<h3>Status</h3>';
77
+ echo '<table class="puc-debug-data">';
78
+ $state = $this->updateChecker->getUpdateState();
79
+ $checkNowButton = '';
80
+ if ( function_exists('get_submit_button') ) {
81
+ $checkNowButton = get_submit_button('Check Now', 'secondary', 'puc-check-now-button', false, array('id' => 'puc-check-now-button-' . $this->updateChecker->slug));
82
+ }
83
+
84
+ if ( isset($state, $state->lastCheck) ) {
85
+ $this->row('Last check', $this->formatTimeWithDelta($state->lastCheck) . ' ' . $checkNowButton . $this->responseBox);
86
+ } else {
87
+ $this->row('Last check', 'Never');
88
+ }
89
+
90
+ $nextCheck = wp_next_scheduled($this->updateChecker->scheduler->getCronHookName());
91
+ $this->row('Next automatic check', $this->formatTimeWithDelta($nextCheck));
92
+
93
+ if ( isset($state, $state->checkedVersion) ) {
94
+ $this->row('Checked version', htmlentities($state->checkedVersion));
95
+ $this->row('Cached update', $state->update);
96
+ }
97
+ $this->row('Update checker class', htmlentities(get_class($this->updateChecker)));
98
+ echo '</table>';
99
+ }
100
+
101
+ private function displayCurrentUpdate() {
102
+ $update = $this->updateChecker->getUpdate();
103
+ if ( $update !== null ) {
104
+ echo '<h3>An Update Is Available</h3>';
105
+ echo '<table class="puc-debug-data">';
106
+ $fields = array('version', 'download_url', 'slug', 'homepage', 'upgrade_notice');
107
+ foreach($fields as $field) {
108
+ $this->row(ucwords(str_replace('_', ' ', $field)), htmlentities($update->$field));
109
+ }
110
+ echo '</table>';
111
+ } else {
112
+ echo '<h3>No updates currently available</h3>';
113
+ }
114
+ }
115
+
116
+ private function formatTimeWithDelta($unixTime) {
117
+ if ( empty($unixTime) ) {
118
+ return 'Never';
119
+ }
120
+
121
+ $delta = time() - $unixTime;
122
+ $result = human_time_diff(time(), $unixTime);
123
+ if ( $delta < 0 ) {
124
+ $result = 'after ' . $result;
125
+ } else {
126
+ $result = $result . ' ago';
127
+ }
128
+ $result .= ' (' . $this->formatTimestamp($unixTime) . ')';
129
+ return $result;
130
+ }
131
+
132
+ private function formatTimestamp($unixTime) {
133
+ return gmdate('Y-m-d H:i:s', $unixTime + (get_option('gmt_offset') * 3600));
134
+ }
135
+
136
+ private function row($name, $value) {
137
+ if ( is_object($value) || is_array($value) ) {
138
+ $value = '<pre>' . htmlentities(print_r($value, true)) . '</pre>';
139
+ } else if ($value === null) {
140
+ $value = '<code>null</code>';
141
+ }
142
+ printf('<tr><th scope="row">%1$s</th> <td>%2$s</td></tr>', $name, $value);
143
+ }
144
+ }
145
+
146
+ }
functions/updates/debug-bar-plugin.php ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( !class_exists('PucDebugBarPlugin', false) ) {
3
+
4
+ class PucDebugBarPlugin {
5
+ /** @var PluginUpdateChecker_3_0 */
6
+ private $updateChecker;
7
+
8
+ public function __construct($updateChecker) {
9
+ $this->updateChecker = $updateChecker;
10
+
11
+ add_filter('debug_bar_panels', array($this, 'addDebugBarPanel'));
12
+ add_action('debug_bar_enqueue_scripts', array($this, 'enqueuePanelDependencies'));
13
+
14
+ add_action('wp_ajax_puc_debug_check_now', array($this, 'ajaxCheckNow'));
15
+ add_action('wp_ajax_puc_debug_request_info', array($this, 'ajaxRequestInfo'));
16
+ }
17
+
18
+ /**
19
+ * Register the PUC Debug Bar panel.
20
+ *
21
+ * @param array $panels
22
+ * @return array
23
+ */
24
+ public function addDebugBarPanel($panels) {
25
+ require_once dirname(__FILE__) . '/debug-bar-panel.php';
26
+ if ( current_user_can('update_plugins') && class_exists('PluginUpdateCheckerPanel', false) ) {
27
+ $panels[] = new PluginUpdateCheckerPanel($this->updateChecker);
28
+ }
29
+ return $panels;
30
+ }
31
+
32
+ /**
33
+ * Enqueue our Debug Bar scripts and styles.
34
+ */
35
+ public function enqueuePanelDependencies() {
36
+ wp_enqueue_style(
37
+ 'puc-debug-bar-style',
38
+ plugins_url( "/css/puc-debug-bar.css", __FILE__ ),
39
+ array('debug-bar'),
40
+ '20130927'
41
+ );
42
+
43
+ wp_enqueue_script(
44
+ 'puc-debug-bar-js',
45
+ plugins_url( "/js/debug-bar.js", __FILE__ ),
46
+ array('jquery'),
47
+ '20121026'
48
+ );
49
+ }
50
+
51
+ /**
52
+ * Run an update check and output the result. Useful for making sure that
53
+ * the update checking process works as expected.
54
+ */
55
+ public function ajaxCheckNow() {
56
+ if ( $_POST['slug'] !== $this->updateChecker->slug ) {
57
+ return;
58
+ }
59
+ $this->preAjaxReqest();
60
+ $update = $this->updateChecker->checkForUpdates();
61
+ if ( $update !== null ) {
62
+ echo "An update is available:";
63
+ echo '<pre>', htmlentities(print_r($update, true)), '</pre>';
64
+ } else {
65
+ echo 'No updates found.';
66
+ }
67
+ exit;
68
+ }
69
+
70
+ /**
71
+ * Request plugin info and output it.
72
+ */
73
+ public function ajaxRequestInfo() {
74
+ if ( $_POST['slug'] !== $this->updateChecker->slug ) {
75
+ return;
76
+ }
77
+ $this->preAjaxReqest();
78
+ $info = $this->updateChecker->requestInfo();
79
+ if ( $info !== null ) {
80
+ echo 'Successfully retrieved plugin info from the metadata URL:';
81
+ echo '<pre>', htmlentities(print_r($info, true)), '</pre>';
82
+ } else {
83
+ echo 'Failed to retrieve plugin info from the metadata URL.';
84
+ }
85
+ exit;
86
+ }
87
+
88
+ /**
89
+ * Check access permissions and enable error display (for debugging).
90
+ */
91
+ private function preAjaxReqest() {
92
+ if ( !current_user_can('update_plugins') ) {
93
+ die('Access denied');
94
+ }
95
+ check_ajax_referer('puc-ajax');
96
+
97
+ error_reporting(E_ALL);
98
+ @ini_set('display_errors','On');
99
+ }
100
+ }
101
+
102
+ }
functions/updates/github-checker.php ADDED
@@ -0,0 +1,459 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( !class_exists('PucGitHubChecker_3_0', false) ):
4
+
5
+ class PucGitHubChecker_3_0 extends PluginUpdateChecker_3_0 {
6
+ /**
7
+ * @var string GitHub username.
8
+ */
9
+ protected $userName;
10
+ /**
11
+ * @var string GitHub repository name.
12
+ */
13
+ protected $repositoryName;
14
+
15
+ /**
16
+ * @var string Either a fully qualified repository URL, or just "user/repo-name".
17
+ */
18
+ protected $repositoryUrl;
19
+
20
+ /**
21
+ * @var string The branch to use as the latest version. Defaults to "master".
22
+ */
23
+ protected $branch;
24
+
25
+ /**
26
+ * @var string GitHub authentication token. Optional.
27
+ */
28
+ protected $accessToken;
29
+
30
+ public function __construct(
31
+ $repositoryUrl,
32
+ $pluginFile,
33
+ $branch = 'master',
34
+ $checkPeriod = 12,
35
+ $optionName = '',
36
+ $muPluginFile = ''
37
+ ) {
38
+
39
+ $this->repositoryUrl = $repositoryUrl;
40
+ $this->branch = empty($branch) ? 'master' : $branch;
41
+
42
+ $path = @parse_url($repositoryUrl, PHP_URL_PATH);
43
+ if ( preg_match('@^/?(?P<username>[^/]+?)/(?P<repository>[^/#?&]+?)/?$@', $path, $matches) ) {
44
+ $this->userName = $matches['username'];
45
+ $this->repositoryName = $matches['repository'];
46
+ } else {
47
+ throw new InvalidArgumentException('Invalid GitHub repository URL: "' . $repositoryUrl . '"');
48
+ }
49
+
50
+ parent::__construct($repositoryUrl, $pluginFile, '', $checkPeriod, $optionName, $muPluginFile);
51
+ }
52
+
53
+ /**
54
+ * Retrieve details about the latest plugin version from GitHub.
55
+ *
56
+ * @param array $unusedQueryArgs Unused.
57
+ * @return PluginInfo_3_0
58
+ */
59
+ public function requestInfo($unusedQueryArgs = array()) {
60
+ $info = new PluginInfo_3_0();
61
+ $info->filename = $this->pluginFile;
62
+ $info->slug = $this->slug;
63
+
64
+ $this->setInfoFromHeader($this->getPluginHeader(), $info);
65
+
66
+ //Figure out which reference (tag or branch) we'll use to get the latest version of the plugin.
67
+ $ref = $this->branch;
68
+ if ( $this->branch === 'master' ) {
69
+ //Use the latest release.
70
+ $release = $this->getLatestRelease();
71
+ if ( $release !== null ) {
72
+ $ref = $release->tag_name;
73
+ $info->version = ltrim($release->tag_name, 'v'); //Remove the "v" prefix from "v1.2.3".
74
+ $info->last_updated = $release->created_at;
75
+ $info->download_url = $release->zipball_url;
76
+
77
+ if ( !empty($release->body) ) {
78
+ $info->sections['changelog'] = $this->parseMarkdown($release->body);
79
+ }
80
+ if ( isset($release->assets[0]) ) {
81
+ $info->downloaded = $release->assets[0]->download_count;
82
+ }
83
+ } else {
84
+ //Failing that, use the tag with the highest version number.
85
+ $tag = $this->getLatestTag();
86
+ if ( $tag !== null ) {
87
+ $ref = $tag->name;
88
+ $info->version = $tag->name;
89
+ $info->download_url = $tag->zipball_url;
90
+ }
91
+ }
92
+ }
93
+
94
+ if ( empty($info->download_url) ) {
95
+ $info->download_url = $this->buildArchiveDownloadUrl($ref);
96
+ } else if ( !empty($this->accessToken) ) {
97
+ $info->download_url = add_query_arg('access_token', $this->accessToken, $info->download_url);
98
+ }
99
+
100
+ //Get headers from the main plugin file in this branch/tag. Its "Version" header and other metadata
101
+ //are what the WordPress install will actually see after upgrading, so they take precedence over releases/tags.
102
+ $mainPluginFile = basename($this->pluginFile);
103
+ $remotePlugin = $this->getRemoteFile($mainPluginFile, $ref);
104
+ if ( !empty($remotePlugin) ) {
105
+ $remoteHeader = $this->getFileHeader($remotePlugin);
106
+ $this->setInfoFromHeader($remoteHeader, $info);
107
+ }
108
+
109
+ //Try parsing readme.txt. If it's formatted according to WordPress.org standards, it will contain
110
+ //a lot of useful information like the required/tested WP version, changelog, and so on.
111
+ if ( $this->readmeTxtExistsLocally() ) {
112
+ $this->setInfoFromRemoteReadme($ref, $info);
113
+ }
114
+
115
+ //The changelog might be in a separate file.
116
+ if ( empty($info->sections['changelog']) ) {
117
+ $info->sections['changelog'] = $this->getRemoteChangelog($ref);
118
+ if ( empty($info->sections['changelog']) ) {
119
+ $info->sections['changelog'] = __('There is no changelog available.', 'plugin-update-checker');
120
+ }
121
+ }
122
+
123
+ if ( empty($info->last_updated) ) {
124
+ //Fetch the latest commit that changed the main plugin file and use it as the "last_updated" date.
125
+ //It's reasonable to assume that every update will change the version number in that file.
126
+ $latestCommit = $this->getLatestCommit($mainPluginFile, $ref);
127
+ if ( $latestCommit !== null ) {
128
+ $info->last_updated = $latestCommit->commit->author->date;
129
+ }
130
+ }
131
+
132
+ $info = apply_filters('puc_request_info_result-' . $this->slug, $info, null);
133
+ return $info;
134
+ }
135
+
136
+ /**
137
+ * Get the latest release from GitHub.
138
+ *
139
+ * @return StdClass|null
140
+ */
141
+ protected function getLatestRelease() {
142
+ $releases = $this->api('/repos/:user/:repo/releases');
143
+ if ( is_wp_error($releases) || !is_array($releases) || !isset($releases[0]) ) {
144
+ return null;
145
+ }
146
+
147
+ $latestRelease = $releases[0];
148
+ return $latestRelease;
149
+ }
150
+
151
+ /**
152
+ * Get the tag that looks like the highest version number.
153
+ *
154
+ * @return StdClass|null
155
+ */
156
+ protected function getLatestTag() {
157
+ $tags = $this->api('/repos/:user/:repo/tags');
158
+
159
+ if ( is_wp_error($tags) || empty($tags) || !is_array($tags) ) {
160
+ return null;
161
+ }
162
+
163
+ usort($tags, array($this, 'compareTagNames')); //Sort from highest to lowest.
164
+ return $tags[0];
165
+ }
166
+
167
+ /**
168
+ * Compare two GitHub tags as if they were version number.
169
+ *
170
+ * @param string $tag1
171
+ * @param string $tag2
172
+ * @return int
173
+ */
174
+ protected function compareTagNames($tag1, $tag2) {
175
+ if ( !isset($tag1->name) ) {
176
+ return 1;
177
+ }
178
+ if ( !isset($tag2->name) ) {
179
+ return -1;
180
+ }
181
+ return -version_compare($tag1->name, $tag2->name);
182
+ }
183
+
184
+ /**
185
+ * Get the latest commit that changed the specified file.
186
+ *
187
+ * @param string $filename
188
+ * @param string $ref Reference name (e.g. branch or tag).
189
+ * @return StdClass|null
190
+ */
191
+ protected function getLatestCommit($filename, $ref = 'master') {
192
+ $commits = $this->api(
193
+ '/repos/:user/:repo/commits',
194
+ array(
195
+ 'path' => $filename,
196
+ 'sha' => $ref,
197
+ )
198
+ );
199
+ if ( !is_wp_error($commits) && is_array($commits) && isset($commits[0]) ) {
200
+ return $commits[0];
201
+ }
202
+ return null;
203
+ }
204
+
205
+ protected function getRemoteChangelog($ref = '') {
206
+ $filename = $this->getChangelogFilename();
207
+ if ( empty($filename) ) {
208
+ return null;
209
+ }
210
+
211
+ $changelog = $this->getRemoteFile($filename, $ref);
212
+ if ( $changelog === null ) {
213
+ return null;
214
+ }
215
+ return $this->parseMarkdown($changelog);
216
+ }
217
+
218
+ protected function getChangelogFilename() {
219
+ $pluginDirectory = dirname($this->pluginAbsolutePath);
220
+ if ( empty($this->pluginAbsolutePath) || !is_dir($pluginDirectory) || ($pluginDirectory === '.') ) {
221
+ return null;
222
+ }
223
+
224
+ $possibleNames = array('CHANGES.md', 'CHANGELOG.md', 'changes.md', 'changelog.md');
225
+ $files = scandir($pluginDirectory);
226
+ $foundNames = array_intersect($possibleNames, $files);
227
+
228
+ if ( !empty($foundNames) ) {
229
+ return reset($foundNames);
230
+ }
231
+ return null;
232
+ }
233
+
234
+ /**
235
+ * Convert Markdown to HTML.
236
+ *
237
+ * @param string $markdown
238
+ * @return string
239
+ */
240
+ protected function parseMarkdown($markdown) {
241
+ if ( !class_exists('Parsedown', false) ) {
242
+ require_once(dirname(__FILE__) . '/vendor/Parsedown' . (version_compare(PHP_VERSION, '5.3.0', '>=') ? '' : 'Legacy') . '.php');
243
+ }
244
+
245
+ $instance = Parsedown::instance();
246
+ return $instance->text($markdown);
247
+ }
248
+
249
+ /**
250
+ * Perform a GitHub API request.
251
+ *
252
+ * @param string $url
253
+ * @param array $queryParams
254
+ * @return mixed|WP_Error
255
+ */
256
+ protected function api($url, $queryParams = array()) {
257
+ $variables = array(
258
+ 'user' => $this->userName,
259
+ 'repo' => $this->repositoryName,
260
+ );
261
+ foreach ($variables as $name => $value) {
262
+ $url = str_replace('/:' . $name, '/' . urlencode($value), $url);
263
+ }
264
+ $url = 'https://api.github.com' . $url;
265
+
266
+ if ( !empty($this->accessToken) ) {
267
+ $queryParams['access_token'] = $this->accessToken;
268
+ }
269
+ if ( !empty($queryParams) ) {
270
+ $url = add_query_arg($queryParams, $url);
271
+ }
272
+
273
+ $response = wp_remote_get($url, array('timeout' => 10));
274
+ if ( is_wp_error($response) ) {
275
+ return $response;
276
+ }
277
+
278
+ $code = wp_remote_retrieve_response_code($response);
279
+ $body = wp_remote_retrieve_body($response);
280
+ if ( $code === 200 ) {
281
+ $document = json_decode($body);
282
+ return $document;
283
+ }
284
+
285
+ return new WP_Error(
286
+ 'puc-github-http-error',
287
+ 'GitHub API error. HTTP status: ' . $code
288
+ );
289
+ }
290
+
291
+ /**
292
+ * Set the access token that will be used to make authenticated GitHub API requests.
293
+ *
294
+ * @param string $accessToken
295
+ */
296
+ public function setAccessToken($accessToken) {
297
+ $this->accessToken = $accessToken;
298
+ }
299
+
300
+ /**
301
+ * Get the contents of a file from a specific branch or tag.
302
+ *
303
+ * @param string $path File name.
304
+ * @param string $ref
305
+ * @return null|string Either the contents of the file, or null if the file doesn't exist or there's an error.
306
+ */
307
+ protected function getRemoteFile($path, $ref = 'master') {
308
+ $apiUrl = '/repos/:user/:repo/contents/' . $path;
309
+ $response = $this->api($apiUrl, array('ref' => $ref));
310
+
311
+ if ( is_wp_error($response) || !isset($response->content) || ($response->encoding !== 'base64') ) {
312
+ return null;
313
+ }
314
+ return base64_decode($response->content);
315
+ }
316
+
317
+ /**
318
+ * Parse plugin metadata from the header comment.
319
+ * This is basically a simplified version of the get_file_data() function from /wp-includes/functions.php.
320
+ *
321
+ * @param $content
322
+ * @return array
323
+ */
324
+ protected function getFileHeader($content) {
325
+ $headers = array(
326
+ 'Name' => 'Plugin Name',
327
+ 'PluginURI' => 'Plugin URI',
328
+ 'Version' => 'Version',
329
+ 'Description' => 'Description',
330
+ 'Author' => 'Author',
331
+ 'AuthorURI' => 'Author URI',
332
+ 'TextDomain' => 'Text Domain',
333
+ 'DomainPath' => 'Domain Path',
334
+ 'Network' => 'Network',
335
+
336
+ //The newest WordPress version that this plugin requir