Вход Регистрация
Файл: wordpress/wp-includes/js/tinymce/plugins/wpview/plugin.js
Строк: 801
<?php
/* global tinymce */

/**
 * WordPress View plugin.
 */
tinymce.PluginManager.add'wpview', function( editor ) {
    var $ = 
editor.$,
        
selected,
        
Env tinymce.Env,
        
VK tinymce.util.VK,
        
TreeWalker tinymce.dom.TreeWalker,
        
toRemove false,
        
firstFocus true,
        
_noop = function() { return false; },
        
isios = /iPad|iPod|iPhone/.testnavigator.userAgent ),
        
cursorInterval,
        
lastKeyDownNode,
        
setViewCursorTries,
        
focus,
        
execCommandView,
        
execCommandBefore,
        
toolbar;

    function 
getViewnode ) {
        return 
getParentnode'wpview-wrap' );
    }

    
/**
     * Returns the node or a parent of the node that has the passed className.
     * Doing this directly is about 40% faster
     */
    
function getParentnodeclassName ) {
        while ( 
node && node.parentNode ) {
            if ( 
node.className && ( ' ' node.className ' ' ).indexOf' ' className ' ' ) !== -) {
                return 
node;
            }

            
node node.parentNode;
        }

        return 
false;
    }

    function 
_stopevent ) {
        
event.stopPropagation();
    }

    function 
setViewCursorbeforeview ) {
        var 
location before 'before' 'after',
            
offset before 1;
        
deselect();
        
editor.selection.setCursorLocationeditor.dom.select'.wpview-selection-' locationview )[0], offset );
        
editor.nodeChanged();
    }

    function 
handleEnterviewbeforekey ) {
        var 
dom editor.dom,
            
padNode dom.create'p' );

        if ( ! ( 
Env.ie && Env.ie 11 ) ) {
            
padNode.innerHTML '<br data-mce-bogus="1">';
        }

        if ( 
before ) {
            
view.parentNode.insertBeforepadNodeview );
        } else {
            
dom.insertAfterpadNodeview );
        }

        
deselect();

        if ( 
before && key === VK.ENTER ) {
            
setViewCursorbeforeview );
        } else {
            
editor.selection.setCursorLocationpadNode);
        }

        
editor.nodeChanged();
    }

    function 
removeViewview ) {
        
editor.undoManager.transact( function() {
            
handleEnterview );
            
wp.mce.views.removeeditorview );
        });
    }

    function 
selectviewNode ) {
        var 
clipboard,
            
dom editor.dom;

        if ( ! 
viewNode ) {
            return;
        }

        if ( 
viewNode !== selected ) {
            
// Make sure that the editor is focused.
            // It is possible that the editor is not focused when the mouse event fires
            // without focus, the selection will not work properly.
            
editor.getBody().focus();

            
deselect();
            
selected viewNode;
            
dom.setAttribviewNode'data-mce-selected');

            
clipboard dom.create'div', {
                
'class''wpview-clipboard',
                
'contenteditable''true'
            
}, wp.mce.views.getTextviewNode ) );

            
editor.dom.select'.wpview-body'viewNode )[0].appendChildclipboard );

            
// Both of the following are necessary to prevent manipulating the selection/focus
            
dom.bindclipboard'beforedeactivate focusin focusout'_stop );
            
dom.bindselected'beforedeactivate focusin focusout'_stop );

            
// select the hidden div
            
if ( isios ) {
                
editor.selection.selectclipboard );
            } else {
                
editor.selection.selectclipboardtrue );
            }
        }

        
editor.nodeChanged();
        
editor.fire'wpview-selected'viewNode );
    }

    
/**
     * Deselect a selected view and remove clipboard
     */
    
function deselect() {
        var 
clipboard,
            
dom editor.dom;

        if ( 
selected ) {
            
clipboard editor.dom.select'.wpview-clipboard'selected )[0];
            
dom.unbindclipboard );
            
