• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Yoast / wordpress-seo / d06ecddd1a2dfd570966e4466fc1ee34449e48a4

28 May 2024 08:44AM UTC coverage: 52.735% (+0.1%) from 52.604%
d06ecddd1a2dfd570966e4466fc1ee34449e48a4

Pull #21412

github

web-flow
Merge dff4c17b2 into 1cf35a642
Pull Request #21412: Feature/decouple hidden fields

7359 of 13368 branches covered (55.05%)

Branch coverage included in aggregate %.

63 of 297 new or added lines in 44 files covered. (21.21%)

22 existing lines in 16 files now uncovered.

28302 of 54255 relevant lines covered (52.16%)

41401.53 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/packages/js/src/initializers/primary-category.js
1
/* global wp, _, wpseoPrimaryCategoryL10n */
2
/* External dependencies */
3
import { dispatch, select } from "@wordpress/data";
4
import { Component } from "@wordpress/element";
5
import {
6
        get,
7
        noop,
8
} from "lodash";
9

10
/* Internal dependencies */
11
import PrimaryTaxonomyFilter from "../components/PrimaryTaxonomyFilter";
12
import isBlockEditor from "../helpers/isBlockEditor";
13

14
const PLUGIN_NAMESPACE = "yoast-seo";
×
15

16
/**
17
 * @summary Initializes the primary category integration.
18
 *
19
 * @param {object} $ jQuery
20
 *
21
 * @returns {void}
22
 */
