cloudinary / cloudinary_js

Cloudinary JavaScript library
MIT License
328 stars 224 forks source link

How to deal with iFrame #99

Closed ilan-schemoul closed 6 years ago

ilan-schemoul commented 8 years ago

$.cloudinary.responsive() doesn't work because my images must be inside an iframe (tinymce), I can do something like $('iframe').contents().find('.dynamic-image').last().cloudinary() but then it's not responsive ? PS : I know iFrame sucks but it's tinymce's fault.

ilan-schemoul commented 8 years ago

The full story is that I have an editor (WYSIWYG) which is an iFrame. When I insert images it goes directly to the iFrame. This is just a way to edit texts, it could be either an admin or an user who edit the text, if it was only admin I could give an horrible static image not responsive but users also edit texts. So when an image is inserted into an iFrame it HAS to be be responsive. I already waste full days on Cloudinary, including because when one calls unsigned_cloudinary_upload() on a node, it's stupid but has to have name="file" tough it's not mentioned in articles

tocker commented 8 years ago

Hi @NitroBAY, If the iframe src on the same domain as your main document? Can you load scripts on the iframe?

ilan-schemoul commented 8 years ago

The iFrame is generated by a plugin on the DOM so it is on the same domain that the website. I'll check if tinyMCE (the WYSIWYG editor) allow me to load script when it generated an iFrame, thanks.

tocker commented 8 years ago

Good luck!

Here's a little script to help you test. Note that using requirejs, webpack, browserify et al will probably be better for production use.

var f;
var createIFrame = true;
if (createIFrame) {
// create a frame and append it to the current page
    f = document.createElement('iframe');
    f.setAttribute('width', '50%');
    f.setAttribute('height', '100%');

    document.body.appendChild(f);
} else {
// ~~or~~

// get the frame created by the plugin
    f = document.getElementById('frame_id');
}

// create a script tag on iframe
// onload is used to make sure each script is loaded before loading the next one
var scriptTag = f.contentDocument.createElement('script');
scriptTag.innerHTML =
        "function loadScript(src, onload) {" +
        "    var tag = document.createElement('script');" +
        "    tag.src = src;" +
        "    if( onload) { tag.onload = onload;}" +
        "    document.head.appendChild(tag);" +
        "}" +
        "loadScript('https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js', function(){" +
        "    loadScript('https://cdnjs.cloudflare.com/ajax/libs/cloudinary-jquery-file-upload/2.1.2/cloudinary-jquery-file-upload.min.js', function(){" +
        "        window.cl = cloudinary.Cloudinary.new({cloud_name: 'demo', responsive: true});" + "" +
        "        document.body.append(cl.image('sample', {width: 'auto', crop: 'scale'}));" +
        "        cl.responsive()" +
        "    })" +
        "});";
f.contentDocument.body.appendChild(scriptTag);
ilan-schemoul commented 8 years ago

Thanks, but due to very very particular structure of tinymce iframe and Meteor (the isomorphic framework I use) it would be simpler if cloudinary could take as a possible option the iframe one wants to work on. Something lyou could do something like

if (option.iframe !== 'undefined') {
// This is for jquery but you can do the same with jQuery
  const nodes = $(option.iframe).contents();
} 

I mean I don't know what's the best approach but I really would like that Cloudinary know how to use another 'DOM' than the main one. But obviously if I'm the only one with such problem, you'll not consider this option, will you ? Edit : it was a bit tricky, as I was already using my own code to insert script I didn't use yours but everyone should notice that if you want to create a script which has iframe's windows as SCOPE you need to create script like this : myIframe.contentWindow.document.createElement("script"); (see http://stackoverflow.com/a/5328334/5496376). Now I need to find a way to use all the packages, loaded automatically in the DOM by Meteor, in the iFrame. Sometimes it's good to be the first one to have a specific hard problem (make Cloudinary images responsives inside a tinyMCE frame when using Meteor framework) because when it's a common problem stackoverflow always tell me the solution and it's not much fun.

ilan-schemoul commented 8 years ago

It's in progress. Now I create a script element which is properly bind to the iFrame and I load all the script to the iFrame (problem of performance ?)

        ed.on('init', () => {
          $('script').each((i, script) => {
            $(ed.getWin().document.body).append($(script));
          });

          const script = ed.getWin().document.createElement('script');
          script.src = '/iframeImage.js';
          ed.getWin().document.body.appendChild(script);
        });
      }
ilan-schemoul commented 8 years ago

No finally with Meteor <script> are useless because of how my framework is made. Edit for instance in the (doc)[https://cloudinary.github.io/pkg-cloudinary-core/Cloudinary.html#processImageTags] processImageTags() doesn't takes any argument but if I call it w/o arguments it says that nodes is undefined and he's not happy because he tries to make a for with nodes.length. And nodes is undefined because it's written Cloudinary.prototype.processImageTags = function(nodes, options) So finally Cloudinary needs a nodes arguments ? myCloudinary.processImageTags(document.getElementsByTagName('img')); returns jquery.cloudinary.js:3606 Uncaught TypeError: Cannot read property 'tagName' of undefined

ilan-schemoul commented 8 years ago

Finally due to the non compatibility between Meteor and iFrame, cloudinary has to change to have an option iFrame.

ilan-schemoul commented 8 years ago

I lost more than a full month with cloudinary, so I really seek for a short answer to my problem now.

taragano commented 8 years ago

Sorry for our response delay @NitroBAY. Note that when using responsive functionality the url should be placed in data-src and not in src. A url placed in src will be immediately loaded by the browser, before the responsive script has changed w_auto to the appropriate value.

ilan-schemoul commented 8 years ago

Yes I know

roeeba commented 6 years ago

Closing this issue due to the time elapsed. Please feel free to either re-open the issue, contact our support at http://support.cloudinary.com or create a new ticket if you have any additional issues.