dom.removeclipboard );

            
dom.unbindselected'beforedeactivate focusin focusout click mouseup'_stop );
            
dom.setAttribselected'data-mce-selected'null );
        }

        
selected null;
    }

    
// Check if the `wp.mce` API exists.
    
if ( typeof wp === 'undefined' || ! wp.mce ) {
        return {
            
getView_noop
        
};
    }

    
// Remove the content of view wrappers from HTML string
    
function emptyViewscontent ) {
        
content content.replace( /<div[^>]+data-wpview-text="([^"]+)"[^>]*>[sS]+?wpview-selection-after[^>]+>[^<>]*</p>s*</div>/g, function( all, match ) {
            return '<p>' + window.decodeURIComponent( match ) + '</p>';
        });

        return content.replace( / data-wpview-marker="
[^"]+"/g'' );
    }

    
// Prevent adding undo levels on changes inside a view wrapper
    
editor.on'BeforeAddUndo', function( event ) {
        if ( 
event.level.content ) {
            
event.level.content emptyViewsevent.level.content );
        }
    });

    
// When the editor's content changes, scan the new content for
    // matching view patterns, and transform the matches into
    // view wrappers.
    
editor.on'BeforeSetContent', function( event ) {
        var 
node;

        if ( ! 
event.selection ) {
            
wp.mce.views.unbind();
        }

        if ( ! 
event.content ) {
            return;
        }

        if ( ! 
event.load ) {
            if ( 
selected ) {
                
removeViewselected );
            }

            
node editor.selection.getNode();

            if ( 
node && node !== editor.getBody() && /^s*https?://S+s*$/i.test( event.content ) ) {
                // When a url is pasted or inserted, only try to embed it when it is in an empty paragrapgh.
                
node editor.dom.getParentnode'p' );

                if ( 
node && /^[suFEFFu00A0]*$/.test( $( node ).text() || '' ) ) {
                    
// Make sure there are no empty inline elements in the <p>
                    
node.innerHTML '';
                } else {
                    return;
                }
            }
        }

        
event.content wp.mce.views.setMarkersevent.content );
    });

    
// When pasting strip all tags and check if the string is an URL.
    // Then replace the pasted content with the cleaned URL.
    
editor.on'pastePreProcess', function( event ) {
        var 
pastedStr event.content;

        if ( 
pastedStr ) {
            
pastedStr tinymce.trimpastedStr.replace( /<[^>]+>/g'' ) );

            if ( /^
https?://S+$/i.test( pastedStr ) ) {
                
event.content pastedStr;
            }
        }
    });

    
// When the editor's content has been updated and the DOM has been
    // processed, render the views in the document.
    
editor.on'SetContent', function() {
        
wp.mce.views.render();
    });

    
// Set the cursor before or after a view when clicking next to it.
    
editor.on'click', function( event ) {
        var 
event.clientX,
            
event.clientY,
            
body editor.getBody(),
            
bodyRect body.getBoundingClientRect(),
            
first body.firstChild,
            
last body.lastChild,
            
firstRectlastRectview;

        if ( ! 
first || ! last ) {
            return;
        }

        
firstRect first.getBoundingClientRect();
        
lastRect last.getBoundingClientRect();

        if ( 
firstRect.top && ( view getViewfirst ) ) ) {
            
setViewCursortrueview );
            
event.preventDefault();
        } else if ( 
lastRect.bottom && ( view getViewlast ) ) ) {
            
setViewCursorfalseview );
            
event.preventDefault();
        } else if ( 
bodyRect.left || bodyRect.right ) {
            
tinymce.eacheditor.dom.select'.wpview-wrap' ), function( view ) {
                var 
rect view.getBoundingClientRect();

                if ( 
rect.top ) {
                    return 
false;
                }

                if ( 
>= rect.top && <= rect.bottom ) {
                    if ( 
bodyRect.left ) {
                        
setViewCursortrueview );
                        
event.preventDefault();
                    } else if ( 
bodyRect.right ) {
                        
setViewCursorfalseview );
                        
event.preventDefault();
                    }

                    return 
