PluginProbe
WPGet API – Connect to any external REST API / 2.2.10
WPGet API – Connect to any external REST API v2.2.10
1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.1.0 2.1.1 2.1.3 2.1.4 2.1.5 2.2.0 2.2.1 2.2.10 2.2.2 2.2.3 All 97 releases
wpgetapi / lib / cmb2 / js / cmb2-char-counter.js

cmb2-char-counter.js in WPGet API – Connect to any external REST API 2.2.10, at lib/cmb2/js/cmb2-char-counter.js

212 lines 5.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Used for character counters
3 */
4 window.CMB2 = window.CMB2 || {};
5 window.CMB2.charcounter = window.CMB2.charcounter || {};
6
7 ( function(window, document, $, cmb, counter ) {
8 'use strict';
9
10 if ( ! wp.utils || ! wp.utils.WordCounter ) {
11 return cmb.log( 'Cannot find wp.utils!' );
12 }
13
14 // Private variables
15 counter.counters = {};
16 var counters = counter.counters;
17 var wpCounter = new wp.utils.WordCounter();
18
19 /**
20 * Update a field's character counter
21 *
22 * @since 2.7.0
23 *
24 * @param {string} field_id
25 *
26 * @return {int}
27 */
28 counter.updateCounter = function( field_id ) {
29 // No counter?
30 if ( ! counters.hasOwnProperty( field_id ) ) {
31 return null;
32 }
33
34 var instance = counters[ field_id ];
35 var wysiwyg = instance.editor && ! instance.editor.isHidden();
36
37 // Are we dealing with WYSIWYG visual editor, or textarea / WYSIWYG textarea?
38 var text = wysiwyg ? instance.editor.getContent( { format: 'raw' } ) : cmb.$id( field_id ).val().trim();
39 var count = wpCounter.count( text, instance.type );
40 var exceeded = instance.max && count > instance.max;
41
42 // Number remaining when max is defined
43 var val = instance.max ? instance.max - count : count;
44
45 // Over maximum?
46 instance.$el.parents( '.cmb2-char-counter-wrap' )[ exceeded ? 'addClass' : 'removeClass' ]( 'cmb2-max-exceeded' );
47
48 // Update counter, and update counter input width.
49 instance.$el.val( val ).outerWidth( ( ( 8 * String( val ).length ) + 15 ) + 'px' );
50
51 return count;
52 };
53
54 counter.instantiate = function( $el ) {
55 var data = $el.data();
56
57 // Add counter details if not already done
58 if ( ! ( data.fieldId in counters ) ) {
59
60 var instance = {
61 $el : $el,
62 max : data.max,
63 type : 'words' === data.counterType ? 'words' : 'characters_including_spaces',
64 editor : false,
65 };
66
67 counters[ data.fieldId ] = instance;
68
69 // Initialise counter
70 counter.updateCounter( data.fieldId );
71 }
72 };
73
74 /**
75 * Initializes all character counters. Hooked to cmb_init.
76 *
77 * @since 2.7.0
78 *
79 * @param {bool} init First init?
80 *
81 * @return {void}
82 */
83 counter.initAll = function() {
84
85 // Gather counters and initialise
86 $( '.cmb2-char-counter' ).each( function() {
87 counter.instantiate( $( this ) );
88 });
89 };
90
91 /**
92 * Initializes WYSIWYG editors. Hooked to tinymce-editor-init
93 *
94 * @since 2.7.0
95 *
96 * @param {object} evt
97 * @param {object} editor
98 *
99 * @return {void}
100 */
101 counter.initWysiwyg = function( evt, editor ) {
102
103 // Check if it's one of our WYSIWYGs
104 // Should have already been registered in counters via hidden textarea
105 if ( editor.id in counters ) {
106
107 // Add editor to counter
108 counters[ editor.id ].editor = editor;
109
110 // Add nodechange event
111 editor.on( 'nodechange keyup', counter.countWysiwyg );
112 }
113 };
114
115 /**
116 * Initializes after a new repeatable row has been added. Hooked to cmb2_add_row
117 *
118 * @since 2.7.0
119 *
120 * @param {object} evt A jQuery-normalized event object.
121 * @param {object} $row A jQuery dom element object for the group row.
122 *
123 * @return {void}
124 */
125 counter.addRow = function( evt, $row ) {
126
127 // Character counters in row?
128 $row.find( '.cmb2-char-counter' ).each( function() {
129
130 // Update attributes
131 var $this = $( this );
132 var id = $this.attr( 'id' );
133 var field_id = id.replace( /^char-counter-/, '' );
134 $this.attr( 'data-field-id', field_id ).data( 'field-id', field_id );
135
136 counter.instantiate( $this );
137 });
138 };
139
140 /**
141 * Clean the counters array.
142 * Removes counters after a repeatable row has been removed. Hooked to cmb2_remove_row.
143 *
144 * @since 2.7.0
145 *
146 * @return {void}
147 */
148 counter.cleanCounters = function() {
149 var field_id, remove = [];
150
151 // Got through counters
152 for ( field_id in counters ) {
153 // Check for element, gather for removal
154 if ( ! document.getElementById( field_id ) ) {
155 remove.push( field_id );
156 }
157 }
158
159 // Anything to remove?
160 if ( remove.length ) {
161 _.each( remove, function( field_id ) {
162 delete counters[ field_id ];
163 });
164 }
165 };
166
167 /**
168 * Counts the value of wysiwyg on the keyup event.
169 *
170 * @since 2.7.0
171 *
172 * @param {object} evt
173 *
174 * @return {void}
175 */
176 counter.countWysiwyg = _.throttle( function( evt ) {
177
178 // Init event
179 if ( evt.hasOwnProperty( 'element' ) ) {
180 return counter.updateCounter( $( evt.element ).data( 'id' ) );
181 }
182
183 // Nodechange event
184 if ( evt.hasOwnProperty( 'currentTarget' ) ) {
185 return counter.updateCounter( $( evt.currentTarget ).data( 'id' ) );
186 }
187
188 } );
189
190 /**
191 * Counts the value of textarea on the keyup event.
192 *
193 * @since 2.7.0
194 *
195 * @param {object} evt
196 *
197 * @return {void}
198 */
199 counter.countTextarea = _.throttle( function(evt) {
200 counter.updateCounter( evt.currentTarget.id );
201 }, 400 );
202
203 // Hook in our event callbacks.
204 $( document )
205 .on( 'cmb_init', counter.initAll )
206 .on( 'tinymce-editor-init', counter.initWysiwyg )
207 .on( 'cmb2_add_row', counter.addRow )
208 .on( 'cmb2_remove_row', counter.cleanCounters )
209 .on( 'input keyup', '.cmb2-count-chars', counter.countTextarea );
210
211 } )( window, document, jQuery, window.CMB2, window.CMB2.charcounter );
212