Category Posts Widget - Version 4.9.4

Version Description

  • March 2th 2020 =
  • Fixed Delete global click event
Download this release

Release Info

Developer Kometschuh
Plugin Icon 128x128 Category Posts Widget
Version 4.9.4
Comparing to
See all releases

Code changes from version 4.9.3 to 4.9.4

cat-posts.php CHANGED
@@ -1,1002 +1,1002 @@
1
- <?php
2
- /**
3
- * Main file of the plugin
4
- *
5
- * @package categoryposts.
6
- *
7
- * @since 1.0
8
- */
9
-
10
- /*
11
- Plugin Name: Category Posts Widget
12
- Plugin URI: https://wordpress.org/plugins/category-posts/
13
- Description: Adds a widget that shows the most recent posts from a single category.
14
- Author: TipTopPress
15
- Version: 4.9.3
16
- Author URI: http://tiptoppress.com
17
- Text Domain: category-posts
18
- Domain Path: /languages
19
- */
20
-
21
- namespace categoryPosts;
22
-
23
- // Don't call the file directly.
24
- if ( ! defined( 'ABSPATH' ) ) {
25
- exit;
26
- }
27
-
28
- const VERSION = '4.9.2';
29
- const DOC_URL = 'http://tiptoppress.com/category-posts-widget/documentation-4-9/';
30
- const PRO_URL = 'http://tiptoppress.com/term-and-category-based-posts-widget/';
31
- const SUPPORT_URL = 'https://wordpress.org/support/plugin/category-posts/';
32
- const SHORTCODE_NAME = 'catposts';
33
- const SHORTCODE_META = 'categoryPosts-shorcode';
34
- const WIDGET_BASE_ID = 'category-posts';
35
-
36
- require_once __DIR__ . '/class-virtual-widget.php';
37
- require_once __DIR__ . '/class-virtual-widgets-repository.php';
38
- require_once __DIR__ . '/class-widget.php';
39
- require_once __DIR__ . '/loadmore.php';
40
- require_once __DIR__ . '/localizeddate.php';
41
-
42
- /**
43
- * Adds the "Customize" link to the Toolbar on edit mode.
44
- *
45
- * @since 4.6
46
- */
47
- function wp_admin_bar_customize_menu() {
48
- global $wp_admin_bar;
49
-
50
- if ( ! isset( $_GET['action'] ) || ( 'edit' !== $_GET['action'] ) ) {
51
- return;
52
- }
53
-
54
- if ( ! current_user_can( 'customize' ) || ! is_admin() || ! is_user_logged_in() || ! is_admin_bar_showing() ) {
55
- return;
56
- }
57
-
58
- $current_url = '';
59
- if ( isset( $_GET['post'] ) && ( '' !== $_GET['post'] ) ) {
60
- $current_url = get_permalink( absint( $_GET['post'] ) );
61
- }
62
- $customize_url = add_query_arg( 'url', rawurlencode( $current_url ), wp_customize_url() );
63
-
64
- $p = isset( $_GET['post'] ) && ! empty( $_GET['post'] ) ? get_post( absint( $_GET['post'] ) ) : false;
65
- $names = $p ? shortcode_names( SHORTCODE_NAME, $p->post_content ) : array();
66
- if ( empty( $names ) ) {
67
- return;
68
- }
69
-
70
- $wp_admin_bar->add_menu( array(
71
- 'id' => 'customize',
72
- 'title' => __( 'Customize' ),
73
- 'href' => $customize_url,
74
- 'meta' => array(
75
- 'class' => 'hide-if-no-customize',
76
- ),
77
- ) );
78
- add_action( 'wp_before_admin_bar_render', 'wp_customize_support_script' );
79
- }
80
-
81
- add_action( 'admin_bar_menu', __NAMESPACE__ . '\wp_admin_bar_customize_menu', 35 );
82
-
83
- /**
84
- * Print out required CSS, hooked on the wp_head hook.
85
- */
86
- function wp_head() {
87
-
88
- $widget_repository = new Virtual_Widgets_Repository();
89
-
90
- $styles = array();
91
-
92
- foreach ( $widget_repository->getShortcodes() as $widget ) {
93
- $widget->getCSSRules( true, $styles );
94
- }
95
-
96
- foreach ( $widget_repository->getWidgets() as $widget ) {
97
- $widget->getCSSRules( false, $styles );
98
- }
99
-
100
- if ( ! empty( $styles ) ) {
101
- ?>
102
- <style>
103
- <?php
104
- foreach ( $styles as $rules ) {
105
- foreach ( $rules as $rule ) {
106
- echo "$rule\n"; // Xss ok. raw css output, can not be html escaped.
107
- }
108
- }
109
- ?>
110
- </style>
111
- <?php
112
- }
113
- }
114
-
115
- add_action( 'wp_head', __NAMESPACE__ . '\register_virtual_widgets', 0 );
116
-
117
- /**
118
- * Register virtual widgets for all widgets and shortcodes that are going to be displayed on the page
119
- *
120
- * @return void
121
- *
122
- * @since 4.7
123
- */
124
- function register_virtual_widgets() {
125
- global $post;
126
- global $wp_registered_widgets;
127
-
128
- $repository = new Virtual_Widgets_Repository();
129
-
130
- // check first for shortcode settings.
131
- if ( is_singular() ) {
132
- $names = shortcode_names( SHORTCODE_NAME, $post->post_content );
133
-
134
- foreach ( $names as $name ) {
135
- $meta = shortcode_settings( get_the_ID(), $name );
136
- if ( is_array( $meta ) ) {
137
- $id = WIDGET_BASE_ID . '-shortcode-' . get_the_ID(); // needed to make a unique id for the widget html element.
138
- if ( '' !== $name ) { // if not default name append to the id.
139
- $id .= '-' . sanitize_title( $name ); // sanitize to be on the safe side, not sure where when and how this will be used.
140
- }
141
- $repository->addShortcode( $name, new Virtual_Widget( $id, WIDGET_BASE_ID . '-shortcode', $meta ) );
142
- }
143
- }
144
- }
145
-
146
- $sidebars_widgets = wp_get_sidebars_widgets();
147
-
148
- if ( is_array( $sidebars_widgets ) ) {
149
- foreach ( $sidebars_widgets as $sidebar => $widgets ) {
150
- if ( 'wp_inactive_widgets' === $sidebar || 'orphaned_widgets' === substr( $sidebar, 0, 16 ) ) {
151
- continue;
152
- }
153
-
154
- if ( is_array( $widgets ) ) {
155
- foreach ( $widgets as $widget ) {
156
- $widget_base = _get_widget_id_base( $widget );
157
- if ( WIDGET_BASE_ID === $widget_base ) {
158
- $class = __NAMESPACE__ . '\Widget';
159
- $widgetclass = new $class();
160
- $allsettings = $widgetclass->get_settings();
161
- $settings = isset( $allsettings[ str_replace( $widget_base . '-', '', $widget ) ] ) ? $allsettings[ str_replace( $widget_base . '-', '', $widget ) ] : false;
162
- $repository->addWidget( $widget, new Virtual_Widget( $widget, $widget, $settings ) );
163
- }
164
- }
165
- }
166
- }
167
- }
168
- }
169
-
170
- add_action( 'wp_head', __NAMESPACE__ . '\wp_head' );
171
-
172
- /**
173
- * Enqueue widget related scripts for the widget front-end
174
- *
175
- * @since 4.8
176
- */
177
- function frontend_script() {
178
- $suffix = 'min.js';
179
- if ( defined( 'WP_DEBUG' ) && WP_DEBUG === true ) {
180
- $suffix = 'js';
181
- }
182
- wp_enqueue_script( 'cat-posts-frontend-js', plugins_url( 'js/frontend/category-posts-frontend.' . $suffix, __FILE__ ), array( 'jquery' ), VERSION, true );
183
- }
184
-
185
- /**
186
- * Embed the front end JS in the HTML footer.
187
- *
188
- * @since 4.9
189
- */
190
- function embed_front_end_scripts() {
191
- $suffix = 'min.js';
192
- if ( defined( 'WP_DEBUG' ) && WP_DEBUG === true ) {
193
- $suffix = 'js';
194
- }
195
- echo '<script>';
196
- include __DIR__ . '/js/frontend/category-posts-frontend.' . $suffix;
197
- echo '</script>';
198
- }
199
-
200
- /**
201
- * Enqueue widget related scripts for the widget admin page and customizer.
202
- *
203
- * @param string $hook the name of the admin hook for which the function was triggered.
204
- */
205
- function admin_scripts( $hook ) {
206
-
207
- if ( 'widgets.php' === $hook || 'post.php' === $hook ) { // enqueue only for widget admin and customizer. (add if post.php: fix make widget SiteOrigin Page Builder plugin, GH issue #181)
208
-
209
- /*
210
- * Add script to control admin UX.
211
- */
212
-
213
- // Use unminified version of JS when debuging, and minified when not.
214
- $suffix = 'min.js';
215
- if ( defined( 'WP_DEBUG' ) && WP_DEBUG === true ) {
216
- $suffix = 'js';
217
- }
218
- wp_register_script( 'category-posts-widget-admin-js', plugins_url( 'js/admin/category-posts-widget.' . $suffix, __FILE__ ), array( 'jquery' ), VERSION, true );
219
- wp_enqueue_script( 'category-posts-widget-admin-js' );
220
-
221
- $js_data = array( 'accordion' => false );
222
- $meta = get_user_meta( get_current_user_id(), __NAMESPACE__, true );
223
- if ( is_array( $meta ) && isset( $meta['panels'] ) ) {
224
- $js_data['accordion'] = true;
225
- }
226
- $js_data['template_tags'] = get_template_tags();
227
- $js_data[ __NAMESPACE__ ] = $js_data; // To make accessing the data in JS easier to understand.
228
-
229
- wp_localize_script( 'category-posts-widget-admin-js', 'tiptoppress', $js_data );
230
- wp_enqueue_media();
231
- wp_localize_script( 'category-posts-widget-admin-js', 'cwp_default_thumb_selection', array(
232
- 'frame_title' => __( 'Select a default thumbnail', 'category-posts' ),
233
- 'button_title' => __( 'Select', 'category-posts' ),
234
- 'none' => __( 'None', 'category-posts' ),
235
- ) );
236
- }
237
- }
238
-
239
- add_action( 'admin_enqueue_scripts', __NAMESPACE__ . '\admin_scripts' ); // "called on widgets.php and costumizer since 3.9.
240
-
241
- add_action( 'admin_init', __NAMESPACE__ . '\load_textdomain' );
242
-
243
- /**
244
- * Load plugin textdomain.
245
- *
246
- * @return void
247
- *
248
- * @since 4.1
249
- **/
250
- function load_textdomain() {
251
- load_plugin_textdomain( 'category-posts', false, plugin_basename( dirname( __FILE__ ) ) . '/languages' );
252
- }
253
-
254
- /**
255
- * Add styles for widget admin sections
256
- *
257
- * @since 4.1
258
- **/
259
- function admin_styles() {
260
- wp_enqueue_style( 'cat-posts-admin-styles', plugins_url( 'styles/admin/category-posts-widget.css', __FILE__ ), array(), VERSION, false );
261
- }
262
-
263
- add_action( 'admin_print_styles-widgets.php', __NAMESPACE__ . '\admin_styles' );
264
-
265
- // fix make widget SiteOrigin Page Builder plugin, GH issue #181
266
- add_action('siteorigin_panel_enqueue_admin_scripts', __NAMESPACE__ . '\admin_styles' );
267
-
268
- /**
269
- * Get the tags which might be used in the template.
270
- *
271
- * @since 4.8
272
- *
273
- * @return array Array of strings of the tags.
274
- */
275
- function get_template_tags() {
276
- return array( 'author', 'title', 'date', 'thumb', 'excerpt', 'commentnum', 'post_tag', 'category' );
277
- }
278
-
279
- /**
280
- * Get a regex to parse the template in order to find the tags used in it.
281
- *
282
- * @since 4.8
283
- *
284
- * @return string The template parsing regex.
285
- */
286
- function get_template_regex() {
287
- $tags = get_template_tags();
288
-
289
- $regexp = '';
290
- foreach ( $tags as $t ) {
291
- if ( ! empty( $regexp ) ) {
292
- $regexp .= '|';
293
- }
294
- $regexp .= '%' . $t . '%';
295
- }
296
-
297
- $regexp = '@(' . $regexp . ')@i';
298
-
299
- return $regexp;
300
- }
301
-
302
- /**
303
- * The convert old data structure to current one.
304
- *
305
- * @param array $settings The settings to upgrade.
306
- *
307
- * @return array The settings matching current version standard.
308
- *
309
- * @since 4.8
310
- */
311
- function upgrade_settings( $settings ) {
312
-
313
- if ( 0 === count( $settings ) ) {
314
- return default_settings();
315
- }
316
-
317
- if ( ! isset( $settings['ver'] ) ) {
318
- /*
319
- * Pre 4.9 version.
320
- */
321
-
322
- // Upgrade the hide if empty option.
323
- if ( isset( $settings['hide_if_empty'] ) && $settings['hide_if_empty'] ) {
324
- $settings['no_match_handling'] = 'hide';
325
- } else {
326
- $settings['no_match_handling'] = 'nothing';
327
- }
328
- if ( isset( $settings['hide_if_empty'] ) ) {
329
- unset( $settings['hide_if_empty'] );
330
- }
331
- }
332
-
333
- $settings['ver'] = VERSION;
334
-
335
- // Make sure all "empty" settings have default value.
336
- $settings = wp_parse_args( $settings, default_settings() );
337
-
338
- return $settings;
339
- }
340
-
341
- /**
342
- * Convert pre 4.8 settings into template
343
- *
344
- * @param array $instance Array which contains the various settings.
345
- *
346
- * @since 4.8
347
- */
348
- function convert_settings_to_template( $instance ) {
349
-
350
- $template = '';
351
-
352
- if ( isset( $instance['thumb'] ) && $instance['thumb'] ) {
353
- if ( isset( $instance['thumbTop'] ) && $instance['thumbTop'] ) {
354
- $template .= "%thumb%\n\n";
355
- if ( ! ( isset( $instance['hide_post_titles'] ) && $instance['hide_post_titles'] ) ) {
356
- $template .= "%title%\n";
357
- }
358
- } elseif ( isset( $instance['date'] ) && $instance['date'] ) {
359
- if ( ! ( isset( $instance['hide_post_titles'] ) && $instance['hide_post_titles'] ) ) {
360
- $template .= "%title%\n\n";
361
- }
362
- $template .= "%date%\n\n";
363
- $template .= "%thumb%\n";
364
- } elseif ( ! ( isset( $instance['hide_post_titles'] ) && $instance['hide_post_titles'] ) ) {
365
- $template .= "%thumb%\n%title%\n";
366
- }
367
- } else {
368
- if ( ! ( isset( $instance['hide_post_titles'] ) && $instance['hide_post_titles'] ) ) {
369
- $template .= "%title%\n";
370
- }
371
- if ( isset( $instance['date'] ) && $instance['date'] ) {
372
- $template .= "%date%\n\n";
373
- }
374
- }
375
- if ( isset( $instance['excerpt'] ) && $instance['excerpt'] ) {
376
- $template .= '%excerpt%';
377
- }
378
- if ( isset( $instance['comment_num'] ) && $instance['comment_num'] ) {
379
- $template .= "%commentnum%\n\n";
380
- }
381
- if ( isset( $instance['author'] ) && $instance['author'] ) {
382
- $template .= "%author%\n\n";
383
- }
384
-
385
- return $template;
386
- }
387
-
388
- /*
389
- * Plugin action links section
390
- */
391
-
392
- /**
393
- * Applied to the list of links to display on the plugins page (beside the activate/deactivate links).
394
- *
395
- * @return array of the widget links
396
- *
397
- * @since 4.6.3
398
- */
399
- add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), __NAMESPACE__ . '\add_action_links' );
400
-
401
- /**
402
- * Handle the add links filter, add our links to the links displayed under the plugin_basename
403
- * in the plugin admin screen.
404
- *
405
- * @param array $links The current links about to be displayed.
406
- */
407
- function add_action_links( $links ) {
408
-
409
- if ( ! class_exists( '\\termcategoryPostsPro\\Widget' ) ) {
410
- $pro_link = array(
411
- '<a target="_blank" href="' . esc_url( PRO_URL ) . '">' . esc_html__( 'Get the Pro version', 'category-posts' ) . '</a>',
412
- );
413
-
414
- $links = array_merge( $pro_link, $links );
415
- }
416
-
417
- return $links;
418
- }
419
-
420
- /**
421
- * Register the widget.
422
- */
423
- function register_widget() {
424
- return \register_widget( __NAMESPACE__ . '\Widget' );
425
- }
426
-
427
- add_action( 'widgets_init', __NAMESPACE__ . '\register_widget' );
428
-
429
- /*
430
- * shortcode section.
431
- */
432
-
433
- /**
434
- * Get shortcode settings taking into account if it is being customized
435
- *
436
- * When not customized returns the settings as stored in the meta, but when
437
- * it is customized returns the setting stored in the virtual option used by the customizer
438
- *
439
- * @param string $pid The ID of the post in which the shortcode is.
440
- * @param string $name The name of the shortcode to retun, empty string indicates the nameless.
441
- *
442
- * @return array The shortcode settings if a short code name exists or is an empty string,
443
- * empty array if name not found.
444
- *
445
- * @since 4.6
446
- */
447
- function shortcode_settings( $pid, $name ) {
448
- $meta = get_post_meta( $pid, SHORTCODE_META, true );
449
-
450
- if ( ! empty( $meta ) && ! is_array( reset( $meta ) ) ) {
451
- $meta = array( '' => $meta ); // the conversion.
452
- }
453
-
454
- if ( ! isset( $meta[ $name ] ) ) { // name do not exists? return empty array.
455
- return array();
456
- }
457
-
458
- $instance = $meta[ $name ];
459
- if ( is_customize_preview() ) {
460
- $o = get_option( '_virtual-' . WIDGET_BASE_ID );
461
- if ( is_array( $o ) ) {
462
- $instance = $o[ $pid ][ $name ];
463
- $instance['ver'] = VERSION;
464
- }
465
- }
466
-
467
- if ( isset( $instance['template'] ) && $instance['template'] ) {
468
- ;
469
- } else {
470
- $instance['template'] = convert_settings_to_template( $instance );
471
- }
472
-
473
- $instance = upgrade_settings( $instance );
474
-
475
- return $instance;
476
- }
477
-
478
- /**
479
- * Handle the shortcode
480
- *
481
- * @param array $attr Array of the attributes to the short code, none is expected.
482
- * @param string $content The content enclosed in the shortcode, none is expected.
483
- *
484
- * @return string An HTML of the "widget" based on its settings, actual or customized
485
- */
486
- function shortcode( $attr, $content = null ) {
487
- $repository = new Virtual_Widgets_Repository();
488
-
489
- $shortcodes = $repository->getShortcodes();
490
-
491
- $name = '';
492
- if ( isset( $attr['name'] ) ) {
493
- $name = $attr['name'];
494
- }
495
-
496
- if ( is_singular() ) {
497
- if ( isset( $shortcodes[ $name ] ) ) {
498
- return $shortcodes[ $name ]->getHTML();
499
- }
500
- }
501
-
502
- return '';
503
- }
504
-
505
- add_shortcode( SHORTCODE_NAME, __NAMESPACE__ . '\shortcode' );
506
-
507
- /**
508
- * Find if a specific shortcode is used in a content
509
- *
510
- * @param string $shortcode_name The name of the shortcode.
511
- * @param string $content The content to look at.
512
- *
513
- * @return array An array containing the name attributes of the shortcodes. Empty array is
514
- * an indication there were no shourcodes
515
- *
516
- * @since 4.7
517
- */
518
- function shortcode_names( $shortcode_name, $content ) {
519
-
520
- $names = array();
521
-
522
- $regex_pattern = get_shortcode_regex();
523
- if ( preg_match_all( '/' . $regex_pattern . '/s', $content, $matches ) ) {
524
- foreach ( $matches[2] as $k => $shortcode ) {
525
- if ( SHORTCODE_NAME === $shortcode ) {
526
- $name = '';
527
- $atts = shortcode_parse_atts( $matches[3][ $k ] );
528
- if ( ! empty( $atts['name'] ) ) {
529
- $name = $atts['name'];
530
- }
531
- $names[] = $name;
532
- }
533
- }
534
- }
535
-
536
- return $names;
537
- }
538
-
539
- /**
540
- * Organized way to have the default widget settings accessible
541
- *
542
- * @since 4.6
543
- */
544
- function default_settings() {
545
- return array(
546
- 'title' => __( 'Recent Posts', 'category-posts' ),
547
- 'title_link' => false,
548
- 'title_link_url' => '',
549
- 'hide_title' => false,
550
- 'cat' => 0,
551
- 'num' => get_option( 'posts_per_page' ),
552
- 'offset' => 1,
553
- 'sort_by' => 'date',
554
- 'status' => 'publish',
555
- 'asc_sort_order' => false,
556
- 'exclude_current_post' => false,
557
- 'hideNoThumb' => false,
558
- 'footer_link_text' => '',
559
- 'footer_link' => '',
560
- 'thumb_w' => get_option( 'thumbnail_size_w', 150 ),
561
- 'thumb_fluid_width' => 100,
562
- 'thumb_h' => get_option( 'thumbnail_size_h', 150 ),
563
- 'use_css_cropping' => true,
564
- 'thumb_hover' => 'none',
565
- 'hide_post_titles' => false,
566
- 'excerpt_lines' => 0,
567
- 'excerpt_length' => 0,
568
- 'excerpt_more_text' => __( '...', 'category-posts' ),
569
- 'excerpt_filters' => false,
570
- 'comment_num' => false,
571
- 'date_link' => false,
572
- 'date_format' => '',
573
- 'disable_css' => false,
574
- 'disable_font_styles' => false,
575
- 'show_post_format' => 'none',
576
- 'no_cat_childs' => false,
577
- 'everything_is_link' => false,
578
- 'preset_date_format' => 'sitedateandtime',
579
- 'template' => "%title%\n\n%thumb%",
580
- 'text_do_not_wrap_thumb' => false,
581
- 'enable_loadmore' => false,
582
- 'loadmore_text' => __( 'Load More', 'category-posts' ),
583
- 'loading_text' => __( 'Loading...', 'category-posts' ),
584
- 'date_range' => 'off',
585
- 'start_date' => '',
586
- 'end_date' => '',
587
- 'days_ago' => 30,
588
- 'no_match_handling' => 'nothing',
589
- 'no_match_text' => '',
590
- 'default_thunmbnail' => 0,
591
- 'ver' => VERSION,
592
- );
593
- }
594
-
595
- /**
596
- * Manipulate the relevant meta related to the short code when a post is save
597
- *
598
- * If A post has a short code, a meta holder is created, If it does not the meta holder is deleted
599
- *
600
- * @param integer $pid The post ID of the post being saved.
601
- * @param WP_Post $post The post being saved.
602
- * @return void
603
- *
604
- * @since 4.6
605
- */
606
- function save_post( $pid, $post ) {
607
-
608
- // ignore revisions and auto saves.
609
- if ( wp_is_post_revision( $pid ) || wp_is_post_autosave( $pid ) ) {
610
- return;
611
- }
612
-
613
- $meta = get_post_meta( $pid, SHORTCODE_META, true );
614
- if ( empty( $meta ) ) {
615
- $meta = array();
616
- }
617
-
618
- // check if only one shortcode format - non array of arrays, and convert it.
619
- if ( ! empty( $meta ) && ! is_array( reset( $meta ) ) ) {
620
- $meta = array( '' => $meta ); // the conversion.
621
- }
622
-
623
- $old_names = array_keys( $meta ); // keep list of current shortcode names to delete lter whatever was deleted.
624
- $names = shortcode_names( SHORTCODE_NAME, $post->post_content );
625
-
626
- // remove setting for unused names.
627
- $to_delete = array_diff( $old_names, $names );
628
- foreach ( $to_delete as $k ) {
629
- unset( $meta[ $k ] );
630
- }
631
-
632
- foreach ( $names as $name ) {
633
- if ( ! isset( $meta[ $name ] ) ) {
634
- $meta[ $name ] = default_settings();
635
- }
636
- }
637
-
638
- delete_post_meta( $pid, SHORTCODE_META );
639
- if ( ! empty( $meta ) ) {
640
- add_post_meta( $pid, SHORTCODE_META, $meta, true );
641
- }
642
- }
643
-
644
- add_action( 'save_post', __NAMESPACE__ . '\save_post', 10, 2 );
645
-
646
- /**
647
- * Called on Customizer init to do related registrations.
648
- *
649
- * @param mixed $wp_customize The customizer object.
650
- */
651
- function customize_register( $wp_customize ) {
652
-
653
- require_once __DIR__ . '/class-shortcode-control.php';
654
-
655
- $args = array(
656
- 'post_type' => 'any',
657
- 'post_status' => 'any',
658
- 'posts_per_page' => -1,
659
- 'update_post_term_cache' => false,
660
- 'meta_query' => array(
661
- array(
662
- 'key' => SHORTCODE_META,
663
- 'compare' => 'EXISTS',
664
- ),
665
- ),
666
-
667
- );
668
- $posts = get_posts( $args );
669
-
670
- if ( count( $posts ) > 0 ) {
671
- $wp_customize->add_panel( __NAMESPACE__, array(
672
- 'title' => __( 'Category Posts Shortcode', 'category-posts' ),
673
- 'priority' => 300,
674
- 'capability' => 'edit_theme_options',
675
- ) );
676
-
677
- foreach ( $posts as $p ) {
678
- $widget = new Widget();
679
- $meta = get_post_meta( $p->ID, SHORTCODE_META, true );
680
- if ( ! is_array( $meta ) ) {
681
- continue;
682
- }
683
-
684
- if ( ! is_array( reset( $meta ) ) ) { // 4.6 format.
685
- $meta = array( '' => $meta );
686
- }
687
-
688
- foreach ( $meta as $k => $m ) {
689
-
690
- if ( isset( $m['template'] ) && $m['template'] ) {
691
- ;
692
- } else {
693
- $m['template'] = convert_settings_to_template( $m );
694
- }
695
-
696
- if ( 0 === count( $meta ) ) { // new widget, use defaults.
697
- ;
698
- } else { // updated widgets come from =< 4.6 excerpt filter is on.
699
- if ( ! isset( $m['excerpt_filters'] ) ) {
700
- $m['excerpt_filters'] = 'on';
701
- }
702
- }
703
-
704
- $m = upgrade_settings( $m );
705
-
706
- $section_title = $k;
707
- if ( '' === $section_title ) {
708
- $section_title = __( '[shortcode]', 'category-posts' );
709
- }
710
-
711
- $wp_customize->add_section( __NAMESPACE__ . '-' . $p->id . '-' . $k, array(
712
- 'title' => $section_title,
713
- 'priority' => 10,
714
- 'capability' => 'edit_theme_options',
715
- 'panel' => __NAMESPACE__,
716
- ) );
717
-
718
- ob_start();
719
-
720
- // For the form method to handle generation gracefully, the number needs to be a simple string, and the name might include other chars as well, so for simplisity md5 it.
721
- if ( '' !== $k ) {
722
- $widget->number = $p->ID . '_' . md5( $k );
723
- } else {
724
- $widget->number = $p->ID . '_';
725
- }
726
-
727
- $widget->form( $m );
728
- $form = ob_get_clean();
729
- $form = preg_replace_callback('/<(input|select|textarea)\s+.*name=("|\').*\[\w*\]\[([^\]]*)\][^>]*>/',
730
- function ( $matches ) use ( $p, $wp_customize, $m, $k ) {
731
- $setting = '_virtual-' . WIDGET_BASE_ID . '[' . $p->ID . '][' . $k . '][' . $matches[3] . ']';
732
- if ( ! isset( $m[ $matches[3] ] ) ) {
733
- $m[ $matches[3] ] = null;
734
- }
735
- $wp_customize->add_setting( $setting, array(
736
- 'default' => $m[ $matches[3] ], // set default to current value.
737
- 'type' => 'option',
738
- ) );
739
-
740
- return str_replace( '<' . $matches[1], '<' . $matches[1] . ' data-customize-setting-link="' . $setting . '"', $matches[0] );
741
- },
742
- $form
743
- );
744
-
745
- $args = array(
746
- 'label' => __( 'Layout', 'twentyfourteen' ),
747
- 'section' => __NAMESPACE__ . '-' . $p->id . '-' . $k,
748
- 'form' => $form,
749
- 'settings' => '_virtual-' . WIDGET_BASE_ID . '[' . $p->ID . '][' . $k . '][title]',
750
- 'active_callback' => function () use ( $p ) {
751
- return is_singular() && ( get_the_ID() === $p->ID );
752
- },
753
- );
754
-
755
- if ( get_option( 'page_on_front' ) === $p->ID ) {
756
- $args['active_callback'] = function () {
757
- return is_front_page();
758
- };
759
- }
760
-
761
- $sc = new ShortCode_Control(
762
- $wp_customize,
763
- '_virtual-' . WIDGET_BASE_ID . '[' . $p->ID . '][' . $k . '][title]',
764
- $args
765
- );
766
-
767
- if ( '' !== $k ) {
768
- $sc->title_postfix = ' ' . $k;
769
- }
770
- $wp_customize->add_control( $sc );
771
- }
772
- }
773
- }
774
- }
775
-
776
- add_action( 'customize_register', __NAMESPACE__ . '\customize_register' );
777
-
778
- /**
779
- * Save the virtual option used by the customizer into the proper meta values.
780
- *
781
- * The customizer actually saves only the changed values, so a merge needs to be done.
782
- * After everything is updated the virtual option is deleted to leave a clean slate
783
- *
784
- * @return void
785
- *
786
- * @since 4.6
787
- */
788
- function customize_save_after() {
789
- $virtual = get_option( '_virtual-' . WIDGET_BASE_ID );
790
-
791
- if ( is_array( $virtual ) ) {
792
- foreach ( $virtual as $pid => $instance ) {
793
- $meta = get_post_meta( $pid, SHORTCODE_META, true );
794
- if ( ! empty( $meta ) && ! is_array( reset( $meta ) ) ) {
795
- $meta = array( '' => $meta ); // the conversion.
796
- }
797
-
798
- foreach ( $instance as $name => $new ) {
799
- if ( isset( $meta[ $name ] ) ) { // unlikely but maybe that short code was deleted by other session.
800
- $meta[ $name ] = array_merge( $meta[ $name ], $new );
801
- }
802
- }
803
- }
804
- update_post_meta( $pid, SHORTCODE_META, $meta );
805
- }
806
-
807
- delete_option( '_virtual-' . WIDGET_BASE_ID );
808
- }
809
-
810
- add_action( 'customize_save_after', __NAMESPACE__ . '\customize_save_after', 100 );
811
-
812
- /*
813
- * tinymce related functions.
814
- */
815
-
816
- /**
817
- * Uninstall handler, cleanup DB from options and meta
818
- *
819
- * @return void
820
- *
821
- * @since 4.7
822
- */
823
- function uninstall() {
824
- delete_option( 'widget-' . WIDGET_BASE_ID ); // delete the option storing the widget options.
825
- delete_post_meta_by_key( SHORTCODE_META ); // delete the meta storing the shortcode.
826
- delete_metadata( 'user', 0, __NAMESPACE__, '', true ); // delete all user metadata.
827
- }
828
-
829
- register_uninstall_hook( __FILE__, __NAMESPACE__ . 'uninstall' );
830
-
831
- /**
832
- * Register the tinymce shortcode plugin
833
- *
834
- * @param array $plugin_array An array containing the current plugins to be used by tinymce.
835
- *
836
- * @return array An array containing the plugins to be used by tinymce, our plugin added to the $plugin_array parameter
837
- *
838
- * @since 4.7
839
- */
840
- function mce_external_plugins( $plugin_array ) {
841
- if ( current_user_can( 'edit_theme_options' ) ) { // don't load the code if the user can not customize the shortcode.
842
- // enqueue TinyMCE plugin script with its ID.
843
- $meta = get_user_meta( get_current_user_id(), __NAMESPACE__, true );
844
- if ( is_array( $meta ) && isset( $meta['editor'] ) ) {
845
- ;
846
- } else {
847
- $plugin_array[ __NAMESPACE__ ] = plugins_url( 'js/admin/tinymce.min.js?ver=' . VERSION, __FILE__ );
848
- }
849
- }
850
-
851
- return $plugin_array;
852
- }
853
-
854
- add_filter( 'mce_external_plugins', __NAMESPACE__ . '\mce_external_plugins' );
855
-
856
- /**
857
- * Register the tinymce buttons for the add shortcode
858
- *
859
- * @param array $buttons An array containing the current buttons to be used by tinymce.
860
- *
861
- * @return array An array containing the buttons to be used by tinymce, our button added to the $buttons parameter
862
- *
863
- * @since 4.7
864
- */
865
- function mce_buttons( $buttons ) {
866
- if ( current_user_can( 'edit_theme_options' ) ) { // don't load the code if the user can not customize the shortcode
867
- // register buttons with their id.
868
- $meta = get_user_meta( get_current_user_id(), __NAMESPACE__, true );
869
- if ( is_array( $meta ) && isset( $meta['editor'] ) ) {
870
- ;
871
- } else {
872
- array_push( $buttons, __NAMESPACE__ );
873
- }
874
- }
875
-
876
- return $buttons;
877
- }
878
-
879
- add_filter( 'mce_buttons', __NAMESPACE__ . '\mce_buttons' );
880
-
881
- /**
882
- * Register the tinymcetranslation file
883
- *
884
- * @param array $locales An array containing the current translations to be used by tinymce.
885
- *
886
- * @return array An array containing the translations to be used by tinymce, our localization added to the $locale parameter
887
- *
888
- * @since 4.7
889
- */
890
- function mce_external_languages( $locales ) {
891
- if ( current_user_can( 'edit_theme_options' ) ) { // don't load the code if the user can not customize the shortcode.
892
- $meta = get_user_meta( get_current_user_id(), __NAMESPACE__, true );
893
- if ( is_array( $meta ) && isset( $meta['editor'] ) ) {
894
- ;
895
- } else {
896
- $locales['cat-posts'] = plugin_dir_path( __FILE__ ) . 'tinymce_translations.php';
897
- }
898
- }
899
-
900
- return $locales;
901
- }
902
-
903
- add_filter( 'mce_external_languages', __NAMESPACE__ . '\mce_external_languages' );
904
-
905
- /*
906
- * user profile related functions.
907
- */
908
-
909
- add_action( 'show_user_profile', __NAMESPACE__ . '\show_user_profile' );
910
- add_action( 'edit_user_profile', __NAMESPACE__ . '\show_user_profile' );
911
-
912
- /**
913
- * Display the user specific setting on its profile page
914
- *
915
- * @param WP_user $user The user for which the profile page displays information.
916
- *
917
- * @since 4.7
918
- */
919
- function show_user_profile( $user ) {
920
-
921
- if ( ! current_user_can( 'edit_user', $user->ID ) ) {
922
- return;
923
- }
924
-
925
- if ( ! current_user_can( 'edit_theme_options', $user->ID ) ) {
926
- return;
927
- }
928
-
929
- $meta = get_the_author_meta( __NAMESPACE__, $user->ID );
930
-
931
- if ( empty( $meta ) ) {
932
- $meta = array();
933
- }
934
-
935
- $accordion = false;
936
- if ( isset( $meta['panels'] ) ) {
937
- $accordion = true;
938
- }
939
-
940
- $editor = false;
941
- if ( isset( $meta['editor'] ) ) {
942
- $editor = true;
943
- }
944
- ?>
945
- <h3 id="<?php echo __NAMESPACE__; ?>"><?php esc_html_e( 'Category Posts Widget behaviour settings', 'category-posts' ); ?></h3>
946
-
947
- <table class="form-table">
948
- <tr>
949
- <th><label for="<?php echo __NAMESPACE__; ?>[panels]"><?php esc_html_e( 'Open panels behavior', 'category-posts' ); ?></label></th>
950
- <td>
951
- <input type="checkbox" name="<?php echo __NAMESPACE__; ?>[panels]" id="<?php echo __NAMESPACE__; ?>[panels]" <?php checked( $accordion ); ?>>
952
- <label for=<?php echo __NAMESPACE__; ?>[panels]><?php esc_html_e( 'Close the currently open panel when opening a new one', 'category-posts' ); ?></label>
953
- </td>
954
- </tr>
955
- <tr>
956
- <th><label for="<?php echo __NAMESPACE__; ?>[editor]"><?php esc_html_e( 'Visual editor button', 'category-posts' ); ?></label></th>
957
- <td>
958
- <input type="checkbox" name="<?php echo __NAMESPACE__; ?>[editor]" id="<?php echo __NAMESPACE__; ?>[editor]" <?php checked( $editor ); ?>>
959
- <label for="<?php echo __NAMESPACE__; ?>[editor]"><?php esc_html_e( 'Hide the "insert shortcode" button from the editor', 'category-posts' ); ?></label>
960
- </td>
961
- </tr>
962
- </table>
963
- <?php
964
- }
965
-
966
- add_action( 'personal_options_update', __NAMESPACE__ . '\personal_options_update' );
967
- add_action( 'edit_user_profile_update', __NAMESPACE__ . '\personal_options_update' );
968
-
969
- /**
970
- * Handles saving user related settings as was set in the profile page.
971
- *
972
- * @param int $user_id the ID of the user for which the data is saved..
973
- *
974
- * @since 4.7
975
- */
976
- function personal_options_update( $user_id ) {
977
-
978
- if ( ! current_user_can( 'edit_user', $user_id ) ) {
979
- return false;
980
- }
981
-
982
- if ( ! current_user_can( 'edit_theme_options', $user_id ) ) {
983
- return;
984
- }
985
-
986
- if ( isset( $_POST[ __NAMESPACE__ ] ) ) {
987
- update_user_meta( $user_id, __NAMESPACE__, wp_unslash( $_POST[ __NAMESPACE__ ] ) );
988
- } else {
989
- delete_user_meta( $user_id, __NAMESPACE__ );
990
- }
991
- }
992
-
993
- add_action( 'wp_loaded', __NAMESPACE__ . '\wp_loaded' );
994
-
995
- /**
996
- * Run after WordPress finished bootstrapping, do whatever is needed at this stage
997
- * like registering the meta.
998
- */
999
- function wp_loaded() {
1000
- register_meta( 'post', SHORTCODE_META, null, '__return_false' ); // do not allow access to the shortcode meta
1001
- // use the pre 4.6 format for backward compatibility.
1002
- }
1
+ <?php
2
+ /**
3
+ * Main file of the plugin
4
+ *
5
+ * @package categoryposts.
6
+ *
7
+ * @since 1.0
8
+ */
9
+
10
+ /*
11
+ Plugin Name: Category Posts Widget
12
+ Plugin URI: https://wordpress.org/plugins/category-posts/
13
+ Description: Adds a widget that shows the most recent posts from a single category.
14
+ Author: TipTopPress
15
+ Version: 4.9.4
16
+ Author URI: http://tiptoppress.com
17
+ Text Domain: category-posts
18
+ Domain Path: /languages
19
+ */
20
+
21
+ namespace categoryPosts;
22
+
23
+ // Don't call the file directly.
24
+ if ( ! defined( 'ABSPATH' ) ) {
25
+ exit;
26
+ }
27
+
28
+ const VERSION = '4.9.4';
29
+ const DOC_URL = 'http://tiptoppress.com/category-posts-widget/documentation-4-9/';
30
+ const PRO_URL = 'http://tiptoppress.com/term-and-category-based-posts-widget/';
31
+ const SUPPORT_URL = 'https://wordpress.org/support/plugin/category-posts/';
32
+ const SHORTCODE_NAME = 'catposts';
33
+ const SHORTCODE_META = 'categoryPosts-shorcode';
34
+ const WIDGET_BASE_ID = 'category-posts';
35
+
36
+ require_once __DIR__ . '/class-virtual-widget.php';
37
+ require_once __DIR__ . '/class-virtual-widgets-repository.php';
38
+ require_once __DIR__ . '/class-widget.php';
39
+ require_once __DIR__ . '/loadmore.php';
40
+ require_once __DIR__ . '/localizeddate.php';
41
+
42
+ /**
43
+ * Adds the "Customize" link to the Toolbar on edit mode.
44
+ *
45
+ * @since 4.6
46
+ */
47
+ function wp_admin_bar_customize_menu() {
48
+ global $wp_admin_bar;
49
+
50
+ if ( ! isset( $_GET['action'] ) || ( 'edit' !== $_GET['action'] ) ) {
51
+ return;
52
+ }
53
+
54
+ if ( ! current_user_can( 'customize' ) || ! is_admin() || ! is_user_logged_in() || ! is_admin_bar_showing() ) {
55
+ return;
56
+ }
57
+
58
+ $current_url = '';
59
+ if ( isset( $_GET['post'] ) && ( '' !== $_GET['post'] ) ) {
60
+ $current_url = get_permalink( absint( $_GET['post'] ) );
61
+ }
62
+ $customize_url = add_query_arg( 'url', rawurlencode( $current_url ), wp_customize_url() );
63
+
64
+ $p = isset( $_GET['post'] ) && ! empty( $_GET['post'] ) ? get_post( absint( $_GET['post'] ) ) : false;
65
+ $names = $p ? shortcode_names( SHORTCODE_NAME, $p->post_content ) : array();
66
+ if ( empty( $names ) ) {
67
+ return;
68
+ }
69
+
70
+ $wp_admin_bar->add_menu( array(
71
+ 'id' => 'customize',
72
+ 'title' => __( 'Customize' ),
73
+ 'href' => $customize_url,
74
+ 'meta' => array(
75
+ 'class' => 'hide-if-no-customize',
76
+ ),
77
+ ) );
78
+ add_action( 'wp_before_admin_bar_render', 'wp_customize_support_script' );
79
+ }
80
+
81
+ add_action( 'admin_bar_menu', __NAMESPACE__ . '\wp_admin_bar_customize_menu', 35 );
82
+
83
+ /**
84
+ * Print out required CSS, hooked on the wp_head hook.
85
+ */
86
+ function wp_head() {
87
+
88
+ $widget_repository = new Virtual_Widgets_Repository();
89
+
90
+ $styles = array();
91
+
92
+ foreach ( $widget_repository->getShortcodes() as $widget ) {
93
+ $widget->getCSSRules( true, $styles );
94
+ }
95
+
96
+ foreach ( $widget_repository->getWidgets() as $widget ) {
97
+ $widget->getCSSRules( false, $styles );
98
+ }
99
+
100
+ if ( ! empty( $styles ) ) {
101
+ ?>
102
+ <style>
103
+ <?php
104
+ foreach ( $styles as $rules ) {
105
+ foreach ( $rules as $rule ) {
106
+ echo "$rule\n"; // Xss ok. raw css output, can not be html escaped.
107
+ }
108
+ }
109
+ ?>
110
+ </style>
111
+ <?php
112
+ }
113
+ }
114
+
115
+ add_action( 'wp_head', __NAMESPACE__ . '\register_virtual_widgets', 0 );
116
+
117
+ /**
118
+ * Register virtual widgets for all widgets and shortcodes that are going to be displayed on the page
119
+ *
120
+ * @return void
121
+ *
122
+ * @since 4.7
123
+ */
124
+ function register_virtual_widgets() {
125
+ global $post;
126
+ global $wp_registered_widgets;
127
+
128
+ $repository = new Virtual_Widgets_Repository();
129
+
130
+ // check first for shortcode settings.
131
+ if ( is_singular() ) {
132
+ $names = shortcode_names( SHORTCODE_NAME, $post->post_content );
133
+
134
+ foreach ( $names as $name ) {
135
+ $meta = shortcode_settings( get_the_ID(), $name );
136
+ if ( is_array( $meta ) ) {
137
+ $id = WIDGET_BASE_ID . '-shortcode-' . get_the_ID(); // needed to make a unique id for the widget html element.
138
+ if ( '' !== $name ) { // if not default name append to the id.
139
+ $id .= '-' . sanitize_title( $name ); // sanitize to be on the safe side, not sure where when and how this will be used.
140
+ }
141
+ $repository->addShortcode( $name, new Virtual_Widget( $id, WIDGET_BASE_ID . '-shortcode', $meta ) );
142
+ }
143
+ }
144
+ }
145
+
146
+ $sidebars_widgets = wp_get_sidebars_widgets();
147
+
148
+ if ( is_array( $sidebars_widgets ) ) {
149
+ foreach ( $sidebars_widgets as $sidebar => $widgets ) {
150
+ if ( 'wp_inactive_widgets' === $sidebar || 'orphaned_widgets' === substr( $sidebar, 0, 16 ) ) {
151
+ continue;
152
+ }
153
+
154
+ if ( is_array( $widgets ) ) {
155
+ foreach ( $widgets as $widget ) {
156
+ $widget_base = _get_widget_id_base( $widget );
157
+ if ( WIDGET_BASE_ID === $widget_base ) {
158
+ $class = __NAMESPACE__ . '\Widget';
159
+ $widgetclass = new $class();
160
+ $allsettings = $widgetclass->get_settings();
161
+ $settings = isset( $allsettings[ str_replace( $widget_base . '-', '', $widget ) ] ) ? $allsettings[ str_replace( $widget_base . '-', '', $widget ) ] : false;
162
+ $repository->addWidget( $widget, new Virtual_Widget( $widget, $widget, $settings ) );
163
+ }
164
+ }
165
+ }
166
+ }
167
+ }
168
+ }
169
+
170
+ add_action( 'wp_head', __NAMESPACE__ . '\wp_head' );
171
+
172
+ /**
173
+ * Enqueue widget related scripts for the widget front-end
174
+ *
175
+ * @since 4.8
176
+ */
177
+ function frontend_script() {
178
+ $suffix = 'min.js';
179
+ if ( defined( 'WP_DEBUG' ) && WP_DEBUG === true ) {
180
+ $suffix = 'js';
181
+ }
182
+ wp_enqueue_script( 'cat-posts-frontend-js', plugins_url( 'js/frontend/category-posts-frontend.' . $suffix, __FILE__ ), array( 'jquery' ), VERSION, true );
183
+ }
184
+
185
+ /**
186
+ * Embed the front end JS in the HTML footer.
187
+ *
188
+ * @since 4.9
189
+ */
190
+ function embed_front_end_scripts() {
191
+ $suffix = 'min.js';
192
+ if ( defined( 'WP_DEBUG' ) && WP_DEBUG === true ) {
193
+ $suffix = 'js';
194
+ }
195
+ echo '<script>';
196
+ include __DIR__ . '/js/frontend/category-posts-frontend.' . $suffix;
197
+ echo '</script>';
198
+ }
199
+
200
+ /**
201
+ * Enqueue widget related scripts for the widget admin page and customizer.
202
+ *
203
+ * @param string $hook the name of the admin hook for which the function was triggered.
204
+ */
205
+ function admin_scripts( $hook ) {
206
+
207
+ if ( 'widgets.php' === $hook || 'post.php' === $hook ) { // enqueue only for widget admin and customizer. (add if post.php: fix make widget SiteOrigin Page Builder plugin, GH issue #181)
208
+
209
+ /*
210
+ * Add script to control admin UX.
211
+ */
212
+
213
+ // Use unminified version of JS when debuging, and minified when not.
214
+ $suffix = 'min.js';
215
+ if ( defined( 'WP_DEBUG' ) && WP_DEBUG === true ) {
216
+ $suffix = 'js';
217
+ }
218
+ wp_register_script( 'category-posts-widget-admin-js', plugins_url( 'js/admin/category-posts-widget.' . $suffix, __FILE__ ), array( 'jquery' ), VERSION, true );
219
+ wp_enqueue_script( 'category-posts-widget-admin-js' );
220
+
221
+ $js_data = array( 'accordion' => false );
222
+ $meta = get_user_meta( get_current_user_id(), __NAMESPACE__, true );
223
+ if ( is_array( $meta ) && isset( $meta['panels'] ) ) {
224
+ $js_data['accordion'] = true;
225
+ }
226
+ $js_data['template_tags'] = get_template_tags();
227
+ $js_data[ __NAMESPACE__ ] = $js_data; // To make accessing the data in JS easier to understand.
228
+
229
+ wp_localize_script( 'category-posts-widget-admin-js', 'tiptoppress', $js_data );
230
+ wp_enqueue_media();
231
+ wp_localize_script( 'category-posts-widget-admin-js', 'cwp_default_thumb_selection', array(
232
+ 'frame_title' => __( 'Select a default thumbnail', 'category-posts' ),
233
+ 'button_title' => __( 'Select', 'category-posts' ),
234
+ 'none' => __( 'None', 'category-posts' ),
235
+ ) );
236
+ }
237
+ }
238
+
239
+ add_action( 'admin_enqueue_scripts', __NAMESPACE__ . '\admin_scripts' ); // "called on widgets.php and costumizer since 3.9.
240
+
241
+ add_action( 'admin_init', __NAMESPACE__ . '\load_textdomain' );
242
+
243
+ /**
244
+ * Load plugin textdomain.
245
+ *
246
+ * @return void
247
+ *
248
+ * @since 4.1
249
+ **/
250
+ function load_textdomain() {
251
+ load_plugin_textdomain( 'category-posts', false, plugin_basename( dirname( __FILE__ ) ) . '/languages' );
252
+ }
253
+
254
+ /**
255
+ * Add styles for widget admin sections
256
+ *
257
+ * @since 4.1
258
+ **/
259
+ function admin_styles() {
260
+ wp_enqueue_style( 'cat-posts-admin-styles', plugins_url( 'styles/admin/category-posts-widget.css', __FILE__ ), array(), VERSION, false );
261
+ }
262
+
263
+ add_action( 'admin_print_styles-widgets.php', __NAMESPACE__ . '\admin_styles' );
264
+
265
+ // fix make widget SiteOrigin Page Builder plugin, GH issue #181
266
+ add_action('siteorigin_panel_enqueue_admin_scripts', __NAMESPACE__ . '\admin_styles' );
267
+
268
+ /**
269
+ * Get the tags which might be used in the template.
270
+ *
271
+ * @since 4.8
272
+ *
273
+ * @return array Array of strings of the tags.
274
+ */
275
+ function get_template_tags() {
276
+ return array( 'author', 'title', 'date', 'thumb', 'excerpt', 'commentnum', 'post_tag', 'category' );
277
+ }
278
+
279
+ /**
280
+ * Get a regex to parse the template in order to find the tags used in it.
281
+ *
282
+ * @since 4.8
283
+ *
284
+ * @return string The template parsing regex.
285
+ */
286
+ function get_template_regex() {
287
+ $tags = get_template_tags();
288
+
289
+ $regexp = '';
290
+ foreach ( $tags as $t ) {
291
+ if ( ! empty( $regexp ) ) {
292
+ $regexp .= '|';
293
+ }
294
+ $regexp .= '%' . $t . '%';
295
+ }
296
+
297
+ $regexp = '@(' . $regexp . ')@i';
298
+
299
+ return $regexp;
300
+ }
301
+
302
+ /**
303
+ * The convert old data structure to current one.
304
+ *
305
+ * @param array $settings The settings to upgrade.
306
+ *
307
+ * @return array The settings matching current version standard.
308
+ *
309
+ * @since 4.8
310
+ */
311
+ function upgrade_settings( $settings ) {
312
+
313
+ if ( 0 === count( $settings ) ) {
314
+ return default_settings();
315
+ }
316
+
317
+ if ( ! isset( $settings['ver'] ) ) {
318
+ /*
319
+ * Pre 4.9 version.
320
+ */
321
+
322
+ // Upgrade the hide if empty option.
323
+ if ( isset( $settings['hide_if_empty'] ) && $settings['hide_if_empty'] ) {
324
+ $settings['no_match_handling'] = 'hide';
325
+ } else {
326
+ $settings['no_match_handling'] = 'nothing';
327
+ }
328
+ if ( isset( $settings['hide_if_empty'] ) ) {
329
+ unset( $settings['hide_if_empty'] );
330
+ }
331
+ }
332
+
333
+ $settings['ver'] = VERSION;
334
+
335
+ // Make sure all "empty" settings have default value.
336
+ $settings = wp_parse_args( $settings, default_settings() );
337
+
338
+ return $settings;
339
+ }
340
+
341
+ /**
342
+ * Convert pre 4.8 settings into template
343
+ *
344
+ * @param array $instance Array which contains the various settings.
345
+ *
346
+ * @since 4.8
347
+ */
348
+ function convert_settings_to_template( $instance ) {
349
+
350
+ $template = '';
351
+
352
+ if ( isset( $instance['thumb'] ) && $instance['thumb'] ) {
353
+ if ( isset( $instance['thumbTop'] ) && $instance['thumbTop'] ) {
354
+ $template .= "%thumb%\n\n";
355
+ if ( ! ( isset( $instance['hide_post_titles'] ) && $instance['hide_post_titles'] ) ) {
356
+ $template .= "%title%\n";
357
+ }
358
+ } elseif ( isset( $instance['date'] ) && $instance['date'] ) {
359
+ if ( ! ( isset( $instance['hide_post_titles'] ) && $instance['hide_post_titles'] ) ) {
360
+ $template .= "%title%\n\n";
361
+ }
362
+ $template .= "%date%\n\n";
363
+ $template .= "%thumb%\n";
364
+ } elseif ( ! ( isset( $instance['hide_post_titles'] ) && $instance['hide_post_titles'] ) ) {
365
+ $template .= "%thumb%\n%title%\n";
366
+ }
367
+ } else {
368
+ if ( ! ( isset( $instance['hide_post_titles'] ) && $instance['hide_post_titles'] ) ) {
369
+ $template .= "%title%\n";
370
+ }
371
+ if ( isset( $instance['date'] ) && $instance['date'] ) {
372
+ $template .= "%date%\n\n";
373
+ }
374
+ }
375
+ if ( isset( $instance['excerpt'] ) && $instance['excerpt'] ) {
376
+ $template .= '%excerpt%';
377
+ }
378
+ if ( isset( $instance['comment_num'] ) && $instance['comment_num'] ) {
379
+ $template .= "%commentnum%\n\n";
380
+ }
381
+ if ( isset( $instance['author'] ) && $instance['author'] ) {
382
+ $template .= "%author%\n\n";
383
+ }
384
+
385
+ return $template;
386
+ }
387
+
388
+ /*
389
+ * Plugin action links section
390
+ */
391
+
392
+ /**
393
+ * Applied to the list of links to display on the plugins page (beside the activate/deactivate links).
394
+ *
395
+ * @return array of the widget links
396
+ *
397
+ * @since 4.6.3
398
+ */
399
+ add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), __NAMESPACE__ . '\add_action_links' );
400
+
401
+ /**
402
+ * Handle the add links filter, add our links to the links displayed under the plugin_basename
403
+ * in the plugin admin screen.
404
+ *
405
+ * @param array $links The current links about to be displayed.
406
+ */
407
+ function add_action_links( $links ) {
408
+
409
+ if ( ! class_exists( '\\termcategoryPostsPro\\Widget' ) ) {
410
+ $pro_link = array(
411
+ '<a target="_blank" href="' . esc_url( PRO_URL ) . '">' . esc_html__( 'Get the Pro version', 'category-posts' ) . '</a>',
412
+ );
413
+
414
+ $links = array_merge( $pro_link, $links );
415
+ }
416
+
417
+ return $links;
418
+ }
419
+
420
+ /**
421
+ * Register the widget.
422
+ */
423
+ function register_widget() {
424
+ return \register_widget( __NAMESPACE__ . '\Widget' );
425
+ }
426
+
427
+ add_action( 'widgets_init', __NAMESPACE__ . '\register_widget' );
428
+
429
+ /*
430
+ * shortcode section.
431
+ */
432
+
433
+ /**
434
+ * Get shortcode settings taking into account if it is being customized
435
+ *
436
+ * When not customized returns the settings as stored in the meta, but when
437
+ * it is customized returns the setting stored in the virtual option used by the customizer
438
+ *
439
+ * @param string $pid The ID of the post in which the shortcode is.
440
+ * @param string $name The name of the shortcode to retun, empty string indicates the nameless.
441
+ *
442
+ * @return array The shortcode settings if a short code name exists or is an empty string,
443
+ * empty array if name not found.
444
+ *
445
+ * @since 4.6
446
+ */
447
+ function shortcode_settings( $pid, $name ) {
448
+ $meta = get_post_meta( $pid, SHORTCODE_META, true );
449
+
450
+ if ( ! empty( $meta ) && ! is_array( reset( $meta ) ) ) {
451
+ $meta = array( '' => $meta ); // the conversion.
452
+ }
453
+
454
+ if ( ! isset( $meta[ $name ] ) ) { // name do not exists? return empty array.
455
+ return array();
456
+ }
457
+
458
+ $instance = $meta[ $name ];
459
+ if ( is_customize_preview() ) {
460
+ $o = get_option( '_virtual-' . WIDGET_BASE_ID );
461
+ if ( is_array( $o ) ) {
462
+ $instance = $o[ $pid ][ $name ];
463
+ $instance['ver'] = VERSION;
464
+ }
465
+ }
466
+
467
+ if ( isset( $instance['template'] ) && $instance['template'] ) {
468
+ ;
469
+ } else {
470
+ $instance['template'] = convert_settings_to_template( $instance );
471
+ }
472
+
473
+ $instance = upgrade_settings( $instance );
474
+
475
+ return $instance;
476
+ }
477
+
478
+ /**
479
+ * Handle the shortcode
480
+ *
481
+ * @param array $attr Array of the attributes to the short code, none is expected.
482
+ * @param string $content The content enclosed in the shortcode, none is expected.
483
+ *
484
+ * @return string An HTML of the "widget" based on its settings, actual or customized
485
+ */
486
+ function shortcode( $attr, $content = null ) {
487
+ $repository = new Virtual_Widgets_Repository();
488
+
489
+ $shortcodes = $repository->getShortcodes();
490
+
491
+ $name = '';
492
+ if ( isset( $attr['name'] ) ) {
493
+ $name = $attr['name'];
494
+ }
495
+
496
+ if ( is_singular() ) {
497
+ if ( isset( $shortcodes[ $name ] ) ) {
498
+ return $shortcodes[ $name ]->getHTML();
499
+ }
500
+ }
501
+
502
+ return '';
503
+ }
504
+
505
+ add_shortcode( SHORTCODE_NAME, __NAMESPACE__ . '\shortcode' );
506
+
507
+ /**
508
+ * Find if a specific shortcode is used in a content
509
+ *
510
+ * @param string $shortcode_name The name of the shortcode.
511
+ * @param string $content The content to look at.
512
+ *
513
+ * @return array An array containing the name attributes of the shortcodes. Empty array is
514
+ * an indication there were no shourcodes
515
+ *
516
+ * @since 4.7
517
+ */
518
+ function shortcode_names( $shortcode_name, $content ) {
519
+
520
+ $names = array();
521
+
522
+ $regex_pattern = get_shortcode_regex();
523
+ if ( preg_match_all( '/' . $regex_pattern . '/s', $content, $matches ) ) {
524
+ foreach ( $matches[2] as $k => $shortcode ) {
525
+ if ( SHORTCODE_NAME === $shortcode ) {
526
+ $name = '';
527
+ $atts = shortcode_parse_atts( $matches[3][ $k ] );
528
+ if ( ! empty( $atts['name'] ) ) {
529
+ $name = $atts['name'];
530
+ }
531
+ $names[] = $name;
532
+ }
533
+ }
534
+ }
535
+
536
+ return $names;
537
+ }
538
+
539
+ /**
540
+ * Organized way to have the default widget settings accessible
541
+ *
542
+ * @since 4.6
543
+ */
544
+ function default_settings() {
545
+ return array(
546
+ 'title' => __( 'Recent Posts', 'category-posts' ),
547
+ 'title_link' => false,
548
+ 'title_link_url' => '',
549
+ 'hide_title' => false,
550
+ 'cat' => 0,
551
+ 'num' => get_option( 'posts_per_page' ),
552
+ 'offset' => 1,
553
+ 'sort_by' => 'date',
554
+ 'status' => 'publish',
555
+ 'asc_sort_order' => false,
556
+ 'exclude_current_post' => false,
557
+ 'hideNoThumb' => false,
558
+ 'footer_link_text' => '',
559
+ 'footer_link' => '',
560
+ 'thumb_w' => get_option( 'thumbnail_size_w', 150 ),
561
+ 'thumb_fluid_width' => 100,
562
+ 'thumb_h' => get_option( 'thumbnail_size_h', 150 ),
563
+ 'use_css_cropping' => true,
564
+ 'thumb_hover' => 'none',
565
+ 'hide_post_titles' => false,
566
+ 'excerpt_lines' => 0,
567
+ 'excerpt_length' => 0,
568
+ 'excerpt_more_text' => __( '...', 'category-posts' ),
569
+ 'excerpt_filters' => false,
570
+ 'comment_num' => false,
571
+ 'date_link' => false,
572
+ 'date_format' => '',
573
+ 'disable_css' => false,
574
+ 'disable_font_styles' => false,
575
+ 'show_post_format' => 'none',
576
+ 'no_cat_childs' => false,
577
+ 'everything_is_link' => false,
578
+ 'preset_date_format' => 'sitedateandtime',
579
+ 'template' => "%title%\n\n%thumb%",
580
+ 'text_do_not_wrap_thumb' => false,
581
+ 'enable_loadmore' => false,
582
+ 'loadmore_text' => __( 'Load More', 'category-posts' ),
583
+ 'loading_text' => __( 'Loading...', 'category-posts' ),
584
+ 'date_range' => 'off',
585
+ 'start_date' => '',
586
+ 'end_date' => '',
587
+ 'days_ago' => 30,
588
+ 'no_match_handling' => 'nothing',
589
+ 'no_match_text' => '',
590
+ 'default_thunmbnail' => 0,
591
+ 'ver' => VERSION,
592
+ );
593
+ }
594
+
595
+ /**
596
+ * Manipulate the relevant meta related to the short code when a post is save
597
+ *
598
+ * If A post has a short code, a meta holder is created, If it does not the meta holder is deleted
599
+ *
600
+ * @param integer $pid The post ID of the post being saved.
601
+ * @param WP_Post $post The post being saved.
602
+ * @return void
603
+ *
604
+ * @since 4.6
605
+ */
606
+ function save_post( $pid, $post ) {
607
+
608
+ // ignore revisions and auto saves.
609
+ if ( wp_is_post_revision( $pid ) || wp_is_post_autosave( $pid ) ) {
610
+ return;
611
+ }
612
+
613
+ $meta = get_post_meta( $pid, SHORTCODE_META, true );
614
+ if ( empty( $meta ) ) {
615
+ $meta = array();
616
+ }
617
+
618
+ // check if only one shortcode format - non array of arrays, and convert it.
619
+ if ( ! empty( $meta ) && ! is_array( reset( $meta ) ) ) {
620
+ $meta = array( '' => $meta ); // the conversion.
621
+ }
622
+
623
+ $old_names = array_keys( $meta ); // keep list of current shortcode names to delete lter whatever was deleted.
624
+ $names = shortcode_names( SHORTCODE_NAME, $post->post_content );
625
+
626
+ // remove setting for unused names.
627
+ $to_delete = array_diff( $old_names, $names );
628
+ foreach ( $to_delete as $k ) {
629
+ unset( $meta[ $k ] );
630
+ }
631
+
632
+ foreach ( $names as $name ) {
633
+ if ( ! isset( $meta[ $name ] ) ) {
634
+ $meta[ $name ] = default_settings();
635
+ }
636
+ }
637
+
638
+ delete_post_meta( $pid, SHORTCODE_META );
639
+ if ( ! empty( $meta ) ) {
640
+ add_post_meta( $pid, SHORTCODE_META, $meta, true );
641
+ }
642
+ }
643
+
644
+ add_action( 'save_post', __NAMESPACE__ . '\save_post', 10, 2 );
645
+
646
+ /**
647
+ * Called on Customizer init to do related registrations.
648
+ *
649
+ * @param mixed $wp_customize The customizer object.
650
+ */
651
+ function customize_register( $wp_customize ) {
652
+
653
+ require_once __DIR__ . '/class-shortcode-control.php';
654
+
655
+ $args = array(
656
+ 'post_type' => 'any',
657
+ 'post_status' => 'any',
658
+ 'posts_per_page' => -1,
659
+ 'update_post_term_cache' => false,
660
+ 'meta_query' => array(
661
+ array(
662
+ 'key' => SHORTCODE_META,
663
+ 'compare' => 'EXISTS',
664
+ ),
665
+ ),
666
+
667
+ );
668
+ $posts = get_posts( $args );
669
+
670
+ if ( count( $posts ) > 0 ) {
671
+ $wp_customize->add_panel( __NAMESPACE__, array(
672
+ 'title' => __( 'Category Posts Shortcode', 'category-posts' ),
673
+ 'priority' => 300,
674
+ 'capability' => 'edit_theme_options',
675
+ ) );
676
+
677
+ foreach ( $posts as $p ) {
678
+ $widget = new Widget();
679
+ $meta = get_post_meta( $p->ID, SHORTCODE_META, true );
680
+ if ( ! is_array( $meta ) ) {
681
+ continue;
682
+ }
683
+
684
+ if ( ! is_array( reset( $meta ) ) ) { // 4.6 format.
685
+ $meta = array( '' => $meta );
686
+ }
687
+
688
+ foreach ( $meta as $k => $m ) {
689
+
690
+ if ( isset( $m['template'] ) && $m['template'] ) {
691
+ ;
692
+ } else {
693
+ $m['template'] = convert_settings_to_template( $m );
694
+ }
695
+
696
+ if ( 0 === count( $meta ) ) { // new widget, use defaults.
697
+ ;
698
+ } else { // updated widgets come from =< 4.6 excerpt filter is on.
699
+ if ( ! isset( $m['excerpt_filters'] ) ) {
700
+ $m['excerpt_filters'] = 'on';
701
+ }
702
+ }
703
+
704
+ $m = upgrade_settings( $m );
705
+
706
+ $section_title = $k;
707
+ if ( '' === $section_title ) {
708
+ $section_title = __( '[shortcode]', 'category-posts' );
709
+ }
710
+
711
+ $wp_customize->add_section( __NAMESPACE__ . '-' . $p->id . '-' . $k, array(
712
+ 'title' => $section_title,
713
+ 'priority' => 10,
714
+ 'capability' => 'edit_theme_options',
715
+ 'panel' => __NAMESPACE__,
716
+ ) );
717
+
718
+ ob_start();
719
+
720
+ // For the form method to handle generation gracefully, the number needs to be a simple string, and the name might include other chars as well, so for simplisity md5 it.
721
+ if ( '' !== $k ) {
722
+ $widget->number = $p->ID . '_' . md5( $k );
723
+ } else {
724
+ $widget->number = $p->ID . '_';
725
+ }
726
+
727
+ $widget->form( $m );
728
+ $form = ob_get_clean();
729
+ $form = preg_replace_callback('/<(input|select|textarea)\s+.*name=("|\').*\[\w*\]\[([^\]]*)\][^>]*>/',
730
+ function ( $matches ) use ( $p, $wp_customize, $m, $k ) {
731
+ $setting = '_virtual-' . WIDGET_BASE_ID . '[' . $p->ID . '][' . $k . '][' . $matches[3] . ']';
732
+ if ( ! isset( $m[ $matches[3] ] ) ) {
733
+ $m[ $matches[3] ] = null;
734
+ }
735
+ $wp_customize->add_setting( $setting, array(
736
+ 'default' => $m[ $matches[3] ], // set default to current value.
737
+ 'type' => 'option',
738
+ ) );
739
+
740
+ return str_replace( '<' . $matches[1], '<' . $matches[1] . ' data-customize-setting-link="' . $setting . '"', $matches[0] );
741
+ },
742
+ $form
743
+ );
744
+
745
+ $args = array(
746
+ 'label' => __( 'Layout', 'twentyfourteen' ),
747
+ 'section' => __NAMESPACE__ . '-' . $p->id . '-' . $k,
748
+ 'form' => $form,
749
+ 'settings' => '_virtual-' . WIDGET_BASE_ID . '[' . $p->ID . '][' . $k . '][title]',
750
+ 'active_callback' => function () use ( $p ) {
751
+ return is_singular() && ( get_the_ID() === $p->ID );
752
+ },
753
+ );
754
+
755
+ if ( get_option( 'page_on_front' ) === $p->ID ) {
756
+ $args['active_callback'] = function () {
757
+ return is_front_page();
758
+ };
759
+ }
760
+
761
+ $sc = new ShortCode_Control(
762
+ $wp_customize,
763
+ '_virtual-' . WIDGET_BASE_ID . '[' . $p->ID . '][' . $k . '][title]',
764
+ $args
765
+ );
766
+
767
+ if ( '' !== $k ) {
768
+ $sc->title_postfix = ' ' . $k;
769
+ }
770
+ $wp_customize->add_control( $sc );
771
+ }
772
+ }
773
+ }
774
+ }
775
+
776
+ add_action( 'customize_register', __NAMESPACE__ . '\customize_register' );
777
+
778
+ /**
779
+ * Save the virtual option used by the customizer into the proper meta values.
780
+ *
781
+ * The customizer actually saves only the changed values, so a merge needs to be done.
782
+ * After everything is updated the virtual option is deleted to leave a clean slate
783
+ *
784
+ * @return void
785
+ *
786
+ * @since 4.6
787
+ */
788
+ function customize_save_after() {
789
+ $virtual = get_option( '_virtual-' . WIDGET_BASE_ID );
790
+
791
+ if ( is_array( $virtual ) ) {
792
+ foreach ( $virtual as $pid => $instance ) {
793
+ $meta = get_post_meta( $pid, SHORTCODE_META, true );
794
+ if ( ! empty( $meta ) && ! is_array( reset( $meta ) ) ) {
795
+ $meta = array( '' => $meta ); // the conversion.
796
+ }
797
+
798
+ foreach ( $instance as $name => $new ) {
799
+ if ( isset( $meta[ $name ] ) ) { // unlikely but maybe that short code was deleted by other session.
800
+ $meta[ $name ] = array_merge( $meta[ $name ], $new );
801
+ }
802
+ }
803
+ }
804
+ update_post_meta( $pid, SHORTCODE_META, $meta );
805
+ }
806
+
807
+ delete_option( '_virtual-' . WIDGET_BASE_ID );
808
+ }
809
+
810
+ add_action( 'customize_save_after', __NAMESPACE__ . '\customize_save_after', 100 );
811
+
812
+ /*
813
+ * tinymce related functions.
814
+ */
815
+
816
+ /**
817
+ * Uninstall handler, cleanup DB from options and meta
818
+ *
819
+ * @return void
820
+ *
821
+ * @since 4.7
822
+ */
823
+ function uninstall() {
824
+ delete_option( 'widget-' . WIDGET_BASE_ID ); // delete the option storing the widget options.
825
+ delete_post_meta_by_key( SHORTCODE_META ); // delete the meta storing the shortcode.
826
+ delete_metadata( 'user', 0, __NAMESPACE__, '', true ); // delete all user metadata.
827
+ }
828
+
829
+ register_uninstall_hook( __FILE__, __NAMESPACE__ . 'uninstall' );
830
+
831
+ /**
832
+ * Register the tinymce shortcode plugin
833
+ *
834
+ * @param array $plugin_array An array containing the current plugins to be used by tinymce.
835
+ *
836
+ * @return array An array containing the plugins to be used by tinymce, our plugin added to the $plugin_array parameter
837
+ *
838
+ * @since 4.7
839
+ */
840
+ function mce_external_plugins( $plugin_array ) {
841
+ if ( current_user_can( 'edit_theme_options' ) ) { // don't load the code if the user can not customize the shortcode.
842
+ // enqueue TinyMCE plugin script with its ID.
843
+ $meta = get_user_meta( get_current_user_id(), __NAMESPACE__, true );
844
+ if ( is_array( $meta ) && isset( $meta['editor'] ) ) {
845
+ ;
846
+ } else {
847
+ $plugin_array[ __NAMESPACE__ ] = plugins_url( 'js/admin/tinymce.min.js?ver=' . VERSION, __FILE__ );
848
+ }
849
+ }
850
+
851
+ return $plugin_array;
852
+ }
853
+
854
+ add_filter( 'mce_external_plugins', __NAMESPACE__ . '\mce_external_plugins' );
855
+
856
+ /**
857
+ * Register the tinymce buttons for the add shortcode
858
+ *
859
+ * @param array $buttons An array containing the current buttons to be used by tinymce.
860
+ *
861
+ * @return array An array containing the buttons to be used by tinymce, our button added to the $buttons parameter
862
+ *
863
+ * @since 4.7
864
+ */
865
+ function mce_buttons( $buttons ) {
866
+ if ( current_user_can( 'edit_theme_options' ) ) { // don't load the code if the user can not customize the shortcode
867
+ // register buttons with their id.
868
+ $meta = get_user_meta( get_current_user_id(), __NAMESPACE__, true );
869
+ if ( is_array( $meta ) && isset( $meta['editor'] ) ) {
870
+ ;
871
+ } else {
872
+ array_push( $buttons, __NAMESPACE__ );
873
+ }
874
+ }
875
+
876
+ return $buttons;
877
+ }
878
+
879
+ add_filter( 'mce_buttons', __NAMESPACE__ . '\mce_buttons' );
880
+
881
+ /**
882
+ * Register the tinymcetranslation file
883
+ *
884
+ * @param array $locales An array containing the current translations to be used by tinymce.
885
+ *
886
+ * @return array An array containing the translations to be used by tinymce, our localization added to the $locale parameter
887
+ *
888
+ * @since 4.7
889
+ */
890
+ function mce_external_languages( $locales ) {
891
+ if ( current_user_can( 'edit_theme_options' ) ) { // don't load the code if the user can not customize the shortcode.
892
+ $meta = get_user_meta( get_current_user_id(), __NAMESPACE__, true );
893
+ if ( is_array( $meta ) && isset( $meta['editor'] ) ) {
894
+ ;
895
+ } else {
896
+ $locales['cat-posts'] = plugin_dir_path( __FILE__ ) . 'tinymce_translations.php';
897
+ }
898
+ }
899
+
900
+ return $locales;
901
+ }
902
+
903
+ add_filter( 'mce_external_languages', __NAMESPACE__ . '\mce_external_languages' );
904
+
905
+ /*
906
+ * user profile related functions.
907
+ */
908
+
909
+ add_action( 'show_user_profile', __NAMESPACE__ . '\show_user_profile' );
910
+ add_action( 'edit_user_profile', __NAMESPACE__ . '\show_user_profile' );
911
+
912
+ /**
913
+ * Display the user specific setting on its profile page
914
+ *
915
+ * @param WP_user $user The user for which the profile page displays information.
916
+ *
917
+ * @since 4.7
918
+ */
919
+ function show_user_profile( $user ) {
920
+
921
+ if ( ! current_user_can( 'edit_user', $user->ID ) ) {
922
+ return;
923
+ }
924
+
925
+ if ( ! current_user_can( 'edit_theme_options', $user->ID ) ) {
926
+ return;
927
+ }
928
+
929
+ $meta = get_the_author_meta( __NAMESPACE__, $user->ID );
930
+
931
+ if ( empty( $meta ) ) {
932
+ $meta = array();
933
+ }
934
+
935
+ $accordion = false;
936
+ if ( isset( $meta['panels'] ) ) {
937
+ $accordion = true;
938
+ }
939
+
940
+ $editor = false;
941
+ if ( isset( $meta['editor'] ) ) {
942
+ $editor = true;
943
+ }
944
+ ?>
945
+ <h3 id="<?php echo __NAMESPACE__; ?>"><?php esc_html_e( 'Category Posts Widget behaviour settings', 'category-posts' ); ?></h3>
946
+
947
+ <table class="form-table">
948
+ <tr>
949
+ <th><label for="<?php echo __NAMESPACE__; ?>[panels]"><?php esc_html_e( 'Open panels behavior', 'category-posts' ); ?></label></th>
950
+ <td>
951
+ <input type="checkbox" name="<?php echo __NAMESPACE__; ?>[panels]" id="<?php echo __NAMESPACE__; ?>[panels]" <?php checked( $accordion ); ?>>
952
+ <label for=<?php echo __NAMESPACE__; ?>[panels]><?php esc_html_e( 'Close the currently open panel when opening a new one', 'category-posts' ); ?></label>
953
+ </td>
954
+ </tr>
955
+ <tr>
956
+ <th><label for="<?php echo __NAMESPACE__; ?>[editor]"><?php esc_html_e( 'Visual editor button', 'category-posts' ); ?></label></th>
957
+ <td>
958
+ <input type="checkbox" name="<?php echo __NAMESPACE__; ?>[editor]" id="<?php echo __NAMESPACE__; ?>[editor]" <?php checked( $editor ); ?>>
959
+ <label for="<?php echo __NAMESPACE__; ?>[editor]"><?php esc_html_e( 'Hide the "insert shortcode" button from the editor', 'category-posts' ); ?></label>
960
+ </td>
961
+ </tr>
962
+ </table>
963
+ <?php
964
+ }
965
+
966
+ add_action( 'personal_options_update', __NAMESPACE__ . '\personal_options_update' );
967
+ add_action( 'edit_user_profile_update', __NAMESPACE__ . '\personal_options_update' );
968
+
969
+ /**
970
+ * Handles saving user related settings as was set in the profile page.
971
+ *
972
+ * @param int $user_id the ID of the user for which the data is saved..
973
+ *
974
+ * @since 4.7
975
+ */
976
+ function personal_options_update( $user_id ) {
977
+
978
+ if ( ! current_user_can( 'edit_user', $user_id ) ) {
979
+ return false;
980
+ }
981
+
982
+ if ( ! current_user_can( 'edit_theme_options', $user_id ) ) {
983
+ return;
984
+ }
985
+
986
+ if ( isset( $_POST[ __NAMESPACE__ ] ) ) {
987
+ update_user_meta( $user_id, __NAMESPACE__, wp_unslash( $_POST[ __NAMESPACE__ ] ) );
988
+ } else {
989
+ delete_user_meta( $user_id, __NAMESPACE__ );
990
+ }
991
+ }
992
+
993
+ add_action( 'wp_loaded', __NAMESPACE__ . '\wp_loaded' );
994
+
995
+ /**
996
+ * Run after WordPress finished bootstrapping, do whatever is needed at this stage
997
+ * like registering the meta.
998
+ */
999
+ function wp_loaded() {
1000
+ register_meta( 'post', SHORTCODE_META, null, '__return_false' ); // do not allow access to the shortcode meta
1001
+ // use the pre 4.6 format for backward compatibility.
1002
+ }
js/admin/category-posts-widget.js CHANGED
@@ -1,503 +1,503 @@
1
- /**
2
- * Category Posts Widget
3
- * http://mkrdip.me/category-posts-widget
4
- *
5
- * Adds a widget that shows the most recent posts from a single category.
6
- *
7
- * Released under the GPLv2 license or later - http://www.gnu.org/licenses/gpl-2.0.html
8
- */
9
-
10
- // namespace
11
-
12
- var cwp_namespace = {
13
-
14
- php_settings_var : 'categoryPosts',
15
- widget_class : '.category-widget-cont',
16
- template_panel_prefix : '.categoryposts-data-panel-',
17
- open_panels : {}, // holds an array of open panels per wiget id
18
- template_change_timer : null, // Used for debouncing change events generate when template changes.
19
-
20
- // generic click handler on the panel title
21
- clickHandler: function(element) {
22
- // open the div "below" the h4 title
23
- jQuery(element).toggleClass('open')
24
- .next().stop().slideToggle();
25
- // mark the change of state in the open panels array
26
- var panel = jQuery(element).data('panel');
27
- var id = jQuery(element).parent().parent().parent().parent().parent().attr('id');
28
- var o = {};
29
- if (this.open_panels.hasOwnProperty(id))
30
- o = this.open_panels[id];
31
- if (o.hasOwnProperty(panel))
32
- delete o[panel];
33
- else
34
- o[panel] = true;
35
- this.open_panels[id] = o;
36
- },
37
-
38
- // Show hide foote link URL
39
- toggleCatSelection: function(item) {
40
- var cat = jQuery(item).find("option:selected").attr('value');
41
- var panel = item.parentElement.parentElement.parentElement.parentElement;
42
- if(cat == '0') {
43
- jQuery(panel).find( '.categoryPosts-title_link' ).hide();
44
- jQuery(panel).find( '.categoryPosts-title_link_url' ).show();
45
- jQuery(panel).find( '.categoryPosts-no_cat_childs' ).hide();
46
- }
47
- else {
48
- jQuery(panel).find('.categoryPosts-title_link' ).show();
49
- jQuery(panel).find('.categoryPosts-title_link_url' ).hide();
50
- jQuery(panel).find( '.categoryPosts-no_cat_childs' ).show();
51
- }
52
- },
53
-
54
- // Show hide disable font styles
55
- toggleDisableFontStyles: function(item) {
56
- var value = jQuery(item).find("input").attr('checked');
57
- var panel = item.parentElement.parentElement;
58
- if(value == 'checked') {
59
- jQuery(panel).find('.categoryposts-data-panel-general-disable-font-styles').hide();
60
- }
61
- else {
62
- jQuery(panel).find('.categoryposts-data-panel-general-disable-font-styles').show();
63
- }
64
- },
65
-
66
- // Show hide other date format
67
- toggleDateFormat: function(item) {
68
- var value = jQuery(item).val();
69
- var panel = item.parentElement.parentElement;
70
- if( value != 'other') {
71
- jQuery(panel).find('.categoryPosts-date_format').hide();
72
- } else {
73
- jQuery(panel).find('.categoryPosts-date_format').show();
74
- }
75
- },
76
-
77
- // Show hide other date range settings
78
- toggleDateRange: function(item) {
79
- var value = jQuery(item).val();
80
- var panel = item.parentElement.parentElement;
81
- jQuery(panel).find('.categoryPosts-date-range p').hide();
82
- jQuery(panel).find('.categoryPosts-date-range').show();
83
- switch ( value ) {
84
- case 'off':
85
- jQuery(panel).find('.categoryPosts-date-range').hide();
86
- break;
87
- case 'days_ago':
88
- jQuery(panel).find('.categoryPosts-days_ago').show();
89
- break;
90
- case 'between_dates':
91
- jQuery(panel).find('.categoryPosts-start_date').show();
92
- jQuery(panel).find('.categoryPosts-end_date').show();
93
- break;
94
- }
95
- },
96
-
97
- // Show/hide no match related settings
98
- toggleNoMatch: function(item) {
99
- var value = jQuery(item).val();
100
- var panel = item.parentElement.parentElement;
101
- if ( 'text' == value ) {
102
- jQuery(panel).find('.categoryPosts-no-match-text').show();
103
- } else {
104
- jQuery(panel).find('.categoryPosts-no-match-text').hide();
105
- }
106
- },
107
-
108
- // Show template help
109
- toggleTemplateHelp: function(item,event) {
110
- event.preventDefault();
111
- var panel = item.parentElement.parentElement.parentElement.parentElement;
112
- jQuery(panel).find('.cat-post-template-help').toggle('slow');
113
- },
114
-
115
- toggleAssignedCategoriesTop: function(item) {
116
- var value = jQuery(item).find("input").attr('checked');
117
- var panel = item.parentElement.parentElement;
118
- if(value == 'checked') {
119
- jQuery(panel).find('.categoryposts-details-panel-assigned-cat-top').show();
120
- }
121
- else {
122
- jQuery(panel).find('.categoryposts-details-panel-assigned-cat-top').hide();
123
- }
124
- },
125
-
126
- toggleHideTitle: function(item) {
127
- var value = jQuery(item).attr('checked');
128
- var panel = item.parentElement.parentElement.parentElement;
129
- if (value != 'checked') {
130
- jQuery(panel).find('.categoryposts-data-panel-title-settings').show();
131
- } else {
132
- jQuery(panel).find('.categoryposts-data-panel-title-settings').hide();
133
- }
134
- },
135
-
136
- toggleLoadMore: function(item) {
137
- var value = jQuery(item).attr('checked');
138
- var panel = item.parentElement.parentElement.parentElement;
139
- if (value != 'checked') {
140
- jQuery(panel).find('.loadmore-settings').hide();
141
- } else {
142
- jQuery(panel).find('.loadmore-settings').show();
143
- }
144
- },
145
-
146
- selectPremadeTemplate: function(item) {
147
- var panel = item.parentElement.parentElement.parentElement;
148
- var div = item.parentElement.parentElement;
149
- var select = jQuery(div).find('select');
150
- var template = '%title%';
151
- value = select.val();
152
- switch (value) {
153
- case 'title':
154
- template = '%title%';
155
- break;
156
- case 'title_excerpt':
157
- template = '%title%\n\n%excerpt%';
158
- break;
159
- case 'title_thumb':
160
- template = '%title%\n\n%thumb%';
161
- break;
162
- case 'title_thum_excerpt':
163
- template = '%title%\n\n%thumb%\n%excerpt%';
164
- break;
165
- case 'everything':
166
- template = '%title%\n\n';
167
- template += '%date%\n\n';
168
- template += '%thumb%\n';
169
- template += '<span class="dashicons dashicons-admin-comments"></span> %commentnum% ';
170
- template += '<span class="dashicons dashicons-admin-users"></span> %author%\n';
171
- template += '%excerpt%';
172
- template += 'Categories: %category% ';
173
- template += '<span class="dashicons dashicons-tag"></span> %post_tag%';
174
- }
175
- var textarea = jQuery(panel).find('textarea');
176
- textarea.val(template);
177
- textarea.trigger('input', 'change');
178
- },
179
-
180
- // Close all open panels if open
181
- autoCloseOpenPanels: function(_this) {
182
- if( tiptoppress[ this.php_settings_var ].accordion ) {
183
- if(!jQuery(_this).hasClass('open')) {
184
- var jCloseElement = jQuery(_this).parent().find('.open');
185
- this.clickHandler(jCloseElement);
186
- }
187
- }
188
- },
189
-
190
- defaultThumbnailSelection: function (elem, title, button_title) {
191
-
192
- var frame = wp.media({
193
- title : title,
194
- multiple : false,
195
- library : { type : 'image' },
196
- button : { text : button_title },
197
- });
198
-
199
- // Handle results from media manager.
200
- frame.on('close',function( ) {
201
- var attachments = frame.state().get('selection').toJSON();
202
- if (attachments.length == 1) {
203
- var attachment = attachments[0];
204
- var img_html = '<img src="' + attachment.url + '" ';
205
- img_html += 'width="60" ';
206
- img_html += 'height="60" ';
207
- img_html += '/>';
208
- jQuery(elem).parent().prev().find('.default_thumb_img').html(img_html);
209
- jQuery(elem).parent().find('.cwp_default_thumb_remove').show();
210
- jQuery(elem).parent().prev().find('.default_thumb_id').val(attachment.id).change();
211
- }
212
- });
213
-
214
- frame.open();
215
- return false;
216
- },
217
-
218
- removeDefaultThumbnailSelection : function (elem) {
219
- jQuery(elem).parent().prev().find('.default_thumb_img').html(cwp_default_thumb_selection.none);
220
- jQuery(elem).hide();
221
- jQuery(elem).parent().prev().find('.default_thumb_id').val(0).change();
222
-
223
- return false;
224
- },
225
-
226
- templateChange : function (elem) {
227
-
228
- function adjustUiToTemplate() {
229
- var template = jQuery(elem).val();
230
- var tags = tiptoppress[ this.php_settings_var ].template_tags;
231
- var widget_cont = jQuery(elem.parentElement.parentElement.parentElement.parentElement);
232
- for (var key in tags) {
233
- if ( -1 !== template.indexOf( tags[key] ) ) {
234
- widget_cont.find(this.template_panel_prefix + tags[key] ).show();
235
- } else {
236
- widget_cont.find(this.template_panel_prefix + tags[key] ).hide();
237
- }
238
- }
239
- }
240
-
241
- if (null != this.template_change_timer) {
242
- clearTimeout( this.template_change_timer );
243
- }
244
- this.template_change_timer = setTimeout(adjustUiToTemplate.bind(this), 250);
245
-
246
- },
247
-
248
- thumbnailSizeChange : function (elem) {
249
-
250
- var _that = jQuery(elem),
251
- thumb_h,
252
- thumb_w,
253
- _input_thumb_h = _that.closest('.categoryposts-data-panel-thumb').find('.thumb_h'),
254
- _input_thumb_w = _that.closest('.categoryposts-data-panel-thumb').find('.thumb_w');
255
-
256
- if (_that.hasClass('smaller')) {
257
- thumb_w = _input_thumb_w.val() / 1.015;
258
- thumb_h = _input_thumb_h.val() / 1.015;
259
- } else if (_that.hasClass('quarter')) {
260
- thumb_w = _input_thumb_w.val() / 4;
261
- thumb_h = _input_thumb_h.val() / 4;
262
- } else if (_that.hasClass('half')){
263
- thumb_h = _input_thumb_h.val() / 2;
264
- thumb_w = _input_thumb_w.val() / 2;
265
- } else if (_that.hasClass('double')){
266
- thumb_h = _input_thumb_h.val() * 2;
267
- thumb_w = _input_thumb_w.val() * 2;
268
- } else if (_that.hasClass('bigger')) {
269
- thumb_w = _input_thumb_w.val() * 1.02;
270
- thumb_h = _input_thumb_h.val() * 1.02;
271
- } else if (_that.hasClass('square')) {
272
- if (parseInt(_input_thumb_w.val()) >= parseInt(_input_thumb_h.val()) ) {
273
- thumb_h = _input_thumb_w.val();
274
- thumb_w = _input_thumb_w.val();
275
- } else{
276
- thumb_h = _input_thumb_h.val();
277
- thumb_w = _input_thumb_h.val();
278
- }
279
- } else if (_that.hasClass('standard')) {
280
- if (parseInt(_input_thumb_w.val()) >= parseInt(_input_thumb_h.val()) ) {
281
- thumb_h = _input_thumb_w.val() / 4 * 3
282
- thumb_w = _input_thumb_w.val();
283
- } else {
284
- thumb_h = _input_thumb_w.val() * 4 / 3;
285
- thumb_w = _input_thumb_w.val();
286
- }
287
- } else if (_that.hasClass('wide')) {
288
- if (parseInt(_input_thumb_w.val()) >= parseInt(_input_thumb_h.val()) ) {
289
- thumb_h = _input_thumb_w.val() / 16 * 9;
290
- thumb_w = _input_thumb_w.val();
291
- } else {
292
- thumb_h = _input_thumb_w.val() * 16 / 9;
293
- thumb_w = _input_thumb_w.val();
294
- }
295
- } else if (_that.hasClass('switch')){
296
- thumb_h = _input_thumb_w.val();
297
- thumb_w = _input_thumb_h.val();
298
- } else {
299
- thumb_w = _that.data("thumb-w");
300
- thumb_h = _that.data("thumb-h");
301
- }
302
- _input_thumb_w.val(Math.floor(thumb_w));
303
- _input_thumb_h.val(Math.floor(thumb_h));
304
- _input_thumb_w.trigger('input', 'change');
305
- _input_thumb_h.trigger('input', 'change');
306
-
307
- return false;
308
- },
309
-
310
- thumbnailFluidWidthChange : function (elem) {
311
-
312
- var _that = jQuery(elem),
313
- _input_thumb_h = _that.closest('.categoryposts-data-panel-thumb').find('.thumb_h');
314
-
315
- _that.closest( 'label' ).find( 'span' ).html( _that.val() + '%' );
316
-
317
- _input_thumb_h.val(0);
318
- _input_thumb_h.trigger('input', 'change');
319
-
320
- return false;
321
- },
322
-
323
- openAddPlaceholder : function (elem) {
324
-
325
- var _that = jQuery(elem);
326
-
327
- _that.closest( '.cat-post-add_premade_templates' ).find( '.cpwp-placeholder-dropdown-menu' ).toggle();
328
-
329
- _that.closest( '.cat-post-add_premade_templates' ).find( '.cpwp-placeholder-dropdown-menu span' ).off('click').on('click', function() {
330
- var text = jQuery( this ).data( 'value' );
331
- switch( text ){
332
- case 'NewLine':
333
- text = '\n';
334
- break;
335
- case 'EmptyLine':
336
- text = '\n\n';
337
- break;
338
- default:
339
- text = '%' + text + '%';
340
- break;
341
- }
342
- var _div = this.parentElement.parentElement.parentElement;
343
- var textarea = jQuery( _div ).find( 'textarea' );
344
- var textareaPos = textarea[0].selectionStart;
345
- var textareaTxt = textarea.val();
346
- textarea.val( textareaTxt.substring(0, textareaPos) + text + textareaTxt.substring(textareaPos) );
347
-
348
- textarea[0].selectionStart = textareaPos + text.length;
349
- textarea[0].selectionEnd = textareaPos + text.length;
350
- textarea.focus();
351
- textarea.trigger('input', 'change');
352
-
353
- //_that.closest( '.cat-post-add_premade_templates' ).find( '.cpwp-placeholder-dropdown-menu' ).hide();
354
- });
355
-
356
- _that.closest( '.cat-post-add_premade_templates' ).find( '.cpwp-placeholder-dropdown-menu' ).on('mouseenter', function(){
357
- jQuery(this).addClass('cpw-doNotClose');
358
- });
359
- _that.closest( '.cat-post-add_premade_templates' ).find( '.cpwp-placeholder-dropdown-menu' ).on('mouseleave', function(){
360
- jQuery(this).removeClass('cpw-doNotClose');
361
- });
362
-
363
- return false;
364
- },
365
-
366
- selectPlaceholderHelper : function (elem) {
367
-
368
- var textarea = jQuery(elem);
369
- var textareaPos = textarea[0].selectionStart;
370
- var textareaTxt = textarea.val();
371
-
372
- var nStartSel = textareaTxt.substring(0, textareaPos).lastIndexOf( '%' );
373
- var nEndSel = textareaPos + textareaTxt.substring(textareaPos).indexOf( '%' ) + 1;
374
-
375
- var strSelTxt = textareaTxt.substring(nStartSel, nEndSel);
376
- if( strSelTxt.indexOf( '\n' ) >= 0 || strSelTxt.indexOf( ' ' ) >= 0 || strSelTxt.length <=2 ) {
377
- return false;
378
- }
379
-
380
- textarea[0].selectionStart = nStartSel;
381
- textarea[0].selectionEnd = nEndSel;
382
- return false;
383
- },
384
- }
385
-
386
- jQuery(document).ready( function () {
387
-
388
- var class_namespace = '.category-widget-cont';
389
-
390
- jQuery('.category-widget-cont h4').click(function () { // for widgets page
391
- cwp_namespace.autoCloseOpenPanels(this);
392
- // toggle panel open/close
393
- cwp_namespace.clickHandler(this);
394
- });
395
-
396
- // needed to reassign click handlers after widget refresh
397
- jQuery(document).on('widget-added widget-updated panelsopen', function(root,element){ // for customize and after save on widgets page (add panelsopen: fix make widget SiteOrigin Page Builder plugin, GH issue #181)
398
-
399
- jQuery('.category-widget-cont h4').off('click').on('click', function () {
400
- cwp_namespace.autoCloseOpenPanels(this);
401
- // toggle panel open/close
402
- cwp_namespace.clickHandler(this);
403
- });
404
- jQuery('.cwp_default_thumb_select').off('click').on('click', function () { // select default thumb
405
- cwp_namespace.defaultThumbnailSelection(this, cwp_default_thumb_selection.frame_title,cwp_default_thumb_selection.button_title);
406
- });
407
-
408
- jQuery('.cwp_default_thumb_remove').off('click').on('click', function () { // remove default thumb
409
- cwp_namespace.removeDefaultThumbnailSelection(this);
410
- });
411
-
412
- // refresh panels to state before the refresh
413
- var id = jQuery(element).attr('id');
414
- if (cwp_namespace.open_panels.hasOwnProperty(id)) {
415
- var o = cwp_namespace.open_panels[id];
416
- for (var panel in o) {
417
- jQuery(element).find('[data-panel='+panel+']').toggleClass('open')
418
- .next().stop().show();
419
- }
420
- }
421
-
422
- setChangeHandlers();
423
- });
424
-
425
- function setChangeHandlers() {
426
- jQuery('.cwp_default_thumb_select').off('click').on('click', function () { // select default thumb
427
- cwp_namespace.defaultThumbnailSelection(this, cwp_default_thumb_selection.frame_title,cwp_default_thumb_selection.button_title);
428
- });
429
-
430
- jQuery(document).on('change', class_namespace+' .categoryposts-data-panel-filter-cat', function () { // change category filter
431
- cwp_namespace.toggleCatSelection(this);
432
- });
433
-
434
- jQuery('.cwp_default_thumb_remove').off('click').on('click', function () { // remove default thumb
435
- cwp_namespace.removeDefaultThumbnailSelection(this);
436
- });
437
-
438
- jQuery(class_namespace+'-assigned_categories').off('click').on('click', function () {
439
- cwp_namespace.toggleAssignedCategoriesTop(this);
440
- });
441
-
442
- jQuery(document).on('click', class_namespace+' .categoryPosts-hide_title input', function () {
443
- cwp_namespace.toggleHideTitle(this);
444
- });
445
-
446
- jQuery(document).on('click', class_namespace+' .categoryPosts-enable_loadmore input', function () {
447
- cwp_namespace.toggleLoadMore(this);
448
- });
449
-
450
- jQuery(document).on('change', class_namespace+' .categoryPosts-preset_date_format select', function () { // change date format
451
- cwp_namespace.toggleDateFormat(this);
452
- });
453
-
454
- jQuery(document).on('change', class_namespace+' .categoryPosts-date_range select', function () { // change date range
455
- cwp_namespace.toggleDateRange(this);
456
- });
457
-
458
- jQuery(document).on('change', class_namespace+' .categoryPosts-no_match_handling select', function () { // change date range
459
- cwp_namespace.toggleNoMatch(this);
460
- });
461
-
462
- jQuery(class_namespace+' a.toggle-template-help').off('click').on('click', function (event) { // show template help
463
- cwp_namespace.toggleTemplateHelp(this, event);
464
- });
465
-
466
- jQuery(document).on('click', class_namespace+' .cat-post-premade_templates button', function () { // select a pre made template
467
- cwp_namespace.selectPremadeTemplate(this);
468
- });
469
-
470
- jQuery(document).on('change', class_namespace+' .cat-post-premade_templates select', function (event) { // prevent refresh ontemplate selection
471
- event.preventDefault();
472
- event.stopPropagation();
473
- });
474
-
475
- jQuery(document).on('input', class_namespace+' .categoryPosts-template textarea', function () { // prevent refresh ontemplate selection
476
- cwp_namespace.templateChange(this);
477
- });
478
-
479
- jQuery(document).off('click').on('click', class_namespace+' .cat-post-thumb-change-size button', function () { // find a thumbnail size
480
- cwp_namespace.thumbnailSizeChange(this);
481
- });
482
-
483
- jQuery(document).on('change', class_namespace+' .thumb_fluid_width', function () { // select a thumbnail fluid size
484
- cwp_namespace.thumbnailFluidWidthChange(this);
485
- });
486
-
487
- jQuery(class_namespace+' .cpwp-open-placholder-dropdown-menu').off('click').on('click', function () { // open drop down and add placeholder
488
- cwp_namespace.openAddPlaceholder(this);
489
- });
490
-
491
- jQuery(document).on('onfocusout, blur', class_namespace+' .cpwp-open-placholder-dropdown-menu,'+class_namespace+' .categoryPosts-template textarea', function () { // close drop down placeholder, if not used
492
- jQuery(this).closest( class_namespace+' .categoryPosts-template' ).parent().find( '.cpwp-placeholder-dropdown-menu' ).not('.cpw-doNotClose').hide();
493
- });
494
-
495
- jQuery(document).on('mousedown', class_namespace+' .categoryPosts-template textarea', function () { // help to select the placeholder
496
- var _that = this;
497
- setTimeout(function(){ cwp_namespace.selectPlaceholderHelper(_that); }, 0);
498
- ;
499
- });
500
- }
501
-
502
- setChangeHandlers();
503
- });
1
+ /**
2
+ * Category Posts Widget
3
+ * http://mkrdip.me/category-posts-widget
4
+ *
5
+ * Adds a widget that shows the most recent posts from a single category.
6
+ *
7
+ * Released under the GPLv2 license or later - http://www.gnu.org/licenses/gpl-2.0.html
8
+ */
9
+
10
+ // namespace
11
+
12
+ var cwp_namespace = {
13
+
14
+ php_settings_var : 'categoryPosts',
15
+ widget_class : '.category-widget-cont',
16
+ template_panel_prefix : '.categoryposts-data-panel-',
17
+ open_panels : {}, // holds an array of open panels per wiget id
18
+ template_change_timer : null, // Used for debouncing change events generate when template changes.
19
+
20
+ // generic click handler on the panel title
21
+ clickHandler: function(element) {
22
+ // open the div "below" the h4 title
23
+ jQuery(element).toggleClass('open')
24
+ .next().stop().slideToggle();
25
+ // mark the change of state in the open panels array
26
+ var panel = jQuery(element).data('panel');
27
+ var id = jQuery(element).parent().parent().parent().parent().parent().attr('id');
28
+ var o = {};
29
+ if (this.open_panels.hasOwnProperty(id))
30
+ o = this.open_panels[id];
31
+ if (o.hasOwnProperty(panel))
32
+ delete o[panel];
33
+ else
34
+ o[panel] = true;
35
+ this.open_panels[id] = o;
36
+ },
37
+
38
+ // Show hide foote link URL
39
+ toggleCatSelection: function(item) {
40
+ var cat = jQuery(item).find("option:selected").attr('value');
41
+ var panel = item.parentElement.parentElement.parentElement.parentElement;
42
+ if(cat == '0') {
43
+ jQuery(panel).find( '.categoryPosts-title_link' ).hide();
44
+ jQuery(panel).find( '.categoryPosts-title_link_url' ).show();
45
+ jQuery(panel).find( '.categoryPosts-no_cat_childs' ).hide();
46
+ }
47
+ else {
48
+ jQuery(panel).find('.categoryPosts-title_link' ).show();
49
+ jQuery(panel).find('.categoryPosts-title_link_url' ).hide();
50
+ jQuery(panel).find( '.categoryPosts-no_cat_childs' ).show();
51
+ }
52
+ },
53
+
54
+ // Show hide disable font styles
55
+ toggleDisableFontStyles: function(item) {
56
+ var value = jQuery(item).find("input").attr('checked');
57
+ var panel = item.parentElement.parentElement;
58
+ if(value == 'checked') {
59
+ jQuery(panel).find('.categoryposts-data-panel-general-disable-font-styles').hide();
60
+ }
61
+ else {
62
+ jQuery(panel).find('.categoryposts-data-panel-general-disable-font-styles').show();
63
+ }
64
+ },
65
+
66
+ // Show hide other date format
67
+ toggleDateFormat: function(item) {
68
+ var value = jQuery(item).val();
69
+ var panel = item.parentElement.parentElement;
70
+ if( value != 'other') {
71
+ jQuery(panel).find('.categoryPosts-date_format').hide();
72
+ } else {
73
+ jQuery(panel).find('.categoryPosts-date_format').show();
74
+ }
75
+ },
76
+
77
+ // Show hide other date range settings
78
+ toggleDateRange: function(item) {
79
+ var value = jQuery(item).val();
80
+ var panel = item.parentElement.parentElement;
81
+ jQuery(panel).find('.categoryPosts-date-range p').hide();
82
+ jQuery(panel).find('.categoryPosts-date-range').show();
83
+ switch ( value ) {
84
+ case 'off':
85
+ jQuery(panel).find('.categoryPosts-date-range').hide();
86
+ break;
87
+ case 'days_ago':
88
+ jQuery(panel).find('.categoryPosts-days_ago').show();
89
+ break;
90
+ case 'between_dates':
91
+ jQuery(panel).find('.categoryPosts-start_date').show();
92
+ jQuery(panel).find('.categoryPosts-end_date').show();
93
+ break;
94
+ }
95
+ },
96
+
97
+ // Show/hide no match related settings
98
+ toggleNoMatch: function(item) {
99
+ var value = jQuery(item).val();
100
+ var panel = item.parentElement.parentElement;
101
+ if ( 'text' == value ) {
102
+ jQuery(panel).find('.categoryPosts-no-match-text').show();
103
+ } else {
104
+ jQuery(panel).find('.categoryPosts-no-match-text').hide();
105
+ }
106
+ },
107
+
108
+ // Show template help
109
+ toggleTemplateHelp: function(item,event) {
110
+ event.preventDefault();
111
+ var panel = item.parentElement.parentElement.parentElement.parentElement;
112
+ jQuery(panel).find('.cat-post-template-help').toggle('slow');
113
+ },
114
+
115
+ toggleAssignedCategoriesTop: function(item) {
116
+ var value = jQuery(item).find("input").attr('checked');
117
+ var panel = item.parentElement.parentElement;
118
+ if(value == 'checked') {
119
+ jQuery(panel).find('.categoryposts-details-panel-assigned-cat-top').show();
120
+ }
121
+ else {
122
+ jQuery(panel).find('.categoryposts-details-panel-assigned-cat-top').hide();
123
+ }
124
+ },
125
+
126
+ toggleHideTitle: function(item) {
127
+ var value = jQuery(item).attr('checked');
128
+ var panel = item.parentElement.parentElement.parentElement;
129
+ if (value != 'checked') {
130
+ jQuery(panel).find('.categoryposts-data-panel-title-settings').show();
131
+ } else {
132
+ jQuery(panel).find('.categoryposts-data-panel-title-settings').hide();
133
+ }
134
+ },
135
+
136
+ toggleLoadMore: function(item) {
137
+ var value = jQuery(item).attr('checked');
138
+ var panel = item.parentElement.parentElement.parentElement;
139
+ if (value != 'checked') {
140
+ jQuery(panel).find('.loadmore-settings').hide();
141
+ } else {
142
+ jQuery(panel).find('.loadmore-settings').show();
143
+ }
144
+ },
145
+
146
+ selectPremadeTemplate: function(item) {
147
+ var panel = item.parentElement.parentElement.parentElement;
148
+ var div = item.parentElement.parentElement;
149
+ var select = jQuery(div).find('select');
150
+ var template = '%title%';
151
+ value = select.val();
152
+ switch (value) {
153
+ case 'title':
154
+ template = '%title%';
155
+ break;
156
+ case 'title_excerpt':
157
+ template = '%title%\n\n%excerpt%';
158
+ break;
159
+ case 'title_thumb':
160
+ template = '%title%\n\n%thumb%';
161
+ break;
162
+ case 'title_thum_excerpt':
163
+ template = '%title%\n\n%thumb%\n%excerpt%';
164
+ break;
165
+ case 'everything':
166
+ template = '%title%\n\n';
167
+ template += '%date%\n\n';
168
+ template += '%thumb%\n';
169
+ template += '<span class="dashicons dashicons-admin-comments"></span> %commentnum% ';
170
+ template += '<span class="dashicons dashicons-admin-users"></span> %author%\n';
171
+ template += '%excerpt%';
172
+ template += 'Categories: %category% ';
173
+ template += '<span class="dashicons dashicons-tag"></span> %post_tag%';
174
+ }
175
+ var textarea = jQuery(panel).find('textarea');
176
+ textarea.val(template);
177
+ textarea.trigger('input', 'change');
178
+ },
179
+
180
+ // Close all open panels if open
181
+ autoCloseOpenPanels: function(_this) {
182
+ if( tiptoppress[ this.php_settings_var ].accordion ) {
183
+ if(!jQuery(_this).hasClass('open')) {
184
+ var jCloseElement = jQuery(_this).parent().find('.open');
185
+ this.clickHandler(jCloseElement);
186
+ }
187
+ }
188
+ },
189
+
190
+ defaultThumbnailSelection: function (elem, title, button_title) {
191
+
192
+ var frame = wp.media({
193
+ title : title,
194
+ multiple : false,
195
+ library : { type : 'image' },
196
+ button : { text : button_title },
197
+ });
198
+
199
+ // Handle results from media manager.
200
+ frame.on('close',function( ) {
201
+ var attachments = frame.state().get('selection').toJSON();
202
+ if (attachments.length == 1) {
203
+ var attachment = attachments[0];
204
+ var img_html = '<img src="' + attachment.url + '" ';
205
+ img_html += 'width="60" ';
206
+ img_html += 'height="60" ';
207
+ img_html += '/>';
208
+ jQuery(elem).parent().prev().find('.default_thumb_img').html(img_html);
209
+ jQuery(elem).parent().find('.cwp_default_thumb_remove').show();
210
+ jQuery(elem).parent().prev().find('.default_thumb_id').val(attachment.id).change();
211
+ }
212
+ });
213
+
214
+ frame.open();
215
+ return false;
216
+ },
217
+
218
+ removeDefaultThumbnailSelection : function (elem) {
219
+ jQuery(elem).parent().prev().find('.default_thumb_img').html(cwp_default_thumb_selection.none);
220
+ jQuery(elem).hide();
221
+ jQuery(elem).parent().prev().find('.default_thumb_id').val(0).change();
222
+
223
+ return false;
224
+ },
225
+
226
+ templateChange : function (elem) {
227
+
228
+ function adjustUiToTemplate() {
229
+ var template = jQuery(elem).val();
230
+ var tags = tiptoppress[ this.php_settings_var ].template_tags;
231
+ var widget_cont = jQuery(elem.parentElement.parentElement.parentElement.parentElement);
232
+ for (var key in tags) {
233
+ if ( -1 !== template.indexOf( tags[key] ) ) {
234
+ widget_cont.find(this.template_panel_prefix + tags[key] ).show();
235
+ } else {
236
+ widget_cont.find(this.template_panel_prefix + tags[key] ).hide();
237
+ }
238
+ }
239
+ }
240
+
241
+ if (null != this.template_change_timer) {
242
+ clearTimeout( this.template_change_timer );
243
+ }
244
+ this.template_change_timer = setTimeout(adjustUiToTemplate.bind(this), 250);
245
+
246
+ },
247
+
248
+ thumbnailSizeChange : function (elem) {
249
+
250
+ var _that = jQuery(elem),
251
+ thumb_h,
252
+ thumb_w,
253
+ _input_thumb_h = _that.closest('.categoryposts-data-panel-thumb').find('.thumb_h'),
254
+ _input_thumb_w = _that.closest('.categoryposts-data-panel-thumb').find('.thumb_w');
255
+
256
+ if (_that.hasClass('smaller')) {
257
+ thumb_w = _input_thumb_w.val() / 1.015;
258
+ thumb_h = _input_thumb_h.val() / 1.015;
259
+ } else if (_that.hasClass('quarter')) {
260
+ thumb_w = _input_thumb_w.val() / 4;
261
+ thumb_h = _input_thumb_h.val() / 4;
262
+ } else if (_that.hasClass('half')){
263
+ thumb_h = _input_thumb_h.val() / 2;
264
+ thumb_w = _input_thumb_w.val() / 2;
265
+ } else if (_that.hasClass('double')){
266
+ thumb_h = _input_thumb_h.val() * 2;
267
+ thumb_w = _input_thumb_w.val() * 2;
268
+ } else if (_that.hasClass('bigger')) {
269
+ thumb_w = _input_thumb_w.val() * 1.02;
270
+ thumb_h = _input_thumb_h.val() * 1.02;
271
+ } else if (_that.hasClass('square')) {
272
+ if (parseInt(_input_thumb_w.val()) >= parseInt(_input_thumb_h.val()) ) {
273
+ thumb_h = _input_thumb_w.val();
274
+ thumb_w = _input_thumb_w.val();
275
+ } else{
276
+ thumb_h = _input_thumb_h.val();
277
+ thumb_w = _input_thumb_h.val();
278
+ }
279
+ } else if (_that.hasClass('standard')) {
280
+ if (parseInt(_input_thumb_w.val()) >= parseInt(_input_thumb_h.val()) ) {
281
+ thumb_h = _input_thumb_w.val() / 4 * 3
282
+ thumb_w = _input_thumb_w.val();
283
+ } else {
284
+ thumb_h = _input_thumb_w.val() * 4 / 3;
285
+ thumb_w = _input_thumb_w.val();
286
+ }
287
+ } else if (_that.hasClass('wide')) {
288
+ if (parseInt(_input_thumb_w.val()) >= parseInt(_input_thumb_h.val()) ) {
289
+ thumb_h = _input_thumb_w.val() / 16 * 9;
290
+ thumb_w = _input_thumb_w.val();
291
+ } else {
292
+ thumb_h = _input_thumb_w.val() * 16 / 9;
293
+ thumb_w = _input_thumb_w.val();
294
+ }
295
+ } else if (_that.hasClass('switch')){
296
+ thumb_h = _input_thumb_w.val();
297
+ thumb_w = _input_thumb_h.val();
298
+ } else {
299
+ thumb_w = _that.data("thumb-w");
300
+ thumb_h = _that.data("thumb-h");
301
+ }
302
+ _input_thumb_w.val(Math.floor(thumb_w));
303
+ _input_thumb_h.val(Math.floor(thumb_h));
304
+ _input_thumb_w.trigger('input', 'change');
305
+ _input_thumb_h.trigger('input', 'change');
306
+
307
+ return false;
308
+ },
309
+
310
+ thumbnailFluidWidthChange : function (elem) {
311
+
312
+ var _that = jQuery(elem),
313
+ _input_thumb_h = _that.closest('.categoryposts-data-panel-thumb').find('.thumb_h');
314
+
315
+ _that.closest( 'label' ).find( 'span' ).html( _that.val() + '%' );
316
+
317
+ _input_thumb_h.val(0);
318
+ _input_thumb_h.trigger('input', 'change');
319
+
320
+ return false;
321
+ },
322
+
323
+ openAddPlaceholder : function (elem) {
324
+
325
+ var _that = jQuery(elem);
326
+
327
+ _that.closest( '.cat-post-add_premade_templates' ).find( '.cpwp-placeholder-dropdown-menu' ).toggle();
328
+
329
+ _that.closest( '.cat-post-add_premade_templates' ).find( '.cpwp-placeholder-dropdown-menu span' ).off('click').on('click', function() {
330
+ var text = jQuery( this ).data( 'value' );
331
+ switch( text ){
332
+ case 'NewLine':
333
+ text = '\n';
334
+ break;
335
+ case 'EmptyLine':
336
+ text = '\n\n';
337
+ break;
338
+ default:
339
+ text = '%' + text + '%';
340
+ break;
341
+ }
342
+ var _div = this.parentElement.parentElement.parentElement;
343
+ var textarea = jQuery( _div ).find( 'textarea' );
344
+ var textareaPos = textarea[0].selectionStart;
345
+ var textareaTxt = textarea.val();
346
+ textarea.val( textareaTxt.substring(0, textareaPos) + text + textareaTxt.substring(textareaPos) );
347
+
348
+ textarea[0].selectionStart = textareaPos + text.length;
349
+ textarea[0].selectionEnd = textareaPos + text.length;
350
+ textarea.focus();
351
+ textarea.trigger('input', 'change');
352
+
353
+ //_that.closest( '.cat-post-add_premade_templates' ).find( '.cpwp-placeholder-dropdown-menu' ).hide();
354
+ });
355
+
356
+ _that.closest( '.cat-post-add_premade_templates' ).find( '.cpwp-placeholder-dropdown-menu' ).on('mouseenter', function(){
357
+ jQuery(this).addClass('cpw-doNotClose');
358
+ });
359
+ _that.closest( '.cat-post-add_premade_templates' ).find( '.cpwp-placeholder-dropdown-menu' ).on('mouseleave', function(){
360
+ jQuery(this).removeClass('cpw-doNotClose');
361
+ });
362
+
363
+ return false;
364
+ },
365
+
366
+ selectPlaceholderHelper : function (elem) {
367
+
368
+ var textarea = jQuery(elem);
369
+ var textareaPos = textarea[0].selectionStart;
370
+ var textareaTxt = textarea.val();
371
+
372
+ var nStartSel = textareaTxt.substring(0, textareaPos).lastIndexOf( '%' );
373
+ var nEndSel = textareaPos + textareaTxt.substring(textareaPos).indexOf( '%' ) + 1;
374
+
375
+ var strSelTxt = textareaTxt.substring(nStartSel, nEndSel);
376
+ if( strSelTxt.indexOf( '\n' ) >= 0 || strSelTxt.indexOf( ' ' ) >= 0 || strSelTxt.length <=2 ) {
377
+ return false;
378
+ }
379
+
380
+ textarea[0].selectionStart = nStartSel;
381
+ textarea[0].selectionEnd = nEndSel;
382
+ return false;
383
+ },
384
+ }
385
+
386
+ jQuery(document).ready( function () {
387
+
388
+ var class_namespace = '.category-widget-cont';
389
+
390
+ jQuery('.category-widget-cont h4').click(function () { // for widgets page
391
+ cwp_namespace.autoCloseOpenPanels(this);
392
+ // toggle panel open/close
393
+ cwp_namespace.clickHandler(this);
394
+ });
395
+
396
+ // needed to reassign click handlers after widget refresh
397
+ jQuery(document).on('widget-added widget-updated panelsopen', function(root,element){ // for customize and after save on widgets page (add panelsopen: fix make widget SiteOrigin Page Builder plugin, GH issue #181)
398
+
399
+ jQuery('.category-widget-cont h4').off('click').on('click', function () {
400
+ cwp_namespace.autoCloseOpenPanels(this);
401
+ // toggle panel open/close
402
+ cwp_namespace.clickHandler(this);
403
+ });
404
+ jQuery('.cwp_default_thumb_select').off('click').on('click', function () { // select default thumb
405
+ cwp_namespace.defaultThumbnailSelection(this, cwp_default_thumb_selection.frame_title,cwp_default_thumb_selection.button_title);
406
+ });
407
+
408
+ jQuery('.cwp_default_thumb_remove').off('click').on('click', function () { // remove default thumb
409
+ cwp_namespace.removeDefaultThumbnailSelection(this);
410
+ });
411
+
412
+ // refresh panels to state before the refresh
413
+ var id = jQuery(element).attr('id');
414
+ if (cwp_namespace.open_panels.hasOwnProperty(id)) {
415
+ var o = cwp_namespace.open_panels[id];
416
+ for (var panel in o) {
417
+ jQuery(element).find('[data-panel='+panel+']').toggleClass('open')
418
+ .next().stop().show();
419
+ }
420
+ }
421
+
422
+ setChangeHandlers();
423
+ });
424
+
425
+ function setChangeHandlers() {
426
+ jQuery('.cwp_default_thumb_select').off('click').on('click', function () { // select default thumb
427
+ cwp_namespace.defaultThumbnailSelection(this, cwp_default_thumb_selection.frame_title,cwp_default_thumb_selection.button_title);
428
+ });
429
+
430
+ jQuery(document).on('change', class_namespace+' .categoryposts-data-panel-filter-cat', function () { // change category filter
431
+ cwp_namespace.toggleCatSelection(this);
432
+ });
433
+
434
+ jQuery('.cwp_default_thumb_remove').off('click').on('click', function () { // remove default thumb
435
+ cwp_namespace.removeDefaultThumbnailSelection(this);
436
+ });
437
+
438
+ jQuery(class_namespace+'-assigned_categories').off('click').on('click', function () {
439
+ cwp_namespace.toggleAssignedCategoriesTop(this);
440
+ });
441
+
442
+ jQuery(document).on('click', class_namespace+' .categoryPosts-hide_title input', function () {
443
+ cwp_namespace.toggleHideTitle(this);
444
+ });
445
+
446
+ jQuery(document).on('click', class_namespace+' .categoryPosts-enable_loadmore input', function () {
447
+ cwp_namespace.toggleLoadMore(this);
448
+ });
449
+
450
+ jQuery(document).on('change', class_namespace+' .categoryPosts-preset_date_format select', function () { // change date format
451
+ cwp_namespace.toggleDateFormat(this);
452
+ });
453
+
454
+ jQuery(document).on('change', class_namespace+' .categoryPosts-date_range select', function () { // change date range
455
+ cwp_namespace.toggleDateRange(this);
456
+ });
457
+
458
+ jQuery(document).on('change', class_namespace+' .categoryPosts-no_match_handling select', function () { // change date range
459
+ cwp_namespace.toggleNoMatch(this);
460
+ });
461
+
462
+ jQuery(class_namespace+' a.toggle-template-help').off('click').on('click', function (event) { // show template help
463
+ cwp_namespace.toggleTemplateHelp(this, event);
464
+ });
465
+
466
+ jQuery(document).on('click', class_namespace+' .cat-post-premade_templates button', function () { // select a pre made template
467
+ cwp_namespace.selectPremadeTemplate(this);
468
+ });
469
+
470
+ jQuery(document).on('change', class_namespace+' .cat-post-premade_templates select', function (event) { // prevent refresh ontemplate selection
471
+ event.preventDefault();
472
+ event.stopPropagation();
473
+ });
474
+
475
+ jQuery(document).on('input', class_namespace+' .categoryPosts-template textarea', function () { // prevent refresh ontemplate selection
476
+ cwp_namespace.templateChange(this);
477
+ });
478
+
479
+ jQuery(class_namespace+' .cat-post-thumb-change-size button').off('click').on('click', function () { // find a thumbnail size
480
+ cwp_namespace.thumbnailSizeChange(this);
481
+ });
482
+
483
+ jQuery(document).on('change', class_namespace+' .thumb_fluid_width', function () { // select a thumbnail fluid size
484
+ cwp_namespace.thumbnailFluidWidthChange(this);
485
+ });
486
+
487
+ jQuery(class_namespace+' .cpwp-open-placholder-dropdown-menu').off('click').on('click', function () { // open drop down and add placeholder
488
+ cwp_namespace.openAddPlaceholder(this);
489
+ });
490
+
491
+ jQuery(document).on('onfocusout, blur', class_namespace+' .cpwp-open-placholder-dropdown-menu,'+class_namespace+' .categoryPosts-template textarea', function () { // close drop down placeholder, if not used
492
+ jQuery(this).closest( class_namespace+' .categoryPosts-template' ).parent().find( '.cpwp-placeholder-dropdown-menu' ).not('.cpw-doNotClose').hide();
493
+ });
494
+
495
+ jQuery(document).on('mousedown', class_namespace+' .categoryPosts-template textarea', function () { // help to select the placeholder
496
+ var _that = this;
497
+ setTimeout(function(){ cwp_namespace.selectPlaceholderHelper(_that); }, 0);
498
+ ;
499
+ });
500
+ }
501
+
502
+ setChangeHandlers();
503
+ });
js/admin/category-posts-widget.min.js CHANGED
@@ -1 +1 @@
1
- var cwp_namespace={php_settings_var:"categoryPosts",widget_class:".category-widget-cont",template_panel_prefix:".categoryposts-data-panel-",open_panels:{},template_change_timer:null,clickHandler:function(e){jQuery(e).toggleClass("open").next().stop().slideToggle();var t=jQuery(e).data("panel"),a=jQuery(e).parent().parent().parent().parent().parent().attr("id"),n={};this.open_panels.hasOwnProperty(a)&&(n=this.open_panels[a]),n.hasOwnProperty(t)?delete n[t]:n[t]=!0,this.open_panels[a]=n},toggleCatSelection:function(e){var t=jQuery(e).find("option:selected").attr("value"),a=e.parentElement.parentElement.parentElement.parentElement;"0"==t?(jQuery(a).find(".categoryPosts-title_link").hide(),jQuery(a).find(".categoryPosts-title_link_url").show(),jQuery(a).find(".categoryPosts-no_cat_childs").hide()):(jQuery(a).find(".categoryPosts-title_link").show(),jQuery(a).find(".categoryPosts-title_link_url").hide(),jQuery(a).find(".categoryPosts-no_cat_childs").show())},toggleDisableFontStyles:function(e){var t=jQuery(e).find("input").attr("checked"),a=e.parentElement.parentElement;"checked"==t?jQuery(a).find(".categoryposts-data-panel-general-disable-font-styles").hide():jQuery(a).find(".categoryposts-data-panel-general-disable-font-styles").show()},toggleDateFormat:function(e){var t=jQuery(e).val(),a=e.parentElement.parentElement;"other"!=t?jQuery(a).find(".categoryPosts-date_format").hide():jQuery(a).find(".categoryPosts-date_format").show()},toggleDateRange:function(e){var t=jQuery(e).val(),a=e.parentElement.parentElement;switch(jQuery(a).find(".categoryPosts-date-range p").hide(),jQuery(a).find(".categoryPosts-date-range").show(),t){case"off":jQuery(a).find(".categoryPosts-date-range").hide();break;case"days_ago":jQuery(a).find(".categoryPosts-days_ago").show();break;case"between_dates":jQuery(a).find(".categoryPosts-start_date").show(),jQuery(a).find(".categoryPosts-end_date").show()}},toggleNoMatch:function(e){var t=jQuery(e).val(),a=e.parentElement.parentElement;"text"==t?jQuery(a).find(".categoryPosts-no-match-text").show():jQuery(a).find(".categoryPosts-no-match-text").hide()},toggleTemplateHelp:function(e,t){t.preventDefault();var a=e.parentElement.parentElement.parentElement.parentElement;jQuery(a).find(".cat-post-template-help").toggle("slow")},toggleAssignedCategoriesTop:function(e){var t=jQuery(e).find("input").attr("checked"),a=e.parentElement.parentElement;"checked"==t?jQuery(a).find(".categoryposts-details-panel-assigned-cat-top").show():jQuery(a).find(".categoryposts-details-panel-assigned-cat-top").hide()},toggleHideTitle:function(e){var t=jQuery(e).attr("checked"),a=e.parentElement.parentElement.parentElement;"checked"!=t?jQuery(a).find(".categoryposts-data-panel-title-settings").show():jQuery(a).find(".categoryposts-data-panel-title-settings").hide()},toggleLoadMore:function(e){var t=jQuery(e).attr("checked"),a=e.parentElement.parentElement.parentElement;"checked"!=t?jQuery(a).find(".loadmore-settings").hide():jQuery(a).find(".loadmore-settings").show()},selectPremadeTemplate:function(e){var t=e.parentElement.parentElement.parentElement,a=e.parentElement.parentElement,n=jQuery(a).find("select"),o="%title%";switch(value=n.val(),value){case"title":o="%title%";break;case"title_excerpt":o="%title%\n\n%excerpt%";break;case"title_thumb":o="%title%\n\n%thumb%";break;case"title_thum_excerpt":o="%title%\n\n%thumb%\n%excerpt%";break;case"everything":o="%title%\n\n",o+="%date%\n\n",o+="%thumb%\n",o+='<span class="dashicons dashicons-admin-comments"></span> %commentnum% ',o+='<span class="dashicons dashicons-admin-users"></span> %author%\n',o+="%excerpt%",o+="Categories: %category% ",o+='<span class="dashicons dashicons-tag"></span> %post_tag%'}var l=jQuery(t).find("textarea");l.val(o),l.trigger("input","change")},autoCloseOpenPanels:function(e){if(tiptoppress[this.php_settings_var].accordion&&!jQuery(e).hasClass("open")){var t=jQuery(e).parent().find(".open");this.clickHandler(t)}},defaultThumbnailSelection:function(e,t,a){var n=wp.media({title:t,multiple:!1,library:{type:"image"},button:{text:a}});return n.on("close",function(){var t=n.state().get("selection").toJSON();if(1==t.length){var a=t[0],o='<img src="'+a.url+'" ';o+='width="60" ',o+='height="60" ',o+="/>",jQuery(e).parent().prev().find(".default_thumb_img").html(o),jQuery(e).parent().find(".cwp_default_thumb_remove").show(),jQuery(e).parent().prev().find(".default_thumb_id").val(a.id).change()}}),n.open(),!1},removeDefaultThumbnailSelection:function(e){return jQuery(e).parent().prev().find(".default_thumb_img").html(cwp_default_thumb_selection.none),jQuery(e).hide(),jQuery(e).parent().prev().find(".default_thumb_id").val(0).change(),!1},templateChange:function(e){function t(){var t=jQuery(e).val(),a=tiptoppress[this.php_settings_var].template_tags,n=jQuery(e.parentElement.parentElement.parentElement.parentElement);for(var o in a)-1!==t.indexOf(a[o])?n.find(this.template_panel_prefix+a[o]).show():n.find(this.template_panel_prefix+a[o]).hide()}null!=this.template_change_timer&&clearTimeout(this.template_change_timer),this.template_change_timer=setTimeout(t.bind(this),250)},thumbnailSizeChange:function(e){var t,a,n=jQuery(e),o=n.closest(".categoryposts-data-panel-thumb").find(".thumb_h"),l=n.closest(".categoryposts-data-panel-thumb").find(".thumb_w");return n.hasClass("smaller")?(a=l.val()/1.015,t=o.val()/1.015):n.hasClass("quarter")?(a=l.val()/4,t=o.val()/4):n.hasClass("half")?(t=o.val()/2,a=l.val()/2):n.hasClass("double")?(t=2*o.val(),a=2*l.val()):n.hasClass("bigger")?(a=1.02*l.val(),t=1.02*o.val()):n.hasClass("square")?parseInt(l.val())>=parseInt(o.val())?(t=l.val(),a=l.val()):(t=o.val(),a=o.val()):n.hasClass("standard")?parseInt(l.val())>=parseInt(o.val())?(t=l.val()/4*3,a=l.val()):(t=4*l.val()/3,a=l.val()):n.hasClass("wide")?parseInt(l.val())>=parseInt(o.val())?(t=l.val()/16*9,a=l.val()):(t=16*l.val()/9,a=l.val()):n.hasClass("switch")?(t=l.val(),a=o.val()):(a=n.data("thumb-w"),t=n.data("thumb-h")),l.val(Math.floor(a)),o.val(Math.floor(t)),l.trigger("input","change"),o.trigger("input","change"),!1},thumbnailFluidWidthChange:function(e){var t=jQuery(e),a=t.closest(".categoryposts-data-panel-thumb").find(".thumb_h");return t.closest("label").find("span").html(t.val()+"%"),a.val(0),a.trigger("input","change"),!1},openAddPlaceholder:function(e){var t=jQuery(e);return t.closest(".cat-post-add_premade_templates").find(".cpwp-placeholder-dropdown-menu").toggle(),t.closest(".cat-post-add_premade_templates").find(".cpwp-placeholder-dropdown-menu span").off("click").on("click",function(){var e=jQuery(this).data("value");switch(e){case"NewLine":e="\n";break;case"EmptyLine":e="\n\n";break;default:e="%"+e+"%"}var t=this.parentElement.parentElement.parentElement,a=jQuery(t).find("textarea"),n=a[0].selectionStart,o=a.val();a.val(o.substring(0,n)+e+o.substring(n)),a[0].selectionStart=n+e.length,a[0].selectionEnd=n+e.length,a.focus(),a.trigger("input","change")}),t.closest(".cat-post-add_premade_templates").find(".cpwp-placeholder-dropdown-menu").on("mouseenter",function(){jQuery(this).addClass("cpw-doNotClose")}),t.closest(".cat-post-add_premade_templates").find(".cpwp-placeholder-dropdown-menu").on("mouseleave",function(){jQuery(this).removeClass("cpw-doNotClose")}),!1},selectPlaceholderHelper:function(e){var t=jQuery(e),a=t[0].selectionStart,n=t.val(),o=n.substring(0,a).lastIndexOf("%"),l=a+n.substring(a).indexOf("%")+1,s=n.substring(o,l);return!(s.indexOf("\n")>=0||s.indexOf(" ")>=0||s.length<=2)&&(t[0].selectionStart=o,t[0].selectionEnd=l,!1)}};jQuery(document).ready(function(){function e(){jQuery(".cwp_default_thumb_select").off("click").on("click",function(){cwp_namespace.defaultThumbnailSelection(this,cwp_default_thumb_selection.frame_title,cwp_default_thumb_selection.button_title)}),jQuery(document).on("change",t+" .categoryposts-data-panel-filter-cat",function(){cwp_namespace.toggleCatSelection(this)}),jQuery(".cwp_default_thumb_remove").off("click").on("click",function(){cwp_namespace.removeDefaultThumbnailSelection(this)}),jQuery(t+"-assigned_categories").off("click").on("click",function(){cwp_namespace.toggleAssignedCategoriesTop(this)}),jQuery(document).on("click",t+" .categoryPosts-hide_title input",function(){cwp_namespace.toggleHideTitle(this)}),jQuery(document).on("click",t+" .categoryPosts-enable_loadmore input",function(){cwp_namespace.toggleLoadMore(this)}),jQuery(document).on("change",t+" .categoryPosts-preset_date_format select",function(){cwp_namespace.toggleDateFormat(this)}),jQuery(document).on("change",t+" .categoryPosts-date_range select",function(){cwp_namespace.toggleDateRange(this)}),jQuery(document).on("change",t+" .categoryPosts-no_match_handling select",function(){cwp_namespace.toggleNoMatch(this)}),jQuery(t+" a.toggle-template-help").off("click").on("click",function(e){cwp_namespace.toggleTemplateHelp(this,e)}),jQuery(document).on("click",t+" .cat-post-premade_templates button",function(){cwp_namespace.selectPremadeTemplate(this)}),jQuery(document).on("change",t+" .cat-post-premade_templates select",function(e){e.preventDefault(),e.stopPropagation()}),jQuery(document).on("input",t+" .categoryPosts-template textarea",function(){cwp_namespace.templateChange(this)}),jQuery(document).off("click").on("click",t+" .cat-post-thumb-change-size button",function(){cwp_namespace.thumbnailSizeChange(this)}),jQuery(document).on("change",t+" .thumb_fluid_width",function(){cwp_namespace.thumbnailFluidWidthChange(this)}),jQuery(t+" .cpwp-open-placholder-dropdown-menu").off("click").on("click",function(){cwp_namespace.openAddPlaceholder(this)}),jQuery(document).on("onfocusout, blur",t+" .cpwp-open-placholder-dropdown-menu,"+t+" .categoryPosts-template textarea",function(){jQuery(this).closest(t+" .categoryPosts-template").parent().find(".cpwp-placeholder-dropdown-menu").not(".cpw-doNotClose").hide()}),jQuery(document).on("mousedown",t+" .categoryPosts-template textarea",function(){var e=this;setTimeout(function(){cwp_namespace.selectPlaceholderHelper(e)},0)})}var t=".category-widget-cont";jQuery(".category-widget-cont h4").click(function(){cwp_namespace.autoCloseOpenPanels(this),cwp_namespace.clickHandler(this)}),jQuery(document).on("widget-added widget-updated panelsopen",function(t,a){jQuery(".category-widget-cont h4").off("click").on("click",function(){cwp_namespace.autoCloseOpenPanels(this),cwp_namespace.clickHandler(this)}),jQuery(".cwp_default_thumb_select").off("click").on("click",function(){cwp_namespace.defaultThumbnailSelection(this,cwp_default_thumb_selection.frame_title,cwp_default_thumb_selection.button_title)}),jQuery(".cwp_default_thumb_remove").off("click").on("click",function(){cwp_namespace.removeDefaultThumbnailSelection(this)});var n=jQuery(a).attr("id");if(cwp_namespace.open_panels.hasOwnProperty(n)){var o=cwp_namespace.open_panels[n];for(var l in o)jQuery(a).find("[data-panel="+l+"]").toggleClass("open").next().stop().show()}e()}),e()});
1
+ var cwp_namespace={php_settings_var:"categoryPosts",widget_class:".category-widget-cont",template_panel_prefix:".categoryposts-data-panel-",open_panels:{},template_change_timer:null,clickHandler:function(element){jQuery(element).toggleClass("open").next().stop().slideToggle();var panel=jQuery(element).data("panel"),id=jQuery(element).parent().parent().parent().parent().parent().attr("id"),o={};this.open_panels.hasOwnProperty(id)&&(o=this.open_panels[id]),o.hasOwnProperty(panel)?delete o[panel]:o[panel]=!0,this.open_panels[id]=o},toggleCatSelection:function(item){var cat=jQuery(item).find("option:selected").attr("value"),panel=item.parentElement.parentElement.parentElement.parentElement;"0"==cat?(jQuery(panel).find(".categoryPosts-title_link").hide(),jQuery(panel).find(".categoryPosts-title_link_url").show(),jQuery(panel).find(".categoryPosts-no_cat_childs").hide()):(jQuery(panel).find(".categoryPosts-title_link").show(),jQuery(panel).find(".categoryPosts-title_link_url").hide(),jQuery(panel).find(".categoryPosts-no_cat_childs").show())},toggleDisableFontStyles:function(item){var value=jQuery(item).find("input").attr("checked"),panel=item.parentElement.parentElement;"checked"==value?jQuery(panel).find(".categoryposts-data-panel-general-disable-font-styles").hide():jQuery(panel).find(".categoryposts-data-panel-general-disable-font-styles").show()},toggleDateFormat:function(item){var value=jQuery(item).val(),panel=item.parentElement.parentElement;"other"!=value?jQuery(panel).find(".categoryPosts-date_format").hide():jQuery(panel).find(".categoryPosts-date_format").show()},toggleDateRange:function(item){var value=jQuery(item).val(),panel=item.parentElement.parentElement;switch(jQuery(panel).find(".categoryPosts-date-range p").hide(),jQuery(panel).find(".categoryPosts-date-range").show(),value){case"off":jQuery(panel).find(".categoryPosts-date-range").hide();break;case"days_ago":jQuery(panel).find(".categoryPosts-days_ago").show();break;case"between_dates":jQuery(panel).find(".categoryPosts-start_date").show(),jQuery(panel).find(".categoryPosts-end_date").show()}},toggleNoMatch:function(item){var value=jQuery(item).val(),panel=item.parentElement.parentElement;"text"==value?jQuery(panel).find(".categoryPosts-no-match-text").show():jQuery(panel).find(".categoryPosts-no-match-text").hide()},toggleTemplateHelp:function(item,event){event.preventDefault();var panel=item.parentElement.parentElement.parentElement.parentElement;jQuery(panel).find(".cat-post-template-help").toggle("slow")},toggleAssignedCategoriesTop:function(item){var value=jQuery(item).find("input").attr("checked"),panel=item.parentElement.parentElement;"checked"==value?jQuery(panel).find(".categoryposts-details-panel-assigned-cat-top").show():jQuery(panel).find(".categoryposts-details-panel-assigned-cat-top").hide()},toggleHideTitle:function(item){var value=jQuery(item).attr("checked"),panel=item.parentElement.parentElement.parentElement;"checked"!=value?jQuery(panel).find(".categoryposts-data-panel-title-settings").show():jQuery(panel).find(".categoryposts-data-panel-title-settings").hide()},toggleLoadMore:function(item){var value=jQuery(item).attr("checked"),panel=item.parentElement.parentElement.parentElement;"checked"!=value?jQuery(panel).find(".loadmore-settings").hide():jQuery(panel).find(".loadmore-settings").show()},selectPremadeTemplate:function(item){var panel=item.parentElement.parentElement.parentElement,div=item.parentElement.parentElement,select=jQuery(div).find("select"),template="%title%";switch(value=select.val(),value){case"title":template="%title%";break;case"title_excerpt":template="%title%\n\n%excerpt%";break;case"title_thumb":template="%title%\n\n%thumb%";break;case"title_thum_excerpt":template="%title%\n\n%thumb%\n%excerpt%";break;case"everything":template="%title%\n\n",template+="%date%\n\n",template+="%thumb%\n",template+='<span class="dashicons dashicons-admin-comments"></span> %commentnum% ',template+='<span class="dashicons dashicons-admin-users"></span> %author%\n',template+="%excerpt%",template+="Categories: %category% ",template+='<span class="dashicons dashicons-tag"></span> %post_tag%'}var textarea=jQuery(panel).find("textarea");textarea.val(template),textarea.trigger("input","change")},autoCloseOpenPanels:function(_this){if(tiptoppress[this.php_settings_var].accordion&&!jQuery(_this).hasClass("open")){var jCloseElement=jQuery(_this).parent().find(".open");this.clickHandler(jCloseElement)}},defaultThumbnailSelection:function(elem,title,button_title){var frame=wp.media({title:title,multiple:!1,library:{type:"image"},button:{text:button_title}});return frame.on("close",(function(){var attachments=frame.state().get("selection").toJSON();if(1==attachments.length){var attachment=attachments[0],img_html='<img src="'+attachment.url+'" ';img_html+='width="60" ',img_html+='height="60" ',img_html+="/>",jQuery(elem).parent().prev().find(".default_thumb_img").html(img_html),jQuery(elem).parent().find(".cwp_default_thumb_remove").show(),jQuery(elem).parent().prev().find(".default_thumb_id").val(attachment.id).change()}})),frame.open(),!1},removeDefaultThumbnailSelection:function(elem){return jQuery(elem).parent().prev().find(".default_thumb_img").html(cwp_default_thumb_selection.none),jQuery(elem).hide(),jQuery(elem).parent().prev().find(".default_thumb_id").val(0).change(),!1},templateChange:function(elem){function adjustUiToTemplate(){var template=jQuery(elem).val(),tags=tiptoppress[this.php_settings_var].template_tags,widget_cont=jQuery(elem.parentElement.parentElement.parentElement.parentElement);for(var key in tags)-1!==template.indexOf(tags[key])?widget_cont.find(this.template_panel_prefix+tags[key]).show():widget_cont.find(this.template_panel_prefix+tags[key]).hide()}null!=this.template_change_timer&&clearTimeout(this.template_change_timer),this.template_change_timer=setTimeout(adjustUiToTemplate.bind(this),250)},thumbnailSizeChange:function(elem){var _that=jQuery(elem),thumb_h,thumb_w,_input_thumb_h=_that.closest(".categoryposts-data-panel-thumb").find(".thumb_h"),_input_thumb_w=_that.closest(".categoryposts-data-panel-thumb").find(".thumb_w");return _that.hasClass("smaller")?(thumb_w=_input_thumb_w.val()/1.015,thumb_h=_input_thumb_h.val()/1.015):_that.hasClass("quarter")?(thumb_w=_input_thumb_w.val()/4,thumb_h=_input_thumb_h.val()/4):_that.hasClass("half")?(thumb_h=_input_thumb_h.val()/2,thumb_w=_input_thumb_w.val()/2):_that.hasClass("double")?(thumb_h=2*_input_thumb_h.val(),thumb_w=2*_input_thumb_w.val()):_that.hasClass("bigger")?(thumb_w=1.02*_input_thumb_w.val(),thumb_h=1.02*_input_thumb_h.val()):_that.hasClass("square")?parseInt(_input_thumb_w.val())>=parseInt(_input_thumb_h.val())?(thumb_h=_input_thumb_w.val(),thumb_w=_input_thumb_w.val()):(thumb_h=_input_thumb_h.val(),thumb_w=_input_thumb_h.val()):_that.hasClass("standard")?parseInt(_input_thumb_w.val())>=parseInt(_input_thumb_h.val())?(thumb_h=_input_thumb_w.val()/4*3,thumb_w=_input_thumb_w.val()):(thumb_h=4*_input_thumb_w.val()/3,thumb_w=_input_thumb_w.val()):_that.hasClass("wide")?parseInt(_input_thumb_w.val())>=parseInt(_input_thumb_h.val())?(thumb_h=_input_thumb_w.val()/16*9,thumb_w=_input_thumb_w.val()):(thumb_h=16*_input_thumb_w.val()/9,thumb_w=_input_thumb_w.val()):_that.hasClass("switch")?(thumb_h=_input_thumb_w.val(),thumb_w=_input_thumb_h.val()):(thumb_w=_that.data("thumb-w"),thumb_h=_that.data("thumb-h")),_input_thumb_w.val(Math.floor(thumb_w)),_input_thumb_h.val(Math.floor(thumb_h)),_input_thumb_w.trigger("input","change"),_input_thumb_h.trigger("input","change"),!1},thumbnailFluidWidthChange:function(elem){var _that=jQuery(elem),_input_thumb_h=_that.closest(".categoryposts-data-panel-thumb").find(".thumb_h");return _that.closest("label").find("span").html(_that.val()+"%"),_input_thumb_h.val(0),_input_thumb_h.trigger("input","change"),!1},openAddPlaceholder:function(elem){var _that=jQuery(elem);return _that.closest(".cat-post-add_premade_templates").find(".cpwp-placeholder-dropdown-menu").toggle(),_that.closest(".cat-post-add_premade_templates").find(".cpwp-placeholder-dropdown-menu span").off("click").on("click",(function(){var text=jQuery(this).data("value");switch(text){case"NewLine":text="\n";break;case"EmptyLine":text="\n\n";break;default:text="%"+text+"%"}var _div=this.parentElement.parentElement.parentElement,textarea=jQuery(_div).find("textarea"),textareaPos=textarea[0].selectionStart,textareaTxt=textarea.val();textarea.val(textareaTxt.substring(0,textareaPos)+text+textareaTxt.substring(textareaPos)),textarea[0].selectionStart=textareaPos+text.length,textarea[0].selectionEnd=textareaPos+text.length,textarea.focus(),textarea.trigger("input","change")})),_that.closest(".cat-post-add_premade_templates").find(".cpwp-placeholder-dropdown-menu").on("mouseenter",(function(){jQuery(this).addClass("cpw-doNotClose")})),_that.closest(".cat-post-add_premade_templates").find(".cpwp-placeholder-dropdown-menu").on("mouseleave",(function(){jQuery(this).removeClass("cpw-doNotClose")})),!1},selectPlaceholderHelper:function(elem){var textarea=jQuery(elem),textareaPos=textarea[0].selectionStart,textareaTxt=textarea.val(),nStartSel=textareaTxt.substring(0,textareaPos).lastIndexOf("%"),nEndSel=textareaPos+textareaTxt.substring(textareaPos).indexOf("%")+1,strSelTxt=textareaTxt.substring(nStartSel,nEndSel);return!(strSelTxt.indexOf("\n")>=0||strSelTxt.indexOf(" ")>=0||strSelTxt.length<=2)&&(textarea[0].selectionStart=nStartSel,textarea[0].selectionEnd=nEndSel,!1)}};jQuery(document).ready((function(){var class_namespace=".category-widget-cont";function setChangeHandlers(){jQuery(".cwp_default_thumb_select").off("click").on("click",(function(){cwp_namespace.defaultThumbnailSelection(this,cwp_default_thumb_selection.frame_title,cwp_default_thumb_selection.button_title)})),jQuery(document).on("change",class_namespace+" .categoryposts-data-panel-filter-cat",(function(){cwp_namespace.toggleCatSelection(this)})),jQuery(".cwp_default_thumb_remove").off("click").on("click",(function(){cwp_namespace.removeDefaultThumbnailSelection(this)})),jQuery(class_namespace+"-assigned_categories").off("click").on("click",(function(){cwp_namespace.toggleAssignedCategoriesTop(this)})),jQuery(document).on("click",class_namespace+" .categoryPosts-hide_title input",(function(){cwp_namespace.toggleHideTitle(this)})),jQuery(document).on("click",class_namespace+" .categoryPosts-enable_loadmore input",(function(){cwp_namespace.toggleLoadMore(this)})),jQuery(document).on("change",class_namespace+" .categoryPosts-preset_date_format select",(function(){cwp_namespace.toggleDateFormat(this)})),jQuery(document).on("change",class_namespace+" .categoryPosts-date_range select",(function(){cwp_namespace.toggleDateRange(this)})),jQuery(document).on("change",class_namespace+" .categoryPosts-no_match_handling select",(function(){cwp_namespace.toggleNoMatch(this)})),jQuery(class_namespace+" a.toggle-template-help").off("click").on("click",(function(event){cwp_namespace.toggleTemplateHelp(this,event)})),jQuery(document).on("click",class_namespace+" .cat-post-premade_templates button",(function(){cwp_namespace.selectPremadeTemplate(this)})),jQuery(document).on("change",class_namespace+" .cat-post-premade_templates select",(function(event){event.preventDefault(),event.stopPropagation()})),jQuery(document).on("input",class_namespace+" .categoryPosts-template textarea",(function(){cwp_namespace.templateChange(this)})),jQuery(class_namespace+" .cat-post-thumb-change-size button").off("click").on("click",(function(){cwp_namespace.thumbnailSizeChange(this)})),jQuery(document).on("change",class_namespace+" .thumb_fluid_width",(function(){cwp_namespace.thumbnailFluidWidthChange(this)})),jQuery(class_namespace+" .cpwp-open-placholder-dropdown-menu").off("click").on("click",(function(){cwp_namespace.openAddPlaceholder(this)})),jQuery(document).on("onfocusout, blur",class_namespace+" .cpwp-open-placholder-dropdown-menu,"+class_namespace+" .categoryPosts-template textarea",(function(){jQuery(this).closest(class_namespace+" .categoryPosts-template").parent().find(".cpwp-placeholder-dropdown-menu").not(".cpw-doNotClose").hide()})),jQuery(document).on("mousedown",class_namespace+" .categoryPosts-template textarea",(function(){var _that=this;setTimeout((function(){cwp_namespace.selectPlaceholderHelper(_that)}),0)}))}jQuery(".category-widget-cont h4").click((function(){cwp_namespace.autoCloseOpenPanels(this),cwp_namespace.clickHandler(this)})),jQuery(document).on("widget-added widget-updated panelsopen",(function(root,element){jQuery(".category-widget-cont h4").off("click").on("click",(function(){cwp_namespace.autoCloseOpenPanels(this),cwp_namespace.clickHandler(this)})),jQuery(".cwp_default_thumb_select").off("click").on("click",(function(){cwp_namespace.defaultThumbnailSelection(this,cwp_default_thumb_selection.frame_title,cwp_default_thumb_selection.button_title)})),jQuery(".cwp_default_thumb_remove").off("click").on("click",(function(){cwp_namespace.removeDefaultThumbnailSelection(this)}));var id=jQuery(element).attr("id");if(cwp_namespace.open_panels.hasOwnProperty(id)){var o=cwp_namespace.open_panels[id];for(var panel in o)jQuery(element).find("[data-panel="+panel+"]").toggleClass("open").next().stop().show()}setChangeHandlers()})),setChangeHandlers()}));
readme.txt CHANGED
@@ -1,292 +1,295 @@
1
- === Category Posts Widget ===
2
- Contributors: mark-k, kometschuh, mkrdip
3
- Donate link: https://wordpress.org/support/plugin/category-posts/reviews/
4
- Tags: category, categories, posts, widget, posts widget, recent posts, category recent posts, shortcode, sidebar, excerpt, multiple widgets
5
- Requires at least: 2.8
6
- Tested up to: 5.3
7
- Stable tag: 4.9.3
8
- License: GPLv2 or later
9
- License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
-
11
- Adds a widget that shows the most recent posts from a single category.
12
-
13
- == Description ==
14
- Category Posts Widget is a light widget designed to do one thing and do it well: display the most recent posts from a certain category.
15
-
16
- = Term and Category based Posts Widget =
17
- A premium version of that free widget available at [tiptoppress.com](http://tiptoppress.com/) created for big Wordpress sites.
18
-
19
- = Premium features =
20
- * Image-Slider
21
- * Post List "Alterations"
22
- * Full background post images
23
- * Masonry (responsive layouts), Grid and Column full page layouts
24
- * More complex ways to filter (ANY, NOT, AND, not include children)
25
- * Custom Post Types, Events, Products support
26
- * Add-ons
27
- * All free features
28
- * E-Mail support
29
- * Free trial on localhost
30
- * More examples on the [demo pages](http://demo.tiptoppress.com/)
31
-
32
- = Features =
33
- * [Template](http://tiptoppress.com/template-arrange-post-details/) to arrange the post details.
34
- * The Template text can be a post details placeholder, plain text, HTML or a font-icons.
35
- * Font-icon support.
36
- * 'Load more' button / Ajax API
37
- * Shortcode (Easily change all Shortcode options in the customizer).
38
- * Date range filter
39
- * New date format: Time since plublished
40
- * Filter by post status: Published, scheduled, private.
41
- * Multiple shortcodes at the same site or post.
42
- * Add option for post offset (use two or more widgets after another).
43
- * Admin UI: Buttons in the editor toolbar to insert shortcode.
44
- * Excerpt length in lines (line-clamp)
45
- * Option to touch device friendly "everything is a link".
46
- * For editing shortcode adds a Customizer link to the admin-bar ("With one click to the Customizer").
47
- * Set thumbnail width & height / image crop with CSS (object-fit).
48
- * Fluid images (max-width in %).
49
- * One thumb dimension can be left empty.
50
- * Option to set mouse hover effects for post thumbnail.
51
- * Set a default thumbnail.
52
- * Hide widget text or text, if there is no post.
53
- * Option to hide posts which have no thumbnail.
54
- * Option exclude current post.
55
- * Option show post author, comment's count, post date.
56
- * Admin UI: Set / find thumbnail size buttons: +, ¼, ½, 2x, -, ratio and Media sizes
57
- * Admin UI: Buttons to easy add post details placeholder.
58
- * Multi sites support.
59
-
60
- = Documentation =
61
- * Full [documentation](http://tiptoppress.com/category-posts-widget/documentation-4-9)
62
- * Shortcode: Use [catposts] in the content and [edit in the customizer](http://tiptoppress.com/use-shortcode-to-add-category-posts-widget-to-the-content/)
63
- * Formatting date and time: See <a target="_blank" href="https://codex.wordpress.org/Formatting_Date_and_Time">Formatting Date and Time</a>
64
-
65
- = Contribute =
66
- While using this plugin if you find any bug or any conflict, please submit an issue at
67
- [Github](https://github.com/tiptoppress/category-posts-widget) (If possible with a pull request).
68
-
69
- == Installation ==
70
- = Automatic installation =
71
- Automatic installation is the easiest option as WordPress handles the file transfers itself and you don’t need to leave your web browser. To do an automatic install of Category Posts Widget,
72
-
73
- 1. log in to your WordPress dashboard, navigate to the Plugins menu and click Add New.
74
- 2. In the search field type “Category Posts Widget” and click Search Plugins.
75
- 3. Once you’ve found plugin, you can install it by simply clicking “Install Now”.
76
- 4. Then, go to plugins page of WordPress admin activate the plugin.
77
- 5. Now, goto the Widgets page of the Appearance section and configure the Category Posts widget.
78
-
79
- = Manual installation =
80
- 1. Download the plugin.
81
- 2. Upload it to the plugins folder of your blog.
82
- 3. Activate the plugin through the 'Plugins' menu in WordPress
83
- 4. Now, goto the Widgets page of the Appearance section and configure the Category Posts widget.
84
-
85
- == Upgrade Notice ==
86
- * Please consider to re-configure the widget as the latest version has numerous changes from previous.
87
- * Version 4.0 uses CSS file for styling the widget in front end.
88
- * Version 3.0 or later version uses WordPress 2.9's built in post thumbnail functionality.
89
-
90
- == Frequently Asked Questions ==
91
- = Template, placeholder and post detail =
92
- Here You can control the [Post Detail parts](http://tiptoppress.com/category-posts-widget/documentation-4-9/#Post_details), which appears as part of the post item. All post detail will placed as placeholder. The text in the Template area can be a post details placeholder, plain text, HTML or HTML for SVG icons.
93
-
94
- [How it works? and examples.](http://tiptoppress.com/template-arrange-post-details/)
95
-
96
- For more layout options please try our premium widget: [Term and Category based Posts Widget](http://tiptoppress.com/term-and-category-based-posts-widget/).
97
-
98
- = Use SVG icons =
99
- For SVG font-icon HTML we recommend the [WordPress Dashicons](https://developer.wordpress.org/resource/dashicons/), which are included as default and can be used without any font-icon including.
100
-
101
- = How to use Page Bilder plugins like Divi, SiteOrigin Page Builder or Elementor =
102
- Please read more about Page Builder plugins at our [FAQs](http://tiptoppress.com/faqs/)
103
-
104
- = Parse error: syntax error, unexpected T_FUNCTION in /home/www/blog/wp-content/plugins/category-posts/cat-posts.php on line 58 =
105
- Some of the features that were used in that version needs PHP 5.3+.
106
- We apologies for any headache this may cause you, but frankly it is better for you to check with your hosting company how can you upgrade the PHP version that you are using, and not only in order to use this plugin. PHP 5.2 should be considered insecure now, and for your own sake you should upgrade.
107
- PHP 5.2 is very old and any support for it from the php developers had ended more then 5 years ago [php.net/eol.php](http://php.net/eol.php).
108
- We know there are peopel how use PHP 5.2 [wordpress.org/about/stats](https://wordpress.org/about/stats/) and we can't imagine this people will have no other problems, if they don't update.
109
-
110
- = You check the PHP version with phpversion(), but the widget don't work =
111
- Check also the .htaccess file, if there is an entry for an older PHP version.
112
-
113
- = Excerpt length in lines don't work with FireFox and IE =
114
- We use for Excerpt length in lines a CSS feature called "line-clamp" which isn't supported in FireFox and IE at the moment.
115
- But since it is supported by all other browsers, we think it will be supported in FireFox and IE soon.
116
- The FireFox browser has a coverage of 5%, which we find little. For this 5%, we have included a polyfill in our [Excerpt Extension add-on](https://wordpress.org/plugins/excerpt-extension/).
117
-
118
- == Screenshots ==
119
- 1. Front end of the widget with SVG font-icon support for post formats, hover effects and the Template text-area.
120
- 2. Template to arrange the post details with placeholders.
121
- 3. Edit the widget options with the customizer.
122
- 4. Use shortcode [catposts] in the content.
123
- 5. The widget configuration dialog.
124
- 6. Widget behaviour settings for each user.
125
-
126
- == Changelog ==
127
- [Read more on our blog ...](http://tiptoppress.com/category/category-posts-widget)
128
-
129
- = 4.9.3 - March 18th 2020 =
130
- * Fixed Mouse hover icon and post format indication
131
-
132
- = 4.9.2 - Mai 23th 2019 =
133
- * Fixed Starts with post
134
- * Fixed Replace the figure-element
135
-
136
- = 4.9.1 - Mai 17th 2019 =
137
- * 'Load more' button / Ajax API
138
- * Data range filter
139
- * Text, if there is no post
140
- * Excerpt length in lines (line-clamp)
141
- * Image crop with CSS (object-fit)
142
- * Fluid images (max-width in %).
143
- * One thumb dimension can be left empty
144
- * Admin UI: Button to easy add post details placeholder
145
- * Admin UI: Set / find thumbnail size buttons: +, ¼, ½, 2x, -, ratio and Media sizes
146
-
147
- = 4.8.5 - April 02nd 2018 =
148
- * Fixed Tabs not working
149
-
150
- = 4.8.4 - April 02nd 2018 =
151
- * Fixed Make widget SiteOrigin Page Builder Compatible
152
-
153
- = 4.8.3 - March 03th 2018 =
154
- * Fixed Updated widget with zero for the thumb dimensions caused a JavaScript error
155
-
156
- = 4.8.2 - January 30th 2018 =
157
- * Fixed Adding the widget with the customizer only the title is shown
158
- * Fixed Recognize "Empty lines" > Next line is a paragraph in the Template in widget areas
159
-
160
- = 4.8.1 - January 25th 2018 =
161
- * Fixed Recognize "Empty lines" > Next line is a paragraph in the Template
162
-
163
- = 4.8 - January 22th 2018 =
164
- * SVG font-icon support for post formats
165
- * Template to arrange the post details
166
- * Premade Templates
167
- * Date format: Time since plublished
168
- * Filter by post status: Published, scheduled, private
169
- * Hover effect: SVG font-icon
170
-
171
- = 4.7.4 - October 21th 2017 =
172
- * Bugfix for filter by post status (note private)
173
-
174
- = 4.7.3 - October 10th 2017 =
175
- * Add option to filter by post status
176
- * Fixed footer section do not change when switching to and from "all posts"
177
-
178
- = 4.7.2 - February 25th 2017 =
179
- * Add option to disable only the font styles
180
- * Fixed if option 'Everything is a link' no closing anchor tag
181
- * Fixed if option 'Everyting is a link' wrong layout
182
- * Fixed when a manual excerpt is provided, use it instead of generating an automatic one
183
- * Fixed if option 'Disable the built-in CSS' the thumbnail client-side cropping isn't disabled
184
- * Fixed if option 'Disable the built-in CSS' title class is not rendered
185
- * Fixed when having multi shortcodes, clicking on a checkbox label marks in any of them selects the one in the "first"
186
- * Fixed if option 'CSS crop to requested size' for multi shortcodes
187
- * Fixed for CSS animation
188
-
189
- = 4.7.1 - December 20th 2016 =
190
- * Support multiple shortcodes in content
191
- * Add option for post offset (use two or more widgets after another)
192
- * Fluid images for Responsive Layouts
193
- * Set a thumbnail as default thumbnail
194
- * Add option to enable excerpt filters from Themes and plugins
195
- * Add option to disable social buttons, banner, ... in the excerpt
196
- * Add dropdownbox entry for 'all' categories
197
- * Add option to disable subcategories
198
- * Add insert shortcode buttons to the editor toolbar
199
- * Use WP user profile for settings ('auto close' and if the shortcode button appears in the editor toolbar)
200
- * Simple API for external use
201
- * Support localization with translate.wordpress.org: Portuguese (Brazil) thank you [Henrique Vianna](https://profiles.wordpress.org/hvianna/) and German by [Daniel Floeter](https://profiles.wordpress.org/kometschuh/)
202
- * Remove allow_html option (Instead we recommend to use the [manual excerpt](https://codex.wordpress.org/Excerpt#How_to_add_excerpts_to_posts) or we support this option furthermore in the [Term Posts Excerpt Extension](https://github.com/tiptoppress/term-posts-excerpt-extension) for the premium version)
203
-
204
- = 4.6.2 - August 28th 2016 =
205
- * Fixed only five widget instances can be costumized with shortcodes.
206
- * For editing shortcode adds a customizer link to the admin-bar if page/post is in edit mode.
207
-
208
- = 4.6.1 - June 5th 2016 =
209
- * Add shortcode [catposts] edit options only in the customizer
210
- * Keep panels open after save.
211
- * Option to hide social buttons on output.
212
-
213
- = 4.1.9 - May 5th 2016 =
214
- * Fixed undefined constant.
215
-
216
- = 4.1.8 - May 3th 2016 =
217
- * Add mouse hover effects: blur
218
- * Add option to choose allowed HTML in the excerpt
219
- * Add Jetpack 'Sharing - Show buttons on posts' support
220
- * Fixed division by zero bug (for small uploaded images)
221
-
222
- = 4.1.7 - April 14th 2016 =
223
- * Fixed division by zero bug.
224
-
225
- = 4.1.6 - April 13th 2016 =
226
- * Add option CSS cropping for thumbnails.
227
- * Add option to set mouse hover effects for post thumbnail.
228
- * Add option to change the excerpt more text.
229
- * Add option to allow links in the excerpt
230
- * Add filter 'widget_title' for the title
231
- * Add option to hide post titles.
232
-
233
- = 4.1.5 - February 4th 2016 =
234
- * Support for multi sites.
235
- * Support for localization.
236
- * Area UI.
237
- * Meet new plugin author [mark-k](https://profiles.wordpress.org/mark-k/)
238
-
239
- = 4.1.4 =
240
- * Added option exclude current post.
241
- * Added option to hide posts which have no thumbnail.
242
- * Added option to make the widget date link to the category page.
243
- * Added option to link to the category page below posts list.
244
- * Added option show post author.
245
- * Added option to format the outputted date string.
246
-
247
- = 4.1.3 =
248
- * Added option to hide widget, if category have currently no posts.
249
-
250
- = 4.1.2 =
251
- * Fixed hide title bug.
252
-
253
- = 4.1.1 =
254
- * Added option to put thumbnail on top.
255
- * Added option to show/hide the title.
256
- * Fixed no background bug.
257
-
258
- = 4.1.0 =
259
- * Added PHP5 Constructor.
260
- * Added Option to allow/disallow widget CSS.
261
- * Now, compatible with WordPress 4.3.
262
- * Meet new plugin author [kometschuh](https://profiles.wordpress.org/kometschuh)
263
-
264
- = 4.0 =
265
- * Added CSS file for post styling.
266
- * Now compatible with latest versions of WordPress.
267
-
268
- = 3.3 =
269
- * Fixed random sort bug.
270
-
271
- = 3.2 =
272
- * Added option to change ordering of posts. Defaults to showing newest posts first.
273
-
274
- = 3.1 =
275
- * Fixed a bug in the thumbnail size registration routine.
276
-
277
- = 3.0 =
278
- * Added support for WP 2.9's post thumbnail feature.
279
- * Removed support for Simple Post Thumbnails plugin.
280
- * Added option to show the post date.
281
- * Added option to set the excerpt length.
282
- * Added option to show the number of comments.
283
-
284
- = 2.3 =
285
- * Really tried to fix bug where wp_query global was getting over written by manually instantiating a WP_Query object.
286
-
287
- = 2.1 =
288
- * Fixed bug where wp_query global was getting over written.
289
-
290
- = 2.0 =
291
- * Updated to use the WP 2.8 widget API.
292
- * Added support for [Simple Post Thumbnails plugin](http://wordpress.org/extend/plugins/simple-post-thumbnails/).
 
 
 
1
+ === Category Posts Widget ===
2
+ Contributors: mark-k, kometschuh, mkrdip
3
+ Donate link: https://wordpress.org/support/plugin/category-posts/reviews/
4
+ Tags: category, categories, posts, widget, posts widget, recent posts, category recent posts, shortcode, sidebar, excerpt, multiple widgets
5
+ Requires at least: 2.8
6
+ Tested up to: 5.4
7
+ Stable tag: 4.9.4
8
+ License: GPLv2 or later
9
+ License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
+
11
+ Adds a widget that shows the most recent posts from a single category.
12
+
13
+ == Description ==
14
+ Category Posts Widget is a light widget designed to do one thing and do it well: display the most recent posts from a certain category.
15
+
16
+ = Term and Category based Posts Widget =
17
+ A premium version of that free widget available at [tiptoppress.com](http://tiptoppress.com/) created for big Wordpress sites.
18
+
19
+ = Premium features =
20
+ * Image-Slider
21
+ * Post List "Alterations"
22
+ * Full background post images
23
+ * Masonry (responsive layouts), Grid and Column full page layouts
24
+ * More complex ways to filter (ANY, NOT, AND, not include children)
25
+ * Custom Post Types, Events, Products support
26
+ * Add-ons
27
+ * All free features
28
+ * E-Mail support
29
+ * Free trial on localhost
30
+ * More examples on the [demo pages](http://demo.tiptoppress.com/)
31
+
32
+ = Features =
33
+ * [Template](http://tiptoppress.com/template-arrange-post-details/) to arrange the post details.
34
+ * The Template text can be a post details placeholder, plain text, HTML or a font-icons.
35
+ * Font-icon support.
36
+ * 'Load more' button / Ajax API
37
+ * Shortcode (Easily change all Shortcode options in the customizer).
38
+ * Date range filter
39
+ * New date format: Time since plublished
40
+ * Filter by post status: Published, scheduled, private.
41
+ * Multiple shortcodes at the same site or post.
42
+ * Add option for post offset (use two or more widgets after another).
43
+ * Admin UI: Buttons in the editor toolbar to insert shortcode.
44
+ * Excerpt length in lines (line-clamp)
45
+ * Option to touch device friendly "everything is a link".
46
+ * For editing shortcode adds a Customizer link to the admin-bar ("With one click to the Customizer").
47
+ * Set thumbnail width & height / image crop with CSS (object-fit).
48
+ * Fluid images (max-width in %).
49
+ * One thumb dimension can be left empty.
50
+ * Option to set mouse hover effects for post thumbnail.
51
+ * Set a default thumbnail.
52
+ * Hide widget text or text, if there is no post.
53
+ * Option to hide posts which have no thumbnail.
54
+ * Option exclude current post.
55
+ * Option show post author, comment's count, post date.
56
+ * Admin UI: Set / find thumbnail size buttons: +, ¼, ½, 2x, -, ratio and Media sizes
57
+ * Admin UI: Buttons to easy add post details placeholder.
58
+ * Multi sites support.
59
+
60
+ = Documentation =
61
+ * Full [documentation](http://tiptoppress.com/category-posts-widget/documentation-4-9)
62
+ * Shortcode: Use [catposts] in the content and [edit in the customizer](http://tiptoppress.com/use-shortcode-to-add-category-posts-widget-to-the-content/)
63
+ * Formatting date and time: See <a target="_blank" href="https://codex.wordpress.org/Formatting_Date_and_Time">Formatting Date and Time</a>
64
+
65
+ = Contribute =
66
+ While using this plugin if you find any bug or any conflict, please submit an issue at
67
+ [Github](https://github.com/tiptoppress/category-posts-widget) (If possible with a pull request).
68
+
69
+ == Installation ==
70
+ = Automatic installation =
71
+ Automatic installation is the easiest option as WordPress handles the file transfers itself and you don’t need to leave your web browser. To do an automatic install of Category Posts Widget,
72
+
73
+ 1. log in to your WordPress dashboard, navigate to the Plugins menu and click Add New.
74
+ 2. In the search field type “Category Posts Widget” and click Search Plugins.
75
+ 3. Once you’ve found plugin, you can install it by simply clicking “Install Now”.
76
+ 4. Then, go to plugins page of WordPress admin activate the plugin.
77
+ 5. Now, goto the Widgets page of the Appearance section and configure the Category Posts widget.
78
+
79
+ = Manual installation =
80
+ 1. Download the plugin.
81
+ 2. Upload it to the plugins folder of your blog.
82
+ 3. Activate the plugin through the 'Plugins' menu in WordPress
83
+ 4. Now, goto the Widgets page of the Appearance section and configure the Category Posts widget.
84
+
85
+ == Upgrade Notice ==
86
+ * Please consider to re-configure the widget as the latest version has numerous changes from previous.
87
+ * Version 4.0 uses CSS file for styling the widget in front end.
88
+ * Version 3.0 or later version uses WordPress 2.9's built in post thumbnail functionality.
89
+
90
+ == Frequently Asked Questions ==
91
+ = Template, placeholder and post detail =
92
+ Here You can control the [Post Detail parts](http://tiptoppress.com/category-posts-widget/documentation-4-9/#Post_details), which appears as part of the post item. All post detail will placed as placeholder. The text in the Template area can be a post details placeholder, plain text, HTML or HTML for SVG icons.
93
+
94
+ [How it works? and examples.](http://tiptoppress.com/template-arrange-post-details/)
95
+
96
+ For more layout options please try our premium widget: [Term and Category based Posts Widget](http://tiptoppress.com/term-and-category-based-posts-widget/).
97
+
98
+ = Use SVG icons =
99
+ For SVG font-icon HTML we recommend the [WordPress Dashicons](https://developer.wordpress.org/resource/dashicons/), which are included as default and can be used without any font-icon including.
100
+
101
+ = How to use Page Bilder plugins like Divi, SiteOrigin Page Builder or Elementor =
102
+ Please read more about Page Builder plugins at our [FAQs](http://tiptoppress.com/faqs/)
103
+
104
+ = Parse error: syntax error, unexpected T_FUNCTION in /home/www/blog/wp-content/plugins/category-posts/cat-posts.php on line 58 =
105
+ Some of the features that were used in that version needs PHP 5.3+.
106
+ We apologies for any headache this may cause you, but frankly it is better for you to check with your hosting company how can you upgrade the PHP version that you are using, and not only in order to use this plugin. PHP 5.2 should be considered insecure now, and for your own sake you should upgrade.
107
+ PHP 5.2 is very old and any support for it from the php developers had ended more then 5 years ago [php.net/eol.php](http://php.net/eol.php).
108
+ We know there are peopel how use PHP 5.2 [wordpress.org/about/stats](https://wordpress.org/about/stats/) and we can't imagine this people will have no other problems, if they don't update.
109
+
110
+ = You check the PHP version with phpversion(), but the widget don't work =
111
+ Check also the .htaccess file, if there is an entry for an older PHP version.
112
+
113
+ = Excerpt length in lines don't work with FireFox and IE =
114
+ We use for Excerpt length in lines a CSS feature called "line-clamp" which isn't supported in FireFox and IE at the moment.
115
+ But since it is supported by all other browsers, we think it will be supported in FireFox and IE soon.
116
+ The FireFox browser has a coverage of 5%, which we find little. For this 5%, we have included a polyfill in our [Excerpt Extension add-on](https://wordpress.org/plugins/excerpt-extension/).
117
+
118
+ == Screenshots ==
119
+ 1. Front end of the widget with SVG font-icon support for post formats, hover effects and the Template text-area.
120
+ 2. Template to arrange the post details with placeholders.
121
+ 3. Edit the widget options with the customizer.
122
+ 4. Use shortcode [catposts] in the content.
123
+ 5. The widget configuration dialog.
124
+ 6. Widget behaviour settings for each user.
125
+
126
+ == Changelog ==
127
+ [Read more on our blog ...](http://tiptoppress.com/category/category-posts-widget)
128
+
129
+ = 4.9.4 - March 2th 2020 =
130
+ * Fixed Delete global click event
131
+
132
+ = 4.9.3 - March 18th 2020 =
133
+ * Fixed Mouse hover icon and post format indication
134
+
135
+ = 4.9.2 - Mai 23th 2019 =
136
+ * Fixed Starts with post
137
+ * Fixed Replace the figure-element
138
+
139
+ = 4.9.1 - Mai 17th 2019 =
140
+ * 'Load more' button / Ajax API
141
+ * Data range filter
142
+ * Text, if there is no post
143
+ * Excerpt length in lines (line-clamp)
144
+ * Image crop with CSS (object-fit)
145
+ * Fluid images (max-width in %).
146
+ * One thumb dimension can be left empty
147
+ * Admin UI: Button to easy add post details placeholder
148
+ * Admin UI: Set / find thumbnail size buttons: +, ¼, ½, 2x, -, ratio and Media sizes
149
+
150
+ = 4.8.5 - April 02nd 2018 =
151
+ * Fixed Tabs not working
152
+
153
+ = 4.8.4 - April 02nd 2018 =
154
+ * Fixed Make widget SiteOrigin Page Builder Compatible
155
+
156
+ = 4.8.3 - March 03th 2018 =
157
+ * Fixed Updated widget with zero for the thumb dimensions caused a JavaScript error
158
+
159
+ = 4.8.2 - January 30th 2018 =
160
+ * Fixed Adding the widget with the customizer only the title is shown
161
+ * Fixed Recognize "Empty lines" > Next line is a paragraph in the Template in widget areas
162
+
163
+ = 4.8.1 - January 25th 2018 =
164
+ * Fixed Recognize "Empty lines" > Next line is a paragraph in the Template
165
+
166
+ = 4.8 - January 22th 2018 =
167
+ * SVG font-icon support for post formats
168
+ * Template to arrange the post details
169
+ * Premade Templates
170
+ * Date format: Time since plublished
171
+ * Filter by post status: Published, scheduled, private
172
+ * Hover effect: SVG font-icon
173
+
174
+ = 4.7.4 - October 21th 2017 =
175
+ * Bugfix for filter by post status (note private)
176
+
177
+ = 4.7.3 - October 10th 2017 =
178
+ * Add option to filter by post status
179
+ * Fixed footer section do not change when switching to and from "all posts"
180
+
181
+ = 4.7.2 - February 25th 2017 =
182
+ * Add option to disable only the font styles
183
+ * Fixed if option 'Everything is a link' no closing anchor tag
184
+ * Fixed if option 'Everyting is a link' wrong layout
185
+ * Fixed when a manual excerpt is provided, use it instead of generating an automatic one
186
+ * Fixed if option 'Disable the built-in CSS' the thumbnail client-side cropping isn't disabled
187
+ * Fixed if option 'Disable the built-in CSS' title class is not rendered
188
+ * Fixed when having multi shortcodes, clicking on a checkbox label marks in any of them selects the one in the "first"
189
+ * Fixed if option 'CSS crop to requested size' for multi shortcodes
190
+ * Fixed for CSS animation
191
+
192
+ = 4.7.1 - December 20th 2016 =
193
+ * Support multiple shortcodes in content
194
+ * Add option for post offset (use two or more widgets after another)
195
+ * Fluid images for Responsive Layouts
196
+ * Set a thumbnail as default thumbnail
197
+ * Add option to enable excerpt filters from Themes and plugins
198
+ * Add option to disable social buttons, banner, ... in the excerpt
199
+ * Add dropdownbox entry for 'all' categories
200
+ * Add option to disable subcategories
201
+ * Add insert shortcode buttons to the editor toolbar
202
+ * Use WP user profile for settings ('auto close' and if the shortcode button appears in the editor toolbar)
203
+ * Simple API for external use
204
+ * Support localization with translate.wordpress.org: Portuguese (Brazil) thank you [Henrique Vianna](https://profiles.wordpress.org/hvianna/) and German by [Daniel Floeter](https://profiles.wordpress.org/kometschuh/)
205
+ * Remove allow_html option (Instead we recommend to use the [manual excerpt](https://codex.wordpress.org/Excerpt#How_to_add_excerpts_to_posts) or we support this option furthermore in the [Term Posts Excerpt Extension](https://github.com/tiptoppress/term-posts-excerpt-extension) for the premium version)
206
+
207
+ = 4.6.2 - August 28th 2016 =
208
+ * Fixed only five widget instances can be costumized with shortcodes.
209
+ * For editing shortcode adds a customizer link to the admin-bar if page/post is in edit mode.
210
+
211
+ = 4.6.1 - June 5th 2016 =
212
+ * Add shortcode [catposts] edit options only in the customizer
213
+ * Keep panels open after save.
214
+ * Option to hide social buttons on output.
215
+
216
+ = 4.1.9 - May 5th 2016 =
217
+ * Fixed undefined constant.
218
+
219
+ = 4.1.8 - May 3th 2016 =
220
+ * Add mouse hover effects: blur
221
+ * Add option to choose allowed HTML in the excerpt
222
+ * Add Jetpack 'Sharing - Show buttons on posts' support
223
+ * Fixed division by zero bug (for small uploaded images)
224
+
225
+ = 4.1.7 - April 14th 2016 =
226
+ * Fixed division by zero bug.
227
+
228
+ = 4.1.6 - April 13th 2016 =
229
+ * Add option CSS cropping for thumbnails.
230
+ * Add option to set mouse hover effects for post thumbnail.
231
+ * Add option to change the excerpt more text.
232
+ * Add option to allow links in the excerpt
233
+ * Add filter 'widget_title' for the title
234
+ * Add option to hide post titles.
235
+
236
+ = 4.1.5 - February 4th 2016 =
237
+ * Support for multi sites.
238
+ * Support for localization.
239
+ * Area UI.
240
+ * Meet new plugin author [mark-k](https://profiles.wordpress.org/mark-k/)
241
+
242
+ = 4.1.4 =
243
+ * Added option exclude current post.
244
+ * Added option to hide posts which have no thumbnail.
245
+ * Added option to make the widget date link to the category page.
246
+ * Added option to link to the category page below posts list.
247
+ * Added option show post author.
248
+ * Added option to format the outputted date string.
249
+
250
+ = 4.1.3 =
251
+ * Added option to hide widget, if category have currently no posts.
252
+
253
+ = 4.1.2 =
254
+ * Fixed hide title bug.
255
+
256
+ = 4.1.1 =
257
+ * Added option to put thumbnail on top.
258
+ * Added option to show/hide the title.
259
+ * Fixed no background bug.
260
+
261
+ = 4.1.0 =
262
+ * Added PHP5 Constructor.
263
+ * Added Option to allow/disallow widget CSS.
264
+ * Now, compatible with WordPress 4.3.
265
+ * Meet new plugin author [kometschuh](https://profiles.wordpress.org/kometschuh)
266
+
267
+ = 4.0 =
268
+ * Added CSS file for post styling.
269
+ * Now compatible with latest versions of WordPress.
270
+
271
+ = 3.3 =
272
+ * Fixed random sort bug.
273
+
274
+ = 3.2 =
275
+ * Added option to change ordering of posts. Defaults to showing newest posts first.
276
+
277
+ = 3.1 =
278
+ * Fixed a bug in the thumbnail size registration routine.
279
+
280
+ = 3.0 =
281
+ * Added support for WP 2.9's post thumbnail feature.
282
+ * Removed support for Simple Post Thumbnails plugin.
283
+ * Added option to show the post date.
284
+ * Added option to set the excerpt length.
285
+ * Added option to show the number of comments.
286
+
287
+ = 2.3 =
288
+ * Really tried to fix bug where wp_query global was getting over written by manually instantiating a WP_Query object.
289
+
290
+ = 2.1 =
291
+ * Fixed bug where wp_query global was getting over written.
292
+
293
+ = 2.0 =
294
+ * Updated to use the WP 2.8 widget API.
295
+ * Added support for [Simple Post Thumbnails plugin](http://wordpress.org/extend/plugins/simple-post-thumbnails/).