false;
                }
            });
        }
    });

    
editor.on'init', function() {
        var 
scrolled false,
            
selection editor.selection,
            
MutationObserver window.MutationObserver || window.WebKitMutationObserver;

        
// When a view is selected, ensure content that is being pasted
        // or inserted is added to a text node (instead of the view).
        
editor.on'BeforeSetContent', function() {
            var 
walkertarget,
                
view getViewselection.getNode() );

            
// If the selection is not within a view, bail.
            
if ( ! view ) {
                return;
            }

            if ( ! 
view.nextSibling || getViewview.nextSibling ) ) {
                
// If there are no additional nodes or the next node is a
                // view, create a text node after the current view.
                
target editor.getDoc().createTextNode('');
                
editor.dom.insertAftertargetview );
            } else {
                
// Otherwise, find the next text node.
                
walker = new TreeWalkerview.nextSiblingview.nextSibling );
                
target walker.next();
            }

            
// Select the `target` text node.
            
selection.selecttarget );
            
selection.collapsetrue );
        });

        
editor.dom.bindeditor.getDoc(), 'touchmove', function() {
            
scrolled true;
        });

        
editor.on'mousedown mouseup click touchend', function( event ) {
            var 
view getViewevent.target );

            
firstFocus false;

            
// Contain clicks inside the view wrapper
            
if ( view ) {
                
event.stopImmediatePropagation();
                
event.preventDefault();

                if ( 
event.type === 'touchend' && scrolled ) {
                    
scrolled false;
                } else {
                    
selectview );
                }

                
// Returning false stops the ugly bars from appearing in IE11 and stops the view being selected as a range in FF.
                // Unfortunately, it also inhibits the dragging of views to a new location.
                
return false;
            } else {
                if ( 
event.type === 'touchend' || event.type === 'mousedown' ) {
                    
deselect();
                }
            }

            if ( 
event.type === 'touchend' && scrolled ) {
                
scrolled false;
            }
        }, 
true );

        if ( 
MutationObserver ) {
            new 
MutationObserver( function() {
                
editor.fire'wp-body-class-change' );
            } )
            .
observeeditor.getBody(), {
                
attributestrue,
                
attributeFilter: ['class']
            } );
        }
    });

    function 
resetViewsrootNode ) {
        
// Replace view nodes
        
$( 'div[data-wpview-text]'rootNode ).each( function( inode ) {
            var 
$node = $( node ),
                
text window.decodeURIComponent$node.attr'data-wpview-text' ) || '' );

            if ( 
text && node.parentNode ) {
                
$node.replaceWith( $( editor.dom.create('p') ).texttext ) );
            }
        });

        
// Remove marker attributes
        
$( 'p[data-wpview-marker]'rootNode ).attr'data-wpview-marker'null );
    }

    
editor.on'PreProcess', function( event ) {
        
// Replace the view nodes with their text in the DOM clone.
        
resetViewsevent.node );
    }, 
true );

    
editor.on'hide', function() {
        
// Replace the view nodes with their text directly in the editor body.
        
wp.mce.views.unbind();
        
deselect();
        
resetViewseditor.getBody() );
    });

    
// Excludes arrow keys, delete, backspace, enter, space bar.
    // Ref: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent.keyCode
    
function isSpecialKeykey ) {
        return ( ( 
key <= 47 && key !== VK.SPACEBAR && key !== VK.ENTER && key !== VK.DELETE && key !== VK.BACKSPACE && ( key 37 || key 40 ) ) ||
            
key >= 224 || // OEM or non-printable
            
key >= 144 && key <= 150 ) || // Num Lock, Scroll Lock, OEM
            
key >= 91 && key <= 93 ) || // Windows keys
            
