PluginProbe ʕ •ᴥ•ʔ
Menu Icons by Themeisle – Add Icons to Navigation Menus / 0.2.0
Menu Icons by Themeisle – Add Icons to Navigation Menus v0.2.0
0.13.24 trunk 0.1.0 0.1.1 0.1.2 0.1.3 0.1.4 0.1.5 0.10.0 0.10.1 0.10.2 0.11.0 0.11.1 0.11.2 0.11.3 0.11.4 0.11.5 0.12.0 0.12.1 0.12.10 0.12.11 0.12.12 0.12.2 0.12.3 0.12.4 0.12.5 0.12.6 0.12.7 0.12.8 0.12.9 0.13.0 0.13.1 0.13.10 0.13.11 0.13.12 0.13.13 0.13.14 0.13.15 0.13.16 0.13.17 0.13.18 0.13.19 0.13.2 0.13.20 0.13.21 0.13.22 0.13.23 0.13.3 0.13.4 0.13.5 0.13.6 0.13.7 0.13.8 0.13.9 0.2.0 0.2.1 0.2.2 0.2.3 0.3.0 0.3.1 0.3.2 0.4.0 0.5.0 0.5.1 0.6.0 0.7.0 0.8.0 0.8.1 0.9.0 0.9.2
menu-icons / js / admin.js
menu-icons / js Last commit date
admin.js 12 years ago input-dependencies.js 12 years ago input-dependencies.min.js 12 years ago
admin.js
723 lines
1 /* global jQuery, wp, menuIcons */
2 /**
3 * Menu Icons
4 *
5 * @author Dzikri Aziz <kvcrvt@gmail.com>
6 * @version 0.1.0
7 *
8 */
9 (function($) {
10 'use strict';
11
12 $.inputDependencies({
13 selector : 'select.hasdep',
14 disable : false
15 });
16
17 if ( 'undefined' === typeof menuIcons ) {
18 return;
19 }
20
21 if ( undefined === window.menuIcons.iconTypes ) {
22 return;
23 }
24
25 menuIcons = _.defaults({
26 frame : '',
27 currentItem : {},
28
29 toggleSelect : function(e) {
30 var $type = $(e.currentTarget);
31 var $wrapr = $type.closest('div.menu-icons-wrap');
32 var $select = $wrapr.find('a._select');
33 var $remove = $wrapr.find('a._remove');
34
35 if ( '' !== $type.val() ) {
36 $remove.show();
37 }
38 else {
39 $select.text( $select.data('text') );
40 $remove.hide();
41 }
42 },
43
44 selectIcon : function(e) {
45 e.preventDefault();
46 e.stopPropagation();
47
48 var $el = $(this);
49 var id = media.view.settings.post.id = $el.data('id');
50 var attrs = {
51 id : id,
52 title : $('#edit-menu-item-title-'+id).val()
53 };
54
55 $el.closest('div.menu-icons-wrap').find(':input').each(function(i, input) {
56 var key = $(input).data('key');
57 attrs[ key ] = input.value;
58 });
59
60 menuIcons.currentItem = attrs;
61
62 if ( ! ( menuIcons.frame instanceof media.view.MediaFrame.menuIcons ) ) {
63 menuIcons.frame = new media.view.MediaFrame.menuIcons;
64 }
65
66 menuIcons.frame.open();
67 },
68
69 removeIcon : function(e) {
70 e.preventDefault();
71 e.stopPropagation();
72
73 var id = $(this).data('id');
74
75 $('#menu-icons-'+ id +'-type').val('').trigger('change');
76 }
77 }, menuIcons);
78
79
80 // WP Media
81 var media = wp.media;
82 var Attachment = media.model.Attachment;
83
84
85 // Font icon: Menu Items
86 media.model.miMenuItem = Backbone.Model.extend({
87 defaults : {
88 type : '',
89 icon : '',
90 size : '',
91 'vertical-align' : ''
92 }
93 });
94
95 media.model.miMenuItems = Backbone.Collection.extend({
96 model : media.model.miMenuItem,
97 props : new Backbone.Model({
98 item : ''
99 })
100 });
101
102
103 // All: Sidebar
104 media.view.miSidebar = media.view.Sidebar.extend({
105 initialize : function() {
106 media.view.Sidebar.prototype.initialize.apply( this, arguments );
107
108 this.createTitle();
109 },
110
111 createTitle : function() {
112 this.views.add( new media.view.miSidebar.Title );
113 },
114 });
115
116
117 // All: Sidebar title
118 media.view.miSidebar.Title = media.View.extend({
119 initialize : function() {
120 this.template = media.template( 'menu-icons-sidebar-title' );
121 media.View.prototype.initialize.apply( this, arguments );
122 }
123 });
124
125
126 // All: Settings
127 media.view.miSidebar.Settings = media.view.Settings.extend({
128 className : 'mi-settings attachment-info',
129
130 initialize : function() {
131 this.template = media.template( 'menu-icons-settings' );
132 media.view.Settings.prototype.initialize.apply( this, arguments );
133 },
134
135 render : function() {
136 this.$el.html( this.template( this.model.toJSON() ) );
137 _( this.model.attributes ).chain().keys().each( this.update, this );
138
139 return this;
140 },
141
142 update: function( key ) {
143 media.view.Settings.prototype.update.call( this, key );
144
145 var id = this.model.id;
146 var value = this.model.get( key );
147 var $field = $('#menu-icons-'+ id +'-'+ key +'._setting');
148
149 // Bail if we didn't find a matching field.
150 if ( ! $field.length )
151 return;
152
153 $field.val( value ).trigger('change');
154 }
155 });
156
157
158 // Font icon: Browser
159 media.view.miFont = media.View.extend({
160 className : 'attachments-browser mi-items-wrap',
161
162 initialize : function() {
163 this.createToolbar();
164 this.createLibrary();
165 this.createSidebar();
166 },
167
168 createLibrary : function() {
169 this.items = new media.view.miFont.Library({
170 controller : this.controller,
171 collection : this.collection,
172 selection : this.options.selection,
173 type : this.options.type,
174 data : this.options.data
175 });
176 this.views.add( this.items );
177 },
178
179 createToolbar : function() {
180 this.toolbar = new media.view.Toolbar({
181 controller : this.controller
182 });
183 this.views.add( this.toolbar );
184
185 // Dropdown filter
186 this.toolbar.set( 'filters', new media.view.miFont.Filters({
187 controller : this.controller,
188 model : this.collection.props,
189 priority : -80
190 }).render() );
191
192 // Search field
193 this.toolbar.set( 'search', new media.view.Search({
194 controller : this.controller,
195 model : this.collection.props,
196 priority : 60
197 }).render() );
198 },
199
200 createSidebar : function() {
201 var options = this.options;
202 var selection = options.selection;
203 var sidebar = this.sidebar = new media.view.miSidebar({
204 controller : this.controller,
205 type : options.type
206 });
207
208 this.views.add( sidebar );
209
210 selection.on( 'selection:single', this.createSingle, this );
211 selection.on( 'selection:unsingle', this.disposeSingle, this );
212
213 if ( selection.single() ) {
214 this.createSingle();
215 }
216 },
217
218 createSingle : function() {
219 this.controller.miUpdateItemProps();
220
221 var sidebar = this.sidebar;
222 var item = this.controller.miGetCurrentItem();
223
224 sidebar.set( 'details', new media.view.miFont.Icon.Preview({
225 controller : this.controller,
226 model : item,
227 type : this.options.type,
228 priority : 80
229 }) );
230
231 sidebar.set( 'display', new media.view.miSidebar.Settings({
232 controller : this.controller,
233 model : item,
234 type : this.options.type,
235 priority : 120
236 }) );
237 },
238
239 disposeSingle : function() {
240 this.controller.miUpdateItemProps();
241
242 var sidebar = this.sidebar;
243 sidebar.unset('details');
244 sidebar.unset('display');
245 }
246 });
247
248
249 // Font icon: Library
250 media.view.miFont.Library = media.View.extend({
251 tagName : 'ul',
252 className : 'attachments mi-items clearfix',
253
254 initialize : function() {
255 this._viewsByCid = {};
256 this.collection.on( 'reset', this.refresh, this );
257 this.controller.on( 'open', this.scrollToSelected, this );
258 },
259
260 render : function() {
261 this.collection.each( function( model ) {
262 this.views.add( this.renderItem( model ), {
263 at : this.collection.indexOf( model )
264 } );
265 }, this );
266
267 return this;
268 },
269
270 renderItem : function( model ) {
271 var view = new media.view.miFont.Icon({
272 controller : this.controller,
273 model : model,
274 collection : this.collection,
275 selection : this.options.selection,
276 type : this.options.type,
277 data : this.options.data
278 });
279
280 return this._viewsByCid[ view.cid ] = view;
281 },
282
283 clearItems : function() {
284 _.each( this._viewsByCid, function( view ) {
285 delete this._viewsByCid[ view.cid ];
286 view.remove();
287 }, this );
288 },
289
290 refresh : function() {
291 this.clearItems();
292 this.render();
293 },
294
295 ready : function() {
296 this.scrollToSelected();
297 },
298
299 scrollToSelected : function() {
300 var single = this.options.selection.single();
301 var singleView;
302
303 if ( ! single ) {
304 return;
305 }
306
307 singleView = this.getView( single );
308 if ( singleView && ! this.isInView( singleView.$el ) ) {
309 this.$el.scrollTop(
310 singleView.$el.offset().top
311 - this.$el.offset().top
312 + this.$el.scrollTop()
313 - parseInt( this.$el.css('paddingTop') )
314 );
315 }
316 },
317
318 getView : function( model ) {
319 return _.findWhere( this._viewsByCid, { model : model } );
320 },
321
322 isInView: function( $elem ) {
323 var $window = $(window)
324 var docViewTop = $window.scrollTop();
325 var docViewBottom = docViewTop + $window.height();
326 var elemTop = $elem.offset().top;
327 var elemBottom = elemTop + $elem.height();
328
329 return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
330 }
331 });
332
333
334 // Font icon: Dropdown filter
335 media.view.miFont.Filters = media.view.AttachmentFilters.extend({
336 createFilters : function() {
337 this.filters = {
338 all : {
339 text : menuIcons.text.all,
340 props : {
341 group : 'all'
342 }
343 }
344 };
345
346 var groups = this.controller.state().get('data').groups;
347 _.each( groups, function( text, id ) {
348 this.filters[ id ] = {
349 text : text,
350 props : {
351 group : id
352 }
353 };
354 }, this );
355 },
356
357 change : function() {
358 var filter = this.filters[ this.el.value ];
359
360 if ( filter ) {
361 this.model.set( 'group', filter.props.group );
362 }
363 }
364 });
365
366
367 // Font icon: Item
368 media.view.miFont.Icon = media.view.Attachment.extend({
369 className : 'attachment mi-item',
370 events : {
371 'click .attachment-preview' : 'toggleSelectionHandler',
372 'click a' : 'preventDefault'
373 },
374
375 initialize : function() {
376 this.template = media.template( 'menu-icons-' + this.options.type + '-item' );
377 media.view.Attachment.prototype.initialize.apply( this, arguments );
378 },
379
380 render: function() {
381 this.$el.html( this.template( this.model.toJSON() ) );
382 this.updateSelect();
383
384 return this;
385 }
386 });
387
388
389 // Font icon: Preview
390 media.view.miFont.Icon.Preview = Backbone.View.extend({
391 tagName : 'p',
392 className : 'mi-preview menu-item attachment-info',
393 events : {
394 'click a' : 'preventDefault'
395 },
396
397 initialize : function() {
398 this.model.on( 'change', this.render, this );
399 },
400
401 render : function() {
402 var data = this.model.toJSON();
403 var template = 'menu-icons-' + this.options.type + '-preview-' + data.position;
404
405 this.template = media.template( template );
406 this.$el.html( this.template( data ) );
407
408 return this;
409 }
410 });
411
412
413 // Font icon: Controller
414 media.controller.miFont = media.controller.State.extend({
415 defaults : {
416 id : 'mi-font',
417 menu : 'default',
418 toolbar : 'mi-select',
419 type : ''
420 },
421
422 initialize : function() {
423 var state = this;
424
425 if ( ! this.get('library') ) {
426 var Icons = Backbone.Collection.extend({
427 props : new Backbone.Model({
428 group : 'all',
429 search : ''
430 }),
431
432 initialize : function( models ) {
433 this.original = new Backbone.Collection(models);
434 },
435
436 reInitialize : function() {
437 var library = this;
438 var icons = state.get('data').items;
439 var props = this.props.toJSON();
440
441 _.each( props, function( val, filter ) {
442 if ( library.filters[ filter ] ) {
443 icons = _.filter( icons, library.filters[ filter ], val );
444 }
445 }, this);
446
447 this.reset( icons );
448 },
449
450 filters : {
451 group : function( icon ) {
452 var group = this;
453
454 return (
455 'all' === group
456 || icon.group === group
457 || '' === icon.group // fallback
458 );
459 },
460 search : function( icon ) {
461 var term = this;
462 var result;
463
464 if ( '' === term ) {
465 result = true;
466 }
467 else {
468 result = _.any(['id','label'], function( key ) {
469 var value = icon[key];
470
471 return value && -1 !== value.search( this );
472 }, term );
473 }
474
475 return result;
476 }
477 }
478 });
479
480 var library = new Icons( this.get('data').items );
481 library.props.on( 'change', this.miResetLibrary, this );
482
483 this.set( 'library', library );
484 }
485
486 var selection = this.get('selection');
487 if ( ! (selection instanceof media.model.Selection) ) {
488 this.set( 'selection', new media.model.Selection( selection, {
489 multiple : false
490 }) );
491 }
492 },
493
494 activate : function() {
495 media.controller.State.prototype.activate.apply( this, arguments );
496 this.frame.on( 'open', this.refresh, this );
497 this.miUpdateSelection();
498 },
499
500 deactivate : function() {
501 media.controller.State.prototype.deactivate.apply( this, arguments );
502 this.frame.off( 'open', this.refresh, this );
503 },
504
505 refresh : function() {
506 var library = this.get('library');
507 var item = this.frame.miGetCurrentItem();
508 var groups = this.get('data').groups;
509 var group = item.get('group');
510
511 if ( _.isUndefined( groups[ group ] ) ) {
512 group = 'all';
513 }
514
515 library.props.set( 'group', group );
516 this.miUpdateSelection();
517 },
518
519 miResetLibrary : function() {
520 var library = this.get('library');
521 var group = library.props.get('group');
522 var item = this.frame.miGetCurrentItem();
523
524 item.set( 'group', group );
525
526 library.reInitialize();
527 this.set( 'library', library );
528
529 this.miUpdateSelection();
530 },
531
532 miUpdateSelection : function() {
533 var selection = this.get('selection');
534 var type = this.get('type');
535 var key = type+'-icon';
536 var item = this.frame.miGetCurrentItem();
537 var icon = item.get(key);
538 var selected;
539
540 if ( type === item.get('type') && icon ) {
541 selected = this.get('library').findWhere({id: icon});
542 }
543
544 selection.reset( selected ? selected : [] );
545 },
546
547 miGetIcon : function() {
548 var single = this.get('selection').single();
549
550 return single ? single.id : '';
551 }
552 });
553
554
555 // Frame
556 media.view.MediaFrame.menuIcons = media.view.MediaFrame.extend({
557 initialize : function() {
558 media.view.MediaFrame.prototype.initialize.apply( this, arguments );
559
560 _.defaults( this.options, {
561 selection : [],
562 multiple : false,
563 editing : false,
564 toolbar : 'mi-select'
565 });
566
567 this.miMenuItems = new media.model.miMenuItems;
568 this.createStates();
569 this.bindHandlers();
570 },
571
572 createStates : function() {
573 var options = this.options;
574 var controller;
575
576 if ( options.states ) {
577 return;
578 }
579
580 _.each( menuIcons.iconTypes, function( props, type ) {
581 if ( ! media.controller.hasOwnProperty( props.data.controller ) ) {
582 delete menuIcons.iconTypes[ type ];
583 return;
584 }
585
586 controller = media.controller[ props.data.controller ];
587
588 _.defaults( props, {
589 content : props.id,
590 selection : options.selection
591 } );
592
593 // States
594 this.states.add( new controller( props ) );
595 }, this );
596 },
597
598 bindHandlers : function() {
599 this.on( 'toolbar:create:mi-select', this.createToolbar, this );
600 this.on( 'toolbar:render:mi-select', this.miSelectToolbar, this );
601 this.on( 'open', this.miInitialize, this );
602
603 _.each( menuIcons.iconTypes, function( props, type ) {
604 this.on( 'content:activate:'+props.id, this.miContentRender, this, props );
605 }, this );
606 },
607
608 // Toolbars
609 miSelectToolbar : function( view ) {
610 var frame = this;
611 var state = frame.state();
612 var type = state.get('type');
613
614 view.set( state.id, {
615 style : 'primary',
616 priority : 80,
617 text : menuIcons.text.select,
618 requires : {
619 selection : true
620 },
621 click : function() {
622 frame.close();
623 frame.miUpdateItem();
624 }
625 });
626 },
627
628 // Content
629 miContentRender : function() {
630 var state = this.state();
631 var view = media.view[ state.get('data').controller ];
632
633 this.content.set( new view({
634 controller : this,
635 model : state,
636 collection : state.get('library'),
637 selection : state.get('selection'),
638 type : state.get('type')
639 }) );
640 },
641
642 miGetState : function() {
643 var item = menuIcons.currentItem;
644 var type;
645
646 if (
647 ! _.isUndefined( item.type )
648 && '' !== item.type
649 && menuIcons.iconTypes.hasOwnProperty( item.type )
650 ) {
651 type = item.type;
652 }
653 else {
654 type = menuIcons.typeNames[0];
655 }
656
657 return 'mi-'+type;
658 },
659
660 miGetCurrentItem : function() {
661 return this.miMenuItems.get( menuIcons.currentItem.id )
662 },
663
664 miUpdateMenuItems : function() {
665 var item = this.miGetCurrentItem();
666
667 if ( _.isUndefined( item ) ) {
668 this.miMenuItems.add( _.extend({ group : 'all' }, menuIcons.currentItem ) );
669 }
670 else {
671 item.set( menuIcons.currentItem );
672 }
673
674 this.miMenuItems.props.set( 'item', menuIcons.currentItem.id );
675 },
676
677 miInitialize : function() {
678 this.miUpdateMenuItems();
679 this.setState( this.miGetState() );
680 },
681
682 miUpdateItemProps : function() {
683 var state = this.state();
684 var type = state.get('type');
685 var selection = state.get('selection');
686 var single = selection.single();
687 var item = this.miGetCurrentItem();
688 var icon = single ? single.id : '';
689
690 item.set( 'type', type );
691 item.set( type+'-icon', icon );
692 item.set( 'icon', state.miGetIcon() );
693 },
694
695 miUpdateItem : function() {
696 var attrs = this.miGetCurrentItem().toJSON();
697 var id = attrs.id;
698 var field = media.template( 'menu-icons-'+ attrs.type +'-field' );
699 var $el;
700
701 delete attrs.id;
702 delete attrs.title;
703
704 _.each( attrs, function( value, key ) {
705 $el = $('#menu-icons-'+ id +'-'+ key).not('._setting');
706 if ( $el.length ) {
707 $el.val( value ).trigger('change');
708 }
709 });
710
711 $('#menu-icons-'+ id +'-select').html( field(attrs) );
712 }
713 });
714
715
716 $('body')
717 .on( 'click', 'div.menu-icons-wrap a._select', menuIcons.selectIcon )
718 .on( 'click', 'div.menu-icons-wrap a._remove', menuIcons.removeIcon )
719 .on( 'change', 'div.menu-icons-wrap select._type', menuIcons.toggleSelect );
720
721 $('div.menu-icons-wrap select._type').trigger('change');
722 }(jQuery));
723