Version Description
Lazy load images and iframes. Complete rewrite.
Download this release
Release Info
Developer | bjornjohansen |
Plugin | BJ Lazy Load |
Version | 0.5.0 |
Comparing to | |
See all releases |
Code changes from version 0.4.0 to 0.5.0
- admin.php +39 -0
- bj-lazy-load.php +170 -498
- css/bjll.css +0 -1
- js/bj-lazy-load.js +78 -0
- js/bj-lazy-load.min.js +1 -0
- js/bjll.js +0 -5
- js/bjll.min.js +0 -22
- js/jail.min.js +0 -20
- js/jquery.sonar.min.js +1 -0
- lang/bj-lazy-load-nb_NO.mo +0 -0
- lang/bj-lazy-load-nb_NO.po +0 -137
- lang/bj-lazy-load.pot +0 -152
- readme.txt +20 -13
- scb/AdminPage.php +453 -0
- scb/BoxesPage.php +240 -0
- scb/Cron.php +170 -0
- scb/Forms.php +531 -0
- scb/Hooks.php +72 -0
- scb/Options.php +163 -0
- scb/Table.php +78 -0
- scb/Util.php +202 -0
- scb/Widget.php +75 -0
- scb/load.php +91 -0
admin.php
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class BJLL_Admin_Page extends scbAdminPage {
|
4 |
+
|
5 |
+
function setup() {
|
6 |
+
$this->args = array(
|
7 |
+
'menu_title' => 'BJ Lazy Load',
|
8 |
+
'page_title' => __( 'BJ Lazy Load Options', 'bj_lazy_load' ),
|
9 |
+
);
|
10 |
+
}
|
11 |
+
|
12 |
+
function page_content() {
|
13 |
+
|
14 |
+
|
15 |
+
echo $this->form_table( array(
|
16 |
+
array(
|
17 |
+
'title' => __( 'Lazy load images', 'bj_lazy_load' ),
|
18 |
+
'type' => 'radio',
|
19 |
+
'name' => 'lazy_load_images',
|
20 |
+
'value' => array( 'yes' => __('Yes', 'bj_lazy_load'), 'no' => __('No', 'bj_lazy_load') ),
|
21 |
+
),
|
22 |
+
array(
|
23 |
+
'title' => __( 'Lazy load iframes', 'bj_lazy_load' ),
|
24 |
+
'type' => 'radio',
|
25 |
+
'name' => 'lazy_load_iframes',
|
26 |
+
'value' => array( 'yes' => __('Yes', 'bj_lazy_load'), 'no' => __('No', 'bj_lazy_load') ),
|
27 |
+
),
|
28 |
+
array(
|
29 |
+
'title' => __( 'Theme loader function', 'bj_lazy_load' ),
|
30 |
+
'type' => 'select',
|
31 |
+
'name' => 'theme_loader_function',
|
32 |
+
'value' => array( 'wp_footer', 'wp_head' ),
|
33 |
+
|
34 |
+
)
|
35 |
+
) );
|
36 |
+
|
37 |
+
}
|
38 |
+
|
39 |
+
}
|
bj-lazy-load.php
CHANGED
@@ -1,498 +1,170 @@
|
|
1 |
-
<?php
|
2 |
-
/*
|
3 |
-
Plugin Name: BJ Lazy Load
|
4 |
-
Plugin URI: http://wordpress.org/extend/plugins/bj-lazy-load/
|
5 |
-
Description: Lazy image loading makes your site load faster and saves bandwidth.
|
6 |
-
Version: 0.
|
7 |
-
Author: Bjørn Johansen
|
8 |
-
Author URI: http://twitter.com/bjornjohansen
|
9 |
-
License: GPL2
|
10 |
-
|
11 |
-
Copyright 2011–2012 Bjørn Johansen (email : post@bjornjohansen.no)
|
12 |
-
|
13 |
-
This program is free software; you can redistribute it and/or modify
|
14 |
-
it under the terms of the GNU General Public License, version 2, as
|
15 |
-
published by the Free Software Foundation.
|
16 |
-
|
17 |
-
This program is distributed in the hope that it will be useful,
|
18 |
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
19 |
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
20 |
-
GNU General Public License for more details.
|
21 |
-
|
22 |
-
You should have received a copy of the GNU General Public License
|
23 |
-
along with this program; if not, write to the Free Software
|
24 |
-
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
25 |
-
|
26 |
-
*/
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
protected function _get_placeholder_html ( $html ) {
|
172 |
-
|
173 |
-
if ( class_exists( 'DOMDocument') ) {
|
174 |
-
$html = $this->_get_placeholder_html_dom( $html );
|
175 |
-
} else {
|
176 |
-
$html = $this->_get_placeholder_html_regexp( $html );
|
177 |
-
}
|
178 |
-
|
179 |
-
return $html;
|
180 |
-
}
|
181 |
-
|
182 |
-
protected function _get_placeholder_html_dom ( $html ) {
|
183 |
-
|
184 |
-
$loadhtml = sprintf( '<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"><title></title></head><body>%s</body></html>', $html );
|
185 |
-
|
186 |
-
$doc = @DOMDocument::loadHTML( $loadhtml );
|
187 |
-
if ( ! $doc ) {
|
188 |
-
return $this->_get_placeholder_html_regexp( $html );
|
189 |
-
}
|
190 |
-
|
191 |
-
$images = $doc->getElementsByTagName( 'img' );
|
192 |
-
|
193 |
-
//$img = $images->item( 0 );
|
194 |
-
// Thanks to d.sturm for pointing this out: http://wordpress.org/support/topic/plugin-bj-lazy-load?replies=3#post-2539962
|
195 |
-
if ( ! $img = $images->item( 0 ) ) {
|
196 |
-
return $this->_get_placeholder_html_regexp( $html );
|
197 |
-
}
|
198 |
-
|
199 |
-
//foreach ( $images as $img ) {
|
200 |
-
|
201 |
-
$noscriptImg = $img->cloneNode( true );
|
202 |
-
$noscript = $doc->createElement( 'noscript' );
|
203 |
-
$noscript->appendChild( $noscriptImg );
|
204 |
-
|
205 |
-
$src = $img->getAttribute( 'src' );
|
206 |
-
$class = $img->getAttribute( 'class' );
|
207 |
-
|
208 |
-
$class .= ' lazy lazy-hidden';
|
209 |
-
|
210 |
-
$img->setAttribute( 'data-src' , $src );
|
211 |
-
$img->setAttribute( 'src' , $this->_placeholder_url );
|
212 |
-
$img->setAttribute( 'class' , trim( $class ) );
|
213 |
-
|
214 |
-
$img->parentNode->appendChild( $noscript );
|
215 |
-
|
216 |
-
//}
|
217 |
-
|
218 |
-
$rethtml = $doc->saveHTML();
|
219 |
-
|
220 |
-
$rethtml = substr( $rethtml, strpos( $rethtml, '<body>' ) + 6 );
|
221 |
-
$rethtml = substr( $rethtml, 0, strpos( $rethtml, '</body>' ) );
|
222 |
-
|
223 |
-
return $rethtml;
|
224 |
-
}
|
225 |
-
protected function _get_placeholder_html_regexp ( $html ) {
|
226 |
-
$orig_html = $html;
|
227 |
-
|
228 |
-
/**/
|
229 |
-
// replace the src and add the data-src attribute
|
230 |
-
$html = preg_replace( '/<img(.*?)src=/i', '<img$1src="' . $this->_placeholder_url . '" data-src=', $html );
|
231 |
-
|
232 |
-
// add the lazy class to the img element
|
233 |
-
if ( preg_match( '/class="/i', $html ) ) {
|
234 |
-
$html = preg_replace( '/class="(.*?)"/i', ' class="lazy lazy-hidden $1"', $html );
|
235 |
-
} else {
|
236 |
-
$html = preg_replace( '/<img/i', '<img class="lazy lazy-hidden"', $html );
|
237 |
-
}
|
238 |
-
|
239 |
-
$html .= '<noscript>' . $orig_html . '</noscript>';
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
// http://24ways.org/2011/adaptive-images-for-responsive-designs-again
|
244 |
-
// This is a no-go. <img> within <noscript> within <a> gets parsed horribly wrong
|
245 |
-
//$html = "<script>document.write('<' + '!--')</script><noscript class=\"lazy-nojs\">" . $orig_html . '<noscript -->';
|
246 |
-
|
247 |
-
return $html;
|
248 |
-
}
|
249 |
-
|
250 |
-
}
|
251 |
-
|
252 |
-
class BJLL_Admin {
|
253 |
-
|
254 |
-
function __construct () {
|
255 |
-
add_action( 'init', array( $this, 'load_i18n' ) );
|
256 |
-
add_action( 'admin_menu', array( $this, 'plugin_menu' ) );
|
257 |
-
add_action( 'admin_init', array( $this, 'register_settings' ) );
|
258 |
-
|
259 |
-
add_filter( 'plugin_action_links', array( $this, 'plugin_settings_link' ), 10, 2);
|
260 |
-
}
|
261 |
-
|
262 |
-
function load_i18n() {;
|
263 |
-
load_plugin_textdomain( 'bj-lazy-load', false, basename( dirname( __FILE__ ) ) . DIRECTORY_SEPARATOR . 'lang' );
|
264 |
-
}
|
265 |
-
|
266 |
-
function plugin_menu () {
|
267 |
-
add_options_page( 'BJ Lazy Load', 'BJ Lazy Load', 'manage_options', 'bjll', array( $this, 'plugin_options_page' ) );
|
268 |
-
}
|
269 |
-
|
270 |
-
public static function plugin_settings_link( $links, $file ) {
|
271 |
-
|
272 |
-
if ( plugin_basename( __FILE__ ) == $file ) {
|
273 |
-
array_unshift($links, '<a href="' . admin_url( 'admin.php' ) . '?page=bjll">' . __( 'Settings' ) . '</a>');
|
274 |
-
}
|
275 |
-
|
276 |
-
return $links;
|
277 |
-
}
|
278 |
-
|
279 |
-
function register_settings () {
|
280 |
-
register_setting( 'bjll_options', 'bjll_filter_post_thumbnails', 'intval' );
|
281 |
-
register_setting( 'bjll_options', 'bjll_include_js', 'intval' );
|
282 |
-
register_setting( 'bjll_options', 'bjll_include_css', 'intval' );
|
283 |
-
register_setting( 'bjll_options', 'bjll_theme_caller' );
|
284 |
-
|
285 |
-
add_settings_section( 'bjll_general', __('General'), array( 'BJLL_Admin', 'settings_section_general' ), 'bjll' );
|
286 |
-
|
287 |
-
add_settings_field( 'bjll_filter_post_thumbnails', __( 'Lazy load post thumbnails', 'bj-lazy-load' ), array( 'BJLL_Admin', 'setting_field_filter_post_thumbnails' ), 'bjll', 'bjll_general', array( 'label_for' => 'bjll_filter_post_thumbnails' ) );
|
288 |
-
add_settings_field( 'bjll_include_js', __( 'Include JS', 'bj-lazy-load' ), array( 'BJLL_Admin', 'setting_field_include_js'), 'bjll', 'bjll_general', array( 'label_for' => 'bjll_include_js' ) );
|
289 |
-
add_settings_field( 'bjll_include_css', __( 'Include CSS', 'bj-lazy-load' ), array( 'BJLL_Admin', 'setting_field_include_css'), 'bjll', 'bjll_general', array( 'label_for' => 'bjll_include_css' ) );
|
290 |
-
add_settings_field( 'bjll_theme_caller', __( 'Theme caller function', 'bj-lazy-load' ), array('BJLL_Admin', 'setting_field_theme_caller' ), 'bjll', 'bjll_general', array( 'label_for' => 'bjll_theme_caller' ) );
|
291 |
-
|
292 |
-
register_setting( 'bjll_options', 'bjll_timeout', 'intval' );
|
293 |
-
register_setting( 'bjll_options', 'bjll_effect' );
|
294 |
-
register_setting( 'bjll_options', 'bjll_speed', 'intval' );
|
295 |
-
register_setting( 'bjll_options', 'bjll_event', array( 'BJLL_Admin', 'sanitize_setting_event' ) );
|
296 |
-
register_setting( 'bjll_options', 'bjll_callback' );
|
297 |
-
register_setting( 'bjll_options', 'bjll_callbackAfterEachImage' );
|
298 |
-
register_setting( 'bjll_options', 'bjll_placeholder' );
|
299 |
-
register_setting( 'bjll_options', 'bjll_offset', 'intval' );
|
300 |
-
register_setting( 'bjll_options', 'bjll_ignoreHiddenImages', 'intval' );
|
301 |
-
|
302 |
-
add_settings_section( 'bjll_loader', __( 'JAIL Settings', 'bj-lazy-load' ), array( 'BJLL_Admin','settings_section_loader' ), 'bjll' );
|
303 |
-
|
304 |
-
add_settings_field( 'bjll_timeout', __( 'Timeout', 'bj-lazy-load' ), array( 'BJLL_Admin', 'setting_field_timeout' ), 'bjll', 'bjll_loader', array( 'label_for' => 'bjll_timeout' ) );
|
305 |
-
add_settings_field( 'bjll_effect', __( 'jQuery Effect', 'bj-lazy-load' ), array('BJLL_Admin', 'setting_field_effect' ), 'bjll', 'bjll_loader', array( 'label_for' => 'bjll_effect' ) );
|
306 |
-
add_settings_field( 'bjll_speed', __( 'Effect Speed', 'bj-lazy-load' ), array('BJLL_Admin', 'setting_field_speed' ), 'bjll', 'bjll_loader', array( 'label_for' => 'bjll_speed' ) );
|
307 |
-
add_settings_field( 'bjll_event', __( 'Trigger Event', 'bj-lazy-load' ), array('BJLL_Admin', 'setting_field_event' ), 'bjll', 'bjll_loader', array( 'label_for' => 'bjll_event' ) );
|
308 |
-
add_settings_field( 'bjll_offset', __( 'Offset/Threshold', 'bj-lazy-load' ), array('BJLL_Admin', 'setting_field_offset' ), 'bjll', 'bjll_loader', array( 'label_for' => 'bjll_offset' ) );
|
309 |
-
add_settings_field( 'bjll_ignoreHiddenImages', __( 'Ignore Hidden Images', 'bj-lazy-load' ), array( 'BJLL_Admin', 'setting_field_ignoreHiddenImages' ), 'bjll', 'bjll_loader', array( 'label_for' => 'bjll_ignoreHiddenImages' ) );
|
310 |
-
|
311 |
-
}
|
312 |
-
|
313 |
-
function sanitize_setting_theme_caller ( $val ) {
|
314 |
-
$validoptions = self::_get_valid_setting_options_event();
|
315 |
-
if ( ! in_array( $val, $validoptions ) ) {
|
316 |
-
// get previous saved value
|
317 |
-
$val = get_option( 'bjll_theme_caller', 'wp_footer' );
|
318 |
-
if ( ! in_array( $val, $validoptions ) ) {
|
319 |
-
// if still not valid, set to our default
|
320 |
-
$val = $validoptions[0];
|
321 |
-
}
|
322 |
-
}
|
323 |
-
return $val;
|
324 |
-
}
|
325 |
-
function sanitize_setting_event ( $val ) {
|
326 |
-
$validoptions = self::_get_valid_setting_options_event();
|
327 |
-
if ( ! in_array( $val, $validoptions ) ) {
|
328 |
-
// get previous saved value
|
329 |
-
$val = get_option( 'bjll_event', 'load+scroll' );
|
330 |
-
if ( ! in_array( $val, $validoptions ) ) {
|
331 |
-
// if still not valid, set to our default
|
332 |
-
$val = $validoptions[0];
|
333 |
-
}
|
334 |
-
}
|
335 |
-
return $val;
|
336 |
-
}
|
337 |
-
|
338 |
-
function sanitize_setting_effect ( $val ) {
|
339 |
-
if ( ! strlen( $val ) ) {
|
340 |
-
$val = null;
|
341 |
-
}
|
342 |
-
return $val;
|
343 |
-
}
|
344 |
-
|
345 |
-
private static function _get_valid_setting_options_theme_caller () {
|
346 |
-
return array( 'wp_footer', 'wp_head' );
|
347 |
-
}
|
348 |
-
private static function _get_valid_setting_options_event () {
|
349 |
-
return array( 'load+scroll', 'load', 'click', 'mouseover', 'scroll' );
|
350 |
-
}
|
351 |
-
|
352 |
-
|
353 |
-
function settings_section_general () {
|
354 |
-
}
|
355 |
-
|
356 |
-
function settings_section_loader () {
|
357 |
-
}
|
358 |
-
|
359 |
-
function setting_field_filter_post_thumbnails () {
|
360 |
-
$checked = '';
|
361 |
-
if ( intval( get_option( 'bjll_filter_post_thumbnails', 1 ) ) ) {
|
362 |
-
$checked = ' checked="checked"';
|
363 |
-
}
|
364 |
-
|
365 |
-
echo '<input id="bjll_filter_post_thumbnails" name="bjll_filter_post_thumbnails" type="checkbox" value="1" ' . $checked . ' />';
|
366 |
-
}
|
367 |
-
|
368 |
-
function setting_field_include_js () {
|
369 |
-
$checked = '';
|
370 |
-
if ( intval( get_option( 'bjll_include_js', 1 ) ) ) {
|
371 |
-
$checked = ' checked="checked"';
|
372 |
-
}
|
373 |
-
|
374 |
-
echo '<input id="bjll_include_js" name="bjll_include_js" type="checkbox" value="1" ' . $checked . ' /> ';
|
375 |
-
_e( 'Needed for the plugin to work, but <a href="http://developer.yahoo.com/performance/rules.html#num_http" target="_blank">for best performance you should include it in your combined JS</a>', 'bj-lazy-load' );
|
376 |
-
}
|
377 |
-
|
378 |
-
function setting_field_include_css () {
|
379 |
-
$checked = '';
|
380 |
-
if ( intval( get_option( 'bjll_include_css', 1 ) ) ) {
|
381 |
-
$checked = ' checked="checked"';
|
382 |
-
}
|
383 |
-
|
384 |
-
echo '<input id="bjll_include_css" name="bjll_include_css" type="checkbox" value="1" ' . $checked . ' /> ';
|
385 |
-
_e( 'Needed for the plugin to work, but <a href="http://developer.yahoo.com/performance/rules.html#num_http" target="_blank">for best performance you should include it in your combined CSS</a>' , 'bj-lazy-load');
|
386 |
-
}
|
387 |
-
function setting_field_ignoreHiddenImages () {
|
388 |
-
|
389 |
-
$checked = '';
|
390 |
-
if ( intval( get_option( 'bjll_ignoreHiddenImages', 0 ) ) ) {
|
391 |
-
$checked = ' checked="checked"';
|
392 |
-
}
|
393 |
-
|
394 |
-
echo '<input id="bjll_ignoreHiddenImages" name="bjll_ignoreHiddenImages" type="checkbox" value="1" ' . $checked . ' /> ';
|
395 |
-
_e( 'Whether to ignore hidden images to be loaded - Default: false/unchecked (so hidden images are loaded)', 'bj-lazy-load' );
|
396 |
-
|
397 |
-
}
|
398 |
-
function setting_field_theme_caller () {
|
399 |
-
|
400 |
-
$options = self::_get_valid_setting_options_theme_caller();
|
401 |
-
|
402 |
-
$currentval = get_option( 'bjll_theme_caller' );
|
403 |
-
|
404 |
-
echo '<select id="bjll_theme_caller" name="bjll_theme_caller">';
|
405 |
-
foreach ( $options as $option ) {
|
406 |
-
$selected = '';
|
407 |
-
if ( $option == $currentval ) {
|
408 |
-
$selected = ' selected="selected"';
|
409 |
-
}
|
410 |
-
echo sprintf( '<option value="%1$s"%2$s>%1$s</option>', $option, $selected );
|
411 |
-
}
|
412 |
-
echo '</select> ';
|
413 |
-
_e( 'Put the script in either wp_footer() (should be right before </body>) or wp_head() (in the <head>-element).', 'bj-lazy-load' );
|
414 |
-
}
|
415 |
-
function setting_field_event () {
|
416 |
-
|
417 |
-
$options = self::_get_valid_setting_options_event();
|
418 |
-
|
419 |
-
$currentval = get_option( 'bjll_event' );
|
420 |
-
|
421 |
-
echo '<select id="bjll_event" name="bjll_event">';
|
422 |
-
foreach ( $options as $option ) {
|
423 |
-
$selected = '';
|
424 |
-
if ( $option == $currentval ) {
|
425 |
-
$selected = ' selected="selected"';
|
426 |
-
}
|
427 |
-
echo sprintf( '<option value="%1$s"%2$s>%1$s</option>', $option, $selected );
|
428 |
-
}
|
429 |
-
echo '</select> ';
|
430 |
-
_e( 'Event that triggers the image to load. Default: load+scroll', 'bj-lazy-load' );
|
431 |
-
}
|
432 |
-
function setting_field_timeout () {
|
433 |
-
$val = get_option( 'bjll_timeout', 10 );
|
434 |
-
echo '<input id="bjll_timeout" name="bjll_timeout" type="text" value="' . $val . '" /> ';
|
435 |
-
_e( 'Number of msec after that the images will be loaded - Default: 10', 'bj-lazy-load' );
|
436 |
-
}
|
437 |
-
function setting_field_effect () {
|
438 |
-
$val = get_option( 'bjll_effect', '' );
|
439 |
-
if ( 'null' == strtolower( $val ) ) {
|
440 |
-
$val = '';
|
441 |
-
}
|
442 |
-
echo '<input id="bjll_effect" name="bjll_effect" type="text" value="' . $val . '" />';
|
443 |
-
_e( 'Any jQuery effect that makes the images display (e.g. "fadeIn") - Default: NULL', 'bj-lazy-load');
|
444 |
-
echo '<p>';
|
445 |
-
_e( 'NOTE: If you are loading a large number of images, it is best to NOT use this setting. Effects calls are very expensive. Even a simple show() can have a major impact on the browser’s responsiveness.', 'bj-lazy-load' );
|
446 |
-
echo '</p>';
|
447 |
-
}
|
448 |
-
function setting_field_speed () {
|
449 |
-
$val = get_option( 'bjll_speed', 400 );
|
450 |
-
echo '<input id="bjll_speed" name="bjll_speed" type="text" value="' . $val . '" /> ';
|
451 |
-
_e( 'string or number determining how long the animation will run - Default: 400', 'bj-lazy-load' );
|
452 |
-
}
|
453 |
-
function setting_field_offset () {
|
454 |
-
$val = get_option( 'bjll_offset', 200 );
|
455 |
-
echo '<input id="bjll_offset" name="bjll_offset" type="text" value="' . $val . '" /> ';
|
456 |
-
_e( 'An offset of "500" would cause any images that are less than 500px below the bottom of the window or 500px above the top of the window to load. - Default: 200', 'bj-lazy-load' );
|
457 |
-
}
|
458 |
-
|
459 |
-
function plugin_options_page () {
|
460 |
-
if ( ! current_user_can( 'manage_options' ) ) {
|
461 |
-
wp_die( __( 'You do not have sufficient permissions to access this page.', 'bj-lazy-load' ) );
|
462 |
-
}
|
463 |
-
?>
|
464 |
-
<div class="wrap">
|
465 |
-
<h2>BJ Lazy Load <?php _e( 'Settings' ); ?></h2>
|
466 |
-
<form method="post" action="options.php">
|
467 |
-
<?php settings_fields( 'bjll_options' ); ?>
|
468 |
-
<?php do_settings_sections( 'bjll' ); ?>
|
469 |
-
|
470 |
-
<p class="submit">
|
471 |
-
<input type="submit" class="button-primary" value="<?php _e( 'Save Changes' ) ?>" />
|
472 |
-
</p>
|
473 |
-
</form>
|
474 |
-
</div>
|
475 |
-
<?php
|
476 |
-
}
|
477 |
-
|
478 |
-
}
|
479 |
-
|
480 |
-
|
481 |
-
/*
|
482 |
-
is_admin() will return true when trying to make an ajax request
|
483 |
-
if (!is_admin() && !is_feed()) {
|
484 |
-
*/
|
485 |
-
/* 'Conditional query tags do not work before the query is run. Before then, they always return false.' */
|
486 |
-
/* Anonymous functions aren't available before PHP 5.3, so we need a temp wrapper */
|
487 |
-
function BJLL_action_init () {
|
488 |
-
if ( ! is_feed() ) {
|
489 |
-
BJLL::singleton() ;
|
490 |
-
}
|
491 |
-
}
|
492 |
-
add_action( 'wp', 'BJLL_action_init', 10, 0 );
|
493 |
-
|
494 |
-
|
495 |
-
if ( is_admin() ) {
|
496 |
-
new BJLL_Admin;
|
497 |
-
}
|
498 |
-
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
Plugin Name: BJ Lazy Load
|
4 |
+
Plugin URI: http://wordpress.org/extend/plugins/bj-lazy-load/
|
5 |
+
Description: Lazy image loading makes your site load faster and saves bandwidth.
|
6 |
+
Version: 0.5.0
|
7 |
+
Author: Bjørn Johansen
|
8 |
+
Author URI: http://twitter.com/bjornjohansen
|
9 |
+
License: GPL2
|
10 |
+
|
11 |
+
Copyright 2011–2012 Bjørn Johansen (email : post@bjornjohansen.no)
|
12 |
+
|
13 |
+
This program is free software; you can redistribute it and/or modify
|
14 |
+
it under the terms of the GNU General Public License, version 2, as
|
15 |
+
published by the Free Software Foundation.
|
16 |
+
|
17 |
+
This program is distributed in the hope that it will be useful,
|
18 |
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
19 |
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
20 |
+
GNU General Public License for more details.
|
21 |
+
|
22 |
+
You should have received a copy of the GNU General Public License
|
23 |
+
along with this program; if not, write to the Free Software
|
24 |
+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
25 |
+
|
26 |
+
*/
|
27 |
+
|
28 |
+
|
29 |
+
require_once( dirname(__FILE__) . '/scb/load.php' );
|
30 |
+
|
31 |
+
if ( ! class_exists( 'BJLL' ) ) {
|
32 |
+
class BJLL {
|
33 |
+
|
34 |
+
const version = '0.5.0';
|
35 |
+
protected $_placeholder_url;
|
36 |
+
|
37 |
+
protected static $_instance;
|
38 |
+
|
39 |
+
function __construct() {
|
40 |
+
|
41 |
+
$this->_placeholder_url = plugins_url( '/img/placeholder.gif', __FILE__ );
|
42 |
+
|
43 |
+
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
|
44 |
+
|
45 |
+
add_filter( 'the_content', array( $this, 'filter' ), 200 );
|
46 |
+
add_filter( 'post_thumbnail_html', array( $this, 'filter' ), 200 );
|
47 |
+
add_filter( 'get_avatar', array( $this, 'filter' ), 200 );
|
48 |
+
}
|
49 |
+
|
50 |
+
static function singleton() {
|
51 |
+
if ( ! isset( self::$_instance ) ) {
|
52 |
+
$className = __CLASS__;
|
53 |
+
self::$_instance = new $className;
|
54 |
+
}
|
55 |
+
return self::$_instance;
|
56 |
+
}
|
57 |
+
|
58 |
+
static function enqueue_scripts() {
|
59 |
+
|
60 |
+
$in_footer = true;
|
61 |
+
|
62 |
+
$options = self::_get_options();
|
63 |
+
$theme_loader_function = $options->get( 'theme_loader_function' );
|
64 |
+
|
65 |
+
if ( $theme_loader_function == 'wp_head' ) {
|
66 |
+
$in_footer = false;
|
67 |
+
}
|
68 |
+
|
69 |
+
wp_enqueue_script( 'jquery.sonar', plugins_url( '/js/jquery.sonar.min.js', __FILE__ ), array( 'jquery' ), self::version, $in_footer );
|
70 |
+
wp_enqueue_script( 'BJLL', plugins_url( '/js/bj-lazy-load.min.js', __FILE__ ), array( 'jquery', 'jquery.sonar' ), self::version, $in_footer );
|
71 |
+
}
|
72 |
+
|
73 |
+
static function filter( $content ) {
|
74 |
+
|
75 |
+
$BJLL = BJLL::singleton();
|
76 |
+
|
77 |
+
$options = self::_get_options();
|
78 |
+
|
79 |
+
if ( $options->get('lazy_load_images') == 'yes' ) {
|
80 |
+
$content = $BJLL->_filter_images( $content );
|
81 |
+
}
|
82 |
+
|
83 |
+
if ( $options->get('lazy_load_iframes') == 'yes' ) {
|
84 |
+
$content = $BJLL->_filter_iframes( $content );
|
85 |
+
}
|
86 |
+
|
87 |
+
return $content;
|
88 |
+
}
|
89 |
+
|
90 |
+
protected function _filter_images( $content ) {
|
91 |
+
|
92 |
+
$matches = array();
|
93 |
+
preg_match_all( '/<img\s+.*?>/', $content, $matches );
|
94 |
+
|
95 |
+
$search = array();
|
96 |
+
$replace = array();
|
97 |
+
|
98 |
+
foreach ( $matches[0] as $imgHTML ) {
|
99 |
+
|
100 |
+
// replace the src and add the data-src attribute
|
101 |
+
$replaceHTML = preg_replace( '/<img(.*?)src=/i', '<img$1src="' . $this->_placeholder_url . '" data-lazy-type="image" data-lazy-src=', $imgHTML );
|
102 |
+
|
103 |
+
// add the lazy class to the img element
|
104 |
+
if ( preg_match( '/class="/i', $replaceHTML ) ) {
|
105 |
+
$replaceHTML = preg_replace( '/class="(.*?)"/i', 'class="lazy lazy-hidden $1"', $replaceHTML );
|
106 |
+
} else {
|
107 |
+
$replaceHTML = preg_replace( '/<img/i', '<img class="lazy lazy-hidden"', $replaceHTML );
|
108 |
+
}
|
109 |
+
|
110 |
+
$replaceHTML .= '<noscript>' . $imgHTML . '</noscript>';
|
111 |
+
|
112 |
+
array_push( $search, $imgHTML );
|
113 |
+
array_push( $replace, $replaceHTML );
|
114 |
+
}
|
115 |
+
|
116 |
+
$content = str_replace( $search, $replace, $content );
|
117 |
+
|
118 |
+
|
119 |
+
return $content;
|
120 |
+
}
|
121 |
+
|
122 |
+
protected function _filter_iframes( $content ) {
|
123 |
+
|
124 |
+
$matches = array();
|
125 |
+
preg_match_all( '/<iframe\s+.*?>/', $content, $matches );
|
126 |
+
|
127 |
+
$search = array();
|
128 |
+
$replace = array();
|
129 |
+
|
130 |
+
foreach ( $matches[0] as $iframeHTML ) {
|
131 |
+
$replaceHTML = '<img src="' . $this->_placeholder_url . '" class="lazy lazy-hidden" data-lazy-type="iframe" data-lazy-src="' . base64_encode($iframeHTML) . '" alt="">';
|
132 |
+
|
133 |
+
$replaceHTML .= '<noscript>' . $iframeHTML . '</noscript>';
|
134 |
+
|
135 |
+
array_push( $search, $iframeHTML );
|
136 |
+
array_push( $replace, $replaceHTML );
|
137 |
+
}
|
138 |
+
|
139 |
+
$content = str_replace( $search, $replace, $content );
|
140 |
+
|
141 |
+
return $content;
|
142 |
+
}
|
143 |
+
|
144 |
+
protected function _get_options() {
|
145 |
+
return new scbOptions( 'bj_lazy_load_options', __FILE__, array(
|
146 |
+
'lazy_load_images' => 'yes',
|
147 |
+
'lazy_load_iframes' => 'yes',
|
148 |
+
'theme_loader_function' => 'wp_footer'
|
149 |
+
) );
|
150 |
+
}
|
151 |
+
|
152 |
+
function options_init() {
|
153 |
+
|
154 |
+
$options = self::_get_options();
|
155 |
+
|
156 |
+
// Creating settings page objects
|
157 |
+
if ( is_admin() ) {
|
158 |
+
require_once( dirname( __FILE__ ) . '/admin.php' );
|
159 |
+
new BJLL_Admin_Page( __FILE__, $options );
|
160 |
+
}
|
161 |
+
}
|
162 |
+
|
163 |
+
}
|
164 |
+
}
|
165 |
+
|
166 |
+
|
167 |
+
add_action( 'wp', create_function('', 'if ( ! is_feed() ) { BJLL::singleton(); }'), 10, 0 );
|
168 |
+
|
169 |
+
scb_init( array( 'BJLL', 'options_init' ) );
|
170 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
css/bjll.css
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
.lazy-hidden {display: none !important;}
|
|
js/bj-lazy-load.js
ADDED
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
(function($) {
|
2 |
+
|
3 |
+
function bj_lazy_load_init() {
|
4 |
+
|
5 |
+
$('.lazy-hidden').not('[data-lazy-ready]').one( 'scrollin.bj_lazy_load', { distance: 200 }, function() {
|
6 |
+
|
7 |
+
var $el = $( this ),
|
8 |
+
data_lazy_type = $el.attr( 'data-lazy-type' );
|
9 |
+
|
10 |
+
if ( data_lazy_type == 'image' ) {
|
11 |
+
$el.attr( 'src', $el.attr( 'data-lazy-src' ) )
|
12 |
+
.removeClass( 'lazy-hidden' );
|
13 |
+
} else if ( data_lazy_type == 'iframe' ) {
|
14 |
+
$el.replaceWith( bj_lazy_load_base64_decode( $el.attr( 'data-lazy-src' ) ) );
|
15 |
+
}
|
16 |
+
}).attr( 'data-lazy-ready', 'true' );
|
17 |
+
|
18 |
+
}
|
19 |
+
|
20 |
+
function bj_lazy_load_base64_decode (data) {
|
21 |
+
// http://kevin.vanzonneveld.net
|
22 |
+
// + original by: Tyler Akins (http://rumkin.com)
|
23 |
+
// + improved by: Thunder.m
|
24 |
+
// + input by: Aman Gupta
|
25 |
+
// + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
|
26 |
+
// + bugfixed by: Onno Marsman
|
27 |
+
// + bugfixed by: Pellentesque Malesuada
|
28 |
+
// + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
|
29 |
+
// + input by: Brett Zamir (http://brett-zamir.me)
|
30 |
+
// + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
|
31 |
+
// * example 1: base64_decode('S2V2aW4gdmFuIFpvbm5ldmVsZA==');
|
32 |
+
// * returns 1: 'Kevin van Zonneveld'
|
33 |
+
// mozilla has this native
|
34 |
+
// - but breaks in 2.0.0.12!
|
35 |
+
//if (typeof this.window['atob'] == 'function') {
|
36 |
+
// return atob(data);
|
37 |
+
//}
|
38 |
+
var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
39 |
+
var o1, o2, o3, h1, h2, h3, h4, bits, i = 0,
|
40 |
+
ac = 0,
|
41 |
+
dec = "",
|
42 |
+
tmp_arr = [];
|
43 |
+
|
44 |
+
if (!data) {
|
45 |
+
return data;
|
46 |
+
}
|
47 |
+
|
48 |
+
data += '';
|
49 |
+
|
50 |
+
do { // unpack four hexets into three octets using index points in b64
|
51 |
+
h1 = b64.indexOf(data.charAt(i++));
|
52 |
+
h2 = b64.indexOf(data.charAt(i++));
|
53 |
+
h3 = b64.indexOf(data.charAt(i++));
|
54 |
+
h4 = b64.indexOf(data.charAt(i++));
|
55 |
+
|
56 |
+
bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
|
57 |
+
|
58 |
+
o1 = bits >> 16 & 0xff;
|
59 |
+
o2 = bits >> 8 & 0xff;
|
60 |
+
o3 = bits & 0xff;
|
61 |
+
|
62 |
+
if (h3 == 64) {
|
63 |
+
tmp_arr[ac++] = String.fromCharCode(o1);
|
64 |
+
} else if (h4 == 64) {
|
65 |
+
tmp_arr[ac++] = String.fromCharCode(o1, o2);
|
66 |
+
} else {
|
67 |
+
tmp_arr[ac++] = String.fromCharCode(o1, o2, o3);
|
68 |
+
}
|
69 |
+
} while (i < data.length);
|
70 |
+
|
71 |
+
dec = tmp_arr.join('');
|
72 |
+
|
73 |
+
return dec;
|
74 |
+
}
|
75 |
+
|
76 |
+
$( document ).on( 'ready', bj_lazy_load_init );
|
77 |
+
|
78 |
+
})(jQuery);
|
js/bj-lazy-load.min.js
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
(function(c){function b(){c(".lazy-hidden").not("[data-lazy-ready]").one("scrollin.bj_lazy_load",{distance:200},function(){var d=c(this),e=d.attr("data-lazy-type");if(e=="image"){d.attr("src",d.attr("data-lazy-src")).removeClass("lazy-hidden")}else{if(e=="iframe"){d.replaceWith(a(d.attr("data-lazy-src")))}}}).attr("data-lazy-ready","true")}function a(l){var g="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";var f,e,d,p,o,n,m,q,k=0,r=0,h="",j=[];if(!l){return l}l+="";do{p=g.indexOf(l.charAt(k++));o=g.indexOf(l.charAt(k++));n=g.indexOf(l.charAt(k++));m=g.indexOf(l.charAt(k++));q=p<<18|o<<12|n<<6|m;f=q>>16&255;e=q>>8&255;d=q&255;if(n==64){j[r++]=String.fromCharCode(f)}else{if(m==64){j[r++]=String.fromCharCode(f,e)}else{j[r++]=String.fromCharCode(f,e,d)}}}while(k<l.length);h=j.join("");return h}c(document).on("ready",b)})(jQuery);
|
js/bjll.js
DELETED
@@ -1,5 +0,0 @@
|
|
1 |
-
(function($) {
|
2 |
-
$(document).ready(function() {
|
3 |
-
$('img.lazy').removeClass('lazy-hidden').jail(BJLL.options);
|
4 |
-
});
|
5 |
-
})(jQuery);
|
|
|
|
|
|
|
|
|
|
js/bjll.min.js
DELETED
@@ -1,22 +0,0 @@
|
|
1 |
-
/*
|
2 |
-
* JAIL: jQuery Asynchronous Image Loader
|
3 |
-
*
|
4 |
-
* Copyright (c) 2011 Sebastiano Armeli-Battana (http://www.sebastianoarmelibattana.com)
|
5 |
-
*
|
6 |
-
* By Sebastiano Armeli-Battana (@sebarmeli) - http://www.sebastianoarmelibattana.com
|
7 |
-
* Licensed under the MIT license.
|
8 |
-
* https://github.com/sebarmeli/JAIL/blob/master/MIT-LICENSE.txt
|
9 |
-
*
|
10 |
-
* Tested with jQuery 1.3.2+ on FF 2+, Opera 10+, Safari 4+, Chrome 8+ on Win/Mac/Linux and IE 6/7/8 on Win.
|
11 |
-
*
|
12 |
-
* Contributor : Derek Lindahl - dlindahl
|
13 |
-
*
|
14 |
-
* @link http://github.com/sebarmeli/JAIL
|
15 |
-
* @author Sebastiano Armeli-Battana
|
16 |
-
* @date 30/12/2011
|
17 |
-
* @version 0.9.9
|
18 |
-
*
|
19 |
-
*/
|
20 |
-
(function(a,c){var b=c(jQuery),d=typeof define==="function"&&define.amd;if(d){define("jail",["jquery"],b);}else{(this.jQuery||this.$||this)[a]=b;}}("jail",function(f){var b=f(window),d={timeout:1,effect:false,speed:400,triggerElement:null,offset:0,event:"load",callback:null,callbackAfterEachImage:null,placeholder:false,loadHiddenImages:false},k=[],g=false;f.jail=function(o,n){var o=o||{},n=f.extend({},d,n);f.jail.prototype.init(o,n);if(/^(load|scroll)/.test(n.event)){f.jail.prototype.later.call(o,n);}else{f.jail.prototype.onEvent.call(o,n);}};f.jail.prototype.init=function(o,n){o.data("triggerEl",(n.triggerElement)?f(n.triggerElement):b);if(!!n.placeholder){o.each(function(){f(this).attr("src",n.placeholder);});}};f.jail.prototype.onEvent=function(o){var n=this;if(!!o.triggerElement){i(o,n);}else{n.bind(o.event,{options:o,images:n},function(s){var r=f(this),q=s.data.options,p=s.data.images;k=f.extend({},p);a(q,r);f(s.currentTarget).unbind(s.type);});}};f.jail.prototype.later=function(o){var n=this;setTimeout(function(){k=f.extend({},n);n.each(function(){c(o,this,n);});o.event="scroll";i(o,n);},o.timeout);};function i(o,n){if(!!n){var p=n.data("triggerEl");}if(!!p&&typeof p.bind==="function"){p.bind(o.event,{options:o,images:n},m);b.resize({options:o,images:n},m);}}function j(n){var o=0;if(n.length>0){while(true){if(o===n.length){break;}else{if(n[o].getAttribute("data-src")){o++;}else{n.splice(o,1);}}}}}function m(p){var n=p.data.images,o=p.data.options;n.data("poller",setTimeout(function(){k=f.extend({},n);j(k);f(k).each(function(){if(this===window){return;}c(o,this,k);});if(l(k)){f(p.currentTarget).unbind(p.type);return;}else{if(o.event!=="scroll"){var q=(/scroll/i.test(o.event))?n.data("triggerEl"):b;o.event="scroll";n.data("triggerEl",q);i(o,f(k));}}},o.timeout));}function l(n){var o=true;f(n).each(function(){if(!!f(this).attr("data-src")){o=false;}});return o;}function c(q,s,o){var r=f(s),p=(/scroll/i.test(q.event))?o.data("triggerEl"):b,n=true;if(!q.loadHiddenImages){n=h(r,p,q)&&r.is(":visible");}if(n&&e(p,r,q.offset)){a(q,r);}}function e(u,n,s){var q=u[0]===window,y=(q?{top:0,left:0}:u.offset()),r=y.top+(q?u.scrollTop():0),t=y.left+(q?u.scrollLeft():0),p=t+u.width(),v=r+u.height(),x=n.offset(),w=n.width(),o=n.height();return(r-s)<=(x.top+o)&&(v+s)>=x.top&&(t-s)<=(x.left+w)&&(p+s)>=x.left;}function a(n,o){o.hide();o.attr("src",o.attr("data-src"));o.removeAttr("data-src");if(n.effect){if(n.speed){o[n.effect](n.speed);}else{o[n.effect]();}o.css("opacity",1);o.show();}else{o.show();}j(k);if(!!n.callbackAfterEachImage){n.callbackAfterEachImage.call(this,o,n);}if(l(k)&&!!n.callback&&!g){n.callback.call(f.jail,n);g=true;}}function h(q,o,p){var r=q.parent(),n=true;while(r.get(0).nodeName.toUpperCase()!=="BODY"){if(r.css("overflow")==="hidden"){if(!e(r,q,p.offset)){n=false;break;}}else{if(r.css("overflow")==="scroll"){if(!e(r,q,p.offset)){n=false;f(k).data("triggerEl",r);p.event="scroll";i(p,f(k));break;}}}if(r.css("visibility")==="hidden"||q.css("visibility")==="hidden"){n=false;break;}if(o!==b&&r===o){break;}r=r.parent();}return n;}f.fn.jail=function(n){new f.jail(this,n);k=[];return this;};return f.jail;}));
|
21 |
-
/* bjll.js by Bjørn Johansen (@bjornjohansen) */
|
22 |
-
(function($){$(document).ready(function(){$('img.lazy').removeClass('lazy-hidden').jail(BJLL.options);});})(jQuery);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
js/jail.min.js
DELETED
@@ -1,20 +0,0 @@
|
|
1 |
-
/*
|
2 |
-
* JAIL: jQuery Asynchronous Image Loader
|
3 |
-
*
|
4 |
-
* Copyright (c) 2011 Sebastiano Armeli-Battana (http://www.sebastianoarmelibattana.com)
|
5 |
-
*
|
6 |
-
* By Sebastiano Armeli-Battana (@sebarmeli) - http://www.sebastianoarmelibattana.com
|
7 |
-
* Licensed under the MIT license.
|
8 |
-
* https://github.com/sebarmeli/JAIL/blob/master/MIT-LICENSE.txt
|
9 |
-
*
|
10 |
-
* Tested with jQuery 1.3.2+ on FF 2+, Opera 10+, Safari 4+, Chrome 8+ on Win/Mac/Linux and IE 6/7/8 on Win.
|
11 |
-
*
|
12 |
-
* Contributor : Derek Lindahl - dlindahl
|
13 |
-
*
|
14 |
-
* @link http://github.com/sebarmeli/JAIL
|
15 |
-
* @author Sebastiano Armeli-Battana
|
16 |
-
* @date 30/12/2011
|
17 |
-
* @version 0.9.9
|
18 |
-
*
|
19 |
-
*/
|
20 |
-
(function(a,c){var b=c(jQuery),d=typeof define==="function"&&define.amd;if(d){define("jail",["jquery"],b);}else{(this.jQuery||this.$||this)[a]=b;}}("jail",function(f){var b=f(window),d={timeout:1,effect:false,speed:400,triggerElement:null,offset:0,event:"load",callback:null,callbackAfterEachImage:null,placeholder:false,loadHiddenImages:false},k=[],g=false;f.jail=function(o,n){var o=o||{},n=f.extend({},d,n);f.jail.prototype.init(o,n);if(/^(load|scroll)/.test(n.event)){f.jail.prototype.later.call(o,n);}else{f.jail.prototype.onEvent.call(o,n);}};f.jail.prototype.init=function(o,n){o.data("triggerEl",(n.triggerElement)?f(n.triggerElement):b);if(!!n.placeholder){o.each(function(){f(this).attr("src",n.placeholder);});}};f.jail.prototype.onEvent=function(o){var n=this;if(!!o.triggerElement){i(o,n);}else{n.bind(o.event,{options:o,images:n},function(s){var r=f(this),q=s.data.options,p=s.data.images;k=f.extend({},p);a(q,r);f(s.currentTarget).unbind(s.type);});}};f.jail.prototype.later=function(o){var n=this;setTimeout(function(){k=f.extend({},n);n.each(function(){c(o,this,n);});o.event="scroll";i(o,n);},o.timeout);};function i(o,n){if(!!n){var p=n.data("triggerEl");}if(!!p&&typeof p.bind==="function"){p.bind(o.event,{options:o,images:n},m);b.resize({options:o,images:n},m);}}function j(n){var o=0;if(n.length>0){while(true){if(o===n.length){break;}else{if(n[o].getAttribute("data-src")){o++;}else{n.splice(o,1);}}}}}function m(p){var n=p.data.images,o=p.data.options;n.data("poller",setTimeout(function(){k=f.extend({},n);j(k);f(k).each(function(){if(this===window){return;}c(o,this,k);});if(l(k)){f(p.currentTarget).unbind(p.type);return;}else{if(o.event!=="scroll"){var q=(/scroll/i.test(o.event))?n.data("triggerEl"):b;o.event="scroll";n.data("triggerEl",q);i(o,f(k));}}},o.timeout));}function l(n){var o=true;f(n).each(function(){if(!!f(this).attr("data-src")){o=false;}});return o;}function c(q,s,o){var r=f(s),p=(/scroll/i.test(q.event))?o.data("triggerEl"):b,n=true;if(!q.loadHiddenImages){n=h(r,p,q)&&r.is(":visible");}if(n&&e(p,r,q.offset)){a(q,r);}}function e(u,n,s){var q=u[0]===window,y=(q?{top:0,left:0}:u.offset()),r=y.top+(q?u.scrollTop():0),t=y.left+(q?u.scrollLeft():0),p=t+u.width(),v=r+u.height(),x=n.offset(),w=n.width(),o=n.height();return(r-s)<=(x.top+o)&&(v+s)>=x.top&&(t-s)<=(x.left+w)&&(p+s)>=x.left;}function a(n,o){o.hide();o.attr("src",o.attr("data-src"));o.removeAttr("data-src");if(n.effect){if(n.speed){o[n.effect](n.speed);}else{o[n.effect]();}o.css("opacity",1);o.show();}else{o.show();}j(k);if(!!n.callbackAfterEachImage){n.callbackAfterEachImage.call(this,o,n);}if(l(k)&&!!n.callback&&!g){n.callback.call(f.jail,n);g=true;}}function h(q,o,p){var r=q.parent(),n=true;while(r.get(0).nodeName.toUpperCase()!=="BODY"){if(r.css("overflow")==="hidden"){if(!e(r,q,p.offset)){n=false;break;}}else{if(r.css("overflow")==="scroll"){if(!e(r,q,p.offset)){n=false;f(k).data("triggerEl",r);p.event="scroll";i(p,f(k));break;}}}if(r.css("visibility")==="hidden"||q.css("visibility")==="hidden"){n=false;break;}if(o!==b&&r===o){break;}r=r.parent();}return n;}f.fn.jail=function(n){new f.jail(this,n);k=[];return this;};return f.jail;}));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
js/jquery.sonar.min.js
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
(function(e,h,l,c){e.fn.sonar=function(o,n){if(typeof o==="boolean"){n=o;o=c}return e.sonar(this[0],o,n)};var f=l.body,a="scrollin",m="scrollout",b=function(r,n,t){if(r){f||(f=l.body);var s=r,u=0,v=f.offsetHeight,o=h.innerHeight||l.documentElement.clientHeight||f.clientHeight||0,q=l.documentElement.scrollTop||h.pageYOffset||f.scrollTop||0,p=r.offsetHeight||0;if(!r.sonarElemTop||r.sonarBodyHeight!==v){if(s.offsetParent){do{u+=s.offsetTop}while(s=s.offsetParent)}r.sonarElemTop=u;r.sonarBodyHeight=v}n=n===c?0:n;return(!(r.sonarElemTop+(t?0:p)<q-n)&&!(r.sonarElemTop+(t?p:0)>q+o+n))}},d={},j=0,i=function(){setTimeout(function(){var s,o,t,q,p,r,n;for(t in d){o=d[t];for(r=0,n=o.length;r<n;r++){q=o[r];s=q.elem;p=b(s,q.px,q.full);if(t===m?!p:p){if(!q.tr){if(s[t]){e(s).trigger(t);q.tr=1}else{o.splice(r,1);r--;n--}}}else{q.tr=0}}}},25)},k=function(n,o){n[o]=0},g=function(r,p){var t=p.px,q=p.full,s=p.evt,o=b(r,t,q),n=0;r[s]=1;if(s===m?!o:o){setTimeout(function(){e(r).trigger(s===m?m:a)},0);n=1}d[s].push({elem:r,px:t,full:q,tr:n});if(!j){e(h).bind("scroll",i);j=1}};e.sonar=b;d[a]=[];e.event.special[a]={add:function(n){var p=n.data||{},o=this;if(!o[a]){g(this,{px:p.distance,full:p.full,evt:a})}},remove:function(n){k(this,a)}};d[m]=[];e.event.special[m]={add:function(n){var p=n.data||{},o=this;if(!o[m]){g(o,{px:p.distance,full:p.full,evt:m})}},remove:function(n){k(this,m)}}})(jQuery,window,document);
|
lang/bj-lazy-load-nb_NO.mo
DELETED
Binary file
|
lang/bj-lazy-load-nb_NO.po
DELETED
@@ -1,137 +0,0 @@
|
|
1 |
-
# Copyright (C) 2010 BJ Lazy Load
|
2 |
-
# This file is distributed under the same license as the BJ Lazy Load package.
|
3 |
-
msgid ""
|
4 |
-
msgstr ""
|
5 |
-
"Project-Id-Version: BJ Lazy Load 0.2.4\n"
|
6 |
-
"Report-Msgid-Bugs-To: http://wordpress.org/tag/bj-lazy-load\n"
|
7 |
-
"POT-Creation-Date: 2012-04-04 23:30:34+00:00\n"
|
8 |
-
"PO-Revision-Date: 2012-04-05 01:34+0100\n"
|
9 |
-
"Last-Translator: Bjørn Johansen <post@bjornjohansen.no>\n"
|
10 |
-
"Language-Team: <post@bjornjohansen.no>\n"
|
11 |
-
"MIME-Version: 1.0\n"
|
12 |
-
"Content-Type: text/plain; charset=UTF-8\n"
|
13 |
-
"Content-Transfer-Encoding: 8bit\n"
|
14 |
-
"X-Poedit-Language: Norwegian Bokmal\n"
|
15 |
-
"X-Poedit-Country: NORWAY\n"
|
16 |
-
|
17 |
-
#: bj-lazy-load.php:273
|
18 |
-
#: bj-lazy-load.php:465
|
19 |
-
msgid "Settings"
|
20 |
-
msgstr "Innstillinger"
|
21 |
-
|
22 |
-
#: bj-lazy-load.php:285
|
23 |
-
msgid "General"
|
24 |
-
msgstr "Generelt"
|
25 |
-
|
26 |
-
#: bj-lazy-load.php:287
|
27 |
-
msgid "Lazy load post thumbnails"
|
28 |
-
msgstr "Lat lasting av fremhevede bilder"
|
29 |
-
|
30 |
-
#: bj-lazy-load.php:288
|
31 |
-
msgid "Include JS"
|
32 |
-
msgstr "Inkludér JS"
|
33 |
-
|
34 |
-
#: bj-lazy-load.php:289
|
35 |
-
msgid "Include CSS"
|
36 |
-
msgstr "Inkludér CSS"
|
37 |
-
|
38 |
-
#: bj-lazy-load.php:290
|
39 |
-
msgid "Theme caller function"
|
40 |
-
msgstr "Kallfunksjon i tema"
|
41 |
-
|
42 |
-
#: bj-lazy-load.php:302
|
43 |
-
msgid "JAIL Settings"
|
44 |
-
msgstr "JAIL-innstillinger"
|
45 |
-
|
46 |
-
#: bj-lazy-load.php:304
|
47 |
-
msgid "Timeout"
|
48 |
-
msgstr "Tidsterskel"
|
49 |
-
|
50 |
-
#: bj-lazy-load.php:305
|
51 |
-
msgid "jQuery Effect"
|
52 |
-
msgstr "jQuery-effekt"
|
53 |
-
|
54 |
-
#: bj-lazy-load.php:306
|
55 |
-
msgid "Effect Speed"
|
56 |
-
msgstr "Effekthastighet"
|
57 |
-
|
58 |
-
#: bj-lazy-load.php:307
|
59 |
-
msgid "Trigger Event"
|
60 |
-
msgstr "Handlingsutløser"
|
61 |
-
|
62 |
-
#: bj-lazy-load.php:308
|
63 |
-
msgid "Offset/Threshold"
|
64 |
-
msgstr "Avstand/terskel"
|
65 |
-
|
66 |
-
#: bj-lazy-load.php:309
|
67 |
-
msgid "Ignore Hidden Images"
|
68 |
-
msgstr "Ignorer skjulte bilder"
|
69 |
-
|
70 |
-
#: bj-lazy-load.php:375
|
71 |
-
msgid "Needed for the plugin to work, but <a href=\"http://developer.yahoo.com/performance/rules.html#num_http\" target=\"_blank\">for best performance you should include it in your combined JS</a>"
|
72 |
-
msgstr "Nødvendig for at innstikket skal fungere, men <a href=\"http://developer.yahoo.com/performance/rules.html#num_http\" target=\"_blank\">for best ytelse bør du inkludere det i din kombinerte JS-fil</a>"
|
73 |
-
|
74 |
-
#: bj-lazy-load.php:385
|
75 |
-
msgid "Needed for the plugin to work, but <a href=\"http://developer.yahoo.com/performance/rules.html#num_http\" target=\"_blank\">for best performance you should include it in your combined CSS</a>"
|
76 |
-
msgstr "Nødvendig for at innstikket skal fungere, men <a href=\"http://developer.yahoo.com/performance/rules.html#num_http\" target=\"_blank\">for best ytelse bør du inkludere det i din kombinerte CSS-fil</a>"
|
77 |
-
|
78 |
-
#: bj-lazy-load.php:395
|
79 |
-
msgid "Whether to ignore hidden images to be loaded - Default: false/unchecked (so hidden images are loaded)"
|
80 |
-
msgstr "Om skjulte bilder skal ignoreres - Standard: usann/ikke valgt (slik at skjulte bilder også lastes)"
|
81 |
-
|
82 |
-
#: bj-lazy-load.php:413
|
83 |
-
msgid "Put the script in either wp_footer() (should be right before </body>) or wp_head() (in the <head>-element)."
|
84 |
-
msgstr "Legg skriptet enten i wp_footer() (bør være rett før </body>) eller wp_head() (i <head>-elementet)."
|
85 |
-
|
86 |
-
#: bj-lazy-load.php:430
|
87 |
-
msgid "Event that triggers the image to load. Default: load+scroll"
|
88 |
-
msgstr "Handling som utløser lasting av bilde. Standard: load+scroll"
|
89 |
-
|
90 |
-
#: bj-lazy-load.php:435
|
91 |
-
msgid "Number of msec after that the images will be loaded - Default: 10"
|
92 |
-
msgstr "Antall msec etter handling som bildene lastes - Standard: 10"
|
93 |
-
|
94 |
-
#: bj-lazy-load.php:443
|
95 |
-
msgid "Any jQuery effect that makes the images display (e.g. \"fadeIn\") - Default: NULL"
|
96 |
-
msgstr "Hvilken som helst jQuery-effekt som skal vise bildene (f.eks. \"fadeIn\") - Standard: NULL"
|
97 |
-
|
98 |
-
#: bj-lazy-load.php:445
|
99 |
-
msgid "NOTE: If you are loading a large number of images, it is best to NOT use this setting. Effects calls are very expensive. Even a simple show() can have a major impact on the browser’s responsiveness."
|
100 |
-
msgstr "MERK: Hvis du laster mange bilder, er det best å IKKE bruke denne innstillingen. Effektkall er veldig ressurskrevende. Til og med en enkel show() kan ha større innvirknign på nettleserens reaksjonsevne."
|
101 |
-
|
102 |
-
#: bj-lazy-load.php:451
|
103 |
-
msgid "string or number determining how long the animation will run - Default: 400"
|
104 |
-
msgstr "streng eller tall som angir hvor lenge animasjonen skal kjøres - Standard: 400"
|
105 |
-
|
106 |
-
#: bj-lazy-load.php:456
|
107 |
-
msgid "An offset of \"500\" would cause any images that are less than 500px below the bottom of the window or 500px above the top of the window to load. - Default: 200"
|
108 |
-
msgstr "En terskel på \"500\" vil laste bilder som er mindre enn 500px under nedre kant av vinduet eller 500px over øvre kant av vinduet. - Standard: 200"
|
109 |
-
|
110 |
-
#: bj-lazy-load.php:461
|
111 |
-
msgid "You do not have sufficient permissions to access this page."
|
112 |
-
msgstr "Du har ikke tilstrekkelig tilgangsnivå til denne siden."
|
113 |
-
|
114 |
-
#: bj-lazy-load.php:471
|
115 |
-
msgid "Save Changes"
|
116 |
-
msgstr "Lagre Endringer"
|
117 |
-
|
118 |
-
#. Plugin Name of the plugin/theme
|
119 |
-
msgid "BJ Lazy Load"
|
120 |
-
msgstr "BJ Lazy Load"
|
121 |
-
|
122 |
-
#. Plugin URI of the plugin/theme
|
123 |
-
msgid "http://wordpress.org/extend/plugins/bj-lazy-load/"
|
124 |
-
msgstr "http://wordpress.org/extend/plugins/bj-lazy-load/"
|
125 |
-
|
126 |
-
#. Description of the plugin/theme
|
127 |
-
msgid "Lazy image loading makes your site load faster and saves bandwidth."
|
128 |
-
msgstr "Lat bildelasting gjør nettsteder raskere og sparer båndbredde."
|
129 |
-
|
130 |
-
#. Author of the plugin/theme
|
131 |
-
msgid "Bjørn Johansen"
|
132 |
-
msgstr "Bjørn Johansen"
|
133 |
-
|
134 |
-
#. Author URI of the plugin/theme
|
135 |
-
msgid "http://twitter.com/bjornjohansen"
|
136 |
-
msgstr "http://twitter.com/bjornjohansen"
|
137 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lang/bj-lazy-load.pot
DELETED
@@ -1,152 +0,0 @@
|
|
1 |
-
# Copyright (C) 2012 BJ Lazy Load
|
2 |
-
# This file is distributed under the same license as the BJ Lazy Load package.
|
3 |
-
msgid ""
|
4 |
-
msgstr ""
|
5 |
-
"Project-Id-Version: BJ Lazy Load 0.3.3\n"
|
6 |
-
"Report-Msgid-Bugs-To: http://wordpress.org/tag/bj-lazy-load\n"
|
7 |
-
"POT-Creation-Date: 2012-04-04 23:30:34+00:00\n"
|
8 |
-
"MIME-Version: 1.0\n"
|
9 |
-
"Content-Type: text/plain; charset=UTF-8\n"
|
10 |
-
"Content-Transfer-Encoding: 8bit\n"
|
11 |
-
"PO-Revision-Date: 2012-MO-DA HO:MI+ZONE\n"
|
12 |
-
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
13 |
-
"Language-Team: LANGUAGE <LL@li.org>\n"
|
14 |
-
|
15 |
-
#: bj-lazy-load.php:273 bj-lazy-load.php:465
|
16 |
-
msgid "Settings"
|
17 |
-
msgstr ""
|
18 |
-
|
19 |
-
#: bj-lazy-load.php:285
|
20 |
-
msgid "General"
|
21 |
-
msgstr ""
|
22 |
-
|
23 |
-
#: bj-lazy-load.php:287
|
24 |
-
msgid "Lazy load post thumbnails"
|
25 |
-
msgstr ""
|
26 |
-
|
27 |
-
#: bj-lazy-load.php:288
|
28 |
-
msgid "Include JS"
|
29 |
-
msgstr ""
|
30 |
-
|
31 |
-
#: bj-lazy-load.php:289
|
32 |
-
msgid "Include CSS"
|
33 |
-
msgstr ""
|
34 |
-
|
35 |
-
#: bj-lazy-load.php:290
|
36 |
-
msgid "Theme caller function"
|
37 |
-
msgstr ""
|
38 |
-
|
39 |
-
#: bj-lazy-load.php:302
|
40 |
-
msgid "JAIL Settings"
|
41 |
-
msgstr ""
|
42 |
-
|
43 |
-
#: bj-lazy-load.php:304
|
44 |
-
msgid "Timeout"
|
45 |
-
msgstr ""
|
46 |
-
|
47 |
-
#: bj-lazy-load.php:305
|
48 |
-
msgid "jQuery Effect"
|
49 |
-
msgstr ""
|
50 |
-
|
51 |
-
#: bj-lazy-load.php:306
|
52 |
-
msgid "Effect Speed"
|
53 |
-
msgstr ""
|
54 |
-
|
55 |
-
#: bj-lazy-load.php:307
|
56 |
-
msgid "Trigger Event"
|
57 |
-
msgstr ""
|
58 |
-
|
59 |
-
#: bj-lazy-load.php:308
|
60 |
-
msgid "Offset/Threshold"
|
61 |
-
msgstr ""
|
62 |
-
|
63 |
-
#: bj-lazy-load.php:309
|
64 |
-
msgid "Ignore Hidden Images"
|
65 |
-
msgstr ""
|
66 |
-
|
67 |
-
#: bj-lazy-load.php:375
|
68 |
-
msgid ""
|
69 |
-
"Needed for the plugin to work, but <a href=\"http://developer.yahoo.com/"
|
70 |
-
"performance/rules.html#num_http\" target=\"_blank\">for best performance you "
|
71 |
-
"should include it in your combined JS</a>"
|
72 |
-
msgstr ""
|
73 |
-
|
74 |
-
#: bj-lazy-load.php:385
|
75 |
-
msgid ""
|
76 |
-
"Needed for the plugin to work, but <a href=\"http://developer.yahoo.com/"
|
77 |
-
"performance/rules.html#num_http\" target=\"_blank\">for best performance you "
|
78 |
-
"should include it in your combined CSS</a>"
|
79 |
-
msgstr ""
|
80 |
-
|
81 |
-
#: bj-lazy-load.php:395
|
82 |
-
msgid ""
|
83 |
-
"Whether to ignore hidden images to be loaded - Default: false/unchecked (so "
|
84 |
-
"hidden images are loaded)"
|
85 |
-
msgstr ""
|
86 |
-
|
87 |
-
#: bj-lazy-load.php:413
|
88 |
-
msgid ""
|
89 |
-
"Put the script in either wp_footer() (should be right before </body>) "
|
90 |
-
"or wp_head() (in the <head>-element)."
|
91 |
-
msgstr ""
|
92 |
-
|
93 |
-
#: bj-lazy-load.php:430
|
94 |
-
msgid "Event that triggers the image to load. Default: load+scroll"
|
95 |
-
msgstr ""
|
96 |
-
|
97 |
-
#: bj-lazy-load.php:435
|
98 |
-
msgid "Number of msec after that the images will be loaded - Default: 10"
|
99 |
-
msgstr ""
|
100 |
-
|
101 |
-
#: bj-lazy-load.php:443
|
102 |
-
msgid ""
|
103 |
-
"Any jQuery effect that makes the images display (e.g. \"fadeIn\") - Default: "
|
104 |
-
"NULL"
|
105 |
-
msgstr ""
|
106 |
-
|
107 |
-
#: bj-lazy-load.php:445
|
108 |
-
msgid ""
|
109 |
-
"NOTE: If you are loading a large number of images, it is best to NOT use "
|
110 |
-
"this setting. Effects calls are very expensive. Even a simple show() can "
|
111 |
-
"have a major impact on the browser’s responsiveness."
|
112 |
-
msgstr ""
|
113 |
-
|
114 |
-
#: bj-lazy-load.php:451
|
115 |
-
msgid ""
|
116 |
-
"string or number determining how long the animation will run - Default: 400"
|
117 |
-
msgstr ""
|
118 |
-
|
119 |
-
#: bj-lazy-load.php:456
|
120 |
-
msgid ""
|
121 |
-
"An offset of \"500\" would cause any images that are less than 500px below "
|
122 |
-
"the bottom of the window or 500px above the top of the window to load. - "
|
123 |
-
"Default: 200"
|
124 |
-
msgstr ""
|
125 |
-
|
126 |
-
#: bj-lazy-load.php:461
|
127 |
-
msgid "You do not have sufficient permissions to access this page."
|
128 |
-
msgstr ""
|
129 |
-
|
130 |
-
#: bj-lazy-load.php:471
|
131 |
-
msgid "Save Changes"
|
132 |
-
msgstr ""
|
133 |
-
|
134 |
-
#. Plugin Name of the plugin/theme
|
135 |
-
msgid "BJ Lazy Load"
|
136 |
-
msgstr ""
|
137 |
-
|
138 |
-
#. Plugin URI of the plugin/theme
|
139 |
-
msgid "http://wordpress.org/extend/plugins/bj-lazy-load/"
|
140 |
-
msgstr ""
|
141 |
-
|
142 |
-
#. Description of the plugin/theme
|
143 |
-
msgid "Lazy image loading makes your site load faster and saves bandwidth."
|
144 |
-
msgstr ""
|
145 |
-
|
146 |
-
#. Author of the plugin/theme
|
147 |
-
msgid "Bjørn Johansen"
|
148 |
-
msgstr ""
|
149 |
-
|
150 |
-
#. Author URI of the plugin/theme
|
151 |
-
msgid "http://twitter.com/bjornjohansen"
|
152 |
-
msgstr ""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
readme.txt
CHANGED
@@ -1,24 +1,22 @@
|
|
1 |
=== BJ Lazy Load ===
|
2 |
Contributors: bjornjohansen
|
3 |
Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=NLUWR4SHCJRBJ
|
4 |
-
Tags: images, lazy loading, jquery, javascript, optimize, performance, bandwidth
|
5 |
Author URI: http://twitter.com/bjornjohansen
|
6 |
-
Requires at least: 3.
|
7 |
-
Tested up to: 3.
|
8 |
-
Stable tag: 0.
|
9 |
|
10 |
-
Lazy
|
11 |
|
12 |
== Description ==
|
13 |
-
Lazy
|
14 |
|
15 |
-
This plugin replaces all your post images
|
16 |
|
17 |
-
You can also lazy load other images in your theme, by using a simple function.
|
18 |
|
19 |
-
Non-javascript visitors gets the original
|
20 |
-
|
21 |
-
Includes [JqueryAsynchImageLoader Plugin for jQuery by Sebastiano Armeli-Battana](http://www.sebastianoarmelibattana.com/projects/jail) for the lazy loading magic.
|
22 |
|
23 |
= Coming soon =
|
24 |
* Serving size optimized images for responsive design/adaptive layout
|
@@ -26,7 +24,7 @@ Includes [JqueryAsynchImageLoader Plugin for jQuery by Sebastiano Armeli-Battana
|
|
26 |
|
27 |
== Installation ==
|
28 |
1. Download and unzip plugin
|
29 |
-
2. Upload the 'bj-
|
30 |
3. Activate the plugin through the 'Plugins' menu in WordPress.
|
31 |
|
32 |
== Optional usage ==
|
@@ -42,7 +40,7 @@ echo $img;
|
|
42 |
== Frequently Asked Questions ==
|
43 |
|
44 |
= Whoa, this plugin is using JavaScript. What about visitors without JS? =
|
45 |
-
No worries. They get the original
|
46 |
|
47 |
= Which browsers are supported? =
|
48 |
The included JavaScript is tested in Firefox 2+, Safari 3+, Opera 9+, Chrome 5+, Internet Explorer 6+
|
@@ -58,6 +56,12 @@ Check your HTML source or see the magic at work in Web Inspector, FireBug or sim
|
|
58 |
|
59 |
== Changelog ==
|
60 |
|
|
|
|
|
|
|
|
|
|
|
|
|
61 |
= Version 0.4.0 =
|
62 |
* Upgraded JAIL to version 0.9.9, fixing some bugs. Note: data-href is now renamed data-src.
|
63 |
|
@@ -108,6 +112,9 @@ Check your HTML source or see the magic at work in Web Inspector, FireBug or sim
|
|
108 |
|
109 |
== Upgrade Notice ==
|
110 |
|
|
|
|
|
|
|
111 |
= 0.4.0 =
|
112 |
New JAIL version.
|
113 |
|
1 |
=== BJ Lazy Load ===
|
2 |
Contributors: bjornjohansen
|
3 |
Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=NLUWR4SHCJRBJ
|
4 |
+
Tags: images, iframes, lazy loading, jquery, javascript, optimize, performance, bandwidth
|
5 |
Author URI: http://twitter.com/bjornjohansen
|
6 |
+
Requires at least: 3.3
|
7 |
+
Tested up to: 3.4.1
|
8 |
+
Stable tag: 0.5.0
|
9 |
|
10 |
+
Lazy loading makes your site load faster and saves bandwidth. Uses jQuery and degrades gracefully for non-js users. Works with both images and iframes.
|
11 |
|
12 |
== Description ==
|
13 |
+
Lazy loading makes your site load faster and saves bandwidth.
|
14 |
|
15 |
+
This plugin replaces all your post images, post thumbnails, gravatar images and content iframes with a placeholder and loads the content as it gets close to enter the browser window when the visitor scrolls the page.
|
16 |
|
17 |
+
You can also lazy load other images and iframes in your theme, by using a simple function.
|
18 |
|
19 |
+
Non-javascript visitors gets the original element in noscript.
|
|
|
|
|
20 |
|
21 |
= Coming soon =
|
22 |
* Serving size optimized images for responsive design/adaptive layout
|
24 |
|
25 |
== Installation ==
|
26 |
1. Download and unzip plugin
|
27 |
+
2. Upload the 'bj-lazy-load' folder to the '/wp-content/plugins/' directory,
|
28 |
3. Activate the plugin through the 'Plugins' menu in WordPress.
|
29 |
|
30 |
== Optional usage ==
|
40 |
== Frequently Asked Questions ==
|
41 |
|
42 |
= Whoa, this plugin is using JavaScript. What about visitors without JS? =
|
43 |
+
No worries. They get the original element in a noscript element. No Lazy Loading for them, though.
|
44 |
|
45 |
= Which browsers are supported? =
|
46 |
The included JavaScript is tested in Firefox 2+, Safari 3+, Opera 9+, Chrome 5+, Internet Explorer 6+
|
56 |
|
57 |
== Changelog ==
|
58 |
|
59 |
+
= Version 0.5.0 =
|
60 |
+
* Complete rewrite
|
61 |
+
* Replaced JAIL with jQuery.sonar to accomodate for iframe lazy loading
|
62 |
+
* Added lazy loading for iframes
|
63 |
+
* The manual filter code now works as it should, lazy loading all images instead of just the first.
|
64 |
+
|
65 |
= Version 0.4.0 =
|
66 |
* Upgraded JAIL to version 0.9.9, fixing some bugs. Note: data-href is now renamed data-src.
|
67 |
|
112 |
|
113 |
== Upgrade Notice ==
|
114 |
|
115 |
+
= 0.5.0 =
|
116 |
+
Lazy load images and iframes. Complete rewrite.
|
117 |
+
|
118 |
= 0.4.0 =
|
119 |
New JAIL version.
|
120 |
|
scb/AdminPage.php
ADDED
@@ -0,0 +1,453 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Administration page base class
|
4 |
+
|
5 |
+
abstract class scbAdminPage {
|
6 |
+
/** Page args
|
7 |
+
* $page_title string (mandatory)
|
8 |
+
* $parent (string) (default: options-general.php)
|
9 |
+
* $capability (string) (default: 'manage_options')
|
10 |
+
* $menu_title (string) (default: $page_title)
|
11 |
+
* $page_slug (string) (default: sanitized $page_title)
|
12 |
+
* $toplevel (string) If not empty, will create a new top level menu (for expected values see http://codex.wordpress.org/Administration_Menus#Using_add_submenu_page)
|
13 |
+
* - $icon_url (string) URL to an icon for the top level menu
|
14 |
+
* - $position (int) Position of the toplevel menu (caution!)
|
15 |
+
* $screen_icon (string) The icon type to use in the screen header
|
16 |
+
* $nonce string (default: $page_slug)
|
17 |
+
* $action_link (string|bool) Text of the action link on the Plugins page (default: 'Settings')
|
18 |
+
* $admin_action_priority int The priority that the admin_menu action should be executed at (default: 10)
|
19 |
+
*/
|
20 |
+
protected $args;
|
21 |
+
|
22 |
+
// URL to the current plugin directory.
|
23 |
+
// Useful for adding css and js files
|
24 |
+
protected $plugin_url;
|
25 |
+
|
26 |
+
// Created at page init
|
27 |
+
protected $pagehook;
|
28 |
+
|
29 |
+
// scbOptions object holder
|
30 |
+
// Normally, it's used for storing formdata
|
31 |
+
protected $options;
|
32 |
+
protected $option_name;
|
33 |
+
|
34 |
+
// l10n
|
35 |
+
protected $textdomain;
|
36 |
+
|
37 |
+
|
38 |
+
// ____________REGISTRATION COMPONENT____________
|
39 |
+
|
40 |
+
|
41 |
+
private static $registered = array();
|
42 |
+
|
43 |
+
static function register( $class, $file, $options = null ) {
|
44 |
+
if ( isset( self::$registered[$class] ) )
|
45 |
+
return false;
|
46 |
+
|
47 |
+
self::$registered[$class] = array( $file, $options );
|
48 |
+
|
49 |
+
add_action( '_admin_menu', array( __CLASS__, '_pages_init' ) );
|
50 |
+
|
51 |
+
return true;
|
52 |
+
}
|
53 |
+
|
54 |
+
static function replace( $old_class, $new_class ) {
|
55 |
+
if ( ! isset( self::$registered[$old_class] ) )
|
56 |
+
return false;
|
57 |
+
|
58 |
+
self::$registered[$new_class] = self::$registered[$old_class];
|
59 |
+
unset( self::$registered[$old_class] );
|
60 |
+
|
61 |
+
return true;
|
62 |
+
}
|
63 |
+
|
64 |
+
static function remove( $class ) {
|
65 |
+
if ( ! isset( self::$registered[$class] ) )
|
66 |
+
return false;
|
67 |
+
|
68 |
+
unset( self::$registered[$class] );
|
69 |
+
|
70 |
+
return true;
|
71 |
+
}
|
72 |
+
|
73 |
+
static function _pages_init() {
|
74 |
+
foreach ( self::$registered as $class => $args )
|
75 |
+
new $class( $args[0], $args[1] );
|
76 |
+
}
|
77 |
+
|
78 |
+
|
79 |
+
// ____________MAIN METHODS____________
|
80 |
+
|
81 |
+
|
82 |
+
// Constructor
|
83 |
+
function __construct( $file = false, $options = null ) {
|
84 |
+
if ( is_a( $options, 'scbOptions' ) )
|
85 |
+
$this->options = $options;
|
86 |
+
|
87 |
+
$this->setup();
|
88 |
+
$this->check_args();
|
89 |
+
|
90 |
+
if ( isset( $this->option_name ) ) {
|
91 |
+
add_action( 'admin_init', array( $this, 'option_init' ) );
|
92 |
+
if ( function_exists( 'settings_errors' ) )
|
93 |
+
add_action( 'admin_notices', 'settings_errors' );
|
94 |
+
}
|
95 |
+
|
96 |
+
add_action( 'admin_menu', array( $this, 'page_init' ), $this->args['admin_action_priority'] );
|
97 |
+
add_filter( 'contextual_help', array( $this, '_contextual_help' ), 10, 2 );
|
98 |
+
|
99 |
+
if ( $file ) {
|
100 |
+
$this->file = $file;
|
101 |
+
$this->plugin_url = plugin_dir_url( $file );
|
102 |
+
|
103 |
+
if ( $this->args['action_link'] )
|
104 |
+
add_filter( 'plugin_action_links_' . plugin_basename( $file ), array( $this, '_action_link' ) );
|
105 |
+
}
|
106 |
+
}
|
107 |
+
|
108 |
+
// This is where all the page args can be set
|
109 |
+
function setup(){}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Called when the page is loaded, but before any rendering.
|
113 |
+
*
|
114 |
+
* Useful for calling $screen->add_help_tab() etc.
|
115 |
+
*/
|
116 |
+
function page_loaded() {}
|
117 |
+
|
118 |
+
// This is where the css and js go
|
119 |
+
// Both wp_enqueue_*() and inline code can be added
|
120 |
+
function page_head(){}
|
121 |
+
|
122 |
+
// This is where the contextual help goes
|
123 |
+
// @return string
|
124 |
+
function page_help(){}
|
125 |
+
|
126 |
+
// A generic page header
|
127 |
+
function page_header() {
|
128 |
+
echo "<div class='wrap'>\n";
|
129 |
+
screen_icon( $this->args['screen_icon'] );
|
130 |
+
echo "<h2>" . $this->args['page_title'] . "</h2>\n";
|
131 |
+
}
|
132 |
+
|
133 |
+
// This is where the page content goes
|
134 |
+
abstract function page_content();
|
135 |
+
|
136 |
+
// A generic page footer
|
137 |
+
function page_footer() {
|
138 |
+
echo "</div>\n";
|
139 |
+
}
|
140 |
+
|
141 |
+
// This is where the form data should be validated
|
142 |
+
function validate( $new_data, $old_data ) {
|
143 |
+
return $new_data;
|
144 |
+
}
|
145 |
+
|
146 |
+
// Manually handle option saving ( use Settings API instead )
|
147 |
+
function form_handler() {
|
148 |
+
if ( empty( $_POST['action'] ) )
|
149 |
+
return false;
|
150 |
+
|
151 |
+
check_admin_referer( $this->nonce );
|
152 |
+
|
153 |
+
if ( !isset($this->options) ) {
|
154 |
+
trigger_error('options handler not set', E_USER_WARNING);
|
155 |
+
return false;
|
156 |
+
}
|
157 |
+
|
158 |
+
$new_data = wp_array_slice_assoc( $_POST, array_keys( $this->options->get_defaults() ) );
|
159 |
+
|
160 |
+
$new_data = stripslashes_deep( $new_data );
|
161 |
+
|
162 |
+
$new_data = $this->validate( $new_data, $this->options->get() );
|
163 |
+
|
164 |
+
$this->options->set( $new_data );
|
165 |
+
|
166 |
+
$this->admin_msg();
|
167 |
+
}
|
168 |
+
|
169 |
+
// Manually generate a standard admin notice ( use Settings API instead )
|
170 |
+
function admin_msg( $msg = '', $class = "updated" ) {
|
171 |
+
if ( empty( $msg ) )
|
172 |
+
$msg = __( 'Settings <strong>saved</strong>.', $this->textdomain );
|
173 |
+
|
174 |
+
echo scb_admin_notice( $msg, $class );
|
175 |
+
}
|
176 |
+
|
177 |
+
|
178 |
+
// ____________UTILITIES____________
|
179 |
+
|
180 |
+
|
181 |
+
// Generates a form submit button
|
182 |
+
function submit_button( $value = '', $action = 'action', $class = "button" ) {
|
183 |
+
if ( is_array( $value ) ) {
|
184 |
+
extract( wp_parse_args( $value, array(
|
185 |
+
'value' => __( 'Save Changes', $this->textdomain ),
|
186 |
+
'action' => 'action',
|
187 |
+
'class' => 'button',
|
188 |
+
'ajax' => true
|
189 |
+
) ) );
|
190 |
+
|
191 |
+
if ( ! $ajax )
|
192 |
+
$class .= ' no-ajax';
|
193 |
+
}
|
194 |
+
else {
|
195 |
+
if ( empty( $value ) )
|
196 |
+
$value = __( 'Save Changes', $this->textdomain );
|
197 |
+
}
|
198 |
+
|
199 |
+
$input_args = array(
|
200 |
+
'type' => 'submit',
|
201 |
+
'name' => $action,
|
202 |
+
'value' => $value,
|
203 |
+
'extra' => '',
|
204 |
+
'desc' => false,
|
205 |
+
'wrap' => html( 'p class="submit"', scbForms::TOKEN )
|
206 |
+
);
|
207 |
+
|
208 |
+
if ( ! empty( $class ) )
|
209 |
+
$input_args['extra'] = compact( 'class' );
|
210 |
+
|
211 |
+
return scbForms::input( $input_args );
|
212 |
+
}
|
213 |
+
|
214 |
+
/*
|
215 |
+
Mimics scbForms::form_wrap()
|
216 |
+
|
217 |
+
$this->form_wrap( $content ); // generates a form with a default submit button
|
218 |
+
|
219 |
+
$this->form_wrap( $content, false ); // generates a form with no submit button
|
220 |
+
|
221 |
+
// the second argument is sent to submit_button()
|
222 |
+
$this->form_wrap( $content, array( 'text' => 'Save changes',
|
223 |
+
'name' => 'action',
|
224 |
+
'ajax' => true,
|
225 |
+
) );
|
226 |
+
*/
|
227 |
+
function form_wrap( $content, $submit_button = true ) {
|
228 |
+
if ( is_array( $submit_button ) ) {
|
229 |
+
$content .= $this->submit_button( $submit_button );
|
230 |
+
} elseif ( true === $submit_button ) {
|
231 |
+
$content .= $this->submit_button();
|
232 |
+
} elseif ( false !== strpos( $submit_button, '<input' ) ) {
|
233 |
+
$content .= $submit_button;
|
234 |
+
} elseif ( false !== $submit_button ) {
|
235 |
+
$button_args = array_slice( func_get_args(), 1 );
|
236 |
+
$content .= call_user_func_array( array( $this, 'submit_button' ), $button_args );
|
237 |
+
}
|
238 |
+
|
239 |
+
return scbForms::form_wrap( $content, $this->nonce );
|
240 |
+
}
|
241 |
+
|
242 |
+
// Generates a table wrapped in a form
|
243 |
+
function form_table( $rows, $formdata = false ) {
|
244 |
+
$output = '';
|
245 |
+
foreach ( $rows as $row )
|
246 |
+
$output .= $this->table_row( $row, $formdata );
|
247 |
+
|
248 |
+
$output = $this->form_table_wrap( $output );
|
249 |
+
|
250 |
+
return $output;
|
251 |
+
}
|
252 |
+
|
253 |
+
// Wraps the given content in a <form><table>
|
254 |
+
function form_table_wrap( $content ) {
|
255 |
+
$output = $this->table_wrap( $content );
|
256 |
+
$output = $this->form_wrap( $output );
|
257 |
+
|
258 |
+
return $output;
|
259 |
+
}
|
260 |
+
|
261 |
+
// Generates a form table
|
262 |
+
function table( $rows, $formdata = false ) {
|
263 |
+
$output = '';
|
264 |
+
foreach ( $rows as $row )
|
265 |
+
$output .= $this->table_row( $row, $formdata );
|
266 |
+
|
267 |
+
$output = $this->table_wrap( $output );
|
268 |
+
|
269 |
+
return $output;
|
270 |
+
}
|
271 |
+
|
272 |
+
// Generates a table row
|
273 |
+
function table_row( $args, $formdata = false ) {
|
274 |
+
return $this->row_wrap( $args['title'], $this->input( $args, $formdata ) );
|
275 |
+
}
|
276 |
+
|
277 |
+
// Wraps the given content in a <table>
|
278 |
+
function table_wrap( $content ) {
|
279 |
+
return
|
280 |
+
html( 'table class="form-table"', $content );
|
281 |
+
}
|
282 |
+
|
283 |
+
// Wraps the given content in a <tr><td>
|
284 |
+
function row_wrap( $title, $content ) {
|
285 |
+
return
|
286 |
+
html( 'tr',
|
287 |
+
html( 'th scope="row"', $title )
|
288 |
+
.html( 'td', $content ) );
|
289 |
+
}
|
290 |
+
|
291 |
+
// Mimic scbForms inheritance
|
292 |
+
function __call( $method, $args ) {
|
293 |
+
if ( in_array( $method, array( 'input', 'form' ) ) ) {
|
294 |
+
if ( empty( $args[1] ) && isset( $this->options ) )
|
295 |
+
$args[1] = $this->options->get();
|
296 |
+
|
297 |
+
if ( 'form' == $method )
|
298 |
+
$args[2] = $this->nonce;
|
299 |
+
}
|
300 |
+
|
301 |
+
return call_user_func_array( array( 'scbForms', $method ), $args );
|
302 |
+
}
|
303 |
+
|
304 |
+
// Wraps a string in a <script> tag
|
305 |
+
function js_wrap( $string ) {
|
306 |
+
return "\n<script type='text/javascript'>\n" . $string . "\n</script>\n";
|
307 |
+
}
|
308 |
+
|
309 |
+
// Wraps a string in a <style> tag
|
310 |
+
function css_wrap( $string ) {
|
311 |
+
return "\n<style type='text/css'>\n" . $string . "\n</style>\n";
|
312 |
+
}
|
313 |
+
|
314 |
+
|
315 |
+
// ____________INTERNAL METHODS____________
|
316 |
+
|
317 |
+
|
318 |
+
// Registers a page
|
319 |
+
function page_init() {
|
320 |
+
extract( $this->args );
|
321 |
+
|
322 |
+
if ( ! $toplevel ) {
|
323 |
+
$this->pagehook = add_submenu_page( $parent, $page_title, $menu_title, $capability, $page_slug, array( $this, '_page_content_hook' ) );
|
324 |
+
} else {
|
325 |
+
$func = 'add_' . $toplevel . '_page';
|
326 |
+
$this->pagehook = $func( $page_title, $menu_title, $capability, $page_slug, array( $this, '_page_content_hook' ), $icon_url, $position );
|
327 |
+
}
|
328 |
+
|
329 |
+
if ( ! $this->pagehook )
|
330 |
+
return;
|
331 |
+
|
332 |
+
add_action( 'load-' . $this->pagehook, array( $this, 'page_loaded' ) );
|
333 |
+
|
334 |
+
if ( $ajax_submit ) {
|
335 |
+
$this->ajax_response();
|
336 |
+
add_action( 'admin_footer', array( $this, 'ajax_submit' ), 20 );
|
337 |
+
}
|
338 |
+
|
339 |
+
add_action( 'admin_print_styles-' . $this->pagehook, array( $this, 'page_head' ) );
|
340 |
+
}
|
341 |
+
|
342 |
+
function option_init() {
|
343 |
+
register_setting( $this->option_name, $this->option_name, array( $this, 'validate' ) );
|
344 |
+
}
|
345 |
+
|
346 |
+
private function check_args() {
|
347 |
+
if ( empty( $this->args['page_title'] ) )
|
348 |
+
trigger_error( 'Page title cannot be empty', E_USER_WARNING );
|
349 |
+
|
350 |
+
$this->args = wp_parse_args( $this->args, array(
|
351 |
+
'toplevel' => '',
|
352 |
+
'position' => null,
|
353 |
+
'icon_url' => '',
|
354 |
+
'screen_icon' => '',
|
355 |
+
'parent' => 'options-general.php',
|
356 |
+
'capability' => 'manage_options',
|
357 |
+
'menu_title' => $this->args['page_title'],
|
358 |
+
'page_slug' => '',
|
359 |
+
'nonce' => '',
|
360 |
+
'action_link' => __( 'Settings', $this->textdomain ),
|
361 |
+
'ajax_submit' => false,
|
362 |
+
'admin_action_priority' => 10,
|
363 |
+
) );
|
364 |
+
|
365 |
+
if ( empty( $this->args['page_slug'] ) )
|
366 |
+
$this->args['page_slug'] = sanitize_title_with_dashes( $this->args['menu_title'] );
|
367 |
+
|
368 |
+
if ( empty( $this->args['nonce'] ) )
|
369 |
+
$this->nonce = $this->args['page_slug'];
|
370 |
+
}
|
371 |
+
|
372 |
+
function _contextual_help( $help, $screen ) {
|
373 |
+
if ( is_object( $screen ) )
|
374 |
+
$screen = $screen->id;
|
375 |
+
|
376 |
+
$actual_help = $this->page_help();
|
377 |
+
|
378 |
+
if ( $screen == $this->pagehook && $actual_help )
|
379 |
+
return $actual_help;
|
380 |
+
|
381 |
+
return $help;
|
382 |
+
}
|
383 |
+
|
384 |
+
function ajax_response() {
|
385 |
+
if ( ! isset( $_POST['_ajax_submit'] ) || $_POST['_ajax_submit'] != $this->pagehook )
|
386 |
+
return;
|
387 |
+
|
388 |
+
$this->form_handler();
|
389 |
+
die;
|
390 |
+
}
|
391 |
+
|
392 |
+
function ajax_submit() {
|
393 |
+
global $page_hook;
|
394 |
+
|
395 |
+
if ( $page_hook != $this->pagehook )
|
396 |
+
return;
|
397 |
+
?>
|
398 |
+
<script type="text/javascript">
|
399 |
+
jQuery( document ).ready( function( $ ){
|
400 |
+
var $spinner = $( new Image() ).attr( 'src', '<?php echo admin_url( "images/wpspin_light.gif" ); ?>' );
|
401 |
+
|
402 |
+
$( ':submit' ).click( function( ev ){
|
403 |
+
var $submit = $( this );
|
404 |
+
var $form = $submit.parents( 'form' );
|
405 |
+
|
406 |
+
if ( $submit.hasClass( 'no-ajax' ) || $form.attr( 'method' ).toLowerCase() != 'post' )
|
407 |
+
return true;
|
408 |
+
|
409 |
+
var $this_spinner = $spinner.clone();
|
410 |
+
|
411 |
+
$submit.before( $this_spinner ).hide();
|
412 |
+
|
413 |
+
var data = $form.serializeArray();
|
414 |
+
data.push( {name: $submit.attr( 'name' ), value: $submit.val()} );
|
415 |
+
data.push( {name: '_ajax_submit', value: '<?php echo $this->pagehook; ?>'} );
|
416 |
+
|
417 |
+
$.post( location.href, data, function( response ){
|
418 |
+
var $prev = $( '.wrap > .updated, .wrap > .error' );
|
419 |
+
var $msg = $( response ).hide().insertAfter( $( '.wrap h2' ) );
|
420 |
+
if ( $prev.length > 0 )
|
421 |
+
$prev.fadeOut( 'slow', function(){ $msg.fadeIn( 'slow' ); } );
|
422 |
+
else
|
423 |
+
$msg.fadeIn( 'slow' );
|
424 |
+
|
425 |
+
$this_spinner.hide();
|
426 |
+
$submit.show();
|
427 |
+
} );
|
428 |
+
|
429 |
+
ev.stopPropagation();
|
430 |
+
ev.preventDefault();
|
431 |
+
} );
|
432 |
+
} );
|
433 |
+
</script>
|
434 |
+
<?php
|
435 |
+
}
|
436 |
+
|
437 |
+
function _page_content_hook() {
|
438 |
+
$this->form_handler();
|
439 |
+
|
440 |
+
$this->page_header();
|
441 |
+
$this->page_content();
|
442 |
+
$this->page_footer();
|
443 |
+
}
|
444 |
+
|
445 |
+
function _action_link( $links ) {
|
446 |
+
$url = add_query_arg( 'page', $this->args['page_slug'], admin_url( $this->args['parent'] ) );
|
447 |
+
|
448 |
+
$links[] = html_link( $url, $this->args['action_link'] );
|
449 |
+
|
450 |
+
return $links;
|
451 |
+
}
|
452 |
+
}
|
453 |
+
|
scb/BoxesPage.php
ADDED
@@ -0,0 +1,240 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Admin screen with metaboxes base class
|
4 |
+
|
5 |
+
abstract class scbBoxesPage extends scbAdminPage {
|
6 |
+
/*
|
7 |
+
A box definition looks like this:
|
8 |
+
array( $slug, $title, $column );
|
9 |
+
|
10 |
+
Available columns: normal, side, column3, column4
|
11 |
+
*/
|
12 |
+
protected $boxes = array();
|
13 |
+
|
14 |
+
function __construct( $file = false, $options = null ) {
|
15 |
+
parent::__construct( $file, $options );
|
16 |
+
|
17 |
+
scbUtil::add_uninstall_hook( $this->file, array( $this, 'uninstall' ) );
|
18 |
+
}
|
19 |
+
|
20 |
+
function page_init() {
|
21 |
+
if ( !isset( $this->args['columns'] ) )
|
22 |
+
$this->args['columns'] = 2;
|
23 |
+
|
24 |
+
parent::page_init();
|
25 |
+
|
26 |
+
add_action( 'load-' . $this->pagehook, array( $this, 'boxes_init' ) );
|
27 |
+
}
|
28 |
+
|
29 |
+
function default_css() {
|
30 |
+
?>
|
31 |
+
<style type="text/css">
|
32 |
+
.postbox-container + .postbox-container {
|
33 |
+
margin-left: 18px;
|
34 |
+
}
|
35 |
+
.postbox-container {
|
36 |
+
padding-right: 0;
|
37 |
+
}
|
38 |
+
.inside {
|
39 |
+
clear: both;
|
40 |
+
overflow: hidden;
|
41 |
+
}
|
42 |
+
.inside table {
|
43 |
+
margin: 0 !important;
|
44 |
+
padding: 0 !important;
|
45 |
+
}
|
46 |
+
.inside table td {
|
47 |
+
vertical-align: middle !important;
|
48 |
+
}
|
49 |
+
.inside table .regular-text {
|
50 |
+
width: 100% !important;
|
51 |
+
}
|
52 |
+
.inside .form-table th {
|
53 |
+
width: 30%;
|
54 |
+
max-width: 200px;
|
55 |
+
padding: 10px 0 !important;
|
56 |
+
}
|
57 |
+
.inside .widefat .check-column {
|
58 |
+
padding-bottom: 7px !important;
|
59 |
+
}
|
60 |
+
.inside p,
|
61 |
+
.inside table {
|
62 |
+
margin: 0 0 10px !important;
|
63 |
+
}
|
64 |
+
.inside p.submit {
|
65 |
+
float: left !important;
|
66 |
+
padding: 0 !important;
|
67 |
+
margin-bottom: 0 !important;
|
68 |
+
}
|
69 |
+
</style>
|
70 |
+
<?php
|
71 |
+
}
|
72 |
+
|
73 |
+
function page_content() {
|
74 |
+
$this->default_css();
|
75 |
+
|
76 |
+
global $screen_layout_columns;
|
77 |
+
|
78 |
+
if ( isset( $screen_layout_columns ) ) {
|
79 |
+
$hide2 = $hide3 = $hide4 = '';
|
80 |
+
switch ( $screen_layout_columns ) {
|
81 |
+
case 4:
|
82 |
+
if( !isset( $this->args['column_widths'] ) )
|
83 |
+
$this->args['column_widths'] = array( 24.5, 24.5, 24.5, 24.5 );
|
84 |
+
break;
|
85 |
+
case 3:
|
86 |
+
if( !isset( $this->args['column_widths'] ) )
|
87 |
+
$this->args['column_widths'] = array( 32.67, 32.67, 32.67 );
|
88 |
+
$hide4 = 'display:none;';
|
89 |
+
break;
|
90 |
+
case 2:
|
91 |
+
if( !isset( $this->args['column_widths'] ) )
|
92 |
+
$this->args['column_widths'] = array( 49, 49 );
|
93 |
+
$hide3 = $hide4 = 'display:none;';
|
94 |
+
break;
|
95 |
+
default:
|
96 |
+
if( !isset( $this->args['column_widths'] ) )
|
97 |
+
$this->args['column_widths'] = array( 98 );
|
98 |
+
$hide2 = $hide3 = $hide4 = 'display:none;';
|
99 |
+
}
|
100 |
+
|
101 |
+
$this->args['column_widths'] = array_pad( $this->args['column_widths'], 4, 0 );
|
102 |
+
}
|
103 |
+
?>
|
104 |
+
<div id='<?php echo $this->pagehook ?>-widgets' class='metabox-holder'>
|
105 |
+
<?php
|
106 |
+
echo "\t<div class='postbox-container' style='width:{$this->args['column_widths'][0]}%'>\n";
|
107 |
+
do_meta_boxes( $this->pagehook, 'normal', '' );
|
108 |
+
|
109 |
+
echo "\t</div><div class='postbox-container' style='width:{$hide2}{$this->args['column_widths'][1]}%'>\n";
|
110 |
+
do_meta_boxes( $this->pagehook, 'side', '' );
|
111 |
+
|
112 |
+
echo "\t</div><div class='postbox-container' style='width:{$hide3}{$this->args['column_widths'][2]}%'>\n";
|
113 |
+
do_meta_boxes( $this->pagehook, 'column3', '' );
|
114 |
+
|
115 |
+
echo "\t</div><div class='postbox-container' style='width:{$hide4}{$this->args['column_widths'][3]}%'>\n";
|
116 |
+
do_meta_boxes( $this->pagehook, 'column4', '' );
|
117 |
+
?>
|
118 |
+
</div></div>
|
119 |
+
<?php
|
120 |
+
}
|
121 |
+
|
122 |
+
function page_footer() {
|
123 |
+
parent::page_footer();
|
124 |
+
$this->_boxes_js_init();
|
125 |
+
}
|
126 |
+
|
127 |
+
function form_handler() {
|
128 |
+
if ( empty( $_POST ) )
|
129 |
+
return;
|
130 |
+
|
131 |
+
check_admin_referer( $this->nonce );
|
132 |
+
|
133 |
+
// Box handler
|
134 |
+
foreach ( $this->boxes as $box ) {
|
135 |
+
$args = isset( $box[4] ) ? $box[4] : array();
|
136 |
+
|
137 |
+
$handler = $box[0] . '_handler';
|
138 |
+
|
139 |
+
if ( method_exists( $this, $handler ) )
|
140 |
+
call_user_func_array( array( $this, $handler ), $args );
|
141 |
+
}
|
142 |
+
}
|
143 |
+
|
144 |
+
function uninstall() {
|
145 |
+
global $wpdb;
|
146 |
+
|
147 |
+
$hook = str_replace( '-', '', $this->pagehook );
|
148 |
+
|
149 |
+
foreach ( array( 'metaboxhidden', 'closedpostboxes', 'wp_metaboxorder', 'screen_layout' ) as $option )
|
150 |
+
$keys[] = "'{$option}_{$hook}'";
|
151 |
+
|
152 |
+
$keys = '( ' . implode( ', ', $keys ) . ' )';
|
153 |
+
|
154 |
+
$wpdb->query( "
|
155 |
+
DELETE FROM {$wpdb->usermeta}
|
156 |
+
WHERE meta_key IN {$keys}
|
157 |
+
" );
|
158 |
+
}
|
159 |
+
|
160 |
+
function boxes_init() {
|
161 |
+
wp_enqueue_script( 'postbox' );
|
162 |
+
|
163 |
+
add_screen_option( 'layout_columns', array(
|
164 |
+
'max' => $this->args['columns'],
|
165 |
+
'default' => $this->args['columns']
|
166 |
+
) );
|
167 |
+
|
168 |
+
$registered = array();
|
169 |
+
foreach ( $this->boxes as $box_args ) {
|
170 |
+
foreach ( array( 'name', 'title', 'context', 'priority', 'args' ) as $i => $arg ) {
|
171 |
+
if ( isset( $box_args[$i] ) )
|
172 |
+
$$arg = $box_args[$i];
|
173 |
+
}
|
174 |
+
|
175 |
+
if ( empty( $title ) )
|
176 |
+
$title = ucfirst( $name );
|
177 |
+
if ( empty( $context ) )
|
178 |
+
$context = 'normal';
|
179 |
+
if ( empty( $priority ) )
|
180 |
+
$priority = 'default';
|
181 |
+
if ( empty( $args ) )
|
182 |
+
$args = array();
|
183 |
+
|
184 |
+
if ( isset( $registered[$name] ) ) {
|
185 |
+
if ( empty( $args ) )
|
186 |
+
trigger_error( "Duplicate box name: $name", E_USER_NOTICE );
|
187 |
+
|
188 |
+
$name = $this->_increment( $name );
|
189 |
+
} else {
|
190 |
+
$registered[$name] = true;
|
191 |
+
}
|
192 |
+
|
193 |
+
add_meta_box( $name, $title, array( $this, '_intermediate_callback' ), $this->pagehook, $context, $priority, $args );
|
194 |
+
}
|
195 |
+
}
|
196 |
+
|
197 |
+
// Make it so that $args is actually what's passed to the callback
|
198 |
+
function _intermediate_callback( $_, $box ) {
|
199 |
+
list( $name ) = explode( '-', $box['id'] );
|
200 |
+
|
201 |
+
call_user_func_array( array( $this, $name . '_box' ), $box['args'] );
|
202 |
+
}
|
203 |
+
|
204 |
+
private function _increment( $name ) {
|
205 |
+
$parts = explode( '-', $name );
|
206 |
+
if ( isset( $parts[1] ) )
|
207 |
+
$parts[1]++;
|
208 |
+
else
|
209 |
+
$parts[1] = 2;
|
210 |
+
|
211 |
+
return implode( '-', $parts );
|
212 |
+
}
|
213 |
+
|
214 |
+
// Adds necesary code for JS to work
|
215 |
+
function _boxes_js_init() {
|
216 |
+
echo $this->js_wrap( <<<EOT
|
217 |
+
jQuery( document ).ready( function( $ ){
|
218 |
+
// close postboxes that should be closed
|
219 |
+
$( '.if-js-closed' ).removeClass( 'if-js-closed' ).addClass( 'closed' );
|
220 |
+
// postboxes setup
|
221 |
+
postboxes.add_postbox_toggles( '$this->pagehook' );
|
222 |
+
} );
|
223 |
+
EOT
|
224 |
+
);
|
225 |
+
?>
|
226 |
+
|
227 |
+
<form style='display: none' method='get' action=''>
|
228 |
+
<p>
|
229 |
+
<?php
|
230 |
+
wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false );
|
231 |
+
wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false );
|
232 |
+
?>
|
233 |
+
</p>
|
234 |
+
</form>
|
235 |
+
<?php
|
236 |
+
}
|
237 |
+
}
|
238 |
+
|
239 |
+
|
240 |
+
|
scb/Cron.php
ADDED
@@ -0,0 +1,170 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// wp-cron job container
|
4 |
+
|
5 |
+
class scbCron {
|
6 |
+
protected $schedule;
|
7 |
+
protected $interval;
|
8 |
+
protected $time;
|
9 |
+
|
10 |
+
protected $hook;
|
11 |
+
protected $callback_args = array();
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Create a new cron job
|
15 |
+
*
|
16 |
+
* @param string Reference to main plugin file
|
17 |
+
* @param array List of args:
|
18 |
+
string $action OR callback $callback
|
19 |
+
string $schedule OR number $interval
|
20 |
+
array $callback_args (optional)
|
21 |
+
*/
|
22 |
+
function __construct( $file = false, $args ) {
|
23 |
+
extract( $args, EXTR_SKIP );
|
24 |
+
|
25 |
+
// Set time & schedule
|
26 |
+
if ( isset( $time ) )
|
27 |
+
$this->time = $time;
|
28 |
+
|
29 |
+
if ( isset( $interval ) ) {
|
30 |
+
$this->schedule = $interval . 'secs';
|
31 |
+
$this->interval = $interval;
|
32 |
+
} elseif ( isset( $schedule ) ) {
|
33 |
+
$this->schedule = $schedule;
|
34 |
+
}
|
35 |
+
|
36 |
+
// Set hook
|
37 |
+
if ( isset( $action ) ) {
|
38 |
+
$this->hook = $action;
|
39 |
+
} elseif ( isset( $callback ) ) {
|
40 |
+
$this->hook = self::_callback_to_string( $callback );
|
41 |
+
add_action( $this->hook, $callback );
|
42 |
+
} elseif ( method_exists( $this, 'callback' ) ) {
|
43 |
+
$this->hook = self::_callback_to_string( array( $this, 'callback' ) );
|
44 |
+
add_action( $this->hook, $callback );
|
45 |
+
} else {
|
46 |
+
trigger_error( '$action OR $callback not set', E_USER_WARNING );
|
47 |
+
}
|
48 |
+
|
49 |
+
if ( isset( $callback_args ) )
|
50 |
+
$this->callback_args = (array) $callback_args;
|
51 |
+
|
52 |
+
if ( $file && $this->schedule ) {
|
53 |
+
scbUtil::add_activation_hook( $file, array( $this, 'reset' ) );
|
54 |
+
register_deactivation_hook( $file, array( $this, 'unschedule' ) );
|
55 |
+
}
|
56 |
+
|
57 |
+
add_filter( 'cron_schedules', array( $this, '_add_timing' ) );
|
58 |
+
}
|
59 |
+
|
60 |
+
/* Change the interval of the cron job
|
61 |
+
*
|
62 |
+
* @param array List of args:
|
63 |
+
string $schedule OR number $interval
|
64 |
+
timestamp $time ( optional )
|
65 |
+
*/
|
66 |
+
function reschedule( $args ) {
|
67 |
+
extract( $args );
|
68 |
+
|
69 |
+
if ( $schedule && $this->schedule != $schedule ) {
|
70 |
+
$this->schedule = $schedule;
|
71 |
+
} elseif ( $interval && $this->interval != $interval ) {
|
72 |
+
$this->schedule = $interval . 'secs';
|
73 |
+
$this->interval = $interval;
|
74 |
+
}
|
75 |
+
|
76 |
+
$this->time = $time;
|
77 |
+
|
78 |
+
$this->reset();
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Reset the schedule
|
83 |
+
*/
|
84 |
+
function reset() {
|
85 |
+
$this->unschedule();
|
86 |
+
$this->schedule();
|
87 |
+
}
|
88 |
+
|
89 |
+
/**
|
90 |
+
* Clear the cron job
|
91 |
+
*/
|
92 |
+
function unschedule() {
|
93 |
+
# wp_clear_scheduled_hook( $this->hook, $this->callback_args );
|
94 |
+
self::really_clear_scheduled_hook( $this->hook );
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Execute the job now
|
99 |
+
* @param array $args List of arguments to pass to the callback
|
100 |
+
*/
|
101 |
+
function do_now( $args = null ) {
|
102 |
+
if ( is_null( $args ) )
|
103 |
+
$args = $this->callback_args;
|
104 |
+
|
105 |
+
do_action_ref_array( $this->hook, $args );
|
106 |
+
}
|
107 |
+
|
108 |
+
/**
|
109 |
+
* Execute the job with a given delay
|
110 |
+
* @param int $delay in seconds
|
111 |
+
* @param array $args List of arguments to pass to the callback
|
112 |
+
*/
|
113 |
+
function do_once( $delay = 0, $args = null ) {
|
114 |
+
if ( is_null( $args ) )
|
115 |
+
$args = $this->callback_args;
|
116 |
+
|
117 |
+
wp_clear_scheduled_hook( $this->hook, $args );
|
118 |
+
wp_schedule_single_event( time() + $delay, $this->hook, $args );
|
119 |
+
}
|
120 |
+
|
121 |
+
|
122 |
+
//_____INTERNAL METHODS_____
|
123 |
+
|
124 |
+
|
125 |
+
function _add_timing( $schedules ) {
|
126 |
+
if ( isset( $schedules[$this->schedule] ) )
|
127 |
+
return $schedules;
|
128 |
+
|
129 |
+
$schedules[$this->schedule] = array( 'interval' => $this->interval,
|
130 |
+
'display' => $this->interval . ' seconds' );
|
131 |
+
|
132 |
+
return $schedules;
|
133 |
+
}
|
134 |
+
|
135 |
+
protected function schedule() {
|
136 |
+
if ( ! $this->time )
|
137 |
+
$this->time = time();
|
138 |
+
|
139 |
+
wp_schedule_event( $this->time, $this->schedule, $this->hook, $this->callback_args );
|
140 |
+
}
|
141 |
+
|
142 |
+
protected static function really_clear_scheduled_hook( $name ) {
|
143 |
+
$crons = _get_cron_array();
|
144 |
+
|
145 |
+
foreach ( $crons as $timestamp => $hooks ) {
|
146 |
+
foreach ( $hooks as $hook => $args )
|
147 |
+
if ( $hook == $name )
|
148 |
+
unset( $crons[$timestamp][$hook] );
|
149 |
+
|
150 |
+
if ( empty( $hooks ) )
|
151 |
+
unset( $crons[$timestamp] );
|
152 |
+
}
|
153 |
+
|
154 |
+
_set_cron_array( $crons );
|
155 |
+
}
|
156 |
+
|
157 |
+
protected static function _callback_to_string( $callback ) {
|
158 |
+
if ( ! is_array( $callback ) )
|
159 |
+
$str = $callback;
|
160 |
+
elseif ( ! is_string( $callback[0] ) )
|
161 |
+
$str = get_class( $callback[0] ) . '_' . $callback[1];
|
162 |
+
else
|
163 |
+
$str = $callback[0] . '::' . $callback[1];
|
164 |
+
|
165 |
+
$str .= '_hook';
|
166 |
+
|
167 |
+
return $str;
|
168 |
+
}
|
169 |
+
}
|
170 |
+
|
scb/Forms.php
ADDED
@@ -0,0 +1,531 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Data-aware form generator
|
4 |
+
|
5 |
+
class scbForms {
|
6 |
+
|
7 |
+
const TOKEN = '%input%';
|
8 |
+
|
9 |
+
protected static $cur_name;
|
10 |
+
|
11 |
+
function input_with_value( $args, $value ) {
|
12 |
+
if ( is_null( $value ) && isset( $args['default'] ) )
|
13 |
+
$value = $args['default'];
|
14 |
+
|
15 |
+
if ( !is_null( $value ) ) {
|
16 |
+
switch ( $args['type'] ) {
|
17 |
+
case 'select':
|
18 |
+
case 'radio':
|
19 |
+
$args['selected'] = $value;
|
20 |
+
break;
|
21 |
+
case 'checkbox':
|
22 |
+
if ( is_array( $value ) )
|
23 |
+
$args['checked'] = $value;
|
24 |
+
else
|
25 |
+
$args['checked'] = ( $value || ( isset( $args['value'] ) && $value == $args['value'] ) );
|
26 |
+
break;
|
27 |
+
default:
|
28 |
+
$args['value'] = $value;
|
29 |
+
}
|
30 |
+
}
|
31 |
+
|
32 |
+
return self::input( $args );
|
33 |
+
}
|
34 |
+
|
35 |
+
static function input( $args, $formdata = false ) {
|
36 |
+
if ( false !== $formdata ) {
|
37 |
+
$form = new scbForm( $formdata );
|
38 |
+
return $form->input( $args );
|
39 |
+
}
|
40 |
+
|
41 |
+
if ( empty( $args['name'] ) ) {
|
42 |
+
return trigger_error( 'Empty name', E_USER_WARNING );
|
43 |
+
}
|
44 |
+
|
45 |
+
$args = wp_parse_args( $args, array(
|
46 |
+
'desc' => '',
|
47 |
+
'desc_pos' => 'after',
|
48 |
+
'wrap' => self::TOKEN,
|
49 |
+
'wrap_each' => self::TOKEN,
|
50 |
+
) );
|
51 |
+
|
52 |
+
if ( isset( $args['value'] ) && is_array( $args['value'] ) ) {
|
53 |
+
$args['values'] = $args['value'];
|
54 |
+
unset( $args['value'] );
|
55 |
+
}
|
56 |
+
|
57 |
+
if ( isset( $args['extra'] ) && !is_array( $args['extra'] ) )
|
58 |
+
$args['extra'] = shortcode_parse_atts( $args['extra'] );
|
59 |
+
|
60 |
+
self::$cur_name = self::get_name( $args['name'] );
|
61 |
+
|
62 |
+
switch ( $args['type'] ) {
|
63 |
+
case 'select':
|
64 |
+
case 'radio':
|
65 |
+
$input = self::_single_choice( $args );
|
66 |
+
break;
|
67 |
+
case 'checkbox':
|
68 |
+
if ( isset( $args['values'] ) )
|
69 |
+
$input = self::_multiple_choice( $args );
|
70 |
+
else
|
71 |
+
$input = self::_checkbox( $args );
|
72 |
+
break;
|
73 |
+
default:
|
74 |
+
$input = self::_input( $args );
|
75 |
+
}
|
76 |
+
|
77 |
+
return str_replace( self::TOKEN, $input, $args['wrap'] );
|
78 |
+
}
|
79 |
+
|
80 |
+
|
81 |
+
// ____________UTILITIES____________
|
82 |
+
|
83 |
+
|
84 |
+
// Generates a table wrapped in a form
|
85 |
+
static function form_table( $rows, $formdata = NULL ) {
|
86 |
+
$output = '';
|
87 |
+
foreach ( $rows as $row )
|
88 |
+
$output .= self::table_row( $row, $formdata );
|
89 |
+
|
90 |
+
$output = self::form_table_wrap( $output );
|
91 |
+
|
92 |
+
return $output;
|
93 |
+
}
|
94 |
+
|
95 |
+
// Generates a form
|
96 |
+
static function form( $inputs, $formdata = NULL, $nonce ) {
|
97 |
+
$output = '';
|
98 |
+
foreach ( $inputs as $input )
|
99 |
+
$output .= self::input( $input, $formdata );
|
100 |
+
|
101 |
+
$output = self::form_wrap( $output, $nonce );
|
102 |
+
|
103 |
+
return $output;
|
104 |
+
}
|
105 |
+
|
106 |
+
// Generates a table
|
107 |
+
static function table( $rows, $formdata = NULL ) {
|
108 |
+
$output = '';
|
109 |
+
foreach ( $rows as $row )
|
110 |
+
$output .= self::table_row( $row, $formdata );
|
111 |
+
|
112 |
+
$output = self::table_wrap( $output );
|
113 |
+
|
114 |
+
return $output;
|
115 |
+
}
|
116 |
+
|
117 |
+
// Generates a table row
|
118 |
+
static function table_row( $args, $formdata = NULL ) {
|
119 |
+
return self::row_wrap( $args['title'], self::input( $args, $formdata ) );
|
120 |
+
}
|
121 |
+
|
122 |
+
|
123 |
+
// ____________WRAPPERS____________
|
124 |
+
|
125 |
+
|
126 |
+
// Wraps the given content in a <form><table>
|
127 |
+
static function form_table_wrap( $content, $nonce = 'update_options' ) {
|
128 |
+
$output = self::table_wrap( $content );
|
129 |
+
$output = self::form_wrap( $output, $nonce );
|
130 |
+
|
131 |
+
return $output;
|
132 |
+
}
|
133 |
+
|
134 |
+
// Wraps the given content in a <form> tag
|
135 |
+
static function form_wrap( $content, $nonce = 'update_options' ) {
|
136 |
+
$output = "\n<form method='post' action=''>\n";
|
137 |
+
$output .= $content;
|
138 |
+
$output .= wp_nonce_field( $action = $nonce, $name = "_wpnonce", $referer = true , $echo = false );
|
139 |
+
$output .= "\n</form>\n";
|
140 |
+
|
141 |
+
return $output;
|
142 |
+
}
|
143 |
+
|
144 |
+
// Wraps the given content in a <table>
|
145 |
+
static function table_wrap( $content ) {
|
146 |
+
$output = "\n<table class='form-table'>\n" . $content . "\n</table>\n";
|
147 |
+
|
148 |
+
return $output;
|
149 |
+
}
|
150 |
+
|
151 |
+
// Wraps the given content in a <tr><td>
|
152 |
+
static function row_wrap( $title, $content ) {
|
153 |
+
return "\n<tr>\n\t<th scope='row'>" . $title . "</th>\n\t<td>\n\t\t" . $content . "\t</td>\n\n</tr>";
|
154 |
+
}
|
155 |
+
|
156 |
+
|
157 |
+
// ____________PRIVATE METHODS____________
|
158 |
+
|
159 |
+
|
160 |
+
private static function _single_choice( $args ) {
|
161 |
+
$args = wp_parse_args( $args, array(
|
162 |
+
'numeric' => false, // use numeric array instead of associative
|
163 |
+
'selected' => array( 'foo' ), // hack to make default blank
|
164 |
+
) );
|
165 |
+
|
166 |
+
self::_expand_values( $args );
|
167 |
+
|
168 |
+
if ( 'select' == $args['type'] )
|
169 |
+
return self::_select( $args );
|
170 |
+
else
|
171 |
+
return self::_radio( $args );
|
172 |
+
}
|
173 |
+
|
174 |
+
private static function _multiple_choice( $args ) {
|
175 |
+
$args = wp_parse_args( $args, array(
|
176 |
+
'numeric' => false, // use numeric array instead of associative
|
177 |
+
'checked' => null,
|
178 |
+
) );
|
179 |
+
|
180 |
+
self::$cur_name .= '[]';
|
181 |
+
|
182 |
+
self::_expand_values( $args );
|
183 |
+
|
184 |
+
extract( $args );
|
185 |
+
|
186 |
+
if ( !is_array( $checked ) )
|
187 |
+
$checked = array();
|
188 |
+
|
189 |
+
$opts = '';
|
190 |
+
foreach ( $values as $value => $title ) {
|
191 |
+
$single_input = self::_checkbox( array(
|
192 |
+
'type' => 'checkbox',
|
193 |
+
'value' => $value,
|
194 |
+
'checked' => in_array( $value, $checked ),
|
195 |
+
'desc' => $title,
|
196 |
+
'desc_pos' => 'after'
|
197 |
+
) );
|
198 |
+
|
199 |
+
$opts .= str_replace( self::TOKEN, $single_input, $args['wrap_each'] );
|
200 |
+
}
|
201 |
+
|
202 |
+
return self::add_desc( $opts, $desc, $desc_pos );
|
203 |
+
}
|
204 |
+
|
205 |
+
private static function _expand_values( &$args ) {
|
206 |
+
$values =& $args['values'];
|
207 |
+
|
208 |
+
if ( !empty( $values ) && !self::is_associative( $values ) ) {
|
209 |
+
if ( is_array( $args['desc'] ) ) {
|
210 |
+
$values = array_combine( $values, $args['desc'] ); // back-compat
|
211 |
+
$args['desc'] = false;
|
212 |
+
} elseif ( !isset( $args['numeric'] ) || !$args['numeric'] ) {
|
213 |
+
$values = array_combine( $values, $values );
|
214 |
+
}
|
215 |
+
}
|
216 |
+
}
|
217 |
+
|
218 |
+
private static function _radio( $args ) {
|
219 |
+
extract( $args );
|
220 |
+
|
221 |
+
if ( array( 'foo' ) == $selected ) {
|
222 |
+
// radio buttons should always have one option selected
|
223 |
+
$selected = key( $values );
|
224 |
+
}
|
225 |
+
|
226 |
+
$opts = '';
|
227 |
+
foreach ( $values as $value => $title ) {
|
228 |
+
$single_input = self::_checkbox( array(
|
229 |
+
'type' => 'radio',
|
230 |
+
'value' => $value,
|
231 |
+
'checked' => ( (string) $value == (string) $selected ),
|
232 |
+
'desc' => $title,
|
233 |
+
'desc_pos' => 'after'
|
234 |
+
) );
|
235 |
+
|
236 |
+
$opts .= str_replace( self::TOKEN, $single_input, $args['wrap_each'] );
|
237 |
+
}
|
238 |
+
|
239 |
+
return self::add_desc( $opts, $desc, $desc_pos );
|
240 |
+
}
|
241 |
+
|
242 |
+
private static function _select( $args ) {
|
243 |
+
extract( wp_parse_args( $args, array(
|
244 |
+
'text' => false,
|
245 |
+
'extra' => array()
|
246 |
+
) ) );
|
247 |
+
|
248 |
+
$options = array();
|
249 |
+
|
250 |
+
if ( false !== $text ) {
|
251 |
+
$options[] = array(
|
252 |
+
'value' => '',
|
253 |
+
'selected' => ( $selected == array( 'foo' ) ),
|
254 |
+
'title' => $text
|
255 |
+
);
|
256 |
+
}
|
257 |
+
|
258 |
+
foreach ( $values as $value => $title ) {
|
259 |
+
$options[] = array(
|
260 |
+
'value' => $value,
|
261 |
+
'selected' => ( (string) $value == (string) $selected ),
|
262 |
+
'title' => $title
|
263 |
+
);
|
264 |
+
}
|
265 |
+
|
266 |
+
$opts = '';
|
267 |
+
foreach ( $options as $option ) {
|
268 |
+
extract( $option );
|
269 |
+
|
270 |
+
$opts .= html( 'option', compact( 'value', 'selected' ), $title );
|
271 |
+
}
|
272 |
+
|
273 |
+
$extra['name'] = self::$cur_name;
|
274 |
+
|
275 |
+
$input = html( 'select', $extra, $opts );
|
276 |
+
|
277 |
+
return self::add_label( $input, $desc, $desc_pos );
|
278 |
+
}
|
279 |
+
|
280 |
+
// Handle args for a single checkbox or radio input
|
281 |
+
private static function _checkbox( $args ) {
|
282 |
+
$args = wp_parse_args( $args, array(
|
283 |
+
'value' => true,
|
284 |
+
'desc' => NULL,
|
285 |
+
'checked' => false,
|
286 |
+
'extra' => array(),
|
287 |
+
) );
|
288 |
+
|
289 |
+
foreach ( $args as $key => &$val )
|
290 |
+
$$key = &$val;
|
291 |
+
unset( $val );
|
292 |
+
|
293 |
+
$extra['checked'] = $checked;
|
294 |
+
|
295 |
+
if ( is_null( $desc ) && !is_bool( $value ) )
|
296 |
+
$desc = str_replace( '[]', '', $value );
|
297 |
+
|
298 |
+
return self::_input_gen( $args );
|
299 |
+
}
|
300 |
+
|
301 |
+
// Handle args for text inputs
|
302 |
+
private static function _input( $args ) {
|
303 |
+
$args = wp_parse_args( $args, array(
|
304 |
+
'value' => '',
|
305 |
+
'desc_pos' => 'after',
|
306 |
+
'extra' => array( 'class' => 'regular-text' ),
|
307 |
+
) );
|
308 |
+
|
309 |
+
foreach ( $args as $key => &$val )
|
310 |
+
$$key = &$val;
|
311 |
+
unset( $val );
|
312 |
+
|
313 |
+
if ( !isset( $extra['id'] ) && !is_array( $name ) && false === strpos( $name, '[' ) )
|
314 |
+
$extra['id'] = $name;
|
315 |
+
|
316 |
+
return self::_input_gen( $args );
|
317 |
+
}
|
318 |
+
|
319 |
+
// Generate html with the final args
|
320 |
+
private static function _input_gen( $args ) {
|
321 |
+
extract( wp_parse_args( $args, array(
|
322 |
+
'value' => NULL,
|
323 |
+
'desc' => NULL,
|
324 |
+
'extra' => array()
|
325 |
+
) ) );
|
326 |
+
|
327 |
+
$extra['name'] = self::$cur_name;
|
328 |
+
|
329 |
+
if ( 'textarea' == $type ) {
|
330 |
+
$input = html( 'textarea', $extra, esc_textarea( $value ) );
|
331 |
+
} else {
|
332 |
+
$extra['value'] = $value;
|
333 |
+
$extra['type'] = $type;
|
334 |
+
$input = html( 'input', $extra );
|
335 |
+
}
|
336 |
+
|
337 |
+
return self::add_label( $input, $desc, $desc_pos );
|
338 |
+
}
|
339 |
+
|
340 |
+
private static function add_label( $input, $desc, $desc_pos ) {
|
341 |
+
return html( 'label', self::add_desc( $input, $desc, $desc_pos ) ) . "\n";
|
342 |
+
}
|
343 |
+
|
344 |
+
private static function add_desc( $input, $desc, $desc_pos ) {
|
345 |
+
if ( empty( $desc ) )
|
346 |
+
return $input;
|
347 |
+
|
348 |
+
if ( 'before' == $desc_pos )
|
349 |
+
return $desc . ' ' . $input;
|
350 |
+
else
|
351 |
+
return $input . ' ' . $desc;
|
352 |
+
}
|
353 |
+
|
354 |
+
|
355 |
+
// Utilities
|
356 |
+
|
357 |
+
|
358 |
+
/**
|
359 |
+
* Generates the proper string for a name attribute.
|
360 |
+
*
|
361 |
+
* @param array|string $name The raw name
|
362 |
+
*
|
363 |
+
* @return string
|
364 |
+
*/
|
365 |
+
static function get_name( $name ) {
|
366 |
+
$name = (array) $name;
|
367 |
+
|
368 |
+
$name_str = array_shift( $name );
|
369 |
+
|
370 |
+
foreach ( $name as $key ) {
|
371 |
+
$name_str .= '[' . esc_attr( $key ) . ']';
|
372 |
+
}
|
373 |
+
|
374 |
+
return $name_str;
|
375 |
+
}
|
376 |
+
|
377 |
+
/**
|
378 |
+
* Traverses the formdata and retrieves the correct value.
|
379 |
+
*
|
380 |
+
* @param array|string $name The name of the value
|
381 |
+
* @param array $value The data that will be traversed
|
382 |
+
* @param mixed $fallback The value returned when the key is not found
|
383 |
+
*
|
384 |
+
* @return mixed
|
385 |
+
*/
|
386 |
+
static function get_value( $name, $value, $fallback = null ) {
|
387 |
+
foreach ( (array) $name as $key ) {
|
388 |
+
if ( !isset( $value[ $key ] ) )
|
389 |
+
return $fallback;
|
390 |
+
|
391 |
+
$value = $value[$key];
|
392 |
+
}
|
393 |
+
|
394 |
+
return $value;
|
395 |
+
}
|
396 |
+
|
397 |
+
/**
|
398 |
+
* Given a list of fields, extract the appropriate POST data and return it.
|
399 |
+
*
|
400 |
+
* @param array $fields List of args that would be sent to scbForms::input()
|
401 |
+
* @param array $to_update Existing data to update
|
402 |
+
*
|
403 |
+
* @return array
|
404 |
+
*/
|
405 |
+
static function validate_post_data( $fields, $to_update = array() ) {
|
406 |
+
foreach ( $fields as $field ) {
|
407 |
+
$value = scbForms::get_value( $field['name'], $_POST );
|
408 |
+
|
409 |
+
$value = stripslashes_deep( $value );
|
410 |
+
|
411 |
+
switch ( $field['type'] ) {
|
412 |
+
case 'checkbox':
|
413 |
+
if ( isset( $field['values'] ) && is_array( $field['values'] ) )
|
414 |
+
$value = array_intersect( $field['values'], (array) $value );
|
415 |
+
else
|
416 |
+
$value = (bool) $value;
|
417 |
+
|
418 |
+
break;
|
419 |
+
case 'radio':
|
420 |
+
case 'select':
|
421 |
+
self::_expand_values( $field );
|
422 |
+
|
423 |
+
if ( !isset( $field['values'][ $value ] ) )
|
424 |
+
continue 2;
|
425 |
+
}
|
426 |
+
|
427 |
+
self::set_value( $to_update, $field['name'], $value );
|
428 |
+
}
|
429 |
+
|
430 |
+
return $to_update;
|
431 |
+
}
|
432 |
+
|
433 |
+
static function input_from_meta( $args, $object_id, $meta_type = 'post' ) {
|
434 |
+
$single = ( 'checkbox' != $args['type'] );
|
435 |
+
|
436 |
+
$key = (array) $args['name'];
|
437 |
+
$key = end( $key );
|
438 |
+
|
439 |
+
$value = get_metadata( $meta_type, $object_id, $key );
|
440 |
+
|
441 |
+
if ( empty( $value ) )
|
442 |
+
$value = null;
|
443 |
+
elseif( $single )
|
444 |
+
$value = reset( $value );
|
445 |
+
|
446 |
+
return self::input_with_value( $args, $value );
|
447 |
+
}
|
448 |
+
|
449 |
+
static function update_meta( $fields, $data, $object_id, $meta_type = 'post' ) {
|
450 |
+
foreach ( $fields as $field_args ) {
|
451 |
+
$key = $field_args['name'];
|
452 |
+
|
453 |
+
if ( 'checkbox' == $field_args['type'] ) {
|
454 |
+
$new_values = isset( $data[$key] ) ? $data[$key] : array();
|
455 |
+
|
456 |
+
$old_values = get_metadata( $meta_type, $object_id, $key );
|
457 |
+
|
458 |
+
foreach ( array_diff( $new_values, $old_values ) as $value )
|
459 |
+
add_metadata( $meta_type, $object_id, $key, $value );
|
460 |
+
|
461 |
+
foreach ( array_diff( $old_values, $new_values ) as $value )
|
462 |
+
delete_metadata( $meta_type, $object_id, $key, $value );
|
463 |
+
} else {
|
464 |
+
$value = $data[$key];
|
465 |
+
|
466 |
+
if ( '' === $value )
|
467 |
+
delete_metadata( $meta_type, $object_id, $key );
|
468 |
+
else
|
469 |
+
update_metadata( $meta_type, $object_id, $key, $value );
|
470 |
+
}
|
471 |
+
}
|
472 |
+
}
|
473 |
+
|
474 |
+
private static function set_value( &$arr, $name, $value ) {
|
475 |
+
$name = (array) $name;
|
476 |
+
|
477 |
+
$final_key = array_pop( $name );
|
478 |
+
|
479 |
+
while ( !empty( $name ) ) {
|
480 |
+
$key = array_shift( $name );
|
481 |
+
|
482 |
+
if ( !isset( $arr[ $key ] ) )
|
483 |
+
$arr[ $key ] = array();
|
484 |
+
|
485 |
+
$arr =& $arr[ $key ];
|
486 |
+
}
|
487 |
+
|
488 |
+
$arr[ $final_key ] = $value;
|
489 |
+
}
|
490 |
+
|
491 |
+
private static function is_associative( $array ) {
|
492 |
+
$keys = array_keys( $array );
|
493 |
+
return array_keys( $keys ) !== $keys;
|
494 |
+
}
|
495 |
+
}
|
496 |
+
|
497 |
+
|
498 |
+
/**
|
499 |
+
* A wrapper for scbForms, containing the formdata
|
500 |
+
*/
|
501 |
+
class scbForm {
|
502 |
+
protected $data = array();
|
503 |
+
protected $prefix = array();
|
504 |
+
|
505 |
+
function __construct( $data, $prefix = false ) {
|
506 |
+
if ( is_array( $data ) )
|
507 |
+
$this->data = $data;
|
508 |
+
|
509 |
+
if ( $prefix )
|
510 |
+
$this->prefix = (array) $prefix;
|
511 |
+
}
|
512 |
+
|
513 |
+
function traverse_to( $path ) {
|
514 |
+
$data = scbForms::get_value( $path, $this->data );
|
515 |
+
|
516 |
+
$prefix = array_merge( $this->prefix, (array) $path );
|
517 |
+
|
518 |
+
return new scbForm( $data, $prefix );
|
519 |
+
}
|
520 |
+
|
521 |
+
function input( $args ) {
|
522 |
+
$value = scbForms::get_value( $args['name'], $this->data );
|
523 |
+
|
524 |
+
if ( !empty( $this->prefix ) ) {
|
525 |
+
$args['name'] = array_merge( $this->prefix, (array) $args['name'] );
|
526 |
+
}
|
527 |
+
|
528 |
+
return scbForms::input_with_value( $args, $value );
|
529 |
+
}
|
530 |
+
}
|
531 |
+
|
scb/Hooks.php
ADDED
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class scbHooks {
|
4 |
+
private static $mangle_name;
|
5 |
+
|
6 |
+
public static function add( $class ) {
|
7 |
+
self::_do( 'add_filter', $class );
|
8 |
+
}
|
9 |
+
|
10 |
+
public static function remove( $class ) {
|
11 |
+
self::_do( 'remove_filter', $class );
|
12 |
+
}
|
13 |
+
|
14 |
+
public static function debug( $class, $mangle_name = false ) {
|
15 |
+
self::$mangle_name = $mangle_name;
|
16 |
+
|
17 |
+
echo "<pre>";
|
18 |
+
self::_do( array( __CLASS__, '_print' ), $class );
|
19 |
+
echo "</pre>";
|
20 |
+
}
|
21 |
+
|
22 |
+
private static function _print( $tag, $callback, $prio, $argc ) {
|
23 |
+
$static = !is_object( $callback[0] );
|
24 |
+
|
25 |
+
if ( self::$mangle_name )
|
26 |
+
$class = $static ? '__CLASS__' : '$this';
|
27 |
+
else if ( $static )
|
28 |
+
$class = "'" . $callback[0] . "'";
|
29 |
+
else
|
30 |
+
$class = '$' . get_class( $callback[0] );
|
31 |
+
|
32 |
+
$func = "array( $class, '$callback[1]' )";
|
33 |
+
|
34 |
+
echo "add_filter( '$tag', $func";
|
35 |
+
|
36 |
+
if ( $prio != 10 || $argc > 1 ) {
|
37 |
+
echo ", $prio";
|
38 |
+
|
39 |
+
if ( $argc > 1 )
|
40 |
+
echo ", $argc";
|
41 |
+
}
|
42 |
+
|
43 |
+
echo " );\n";
|
44 |
+
}
|
45 |
+
|
46 |
+
private static function _do( $action, $class ) {
|
47 |
+
$reflection = new ReflectionClass( $class );
|
48 |
+
|
49 |
+
foreach ( $reflection->getMethods() as $method ) {
|
50 |
+
if ( $method->isPublic() && !$method->isConstructor() ) {
|
51 |
+
$comment = $method->getDocComment();
|
52 |
+
|
53 |
+
if ( preg_match( '/@nohook[ \t\*\n]+/', $comment ) ) {
|
54 |
+
continue;
|
55 |
+
}
|
56 |
+
|
57 |
+
preg_match_all( '/@hook:?\s+([^\s]+)/', $comment, $matches ) ? $matches[1] : $method->name;
|
58 |
+
if ( empty( $matches[1] ) )
|
59 |
+
$hooks = array( $method->name );
|
60 |
+
else
|
61 |
+
$hooks = $matches[1];
|
62 |
+
|
63 |
+
$priority = preg_match( '/@priority:?\s+(\d+)/', $comment, $matches ) ? $matches[1] : 10;
|
64 |
+
|
65 |
+
foreach ( $hooks as $hook ) {
|
66 |
+
call_user_func( $action, $hook, array( $class, $method->name ), $priority, $method->getNumberOfParameters() );
|
67 |
+
}
|
68 |
+
}
|
69 |
+
}
|
70 |
+
}
|
71 |
+
}
|
72 |
+
|
scb/Options.php
ADDED
@@ -0,0 +1,163 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Container for an array of options
|
4 |
+
|
5 |
+
class scbOptions {
|
6 |
+
|
7 |
+
protected $key; // the option name
|
8 |
+
|
9 |
+
protected $defaults; // the default values
|
10 |
+
|
11 |
+
public $wp_filter_id; // used by WP hooks
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Create a new set of options
|
15 |
+
*
|
16 |
+
* @param string $key Option name
|
17 |
+
* @param string $file Reference to main plugin file
|
18 |
+
* @param array $defaults An associative array of default values (optional)
|
19 |
+
*/
|
20 |
+
public function __construct( $key, $file, $defaults = array() ) {
|
21 |
+
$this->key = $key;
|
22 |
+
$this->defaults = $defaults;
|
23 |
+
|
24 |
+
if ( $file ) {
|
25 |
+
scbUtil::add_activation_hook( $file, array( $this, '_activation' ) );
|
26 |
+
scbUtil::add_uninstall_hook( $file, array( $this, 'delete' ) );
|
27 |
+
}
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Get option name
|
32 |
+
*/
|
33 |
+
public function get_key() {
|
34 |
+
return $this->key;
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Get option values for one, many or all fields
|
39 |
+
*
|
40 |
+
* @param string|array $field The field(s) to get
|
41 |
+
* @return mixed Whatever is in those fields
|
42 |
+
*/
|
43 |
+
public function get( $field = '' ) {
|
44 |
+
$data = get_option( $this->key, array() );
|
45 |
+
|
46 |
+
$data = array_merge( $this->defaults, $data );
|
47 |
+
|
48 |
+
return $this->_get( $field, $data );
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Get default values for one, many or all fields
|
53 |
+
*
|
54 |
+
* @param string|array $field The field( s ) to get
|
55 |
+
* @return mixed Whatever is in those fields
|
56 |
+
*/
|
57 |
+
public function get_defaults( $field = '' ) {
|
58 |
+
return $this->_get( $field, $this->defaults );
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Set all data fields, certain fields or a single field
|
63 |
+
*
|
64 |
+
* @param string|array $field The field to update or an associative array
|
65 |
+
* @param mixed $value The new value ( ignored if $field is array )
|
66 |
+
* @return null
|
67 |
+
*/
|
68 |
+
public function set( $field, $value = '' ) {
|
69 |
+
if ( is_array( $field ) )
|
70 |
+
$newdata = $field;
|
71 |
+
else
|
72 |
+
$newdata = array( $field => $value );
|
73 |
+
|
74 |
+
$this->update( array_merge( $this->get(), $newdata ) );
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Reset option to defaults
|
79 |
+
*
|
80 |
+
* @return null
|
81 |
+
*/
|
82 |
+
public function reset() {
|
83 |
+
$this->update( $this->defaults, false );
|
84 |
+
}
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Remove any keys that are not in the defaults array
|
88 |
+
*
|
89 |
+
* @return bool
|
90 |
+
*/
|
91 |
+
public function cleanup() {
|
92 |
+
$this->update( $this->_clean( $this->get() ) );
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Update raw data
|
97 |
+
*
|
98 |
+
* @param mixed $newdata
|
99 |
+
* @param bool $clean wether to remove unrecognized keys or not
|
100 |
+
* @return null
|
101 |
+
*/
|
102 |
+
public function update( $newdata, $clean = true ) {
|
103 |
+
if ( $clean )
|
104 |
+
$newdata = $this->_clean( $newdata );
|
105 |
+
|
106 |
+
update_option( $this->key, array_merge( $this->get(), $newdata ) );
|
107 |
+
}
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Delete the option
|
111 |
+
*
|
112 |
+
* @return null
|
113 |
+
*/
|
114 |
+
public function delete() {
|
115 |
+
delete_option( $this->key );
|
116 |
+
}
|
117 |
+
|
118 |
+
|
119 |
+
//_____INTERNAL METHODS_____
|
120 |
+
|
121 |
+
|
122 |
+
// Saves an extra query
|
123 |
+
function _activation() {
|
124 |
+
add_option( $this->key, $this->defaults );
|
125 |
+
}
|
126 |
+
|
127 |
+
// Keep only the keys defined in $this->defaults
|
128 |
+
private function _clean( $data ) {
|
129 |
+
return wp_array_slice_assoc( $data, array_keys( $this->defaults ) );
|
130 |
+
}
|
131 |
+
|
132 |
+
// Get one, more or all fields from an array
|
133 |
+
private function &_get( $field, $data ) {
|
134 |
+
if ( empty( $field ) )
|
135 |
+
return $data;
|
136 |
+
|
137 |
+
if ( is_string( $field ) )
|
138 |
+
return $data[$field];
|
139 |
+
|
140 |
+
foreach ( $field as $key )
|
141 |
+
if ( isset( $data[$key] ) )
|
142 |
+
$result[] = $data[$key];
|
143 |
+
|
144 |
+
return $result;
|
145 |
+
}
|
146 |
+
|
147 |
+
// Magic method: $options->field
|
148 |
+
function __get( $field ) {
|
149 |
+
return $this->get( $field );
|
150 |
+
}
|
151 |
+
|
152 |
+
// Magic method: $options->field = $value
|
153 |
+
function __set( $field, $value ) {
|
154 |
+
$this->set( $field, $value );
|
155 |
+
}
|
156 |
+
|
157 |
+
// Magic method: isset( $options->field )
|
158 |
+
function __isset( $field ) {
|
159 |
+
$data = $this->get();
|
160 |
+
return isset( $data[$field] );
|
161 |
+
}
|
162 |
+
}
|
163 |
+
|
scb/Table.php
ADDED
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Takes care of creating, updating and deleting database tables
|
4 |
+
|
5 |
+
class scbTable {
|
6 |
+
protected $name;
|
7 |
+
protected $columns;
|
8 |
+
protected $upgrade_method;
|
9 |
+
|
10 |
+
function __construct( $name, $file, $columns, $upgrade_method = 'dbDelta' ) {
|
11 |
+
$this->name = $name;
|
12 |
+
$this->columns = $columns;
|
13 |
+
$this->upgrade_method = $upgrade_method;
|
14 |
+
|
15 |
+
scb_register_table( $name );
|
16 |
+
|
17 |
+
if ( $file ) {
|
18 |
+
scbUtil::add_activation_hook( $file, array( $this, 'install' ) );
|
19 |
+
scbUtil::add_uninstall_hook( $file, array( $this, 'uninstall' ) );
|
20 |
+
}
|
21 |
+
}
|
22 |
+
|
23 |
+
function install() {
|
24 |
+
scb_install_table( $this->name, $this->columns, $this->upgrade_method );
|
25 |
+
}
|
26 |
+
|
27 |
+
function uninstall() {
|
28 |
+
scb_uninstall_table( $this->name );
|
29 |
+
}
|
30 |
+
}
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Register a table with $wpdb
|
34 |
+
*
|
35 |
+
* @param string $key The key to be used on the $wpdb object
|
36 |
+
* @param string $name The actual name of the table, without $wpdb->prefix
|
37 |
+
*/
|
38 |
+
function scb_register_table( $key, $name = false ) {
|
39 |
+
global $wpdb;
|
40 |
+
|
41 |
+
if ( !$name )
|
42 |
+
$name = $key;
|
43 |
+
|
44 |
+
$wpdb->tables[] = $name;
|
45 |
+
$wpdb->$key = $wpdb->prefix . $name;
|
46 |
+
}
|
47 |
+
|
48 |
+
function scb_install_table( $key, $columns, $upgrade_method = 'dbDelta' ) {
|
49 |
+
global $wpdb;
|
50 |
+
|
51 |
+
$full_table_name = $wpdb->$key;
|
52 |
+
|
53 |
+
$charset_collate = '';
|
54 |
+
if ( $wpdb->has_cap( 'collation' ) ) {
|
55 |
+
if ( ! empty( $wpdb->charset ) )
|
56 |
+
$charset_collate = "DEFAULT CHARACTER SET $wpdb->charset";
|
57 |
+
if ( ! empty( $wpdb->collate ) )
|
58 |
+
$charset_collate .= " COLLATE $wpdb->collate";
|
59 |
+
}
|
60 |
+
|
61 |
+
if ( 'dbDelta' == $upgrade_method ) {
|
62 |
+
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
|
63 |
+
dbDelta( "CREATE TABLE $full_table_name ( $columns ) $charset_collate" );
|
64 |
+
return;
|
65 |
+
}
|
66 |
+
|
67 |
+
if ( 'delete_first' == $upgrade_method )
|
68 |
+
$wpdb->query( "DROP TABLE IF EXISTS $full_table_name;" );
|
69 |
+
|
70 |
+
$wpdb->query( "CREATE TABLE IF NOT EXISTS $full_table_name ( $columns ) $charset_collate;" );
|
71 |
+
}
|
72 |
+
|
73 |
+
function scb_uninstall_table( $key ) {
|
74 |
+
global $wpdb;
|
75 |
+
|
76 |
+
$wpdb->query( "DROP TABLE IF EXISTS " . $wpdb->$key );
|
77 |
+
}
|
78 |
+
|
scb/Util.php
ADDED
@@ -0,0 +1,202 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Various utilities
|
4 |
+
|
5 |
+
class scbUtil {
|
6 |
+
|
7 |
+
// Force script enqueue
|
8 |
+
static function do_scripts( $handles ) {
|
9 |
+
global $wp_scripts;
|
10 |
+
|
11 |
+
if ( ! is_a( $wp_scripts, 'WP_Scripts' ) )
|
12 |
+
$wp_scripts = new WP_Scripts();
|
13 |
+
|
14 |
+
$wp_scripts->do_items( ( array ) $handles );
|
15 |
+
}
|
16 |
+
|
17 |
+
// Force style enqueue
|
18 |
+
static function do_styles( $handles ) {
|
19 |
+
self::do_scripts( 'jquery' );
|
20 |
+
|
21 |
+
global $wp_styles;
|
22 |
+
|
23 |
+
if ( ! is_a( $wp_styles, 'WP_Styles' ) )
|
24 |
+
$wp_styles = new WP_Styles();
|
25 |
+
|
26 |
+
ob_start();
|
27 |
+
$wp_styles->do_items( ( array ) $handles );
|
28 |
+
$content = str_replace( array( "'", "\n" ), array( '"', '' ), ob_get_clean() );
|
29 |
+
|
30 |
+
echo "<script type='text/javascript'>\n";
|
31 |
+
echo "jQuery(function ($) { $('head').prepend('$content'); });\n";
|
32 |
+
echo "</script>";
|
33 |
+
}
|
34 |
+
|
35 |
+
// Enable delayed activation; to be used with scb_init()
|
36 |
+
static function add_activation_hook( $plugin, $callback ) {
|
37 |
+
if ( defined( 'SCB_LOAD_MU' ) )
|
38 |
+
register_activation_hook( $plugin, $callback );
|
39 |
+
else
|
40 |
+
add_action( 'scb_activation_' . plugin_basename( $plugin ), $callback );
|
41 |
+
}
|
42 |
+
|
43 |
+
// For debugging
|
44 |
+
static function do_activation( $plugin ) {
|
45 |
+
do_action( 'scb_activation_' . plugin_basename( $plugin ) );
|
46 |
+
}
|
47 |
+
|
48 |
+
// Allows more than one uninstall hooks.
|
49 |
+
// Also prevents an UPDATE query on each page load.
|
50 |
+
static function add_uninstall_hook( $plugin, $callback ) {
|
51 |
+
if ( !is_admin() )
|
52 |
+
return;
|
53 |
+
|
54 |
+
register_uninstall_hook( $plugin, '__return_false' ); // dummy
|
55 |
+
|
56 |
+
add_action( 'uninstall_' . plugin_basename( $plugin ), $callback );
|
57 |
+
}
|
58 |
+
|
59 |
+
// For debugging
|
60 |
+
static function do_uninstall( $plugin ) {
|
61 |
+
do_action( 'uninstall_' . plugin_basename( $plugin ) );
|
62 |
+
}
|
63 |
+
|
64 |
+
// Get the current, full URL
|
65 |
+
static function get_current_url() {
|
66 |
+
return ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
|
67 |
+
}
|
68 |
+
|
69 |
+
// Apply a function to each element of a ( nested ) array recursively
|
70 |
+
static function array_map_recursive( $callback, $array ) {
|
71 |
+
array_walk_recursive( $array, array( __CLASS__, 'array_map_recursive_helper' ), $callback );
|
72 |
+
|
73 |
+
return $array;
|
74 |
+
}
|
75 |
+
|
76 |
+
static function array_map_recursive_helper( &$val, $key, $callback ) {
|
77 |
+
$val = call_user_func( $callback, $val );
|
78 |
+
}
|
79 |
+
|
80 |
+
// Extract certain $keys from $array
|
81 |
+
static function array_extract( $array, $keys ) {
|
82 |
+
_deprecated_function( __CLASS__ . '::' . __FUNCTION__, 'WP 3.1', 'wp_array_slice_assoc()' );
|
83 |
+
return wp_array_slice_assoc( $array, $keys );
|
84 |
+
}
|
85 |
+
|
86 |
+
// Extract a certain value from a list of arrays
|
87 |
+
static function array_pluck( $array, $key ) {
|
88 |
+
_deprecated_function( __CLASS__ . '::' . __FUNCTION__, 'WP 3.1', 'wp_list_pluck()' );
|
89 |
+
return wp_list_pluck( $array, $key );
|
90 |
+
}
|
91 |
+
|
92 |
+
// Transform a list of objects into an associative array
|
93 |
+
static function objects_to_assoc( $objects, $key, $value ) {
|
94 |
+
_deprecated_function( __CLASS__ . '::' . __FUNCTION__, 'r41', 'scb_list_fold()' );
|
95 |
+
return scb_list_fold( $objects, $key, $value );
|
96 |
+
}
|
97 |
+
|
98 |
+
// Prepare an array for an IN statement
|
99 |
+
static function array_to_sql( $values ) {
|
100 |
+
foreach ( $values as &$val )
|
101 |
+
$val = "'" . esc_sql( trim( $val ) ) . "'";
|
102 |
+
|
103 |
+
return implode( ',', $values );
|
104 |
+
}
|
105 |
+
|
106 |
+
// Example: split_at( '</', '<a></a>' ) => array( '<a>', '</a>' )
|
107 |
+
static function split_at( $delim, $str ) {
|
108 |
+
$i = strpos( $str, $delim );
|
109 |
+
|
110 |
+
if ( false === $i )
|
111 |
+
return false;
|
112 |
+
|
113 |
+
$start = substr( $str, 0, $i );
|
114 |
+
$finish = substr( $str, $i );
|
115 |
+
|
116 |
+
return array( $start, $finish );
|
117 |
+
}
|
118 |
+
}
|
119 |
+
|
120 |
+
// Return a standard admin notice
|
121 |
+
function scb_admin_notice( $msg, $class = 'updated' ) {
|
122 |
+
return "<div class='$class fade'><p>$msg</p></div>\n";
|
123 |
+
}
|
124 |
+
|
125 |
+
// Transform a list of objects into an associative array
|
126 |
+
function scb_list_fold( $list, $key, $value ) {
|
127 |
+
$r = array();
|
128 |
+
|
129 |
+
if ( is_array( reset( $list ) ) ) {
|
130 |
+
foreach ( $list as $item )
|
131 |
+
$r[ $item[ $key ] ] = $item[ $value ];
|
132 |
+
} else {
|
133 |
+
foreach ( $list as $item )
|
134 |
+
$r[ $item->$key ] = $item->$value;
|
135 |
+
}
|
136 |
+
|
137 |
+
return $r;
|
138 |
+
}
|
139 |
+
|
140 |
+
|
141 |
+
//_____Minimalist HTML framework_____
|
142 |
+
|
143 |
+
/**
|
144 |
+
* Generate an HTML tag. Atributes are escaped. Content is NOT escaped.
|
145 |
+
*/
|
146 |
+
if ( ! function_exists( 'html' ) ):
|
147 |
+
function html( $tag ) {
|
148 |
+
$args = func_get_args();
|
149 |
+
|
150 |
+
$tag = array_shift( $args );
|
151 |
+
|
152 |
+
if ( is_array( $args[0] ) ) {
|
153 |
+
$closing = $tag;
|
154 |
+
$attributes = array_shift( $args );
|
155 |
+
foreach ( $attributes as $key => $value ) {
|
156 |
+
if ( false === $value )
|
157 |
+
continue;
|
158 |
+
|
159 |
+
if ( true === $value )
|
160 |
+
$value = $key;
|
161 |
+
|
162 |
+
$tag .= ' ' . $key . '="' . esc_attr( $value ) . '"';
|
163 |
+
}
|
164 |
+
} else {
|
165 |
+
list( $closing ) = explode( ' ', $tag, 2 );
|
166 |
+
}
|
167 |
+
|
168 |
+
if ( in_array( $closing, array( 'area', 'base', 'basefont', 'br', 'hr', 'input', 'img', 'link', 'meta' ) ) ) {
|
169 |
+
return "<{$tag} />";
|
170 |
+
}
|
171 |
+
|
172 |
+
$content = implode( '', $args );
|
173 |
+
|
174 |
+
return "<{$tag}>{$content}</{$closing}>";
|
175 |
+
}
|
176 |
+
endif;
|
177 |
+
|
178 |
+
// Generate an <a> tag
|
179 |
+
if ( ! function_exists( 'html_link' ) ):
|
180 |
+
function html_link( $url, $title = '' ) {
|
181 |
+
if ( empty( $title ) )
|
182 |
+
$title = $url;
|
183 |
+
|
184 |
+
return html( 'a', array( 'href' => $url ), $title );
|
185 |
+
}
|
186 |
+
endif;
|
187 |
+
|
188 |
+
|
189 |
+
//_____Compatibility layer_____
|
190 |
+
|
191 |
+
// WP < ?
|
192 |
+
if ( ! function_exists( 'set_post_field' ) ) :
|
193 |
+
function set_post_field( $field, $value, $post_id ) {
|
194 |
+
global $wpdb;
|
195 |
+
|
196 |
+
$post_id = absint( $post_id );
|
197 |
+
$value = sanitize_post_field( $field, $value, $post_id, 'db' );
|
198 |
+
|
199 |
+
return $wpdb->update( $wpdb->posts, array( $field => $value ), array( 'ID' => $post_id ) );
|
200 |
+
}
|
201 |
+
endif;
|
202 |
+
|
scb/Widget.php
ADDED
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Adds compatibility methods between WP_Widget and scbForms
|
4 |
+
|
5 |
+
abstract class scbWidget extends WP_Widget {
|
6 |
+
protected $defaults = array();
|
7 |
+
|
8 |
+
private static $scb_widgets = array();
|
9 |
+
|
10 |
+
static function init( $class, $file = '', $base = '' ) {
|
11 |
+
self::$scb_widgets[] = $class;
|
12 |
+
|
13 |
+
add_action( 'widgets_init', array( __CLASS__, '_scb_register' ) );
|
14 |
+
|
15 |
+
// for auto-uninstall
|
16 |
+
if ( $file && $base && class_exists( 'scbOptions' ) )
|
17 |
+
new scbOptions( "widget_$base", $file );
|
18 |
+
}
|
19 |
+
|
20 |
+
static function _scb_register() {
|
21 |
+
foreach ( self::$scb_widgets as $widget )
|
22 |
+
register_widget( $widget );
|
23 |
+
}
|
24 |
+
|
25 |
+
// A pre-filled method, for convenience
|
26 |
+
function widget( $args, $instance ) {
|
27 |
+
$instance = wp_parse_args( $instance, $this->defaults );
|
28 |
+
|
29 |
+
extract( $args );
|
30 |
+
|
31 |
+
echo $before_widget;
|
32 |
+
|
33 |
+
$title = apply_filters( 'widget_title', isset( $instance['title'] ) ? $instance['title'] : '', $instance, $this->id_base );
|
34 |
+
|
35 |
+
if ( ! empty( $title ) )
|
36 |
+
echo $before_title . $title . $after_title;
|
37 |
+
|
38 |
+
$this->content( $instance );
|
39 |
+
|
40 |
+
echo $after_widget;
|
41 |
+
}
|
42 |
+
|
43 |
+
// This is where the actual widget content goes
|
44 |
+
function content( $instance ) {}
|
45 |
+
|
46 |
+
|
47 |
+
//_____HELPER METHODS_____
|
48 |
+
|
49 |
+
|
50 |
+
// See scbForms::input()
|
51 |
+
// Allows extra parameter $args['title']
|
52 |
+
protected function input( $args, $formdata = array() ) {
|
53 |
+
$prefix = array( 'widget-' . $this->id_base, $this->number );
|
54 |
+
|
55 |
+
$form = new scbForm( $formdata, $prefix );
|
56 |
+
|
57 |
+
// Add default class
|
58 |
+
if ( !isset( $args['extra'] ) && 'text' == $args['type'] )
|
59 |
+
$args['extra'] = array( 'class' => 'widefat' );
|
60 |
+
|
61 |
+
// Add default label position
|
62 |
+
if ( !in_array( $args['type'], array( 'checkbox', 'radio' ) ) && empty( $args['desc_pos'] ) )
|
63 |
+
$args['desc_pos'] = 'before';
|
64 |
+
|
65 |
+
$name = $args['name'];
|
66 |
+
|
67 |
+
if ( !is_array( $name ) && '[]' == substr( $name, -2 ) )
|
68 |
+
$name = array( substr( $name, 0, -2 ), '' );
|
69 |
+
|
70 |
+
$args['name'] = $name;
|
71 |
+
|
72 |
+
return $form->input( $args );
|
73 |
+
}
|
74 |
+
}
|
75 |
+
|
scb/load.php
ADDED
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
$GLOBALS['_scb_data'] = array( 53, __FILE__, array(
|
4 |
+
'scbUtil', 'scbOptions', 'scbForms', 'scbTable',
|
5 |
+
'scbWidget', 'scbAdminPage', 'scbBoxesPage',
|
6 |
+
'scbCron', 'scbHooks',
|
7 |
+
) );
|
8 |
+
|
9 |
+
if ( !class_exists( 'scbLoad4' ) ) :
|
10 |
+
/**
|
11 |
+
* The main idea behind this class is to load the most recent version of the scb classes available.
|
12 |
+
*
|
13 |
+
* It waits until all plugins are loaded and then does some crazy hacks to make activation hooks work.
|
14 |
+
*/
|
15 |
+
class scbLoad4 {
|
16 |
+
|
17 |
+
private static $candidates = array();
|
18 |
+
private static $classes;
|
19 |
+
private static $callbacks = array();
|
20 |
+
|
21 |
+
private static $loaded;
|
22 |
+
|
23 |
+
static function init( $callback = '' ) {
|
24 |
+
list( $rev, $file, $classes ) = $GLOBALS['_scb_data'];
|
25 |
+
|
26 |
+
self::$candidates[$file] = $rev;
|
27 |
+
self::$classes[$file] = $classes;
|
28 |
+
|
29 |
+
if ( !empty( $callback ) ) {
|
30 |
+
self::$callbacks[$file] = $callback;
|
31 |
+
|
32 |
+
add_action( 'activate_plugin', array( __CLASS__, 'delayed_activation' ) );
|
33 |
+
}
|
34 |
+
|
35 |
+
// TODO: don't load when activating a plugin ?
|
36 |
+
add_action( 'plugins_loaded', array( __CLASS__, 'load' ), 9, 0 );
|
37 |
+
}
|
38 |
+
|
39 |
+
static function delayed_activation( $plugin ) {
|
40 |
+
$plugin_dir = dirname( $plugin );
|
41 |
+
|
42 |
+
if ( '.' == $plugin_dir )
|
43 |
+
return;
|
44 |
+
|
45 |
+
foreach ( self::$callbacks as $file => $callback ) {
|
46 |
+
if ( dirname( dirname( plugin_basename( $file ) ) ) == $plugin_dir ) {
|
47 |
+
self::load( false );
|
48 |
+
call_user_func( $callback );
|
49 |
+
do_action( 'scb_activation_' . $plugin );
|
50 |
+
break;
|
51 |
+
}
|
52 |
+
}
|
53 |
+
}
|
54 |
+
|
55 |
+
static function load( $do_callbacks = true ) {
|
56 |
+
arsort( self::$candidates );
|
57 |
+
|
58 |
+
$file = key( self::$candidates );
|
59 |
+
|
60 |
+
$path = dirname( $file ) . '/';
|
61 |
+
|
62 |
+
foreach ( self::$classes[$file] as $class_name ) {
|
63 |
+
if ( class_exists( $class_name ) )
|
64 |
+
continue;
|
65 |
+
|
66 |
+
$fpath = $path . substr( $class_name, 3 ) . '.php';
|
67 |
+
if ( file_exists( $fpath ) ) {
|
68 |
+
include $fpath;
|
69 |
+
self::$loaded[] = $fpath;
|
70 |
+
}
|
71 |
+
}
|
72 |
+
|
73 |
+
if ( $do_callbacks )
|
74 |
+
foreach ( self::$callbacks as $callback )
|
75 |
+
call_user_func( $callback );
|
76 |
+
}
|
77 |
+
|
78 |
+
static function get_info() {
|
79 |
+
arsort( self::$candidates );
|
80 |
+
|
81 |
+
return array( self::$loaded, self::$candidates );
|
82 |
+
}
|
83 |
+
}
|
84 |
+
endif;
|
85 |
+
|
86 |
+
if ( !function_exists( 'scb_init' ) ) :
|
87 |
+
function scb_init( $callback = '' ) {
|
88 |
+
scbLoad4::init( $callback );
|
89 |
+
}
|
90 |
+
endif;
|
91 |
+
|