key >= 112 && key <= 135 ) ); // F keys
    
}

    
// (De)select views when arrow keys are used to navigate the content of the editor.
    
editor.on'keydown', function( event ) {
        var 
key event.keyCode,
            
dom editor.dom,
            
selection editor.selection,
            
nodeviewcursorBeforecursorAfter,
            
rangeclonedRangetempRange;

        if ( 
selected ) {
            
// Ignore key presses that involve the command or control key, but continue when in combination with backspace or v.
            // Also ignore the F# keys.
            
if ( ( ( event.metaKey || event.ctrlKey ) && key !== VK.BACKSPACE && key !== 86 ) || ( key >= 112 && key <= 123 ) ) {
                
// Remove the view when pressing cmd/ctrl+x on keyup, otherwise the browser can't copy the content.
                
if ( ( event.metaKey || event.ctrlKey ) && key === 88 ) {
                    
toRemove selected;
                }
                return;
            }

            
view getViewselection.getNode() );

            
// If the caret is not within the selected view, deselect the view and bail.
            
if ( view !== selected ) {
                
deselect();
                return;
            }

            if ( 
key === VK.LEFT ) {
                
setViewCursortrueview );
                
event.preventDefault();
            } else if ( 
key === VK.UP ) {
                if ( 
view.previousSibling ) {
                    if ( 
getViewview.previousSibling ) ) {
                        
setViewCursortrueview.previousSibling );
                    } else {
                        
deselect();
                        
selection.selectview.previousSiblingtrue );
                        
selection.collapse();
                    }
                } else {
                    
setViewCursortrueview );
                }
                
event.preventDefault();
            } else if ( 
key === VK.RIGHT ) {
                
setViewCursorfalseview );
                
event.preventDefault();
            } else if ( 
key === VK.DOWN ) {
                if ( 
view.nextSibling ) {
                    if ( 
getViewview.nextSibling ) ) {
                        
setViewCursorfalseview.nextSibling );
                    } else {
                        
deselect();
                        
selection.setCursorLocationview.nextSibling);
                    }
                } else {
                    
setViewCursorfalseview );
                }

                
event.preventDefault();
            
// Ignore keys that don't insert anything.
            
} else if ( ! isSpecialKeykey ) ) {
                
removeViewselected );

                if ( 
key === VK.ENTER || key === VK.DELETE || key === VK.BACKSPACE ) {
                    
event.preventDefault();
                }
            }
        } else {
            if ( 
event.metaKey || event.ctrlKey || ( key >= 112 && key <= 123 ) ) {
                return;
            }

            
node selection.getNode();
            
lastKeyDownNode node;
            
view getViewnode );

            
// Make sure we don't delete part of a view.
            // If the range ends or starts with the view, we'll need to trim it.
            
if ( ! selection.isCollapsed() ) {
                
range selection.getRng();

                if ( 
view getViewrange.endContainer ) ) {
                    
clonedRange range.cloneRange();
                    
selection.selectview.previousSiblingtrue );
                    
selection.collapse();
                    
tempRange selection.getRng();
                    
clonedRange.setEndtempRange.endContainertempRange.endOffset );
                    
selection.setRngclonedRange );
                } else if ( 
view getViewrange.startContainer ) ) {
                    
clonedRange range.cloneRange();
                    
clonedRange.setStartview.nextSibling);
                    
selection.setRngclonedRange );
                }
            }

            if ( ! 
view ) {
                
// Make sure we don't eat any content.
                
if ( event.keyCode === VK.BACKSPACE ) {
                    if ( 
editor.dom.isEmptynode ) ) {
                        if ( 
view getViewnode.previousSibling ) ) {
                            
setViewCursorfalseview );
                            
editor.dom.removenode );
                            
