icecoder / ICEcoder

Browser code editor awesomeness
http://icecoder.net
Other
1.41k stars 347 forks source link

Feature request: option for simple "preview window" reload instead of innerhtml #642

Open Kasad opened 8 years ago

Kasad commented 8 years ago

Dear developer,

I love the power of your editor, but two things I miss:

Example: RewriteRule ^domainfolder/(.*)$ https://realdomain.com/$1 [R=301,NC,L]

This works fantastically for pictures and files (like php), but when I edit the code and the preview-window is going to update, the following error occurs:

Uncaught SecurityError: Blocked a frame with origin "https://editordomain.com" from accessing a frame with origin "https://realdomain.com". Protocols, domains, and ports must match.

I've read a lot and bypassing this restriction is freaking difficult... so I think it would be easier to just have the option to simply reload the content of the preview-window instead of trying to act with it's innerhtml.

TL:DR ;) Could you please add an option to simply reload the preview window after stopping to type for x seconds?

Code example for this: http://stackoverflow.com/a/4220182

Thank you very much.

Kasad

Kasad commented 8 years ago

I was bored and have done it by myself XD I added some try / catch events to prevent the editor to crash when trying to access the cross domain preview window. If cross-domain is detected, the preview, window only updates after the file is saved (for example with contr. + s). Also the console shows the recognition of the cross-domain...

Because of the cross-domain-policy it needs a small helper script in the page you want to preview. So simply add this line to your code. After finishing your project, you could simply remove it. It listens to an windowMessage command from the editor and simply reloads, if this command is recognized.

In your previewed page: <script>window.onmessage = function (e) {if (e.data === 'reload') { window.location.reload(); }};</script>

You can add it to your code if you like:

/lib/ice-coder.js (renamed it to ice-coder.min.js so the editor uses the non minified version).

