Ditty News Ticker - Version 3.0.21

Version Description

  • Dashboard menu order updates
Download this release

Release Info

Developer metaphorcreations
Plugin Icon 128x128 Ditty News Ticker
Version 3.0.21
Comparing to
See all releases

Code changes from version 3.0.20 to 3.0.21

ditty-news-ticker.php CHANGED
@@ -4,7 +4,7 @@
4
  * Plugin Name: Ditty (formerly Ditty News Ticker)
5
  * Plugin URI: https://www.metaphorcreations.com/ditty
6
  * Description: Formerly Ditty News Ticker. Ditty is a multi-functional data display plugin.
7
- * Version: 3.0.20
8
  * Author: Metaphor Creations
9
  * Author URI: https://www.metaphorcreations.com
10
  * License: GPL-2.0+
@@ -20,7 +20,7 @@ if ( ! defined( 'WPINC' ) ) {
20
 
21
  // Plugin version.
22
  if ( ! defined( 'DITTY_VERSION' ) ) {
23
- define( 'DITTY_VERSION', '3.0.20' );
24
  }
25
 
26
  // Plugin Folder Path.
4
  * Plugin Name: Ditty (formerly Ditty News Ticker)
5
  * Plugin URI: https://www.metaphorcreations.com/ditty
6
  * Description: Formerly Ditty News Ticker. Ditty is a multi-functional data display plugin.
7
+ * Version: 3.0.21
8
  * Author: Metaphor Creations
9
  * Author URI: https://www.metaphorcreations.com
10
  * License: GPL-2.0+
20
 
21
  // Plugin version.
22
  if ( ! defined( 'DITTY_VERSION' ) ) {
23
+ define( 'DITTY_VERSION', '3.0.21' );
24
  }
25
 
26
  // Plugin Folder Path.
includes/class-ditty-item-type-posts-lite.php CHANGED
@@ -73,7 +73,31 @@ class Ditty_Item_Type_Posts_Lite extends Ditty_Item_Type {
73
  'contentSettings' => method_exists( $this, 'content_settings' ) ? $this->content_settings( $values ) : false,
74
  'linkSettings' => method_exists( $this, 'link_settings' ) ? $this->link_settings( $values ) : false,
75
  );
76
- return $fields;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
  }
78
 
79
  /**
@@ -96,6 +120,7 @@ class Ditty_Item_Type_Posts_Lite extends Ditty_Item_Type {
96
  'title_link' => 'default',
97
  'link_target' => '_self',
98
  'link_nofollow' => '',
 
99
  );
100
  return apply_filters( 'ditty_type_default_settings', $defaults, $this->slug );
101
  }
73
  'contentSettings' => method_exists( $this, 'content_settings' ) ? $this->content_settings( $values ) : false,
74
  'linkSettings' => method_exists( $this, 'link_settings' ) ? $this->link_settings( $values ) : false,
75
  );
76
+ return apply_filters( 'ditty_item_type_fields', $fields, $this, $values );
77
+ }
78
+
79
+ /**
80
+ * Set the allowed layout tags
81
+ *
82
+ * @access public
83
+ * @since 3.0.21
84
+ */
85
+ public function layout_tags() {
86
+ $allowed_tags = array(
87
+ 'author_avatar',
88
+ 'author_bio',
89
+ 'author_name',
90
+ 'categories',
91
+ 'content',
92
+ 'excerpt',
93
+ 'icon',
94
+ 'image',
95
+ 'image_url',
96
+ 'permalink',
97
+ 'time',
98
+ 'title',
99
+ );
100
+ return $allowed_tags;
101
  }
102
 
103
  /**
120
  'title_link' => 'default',
121
  'link_target' => '_self',
122
  'link_nofollow' => '',
123
+ //'layout_tag_title' => array(),
124
  );
125
  return apply_filters( 'ditty_type_default_settings', $defaults, $this->slug );
126
  }
includes/class-ditty-item-type.php CHANGED
@@ -109,7 +109,7 @@ class Ditty_Item_Type {
109
  * Setup the type settings
110
  *
111
  * @access public
112
- * @since 3.0
113
  */