event.preventDefault();
                        }
                    } else if ( ( 
range selection.getRng() ) &&
                            
range.startOffset === &&
                            
range.endOffset === &&
                            ( 
view getViewnode.previousSibling ) ) ) {
                        
setViewCursorfalseview );
                        
event.preventDefault();
                    }
                }
                return;
            }

            if ( ! ( ( 
cursorBefore dom.hasClassview'wpview-selection-before' ) ) ||
                    ( 
cursorAfter dom.hasClassview'wpview-selection-after' ) ) ) ) {
                return;
            }

            if ( 
isSpecialKeykey ) ) {
                
// ignore
                
return;
            }

            if ( ( 
cursorAfter && key === VK.UP ) || ( cursorBefore && key === VK.BACKSPACE ) ) {
                if ( 
view.previousSibling ) {
                    if ( 
getViewview.previousSibling ) ) {
                        
setViewCursorfalseview.previousSibling );
                    } else {
                        if ( 
dom.isEmptyview.previousSibling ) && key === VK.BACKSPACE ) {
                            
dom.removeview.previousSibling );
                        } else {
                            
selection.selectview.previousSiblingtrue );
                            
selection.collapse();
                        }
                    }
                } else {
                    
setViewCursortrueview );
                }
                
event.preventDefault();
            } else if ( 
cursorAfter && ( key === VK.DOWN || key === VK.RIGHT ) ) {
                if ( 
view.nextSibling ) {
                    if ( 
getViewview.nextSibling ) ) {
                        
setViewCursorkey === VK.RIGHTview.nextSibling );
                    } else {
                        
selection.setCursorLocationview.nextSibling);
                    }
                }
                
event.preventDefault();
            } else if ( 
cursorBefore && ( key === VK.UP || key ===  VK.LEFT ) ) {
                if ( 
view.previousSibling ) {
                    if ( 
getViewview.previousSibling ) ) {
                        
setViewCursorkey === VK.UPview.previousSibling );
                    } else {
                        
selection.selectview.previousSiblingtrue );
                        
selection.collapse();
                    }
                }
                
event.preventDefault();
            } else if ( 
cursorBefore && key === VK.DOWN ) {
                if ( 
view.nextSibling ) {
                    if ( 
getViewview.nextSibling ) ) {
                        
setViewCursortrueview.nextSibling );
                    } else {
                        
selection.setCursorLocationview.nextSibling);
                    }
                } else {
                    
setViewCursorfalseview );
                }
                
event.preventDefault();
            } else if ( ( 
cursorAfter && key === VK.LEFT ) || ( cursorBefore && key === VK.RIGHT ) ) {
                
selectview );
                
event.preventDefault();
            } else if ( 
cursorAfter && key === VK.BACKSPACE ) {
                
removeViewview );
                
event.preventDefault();
            } else if ( 
cursorAfter ) {
                
handleEnterview );
            } else if ( 
cursorBefore ) {
                
handleEnterview truekey );
            }

            if ( 
key === VK.ENTER ) {
                
event.preventDefault();
            }
        }
    });

    
editor.on'keyup', function() {
        if ( 
toRemove ) {
            
removeViewtoRemove );
            
toRemove false;
        }
    });

    
editor.on'focus', function() {
        var 
view;

        
focus true;
        
editor.dom.addClasseditor.getBody(), 'has-focus' );

        
// Edge case: show the fake caret when the editor is focused for the first time
        // and the first element is a view.
        
if ( firstFocus && ( view getVieweditor.getBody().firstChild ) ) ) {
            
setViewCursortrueview );
        }

        
firstFocus false;
    } );

    
editor.on'blur', function() {
        
focus false;
        
editor.dom.removeClasseditor.getBody(), 'has-focus' );
    } );

    
editor.on'NodeChange', function( event ) {
        var 
dom editor.dom,
            
views editor.dom.select'.wpview-wrap' ),
            
className event.element.className,
            
view getViewevent.element ),
            
