TinyMCE如何在删除图片时获取图片详细信息

4
我创建了一个插件来处理tinymce的图像上传,一切都正常工作。我想做的是,如果用户删除了图片,就能够从我的服务器上删除该图片,以免出现大量的孤立文件。
我已经能够使用tinymce初始化设置部分监听nodechange事件。
<script src="//tinymce.cachefly.net/4.0/tinymce.min.js"></script>
<script type="text/javascript">
tinymce.init({
    selector: "textarea",
    plugins: "autoresize",

    toolbar: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image jbimages",
    relative_urls: false,
        setup : function(ed) {
                    ed.on("NodeChange", function(e) {
        console.log('change event', e);
               });
}

});</script>

这给了我一个事件,我可以在控制台中看到它,但我找不到从事件中获取的任何内容,告诉我图片已被删除,以便我可以从服务器上删除该图片。我已经为此创建了一个演示,您可以在这里查看。
如果您加载控制台并删除图像,您将明白我的意思。我是否缺少事件的某些属性或方法?
提前致谢。
3个回答

7

我也想做同样的事情,但是在经过大量的互联网搜索和调试后,我发现唯一实现这一目标的方法是在编辑器中选择图像时观察删除键或退格键是否被按下。

因此,在你的tinymce.init "setup"函数中:

ed.on('KeyDown', function (e) {

    if ((e.keyCode == 8 || e.keyCode == 46) && editor.selection) { // delete & backspace keys

        var selectedNode = editor.selection.getNode(); // get the selected node (element) in the editor

        if (selectedNode && selectedNode.nodeName == 'IMG') {

            MyCallback(selectedNode.src); // A callback that will let me invoke the deletion of the image on the server if appropriate for the image source.
        }
    }
});

我在一个新插件中设置了它,然后将回调函数添加为该插件的其中一个设置。


1
有趣的是,如果您同时选择多个元素(例如 img 和 p 标签),然后执行删除操作,这会如何影响代码? - Chinmay
好的观点。简而言之,它不起作用。我尝试了Ctrl+A和在那种情况下的"selectedNode"是TinyMCE IFrame的"body"标签。该方法必须通过递归遍历所选节点(如果它不是图像)的子节点并挑选出所有要处理的图像来使其更加健壮。我非常确定还会有其他情况,您可以删除包含一个或多个图像的节点。就我所见,您无法选择多个节点(尝试使用ctrl单击、shift单击和用鼠标突出显示)。 - JohnB
是的。我最终做的事情非常特定于我的实现。我将我的图像钩到了URL上(无论如何,我都必须在数据库中维护链接)。服务器在提交时会删除除HTML中的图像之外的所有图像。 - Chinmay
1
使用 tinymce v4 替代: var selectedNode = editor.selection.getNode(); 使用: var selectedNode = tinymce.activeEditor.selection.getNode(); - Jaylord Ferrer
这是一个很好的解决方案,但需要提醒一句。如果你想在移动设备上使用“mobile”键配置,那么不要将此代码作为插件添加,因为目前 TinyMCE 不支持移动配置的自定义插件。当我说移动配置时,我的意思是“tinymce.init({mobile:{theme:'mobile'}});”... - Charles Robertson
相信我,如果你计划为移动设备添加支持,你需要使用移动配置。桌面配置对于移动设备来说并不好用,其中许多核心功能,如滚动等,在桌面配置下无法实现! - Charles Robertson

3
在我看来,我想通过在init_instance_callback方法中使用MutationObserver来完成这项工作。
init_instance_callback: function (editor) {
    //console.log("tinymce " + editor.id + " init finished.");

    var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;

    var observer = new MutationObserver(function (mutations, instance) {
        var addedImages = new Array();
        $.each(mutations, function (index, mutationRecord) {
            for (var i = 0; i < mutationRecord.addedNodes.length; i++) {
                var currentNode = mutationRecord.addedNodes[i];
                if (currentNode.nodeName == 'IMG' && currentNode.className != "mce-clonedresizable") {
                    if (addedImages.indexOf(currentNode.src) >= 0) continue;

                    addedImages.push(currentNode.getAttribute("src"));
                    continue;
                }

                var imgs = $(currentNode).find('img');
                for (var j = 0; j < imgs.length; j++) {
                    if (addedImages.indexOf(imgs[j].src) >= 0) continue;

                    addedImages.push(imgs[j].getAttribute("src"));
                }
            }
        });

        var removedImages = new Array();
        $.each(mutations, function (index, mutationRecord) {
            for (var i = 0; i < mutationRecord.removedNodes.length; i++) {
                var currentNode = mutationRecord.removedNodes[i];
                if (currentNode.nodeName == 'IMG' && currentNode.className != "mce-clonedresizable") {
                    if (removedImages.indexOf(currentNode.src) >= 0) continue;

                    removedImages.push(currentNode.getAttribute("src"));
                    continue;
                }

                var imgs = $(currentNode).find('img');
                for (var j = 0; j < imgs.length; j++) {
                    if (removedImages.indexOf(imgs[j].src) >= 0) continue;

                    removedImages.push(imgs[j].getAttribute("src"));
                }
            }
        });

        for (var i = 0; i < removedImages.length; i++) {
            var imageSrc = removedImages[i];
            if (addedImages.indexOf(imageSrc) >= 0) continue;

            if (confirm("delete image from server?\n" + imageSrc)) {
                //delete image from server.
            }
        };
    });
    
    observer.observe(editor.getBody(), {
        childList: true,
        subtree: true
    });
}

完全适用于我。谢谢。 - pradipta paul

2

这种变体已应用于tinyMCE-5,但我认为它会很有用。

  1. 从服务器获取初始标记(编辑器的值);
  2. 从标记中解析图像的ID(使用正则表达式等);
  3. 将图像ID保存在状态数组中;
  4. 在向编辑器添加新图像时,我们应该将新ID添加到现有状态中(使用images_upload_handler);
  5. 在提交数据时,我们应该再次解析编辑器的值,并将其与现有状态进行比较(实际上是比较两个数组);
  6. 对于缺失的ID,调用api.deleteImages。

这里没有描述一些细节,但我认为总体逻辑很清楚。这种变体保证我们在编辑器中进行所有复制/粘贴/删除、撤销/重做等操作后(第5点),得到最终图像列表。此外,我们避免了在编辑器的每个操作上使用监听器和复杂逻辑,而只在获取/提交数据时处理所有数据。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接