~canonical-sysadmins/wordpress/4.7.2

« back to all changes in this revision

Viewing changes to wp-admin/js/widgets.js

  • Committer: Jacek Nykis
  • Date: 2015-01-05 16:17:05 UTC
  • Revision ID: jacek.nykis@canonical.com-20150105161705-w544l1h5mcg7u4w9
Initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*global ajaxurl, isRtl */
 
2
var wpWidgets;
 
3
(function($) {
 
4
 
 
5
wpWidgets = {
 
6
 
 
7
        init : function() {
 
8
                var rem, the_id,
 
9
                        self = this,
 
10
                        chooser = $('.widgets-chooser'),
 
11
                        selectSidebar = chooser.find('.widgets-chooser-sidebars'),
 
12
                        sidebars = $('div.widgets-sortables'),
 
13
                        isRTL = !! ( 'undefined' !== typeof isRtl && isRtl );
 
14
 
 
15
                $('#widgets-right .sidebar-name').click( function() {
 
16
                        var $this = $(this),
 
17
                                $wrap = $this.closest('.widgets-holder-wrap');
 
18
 
 
19
                        if ( $wrap.hasClass('closed') ) {
 
20
                                $wrap.removeClass('closed');
 
21
                                $this.parent().sortable('refresh');
 
22
                        } else {
 
23
                                $wrap.addClass('closed');
 
24
                        }
 
25
                });
 
26
 
 
27
                $('#widgets-left .sidebar-name').click( function() {
 
28
                        $(this).closest('.widgets-holder-wrap').toggleClass('closed');
 
29
                });
 
30
 
 
31
                $(document.body).bind('click.widgets-toggle', function(e) {
 
32
                        var target = $(e.target),
 
33
                                css = { 'z-index': 100 },
 
34
                                widget, inside, targetWidth, widgetWidth, margin;
 
35
 
 
36
                        if ( target.parents('.widget-top').length && ! target.parents('#available-widgets').length ) {
 
37
                                widget = target.closest('div.widget');
 
38
                                inside = widget.children('.widget-inside');
 
39
                                targetWidth = parseInt( widget.find('input.widget-width').val(), 10 ),
 
40
                                widgetWidth = widget.parent().width();
 
41
 
 
42
                                if ( inside.is(':hidden') ) {
 
43
                                        if ( targetWidth > 250 && ( targetWidth + 30 > widgetWidth ) && widget.closest('div.widgets-sortables').length ) {
 
44
                                                if ( widget.closest('div.widget-liquid-right').length ) {
 
45
                                                        margin = isRTL ? 'margin-right' : 'margin-left';
 
46
                                                } else {
 
47
                                                        margin = isRTL ? 'margin-left' : 'margin-right';
 
48
                                                }
 
49
 
 
50
                                                css[ margin ] = widgetWidth - ( targetWidth + 30 ) + 'px';
 
51
                                                widget.css( css );
 
52
                                        }
 
53
                                        widget.addClass( 'open' );
 
54
                                        inside.slideDown('fast');
 
55
                                } else {
 
56
                                        inside.slideUp('fast', function() {
 
57
                                                widget.attr( 'style', '' );
 
58
                                                widget.removeClass( 'open' );
 
59
                                        });
 
60
                                }
 
61
                                e.preventDefault();
 
62
                        } else if ( target.hasClass('widget-control-save') ) {
 
63
                                wpWidgets.save( target.closest('div.widget'), 0, 1, 0 );
 
64
                                e.preventDefault();
 
65
                        } else if ( target.hasClass('widget-control-remove') ) {
 
66
                                wpWidgets.save( target.closest('div.widget'), 1, 1, 0 );
 
67
                                e.preventDefault();
 
68
                        } else if ( target.hasClass('widget-control-close') ) {
 
69
                                wpWidgets.close( target.closest('div.widget') );
 
70
                                e.preventDefault();
 
71
                        }
 
72
                });
 
73
 
 
74
                sidebars.children('.widget').each( function() {
 
75
                        var $this = $(this);
 
76
 
 
77
                        wpWidgets.appendTitle( this );
 
78
 
 
79
                        if ( $this.find( 'p.widget-error' ).length ) {
 
80
                                $this.find( 'a.widget-action' ).trigger('click');
 
81
                        }
 
82
                });
 
83
 
 
84
                $('#widget-list').children('.widget').draggable({
 
85
                        connectToSortable: 'div.widgets-sortables',
 
86
                        handle: '> .widget-top > .widget-title',
 
87
                        distance: 2,
 
88
                        helper: 'clone',
 
89
                        zIndex: 100,
 
90
                        containment: 'document',
 
91
                        start: function( event, ui ) {
 
92
                                var chooser = $(this).find('.widgets-chooser');
 
93
 
 
94
                                ui.helper.find('div.widget-description').hide();
 
95
                                the_id = this.id;
 
96
 
 
97
                                if ( chooser.length ) {
 
98
                                        // Hide the chooser and move it out of the widget
 
99
                                        $( '#wpbody-content' ).append( chooser.hide() );
 
100
                                        // Delete the cloned chooser from the drag helper
 
101
                                        ui.helper.find('.widgets-chooser').remove();
 
102
                                        self.clearWidgetSelection();
 
103
                                }
 
104
                        },
 
105
                        stop: function() {
 
106
                                if ( rem ) {
 
107
                                        $(rem).hide();
 
108
                                }
 
109
 
 
110
                                rem = '';
 
111
                        }
 
112
                });
 
113
 
 
114
                sidebars.sortable({
 
115
                        placeholder: 'widget-placeholder',
 
116
                        items: '> .widget',
 
117
                        handle: '> .widget-top > .widget-title',
 
118
                        cursor: 'move',
 
119
                        distance: 2,
 
120
                        containment: 'document',
 
121
                        start: function( event, ui ) {
 
122
                                var height, $this = $(this),
 
123
                                        $wrap = $this.parent(),
 
124
                                        inside = ui.item.children('.widget-inside');
 
125
 
 
126
                                if ( inside.css('display') === 'block' ) {
 
127
                                        inside.hide();
 
128
                                        $(this).sortable('refreshPositions');
 
129
                                }
 
130
 
 
131
                                if ( ! $wrap.hasClass('closed') ) {
 
132
                                        // Lock all open sidebars min-height when starting to drag.
 
133
                                        // Prevents jumping when dragging a widget from an open sidebar to a closed sidebar below.
 
134
                                        height = ui.item.hasClass('ui-draggable') ? $this.height() : 1 + $this.height();
 
135
                                        $this.css( 'min-height', height + 'px' );
 
136
                                }
 
137
                        },
 
138
 
 
139
                        stop: function( event, ui ) {
 
140
                                var addNew, widgetNumber, $sidebar, $children, child, item,
 
141
                                        $widget = ui.item,
 
142
                                        id = the_id;
 
143
 
 
144
                                if ( $widget.hasClass('deleting') ) {
 
145
                                        wpWidgets.save( $widget, 1, 0, 1 ); // delete widget
 
146
                                        $widget.remove();
 
147
                                        return;
 
148
                                }
 
149
 
 
150
                                addNew = $widget.find('input.add_new').val();
 
151
                                widgetNumber = $widget.find('input.multi_number').val();
 
152
 
 
153
                                $widget.attr( 'style', '' ).removeClass('ui-draggable');
 
154
                                the_id = '';
 
155
 
 
156
                                if ( addNew ) {
 
157
                                        if ( 'multi' === addNew ) {
 
158
                                                $widget.html(
 
159
                                                        $widget.html().replace( /<[^<>]+>/g, function( tag ) {
 
160
                                                                return tag.replace( /__i__|%i%/g, widgetNumber );
 
161
                                                        })
 
162
                                                );
 
163
 
 
164
                                                $widget.attr( 'id', id.replace( '__i__', widgetNumber ) );
 
165
                                                widgetNumber++;
 
166
 
 
167
                                                $( 'div#' + id ).find( 'input.multi_number' ).val( widgetNumber );
 
168
                                        } else if ( 'single' === addNew ) {
 
169
                                                $widget.attr( 'id', 'new-' + id );
 
170
                                                rem = 'div#' + id;
 
171
                                        }
 
172
 
 
173
                                        wpWidgets.save( $widget, 0, 0, 1 );
 
174
                                        $widget.find('input.add_new').val('');
 
175
                                        $( document ).trigger( 'widget-added', [ $widget ] );
 
176
                                }
 
177
 
 
178
                                $sidebar = $widget.parent();
 
179
 
 
180
                                if ( $sidebar.parent().hasClass('closed') ) {
 
181
                                        $sidebar.parent().removeClass('closed');
 
182
                                        $children = $sidebar.children('.widget');
 
183
 
 
184
                                        // Make sure the dropped widget is at the top
 
185
                                        if ( $children.length > 1 ) {
 
186
                                                child = $children.get(0);
 
187
                                                item = $widget.get(0);
 
188
 
 
189
                                                if ( child.id && item.id && child.id !== item.id ) {
 
190
                                                        $( child ).before( $widget );
 
191
                                                }
 
192
                                        }
 
193
                                }
 
194
 
 
195
                                if ( addNew ) {
 
196
                                        $widget.find( 'a.widget-action' ).trigger('click');
 
197
                                } else {
 
198
                                        wpWidgets.saveOrder( $sidebar.attr('id') );
 
199
                                }
 
200
                        },
 
201
 
 
202
                        activate: function() {
 
203
                                $(this).parent().addClass( 'widget-hover' );
 
204
                        },
 
205
 
 
206
                        deactivate: function() {
 
207
                                // Remove all min-height added on "start"
 
208
                                $(this).css( 'min-height', '' ).parent().removeClass( 'widget-hover' );
 
209
                        },
 
210
 
 
211
                        receive: function( event, ui ) {
 
212
                                var $sender = $( ui.sender );
 
213
 
 
214
                                // Don't add more widgets to orphaned sidebars
 
215
                                if ( this.id.indexOf('orphaned_widgets') > -1 ) {
 
216
                                        $sender.sortable('cancel');
 
217
                                        return;
 
218
                                }
 
219
 
 
220
                                // If the last widget was moved out of an orphaned sidebar, close and remove it.
 
221
                                if ( $sender.attr('id').indexOf('orphaned_widgets') > -1 && ! $sender.children('.widget').length ) {
 
222
                                        $sender.parents('.orphan-sidebar').slideUp( 400, function(){ $(this).remove(); } );
 
223
                                }
 
224
                        }
 
225
                }).sortable( 'option', 'connectWith', 'div.widgets-sortables' );
 
226
 
 
227
                $('#available-widgets').droppable({
 
228
                        tolerance: 'pointer',
 
229
                        accept: function(o){
 
230
                                return $(o).parent().attr('id') !== 'widget-list';
 
231
                        },
 
232
                        drop: function(e,ui) {
 
233
                                ui.draggable.addClass('deleting');
 
234
                                $('#removing-widget').hide().children('span').html('');
 
235
                        },
 
236
                        over: function(e,ui) {
 
237
                                ui.draggable.addClass('deleting');
 
238
                                $('div.widget-placeholder').hide();
 
239
 
 
240
                                if ( ui.draggable.hasClass('ui-sortable-helper') ) {
 
241
                                        $('#removing-widget').show().children('span')
 
242
                                        .html( ui.draggable.find('div.widget-title').children('h4').html() );
 
243
                                }
 
244
                        },
 
245
                        out: function(e,ui) {
 
246
                                ui.draggable.removeClass('deleting');
 
247
                                $('div.widget-placeholder').show();
 
248
                                $('#removing-widget').hide().children('span').html('');
 
249
                        }
 
250
                });
 
251
 
 
252
                // Area Chooser
 
253
                $( '#widgets-right .widgets-holder-wrap' ).each( function( index, element ) {
 
254
                        var $element = $( element ),
 
255
                                name = $element.find( '.sidebar-name h3' ).text(),
 
256
                                id = $element.find( '.widgets-sortables' ).attr( 'id' ),
 
257
                                li = $('<li tabindex="0">').text( $.trim( name ) );
 
258
 
 
259
                        if ( index === 0 ) {
 
260
                                li.addClass( 'widgets-chooser-selected' );
 
261
                        }
 
262
 
 
263
                        selectSidebar.append( li );
 
264
                        li.data( 'sidebarId', id );
 
265
                });
 
266
 
 
267
                $( '#available-widgets .widget .widget-title' ).on( 'click.widgets-chooser', function() {
 
268
                        var $widget = $(this).closest( '.widget' );
 
269
 
 
270
                        if ( $widget.hasClass( 'widget-in-question' ) || $( '#widgets-left' ).hasClass( 'chooser' ) ) {
 
271
                                self.closeChooser();
 
272
                        } else {
 
273
                                // Open the chooser
 
274
                                self.clearWidgetSelection();
 
275
                                $( '#widgets-left' ).addClass( 'chooser' );
 
276
                                $widget.addClass( 'widget-in-question' ).children( '.widget-description' ).after( chooser );
 
277
 
 
278
                                chooser.slideDown( 300, function() {
 
279
                                        selectSidebar.find('.widgets-chooser-selected').focus();
 
280
                                });
 
281
 
 
282
                                selectSidebar.find( 'li' ).on( 'focusin.widgets-chooser', function() {
 
283
                                        selectSidebar.find('.widgets-chooser-selected').removeClass( 'widgets-chooser-selected' );
 
284
                                        $(this).addClass( 'widgets-chooser-selected' );
 
285
                                } );
 
286
                        }
 
287
                });
 
288
 
 
289
                // Add event handlers
 
290
                chooser.on( 'click.widgets-chooser', function( event ) {
 
291
                        var $target = $( event.target );
 
292
 
 
293
                        if ( $target.hasClass('button-primary') ) {
 
294
                                self.addWidget( chooser );
 
295
                                self.closeChooser();
 
296
                        } else if ( $target.hasClass('button-secondary') ) {
 
297
                                self.closeChooser();
 
298
                        }
 
299
                }).on( 'keyup.widgets-chooser', function( event ) {
 
300
                        if ( event.which === $.ui.keyCode.ENTER ) {
 
301
                                if ( $( event.target ).hasClass('button-secondary') ) {
 
302
                                        // Close instead of adding when pressing Enter on the Cancel button
 
303
                                        self.closeChooser();
 
304
                                } else {
 
305
                                        self.addWidget( chooser );
 
306
                                        self.closeChooser();
 
307
                                }
 
308
                        } else if ( event.which === $.ui.keyCode.ESCAPE ) {
 
309
                                self.closeChooser();
 
310
                        }
 
311
                });
 
312
        },
 
313
 
 
314
        saveOrder : function( sidebarId ) {
 
315
                var data = {
 
316
                        action: 'widgets-order',
 
317
                        savewidgets: $('#_wpnonce_widgets').val(),
 
318
                        sidebars: []
 
319
                };
 
320
 
 
321
                if ( sidebarId ) {
 
322
                        $( '#' + sidebarId ).find('.spinner:first').css('display', 'inline-block');
 
323
                }
 
324
 
 
325
                $('div.widgets-sortables').each( function() {
 
326
                        if ( $(this).sortable ) {
 
327
                                data['sidebars[' + $(this).attr('id') + ']'] = $(this).sortable('toArray').join(',');
 
328
                        }
 
329
                });
 
330
 
 
331
                $.post( ajaxurl, data, function() {
 
332
                        $('.spinner').hide();
 
333
                });
 
334
        },
 
335
 
 
336
        save : function( widget, del, animate, order ) {
 
337
                var sidebarId = widget.closest('div.widgets-sortables').attr('id'),
 
338
                        data = widget.find('form').serialize(), a;
 
339
 
 
340
                widget = $(widget);
 
341
                $('.spinner', widget).show();
 
342
 
 
343
                a = {
 
344
                        action: 'save-widget',
 
345
                        savewidgets: $('#_wpnonce_widgets').val(),
 
346
                        sidebar: sidebarId
 
347
                };
 
348
 
 
349
                if ( del ) {
 
350
                        a.delete_widget = 1;
 
351
                }
 
352
 
 
353
                data += '&' + $.param(a);
 
354
 
 
355
                $.post( ajaxurl, data, function(r) {
 
356
                        var id;
 
357
 
 
358
                        if ( del ) {
 
359
                                if ( ! $('input.widget_number', widget).val() ) {
 
360
                                        id = $('input.widget-id', widget).val();
 
361
                                        $('#available-widgets').find('input.widget-id').each(function(){
 
362
                                                if ( $(this).val() === id ) {
 
363
                                                        $(this).closest('div.widget').show();
 
364
                                                }
 
365
                                        });
 
366
                                }
 
367
 
 
368
                                if ( animate ) {
 
369
                                        order = 0;
 
370
                                        widget.slideUp('fast', function(){
 
371
                                                $(this).remove();
 
372
                                                wpWidgets.saveOrder();
 
373
                                        });
 
374
                                } else {
 
375
                                        widget.remove();
 
376
                                }
 
377
                        } else {
 
378
                                $('.spinner').hide();
 
379
                                if ( r && r.length > 2 ) {
 
380
                                        $( 'div.widget-content', widget ).html( r );
 
381
                                        wpWidgets.appendTitle( widget );
 
382
                                        $( document ).trigger( 'widget-updated', [ widget ] );
 
383
                                }
 
384
                        }
 
385
                        if ( order ) {
 
386
                                wpWidgets.saveOrder();
 
387
                        }
 
388
                });
 
389
        },
 
390
 
 
391
        appendTitle : function(widget) {
 
392
                var title = $('input[id*="-title"]', widget).val() || '';
 
393
 
 
394
                if ( title ) {
 
395
                        title = ': ' + title.replace(/<[^<>]+>/g, '').replace(/</g, '&lt;').replace(/>/g, '&gt;');
 
396
                }
 
397
 
 
398
                $(widget).children('.widget-top').children('.widget-title').children()
 
399
                                .children('.in-widget-title').html(title);
 
400
 
 
401
        },
 
402
 
 
403
        close : function(widget) {
 
404
                widget.children('.widget-inside').slideUp('fast', function() {
 
405
                        widget.attr( 'style', '' );
 
406
                });
 
407
        },
 
408
 
 
409
        addWidget: function( chooser ) {
 
410
                var widget, widgetId, add, n, viewportTop, viewportBottom, sidebarBounds,
 
411
                        sidebarId = chooser.find( '.widgets-chooser-selected' ).data('sidebarId'),
 
412
                        sidebar = $( '#' + sidebarId );
 
413
 
 
414
                widget = $('#available-widgets').find('.widget-in-question').clone();
 
415
                widgetId = widget.attr('id');
 
416
                add = widget.find( 'input.add_new' ).val();
 
417
                n = widget.find( 'input.multi_number' ).val();
 
418
 
 
419
                // Remove the cloned chooser from the widget
 
420
                widget.find('.widgets-chooser').remove();
 
421
 
 
422
                if ( 'multi' === add ) {
 
423
                        widget.html(
 
424
                                widget.html().replace( /<[^<>]+>/g, function(m) {
 
425
                                        return m.replace( /__i__|%i%/g, n );
 
426
                                })
 
427
                        );
 
428
 
 
429
                        widget.attr( 'id', widgetId.replace( '__i__', n ) );
 
430
                        n++;
 
431
                        $( '#' + widgetId ).find('input.multi_number').val(n);
 
432
                } else if ( 'single' === add ) {
 
433
                        widget.attr( 'id', 'new-' + widgetId );
 
434
                        $( '#' + widgetId ).hide();
 
435
                }
 
436
 
 
437
                // Open the widgets container
 
438
                sidebar.closest( '.widgets-holder-wrap' ).removeClass('closed');
 
439
 
 
440
                sidebar.append( widget );
 
441
                sidebar.sortable('refresh');
 
442
 
 
443
                wpWidgets.save( widget, 0, 0, 1 );
 
444
                // No longer "new" widget
 
445
                widget.find( 'input.add_new' ).val('');
 
446
 
 
447
                $( document ).trigger( 'widget-added', [ widget ] );
 
448
 
 
449
                /*
 
450
                 * Check if any part of the sidebar is visible in the viewport. If it is, don't scroll.
 
451
                 * Otherwise, scroll up to so the sidebar is in view.
 
452
                 *
 
453
                 * We do this by comparing the top and bottom, of the sidebar so see if they are within
 
454
                 * the bounds of the viewport.
 
455
                 */
 
456
                viewportTop = $(window).scrollTop();
 
457
                viewportBottom = viewportTop + $(window).height();
 
458
                sidebarBounds = sidebar.offset();
 
459
 
 
460
                sidebarBounds.bottom = sidebarBounds.top + sidebar.outerHeight();
 
461
 
 
462
                if ( viewportTop > sidebarBounds.bottom || viewportBottom < sidebarBounds.top ) {
 
463
                        $( 'html, body' ).animate({
 
464
                                scrollTop: sidebarBounds.top - 130
 
465
                        }, 200 );
 
466
                }
 
467
 
 
468
                window.setTimeout( function() {
 
469
                        // Cannot use a callback in the animation above as it fires twice,
 
470
                        // have to queue this "by hand".
 
471
                        widget.find( '.widget-title' ).trigger('click');
 
472
                }, 250 );
 
473
        },
 
474
 
 
475
        closeChooser: function() {
 
476
                var self = this;
 
477
 
 
478
                $( '.widgets-chooser' ).slideUp( 200, function() {
 
479
                        $( '#wpbody-content' ).append( this );
 
480
                        self.clearWidgetSelection();
 
481
                });
 
482
        },
 
483
 
 
484
        clearWidgetSelection: function() {
 
485
                $( '#widgets-left' ).removeClass( 'chooser' );
 
486
                $( '.widget-in-question' ).removeClass( 'widget-in-question' );
 
487
        }
 
488
};
 
489
 
 
490
$(document).ready( function(){ wpWidgets.init(); } );
 
491
 
 
492
})(jQuery);