114
  public function settings( $item_values = false, $action = 'render' ) {
115
  $values = $this->get_values( $item_values );
@@ -117,6 +117,16 @@ class Ditty_Item_Type {
117
  ditty_fields( $fields, $values, $action );
118
  }
119
 
 
 
 
 
 
 
 
 
 
 
120
  /**
121
  * Get values to populate the metabox
122
  *
109
  * Setup the type settings
110
  *
111
  * @access public
112
+ * @since 3.21
113
  */
114
  public function settings( $item_values = false, $action = 'render' ) {
115
  $values = $this->get_values( $item_values );
117
  ditty_fields( $fields, $values, $action );
118
  }
119
 
120
+ /**
121
+ * Set the allowed layout tags
122
+ *
123
+ * @access public
124
+ * @since 3.0.21
125
+ */
126
+ public function layout_tags() {
127
+ return array();
128
+ }
129
+
130
  /**
131
  * Get values to populate the metabox
132
  *
includes/class-ditty-items.php CHANGED
@@ -396,8 +396,6 @@ class Ditty_Items {
396
  unset( $_POST['security'] );
397
  unset( $_POST['item_id'] );
398
 
399
- //ChromePhp::log( '$item_id_ajax: ', $item_id_ajax );
400
-
401
  $editor_item = new Ditty_Item( $item_id_ajax );
402
  $editor_item->set_item_value( $_POST );
403
 
396
  unset( $_POST['security'] );
397
  unset( $_POST['item_id'] );
398
 
 
 
399
  $editor_item = new Ditty_Item( $item_id_ajax );
400
  $editor_item->set_item_value( $_POST );
401
 
includes/class-ditty.php CHANGED
@@ -264,6 +264,7 @@ class Ditty {
264
  require_once DITTY_DIR . 'includes/helpers.php';
265
  require_once DITTY_DIR . 'includes/hooks.php';
266
  require_once DITTY_DIR . 'includes/layout-tags.php';
 
267
  require_once DITTY_DIR . 'includes/layout-tag-helpers.php';
268
  require_once DITTY_DIR . 'includes/layout-tag-hooks.php';
269
  require_once DITTY_DIR . 'includes/layout-tag-hooks-default.php';
264
  require_once DITTY_DIR . 'includes/helpers.php';
265
  require_once DITTY_DIR . 'includes/hooks.php';
266
  require_once DITTY_DIR . 'includes/layout-tags.php';
267
+ //require_once DITTY_DIR . 'includes/layout-tag-fields.php';
268
  require_once DITTY_DIR . 'includes/layout-tag-helpers.php';
269
  require_once DITTY_DIR . 'includes/layout-tag-hooks.php';
270
  require_once DITTY_DIR . 'includes/layout-tag-hooks-default.php';
includes/helpers.php CHANGED
@@ -1250,7 +1250,7 @@ function ditty_border_styles_array() {
1250
  /**
1251
  * Prepare display items
1252
  *
1253
- * @since 3.0.5
1254
  * @var $eases array
1255
  */
1256
  function ditty_prepare_display_items( $meta ) {
@@ -1262,7 +1262,7 @@ function ditty_prepare_display_items( $meta ) {
1262
  return $prepared_items;
1263
  }
1264
  $defaults = $item_type_object->default_settings();
1265
- $args = shortcode_atts( $defaults, $meta['item_value'] );
1266
  $meta['item_value'] = $args;
1267
 
1268
  return $item_type_object->prepare_items( $meta );
1250
  /**
1251
  * Prepare display items
1252
  *
1253
+ * @since 3.0.21
1254
  * @var $eases array
1255
  */
1256
  function ditty_prepare_display_items( $meta ) {
1262
  return $prepared_items;
1263
  }
1264
  $defaults = $item_type_object->default_settings();
1265
+ $args = wp_parse_args( $meta['item_value'], $defaults );
1266
  $meta['item_value'] = $args;
1267
 
1268
  return $item_type_object->prepare_items( $meta );
includes/hooks.php CHANGED
@@ -158,10 +158,15 @@ add_filter( 'admin_body_class', 'ditty_dashboard_menu_classes', 99 );
158
  /**
159
  * Reorder the menu items
160
  *
161
- * @since 3.0.20
162
  */
163
  function ditty_dashboard_menu_order( $menu_ord ) {
164
  global $submenu;
 
 
 
 
 
165
  $current_menu = $submenu['edit.php?post_type=ditty'];
166
  $current_order = array();
167
  $new_menu = array();
@@ -179,10 +184,12 @@ function ditty_dashboard_menu_order( $menu_ord ) {
179
  ), $current_menu );
180
 
181
  // Find any extra items that aren't in the order list
182
- foreach ( $current_menu as $i => $item ) {
183
- $current_order[] = $item[2];
184
- if ( ! in_array( $item[2], $order ) ) {
185
- $extra_items[] = $item;
 
 
186
  }
187
  }
188
 
@@ -191,17 +198,21 @@ function ditty_dashboard_menu_order( $menu_ord ) {
191
 
192
  // Set the order of the new menu
193
  while( count( $order ) > 0 ) {
194
- foreach ( $current_menu as $i => $item ) {
195
- if ( count( $order) > 0 && $order[0] == $item[2] ) {
196
- $new_menu[] = $item;
197
- array_shift( $order );
 
 
198
  }
199
  }
200
  }
201
 
202
  // Add extra menu items not in the order list
203
- foreach ( $extra_items as $i => $item ) {
204
- $new_menu[] = $item;
 
 
205
  }
206
 
207
  // Set the new menu
@@ -209,65 +220,4 @@ function ditty_dashboard_menu_order( $menu_ord ) {
209
 
210
  return $menu_ord;
211
  }
212
- add_filter( 'custom_menu_order', 'ditty_dashboard_menu_order' );
213
-
214
- /**
215
- * Reorder the Ditty submenus
216
- *
217
- * @since 3.0
218
- * @access public
219
- * @var array $allowed
220
- */
221
- // function ditty_set_menu_order() {
222
- // global $submenu;
223
- // $new_sub_menu = [];
224
- // foreach ( $submenu as $menu_name => $menu_items ) {
225
- // if ( 'edit.php?post_type=ditty' === $menu_name ) {
226
- // if ( is_array( $menu_items ) && count( $menu_items ) > 0 ) {
227
- // foreach ( $menu_items as $order => $menu_item ) {
228
- // switch( $menu_item[2] ) {
229
- // case 'edit.php?post_type=ditty_layout':
230
- // $new_sub_menu[11] = $menu_item;
231
- // break;
232
- // case 'edit.php?post_type=ditty_display':
233
- // $new_sub_menu[12] = $menu_item;
234
- // break;
235
- // case 'ditty_extensions':
236
- // $new_sub_menu[13] = $menu_item;
237
- // break;
238
- // case 'ditty_settings':
239
- // $new_sub_menu[14] = $menu_item;
240
- // break;
241
- // case 'ditty_export':
242
- // $new_sub_menu[15] = $menu_item;
243
- // break;
244
- // default:
245
- // $new_sub_menu[$order] = $menu_item;
246
- // }
247
- // }
248
- // }
249
- // $submenu['edit.php?post_type=ditty'] = $new_sub_menu;
250
- // break;
251
- // }
252
- // }
253
- // }
254
- // add_action('custom_menu_order', 'ditty_set_menu_order' );
255
-
256
-
257
-
258
- function sdafdstest() {
259
- $custom = Ditty()->db_item_meta->custom_meta( 129 );
260
- if ( $custom ) {
261
- echo '<pre>';print_r('yes');echo '</pre>';
262
- } else {
263
- echo '<pre>';print_r('no');echo '</pre>';
264
- }
265
- if ( is_array( $custom ) && count( $custom ) > 0 ) {
266
- foreach ( $custom as $data ) {
267
- if ( isset( $data->meta_key ) ) {
268
- Ditty()->db_item_meta->delete_meta( 129, $data->meta_key );
269
- }
270
- }
271
- }
272
- }
273
- //add_action( 'admin_init', 'sdafdstest' );
158
  /**
159
  * Reorder the menu items
160
  *
161
+ * @since 3.0.21
162
  */
163
  function ditty_dashboard_menu_order( $menu_ord ) {
164
  global $submenu;
165
+
166
+ if ( ! isset( $submenu['edit.php?post_type=ditty'] ) ) {
167
+ return $menu_ord;
168
+ }
169
+
170
  $current_menu = $submenu['edit.php?post_type=ditty'];
171
  $current_order = array();
172
  $new_menu = array();
184
  ), $current_menu );
185
 
186
  // Find any extra items that aren't in the order list
187
+ if ( is_array( $current_menu ) && count( $current_menu ) > 0 ) {
188
+ foreach ( $current_menu as $i => $item ) {
189
+ $current_order[] = $item[2];
190
+ if ( ! in_array( $item[2], $order ) ) {
191
+ $extra_items[] = $item;
192
+ }
193
  }
194
  }
195
 
198
 
199
  // Set the order of the new menu
200
  while( count( $order ) > 0 ) {
201
+ if ( is_array( $current_menu ) && count( $current_menu ) > 0 ) {
202
+ foreach ( $current_menu as $i => $item ) {
203
+ if ( count( $order) > 0 && $order[0] == $item[2] ) {
204
+ $new_menu[] = $item;
205
+ array_shift( $order );
206
+ }
207
  }
208
  }
209
  }
210
 
211
  // Add extra menu items not in the order list
212
+ if ( is_array( $extra_items ) && count( $extra_items ) > 0 ) {
213
+ foreach ( $extra_items as $i => $item ) {
214
+ $new_menu[] = $item;
215
+ }
216
  }
217
 
218
  // Set the new menu
220
 
221
  return $menu_ord;
222
  }
223
+ add_filter( 'custom_menu_order', 'ditty_dashboard_menu_order' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/layout-tag-fields.php ADDED
@@ -0,0 +1,143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Add fields to modify layout tag attributes
5
+ *
6
+ * @access public
7
+ * @since 3.0.21
8
+ */
9
+ function ditty_item_type_layout_tag_fields( $fields, $item_type, $values ) {
10
+ $all_tags = ditty_layout_tags( $item_type->get_type() );
11
+ $item_type_tags = $item_type->layout_tags();
12
+ $layout_tags = array_intersect_key( $all_tags, array_flip( $item_type_tags ) );
13
+
14
+ if ( is_array( $layout_tags ) && count( $layout_tags ) > 0 ) {
15
+ foreach ( $layout_tags as $tag => $data ) {
16
+ $atts = isset( $data['atts'] ) ? $data['atts'] : array();
17
+ if ( ! is_array( $atts ) || count( $atts ) < 1 ) {
18
+ continue;
19
+ }
20
+
21
+ $attribute_fields = array();
22
+ foreach ( $atts as $att => $default ) {
23
+ $name = ucwords( implode( ' ', explode( '_', $att ) ) );
24
+ $field = array(
25
+ 'type' => 'text',
26
+ 'id' => $att,
27
+ 'name' => $name,
28
+ 'help' => sprintf( esc_html__( "Customize the '%s' attribute.", 'ditty-news-ticker' ), $att ),
29
+ 'std' => isset( $values[$att] ) ? $values[$att] : false,
30
+ );
31
+ switch( $att ) {
32
+ case 'wrapper':
33
+ $field['type'] = 'select';
34
+ $field['options'] = ditty_layout_wrapper_options();
35
+ break;
36
+ case 'fit':
37
+ $field['type'] = 'select';
38
+ $field['options'] = ditty_layout_object_fit_options();
39
+ break;
40
+ case 'link_target':
41
+ $field['type'] = 'select';
42
+ $field['options'] = ditty_layout_link_target_options();
43
+ break;
44
+ default:
45
+ break;
46
+ }
47
+ $attribute_fields[$att] = $field;
48
+ }
49
+
50
+ $tag_name = sprintf( esc_html__( '%s Settings', 'ditty-news-ticker' ), ucwords( implode( ' ', explode( '_', $tag ) ) ) );
51
+ $fields["layout_tag_{$tag}"] = array(
52
+ 'type' => 'group',
53
+ 'id' => "layout_tag_{$tag}",
54
+ 'collapsible' => true,
55
+ 'default_state' => 'collapsed',
56
+ 'name' => $tag_name,
57
+ //'help' => esc_html__( 'Configure the display of the author avatar tag.', 'ditty-news-ticker' ),
58
+ 'fields' => apply_filters( 'ditty_layout_tag_author_avatar_fields', $attribute_fields, $values ),
59
+ );
60
+ }
61
+ }
62
+ return $fields;
63
+ }
64
+ add_filter( 'ditty_item_type_fields', 'ditty_item_type_layout_tag_fields', 10, 3 );
65
+
66
+ /**
67
+ * Modify the layout tag atts
68
+ *
69
+ * @access public
70
+ * @since 3.0.21
71
+ */
72
+ function ditty_item_type_layout_tag_atts( $atts, $tag, $item_type, $data ) {
73
+ if ( ! isset( $data["layout_tag_{$tag}"] ) ) {
74
+ return $atts;
75
+ }
76
+ $trimmed_atts = array();
77
+ if ( is_array( $data["layout_tag_{$tag}"] ) && count( $data["layout_tag_{$tag}"] ) > 0 ) {
78
+ foreach ( $data["layout_tag_{$tag}"] as $att => $value ) {
79
+ if ( '' != $value ) {
80
+ $trimmed_atts[$att] = $value;
81
+ }
82
+ }
83
+ }
84
+ $parsed_atts = wp_parse_args( $trimmed_atts, $atts );
85
+ return $parsed_atts;
86
+ }
87
+ add_filter( 'ditty_layout_tag_atts', 'ditty_item_type_layout_tag_atts', 10, 4 );
88
+
89
+ /**
90
+ * Return layout wrapper options
91
+ *
92
+ * @access public
93
+ * @since 3.0.21
94
+ */
95
+ function ditty_layout_wrapper_options() {
96
+ $options = array(
97
+ '' => esc_html__( 'Use layout value', 'ditty-news-ticker' ),
98
+ 'none' => esc_html__( 'None', 'ditty-news-ticker' ),
99
+ 'div' => 'div',
100
+ 'p' => 'p',
101
+ 'span' => 'span',
102
+ 'h1' => 'h1',
103
+ 'h2' => 'h2',
104
+ 'h3' => 'h3',
105
+ 'h4' => 'h4',
106
+ 'h5' => 'h5',
107
+ 'h6' => 'h6',
108
+ );
109
+ return apply_filters( 'ditty_layout_wrapper_options', $options );
110
+ }
111
+
112
+ /**
113
+ * Return layout object fit options
114
+ *
115
+ * @access public
116
+ * @since 3.0.21
117
+ */
118
+ function ditty_layout_object_fit_options() {
119
+ $options = array(
120
+ 'default' => esc_html__( 'Use layout value', 'ditty-news-ticker' ),
121
+ 'none' => esc_html__( 'None', 'ditty-news-ticker' ),
122
+ 'fill' => 'fill',
123
+ 'contain' => 'contain',
124
+ 'cover' => 'cover',
125
+ 'scale-down' => 'scale-down',
126
+ );
127
+ return apply_filters( 'ditty_layout_object_fit_options', $options );
128
+ }
129
+
130
+ /**
131
+ * Return layout link target options
132
+ *
133
+ * @access public
134
+ * @since 3.0.21
135
+ */
136
+ function ditty_layout_link_target_options() {
137
+ $options = array(
138
+ 'default' => esc_html__( 'Use layout value', 'ditty-news-ticker' ),
139
+ '_blank' => '_blank',
140
+ '_self' => '_self',
141
+ );
142
+ return apply_filters( 'ditty_layout_link_target_options', $options );
143
+ }
includes/layout-tag-hooks-posts.php CHANGED
@@ -1,5 +1,35 @@
1
  <?php
2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  /**
4
  * Modify tag attributes based on settings
5
  *
@@ -72,36 +102,6 @@ function ditty_posts_lite_layout_tags( $tags, $item_type ) {
72
  }
73
  add_filter( 'ditty_layout_tags', 'ditty_posts_lite_layout_tags', 10, 2 );
74
 
75
- /**
76
- * Filter the available item tags for layout editing
77
- *
78
- * @since 3.0.20
79
- */
80
- function ditty_posts_lite_layout_tags_list( $tags, $item_type ) {
81
- if ( 'posts_feed' == $item_type ) {
82
- $item_types = ditty_item_types();
83
- if ( 'Ditty_Item_Type_Posts_Lite' == $item_types['posts_feed']['class_name'] ) {
84
- $allowed_tags = array(
85
- 'author_avatar',
86
- 'author_bio',
87
- 'author_name',
88
- 'categories',
89
- 'content',
90
- 'excerpt',
91
- 'icon',
92
- 'image',
93
- 'image_url',
94
- 'permalink',
95
- 'time',
96
- 'title',
97
- );
98
- $tags = array_intersect_key( $tags, array_flip( $allowed_tags ) );
99
- }
100
- }
101
- return $tags;
102
- }
103
- add_filter( 'ditty_layout_tags_list', 'ditty_posts_lite_layout_tags_list', 10, 2 );
104
-
105
  /**
106
  * Return a tag value
107
  *
1
  <?php
2
 
3
+ /**
4
+ * Filter the available item tags for layout editing
5
+ *
6
+ * @since 3.0.20
7
+ */
8
+ function ditty_posts_lite_layout_tags_list( $tags, $item_type ) {
9
+ if ( 'posts_feed' == $item_type ) {
10
+ $item_types = ditty_item_types();
11
+ if ( 'Ditty_Item_Type_Posts_Lite' == $item_types['posts_feed']['class_name'] ) {
12
+ $allowed_tags = array(
13
+ 'author_avatar',
14
+ 'author_bio',
15
+ 'author_name',
16
+ 'categories',
17
+ 'content',
18
+ 'excerpt',
19
+ 'icon',
20
+ 'image',
21
+ 'image_url',
22
+ 'permalink',
23
+ 'time',
24
+ 'title',
25
+ );
26
+ $tags = array_intersect_key( $tags, array_flip( $allowed_tags ) );
27
+ }
28
+ }
29
+ return $tags;
30
+ }
31
+ add_filter( 'ditty_layout_tags_list', 'ditty_posts_lite_layout_tags_list', 10, 2 );
32
+
33
  /**
34
  * Modify tag attributes based on settings
35
  *
102
  }
103
  add_filter( 'ditty_layout_tags', 'ditty_posts_lite_layout_tags', 10, 2 );
104
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
  /**
106
  * Return a tag value
107
  *
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_i
4
  Tags: ticker, post ticker, news ticker, content aggregator, latest posts, live refresh, rotator, data rotator, lists, data, aggregator
5
  Requires at least: 4.5
6
  Tested up to: 5.9.3
7
- Stable tag: 3.0.20
8
  License: GPL2
9
 
10
  Formerly Ditty News Ticker. Ditty is a multi-functional data display plugin.
@@ -66,6 +66,9 @@ The most common cause for an unresponsive Ditty (when using scroll or rotate mod
66
 
67
  == Changelog ==
68
 
 
 
 
69
  = 3.0.20 =
70
  * Layout tag filter updates
71
  * Dashboard menu order updates
@@ -708,4 +711,4 @@ The most common cause for an unresponsive Ditty (when using scroll or rotate mod
708
 
709
  == Upgrade Notice ==
710
 
711
- Layout tag filter updates & Dashboard menu order updates
4
  Tags: ticker, post ticker, news ticker, content aggregator, latest posts, live refresh, rotator, data rotator, lists, data, aggregator
5
  Requires at least: 4.5
6
  Tested up to: 5.9.3
7
+ Stable tag: 3.0.21
8
  License: GPL2
9
 
10
  Formerly Ditty News Ticker. Ditty is a multi-functional data display plugin.
66
 
67
  == Changelog ==
68
 
69
+ = 3.0.21 =
70
+ * Dashboard menu order updates
71
+
72
  = 3.0.20 =
73
  * Layout tag filter updates
74
  * Dashboard menu order updates
711
 
712
  == Upgrade Notice ==
713
 
714
+ Dashboard menu order updates