23
export default function initPrimaryCategory( $ ) {
24
        var primaryTermUITemplate, primaryTermScreenReaderTemplate;
25
        var taxonomies = wpseoPrimaryCategoryL10n.taxonomies;
×
26

27
        /**
28
         * Checks if the elements to make a term the primary term and the display for a primary term exist.
29
         *
30
         * @param {Object} checkbox The checkbox to get the closest required fields for.
31
         *
32
         * @returns {boolean} True when there are primary elements.
33
         */
34
        function hasPrimaryTermElements( checkbox ) {
35
                return 1 === $( checkbox ).closest( "li" ).children( ".wpseo-make-primary-term" ).length;
×
36
        }
37

38
        /**
39
         * Retrieves the primary term for a taxonomy.
40
         *
41
         * @param {string} taxonomyName The taxonomy name.
42
         *
43
         * @returns {string} The value of the primary term.
44
         */
45
        function getPrimaryTerm( taxonomyName ) {
NEW
46
                const store = select( "yoast-seo/editor" );
×
NEW
47
                if ( store ) {
×
NEW
48
                        return store.getPrimaryTaxonomyId( taxonomyName );
×
49
                }
50

NEW
51
                const primaryTermInput = $( "#yoast_wpseo_primary_" + taxonomyName );
×
NEW
52
                return primaryTermInput ? primaryTermInput.val() : "";
×
53
        }
54

55
        /**
56
         * Gets the name of a term for the category taxonomy.
57
         *
58
         * @param {number} categoryTermId The terms's id.
59
         *
60
         * @returns {string} The term's name.
61
         */
62
        function getCategoryTermName( categoryTermId ) {
63
                const categoryListItem = $( "#category-all" )
×
64
                        .find( `#category-${ categoryTermId } > label` );
65
                if ( categoryListItem.length === 0 ) {
×
66
                        return "";
×
67
                }
68
                const clone = categoryListItem.clone();
×
69
                clone.children().remove();
×
70
                return clone.text().trim();
×
71
        }
72

73
        /**
74
         * Sets the primary term for a taxonomy.
75
         *
76
         * @param {string} taxonomyName The taxonomy name.
77
         * @param {string} termId       The term id.
78
         *
79
         * @returns {void}
80
         */
81
        function setPrimaryTerm( taxonomyName, termId ) {
82
                const yoastEditor = dispatch( "yoast-seo/editor" );
×
83
                if ( yoastEditor ) {
×
84
                        const termIdInt = parseInt( termId, 10 );
×
NEW
85
                        yoastEditor.setPrimaryTaxonomyId( taxonomyName, termId );
×
86
                        // If the taxonomy is category update the replacement variable.
87
                        if ( taxonomyName === "category" ) {
×
88
                                yoastEditor.updateReplacementVariable(
×
89
                                        "primary_category",
90
                                        getCategoryTermName( termIdInt )
91
                                );
92
                        }
93
                }
94
        }
95

96
        /**
97
         * Creates the elements necessary to show something is a primary term or to make it the primary term.
98
         *
99
         * @param {string} taxonomyName The taxonomy name.
100
         * @param {Object} checkbox     The checkbox to get label for.
101
         *
102
         * @returns {void}
103
         */
104
        function createPrimaryTermElements( taxonomyName, checkbox ) {
105
                var label, html;
106

107
                label = $( checkbox ).closest( "label" );
×
108

109
                html = primaryTermUITemplate( {
×
110
                        taxonomy: taxonomies[ taxonomyName ],
111
                        term: label.text(),
112
                } );
113

114
                label.after( html );
×
115
        }
116

117
        /**
118
         * Updates the primary term selectors/indicators for a certain taxonomy.
119
         *
120
         * @param {string} taxonomyName The taxonomy name.
121
         *
122
         * @returns {void}
123
         */
124
        function updatePrimaryTermSelectors( taxonomyName ) {
125
                var checkedTerms;
126
                var listItem, label;
127

128
                checkedTerms = $( "#" + taxonomyName + 'checklist input[type="checkbox"]:checked' );
×
129

130
                var taxonomyListItem = $( "#" + taxonomyName + "checklist li" );
×
131
                taxonomyListItem.removeClass( "wpseo-term-unchecked wpseo-primary-term wpseo-non-primary-term" );
×
132

133
                $( ".wpseo-primary-category-label" ).remove();
×
134
                taxonomyListItem.addClass( "wpseo-term-unchecked" );
×
135

136
                // If there is only one term selected we don't want to show our interface.
137
                if ( checkedTerms.length <= 1 ) {
×
138
                        return;
×
139
                }
140

141
                checkedTerms.each( function( i, term ) {
×
142
                        term = $( term );
×
143
                        listItem = term.closest( "li" );
×
144
                        listItem.removeClass( "wpseo-term-unchecked" );
×
145

146
                        // Create our interface elements if they don't exist.
147
                        if ( ! hasPrimaryTermElements( term ) ) {
×
148
                                createPrimaryTermElements( taxonomyName, term );
×
149
                        }
150

151
                        if ( term.val() === getPrimaryTerm( taxonomyName ) ) {
×
152
                                listItem.addClass( "wpseo-primary-term" );
×
153

154
                                label = term.closest( "label" );
×
155
                                label.find( ".wpseo-primary-category-label" ).remove();
×
156
                                label.append( primaryTermScreenReaderTemplate( {
×
157
                                        taxonomy: taxonomies[ taxonomyName ],
158
                                } ) );
159
                        } else {
160
                                listItem.addClass( "wpseo-non-primary-term" );
×
161
                        }
162
                } );
163
        }
164

165
        /**
166
         * Makes the first term primary for a certain taxonomy.
167
         *
168
         * @param {string} taxonomyName The taxonomy name.
169
         *
170
         * @returns {void}
171
         */
172
        function makeFirstTermPrimary( taxonomyName ) {
173
                var firstTerm = $( "#" + taxonomyName + 'checklist input[type="checkbox"]:checked:first' );
×
174

175
                setPrimaryTerm( taxonomyName, firstTerm.val() );
×
176
                updatePrimaryTermSelectors( taxonomyName );
×
177
        }
178

179
        /**
180
         * If we check a term while there is no primary term we make that one the primary term.
181
         *
182
         * @param {string} taxonomyName The taxonomy name.
183
         *
184
         * @returns {void}
185
         */
186
        function ensurePrimaryTerm( taxonomyName ) {
187
                if ( "" === getPrimaryTerm( taxonomyName ) ) {
×
188
                        makeFirstTermPrimary( taxonomyName );
×
189
                }
190
        }
191

192
        /**
193
         * Returns the term checkbox handler for a certain taxonomy name.
194
         *
195
         * @param {string} taxonomyName The taxonomy name.
196
         *
197
         * @returns {Function} Event handler for the checkbox.
198
         */
199
        function termCheckboxHandler( taxonomyName ) {
200
                return function() {
×
201
                        // If the user unchecks the primary category we have to select any new primary term
202
                        if ( false === $( this ).prop( "checked" ) && $( this ).val() === getPrimaryTerm( taxonomyName ) ) {
×
203
                                makeFirstTermPrimary( taxonomyName );
×
204
                        }
205

206
                        ensurePrimaryTerm( taxonomyName );
×
207

208
                        updatePrimaryTermSelectors( taxonomyName );
×
209
                };
210
        }
211

212
        /**
213
         * Returns the term list add handler for a certain taxonomy name.
214
         *
215
         * @param {string} taxonomyName The taxonomy name.
216
         *
217
         * @returns {Function} The term list add handler.
218
         */
219
        function termListAddHandler( taxonomyName ) {
220
                return function() {
×
221
                        ensurePrimaryTerm( taxonomyName );
×
222
                        updatePrimaryTermSelectors( taxonomyName );
×
223
                };
224
        }
225

226
        /**
227
         * Returns the make primary event handler for a certain taxonomy name.
228
         *
229
         * @param {string} taxonomyName The taxonomy name.
230
         *
231
         * @returns {Function} The event handler.
232
         */
233
        function makePrimaryHandler( taxonomyName ) {
234
                return function( e ) {
×
235
                        var term, checkbox;
236

237
                        term = $( e.currentTarget );
×
238
                        checkbox = term.siblings( "label" ).find( "input" );
×
239

240
                        setPrimaryTerm( taxonomyName, checkbox.val() );
×
241

242
                        updatePrimaryTermSelectors( taxonomyName );
×
243

244
                        // The clicked link will be hidden so we need to focus something different.
245
                        checkbox.trigger( "focus" );
×
246
                };
247
        }
248

249
        /**
250
         * Add primary taxonomy picker in Gutenberg.
251
         *
252
         * @returns {void}
253
         */
254
        function registerCategorySelectorFilter() {
255
                if ( ! isBlockEditor() ) {
×
256
                        return;
×
257
                }
258

259
                const addFilter = get( window, "wp.hooks.addFilter", noop );
×
260

261
                addFilter(
×
262
                        "editor.PostTaxonomyType",
263
                        PLUGIN_NAMESPACE,
264
                        OriginalComponent => {
265
                                return class Filter extends Component {
×
266
                                        /**
267
                                         * Renders the primary taxonomy filter component.
268
                                         *
269
                                         * @returns {wp.Element} the component.
270
                                         */
271
                                        render() {
272
                                                return (
×
273
                                                        <PrimaryTaxonomyFilter
274
                                                                OriginalComponent={ OriginalComponent }
275
                                                                { ...this.props }
276
                                                        />
277
                                                );
278
                                        }
279
                                };
280
                        }
281
                );
282
        }
283

284
        $.fn.initYstSEOPrimaryCategory = function() {
×
285
                return this.each( function( i, taxonomy ) {
×
286
                        const metaboxTaxonomy = $( "#" + taxonomy.name + "div" );
×
287

288
                        updatePrimaryTermSelectors( taxonomy.name );
×
289

290
                        metaboxTaxonomy.on( "click", 'input[type="checkbox"]', termCheckboxHandler( taxonomy.name ) );
×
291

292
                        // When the AJAX Request is done, this event will be fired.
293
                        metaboxTaxonomy.on( "wpListAddEnd", "#" + taxonomy.name + "checklist", termListAddHandler( taxonomy.name ) );
×
294

295
                        metaboxTaxonomy.on( "click", ".wpseo-make-primary-term", makePrimaryHandler( taxonomy.name ) );
×
296
                } );
297
        };
298

299
        // Initialize our templates
300
        primaryTermUITemplate = wp.template( "primary-term-ui" );
×
301
        primaryTermScreenReaderTemplate = wp.template( "primary-term-screen-reader" );
×
302

303
        $( _.values( taxonomies ) ).initYstSEOPrimaryCategory();
×
304

305
        registerCategorySelectorFilter();
×
306
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc