/home/arranoyd/magicraft/wp-content/plugins/note/assets/js/note-tinymce-insert.js
/**
 * Note TinyMCE Insert Plugin - /assets/js/note-tinymce-insert.js
 * License: GPLv2 or later
 * Copyright: Janneke Van Dorpe (iseulde), http://iseulde.com/
 *
 * @see https://github.com/iseulde/wp-front-end-editor/blob/master/js/tinymce.insert.js
 *
 * We've used Janneke Van Dorpe's TinyMCE Insert Plugin as a base and modified it to suit our needs.
 */

/* global tinymce */

tinymce.PluginManager.add( 'note_insert', function( editor ) {
	'use strict';

	var DOM = tinymce.DOM,
		Factory = tinymce.ui.Factory,
		panel,
		$panel_el,
		$ = jQuery,
		$el = $( editor.getElement() ),
		panel_client_height = 0, // Panel height
		panel_offset_width = 0, // Panel offset width
		$note_widget = $el.parents( '.note-widget' ),
		panel_visible = false, // Flag to determine if the
		panel_hover = false, // Flag to determine if the
		panel_timer,
		panel_timeout = 400, // ms
		frame,
		toolbar;


	/*
	 * TinyMCE Editor Events
	 */

	/*
	 * Preinit event
	 */
	editor.on( 'preinit', function() {
		/*
		 * Panel
		 */
		// Create the Panel (also store a reference to the panel on the editor)
		panel = editor.note.insert_panel = Factory.create( {
			type: 'panel',
			layout: 'flow',
			classes: 'insert-panel note-insert-panel',
			ariaRoot: true,
			ariaRemember: true,
			items: []
		} );

		/*
		 * This function sets the panel's position in the DOM.
		 */
		// TODO: Need to determine when the bounds of the browser window interfere with the position and adjust as necessary
		panel.setPosition = function() {
			var insert_el = this.getEl(), // Insert element
				body = editor.getBody(), // Editor body
				body_pos = editor.dom.getPos( body ), // Editor body position
				left = ( body_pos.x + ( body.clientWidth / 2 ) - ( panel_offset_width / 2 ) ),
				top = ( body_pos.y - panel_client_height - parseInt( DOM.getStyle( insert_el, 'margin-bottom', true ), 10 ) );

			// Adjust the styles of the panel (tied to the insert element)
			DOM.setStyles( insert_el, {
				'left': left, // Editor width minus toolbar width
				'top': top // Editor body y position minus client height reference
			} );

			// Return this for chaining
			return this;
		};

		// Render the panel to the document body
		panel.renderTo( document.body );

		// Reference to the panel element
		$panel_el = $( panel.getEl() );

		/*
		 * Create the toolbar.
		 *
		 * Because the WordPress TinyMCE plugin renders the toolbar to the DOM for us,
		 * we need to add it after the panel is rendered so that we can append it to our
		 * panel 'body' element.
		 */

		// Create the toolbar
		toolbar = editor.wp._createToolbar( editor.settings.blocks );

		// Add the toolbar to our panel
		panel.add( toolbar );

		// Append the toolbar to our panel in the DOM (grab the DOMQuery reference)
		toolbar.$el.appendTo( panel.getEl( 'body' ) );

		// Show the toolbar (WordPress hides it by default)
		toolbar.show();


		// Store the client height of the panel (before it's hidden)
		panel_client_height = panel.getEl().clientHeight;

		// Store the client height of the panel (before it's hidden)
		panel_offset_width = panel.getEl().offsetWidth;

		// Hide the panel
		panel.hide();


		/*
		 * Event Listeners
		 */

		// Window Resize
		DOM.bind( window, 'resize', function() {
			// Hide the panel
			panel.hide();
		} );

		// Set the widget selector (based on note data on the editor)
		if ( editor.hasOwnProperty( 'note' ) && editor.note.hasOwnProperty( 'parent' ) ) {
			$note_widget = $el.parents( editor.note.parent );
		}

		// Note Widgets only
		if ( $note_widget.length ) {
			// Mouse Enter (hover)
			$note_widget.on( 'mouseenter.note', function() {
				// Set the position and show the panel
				panel.setPosition().show();

				// Set the visible flag
				panel_visible = true;

				// Clear the timeout
				clearTimeout( panel_timer );
			} );

			// Mouse Leave (leave; exit)
			$note_widget.on( 'mouseleave.note', function() {
				// Set a timer if the panel is visible
				if ( panel_visible ) {
					panel_timer = setTimeout( function() {
						// Hide the panel
						panel.hide();
					}, panel_timeout );
				}
			} );
		}

		// Panel - Mouse Enter (hover)
		$panel_el.on( 'mouseenter.note', function() {
			// Set the position and show the panel
			panel.setPosition().show();

			// Set the hover flag
			panel_hover = true;

			// Clear the timeout
			clearTimeout( panel_timer );
		} );

		// Panel - Mouse Leave (leave; exit)
		$panel_el.on( 'mouseleave.note', function() {
			// Set a timer if the panel is visible and hovered
			if ( panel_visible && panel_hover ) {
				panel_timer = setTimeout( function() {
					// Hide the panel
					panel.hide();
				}, panel_timeout );
			}
		} );
	} );


	/*
	 * TinyMCE Editor Buttons
	 */

	// TODO: Rename?
	// WordPress Image
	editor.addButton( 'wp_image', {
		tooltip: 'Image', // TODO: i18n, l10n
		icon: 'format-image dashicons-format-image',
		onclick: function() {
			var frame_menu;

			// If we don't have focus
			if ( ! DOM.hasClass( editor.getBody(), 'mce-edit-focus' ) ) {
				// Focus the editor (skip focusing and just set the active editor)
				editor.focus( true );

				// Since we're skipping the DOM focusing, we need to set the global wpActiveEditor ID, which is used as a fallback when WordPress is determining the active TinyMCE editor (@see https://github.com/WordPress/WordPress/blob/4.5-branch/wp-includes/js/tinymce/plugins/wordpress/plugin.js#L89)
				window.wpActiveEditor = editor.id;
			}

			// If we don't have a frame
			if ( ! frame ) {
				// Attach the frame to the editor
				editor.note.media.frame = frame = wp.media.editor.add( editor.id, {
					id: 'note-insert', // Unique ID for this frame
					state: 'note-insert', // Custom Note state
					frame: 'post', // Select state for frame
					// States attached to this frame
					states: [
						// Note Insert State
						new wp.media.controller.Library( {
							id: 'note-insert',
							title: wp.media.view.l10n.insertMediaTitle,
							priority: 10,
							filterable: 'all',
							library: wp.media.query( { type: 'image' } ),
							multiple: false, // Only allow one selection
							editable: false,
							display: true, // TODO: Necessary?
							displaySettings: true,
							displayUserSettings: true
						} )
					],
					// Frame button configuration
					button: {
						text: 'Insert Into Widget', // Button label // TODO: I18n & l10n - move to Note Customizer
						event: 'insert' // Trigger the insert event on click
					}
				} );

				// Hide the default states TODO: Fix gallery insertion and then unhide these
				frame_menu = frame.menu.get();
				frame_menu.hide( 'embed' ); // Embed
				frame_menu.hide( 'gallery' ); // Gallery
				frame_menu.hide( 'insert' ); // Insert (Post)
				frame_menu.hide( 'playlist' ); // Playlist
				frame_menu.hide( 'video-playlist' ); // Playlist

				// If the frame is not attached
				if ( ! frame.modal.views.attached ) {
					// Attach the frame (fixes a bug in FireFox and IE where the $el is initially visible so the rendering process is never completed @see https://github.com/WordPress/WordPress/blob/4.5-branch/wp-includes/js/media-views.js#L6764)
					frame.attach();
				}
			}

			// Open the frame for this editor (wp.media.editor.open() fixes a bug where images could be inserted into the wrong editor due to the active editor reference being incorrect; @see https://github.com/WordPress/WordPress/blob/703d5bdc8deb17781e9c6d8f0dd7e2c6b6353885/wp-includes/js/media-editor.js#L1062)
			wp.media.editor.open( editor.id );

			// Fire an event on the editor (pass an empty array of data and the frame)
			editor.fire( 'wpLoadImageForm', { data : [], frame: frame } );
		}
	} );


	// Note Edit Button
	editor.addButton( 'note_edit', {
		tooltip: 'Edit', // TODO: i18n, l10n
		icon: 'edit dashicons-edit',
		onclick: function() {
			// Send data to the Customizer
			wp.customize.NotePreview.preview.send( 'note-widget-edit', editor.note.widget_data );
		}
	} );
} );