lKDN lastKeyDownNode;

        
lastKeyDownNode false;

        
clearIntervalcursorInterval );

        
// This runs a lot and is faster than replacing each class separately
        
tinymce.eachviews, function ( view ) {
            if ( 
view.className ) {
                
view.className view.className.replace( / ?bwpview-(?:selection-before|selection-after|cursor-hide)b/g'' );
            }
        });

        if ( 
focus && view ) {
            if ( ( 
className === 'wpview-selection-before' || className === 'wpview-selection-after' ) &&
                
editor.selection.isCollapsed() ) {

                
setViewCursorTries 0;

                
deselect();

                
// Make sure the cursor arrived in the right node.
                // This is necessary for Firefox.
                
if ( lKDN === view.previousSibling ) {
                    
setViewCursortrueview );
                    return;
                } else if ( 
lKDN === view.nextSibling ) {
                    
setViewCursorfalseview );
                    return;
                }

                
dom.addClassviewclassName );

                
cursorInterval setInterval( function() {
                    if ( 
dom.hasClassview'wpview-cursor-hide' ) ) {
                        
dom.removeClassview'wpview-cursor-hide' );
                    } else {
                        
dom.addClassview'wpview-cursor-hide' );
                    }
                }, 
500 );
            
// If the cursor lands anywhere else in the view, set the cursor before it.
            // Only try this once to prevent a loop. (You never know.)
            
} else if ( ! getParentevent.element'wpview-clipboard' ) && ! setViewCursorTries ) {
                
deselect();
                
setViewCursorTries++;
                
setViewCursortrueview );
            }
        }
    });

    
editor.on'BeforeExecCommand', function() {
        var 
node editor.selection.getNode(),
            
view;

        if ( 
node && ( ( execCommandBefore node.className === 'wpview-selection-before' ) || node.className === 'wpview-selection-after' ) && ( view getViewnode ) ) ) {
            
handleEnterviewexecCommandBefore );
            
execCommandView view;
        }
    });

    
editor.on'ExecCommand', function() {
        var 
toSelectnode;

        if ( 
selected ) {
            
toSelect selected;
            
deselect();
            
selecttoSelect );
        }

        if ( 
execCommandView ) {
            
node execCommandViewexecCommandBefore 'previousSibling' 'nextSibling' ];

            if ( 
node && node.nodeName === 'P' && editor.dom.isEmptynode ) ) {
                
editor.dom.removenode );
                
setViewCursorexecCommandBeforeexecCommandView );
            }

            
execCommandView false;
        }
    });

    
editor.on'ResolveName', function( event ) {
        if ( 
editor.dom.hasClassevent.target'wpview-wrap' ) ) {
            
event.name editor.dom.getAttribevent.target'data-wpview-type' ) || 'wpview';
            
event.stopPropagation();
        } else if ( 
getViewevent.target ) ) {
            
event.preventDefault();
            
event.stopPropagation();
        }
    });

    
editor.addButton'wp_view_edit', {
        
tooltip'Edit '// trailing space is needed, used for context
        
icon'dashicon dashicons-edit',
        
onclick: function() {
            
selected && wp.mce.views.editeditorselected );
        }
    } );

    
editor.addButton'wp_view_remove', {
        
tooltip'Remove',
        
icon'dashicon dashicons-no',
        
onclick: function() {
            
selected && removeViewselected );
        }
    } );

    
editor.once'preinit', function() {
        
toolbar editor.wp._createToolbar( [
            
'wp_view_edit',
            
'wp_view_remove'
        
] );
    } );

    
editor.on'wptoolbar', function( event ) {
        if ( 
selected ) {
            
event.element selected;
            
event.toolbar toolbar;
        }
    } );

    
// Add to editor.wp
    
editor.wp editor.wp || {};
    
editor.wp.getView getView;

    
// Keep for back-compat.
    
return {
        
getViewgetView
    
};
});
?>
Онлайн: 1
Реклама