9

When i add an image in tinymce, this is the default html source code i get:

<p><img class="img-responsive img-post" src="/Images/uploads/img.png" alt="" /></p>

How do i change this? to something like:

<p><img class="img-responsive img-post" data-original="/Images/uploads/img.png" src="/Images/loading.gif" alt="" /></p>

Where i have data-original as the src and src is the loading icon, it needs to be like this because i have lazy loading on images.

I know you can extend valid elements using:

extend_valid_elements: "data-original"

but how do i change the structure of default html source code? Is there something like on selecting ok for image insert callback??

Update:

Here is my tinymce initiation code:

/******************************tinyMce*******************************/
function tinyMce() {
    tinymce.init({
        theme: "modern",
        selector: "#mceEditor",
        height: 500,
        extend_valid_elements: "data-original",
        relative_urls: true,
        convert_urls: false,
        image_advtab: true,
        image_title: false,
        image_description: false,
        image_dimensions: false,
        image_class_list: [
            { title: "Responsive", value: "lazy img-responsive img-post" }
        ],
        image_list: function (success) {
            $.ajax({
                url: "/Image/List",
                type: "GET",
                dataType: "json",
                success: function (data) {
                    success(data);
                }
            });
        },
        // enable automatic uploads of images represented by blob or data URIs
        automatic_uploads: true,
        // URL of our upload handler (for more details check: https://www.tinymce.com/docs/configure/file-image-upload/#images_upload_url)
        images_upload_url: "/Image/Upload",
        // here we add custom filepicker only to Image dialog
        file_picker_types: "image",
        // and here's our custom image picker
        file_picker_callback: function (cb, value, meta) {
            var input = document.createElement("input");
            input.setAttribute("type", "file");
            input.setAttribute("accept", "image/*");

            // Note: In modern browsers input[type="file"] is functional without 
            // even adding it to the DOM, but that might not be the case in some older
            // or quirky browsers like IE, so you might want to add it to the DOM
            // just in case, and visually hide it. And do not forget do remove it
            // once you do not need it anymore.

            input.onchange = function () {
                var file = this.files[0];

                var reader = new FileReader();
                reader.readAsDataURL(file);
                reader.onload = function () {
                    // Note: Now we need to register the blob in TinyMCEs image blob
                    // registry. In the next release this part hopefully won't be
                    // necessary, as we are looking to handle it internally.
                    var id = "blobid" + (new Date()).getTime();
                    var blobCache = tinymce.activeEditor.editorUpload.blobCache;
                    var base64 = reader.result.split(',')[1];
                    var blobInfo = blobCache.create(id, file, base64);
                    blobCache.add(blobInfo);

                    // call the callback and populate the Title field with the file name
                    cb(blobInfo.blobUri(), { title: file.name });
                };
            };

            input.click();
        }
    });
}

I am thinking about another way now, if i can replace default src attribute inside tinymce to data-original, that would be perfect, but inside tinymce, if i use data-original, it won't show the picture, it justs shows blank. Is there a way to tell tinymce when adding an image, put data-original instead of src and read from data-original instead of src?

so from this:

<p><img class="img-responsive img-post" src="/Images/uploads/img.png" alt="" /></p>

to this without src at all:

<p><img class="img-responsive img-post" data-original="/Images/uploads/img.png" alt="" /></p>
Mindless
  • 2,352
  • 3
  • 27
  • 51
  • You may find that adding images *after* the lazyloading code has loaded it may not detect them. Consequently, it will not show the image at all if you exclude the `src` attribute. – K Scandrett Aug 30 '17 at 14:25
  • @KScandrett it will show – Mindless Aug 30 '17 at 14:29
  • https://www.tinymce.com/docs/configure/file-image-upload/ & https://www.tinymce.com/docs/get-started/upload-images/ for upload completion events – K Scandrett Aug 30 '17 at 15:03
  • Thanks, but i've read this already, uploading has already been done and it's not what i want – Mindless Aug 31 '17 at 01:24

3 Answers3

4

Here is a way to detect when an image gets inserted into the editor.

JS

var newSrc = "/Images/loading.gif";


tinymce.init({
  selector: 'textarea',
  plugins: "image",
  toolbar: "image",
  height: 350,
    setup: function(editor){
    editor.on('NodeChange', function (e) {
      if(e.element.tagName === "IMG"){          
        e.element.setAttribute("data-original", e.element.currentSrc);
        e.element.setAttribute("src", newSrc);
      }
    });
  }
});

You can access the element by listening to the NodeChange event. Then checking tagName is of type IMG. Then we just set our attributes normally.

Check this Demo

PalinDrome555
  • 907
  • 6
  • 16
  • sorry, this isn't what i want, it's causing a weird problem where the image disappears when you inspect source, i think the NodeChange event is not only for image uploads but more. – Mindless Aug 21 '17 at 01:29
  • 1
    and also, i think because i am using local uploading, the url is blob and then it changes to server url, but it is setting data-original to currentSrc before it actually changes to a server url. Any event that i can use so when image uploads finishes, set url to currentSrc? – Mindless Aug 21 '17 at 01:32
2

You can solve this problem with regular expression and string replace method the function will return the replacement for the match.. like the example below

// tinymce returning string
let content = '<p><img class="img-responsive img-post" src="/Images/uploads/img.png" alt="" /></p><p><img class="img-responsive img-post" src="/Images/uploads/img2.png" alt="" /></p>';

// searching through all the img tags in the content..
content = content.replace(/<img(\s+[^>]*)src="([^"]*)"([^>]*)>/g,function(full,key, value){
 return `<img ${key} src="/Images/loading.gif" data-original="${value}" alt="">`;
});


//content replaced
console.log(content);

A regular expression is used to match all the img tags, then we just the new data-original attribute and replace it in the original string

Renzo Calla
  • 7,486
  • 2
  • 22
  • 37
  • and this will run on page load i assume? won't this slow the page down if i have heaps of images on a page – Mindless Sep 07 '17 at 00:46
  • It can run on the page load as you said it might slow the page if you have a significantly amount of image, but it's more optimized than replacing this with pure js string methods...You can save the tinymce result with this regexp, in that case you won't need to run on every page load... – Renzo Calla Sep 07 '17 at 12:27
1

...but inside tinymce, if i use data-original, it won't show the picture, it just shows blank.

Keep doing what you are doing here and simply add a change handler to add new src...

editor.on('Change', function (e) {
    // Get images that have data-original attribute but not src
    $( 'img[data-original]' ).not( 'img[src]' )
      .attr( 'src', '/Images/loading.gif' ) // Add src
} );
shramee
  • 5,030
  • 1
  • 22
  • 46