from line 678 .... to // Clean up our loaded code


    // Update preview window content
    updatePreviewWindow: function(thisCM,filepath,filename,fileExt) {
                try {
                    if (top.ICEcoder.previewWindow.location.pathname==filepath) {
                            if (["htm","html","txt"].indexOf(fileExt) > -1) {
                                    top.ICEcoder.previewWindow.document.documentElement.innerHTML = thisCM.getValue();
                            } else if (["md"].indexOf(fileExt) > -1) {
                                    top.ICEcoder.previewWindow.document.documentElement.innerHTML = mmd(thisCM.getValue());
                            }
                    } else if (["css"].indexOf(fileExt) > -1) {
                            if (top.ICEcoder.previewWindow.document.documentElement.innerHTML.indexOf(filename) > -1) {
                                    var css = thisCM.getValue();
                                    var style = document.createElement('style');
                                    style.type = 'text/css';
                                    style.id = "ICEcoder"+filepath.replace(/\//g,"_");
                                    if (style.styleSheet){
                                            style.styleSheet.cssText = css;
                                    } else {
                                            style.appendChild(document.createTextNode(css));
                                    }
                                    if (top.ICEcoder.previewWindow.document.getElementById(style.id)) {
                                            top.ICEcoder.previewWindow.document.documentElement.removeChild(top.ICEcoder.previewWindow.document.getElementById(style.id));
                                    }
                                    top.ICEcoder.previewWindow.document.documentElement.appendChild(style);
                            }
                    }
                } catch(err){
                    console.log('Cross domain? ' + err);
                }
        // Do the pesticide plugin if it exists
        try {top.ICEcoder.doPesticide();} catch(err) {};
        // Do the stats.js plugin if it exists
        try {top.ICEcoder.doStatsJS('update');} catch(err) {};
        // Do the responsive plugin if it exists
        try {top.ICEcoder.doResponsive();} catch(err) {};
    },

    // Clean up our loaded code

from line 3024 ..... to // Reset auto-logout timer:


    // Open/show the preview window
    openPreviewWindow: function() {
        if (top.ICEcoder.openFiles.length>0) {
            var cM, cMdiff, thisCM, filepath, filename, fileExt;

            filepath = top.ICEcoder.openFiles[top.ICEcoder.selectedTab-1];
            filename = filepath.substr(filepath.lastIndexOf("/")+1);
            fileExt = filename.substr(filename.lastIndexOf(".")+1);
            cM = ICEcoder.getcMInstance();
            cMdiff = ICEcoder.getcMdiffInstance();
            thisCM = top.ICEcoder.editorFocusInstance.indexOf('diff') > -1 ? cMdiff : cM;

            top.ICEcoder.previewWindowLoading = true;
            top.ICEcoder.previewWindow = window.open(filepath,"previewWindow",500,500);
            if (["md"].indexOf(fileExt) > -1) {
                top.ICEcoder.previewWindow.onload = function() {
                    top.ICEcoder.previewWindowLoading = false;
                    top.ICEcoder.previewWindow.document.documentElement.innerHTML = mmd(thisCM.getValue())
                };
            } else {

                            try {
                                top.ICEcoder.previewWindow.onload = function() {
                                    top.ICEcoder.previewWindowLoading = false;
                                    // Do the pesticide plugin if it exists
                                    try {top.ICEcoder.doPesticide();} catch(err) {};
                                    // Do the stats.js plugin if it exists
                                    try {top.ICEcoder.doStatsJS('open');} catch(err) {};
                                    // Do the responsive plugin if it exists
                                    try {top.ICEcoder.doResponsive();} catch(err) {};
                                }
                            } catch (err) {
                                console.log('Cross domain? ' + err);
                            }

            }
        }
    },

    // Reset auto-logout timer

lib/file-control-xhr.php

from line 450 .... to // Copy over content to diff pane if we have that setting on


                // Reload previewWindow window if not a Markdown file
                // In doing this, we check on an interval for the page to be complete and if we last saw it loading
                // When we are done loading, so set the loading status to false and load plugins ontop...       
                $doNext .= 'try{ if (top.ICEcoder.previewWindow.location && top.ICEcoder.previewWindow.location.pathname.indexOf(".md")==-1) {
                    top.ICEcoder.previewWindowLoading = false;
                    top.ICEcoder.previewWindow.location.reload(true);

                    top.ICEcoder.checkPreviewWindowLoadingInt = setInterval(function() {
                        if (top.ICEcoder.previewWindow.document.readyState != "loading" && top.ICEcoder.previewWindowLoading) {
                            top.ICEcoder.previewWindowLoading = false;
                            try {top.ICEcoder.doPesticide();} catch(err) {};
                            try {top.ICEcoder.doStatsJS(\'save\');} catch(err) {};
                            try {top.ICEcoder.doResponsive();} catch(err) {};
                            clearInterval(top.ICEcoder.checkPreviewWindowLoadingInt);
                        } else {
                            top.ICEcoder.previewWindowLoading = top.ICEcoder.previewWindow.document.readyState == "loading" ? true : false;
                        }
                    },4);

                }; }catch(err){
                                    console.log("Cross domain? " + err);
                                    console.log("Use this helper in your page: <script>window.onmessage = function (e) {if (e.data === \'reload\') { window.location.reload(); }};</script>");
                                    top.ICEcoder.previewWindow.postMessage(\'reload\', \'*\');
                };';

                // Copy over content to diff pane if we have that setting on
mattpass commented 8 years ago

Thanks for the suggestions and what looks like potential solution. I'll go through all of this soon and if it seems sound will implement - thanks very much!

Re a HTML, PHP beautifier - you can highlight code and press the tab key to auto-indent, but that's not going as far as a proper beautifier. If you know of a very small & well written JS based beautifier for HTML/PHP, let me know and I can make it a plugin for ICEcoder.

(Is what I did with CSS Beautifier plugin, but always on the lookout for more good plugins) :+1:

mattpass commented 8 years ago

Finally got chance to have a look at this. Looks like a good idea if it works well as you say. However, I'd rather it was a seamless solution that didn't involve the user inserting the JS themselves. If you want to put in a pull request that does that too I'd probably accept it. :-)