Plugin Directory

Changeset 847712


Ignore:
Timestamp:
01/29/2014 03:04:25 PM (12 years ago)
Author:
mihaivalentin
Message:

0.28

  • Images are responsive by default. They will resize nicely on lower resolution devices
  • Their size can be now chosen according to predefined presets or just typed in manually
  • Freely scalable: you can get past the responsive restriction set by your theme
  • A better UI, lots of bugfixes and usability improvements
Location:
image-pro-wordpress-image-media-management-and-resizing-done-right/trunk
Files:
1 added
13 deleted
21 edited

Legend:

Unmodified
Added
Removed
  • image-pro-wordpress-image-media-management-and-resizing-done-right/trunk/imagepro.php

    r839546 r847712  
    55Description: WordPress media & images management done right!
    66Author: Mihai Valentin
    7 Version: 0.27
     7Version: 0.28
    88Author URI: http://www.mihaivalentin.com/
    99*/
     
    2525*/
    2626
    27 /* initialize internationalization */
    28 load_plugin_textdomain('imagepro', false, basename(dirname( __FILE__ )) . '/languages');
    29 
    3027/* load external components */
    3128require_once('src/thumb/phpthumb.class.php');
     
    4340
    4441class impro {
    45    
     42
     43    /* holding the version of the plugin */
     44    private static $version;
     45
    4646    /**
    4747     * Initializes the Image Pro plugin
     
    6464            impro_thumbs::init();           
    6565        }
     66
     67        /* get version */
     68        if (!function_exists('get_plugin_data')) {
     69            require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
     70        }
     71        if (function_exists('get_plugin_data')) {
     72            $pluginData = get_plugin_data(__FILE__, false, false);
     73            self::$version = $pluginData['Version'];
     74        } else {
     75            self::$version = md5(file_get_contents(__FILE__));
     76        }
     77
     78        /* initialize internationalization */
     79        load_plugin_textdomain('imagepro', false, basename(dirname( __FILE__ )) . '/languages');
    6680    }
    6781   
     
    7993     */
    8094    public static function do_scripts() {
    81         echo impro_base::js("/src/js/helper/scroll/jquery.scrollTo.js");
    82         echo impro_base::js("/src/js/helper/augment.js");
    8395        echo impro_base::js("/src/js/impro.js");
    8496        echo impro_base::inlinejs('impro.url = "' . impro::url() . '";');   // set url to javascript
     
    90102    public static function path() {return WP_PLUGIN_DIR.'/'.dirname(plugin_basename( __FILE__ ));}
    91103    public static function url() {return WP_PLUGIN_URL.'/'.dirname(plugin_basename( __FILE__ ));}
     104
     105    /* gets the version of the plugin */
     106    public static function getVersion() { return self::$version; }
    92107}
    93108
  • image-pro-wordpress-image-media-management-and-resizing-done-right/trunk/readme.txt

    r839546 r847712  
    55Requires at least: 3.0.0
    66Tested up to: 3.8
    7 Stable tag: 0.27
     7Stable tag: 0.28
    88
    99Upload, resize, add, change images instantly. Manage your media collection with ease and use it for any post or page. A new way of managing content!
    1010
    1111== Description ==
     12
     13NEW: 0.28 version brings the following new features:
     14
     15*   images are responsive by default. They will resize nicely on lower resolution devices
     16*   their size can be now chosen according to predefined presets or just typed in manually
     17*   freely scalable: you can get past the responsive restriction set by your theme
     18*   a better UI, lots of bugfixes and usability improvements
    1219
    1320Check out the 2 minute video presentation of this plugin:
     
    3239- Apache 2.2.1.4
    3340- WordPress 3.2.1 (should work on any WordPress >= 3.0)
    34 - Firefox >= 5 or Chrome >= 20 or Internet Explorer >= 10
     41- Firefox >= 10 or Chrome >= 26 or Internet Explorer >= 10
    3542
    3643Installation steps:
     
    43504. Go to any post or page and start using it
    4451
    45 If you encounter issues with this plugin, please use the "DBG" link from the "Available Images" panel in the post editor. This will provide deubugging information, which you can send back to me for troubleshooting.
     52If you encounter issues with this plugin, please use the "DBG" link from the "Available Images" panel in the post editor. This will provide debugging information, which you can send back to me for troubleshooting.
    4653
    4754== Arbitrary section ==
     
    4956In case of experiencing problems, make sure you adhere to the installation requirements.
    5057If the problem still persists, take a look at /imagepro/logs/impro.log and see if there are any errors or warnings reported
    51 If nothing helps, please use the "DBG" link from the "Available Images" panel in the post editor. This will provide deubugging information, which you can send back to me for troubleshooting.
     58If nothing helps, please use the "DBG" link from the "Available Images" panel in the post editor. This will provide debugging information, which you can send back to me for troubleshooting.
    5259
    53 Many thanks to phpThumb, TinyMCE Advanced Image Resize Helper Plugin, KLogger
     60Many thanks to phpThumb and KLogger
    5461
    5562== Screenshots ==
     
    6370
    6471== Changelog ==
     72
     73= 0.28 =
     74* Images are responsive by default. They will resize nicely on lower resolution devices
     75* Their size can be now chosen according to predefined presets or just typed in manually
     76* Freely scalable: you can get past the responsive restriction set by your theme
     77* A better UI, lots of bugfixes and usability improvements
    6578
    6679= 0.27 =
     
    119132== Upgrade Notice ==
    120133
     134= 0.28 =
     135Recommended update. Lots of improvements in various areas.
     136
    121137= 0.14 =
    122138Please update! This plugin is now compatible with WordPress 3.3.
  • image-pro-wordpress-image-media-management-and-resizing-done-right/trunk/src/base.php

    r414062 r847712  
    77   
    88   
    9     public static function css($path) {return '<link rel="stylesheet" type="text/css" href="'.impro::url().$path.'" />';}
    10     public static function js($path) {return '<script type="text/javascript" language="javascript" src="'.impro::url().$path.'"></script>';}
     9    public static function css($path) {return '<link rel="stylesheet" type="text/css" href="'.impro::url().$path.'?version=' . impro::getVersion().'" />';}
     10    public static function js($path) {return '<script type="text/javascript" language="javascript" src="'.impro::url().$path.'?version=' . impro::getVersion().'"></script>';}
    1111    public static function inlinejs($js) {return '<script type="text/javascript" language="javascript">'.$js.'</script>';}
    1212   
  • image-pro-wordpress-image-media-management-and-resizing-done-right/trunk/src/editor.php

    r546286 r847712  
    1212            add_meta_box('impro_editor_box', __('Selected image', 'imagepro'), array('impro_editor','do_output'), get_post_type($post->ID), 'side', 'high');
    1313        }
    14        
    15         add_filter("mce_external_plugins", array('impro_editor', 'do_mce_plugin'));
    16         add_filter("tiny_mce_before_init", array('impro_editor', 'do_mce_init'));
    17        
    1814    }
    1915    public static function do_output() {
     
    2723            'enableTinyMCE' => __("You must enable the visual editor from your User Profile in order for Image Pro plugin to work", 'imagepro'),
    2824            'differentDomain' => __("This image is from a different remote domain. To be able to resize it, upload the image on this domain!", 'imagepro'),
    29             'convertToImagePro' => __("This image was inserted through the normal WordPress picture upload. Would you like Image Pro plugin to take care of it's resize and become awesome?", 'imagepro')
     25            'convertToImagePro' => __("This image was inserted through the normal WordPress picture upload. Would you like Image Pro plugin to take care of it's resize and become awesome?", 'imagepro'),
     26            'uploadNew' => __("Upload files", 'imagepro')
    3027        )));
    3128       
    3229        echo impro_base::js("/src/js/editor.js");
    3330    }
    34     public static function do_mce_plugin($plugin_array) {
    35         $plugin_array['advimagescale'] = impro::url() . '/src/js/helper/tinymce_advanced_scale_plugin/editor_plugin_src.js';
    36         return $plugin_array;
    37     }
    38     public static function do_mce_init($init) {
    39         $init['advimagescale_resize_callback'] = 'impro.editor.onMCEResize';
    40         return $init;
    41     }
     31
     32    public static function list_thumbnail_sizes() {
     33        global $_wp_additional_image_sizes;
     34        $sizes = array();
     35        foreach (get_intermediate_image_sizes() as $s) {
     36            $sizes[$s] = array(0, 0);
     37            if (in_array($s, array('thumbnail', 'medium', 'large'))) {
     38                $sizes[$s][0] = get_option($s . '_size_w');
     39                $sizes[$s][1] = get_option($s . '_size_h');
     40            } else {
     41                if (isset($_wp_additional_image_sizes) && isset($_wp_additional_image_sizes[$s]))
     42                    $sizes[$s] = array($_wp_additional_image_sizes[$s]['width'], $_wp_additional_image_sizes[$s]['height'],);
     43            }
     44        }
     45
     46        $finalSizes = array();
     47        foreach($sizes as $name => $attrs) {
     48            if (intval($attrs[0]) >= 30 && intval($attrs[1]) >= 30) {
     49                $finalSizes[$name] = array(intval($attrs[0]), intval($attrs[1]));
     50            }
     51        }
     52
     53        return $finalSizes;
     54    }
    4255}
  • image-pro-wordpress-image-media-management-and-resizing-done-right/trunk/src/folder.php

    r546286 r847712  
    2626            'popupOpenError' => __("The pop-up window containing the attachment could not be opened! Make sure you do not have a popup-blocker active!", 'imagepro'),
    2727            'attachmentLink' => __('The box below contains the full link of the attachment. You can press CTRL + C (or Command + C on Mac) to copy it to the clipboard.\n\nPress OK or Cancel to continue.', 'imagepro'),
    28             'deleteAttachmentConfirmation' => __('Are you sure you want to delete this attachment?\n\nBE AWARE THAT IF IT IS ADDED TO ANOTHER POST, REMOVING IT WILL REMOVE IT FROM THERE TOO!', 'imagepro'),
    29             'noImageSelected' => __('Please select an image in the list below first!', 'imagepro')
     28            'deleteAttachmentConfirmation' => __("Are you sure you want to delete this attachment?\n\nBE AWARE THAT IF IT IS ADDED TO ANOTHER POST, REMOVING IT WILL REMOVE IT FROM THERE TOO!\n\nHowever, if you would like to recover it, you can at any time restore it from the \"Trash\".", 'imagepro')
    3029        )));
    3130       
  • image-pro-wordpress-image-media-management-and-resizing-done-right/trunk/src/js/dragdropupload.js

    r450023 r847712  
    11impro.DragDropUpload = function() {
    22    return {
    3         onProgress : function(e, fileName) {
    4         },
    5         onComplete : function(e, fileName) {
    6         },
    7         onDropFile : function(e, fileName) {
    8         },
     3        onCompleted: function(e, files, filesSucceeded, filesFailed) {},
     4        onProgress : function(e, file, i, currentFileProgress, totalProgress) {},
     5        onDropFiles : function(e, files) {},
     6
    97        url : "",
    10         mousein_class : "vdragover",
     8        mouseOverClass : "vdragover",
    119
    1210        init : function(id, options) {
    1311            this._el = document.getElementById(id);
    1412            this.el = jQuery(this._el);
    15             this.el.bind("dragover", jQuery.proxy(this._over, this)).bind(
    16                     "dragenter", function() {
    17                         return false;
    18                     }).bind('dragleave', jQuery.proxy(this._leave, this)).bind(
    19                     "drop", jQuery.proxy(this._drop, this))
     13            this.el.bind("dragover", jQuery.proxy(this._over, this))
     14                .bind("dragenter", function() { return false; })
     15                .bind('dragleave', jQuery.proxy(this._leave, this))
     16                .bind("drop", jQuery.proxy(this._drop, this));
    2017
    2118            this.blockDocumentDrop();
     
    2421        },
    2522        blockDocumentDrop : function() {
    26             jQuery(document).bind('dragenter', function(e) {
    27                 return false;
    28             }).bind('dragleave', function(e) {
    29                 return false;
    30             }).bind('dragover', jQuery.proxy(function(e) {
    31                 var dt = e.originalEvent.dataTransfer;
    32                 if (!dt) {
    33                     return;
    34                 }
    35                 dt.dropEffect = 'none';
    36                 return false;
    37             }, this));
     23            jQuery(document)
     24                .bind('dragenter', function(e) { return false; })
     25                .bind('dragleave', function(e) { return false; })
     26                .bind('dragover', jQuery.proxy(function(e) {
     27                    var dt = e.originalEvent.dataTransfer;
     28                    if (!dt) {
     29                        return;
     30                    }
     31                    dt.dropEffect = 'none';
     32                    return false;
     33                }, this));
    3834        },
    3935        hideHighlight : function() {
    40             this.el.removeClass(this.mousein_class);
    41             return;
     36            this.el.removeClass(this.mouseOverClass);
    4237        },
    4338        _leave : function(e) {
     
    4641        _over : function(e) {
    4742            var dt = e.originalEvent.dataTransfer;
    48             if (!dt)
     43            if (!dt
     44                || (dt.types.contains && !dt.types.contains("Files"))
     45                || (dt.types.indexOf && dt.types.indexOf("Files") == -1)
     46            ) {
    4947                return;
    50             // FF
    51             if (dt.types.contains && !dt.types.contains("Files"))
    52                 return;
    53             // Chrome
    54             if (dt.types.indexOf && dt.types.indexOf("Files") == -1)
    55                 return;
     48            }
    5649
    57             if (jQuery.browser.webkit)
    58                 dt.dropEffect = 'copy';
     50            dt.dropEffect = 'copy';
    5951
    60             this.el.addClass(this.mousein_class);
     52            this.el.addClass(this.mouseOverClass);
    6153
    6254            return false;
    6355        },
    6456        _drop : function(e) {
    65             // debugger;
    66             // alert('test');
    67 
    68             // jQuery(e.originalTarget).parents('li')
    69 
    7057            var dt = e.originalEvent.dataTransfer;
    71             if (!dt && !dt.files)
     58            if (!dt && !dt.files) {
    7259                return;
     60            }
    7361
    7462            this.hideHighlight();
    7563
    76             var files = dt.files;
    77             for ( var i = 0; i < files.length; i++) {
    78                 var file = files[i];
    79                 this.onDropFile(e, file.fileName);
    80                 this.upload(file);
    81             }
    82             return false;
     64            if ('function' === typeof this.onDropFiles) {
     65                this.onDropFiles.call(this, e, dt.files);
     66            }
     67            this.uploadMultipleFiles(dt.files);
     68
     69            return false;
    8370        },
    8471
    85         upload : function(file) {
    86             var xhr = new XMLHttpRequest();
    87             xhr.upload.addEventListener("progress", jQuery.proxy(function(e) {
    88                 this.onProgress(e, file);
    89             }, this), false);
    90             xhr.onload = jQuery.proxy(function(e) {
    91                 this.onComplete(e, file);
    92             }, this);
    93             xhr.open('POST', this.url + "?name=" + (file.fileName || file.name), true);
    94             xhr.send(file);
    95         }
     72        uploadMultipleFiles: function(files) {
     73            var that = this,
     74                i = 0,
     75                filesFailed = [],
     76                filesSucceeded = [];
     77
     78            /**
     79             * uploads a single file and triggers load, error and progress events
     80             * @param file the File object to upload
     81             * @param load triggered on success
     82             * @param error triggered on error
     83             * @param progress triggered on progress
     84             */
     85            var uploadSingleFile = function(file, load, error, progress) {
     86                var xhr = new XMLHttpRequest();
     87                /* register progress event */
     88                xhr.addEventListener("progress", jQuery.proxy(function(e) {
     89                    if ('function' === typeof progress) {
     90                        progress.call(this, e, file);
     91                    }
     92                }, that), false);
     93                /* register successful event */
     94                xhr.addEventListener("load", jQuery.proxy(function(e) {
     95                    /* increase the number of files processed with 1 */
     96                    i++;
     97                    if ('function' === typeof load) {
     98                        load.call(this, e, file);
     99                    }
     100                }, that), false);
     101                /* register error event */
     102                xhr.addEventListener("error", jQuery.proxy(function(e) {
     103                    /* increase the number of files processed with 1 */
     104                    i++;
     105                    if ('function' === typeof error) {
     106                        error.call(this, e, file);
     107                    }
     108                }, that), false);
     109                /* perform upload */
     110                xhr.open('POST', that.url + "?name=" + file.name, true);
     111                xhr.send(file);
     112            };
     113
     114            /**
     115             * call the onCompleted function to notify of completion
     116             * this method will provide the event of the last file
     117             * and all the files, the files that succeeded and
     118             * the files that failed
     119             * @param e
     120             * @param file
     121             */
     122            var finished = function(e, file) {
     123                if ('function' === typeof that.onCompleted) {
     124                    that.onCompleted.call(that, e, files, filesSucceeded, filesFailed);
     125                }
     126            };
     127
     128            /**
     129             * called when a file has been successfully uploaded
     130             * @param e
     131             * @param file
     132             */
     133            var individualLoad = function(e, file) {
     134                /* the server returned data, but is it correct? was the file uploaded successfully? */
     135                var response = e.target.response;
     136                try {
     137                    response = JSON.parse(e.target.response);
     138                } catch(e) {}
     139
     140                /* if upload was successful */
     141                if ('object' === typeof response && response['ok'] === true) {
     142                    filesSucceeded.push(file);
     143                    if (i === files.length) {
     144                        finished(e, file);
     145                    } else {
     146                        uploadSingleFile(files[i], individualLoad, individualError, individualProgress);
     147                    }
     148                } else {
     149                    individualError(e, file, e.target.status, response);
     150                }
     151            };
     152
     153            /**
     154             * called when a file has failed uploading (server error, not upload code error)
     155             * @param e
     156             * @param file
     157             * @param httpStatus
     158             * @param httpResponse
     159             */
     160            var individualError = function(e, file, httpStatus, httpResponse) {
     161                filesFailed.push(file);
     162                filesFailed[filesFailed.length - 1].httpStatus = httpStatus;
     163                filesFailed[filesFailed.length - 1].httpResponse = httpResponse;
     164                if (i === files.length) {
     165                    finished(e, file);
     166                } else {
     167                    uploadSingleFile(files[i], individualLoad, individualError, individualProgress);
     168                }
     169            };
     170
     171            /**
     172             * called when a progress event occurs for a file
     173             * @param e
     174             * @param file
     175             */
     176            var individualProgress = function(e, file) {
     177                if ('function' === typeof that.onProgress) {
     178                    var currentFileProgress = Math.round((e.loaded / e.total) * 100);
     179                    var totalProgress = Math.round((i / files.length) * 100) + Math.round(currentFileProgress * (1 / files.length));
     180                    that.onProgress(e, file, i, currentFileProgress, totalProgress);
     181                }
     182            };
     183
     184            /* start uploading the first file */
     185            uploadSingleFile(files[i], individualLoad, individualError, individualProgress);
     186        }
    96187    };
    97188};
  • image-pro-wordpress-image-media-management-and-resizing-done-right/trunk/src/js/editor.js

    r839546 r847712  
    1 /* Folder namespace */
    2 impro.editor = {};
    3 
    4 impro.editor.minie10 = navigator.userAgent.indexOf('MSIE 10') > 0 || (navigator.userAgent.indexOf('Trident') > 0 && /rv:[0-9][0-9]/.test(navigator.userAgent));
    5 
    6 /* init the editor support */
    7 impro.editor.init = function() {
    8 
    9     /* set a reference to the image editor */
    10     impro.editor.$editor = jQuery('#impro_editor');
    11    
    12     /* start with the editor closed */
    13     jQuery('#impro_editor_box').addClass('closed').find('.handlediv').hide();
    14        
    15     /* init events */
    16     impro.editor.initEvents();
    17    
    18     /* if the visual editor is enabled in the user preferences */
    19     if (jQuery('#edButtonPreview').size() > 0 || jQuery('#content-tmce').size() > 0) {
    20         /* hook up the switchEditors to find out when the editor is changed */
    21         /* TODO: This does not work for WordPress 3.2 */
    22         try {
    23             switchEditors.old_go = switchEditors.go;
    24             switchEditors.go = function(id, mode) {
    25                 switchEditors.old_go(id, mode);
    26                 impro.editor.onSwitchEditor(id, mode);
    27             };
    28         } catch(ex) {}
    29        
    30         /* tinyMCE will start initialization soon */
    31         var tinymce_timer = setInterval(function() {
    32             if (window.tinymce && window.tinymce.getInstanceById('content')) {
    33                 clearInterval(tinymce_timer);
    34                
    35                 /* prevent the user opening the image settings panel */
    36                 jQuery('#impro_editor_box').find('.hndle').unbind('click');
    37                
    38                 /* initialize the editor */
    39                 impro.editor.onEditorInit(window.tinymce.getInstanceById('content'));
    40             }
    41         }, 300);
    42     } else {
    43         impro.err(imageproEditorL10N.enableTinyMce);
    44     }
    45 };
    46 
    47 /* get TinyMCE */
    48 impro.editor.getTinyMCE = function() {
    49     return tinymce.getInstanceById('content');
    50 };
    51 
    52 /* fires when tinymce is initialized */
    53 impro.editor.onEditorInit = function(editor) {
    54     /* now waiting for the iframe inside to render the post and have the body */
    55     var timer = setInterval(function() {
    56         var body = jQuery(window.tinymce.getInstanceById('content').contentAreaContainer).find('iframe').contents().find('body');
    57         if (body.size() > 0) {
    58             clearInterval(timer);
    59            
    60             /* link the click event to tiny mce */
    61             impro.editor.setTinyMCEInteractions(body, window.tinymce.getInstanceById('content'));
    62            
    63             /* if we're on Chrome or Safari, try to simulate the resize handles */
    64             if (window.tinymce.isWebKit) {
    65                 impro.editor.fakeImageResize();
    66             }
    67         }
    68     }, 300);
    69 };
    70 
    71 /* set the onclick event on the editor */
    72 impro.editor.setTinyMCEInteractions = function(body, editor) { 
    73    
    74     /* register drop event to catch drops */
    75     setInterval(function() {
    76         /* because the ondrop event is not at all reliable
    77          * not to say about it's cross browser support,
    78          * I used a interval checking (polling) */
    79         var body = editor.dom.doc.body;
    80         var thumbs = jQuery(body).find('img[src*="\\/thumb\\/phpThumb\\.php"]');
    81        
    82         if (thumbs.size() > 0) {
    83             thumbs.each(function(i) {
    84                 /* get source image */
    85                 var thumb_w = jQuery(this).width();
    86                 var thumb_h = jQuery(this).height();
    87                
    88                 var src = jQuery(this).attr('src');
    89                 var pic_src;
    90                
    91                 /* get picture source */
    92                 var match = /\/thumb\/phpThumb\.php\?.*?&src=([^&]*)&?/i.exec(src);
    93                 if (match != null) {
    94                     pic_src = match[1];
    95                 }
    96                
    97                 /* apply picture source and dimensions */
    98                 if (pic_src) {
    99                     jQuery(this).attr('src', pic_src).attr('data-mce-src', pic_src).attr('_mce_src', pic_src);
    100                     jQuery(this).attr('width', thumb_w).attr('data-mce-width', thumb_w).attr('_mce_width', thumb_w).width(thumb_w);
    101                     jQuery(this).attr('height', thumb_h).attr('data-mce-height', thumb_h).attr('_mce_height', thumb_h).height(thumb_h);
    102 
    103                     /* open the editor, for the last one
    104                     in theory, it should be JUST one, but if the user is fast enough
    105                     to drag more, we should only open the editor for one, in order
    106                     not to slow down the UI
    107                     we open the editor by simulating a mouseup on the image */
    108                     if (thumbs.length - 1 === i) {
    109                         var outerThis = this;
    110                         setTimeout(function() {
    111                             jQuery(outerThis).trigger(impro.editor.minie10 ? 'mousedown' : 'click');
    112                         }, 100);
     1(function($) {
     2
     3    /* the minimum width and height to which images can be resized */
     4    var MIN_W = 30;
     5    var MIN_H = 30;
     6
     7    /* references to jQuery elements */
     8    var $editor, $imgSize, $imgW, $imgH, $imgMaxW;
     9    var $clickedImage;
     10
     11    /* the maximum width imposed by the current theme, if applicable */
     12    var themeMaxWidth;
     13
     14    var init = function() {
     15        /* set a reference to the image editor and other elements */
     16        $editor = $('#impro_editor');
     17        $imgSize = $('#impro-editor-size');
     18        $imgW = $('#impro-editor-w');
     19        $imgH = $('#impro-editor-h');
     20        $imgMaxW = $('#impro-editor-maxwidth');
     21
     22        /* start with the editor closed */
     23        $('#impro_editor_box').addClass('closed').find('.handlediv').hide();
     24
     25        /* init events */
     26        initEvents();
     27
     28        /* if the visual editor is enabled in the user preferences */
     29        if ($('#edButtonPreview').size() > 0 || $('#content-tmce').size() > 0) {
     30            /* hook up the switchEditors to find out when the editor is changed */
     31            /* TODO: This does not work for WordPress 3.2 */
     32            try {
     33                switchEditors.old_go = switchEditors.go;
     34                switchEditors.go = function(id, mode) {
     35                    switchEditors.old_go(id, mode);
     36                    onSwitchEditor(id, mode);
     37                };
     38            } catch(ex) {}
     39
     40            /* tinyMCE will start initialization soon */
     41            var tinymceInitTimer = setInterval(function() {
     42                if (window.tinymce && window.tinymce.getInstanceById('content')) {
     43                    clearInterval(tinymceInitTimer);
     44
     45                    /* prevent the user opening the image settings panel */
     46                    $('#impro_editor_box').find('.hndle').unbind('click');
     47
     48                    /* initialize the editor */
     49                    onEditorInit(window.tinymce.getInstanceById('content'));
     50                }
     51            }, 300);
     52        } else {
     53            impro.err(imageproEditorL10N.enableTinyMce);
     54        }
     55    };
     56
     57    var getTinyMCE = function() {
     58        return tinymce.getInstanceById('content');
     59    };
     60
     61    var onEditorInit = function(editor) {
     62        /* now waiting for the iframe inside to render the post and have the body */
     63        var timer = setInterval(function() {
     64            var $body = $(getTinyMCE().contentAreaContainer).find('iframe').contents().find('body');
     65            if ($body.length) {
     66                clearInterval(timer);
     67
     68                /* link the click event to tiny mce */
     69                setTinyMCEInteractions($body, getTinyMCE());
     70
     71                /* if we are re on Chrome or Safari, try to simulate the resize handles */
     72                if (window.tinymce.isWebKit) {
     73                    impro.fakeImageResize();
     74                }
     75            }
     76        }, 300);
     77    };
     78
     79    var setTinyMCEInteractions = function(body, editor) {
     80
     81        /* get max width for images, if set by the WordPress theme */
     82        themeMaxWidth = getThemeMaxWidth(body);
     83        if ('number' !== typeof themeMaxWidth) {
     84            /* if the theme is not responsive, the responsiveness checkbox should be hidden */
     85            $('#impro-editor-maxwidth-container').hide();
     86        } else {
     87            $('#impro-editor-maxwidth-info').html($('#impro-editor-maxwidth-info').html().replace('%maxwidth%', themeMaxWidth));
     88        }
     89
     90        /* register drop event to catch drops */
     91        setInterval(function() {
     92            /* because the ondrop event is not at all reliable
     93             * not to say about its cross browser support,
     94             * I used a interval checking (polling) */
     95            var body = editor.dom.doc.body;
     96            var thumbs = $(body).find('img[src*="\\/thumb\\/phpThumb\\.php"]');
     97
     98            if (thumbs.size() > 0) {
     99                thumbs.each(function(i) {
     100                    /* get source image */
     101                    var thumb_w = $(this).width();
     102                    var thumb_h = $(this).height();
     103
     104                    var src = $(this).attr('src');
     105                    var pic_src;
     106
     107                    /* get picture source */
     108                    var match = /\/thumb\/phpThumb\.php\?.*?&src=([^&]*)&?/i.exec(src);
     109                    if (match != null) {
     110                        pic_src = match[1];
    113111                    }
    114                 }
    115             });
    116         }
    117     }, 800);
    118        
    119     /* set the click event on body, then limit by images */
    120     body.bind(impro.editor.minie10 ? 'mousedown' : 'click', function(ev) {
    121         var target = jQuery(ev.target);
    122         /* only process image clicks */
    123         if (target.is('img')) {
    124             impro.editor.showEditor(target);
    125         } else {
    126             jQuery('#impro_editor_box').addClass('closed');
    127         }
    128         return true;
    129     });
    130 };
    131 
    132 /* this is triggered when the picture is resized */
    133 impro.editor.onMCEResize = function(ed, img) {
    134    
    135 };
    136 
    137 /* show the editor and populate the fields */
    138 impro.editor.showEditor = function(target) {
    139    
    140     var current_src = jQuery(target).attr('src');
    141     var current_domain = document.location.protocol + '//' + document.location.host;
    142    
    143     /* if the image begins with http://my.domain/, it was uploaded with classic wordpress upload. ask for migrating to image pro */
    144     if (current_src.indexOf(current_domain + '/') == 0) {
    145         if (confirm(imageproEditorL10N.convertToImagePro)) {
    146             var new_src = current_src.replace(current_domain, '');
    147             jQuery(target).attr('src', new_src).attr('data-mce-src', new_src).attr('_mce_src', new_src);
    148             impro.editor.showEditor(target);
    149         }
    150         return;
    151     }
    152    
    153     /* if does not begin with /, it means it's from an external domain */
    154     if (current_src[0] != "/") {
    155         impro.err(imageproEditorL10N.differentDomain);
    156         return;
    157     }
    158    
    159     /* open the editor panel */
    160     jQuery('#impro_editor_box').removeClass('closed');
    161    
    162     /* remember the clicked image (currently in editor) */
    163     impro.editor.$clickedImage = target;
    164    
    165     /* parse clicked image's path */
    166     var path = impro.editor.parseUrl(target.attr('src'));
    167    
    168     /* remember the old source */
    169     impro.editor.$clickedImage.get(0).old_src = target.attr('src');
    170    
    171     /* show thumb image */
    172     path['w'] = 50;
    173     path['h'] = 50;
    174     path['zc'] = 0;
    175     var url = impro.editor.createThumbUrl(path);
    176     impro.editor.$editor.find('.thumb').attr('src', url);
    177    
    178     /* set alt and title */
    179     jQuery('.impro_alt').val(target.attr('alt'));
    180     jQuery('.impro_title').val(target.attr('title'));
    181    
    182     /* set align mode */
    183     var align = "alignnone";
    184     if (target.hasClass('alignleft')) {
    185         align = "alignleft";
    186     } else if (target.hasClass('aligncenter')) {
    187         align = "aligncenter";
    188     } else if (target.hasClass('alignright')) {
    189         align = "alignright";
    190     }
    191     jQuery('.impro_align').val(align);
    192    
    193     /* set link */
    194     if (impro.editor.$clickedImage.parent().is('a[href]')) {
    195         jQuery('.impro_link').attr('checked', 'checked');
    196     } else {
    197         jQuery('.impro_link').removeAttr('checked');
    198     }
    199 };
    200 
    201 /* change a given img element to what is contained in props */
    202 impro.editor.resize = function(el, props) {
    203     if (!jQuery(el).is('img')) {    /* el must be an img tag */
    204         return null;
    205     }
    206    
    207     if (!(el instanceof jQuery)) {  /* make the element jQuery if not already */
    208         el = jQuery(el);
    209     }
    210    
    211     var el_dom = el.get(0); /* also keep a DOM reference */
    212    
    213     var current_props = impro.editor.parseUrl(el.attr('src'));  /* get the current properties */
    214    
    215     /* if we could not extract properties from the source, get them from the image tag properties */
    216     if (!current_props['w']) {
    217         current_props['w'] = el_dom.width || el.width();
    218     }
    219     if (!current_props['h']) {
    220         current_props['h'] = el_dom.height || el.height();
    221     }
    222    
    223     /* copy properties */
    224     if (props['src']) {
    225         current_props['src'] = props['src'];
    226     }
    227     if (props['w']) {
    228         current_props['w'] = props['w'];
    229     }
    230     if (props['h']) {
    231         current_props['h'] = props['h'];
    232     }
    233     if (props['zc']) {
    234         current_props['zc'] = props['zc'];
    235     }
    236    
    237     var url = impro.editor.createThumbUrl(current_props);
    238    
    239     /* set preview */
    240     el.attr('src', props['src']);
    241     el.attr('width', props['w']);
    242     el.attr('height', props['h']);
    243    
    244     /* save */
    245     el.attr('_mce_src', props['src']);
    246     el.attr('_mce_width', props['w']);
    247     el.attr('_mce_height', props['h']);
    248     el.attr('data-mce-src', props['src']);
    249     el.attr('data-mce-width', props['w']);
    250     el.attr('data-mce-height', props['h']);
    251 };
    252 
    253 impro.editor.initEvents = function() {
    254     var changeProps = function() {
    255         /* preview */
    256         impro.editor.$clickedImage.attr('alt', jQuery('.impro_alt').val());
    257         impro.editor.$clickedImage.attr('title', jQuery('.impro_title').val());
    258         impro.editor.$clickedImage.removeClass('alignnone').removeClass('alignleft').removeClass('aligncenter').removeClass('alignright').addClass(jQuery('.impro_align').val());
    259        
    260         /* save */
    261         impro.editor.$clickedImage.attr('_mce_alt', jQuery('.impro_alt').val());
    262         impro.editor.$clickedImage.attr('_mce_title', jQuery('.impro_title').val());
    263         impro.editor.$clickedImage.attr('_mce_class', impro.editor.$clickedImage.attr('class'));
    264     };
    265    
    266     jQuery('.impro_align, .impro_alt, .impro_title').change(changeProps).keyup(changeProps);
    267    
    268     jQuery('.impro_link').click(function() {
    269         if (jQuery(this).is(':checked')) {
    270             tinyMCE.activeEditor.execCommand('mceInsertLink', false, { href: impro.editor.$clickedImage.attr('src'), target: '_blank' });
    271         } else {
    272             tinyMCE.activeEditor.execCommand('mceInsertLink', false, '');
    273         }       
    274     });
    275    
    276     jQuery('.impro_choose').click(function() {
    277         jQuery('#impro_folder_box #vimg-list').addClass('impro_choosebg');
    278         jQuery.scrollTo('#impro_folder_box',800);
    279         impro.editor.$chosen = impro.editor.$clickedImage;
    280     });
    281 };
    282 
    283 impro.editor.createThumbUrl = function(params) {
    284     var path = impro.url + '/src/thumb/phpThumb.php?';
    285     var tmp = [];
    286     for (var p in params) {
    287         if (['w','h','src','zc','q'].indexOf(p) === -1) {
    288             continue;
    289         }
    290         if (params.hasOwnProperty(p)) {
    291             tmp.push(p+'='+params[p]);
    292         }
    293     }
    294     return path + tmp.join('&');
    295 }
    296 
    297 /* fires when the editor is changed */
    298 impro.editor.onSwitchEditor = function(id, mode) {
    299    
    300 };
    301 
    302 impro.editor.parseUrl = function(url) {
    303     var path = {};
    304    
    305     /* if begins with http(s?):// protocol */
    306     var is_http = /^https?:\/\/$/i.test(url);
    307     /* if contains phpThumb.php */
    308     var is_thumb = url.indexOf('/src/thumb/phpThumb.php') !== -1;
    309    
    310     if (is_thumb) {
    311         path['thumb'] = true;
    312        
    313         url.split('?')[1].split('&').forEach(function(v){
    314             var tmp = v.split('=');
    315            
    316             /* we have the width, height, quality and zoom-crop */
    317             if (tmp[0] === 'w' || tmp[0] === 'h' || tmp[0] === 'q' || tmp[0] === 'zc') {
    318                 tmp[1] = parseInt(tmp[1], 10);
    319                 /* not a numeric value, don't consider */
    320                 if (isNaN(tmp[1])) {
    321                     return;
    322                 }
    323             }
    324            
    325             path[tmp[0]] = tmp[1];
    326         });
    327        
    328         path['url'] = url;
    329     } else {
    330         path['thumb'] = false;
    331         path['url'] = url;
    332         path['src'] = path['url'];
    333     }
    334    
    335     return path;
    336 };
    337 
    338 impro.editor.fakeImageResize = function () {
    339     var editor = tinyMCE.editors[0];
    340     var dom = editor.dom;
    341     var selection = editor.selection;
    342     var VK = tinyMCE.VK;
    343     var settings = editor.settings;
    344    
    345     var selectedElmX, selectedElmY, selectedElm, selectedElmGhost, selectedHandle, startX, startY, startW, startH, ratio,
    346         resizeHandles, width, height, rootDocument = document, editableDoc = editor.getDoc();
    347 
    348     if (settings.webkit_fake_resize === true) {
    349         alert('It seems that you are on a WebKit Browser (Chrome / Safari) '+
    350               'and your configuration has webkit_fake_resize = true.' +
    351               "\n\n" +
    352               "Please turn it off for the Image Pro Plugin to function correctly under WebKit browsers.\n\n" +
    353               "Contact us for more information!");
    354         return;
    355     }
    356    
    357     /*if (!settings.object_resizing || settings.webkit_fake_resize === false) {
    358         return;
    359     }*/
    360 
    361     // Try disabling object resizing if WebKit implements resizing in the future
    362     try {
    363         editor.getDoc().execCommand("enableObjectResizing", false, false);
    364     } catch (ex) {
    365         // Ignore
    366     }
    367 
    368     // Details about each resize handle how to scale etc
    369     resizeHandles = {
    370         // Name: x multiplier, y multiplier, delta size x, delta size y
    371         n: [.5, 0, 0, -1],
    372         e: [1, .5, 1, 0],
    373         s: [.5, 1, 0, 1],
    374         w: [0, .5, -1, 0],
    375         nw: [0, 0, -1, -1],
    376         ne: [1, 0, 1, -1],
    377         se: [1, 1, 1, 1],
    378         sw : [0, 1, -1, 1]
    379     };
    380 
    381     function resizeElement(e) {
    382         var deltaX, deltaY;
    383 
    384         // Calc new width/height
    385         deltaX = e.screenX - startX;
    386         deltaY = e.screenY - startY;
    387 
    388         // Calc new size
    389         width = deltaX * selectedHandle[2] + startW;
    390         height = deltaY * selectedHandle[3] + startH;
    391 
    392         // Never scale down lower than 5 pixels
    393         width = width < 5 ? 5 : width;
    394         height = height < 5 ? 5 : height;
    395 
    396         // Constrain proportions when modifier key is pressed or if the nw, ne, sw, se corners are moved on an image
    397         if (VK.modifierPressed(e) || (selectedElm.nodeName == "IMG" && selectedHandle[2] * selectedHandle[3] !== 0)) {
    398             width = Math.round(height / ratio);
    399             height = Math.round(width * ratio);
    400         }
    401 
    402         // Update ghost size
    403         dom.setStyles(selectedElmGhost, {
    404             width: width,
    405             height: height
    406         });
    407 
    408         // Update ghost X position if needed
    409         if (selectedHandle[2] < 0 && selectedElmGhost.clientWidth <= width) {
    410             dom.setStyle(selectedElmGhost, 'left', selectedElmX + (startW - width));
    411         }
    412 
    413         // Update ghost Y position if needed
    414         if (selectedHandle[3] < 0 && selectedElmGhost.clientHeight <= height) {
    415             dom.setStyle(selectedElmGhost, 'top', selectedElmY + (startH - height));
    416         }
    417     }
    418 
    419     function endResize() {
    420         function setSizeProp(name, value) {
    421             if (value) {
    422                 // Resize by using style or attribute
    423                 /*if (selectedElm.style[name] || !editor.schema.isValid(selectedElm.nodeName.toLowerCase(), name)) {*/
    424                 if (selectedElm.style[name] || !editor.schema.isValidChild(selectedElm.nodeName.toLowerCase(), name)) {
    425                     dom.setStyle(selectedElm, name, value);
    426                 } else {
    427                     dom.setAttrib(selectedElm, name, value);
    428                 }
    429             }
    430         }
    431 
    432         // Set width/height properties
    433         setSizeProp('width', width);
    434         setSizeProp('height', height);
    435         dom.setAttrib(selectedElm, 'data-mce-width', width);
    436         dom.setAttrib(selectedElm, 'data-mce-height', height);
    437         dom.setAttrib(selectedElm, 'width', width);
    438         dom.setAttrib(selectedElm, 'height', height);
    439 
    440         dom.unbind(editableDoc, 'mousemove', resizeElement);
    441         dom.unbind(editableDoc, 'mouseup', endResize);
    442 
    443         if (rootDocument != editableDoc) {
    444             dom.unbind(rootDocument, 'mousemove', resizeElement);
    445             dom.unbind(rootDocument, 'mouseup', endResize);
    446         }
    447 
    448         // Remove ghost and update resize handle positions
    449         dom.remove(selectedElmGhost);
    450         showResizeRect(selectedElm);
    451     }
    452 
    453     function showResizeRect(targetElm) {
    454         var position, targetWidth, targetHeight;
    455 
    456         hideResizeRect();
    457 
    458         // Get position and size of target
    459         position = dom.getPos(targetElm);
    460         selectedElmX = position.x;
    461         selectedElmY = position.y;
    462         targetWidth = targetElm.offsetWidth;
    463         targetHeight = targetElm.offsetHeight;
    464 
    465         // Reset width/height if user selects a new image/table
    466         if (selectedElm != targetElm) {
    467             selectedElm = targetElm;
    468             width = height = 0;
    469         }
    470 
    471         tinymce.each(resizeHandles, function(handle, name) {
    472             var handleElm;
    473 
    474             // Get existing or render resize handle
    475             handleElm = dom.get('mceResizeHandle' + name);
    476             if (!handleElm) {
    477                 handleElm = dom.add(editableDoc.documentElement, 'div', {
    478                     id: 'mceResizeHandle' + name,
    479                     'class': 'mceResizeHandle',
    480                     style: 'cursor:' + name + '-resize; margin:0; padding:0'
    481                 });
    482 
    483                 dom.bind(handleElm, 'mousedown', function(e) {
    484                     e.preventDefault();
    485 
    486                     endResize();
    487 
    488                     startX = e.screenX;
    489                     startY = e.screenY;
    490                     startW = selectedElm.clientWidth;
    491                     startH = selectedElm.clientHeight;
    492                     ratio = startH / startW;
    493                     selectedHandle = handle;
    494 
    495                     selectedElmGhost = selectedElm.cloneNode(true);
    496                     dom.addClass(selectedElmGhost, 'mceClonedResizable');
    497                     dom.setStyles(selectedElmGhost, {
    498                         left: selectedElmX,
    499                         top: selectedElmY,
    500                         margin: 0
    501                     });
    502 
    503                     editableDoc.documentElement.appendChild(selectedElmGhost);
    504 
    505                     dom.bind(editableDoc, 'mousemove', resizeElement);
    506                     dom.bind(editableDoc, 'mouseup', endResize);
    507 
    508                     if (rootDocument != editableDoc) {
    509                         dom.bind(rootDocument, 'mousemove', resizeElement);
    510                         dom.bind(rootDocument, 'mouseup', endResize);
    511                     }
    512                 });
    513             } else {
    514                 dom.show(handleElm);
    515             }
    516 
    517             // Position element
    518             dom.setStyles(handleElm, {
    519                 left: (targetWidth * handle[0] + selectedElmX) - (handleElm.offsetWidth / 2),
    520                 top: (targetHeight * handle[1] + selectedElmY) - (handleElm.offsetHeight / 2)
    521             });
    522         });
    523 
    524         // Only add resize rectangle on WebKit and only on images
    525         if (!tinymce.isOpera && selectedElm.nodeName == "IMG") {
    526             selectedElm.setAttribute('data-mce-selected', '1');
    527         }
    528     }
    529 
    530     function hideResizeRect() {
    531         if (selectedElm) {
    532             selectedElm.removeAttribute('data-mce-selected');
    533         }
    534 
    535         for (var name in resizeHandles) {
    536             dom.hide('mceResizeHandle' + name);
    537         }
    538     }
    539 
    540     // Add CSS for resize handles, cloned element and selected
    541     var css = '.mceResizeHandle {' +
    542         'position: absolute;' +
    543         'border: 1px solid black;' +
    544         'background: #FFF;' +
    545         'width: 5px;' +
    546         'height: 5px;' +
    547         'z-index: 10000' +
    548     '}' +
    549     '.mceResizeHandle:hover {' +
    550         'background: #000' +
    551     '}' +
    552     'img[data-mce-selected] {' +
    553         'outline: 1px solid black' +
    554     '}' +
    555     'img.mceClonedResizable, table.mceClonedResizable {' +
    556         'position: absolute;' +
    557         'outline: 1px dashed black;' +
    558         'opacity: .5;' +
    559         'z-index: 10000' +
    560     '}';
    561    
    562     var el = editor.getDoc().createElement('style');
    563     el.innerHTML = css;
    564     editor.getDoc().getElementsByTagName('head')[0].appendChild(el);
    565 
    566     function updateResizeRect() {
    567         var controlElm = dom.getParent(selection.getNode(), 'table,img');
    568 
    569         // Remove data-mce-selected from all elements since they might have been copied using Ctrl+c/v
    570         tinymce.each(dom.select('img[data-mce-selected]'), function(img) {
    571             img.removeAttribute('data-mce-selected');
    572         });
    573 
    574         if (controlElm) {
    575             showResizeRect(controlElm);
    576         } else {
    577             hideResizeRect();
    578         }
    579     }
    580 
    581     // Show/hide resize rect when image is selected
    582     editor.onNodeChange.add(updateResizeRect);
    583 
    584     // Fixes WebKit quirk where it returns IMG on getNode if caret is after last image in container
    585     dom.bind(editableDoc, 'selectionchange', updateResizeRect);
    586 
    587     // Remove the internal attribute when serializing the DOM
    588     editor.serializer.addAttributeFilter('data-mce-selected', function(nodes, name) {
    589         var i = nodes.length;
    590 
    591         while (i--) {
    592             nodes[i].attr(name, null);
    593         }
    594     });
    595 };
     112
     113                    /* apply picture source and dimensions */
     114                    if (pic_src) {
     115                        $(this).attr('src', pic_src).attr('data-mce-src', pic_src).attr('_mce_src', pic_src);
     116                        $(this).attr('width', thumb_w).attr('data-mce-width', thumb_w).attr('_mce_width', thumb_w);
     117                        $(this).attr('height', thumb_h).attr('data-mce-height', thumb_h).attr('_mce_height', thumb_h);
     118
     119                        /* open the editor, for the last one
     120                         in theory, it should be JUST one, but if the user is fast enough
     121                         to drag more, we should only open the editor for one, in order
     122                         not to slow down the UI
     123                         we open the editor by simulating a mouseup on the image */
     124                        if (thumbs.length - 1 === i) {
     125                            var outerThis = this;
     126                            setTimeout(function() {
     127                                $(outerThis).trigger(impro.minIE10 ? 'mousedown' : 'click');
     128                            }, 100);
     129                        }
     130                    }
     131                });
     132            }
     133        }, 300);
     134
     135        /* set the click event on body, then limit by images */
     136        body.bind(impro.minIE10 ? 'mousedown' : 'click', function(ev) {
     137            var target = $(ev.target);
     138            /* only process image clicks */
     139            if (target.is('img')) {
     140                showEditor(target);
     141            } else {
     142                closeEditor();
     143            }
     144            return true;
     145        });
     146    };
     147
     148    var openEditor = function() {
     149        $('#impro_editor_box').removeClass('closed');
     150    };
     151
     152    var closeEditor = function() {
     153        $('#impro_editor_box').addClass('closed');
     154    };
     155
     156    /**
     157     * populates the editor in the right with the properties of the currently selected image
     158     * @param target the clicked image, as a jQuery element
     159     */
     160    var showEditor = function(target) {
     161
     162        var currentSrc = $(target).attr('src');
     163        var currentDomain = document.location.protocol + '//' + document.location.host;
     164
     165        /* if the image begins with http://my.domain/, it was uploaded with classic wordpress upload,
     166        or it was just moved around the document so it got a http:// at the beginning */
     167        if (0 === currentSrc.indexOf(currentDomain + '/')) {
     168            currentSrc = currentSrc.replace(currentDomain, '');
     169            target.attr('src', currentSrc).attr('data-mce-src', currentSrc).attr('_mce_src', currentSrc);
     170        }
     171
     172        /* if does not begin with /, it means it is from an external domain */
     173        if (currentSrc[0] != "/") {
     174            impro.err(imageproEditorL10N.differentDomain);
     175            return;
     176        }
     177
     178        /* open the editor panel */
     179        openEditor();
     180
     181        /* remember the clicked image (currently in editor) */
     182        $clickedImage = target;
     183
     184        /* remove the inline styles */
     185        $clickedImage.css('width', '');
     186        $clickedImage.css('height', '');
     187        $clickedImage.removeAttr('data-mce-style');
     188
     189        /* remember the old source */
     190        $clickedImage.data('oldSrc', target.attr('src'));
     191
     192        /* show thumb image in the panel to the right */
     193        $('#impro-preview').css({
     194            'background-image': 'url("' + target.attr('src') + '")'
     195        });
     196
     197        /* set alt and title */
     198        $('.impro_alt').val(target.attr('alt'));
     199        $('.impro_title').val(target.attr('title'));
     200
     201        /* set align mode */
     202        var align = "alignnone";
     203        if (target.hasClass('alignleft')) {
     204            align = "alignleft";
     205        } else if (target.hasClass('aligncenter')) {
     206            align = "aligncenter";
     207        } else if (target.hasClass('alignright')) {
     208            align = "alignright";
     209        }
     210        $('.impro_align').val(align);
     211
     212        /* set link */
     213        if ($clickedImage.parent().is('a[href]')) {
     214            $('.impro_link').attr('checked', 'checked');
     215        } else {
     216            $('.impro_link').removeAttr('checked');
     217        }
     218
     219        /* decide if responsivness checkbox should be displayed */
     220        var hasInlineMaxWidthNone = /max-width\s*:\s*none/.test(target[0].style.cssText);
     221
     222        /* if this image has a responsiveness setting attached */
     223        if (hasInlineMaxWidthNone || 'number' === typeof themeMaxWidth) {
     224            $('#impro-editor-maxwidth').show();
     225            if (hasInlineMaxWidthNone) {
     226                $('#impro-editor-maxwidth').attr('checked', 'checked');
     227            } else {
     228                $('#impro-editor-maxwidth').removeAttr('checked');
     229            }
     230        } else {
     231            $('#impro-editor-maxwidth').hide();
     232        }
     233
     234        /* set the size preset */
     235        selectCorrectPreset($clickedImage.attr('width'), $clickedImage.attr('height'));
     236
     237        /* set the height and width */
     238        $imgW.val($clickedImage.attr('width'));
     239        $imgH.val($clickedImage.attr('height'));
     240    };
     241
     242    /* updates the image preset select box with the correct setting depending on the image size */
     243    var selectCorrectPreset = function(w, h) {
     244        /* set the size preset */
     245        var fullWidth = $clickedImage[0].naturalWidth;
     246        var fullHeight = $clickedImage[0].naturalHeight;
     247
     248        /* the value to select at the end */
     249        var valueToSelect;
     250
     251        /* if the image is the full size */
     252        if (fullWidth == w && fullHeight == h) {
     253            valueToSelect = '__full';
     254        }
     255
     256        /* if not yet chosen */
     257        if (!valueToSelect) {
     258            /* search among the presets */
     259            $imgSize.find('option[data-preset-width]').each(function() {
     260                var presetWidth = parseInt($(this).attr('data-preset-width'), 10);
     261                if (presetWidth == w) {
     262                    valueToSelect = $(this).attr('value');
     263                    return false;
     264                }
     265            });
     266        }
     267
     268        /* if not yet chosen */
     269        if (!valueToSelect) {
     270            if ('number' === typeof themeMaxWidth && w == themeMaxWidth && !$imgMaxW.is(':checked')) {
     271                valueToSelect = '__full';
     272            }
     273        }
     274
     275        /* if not yet chosen */
     276        if (!valueToSelect) {
     277            valueToSelect = '__custom';
     278        }
     279
     280        /* apply the selected value */
     281        $imgSize.val(valueToSelect);
     282    }
     283
     284    /**
     285     * gets the current WordPress theme max-width, as set by its CSS stylesheets
     286     * @param $tinyMCEBody the reference to the jQuery body element tag inside the TinyMCE iframe
     287     * @returns {number|undefined} the maximum width recommended by the theme, or undefined if not defined
     288     */
     289    var getThemeMaxWidth = function($tinyMCEBody) {
     290        var tempImgMaxWidthTest = $('<img />').appendTo($tinyMCEBody);
     291        var tempMaxWidth = tempImgMaxWidthTest.css('max-width');
     292        tempImgMaxWidthTest.remove();
     293        tempImgMaxWidthTest = null;
     294
     295        if ('string' === typeof tempMaxWidth) {
     296            /* if it is given as pixels (eg. 474px), return it */
     297            if (tempMaxWidth.indexOf('px') > -1) {
     298                tempMaxWidth = parseInt(tempMaxWidth, 10);
     299                if (!isNaN(tempMaxWidth)) {
     300                    return tempMaxWidth;
     301                }
     302            } else if (tempMaxWidth.indexOf('%') > -1) {    /* if it is given as percent */
     303                /* look for a pixel value on its parent body */
     304                tempMaxWidth = $tinyMCEBody.css('max-width');
     305                /* if it is defined in pixels, return it */
     306                if ('string' === typeof tempMaxWidth && tempMaxWidth.indexOf('px') > -1) {
     307                    tempMaxWidth = parseInt(tempMaxWidth, 10);
     308                    if (!isNaN(tempMaxWidth)) {
     309                        return tempMaxWidth;
     310                    }
     311                }
     312            }
     313        }
     314    };
     315
     316    var getPresetSizeFor = function(presetId) {
     317        var fullWidth = $clickedImage[0].naturalWidth;
     318        var fullHeight = $clickedImage[0].naturalHeight;
     319        var proportion = fullWidth / fullHeight;
     320
     321        if ('__full' === presetId) {
     322            return {
     323                width: fullWidth,
     324                height: fullHeight
     325            };
     326        } else if ('__custom' === presetId) {
     327            return {
     328                width: parseInt($clickedImage.attr('width'), 10),
     329                height: parseInt($clickedImage.attr('height'), 10)
     330            };
     331        } else {
     332            var $opt = $imgSize.find('option[value="' + presetId + '"]');
     333            return {
     334                width: parseInt($opt.attr('data-preset-width'), 10),
     335                height: Math.round(parseInt($opt.attr('data-preset-width'), 10) / proportion)
     336            }
     337        }
     338    };
     339
     340    var setImageSize = function(newWidth, newHeight) {
     341        /* set image dimensions */
     342        $clickedImage.attr('width', newWidth).attr('data-mce-width', newWidth).attr('_mce_width', newWidth);
     343        $clickedImage.attr('height', newHeight).attr('data-mce-height', newHeight).attr('_mce_height', newHeight);
     344
     345        /* clear old inline styles, as they interfere with responsiveness */
     346        $clickedImage.css('width', '');
     347        $clickedImage.css('height', '');
     348
     349        /* update the resizing rectangle to match the new image dimension */
     350        if (window.tinymce.isWebKit) {
     351            impro.updateResizeRect();
     352        }
     353    };
     354
     355    /**
     356     * This function is triggered when any UI event that changes
     357     * a property of the image occurs from the Image Editor panel
     358     * in the right, and inside this function, action is taken
     359     * depending of the input field that changed. At the end, the
     360     * selected image in the post editor is updated with the new
     361     * settings
     362     */
     363    var updateImageSettings = function() {
     364        /* get the current width and height of the image */
     365        var newWidth = parseInt($clickedImage.attr('width'), 10);
     366        var newHeight = parseInt($clickedImage.attr('height'), 10);
     367        /* get the full width and height (the original size) of the image */
     368        var fullWidth = $clickedImage[0].naturalWidth;
     369        var fullHeight = $clickedImage[0].naturalHeight;
     370        /* the max-width value of the image */
     371        var maxWidth;
     372        /* compute the proportion between the width and the height of the image */
     373        var proportion = fullWidth / fullHeight;
     374
     375        /* if we are changing the size preset */
     376        if (this.is($imgSize)) {
     377            /* get the preset size object */
     378            var presetSize = getPresetSizeFor($imgSize.val());
     379            newWidth = presetSize.width;
     380            newHeight = presetSize.height;
     381
     382            /* if the responsiveness checkbox is checked */
     383            if ($imgMaxW.is(':checked')) {
     384                maxWidth = 'none';
     385            } else {
     386                maxWidth = '';
     387                /* resize to max-width */
     388                if ('number' === typeof themeMaxWidth && newWidth > themeMaxWidth) {
     389                    newWidth = themeMaxWidth;
     390                    newHeight = parseInt(newWidth / proportion, 10);
     391                }
     392            }
     393        }
     394
     395        /* if we are toggling the responsiveness checkbox */
     396        if (this.is($imgMaxW)) {
     397            if ($imgMaxW.is(':checked')) {
     398                maxWidth = 'none';
     399                /* get the width from the manual size input */
     400                /* if it is full size or other size (except custom), take it from the dropdown */
     401                if ('__custom' !== $imgSize.val()) {
     402                    /* get the preset size object */
     403                    var presetSize = getPresetSizeFor($imgSize.val());
     404                    newWidth = presetSize.width;
     405                    newHeight = presetSize.height;
     406                } else {
     407                    newWidth = $imgW.val();
     408                    newHeight = parseInt(newWidth / proportion, 10);
     409                }
     410            } else {
     411                maxWidth = '';
     412                /* resize to max-width */
     413                if ('number' === typeof themeMaxWidth && newWidth > themeMaxWidth) {
     414                    newWidth = themeMaxWidth;
     415                    newHeight = parseInt(newWidth / proportion, 10);
     416                }
     417            }
     418        }
     419
     420        /* if we are changing the size manually */
     421        if (this.is($imgW) || this.is($imgH)) {
     422            if (this.is($imgW)) {
     423                newWidth = parseInt(this.val(), 10);
     424                if (!isNaN(newWidth)) {
     425                    newHeight = parseInt(newWidth / proportion);
     426                }
     427            } else if (this.is($imgH)) {
     428                newHeight = parseInt(this.val(), 10);
     429                if (!isNaN(newHeight)) {
     430                    newWidth = parseInt(newHeight * proportion);
     431                }
     432            }
     433
     434            /* any action on the custom fields should change the size dropdown to custom */
     435            if ('__custom' !== $imgSize.val()) {
     436                $imgSize.val('__custom');
     437            }
     438        }
     439
     440        /* set image dimensions */
     441        if (newWidth && newHeight) {
     442
     443            /* if it is too small, just add an error class */
     444            if (newWidth < MIN_W || newHeight < MIN_H) {
     445                $imgW.add($imgH).addClass('impro-editor-wh-error');
     446                return;
     447            } else if ('number' === typeof themeMaxWidth && themeMaxWidth < newWidth && !$imgMaxW.is(':checked')) {
     448                $imgW.add($imgH).addClass('impro-editor-wh-error');
     449                return;
     450            } else {
     451                $imgW.add($imgH).removeClass('impro-editor-wh-error');
     452            }
     453
     454            /* change image size */
     455            setImageSize(newWidth, newHeight);
     456
     457            /* update the width/height inputs */
     458            $imgW.val(newWidth);
     459            $imgH.val(newHeight);
     460        }
     461        /* set the max-width */
     462        if ('none' === maxWidth || '' === maxWidth) {
     463            $clickedImage.css('max-width', maxWidth);
     464            /* also remove it from data-mce-style, as it transmits it further and we do not need it */
     465            if ('' === maxWidth) {
     466                var dataMCEStyle = $clickedImage.attr('data-mce-style');
     467                if ('string' === typeof dataMCEStyle) {
     468                    dataMCEStyle = dataMCEStyle.replace(/max-width\s*:\s*none\s*;?/g, '');
     469                    $clickedImage.attr('data-mce-style', dataMCEStyle);
     470                }
     471            }
     472        }
     473    };
     474
     475    var initEvents = function() {
     476
     477        $imgSize.bind('change', function(ev) {
     478            updateImageSettings.call($(this));
     479        });
     480
     481        $imgMaxW.bind('change', function(ev) {
     482            updateImageSettings.call($(this));
     483        });
     484
     485        $imgW.add($imgH).bind('keyup change', function(ev) {
     486            updateImageSettings.call($(this));
     487            ev.stopImmediatePropagation(); /* keyup and change are bound. we only need one to get it */
     488        });
     489
     490        /* there is no consistent and 100% correct way to be notified on the image's resize. that's why we use polling */
     491        var tInterval = 0;
     492        tInterval = setInterval(function() {
     493            if ($clickedImage && $clickedImage.length) {
     494                /* do not refresh manual size inputs while user is making changes (is in focus there) */
     495                if ($imgW.is(':focus') || $imgH.is(':focus')) {
     496                    return;
     497                }
     498
     499                if (!$clickedImage[0].parentNode) {
     500                    closeEditor();
     501                }
     502
     503                /* get previous size data */
     504                var prevW = $clickedImage.data('prevW');
     505                var prevH = $clickedImage.data('prevH');
     506                var currentW = $clickedImage.width();
     507                var currentH = $clickedImage.height();
     508
     509                /* DeMorgan Law. if no size previously or different sizes, update UI and image data size cache */
     510                if (((prevW !== undefined && prevH !== undefined) && (prevW !== currentW || prevH !== currentH)) || (!(prevW !== undefined && prevH !== undefined))) {
     511                    /* >0 is used to not intercept the images that are just being added, until they get loaded */
     512                    /* prevent resizing to very small images - disabled for the moment because of a bug
     513                    if ((currentW < MIN_W || currentH < MIN_H) && (currentW > 0 || currentH > 0)) {
     514                        var fullWidth = $clickedImage[0].naturalWidth;
     515                        var fullHeight = $clickedImage[0].naturalHeight;
     516                        var proportion = fullWidth / fullHeight;
     517
     518                        if (currentW < currentH) {
     519                            currentW = MIN_W + 20;
     520                            currentH = currentW / proportion;
     521                        } else {
     522                            currentH = MIN_H + 20;
     523                            currentW = currentH * proportion;
     524                        }
     525
     526                        setImageSize(currentW, currentH);
     527
     528                        alert('You cannot resize an image to a size smaller than ' + MIN_W + 'x' + MIN_H + ' pixels!');
     529                    }
     530                    //*/
     531
     532                    /* round values */
     533                    currentW = Math.round(currentW);
     534                    currentH = Math.round(currentH);
     535
     536                    /* set custom sizes */
     537                    $imgW.val(currentW);
     538                    $imgH.val(currentH);
     539                    $clickedImage.data('prevW', currentW);
     540                    $clickedImage.data('prevH', currentH);
     541
     542                    /* set the size preset */
     543                    selectCorrectPreset(currentW, currentH);
     544                }
     545            }
     546        }, 200);
     547
     548
     549
     550
     551        var changeProps = function(ev) {
     552            /* preview */
     553            $clickedImage.attr('alt', $('.impro_alt').val());
     554            $clickedImage.attr('title', $('.impro_title').val());
     555            $clickedImage.removeClass('alignnone alignleft aligncenter alignright').addClass($('.impro_align').val());
     556
     557            /* save */
     558            $clickedImage.attr('_mce_alt', $('.impro_alt').val());
     559            $clickedImage.attr('_mce_title', $('.impro_title').val());
     560            $clickedImage.attr('_mce_class', $clickedImage.attr('class'));
     561
     562            ev.stopImmediatePropagation();
     563        };
     564
     565        $('.impro_align, .impro_alt, .impro_title').bind('change keyup', changeProps);
     566
     567        $('.impro_link').click(function() {
     568            if ($(this).is(':checked')) {
     569                tinyMCE.activeEditor.execCommand('mceInsertLink', false, { href: $clickedImage.attr('src'), target: '_blank' });
     570            } else {
     571                tinyMCE.activeEditor.execCommand('mceInsertLink', false, '');
     572            }
     573        });
     574    };
     575
     576    var onSwitchEditor = function(id, mode) {
     577
     578    };
     579
     580    /* public methods */
     581    $.extend(this, {
     582        init: init,
     583        getTinyMCE: getTinyMCE
     584    });
     585}).call(impro.editor = {}, jQuery);
    596586
    597587jQuery(function() {
  • image-pro-wordpress-image-media-management-and-resizing-done-right/trunk/src/js/folder.js

    r715205 r847712  
    1 /* Folder namespace */
    2 impro.folder = {toolbar:{}};
    3 
    4 /* init folder view */
    5 impro.folder.init = function() {
    6     impro.folder.loadImages();
    7    
    8     impro.folder.initEvents();
    9 };
    10 
    11 /* add to editor action */
    12 impro.folder.toolbar.add = function(li) {
    13     var content = null;
    14     var ext = li.attr('data-ext').toLowerCase();
    15     var id  = li.attr('data-attachment-id');
    16    
    17     var addContent = function(ct) {
    18         impro.editor.getTinyMCE().execCommand('mceInsertContent',false, ct);
    19     };
    20    
    21     /* if we add an image */
    22     if (['jpg','jpeg','gif','png'].indexOf(ext) !== -1) {
    23         var src = li.find('img').attr('src');
    24         content = '<img src="' + src + '" />';
    25         addContent(content);
    26     } else {    /* for any other extension, default is link, but we can easily override */
    27         jQuery.getJSON(impro.url + '/src/request/getattachmentdata.php?id=' + id, function(json) {  /* get all the data of the attachment */
    28             if (impro.folder.custom && typeof impro.folder.custom['extension_' + ext] === 'function') { /* if user defined a custom function, use it */
    29                 content = impro.folder.custom['extension_' + ext].call(this, json, li);
    30             } else {    /* if not, just make a link */
    31                 content = ' <a href="' + json.attachment_url + '" target="_blank">' + json.post_title + '</a> ';
    32             }
    33             addContent(content);
    34         });
    35     }   
    36    
    37     return false;
    38 };
    39 
    40 /* edit in library */
    41 impro.folder.toolbar.library = function(li) {
    42     var content = null;
    43     var att_id = li.attr('data-attachment-id');
    44 
    45     content = impro.admin_url + 'media.php?attachment_id=' + att_id + '&action=edit';   /* build media edit link */
    46    
    47     jQuery('#vimg-toolbar a[data-action=library]').attr('href', content).attr('target', '_blank');  /* set link */
    48    
    49     return true;    /* return true, such that the href link will be used */
    50 }
    51 
    52 /* open */
    53 impro.folder.toolbar.open = function(li) {
    54     var content = null;
    55     var id = li.attr('data-attachment-id');
    56 
    57     jQuery.getJSON(impro.url + '/src/request/getattachmentdata.php?id=' + id, function(json) {  /* get all the data of the attachment */
    58         var result = window.open(json.attachment_url, 'op');
    59         if (!result) {
    60             impro.err(imageproFolderL10N.popupOpenError);
    61         }
    62     });
    63    
    64     return false;
    65 };
    66 
    67 /* show link */
    68 impro.folder.toolbar.link = function(li) {
    69     var content = null;
    70     var id = li.attr('data-attachment-id');
    71 
    72     jQuery.getJSON(impro.url + '/src/request/getattachmentdata.php?id=' + id, function(json) {  /* get all the data of the attachment */
    73         prompt(imageproFolderL10N.attachmentLink, json.attachment_url);
    74     });
    75    
    76     return false;
    77 };
    78 
    79 /* delete */
    80 impro.folder.toolbar.remove = function(li) {
    81     if (confirm(imageproFolderL10N.deleteAttachmentConfirmation)) {
    82         jQuery.post(impro.url + '/src/request/deleteattachment.php', {
    83             id: li.attr('data-attachment-id'),
    84             _ajax_nonce: impro.nonce.deleteNonce
    85         }, function(data) {
    86             if (data.ok) {
    87                 impro.info(data.data.msg);
    88                 impro.folder.loadImages();
    89             } else {
    90                 impro.err(data.data.msg);
    91             }
    92         });
    93     }
    94     return false;
    95 };
    96 
    97 /* init the events */
    98 impro.folder.initEvents = function() {
    99    
    100     var timerID = 0;
    101    
    102     /* searching text event */
    103     jQuery('#vimg-search').keyup(function(ev) {
    104         if (ev.which && (/[a-zA-Z0-9 \.,;-_]/.test(String.fromCharCode(ev.which)) || ev.which === 8)) {
    105             clearTimeout(timerID);     
    106             timerID = setTimeout(function() {
    107                 impro.folder.loadImages();
    108             }, 500);
    109         }
    110     });
    111    
    112     var changeFileType = function(e) {
    113         impro.folder.loadImages();
    114     };
    115 
    116     jQuery('#vimg-dbg').click(function(ev) {
    117         jQuery('#vimg-dbg-content').show().find('textarea').load(impro.url + '/src/request/dbg.php?rnd='+Math.random(), {},  function(t) {
    118             jQuery('#vimg-dbg-content textarea').val(t);
    119         });
    120         return false;
     1(function($){
     2    /* add to post handlers. add here additional functionality for generating HTML in TinyMCE for  custom extensions */
     3    var addToPostHandlers = {};
     4
     5    /* the toolset object contains actions to be taken when the actions of a thumbnail are being used */
     6    var toolset = {
     7        add: function(li, attachmentId) {
     8            var ext = li.attr('data-ext').toLowerCase();
     9
     10            var addContent = function(ct) {
     11                impro.editor.getTinyMCE().execCommand('mceInsertContent',false, ct);
     12            };
     13
     14            /* if we add an image */
     15            if (['jpg','jpeg','gif','png'].indexOf(ext) !== -1) {
     16                var $img = li.find('img');
     17                var src = $img.attr('src');
     18                content = '<img src="' + src + '" />';
     19                addContent(content);
     20
     21                /* add animation of content */
     22                // TODO put it exactly over the image :D
     23                var contentIfr = $(impro.editor.getTinyMCE().contentAreaContainer);
     24                var $imgClone = $img.clone();
     25                $imgClone.css({
     26                    position: 'absolute',
     27                    top: $img.offset().top,
     28                    left: $img.offset().left,
     29                    'z-index': 10000
     30                }).appendTo('body').animate({
     31                        top: contentIfr.offset().top + contentIfr.height() / 2,
     32                        left: contentIfr.offset().left + contentIfr.width() / 2,
     33                        opacity: 0.5
     34                    }, 1000, function() {
     35                        $(this).remove();
     36                    });
     37
     38            } else {    /* for any other extension, default is link, but we can easily override */
     39                $.getJSON(impro.url + '/src/request/getattachmentdata.php?id=' + attachmentId, function(json) { /* get all the data of the attachment */
     40                    if (addToPostHandlers && typeof addToPostHandlers['extension_' + ext] === 'function') { /* if user defined a custom function, use it */
     41                        content = addToPostHandlers['extension_' + ext].call(this, json, li);
     42                    } else {    /* if not, just make a link */
     43                        content = ' <a href="' + json.attachment_url + '" target="_blank">' + json.post_title + '</a> ';
     44                    }
     45                    addContent(content);
     46                });
     47            }
     48
     49            return false;
     50        },
     51        library: function(li, attachmentId) {
     52            var content;
     53            content = impro.admin_url + 'media.php?attachment_id=' + attachmentId + '&action=edit'; /* build media edit link */
     54
     55            $('#vimg-toolset [data-action=library]').attr('href', content).attr('target', '_blank');    /* set link */
     56
     57            return true;    /* return true, such that the href link will be used */
     58        },
     59        open: function(li, attachmentId) {
     60            var content;
     61
     62            $.getJSON(impro.url + '/src/request/getattachmentdata.php?id=' + attachmentId, function(json) { /* get all the data of the attachment */
     63                var result = window.open(json.attachment_url, 'op');
     64                if (!result) {
     65                    impro.err(imageproFolderL10N.popupOpenError);
     66                }
     67            });
     68
     69            return false;
     70        },
     71        link: function(li, attachmentId) {
     72            var content;
     73
     74            $.getJSON(impro.url + '/src/request/getattachmentdata.php?id=' + attachmentId, function(json) { /* get all the data of the attachment */
     75                prompt(imageproFolderL10N.attachmentLink, json.attachment_url);
     76            });
     77
     78            return false;
     79        },
     80        remove: function(li, attachmentId) {
     81            if (confirm(imageproFolderL10N.deleteAttachmentConfirmation)) {
     82                $.post(impro.url + '/src/request/deleteattachment.php', {
     83                    id: attachmentId,
     84                    _ajax_nonce: impro.nonce.deleteNonce
     85                }, function(data) {
     86                    if (data.ok) {
     87                        loadImages();
     88                    } else {
     89                        impro.err(data.data.msg);
     90                    }
     91                });
     92            }
     93            return false;
     94        }
     95    };
     96
     97    var init = function() {
     98        loadImages();
     99        $('#vimg-toolbar-filter').appendTo($('#impro_folder_box .hndle')).show();
     100        initEvents();
     101    };
     102
     103    var initEvents = function() {
     104        var timerID = 0; /* reference for timer, used for event buffering for searching */
     105        /* searching text event. the event is buffered so requests are delayed until user finishes typing */
     106        $('#vimg-search').bind('keyup', function(ev) {
     107            if (ev.which && (/[a-zA-Z0-9 \.,;-_]/.test(String.fromCharCode(ev.which)) || ev.which === 8)) {
     108                clearTimeout(timerID);
     109                timerID = setTimeout(function() {
     110                    loadImages();
     111                }, 500);
     112            }
     113        });
     114
     115        /* selecting a certain file type */
     116        $('#vimg-filetype').bind('change keyup', function(ev) {
     117            loadImages();
     118        });
     119
     120        /* since the filter toolbar is in the header of the panel, any click should not pass through, as it may collapse it */
     121        $('#vimg-toolbar-filter').bind('click', false);
     122
     123        /* the debug log */
     124        $('#vimg-dbg').bind('click', function(ev) {
     125            $('#vimg-dbg-content').show().find('textarea').load(impro.url + '/src/request/dbg.php?rnd='+Math.random(), {},  function(t) {
     126                $('#vimg-dbg-content textarea').val(t);
     127            });
     128            return false;
     129        });
     130
     131        /* when any button from the toolset is clicked */
     132        $('#vimg-toolset').delegate('[data-action]', 'click', function(ev) {
     133            var $li = $(this).closest('li[data-attachment-id]');
     134            return toolset[$(this).attr('data-action')].call(this, $li, $li.attr('data-attachment-id'));
     135        });
     136
     137        /* when the file upload field in the list changes, start file upload */
     138        $('#vimg-list').delegate('input[type="file"]', 'change', function(ev) {
     139            if (this.files && this.files.length) {
     140                ddu.uploadMultipleFiles(this.files);
     141                try {
     142                    this.reset();
     143                } catch(e) {}
     144            }
     145        });
     146
     147        /* display the toolset */
     148        $('#vimg-list')
     149            .delegate('li[data-attachment-id]', 'mouseenter', function(ev) {
     150                $('#vimg-toolset').appendTo(this);
     151            })
     152            .delegate('li[data-attachment-id]', 'mouseleave', function(ev) {
     153                $('#vimg-toolset').appendTo('body');
     154            });
     155
     156        /* when an image is double clicked, it is automatically added to content */
     157        $('#vimg-list').delegate('li[data-attachment-id] img', 'dblclick', function(ev) {
     158            var $li = $(this).closest('li[data-attachment-id]');
     159            return toolset['add'].call(this, $li, $li.attr('data-attachment-id'));
     160        });
     161
     162        /* this event is used for blocking the dragging of non-image files to the editor */
     163        $('#vimg-list').bind('mousedown', function(ev) {
     164            var target = $(ev.target);
     165
     166            if (target.is('img')) { /* if began dragging an image */
     167                target = target.closest('li');  /* get its li parent */
     168            } else {
     169                return false;
     170            }
     171
     172            var ext = target.attr('data-ext');  /* get extension */
     173
     174            if (ext && ['jpg', 'jpeg', 'gif', 'png'].indexOf(ext) === -1) { /* if not image */
     175                /* stop dragging */
     176                ev.stopPropagation();
     177                ev.preventDefault();
     178                setTimeout(function() { /* it seems that showing an alert box immidiately makes the dragged image load. so we time out a bit */
     179                    //impro.err('You can only drag images over the editor! For other file types, click "Add to editor".');
     180                }, 500);
     181                return false;
     182            }
     183        });
     184    };
     185
     186    var loadImages = function() {
     187        $.ajax(impro.url + '/src/request/getimages.php', {
     188            cache: false,
     189            data: {
     190                filetype: $('#vimg-filetype').val(),
     191                search: $('#vimg-search').val(),
     192                sort: $('#vimg-sort').val()
     193            },
     194            dataType: 'json',
     195            type: 'GET',
     196            success: function(data, status, xhr) {
     197                var html = "";
     198
     199                if (data.ok) {
     200                    /* build the "Upload" button */
     201                    html += '<li id="vupload"><input type="file" multiple /><div><span>+</span>' + imageproEditorL10N.uploadNew + '</div>';
     202                    html += '</li>';
     203
     204                    /* build the HTML structure for the images from the server */
     205                    for(var i = 0; i < data.data.length; i++) {
     206                        html += '<li data-attachment-id="' + data.data[i].id + '" data-url="' + data.data[i].thumb + '" data-ext="' + data.data[i].ext + '">';
     207                        html += '<img data-lazy-src="' + data.data[i].thumb + '" />';
     208                        html += '<span>' + data.data[i].name + '</span>';
     209                        html += '</li>';
     210                    }
     211
     212                    /* recover the toolset in case of deleting elements */
     213                    var $toolset = $('#vimg-list #vimg-toolset');
     214                    if ($toolset.length) {
     215                        $toolset.appendTo('body');
     216                    }
     217
     218                    /* render the images */
     219                    $('#vimg-list ul').empty().append(html);
     220                }
     221
     222                /* set up the lazy load of images on scroll*/
     223                lazyscroll();
     224                $('#vimg-list').scroll();
     225            },
     226            error: function() {
     227
     228            }
     229        });
     230    };
     231
     232    var lazyscroll = function() {
     233        var lazyscroll_timers = [];
     234        $('#vimg-list').scroll(function() {
     235            for(var i=0;i<lazyscroll_timers.length;i++) {
     236                clearTimeout(lazyscroll_timers[i]);
     237            }
     238
     239            lazyscroll_timers.push(setTimeout(function() {
     240                var scrollTop = $('#vimg-list').scrollTop();
     241                var containerTop = Math.round($('#vimg-list').offset().top);
     242
     243                /* if there are any images in the list */
     244                if ($('#vimg-list img:eq(0)').size() > 0) {
     245                    var firstImageTop = Math.round($('#vimg-list img:eq(0)').offset().top);
     246
     247                    var j = 0;
     248                    $('#vimg-list img[data-lazy-src]').each(function(i) {
     249                        var _currentImageTop = $(this).offset().top;
     250                        if (_currentImageTop - containerTop > 0 || $(this).not(':visible')) {
     251                            var _el = $(this);
     252                            setTimeout(function() {
     253                                _el.attr('src',_el.attr('data-lazy-src')).removeAttr('data-lazy-src');
     254                            }, j++ * 20);
     255
     256                            if (j == 26) {
     257                                return false;
     258                            }
     259                        }
     260                    });
     261                }
     262
     263            }, 500));
     264        });
     265    };
     266
     267    var ddu = new impro.DragDropUpload();
     268    ddu.init('vimg-list', {
     269        url: impro.url + '/src/request/upload.php',
     270        onProgress: function(e, file, i, currentFileProgress, totalProgress) {
     271            /* show progress */
     272            $('#vimg-progress-wrapper').show();
     273            $('#vimg-progress').show().width(totalProgress + '%');
     274        },
     275        onCompleted: function(e, files, filesSucceeded, filesFailed) {
     276            /* hide progress, but a bit later to allow the animation to complete */
     277            setTimeout(function() {
     278                $('#vimg-progress-wrapper').hide();
     279                $('#vimg-progress').width('0%');
     280            }, 500);
     281
     282            /* get the target - in this case de XMLHttpRequest */
     283            var target = e.target || e.originalTarget || e.currentTarget;
     284
     285            /* if we have files that failed uploading */
     286            if (0 !== filesFailed.length) {
     287                var errContent = "";
     288
     289                errContent += "<div style='margin: 15px;'>";
     290                errContent += "<p style='margin-top: 0;'><strong>";
     291
     292                if (filesFailed.length === files.length) {
     293                    errContent += "There was a general error and no files could be uploaded!";
     294                } else {
     295                    errContent += "" + filesFailed.length + " files of the total of " + files.length + " failed!";
     296                }
     297
     298                errContent += "</strong></p>";
     299
     300                errContent += "<p>Please check out the list below for error messages</p>";
     301
     302                errContent += "<div style='height: 250px; overflow: auto;'>";
     303                errContent += "<table cellspacing='0' cellpadding='3' border='0'>";
     304
     305                errContent += "<tr>";
     306                errContent += "<td style='font-weight: bold; width: 110px; border: 1px solid #ddd;'>";
     307                errContent += "Filename";
     308                errContent += "</td>";
     309                errContent += "<td style='font-weight: bold; width: 255px; border: 1px solid #ddd;'>";
     310                errContent += "Error";
     311                errContent += "</td>";
     312                errContent += "</tr>";
     313
     314                for (var i = 0; i < filesFailed.length; i++) {
     315                    var httpErrStr = ('object' === typeof filesFailed[i].httpResponse ? filesFailed[i].httpResponse.data.str : ('string' === typeof filesFailed[i].httpResponse ? "" : ""));
     316                    errContent += "<tr>";
     317                    errContent += "<td style='border: 1px solid #ddd;'>";
     318                    errContent += filesFailed[i].name;
     319                    errContent += "</td>";
     320                    errContent += "<td style='border: 1px solid #ddd;'>";
     321                    errContent += "Status: " + filesFailed[i].httpStatus + ", " + httpErrStr;
     322                    errContent += "</td>";
     323                    errContent += "</tr>";
     324                }
     325
     326                errContent += "</table>"
     327                errContent += "</div>";
     328                errContent += "</div>";
     329
     330                $(errContent).dialog({
     331                    title: 'File upload error',
     332                    modal: true,
     333                    draggable: false,
     334                    resizable: false,
     335                    width: '400px',
     336                    dialogClass: 'wp-dialog',
     337                    buttons: [ { text: "Ok", click: function() { $( this ).dialog( "close" ); } } ]
     338                });
     339            }
     340
     341            /* load images on the server */
     342            loadImages();
     343        }
    121344    });
    122    
    123     jQuery('#vimg-filetype').change(changeFileType).keyup(changeFileType);
    124        
    125     /* when a toolbar button is clicked */
    126     jQuery('#vimg-toolbar').click(function(ev) {
    127         if (!jQuery(ev.target).is('a[data-action]')) {  /* if not clicked on a link, do nothing */
    128             return false;
    129         }
    130        
    131         if (jQuery('#vimg-list').find('.impro_folder_selected').size() !== 1) { /* if no image is selected */
    132             impro.err(imageproFolderL10N.noImageSelected);
    133             return false;
    134         }
    135        
    136         /* run the action on the toolbar */
    137         return impro.folder.toolbar[jQuery(ev.target).attr('data-action')].call(this, jQuery('#vimg-list').find('.impro_folder_selected'));
    138     });
    139    
    140     /* when an image is clicked */
    141     jQuery('#vimg-list').click(function(ev) {
    142         var target = jQuery(ev.target);
    143        
    144         if (ev.target === this) {   /* if clicked exactly on vimg-list, do nothing */
    145             return false;
    146         }
    147        
    148         if (!target.is('li')) { /* if not clicked on the list item, get the list item */
    149             target = target.parents('li');         
    150         }
    151        
    152         /* select the clicked image */
    153         jQuery('#vimg-list li').removeClass('impro_folder_selected');
    154         target.addClass('impro_folder_selected');
    155        
    156         var liimg = target.find('img');
    157         var src = liimg.attr('src');
    158        
    159         /* if "Select another picture" was previously clicked */
    160         if (impro.editor.$chosen) {
    161             /* get the width and height of the currently selected image */
    162             var old_width = impro.editor.$chosen.width();
    163             var old_height = impro.editor.$chosen.height();
    164            
    165             /* parse the url of the new replacement image */
    166             var props = impro.editor.parseUrl(src);
    167            
    168             /* get the width and height of the new replacement image */
    169             var new_width = liimg.width();
    170             var new_height = liimg.height();
    171             var new_ratio = new_width / new_height;
    172            
    173             /* set the width and height to the old one such that proportion is kept */
    174             props['w'] = old_width;
    175             props['h'] = parseInt(old_width / new_ratio);
    176            
    177             /* resize img element if necessary */
    178             impro.editor.$chosen.attr('width', props['w']).attr('_mce_width', props['w']).attr('data-mce-width', props['w']);
    179             impro.editor.$chosen.attr('height', props['h']).attr('_mce_height', props['h']).attr('data-mce-height', props['h']);
    180            
    181             /* build the thumb and resize it */
    182             impro.editor.resize(impro.editor.$chosen, props );
    183            
    184             /* make advanced scale plugin forget the previous dimensions */
    185             impro.editor.$chosen.removeAttr('mce_advimageresize_id');
    186            
    187             /* simulate a click event to the image */
    188             impro.editor.showEditor(impro.editor.$chosen);
    189 
    190             /* clean up */
    191             impro.editor.$chosen = null;
    192             jQuery('#vimg-list').removeClass('impro_choosebg');
    193             jQuery.scrollTo('#titlediv', 800);
    194         }
    195        
    196        
    197     });
    198    
    199     /* this event is used for blocking the dragging of non-image files to the editor */
    200     jQuery('#vimg-list').mousedown(function(ev) {
    201         var target = jQuery(ev.target);
    202        
    203         if (target.is('img')) { /* if began dragging an image */
    204             target = target.parents('li');  /* get it's li parent */
    205         } else {
    206             return false;
    207         }
    208        
    209         var ext = target.attr('data-ext');  /* get extension */
    210        
    211         if (ext && ['jpg', 'jpeg', 'gif', 'png'].indexOf(ext) === -1) { /* if not image */     
    212             /* stop dragging */
    213             ev.stopPropagation();
    214             ev.preventDefault();
    215             setTimeout(function() { /* it seems that showing an alert box immidiately makes the dragged image load. so we time out a bit */
    216                 //impro.err('You can only drag images over the editor! For other file types, click "Add to editor".');
    217             }, 500);
    218             return false;
    219         }
    220     });
    221 };
    222 
    223 /* load images in the folder view */
    224 impro.folder.loadImages = function() {
    225     jQuery('#vimg-list ul').load(impro.url + '/src/request/getimages.php?filetype='+jQuery('#vimg-filetype').val()+'&search='+jQuery('#vimg-search').val()+'&sort='+jQuery('#vimg-sort').val()+'&rnd='+Math.random(), function() {
    226         /* set up the lazy load of images on scroll*/
    227         impro.folder.lazyscroll();
    228         jQuery('#vimg-list').scroll();
    229     });
    230 };
    231 
    232 /* lazy load of images */
    233 impro.folder.lazyscroll = function() {
    234     impro.folder.lazyscroll_timers = [];   
    235     jQuery('#vimg-list').scroll(function() {
    236         for(var i=0;i<impro.folder.lazyscroll_timers.length;i++) {
    237             clearTimeout(impro.folder.lazyscroll_timers[i]);
    238         }
    239        
    240         impro.folder.lazyscroll_timers.push(setTimeout(function() {
    241             var scrollTop = jQuery('#vimg-list').scrollTop();
    242             var containerTop = Math.round(jQuery('#vimg-list').offset().top);
    243            
    244             /* if there are any images in the list */
    245             if (jQuery('#vimg-list img:eq(0)').size() > 0) {
    246                 var firstImageTop = Math.round(jQuery('#vimg-list img:eq(0)').offset().top);
    247                
    248                 var j = 0;
    249                 jQuery('#vimg-list img[data-lazy-src]').each(function(i) {
    250                     var _currentImageTop = jQuery(this).offset().top;
    251                     if (_currentImageTop - containerTop > 0) {
    252                        
    253                         var _el = jQuery(this);
    254                         setTimeout(function() {
    255                             _el.attr('src',_el.attr('data-lazy-src')).removeAttr('data-lazy-src');
    256                         }, j++*20);
    257                        
    258                         if (j==26) return false;
    259                     }
    260                 });
    261             }
    262            
    263         },500));
    264     });
    265 };
    266 
    267 /* init drag and drop */
    268 impro.folder.ddu = new impro.DragDropUpload();
    269 impro.folder.ddu.init('vimg-list', {
    270     url: impro.url+'/src/request/upload.php',
    271     onProgress: function(e, f) {
    272         /* show progress */
    273         jQuery('#vimg-progress-wrapper').show();
    274         jQuery('#vimg-progress').show().width(Math.round((e.position * 100) / e.totalSize)+'%');
    275     },
    276     onComplete: function( ev ){
    277         /* get the target - in this case de XMLHttpRequest */
    278         var target = ev.target || ev.originalTarget || ev.currentTarget;
    279        
    280         /* try to parse the server response. exceptions may be thrown, or result may be null */
    281         var result;
    282         try {
    283             result = jQuery.parseJSON(target.responseText);
    284         } catch(e) {}
    285         if (!result) {
    286             impro.err("Cannot get response after file upload!");
    287             return;
    288         }
    289        
    290         /* server-side handled error */
    291         if (!result['ok']) {
    292             impro.err(result['data']['str']);
    293             return;
    294         }
    295        
    296         /* hide progress */
    297         jQuery('#vimg-progress-wrapper').hide();
    298         jQuery('#vimg-progress').hide();
    299        
    300         /* load images on the server */
    301         impro.folder.loadImages();
    302     },
    303     onDropFile: function(e, fn) {
    304        
    305     }
    306 });
    307 
    308 jQuery(function() {
     345
     346    /* public methods */
     347    $.extend(this, {
     348        init: init
     349    });
     350}).call(impro.folder = {}, jQuery);
     351
     352jQuery(function($) {
    309353    impro.folder.init();
    310354});
  • image-pro-wordpress-image-media-management-and-resizing-done-right/trunk/src/js/impro.js

    r546286 r847712  
    1 /* Image Pro namespace */
    2 var impro = {};
    3 
    4 impro.nonce = {};
    5 
    6 impro.err = function(str) {
    7     alert(str);
    8 };
    9 
    10 impro.info = function(str) {
    11     alert(str);
    12 };
     1(function($) {
     2    /* the nonce security token */
     3    var nonce = {};
     4
     5    /* whether the browser is minimum IE10 (IE10, IE11, etc) */
     6    var minIE10 = navigator.userAgent.indexOf('MSIE 10') > 0 || (navigator.userAgent.indexOf('Trident') > 0 && /rv:[0-9][0-9]/.test(navigator.userAgent));
     7
     8    /* error message */
     9    var err = function(str) {
     10        alert(str);
     11    };
     12
     13    /* info message */
     14    var info = function(str) {
     15        alert(str);
     16    };
     17
     18    var fakeImageResize = function () {
     19        var editor = tinyMCE.editors[0];
     20        var dom = editor.dom;
     21        var selection = editor.selection;
     22        var VK = tinyMCE.VK;
     23        var settings = editor.settings;
     24
     25        var selectedElmX, selectedElmY, selectedElm, selectedElmGhost, selectedHandle, startX, startY, startW, startH, ratio,
     26            resizeHandles, width, height, rootDocument = document, editableDoc = editor.getDoc();
     27
     28        if (settings.webkit_fake_resize === true) {
     29            alert('It seems that you are on a WebKit Browser (Chrome / Safari) '+
     30                'and your configuration has webkit_fake_resize = true.' +
     31                "\n\n" +
     32                "Please turn it off for the Image Pro Plugin to function correctly under WebKit browsers.\n\n" +
     33                "Contact us for more information!");
     34            return;
     35        }
     36
     37        /*if (!settings.object_resizing || settings.webkit_fake_resize === false) {
     38         return;
     39         }*/
     40
     41        // Try disabling object resizing if WebKit implements resizing in the future
     42        try {
     43            editor.getDoc().execCommand("enableObjectResizing", false, false);
     44        } catch (ex) {
     45            // Ignore
     46        }
     47
     48        // Details about each resize handle how to scale etc
     49        resizeHandles = {
     50            // Name: x multiplier, y multiplier, delta size x, delta size y
     51            n: [.5, 0, 0, -1],
     52            e: [1, .5, 1, 0],
     53            s: [.5, 1, 0, 1],
     54            w: [0, .5, -1, 0],
     55            nw: [0, 0, -1, -1],
     56            ne: [1, 0, 1, -1],
     57            se: [1, 1, 1, 1],
     58            sw : [0, 1, -1, 1]
     59        };
     60
     61        function resizeElement(e) {
     62            var deltaX, deltaY;
     63
     64            // Calc new width/height
     65            deltaX = e.screenX - startX;
     66            deltaY = e.screenY - startY;
     67
     68            // Calc new size
     69            width = deltaX * selectedHandle[2] + startW;
     70            height = deltaY * selectedHandle[3] + startH;
     71
     72            // Never scale down lower than 5 pixels
     73            width = width < 5 ? 5 : width;
     74            height = height < 5 ? 5 : height;
     75
     76            // Constrain proportions when modifier key is pressed or if the nw, ne, sw, se corners are moved on an image
     77            if (VK.modifierPressed(e) || (selectedElm.nodeName == "IMG" && selectedHandle[2] * selectedHandle[3] !== 0)) {
     78                width = Math.round(height / ratio);
     79                height = Math.round(width * ratio);
     80            }
     81
     82            // Update ghost size
     83            dom.setStyles(selectedElmGhost, {
     84                width: width,
     85                height: height
     86            });
     87
     88            // Update ghost X position if needed
     89            if (selectedHandle[2] < 0 && selectedElmGhost.clientWidth <= width) {
     90                dom.setStyle(selectedElmGhost, 'left', selectedElmX + (startW - width));
     91            }
     92
     93            // Update ghost Y position if needed
     94            if (selectedHandle[3] < 0 && selectedElmGhost.clientHeight <= height) {
     95                dom.setStyle(selectedElmGhost, 'top', selectedElmY + (startH - height));
     96            }
     97        }
     98
     99        function endResize() {
     100            /* IMAGEPRO - it is unknown why sometimes width and height come with zero values here. however, we skip this case */
     101            if (width === 0 || height === 0) {
     102                return;
     103            }
     104
     105            // Set width/height properties
     106            dom.setAttrib(selectedElm, 'data-mce-width', width);
     107            dom.setAttrib(selectedElm, 'data-mce-height', height);
     108            dom.setAttrib(selectedElm, 'width', width);
     109            dom.setAttrib(selectedElm, 'height', height);
     110
     111            dom.unbind(editableDoc, 'mousemove', resizeElement);
     112            dom.unbind(editableDoc, 'mouseup', endResize);
     113
     114            if (rootDocument != editableDoc) {
     115                dom.unbind(rootDocument, 'mousemove', resizeElement);
     116                dom.unbind(rootDocument, 'mouseup', endResize);
     117            }
     118
     119            // Remove ghost and update resize handle positions
     120            dom.remove(selectedElmGhost);
     121            showResizeRect(selectedElm);
     122        }
     123
     124        function showResizeRect(targetElm) {
     125            var position, targetWidth, targetHeight;
     126
     127            hideResizeRect();
     128
     129            // Get position and size of target
     130            position = dom.getPos(targetElm);
     131            selectedElmX = position.x;
     132            selectedElmY = position.y;
     133            targetWidth = targetElm.offsetWidth;
     134            targetHeight = targetElm.offsetHeight;
     135
     136            // Reset width/height if user selects a new image/table
     137            if (selectedElm != targetElm) {
     138                selectedElm = targetElm;
     139                width = height = 0;
     140            }
     141
     142            tinymce.each(resizeHandles, function(handle, name) {
     143                var handleElm;
     144
     145                // Get existing or render resize handle
     146                handleElm = dom.get('mceResizeHandle' + name);
     147                if (!handleElm) {
     148                    handleElm = dom.add(editableDoc.documentElement, 'div', {
     149                        id: 'mceResizeHandle' + name,
     150                        'class': 'mceResizeHandle',
     151                        style: 'cursor:' + name + '-resize; margin:0; padding:0'
     152                    });
     153
     154                    dom.bind(handleElm, 'mousedown', function(e) {
     155                        e.preventDefault();
     156
     157                        endResize();
     158
     159                        startX = e.screenX;
     160                        startY = e.screenY;
     161                        startW = selectedElm.clientWidth;
     162                        startH = selectedElm.clientHeight;
     163                        ratio = startH / startW;
     164                        selectedHandle = handle;
     165
     166                        selectedElmGhost = selectedElm.cloneNode(true);
     167                        dom.addClass(selectedElmGhost, 'mceClonedResizable');
     168                        dom.setStyles(selectedElmGhost, {
     169                            left: selectedElmX,
     170                            top: selectedElmY,
     171                            margin: 0
     172                        });
     173
     174                        editableDoc.documentElement.appendChild(selectedElmGhost);
     175
     176                        dom.bind(editableDoc, 'mousemove', resizeElement);
     177                        dom.bind(editableDoc, 'mouseup', endResize);
     178
     179                        if (rootDocument != editableDoc) {
     180                            dom.bind(rootDocument, 'mousemove', resizeElement);
     181                            dom.bind(rootDocument, 'mouseup', endResize);
     182                        }
     183                    });
     184                } else {
     185                    dom.show(handleElm);
     186                }
     187
     188                // Position element
     189                dom.setStyles(handleElm, {
     190                    left: (targetWidth * handle[0] + selectedElmX) - (handleElm.offsetWidth / 2),
     191                    top: (targetHeight * handle[1] + selectedElmY) - (handleElm.offsetHeight / 2)
     192                });
     193            });
     194
     195            // Only add resize rectangle on WebKit and only on images
     196            if (!tinymce.isOpera && selectedElm.nodeName == "IMG") {
     197                selectedElm.setAttribute('data-mce-selected', '1');
     198            }
     199        }
     200
     201        function hideResizeRect() {
     202            if (selectedElm) {
     203                selectedElm.removeAttribute('data-mce-selected');
     204            }
     205
     206            for (var name in resizeHandles) {
     207                dom.hide('mceResizeHandle' + name);
     208            }
     209        }
     210
     211        // Add CSS for resize handles, cloned element and selected
     212        var css = '.mceResizeHandle {' +
     213            'position: absolute;' +
     214            'border: 1px solid black;' +
     215            'background: #FFF;' +
     216            'width: 5px;' +
     217            'height: 5px;' +
     218            'z-index: 10000' +
     219            '}' +
     220            '.mceResizeHandle:hover {' +
     221            'background: #000' +
     222            '}' +
     223            'img[data-mce-selected] {' +
     224            'outline: 1px solid black' +
     225            '}' +
     226            'img.mceClonedResizable, table.mceClonedResizable {' +
     227            'position: absolute;' +
     228            'outline: 1px dashed black;' +
     229            'opacity: .5;' +
     230            'z-index: 10000' +
     231            '}';
     232
     233        var el = editor.getDoc().createElement('style');
     234        el.innerHTML = css;
     235        editor.getDoc().getElementsByTagName('head')[0].appendChild(el);
     236
     237        function updateResizeRect() {
     238            var controlElm = dom.getParent(selection.getNode(), 'table,img');
     239
     240            // Remove data-mce-selected from all elements since they might have been copied using Ctrl+c/v
     241            tinymce.each(dom.select('img[data-mce-selected]'), function(img) {
     242                img.removeAttribute('data-mce-selected');
     243            });
     244
     245            if (controlElm) {
     246                showResizeRect(controlElm);
     247            } else {
     248                hideResizeRect();
     249            }
     250        }
     251
     252        // Show/hide resize rect when image is selected
     253        editor.onNodeChange.add(updateResizeRect);
     254
     255        // Fixes WebKit quirk where it returns IMG on getNode if caret is after last image in container
     256        dom.bind(editableDoc, 'selectionchange', updateResizeRect);
     257
     258        // Remove the internal attribute when serializing the DOM
     259        editor.serializer.addAttributeFilter('data-mce-selected', function(nodes, name) {
     260            var i = nodes.length;
     261
     262            while (i--) {
     263                nodes[i].attr(name, null);
     264            }
     265        });
     266
     267        /* IMAGEPRO - extracted a private method to public to be able to refresh the handles */
     268        impro.updateResizeRect = updateResizeRect;
     269    };
     270
     271    var createThumbUrl = function(params) {
     272        var path = impro.url + '/src/thumb/phpThumb.php?';
     273        var tmp = [];
     274        for (var p in params) {
     275            if (['w','h','src','zc','q'].indexOf(p) === -1) {
     276                continue;
     277            }
     278            if (params.hasOwnProperty(p)) {
     279                tmp.push(p+'='+params[p]);
     280            }
     281        }
     282        return path + tmp.join('&');
     283    };
     284
     285    var parseUrl = function(url) {
     286        var path = {};
     287
     288        /* if begins with http(s?):// protocol */
     289        var is_http = /^https?:\/\/$/i.test(url);
     290        /* if contains phpThumb.php */
     291        var is_thumb = url.indexOf('/src/thumb/phpThumb.php') !== -1;
     292
     293        if (is_thumb) {
     294            path['thumb'] = true;
     295
     296            url.split('?')[1].split('&').forEach(function(v){
     297                var tmp = v.split('=');
     298
     299                /* we have the width, height, quality and zoom-crop */
     300                if (tmp[0] === 'w' || tmp[0] === 'h' || tmp[0] === 'q' || tmp[0] === 'zc') {
     301                    tmp[1] = parseInt(tmp[1], 10);
     302                    /* not a numeric value, don't consider */
     303                    if (isNaN(tmp[1])) {
     304                        return;
     305                    }
     306                }
     307
     308                path[tmp[0]] = tmp[1];
     309            });
     310
     311            path['url'] = url;
     312        } else {
     313            path['thumb'] = false;
     314            path['url'] = url;
     315            path['src'] = path['url'];
     316        }
     317
     318        return path;
     319    };
     320
     321    /* public methods */
     322    $.extend(this, {
     323        nonce: nonce,
     324        err: err,
     325        info: info,
     326        minIE10: minIE10,
     327        fakeImageResize: fakeImageResize
     328    });
     329}).call(window.impro = {}, jQuery);
  • image-pro-wordpress-image-media-management-and-resizing-done-right/trunk/src/request/deleteattachment.php

    r546286 r847712  
    2525    impro_base::err(array('msg' => __('There was an error removing the attachment. Please try again later.', 'imagepro')));
    2626} else {
    27     impro_base::ok(array('msg' => __('The attachment has been removed successfully. However, if you would like to recover it, you can at any time restore it from the "Trash".', 'imagepro')));
     27    impro_base::ok(array());
    2828}
  • image-pro-wordpress-image-media-management-and-resizing-done-right/trunk/src/request/getimages.php

    r486474 r847712  
    4242        "id" => $id,
    4343        "name" => $name,
    44         "size" => $size,
     44        //"size" => $size, // not needed for now
    4545        "ext" => $ext,
    46         "url" => $url,
    47         "thumb" => $thumb 
     46        //"url" => $url, // not needed for now
     47        "thumb" => $thumb
    4848    );
    4949   
    5050endwhile;
    5151
    52 foreach($attachments as $f):
    53 ?>
    54 <li data-attachment-id="<?php echo $f['id']?>" data-url="<?php echo $f['thumb']?>" data-ext="<?php echo $f['ext']?>">
    55     <img data-lazy-src="<?php echo $f['thumb']?>" />
    56     <span><?php echo $f['name']?></span>
    57 </li>
    58 <?php endforeach?>
     52/* output as json */
     53header('Content-Type: application/json');
     54echo json_encode(array(
     55    'ok' => true,
     56    'data' => $attachments
     57));
     58exit;
  • image-pro-wordpress-image-media-management-and-resizing-done-right/trunk/src/request/upload.php

    r546286 r847712  
    2121}
    2222
    23 /* write the file in the coresponding location */
     23/* write the file in the corresponding location */
    2424$upload = wp_upload_bits($_GET['name'], NULL, $contents, NULL);
    2525
    2626/* if we have an upload error */
    27 if ($upload['error'] !==false) {
     27if ($upload['error'] !== false) {
    2828    impro_log::LogError("Error uploading " . $_GET['name'] . ". " . $upload['error']);
    2929    impro_base::err(array(
     
    5252    impro_log::LogError("Error uploading " . $_GET['name'] . ". The file was uploaded succesfuly but the attachment could not be added to the posts table");
    5353    impro_base::err(array(
    54         'str' => __("The file was uploaded succesfuly but the attachment could not be added to the posts table", 'imagepro')
     54        'str' => __("The file was uploaded succesfully but the attachment could not be added to the posts table", 'imagepro')
    5555    ));
    5656}
  • image-pro-wordpress-image-media-management-and-resizing-done-right/trunk/src/requirements.php

    r839546 r847712  
    8888            echo __('<div class="error">
    8989                <strong>ImagePro plugin cannot run on this browser!</strong><br/>
    90                 ImagePro currently supports Firefox, Chrome, Safari.<br/>
    91                 The plugin is currently <strong>NOT WORKING</strong>. Use one of the 3 browsers above to use it!
     90                ImagePro currently supports Internet Explorer 10+, Firefox, Chrome, Safari.<br/>
     91                The plugin is currently <strong>NOT WORKING</strong>. Use one of the browsers suggested!
    9292            </div>', 'imagepro');
    9393        }
     
    112112            $limit = intval(sqrt($limit / 4));  // 4 = r g b a
    113113           
    114             echo __('<div class="error">
     114            echo sprintf(__('<div class="error">
    115115                <strong>Low memory limit!</strong>
    116116                ImagePro requires memory to perform image resizing. <br/>
    117                 Large images such as 2600x2000 pixels will not be resized. You will only be able to resize pictures of maximum resolution '.$limit.'x'.$limit.'. Please increase your memory limit!
    118             </div>', 'imagepro');
     117                Large images such as 2600x2000 pixels will not be resized. You will only be able to resize pictures of maximum resolution %sx%s. Please increase your memory limit!
     118            </div>', 'imagepro'), $limit, $limit);
    119119        }
    120120    }
  • image-pro-wordpress-image-media-management-and-resizing-done-right/trunk/src/thumbs.php

    r626279 r847712  
    7373        /* find images that seem to need resizing */
    7474        preg_match_all('%<img [^>]*src=\\\\?[\'"]/[^>]*>%si', $content, $result, PREG_PATTERN_ORDER);
    75        
     75
    7676        impro_log::LogInfo("When saving post id = " . $post_ID . ", " . count($result[0]) . " thumbnails will require processing");
    7777       
  • image-pro-wordpress-image-media-management-and-resizing-done-right/trunk/src/view/css/editor.css

    r414062 r847712  
    1 #impro_editor {
    2    
    3 }
    4 
    5 #vimg-toolbar {
    6     float: left;
    7 }
    8 
    9 #vimg-toolbar-filter {
    10     float: right;
    11 }
    12 
    13 #vimg-search {
    14     width: 80px;
    15 }
    16 
    17 #impro_editor .thumb {
    18     border-radius: 4px;
    19     -moz-border-radius: 4px;
    20     -webkit-border-radius: 4px;
    21     margin-top: 5px;
    22 }
    23 
    24 .impro_right {
    25     float: right;
    26     margin-top: 5px;
    27     width: 200px;
    28 }
    29 
    30 .impro_right .impro_alt, .impro_right .impro_title {
     1#impro_editor .impro_alt, #impro_editor .impro_title {
    312    margin-top: 6px;
    323    margin-bottom: 10px;
    334    width: 97%;
    34 }
    35 
    36 .impro_wide {
    37     float: none;
    38     clear: both;
    39 }
    40 
    41 .impro_width, .impro_height {
    42     width: 45px;
    43     float: float;
    44 }
    45 
    46 label[for=impro_width], label[for=impro_height] {
    47     display: inline-block;
    48     position: relative;
    49     top: -3px;
    50     width: 42px;
    51 }
    52 
    53 .impro_resize_cont {
    54     float: right;
    55     width: 95px;
    56 }
    57 
    58 .impro_size_cont {
    59     float: left;
    60 }
    61 
    62 .impro_resize_label {
    63     display: inline-block;
    64     margin-top: 6px;
    65 }
    66 
    67 .impro_cancel {
    68     float: left;
    69 }
    70 
    71 .impro_preview {
    72     float: right;
    73 }
    74 
    75 .impro_choose {
    76     width: 176px;
    775}
    786
     
    819}
    8210
    83 .impro_info {
    84     color: #666;
    85     line-height: 1.3em;
    86     margin-top: 5px;
    87     text-align: justify;
    88     padding-right: 10px;
     11.impro-editor-wh-error {
     12    background: #ee5555 !important;
    8913}
    9014
    91 .impro_choosebg {
    92     background: #0A0B0B;
    93     border-radius: 7px;
    94     -moz-border-radius: 7px;
    95     -webkit-border-radius: 7px;
     15#impro-preview {
     16    width: 100%;
     17    height: 70px;
     18    background-size: cover;
     19    background-position: center center;
     20    margin-top: 5px;
     21
     22    -webkit-box-shadow: inset 3px -3px 33px -4px rgba(0,0,0,0.83);
     23    -moz-box-shadow: inset 3px -3px 33px -4px rgba(0,0,0,0.83);
     24    box-shadow: inset 3px -3px 33px -4px rgba(0,0,0,0.83);
    9625}
    9726
    98 .impro_choosebg li {
    99     cursor: pointer;
     27#impro-editor-maxwidth-info {
     28    background: #E4F2FF;
     29    padding: 10px;
     30    border-radius: 3px;
     31    margin-left: 23px;
     32    margin-top: 10px;
    10033}
     34
     35.impro-control-group {
     36    margin-bottom: 5px;
     37}
     38
     39#impro-editor-maxwidth-container {
     40    margin-top: 10px;
     41    margin-bottom: 10px;
     42    margin-left: 1px;
     43}
     44
     45#impro-editor-w, #impro-editor-h {
     46    display: inline-block;
     47    width: 65px;
     48}
     49
     50#impro_editor_box .inside {
     51    margin-top: 12px;
     52}
     53
     54#impro_editor > .impro-control-group:first-child {
     55    margin-top: 5px;
     56}
  • image-pro-wordpress-image-media-management-and-resizing-done-right/trunk/src/view/css/folder.css

    r715205 r847712  
     1#impro_folder_box.closed #vimg-toolbar-filter {
     2    display: none !important;
     3}
     4
     5#vimg-toolbar-filter {
     6    float: right;
     7    font-size: 12px;
     8    margin-top: -3px;
     9}
     10
     11#vimg-toolbar-filter input[type="text"],
     12#vimg-toolbar-filter select {
     13    height: 23px;
     14    font-size: 12px;
     15    padding-top: 0;
     16}
     17
     18#vimg-search {
     19    width: 80px;
     20}
     21
    122#vimg-list {
    223    height: 300px;
    324    overflow-y: scroll;
    425    overflow-x: visible;
    5     padding-top: 5px;
     26    padding-bottom: 55px;
     27    transition: background 0.5s;
     28    -webkit-transition: background 0.5s;
    629}
    730
     
    1134#vimg-list ul li {
    1235    float: left;
    13     padding: 5px;
    14     width: 80px;
     36    padding: 10px;
     37    width: 82px;
    1538    height: 100px;
    16     border: 1px solid transparent;
    1739    position: relative;
    18 }
     40    border-radius: 4px;
     41}
     42
    1943#vimg-list ul li:hover {
    20     background: #FAFCA5;
    21     border: 1px solid #E1DC4F;
    22     -moz-border-radius: 5px;
    23     -webkit-border-radius: 5px;
    24     border-radius: 5px;
     44    background: #efefef;
    2545}
    2646
     
    3454}
    3555
    36 #vimg-list ul li[data-ext=png] img, #vimg-list ul li[data-ext=gif] img, #vimg-list ul li[data-ext=jpg] img, #vimg-list ul li[data-ext=jpeg] img {
     56#vimg-list ul li[data-ext="png"] img, #vimg-list ul li[data-ext="gif"] img, #vimg-list ul li[data-ext="jpg"] img, #vimg-list ul li[data-ext="jpeg"] img {
    3757    cursor: move;
    3858}
    3959
    4060#vimg-list li img {
    41     -moz-border-radius: 5px;
    42     -webkit-border-radius: 5px;
    43     border-radius: 5px;
     61    border-radius: 4px;
     62    border: 1px solid rgba(222, 222, 222, 0.8);
    4463}
    4564
     
    4968
    5069.vdragover {
    51     background: #ddd;
    52 }
    53 .vdragover li { border: 1px solid #ddd !important; }
    54 
    55 #impro_menu_container {
    5670    background: #eee;
    57     border: 1px solid #ccc;
    58     -moz-border-radius: 5px;
    59     -webkit-border-radius: 5px;
    60     border-radius: 5px;
    61     padding: 10px;
    62     position: absolute;
    63 }
    64 
    65 .impro_folder_selected {
    66     -moz-border-radius: 5px;
    67     -webkit-border-radius: 5px;
    68     border-radius: 5px;
    69     border: 1px solid #B0CBDA !important;
    70     background: #EEF5F8 !important;
    71 }
    72 
    73 #vimg-toolbar ul li {
    74     float: left;   
    75 }
    76 
    77 #vimg-toolbar ul li a[data-action] {
    78     background: none no-repeat scroll 5px center #EEEEEE;
    79     border: 1px solid #999999;
    80     color: #333333;
    81     display: block;
    82     margin-right: 6px;
    83     padding: 3px 8px 3px 25px;
    84     text-decoration: none;
    85     border-left: 1px solid #dddddd;
    86     border-top: 1px solid #dddddd;
    87 }
    88 
    89 #vimg-toolbar ul li a[data-action]:hover {
    90     background-color: #dddddd;
    91 }
    92 
    93 #vimg-toolbar ul li a[data-action=add] {
    94     background-image: url(../img/add.png);
    95 }
    96 
    97 #vimg-toolbar ul li a[data-action=library] {
    98     background-image: url(../img/library.png);
    99 }
    100 
    101 #vimg-toolbar ul li a[data-action=open] {
    102     background-image: url(../img/open.png);
    103 }
    104 
    105 #vimg-toolbar ul li a[data-action=link] {
    106     background-image: url(../img/link.png);
    107 }
    108 
    109 #vimg-toolbar ul li a[data-action=remove] {
    110     background-image: url(../img/delete.png);
    11171}
    11272
     
    11878    display: none;
    11979}
     80
     81@-webkit-keyframes progress-bar-stripes {
     82    from {
     83        background-position: 40px 0;
     84    }
     85    to {
     86        background-position: 0 0;
     87    }
     88}
     89
     90@keyframes progress-bar-stripes {
     91    from {
     92        background-position: 40px 0;
     93    }
     94    to {
     95        background-position: 0 0;
     96    }
     97}
     98
     99#vimg-progress-wrapper {
     100    height: 20px;
     101    margin-bottom: 20px;
     102    overflow: hidden;
     103    background-color: #F5F5F5;
     104    border-radius: 4px;
     105    -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
     106    box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
     107}
     108
     109#vimg-progress {
     110    float: left;
     111    width: 0;
     112    height: 100%;
     113    font-size: 12px;
     114    line-height: 20px;
     115    color: #FFF;
     116    text-align: center;
     117    background-color: #428BCA;
     118    -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
     119    box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
     120    -webkit-transition: width .6s ease;
     121    transition: width .6s ease;
     122
     123    background-size: 40px 40px;
     124    background-image: linear-gradient(45deg,rgba(255, 255, 255, 0.15) 25%,rgba(0, 0, 0, 0) 25%,rgba(0, 0, 0, 0) 50%,rgba(255, 255, 255, 0.15) 50%,rgba(255, 255, 255, 0.15) 75%,rgba(0, 0, 0, 0) 75%,rgba(0, 0, 0, 0));
     125
     126    -webkit-animation: progress-bar-stripes 2s linear infinite;
     127    animation: progress-bar-stripes 2s linear infinite;
     128}
     129
     130#vupload {
     131    cursor: pointer !important;
     132    position: relative;
     133}
     134
     135#vupload input[type="file"] {
     136    opacity: 0.01;
     137    position: absolute;
     138    top: 0;
     139    left: 0;
     140    bottom: 0;
     141    right: 0;
     142    cursor: pointer;
     143}
     144
     145#vupload div {
     146    width: 50px;
     147    margin: 0 auto;
     148    text-align: center;
     149    color: #888 !important;
     150}
     151
     152#vupload div span {
     153    display: block !important;
     154    background: #fff !important;
     155    border: 2px solid #0fabfc;
     156    width: 40px !important;
     157    height: 40px !important;
     158    border-radius: 40px !important;
     159    font-size: 24px !important;
     160    font-weight: bold !important;
     161    color: #0fabfc !important;
     162    text-align: center !important;
     163    line-height: 35px !important;
     164    margin: 0 auto !important;
     165}
     166
     167#vupload:hover {
     168    background: #fff !important;
     169}
     170
     171#vupload:hover div {
     172    color: #444 !important;
     173}
     174
     175#vupload:hover div span {
     176    color: #0C70A3 !important;
     177    border: 2px solid #0C70A3 !important;
     178}
     179
     180#vimg-toolset {
     181    border-radius: 4px;
     182    height: 100px;
     183    position: absolute;
     184    left: 0;
     185    right: 0;
     186    top: 73px;
     187    z-index: 2;
     188    display: none;
     189}
     190
     191#vimg-list #vimg-toolset {
     192    display: block;
     193}
     194
     195#vimg-toolset > div {
     196    position: absolute;
     197    top: 0;
     198    left: 0;
     199    bottom: 0;
     200    right: 0;
     201    background: #efefef;
     202    border-radius: 4px;
     203    padding: 8px;
     204}
     205
     206#vimg-toolset > div > a {
     207    cursor: pointer;
     208    text-decoration: none;
     209    display: block;
     210    color: #656565;
     211    padding-bottom: 4px;
     212    padding-left: 20px;
     213    font-size: 11px;
     214    background-repeat: no-repeat;
     215}
     216
     217#vimg-toolset > div > a:hover {
     218    color: #050505 !important;
     219    text-decoration: underline;
     220}
     221
     222
     223
     224#vimg-toolset #vimg-toolset-delete {
     225    background: #C00;
     226    color: #FFF;
     227    font-size: 16px;
     228    font-weight: bold;
     229    border-radius: 16px;
     230    width: 16px;
     231    height: 16px;
     232    text-align: center;
     233    line-height: 14px;
     234    right: -7px;
     235    top: -80px;
     236    position: absolute;
     237    padding-left: 0 !important;
     238    padding-bottom: 0 !important;
     239}
     240
     241#vimg-toolset > div > #vimg-toolset-delete:hover {
     242    background: #e00 !important;
     243    color: #fff !important;
     244    text-decoration: none !important;
     245}
     246
     247#vimg-toolset #vimg-toolset-add {
     248    background-position: 1px 1px;
     249    background-size: 14px 14px;
     250    background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA8ElEQVQ4T2NkwAQ6QKFkIHYFYnGo9AsgvRuI5wDxNWQtjEgcNiC7D4gzgJgZi8Egob9APBWIS4D4N0gAZgBI8xaorTj0ogjvBPL8gPgXzICZQE4aMTqR1EwDsrNBBugC8QUgZsJiAMyC/1jkQN7RAymYDMQ5OGzHZwBIy0SQAlCoapJpwBWQAZ+AmBfJAOSYwWYusnc+gRR/AWJuMg34TKkXroIMACWeQjLDoAdkgDYQXwRibKkPXyz8ASUBmIIJQE4+iQmpB6i+FGYAK5ADSspuRBqyA6jOF4j/UC0zIVsMy84g1yhBJe4C6V1AjJGdAVgPMQjJK3mLAAAAAElFTkSuQmCC');
     251}
     252
     253#vimg-toolset #vimg-toolset-edit {
     254    background-position: 0px 1px;
     255    background-size: 16px 16px;
     256    background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAFTElEQVR4Xu2dsU7bUBSGjVSJFYZKbLHUCrYmUiuYgA4VG2GoGKFSCyMdCnkLVKkwQisVRtShbIhWKm+QsCF1CE8Ab+ByAdOQOMn1tc+5xz4/K7F9z/99PrYPIRkJ8KM6gRHV1aP4AAIolwACQADlCSgvHx0AAihPQHn56AAQQHkCystHB4AAyhNQXj46AARQnoDy8tEBIIDyBJSXjw4AAZQnoLx8dAAIoDwB5eWjA0AA5QkoLx8dgFiAq6urqHV+fnuUsFIJwjAUlbmoxRCzYN/994ODaLPRCK6vrx+O/XFjI/i8vS0mdzELYadDfEAD/8P6euJRVldWgm/7+yKyF7EIYhbsux8EP16MFAkgQM562MCXJAEEyFGANPClSAABchLABb4ECSBADgJkge9bAgiQUYA84PuUAAJkEKDdbkfPp6Yy7KF3U+6nAwiQEV+eHcBHJ4AAGQUwmxdZAgiQUgAz2x8fH+/JragSQIAUAsSz/V8nJ0GtViuFBBDAUoDOM3xsbCzglODr3l7wbnWVhBXJTi0zLczLkto7pwRL9Xrw4+iIhBXJTgtD1mKhg67tXBLMz80Fv09PSViR7NQi10K8xObGjkMCytkABOijog38eFNqCf5eXJC9kwgCJAiQBj61BJQ3gGbtEKBLABf4VBJQw4cAOcLPWwIO+BCgQ4AsZ373VSTrPQEXfAhwTy5P+Fk7ASd8CED0hxxXCbjhqxeA4sx3vRz4gK9aAA74tp3AvI5q1j9s4qbyMZATvo0EwyBR/l6dAD7gS5ZAlQA+4UuVQI0AEuDHEvi64Uu6lKgQAPD730WUXgDAH3wLWWoBAH/480NpBQD84fBLOwgCfDv4pRQA8O3hl04AwE8Hv1QCAH56+KURAPDd4JdCAMB3h194AQA/G/xCCwD42eEXVgDAzwd+IQUA/PzgF04AwM8XfqEEAPz84RdGAMCngV8IAQCfDr54AQCfFr5oAQCfHr5YAQCfB75IAQCfD744AQCfF74oAQCfH74YAQDfD3wRAgC+P/jeBaD4vH3XOCX9u5ZrDS7bef+/AAkdQCt87x0gNtanBJrhexHgz9lZVH3xIuj+zH0fEmiH70WAt8vLUfvy8vbj1n1KAPh3/Zf9HuDJ6GhkDlytVr1JAPj/bxdZBTDt/83CwsPRfUgA+I+fFVgF+LS1Fe3s7j5aAacEgN/7oMgqwMvp6ajVavWsgkMCwE+eErAJYL5t6+nERN9ZBaUEgN9/RMQmgM1jHoUEgD94PsgmwPu1tejg8HDotDJPCQB/aNx8j4HPJiejy5vnf5ufPCQAfJukmeYAzWYzejUzY7ei+1dlkQDw7aNmuQR82dmJNhsN+1VlkADw08XMIoAZ//48Pk63MgcJAD99xCwCxOPf9Mu728LmcgD4bumSC9A9/nVb5mAJzD59fd6+az1StiMXIGn861p8v07guj9sx/AU0G/86xo+JHBNLnk70g4wbPzrWgrllym7rqmo25EKYDP+tQ3OnPn1xcXAwH89P0+6bts1leF1pEHajn+TgqxUKsFSvR7Mzc7eQu9+91AZwpdQA6kAaca/5ts24zPcAA/DkHRtEsKXsAaykG3Gv51neK1WI1uLhKClroEs9KTxr7mOm7PbnOm4jstQgkwAM/5t3rz7JwaO67gM4N2rIBPAPALixk0m9M5VkQkgv3Ss0CQAAZR7AAEggPIElJePDgABlCegvHx0AAigPAHl5aMDQADlCSgvHx0AAihPQHn56AAQQHkCystHB4AAyhNQXj46AARQnoDy8tEBIIDyBJSXjw4AAZQnoLz8fxiAE645as90AAAAAElFTkSuQmCC');
     257}
     258
     259#vimg-toolset #vimg-toolset-link {
     260    background-size: 16px 16px;
     261    background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAC70lEQVRYR+2XX4QWURjGdy0RsUR0ka66yLJEiVKKiGVvyhKb2JQipUSUKCU2XW021qbsKqVI3USRIkWKRF111VVESikioufHOXq9zX7nzMw3a5fv5TEz5ztzzm+e8+c9X3fXHI/uOc7X1QGsO0IdB+eLgxsEukNaIr2TLknfc+BnY4jHBHLYwXzU83bpVQqyacArAtgzAwQODkgvWkE2CejhcO2T1C8tCFBJyKYAJwWwzzhzU/d7pV/SaulBmI9U+RmcfF7kZBOA4+rooOlsOsD9MWV9un8sLQ1lX3VdKX32kO0G3KYO7ibg4s8M9UtpYShgZR9qGvCNOlgVOnmq6+aiYTNlfAwfRbyW1jQN+EUdLA6dMOeuJgBxcG2o80TXLU0DRgeZS7i3SWKDZvjuuM5P6vmcKSv8oHbPQWDYmHFil3Q8ALDFLDMwlI+a50e631rkdrsB6YOVSeaIcJQx1DhEeDjmKhs2W9B/URVwnVoakhZJ76XLEvsZgTMWjqFldbL/DQdFkJZwVKoC6AFoh3S1UWJOFcHdD4DWoSRcFUCfIWgjLgg75yjHuQMSWQP3bLBiB6XCYbUVyzjo4T6oISY3K5Sh887tVNlvKYKTPXiH+XhespnF8f97zAX0iX9aTewPAGd0PWV6wLkIN2PHuT/kAHq462p8d3CgV9dvDo4FMSWxatleakUKkBMJQxvDwlHWI5ENmGO3pSNSXBAM44ladHo5BfhWdUjqBKff9cE52y/JfoXEUd6u8JxcnORPAf5QC+x1xGnpbKLFZ/qd/x/EQ4kNuFakAK2DKUd8hmCLmahFp5dTgCOqw4SPUXhm04/HpAumHvscuTVrK2n1ESlA3r0msZfFuKgbFkMMD5eVIXKdzQFkpd6QOKnEuKcb5hg5ecQ5l5Uh2glIW0WQvo/s9JULR70cB2N7QN6SOMXMClxZwAh1VDec95ZLZApWanZuLeNeVcCyfdSqX2aIa3VU9eUOYFXn4nsdB+s6+Bd5CZIpwD7uTAAAAABJRU5ErkJggg==');
     262}
     263
     264#vimg-toolset #vimg-toolset-open {
     265    background-position: 0px 1px;
     266    background-size: 16px 16px;
     267    background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA0ElEQVQ4T2NkoBAwUqifAWTAf0oMgRlArkv+k2pAF9C1KUA8C4grQK5HN0AJKLgdiBuAeDkWr30GivEAMYjmw2YAyORUIH4FxIpA/A3NEJAL8oB4AjYXsAIFnwOxMFRTPpCeRCCAUbzgAlS8G0nDQyBbBYj/QL3kCaRDgPgxkhoUA2qAEs1oNoIC6jAQ7wNidiC+DcT2UJeClKIYsB4oEEDAySDpC0BsC8Rf0A14AhSQJsIAkJKdQOwDxL9JTQfo5sO9QKTFmMrITcJwkyg2AAB2fTIFnoZD8QAAAABJRU5ErkJggg==');
     268}
  • image-pro-wordpress-image-media-management-and-resizing-done-right/trunk/src/view/editor.php

    r682630 r847712  
     1<div id="impro-preview"></div>
    12<div id="impro_editor">
    2 <img class="thumb" />
    33
    4 <div class="impro_right">
    5     <label><?php _e('Alternative text:', 'imagepro')?>
    6     <input type="text" class="impro_alt" />
    7     </label>
    8    
    9     <label><?php _e('Title text:', 'imagepro')?>
    10     <input type="text" class="impro_title" />
    11     </label>
    12    
     4    <div class="impro-control-group">
     5        <label><?php _e('Image size preset', 'imagepro') ?></label>
     6        <select id="impro-editor-size">
     7            <optgroup label="Wordpress defined">
     8                <option value="__full"><?php _e('Full size', 'imagepro') ?></option>
     9                <?php
     10                $thumbnailSizes = @self::list_thumbnail_sizes();
     11                foreach($thumbnailSizes as $name => $attrs):
     12                    ?><option value="<?php echo addslashes($name) ?>" data-preset-width="<?php echo $attrs[0]?>" data-preset-height="<?php echo $attrs[1]?>"><?php echo ucfirst(htmlentities($name)) ?> (<?php echo $attrs[0]?>x<?php echo $attrs[1]?>)</option><?php
     13                endforeach;
     14                ?>
     15            </optgroup>
     16            <optgroup label="User defined">
     17                <option value="__custom" selected="selected"><?php _e('Custom size', 'imagepro') ?></option>
     18            </optgroup>
     19        </select>
     20    </div>
     21
     22    <div class="impro-control-group">
     23        <label><?php _e('Manually change image size', 'imagepro') ?></label><br/>
     24        <input id="impro-editor-w" type="number" />
     25        <?php _e('width', 'imagepro') ?> x
     26        <input id="impro-editor-h" type="number" />
     27        <?php _e('height', 'imagepro') ?>
     28    </div>
     29
     30    <div id="impro-editor-maxwidth-container">
     31        <label><input id="impro-editor-maxwidth" type="checkbox" /> <?php _e('Override size restriction', 'imagepro') ?></label>
     32        <br/>
     33        <div id="impro-editor-maxwidth-info">
     34<?php _e('The current WordPress theme allows images up to %maxwidth% pixels in width.<br/> Use the option above to disable this restriction for the current image. However, the image will not be responsive anymore.', 'imagepro') ?>
     35        </div>
     36    </div>
     37
     38    <hr/>
     39
    1340    <label><?php _e('Align:', 'imagepro')?>
    1441    <select class="impro_align">
     
    2552    <?php _e('Open the full picture on click', 'imagepro')?>   
    2653    </label>
    27    
    28     <br/><br/>
    29     <input type="button" class="button-primary impro_choose" value="<?php _e('Select another picture', 'imagepro')?>" />
    30     <br/>
    31     <div class="impro_info"><?php _e('Select a new image from the "Available images" panel to replace the current one', 'imagepro')?></div>
    32 </div>
     54
     55    <hr/>
     56
     57    <label><?php _e('Alternative text:', 'imagepro')?>
     58        <input type="text" class="impro_alt" />
     59    </label>
     60
     61    <label><?php _e('Title text:', 'imagepro')?>
     62        <input type="text" class="impro_title" />
     63    </label>
    3364
    3465<div class="clear"></div>
  • image-pro-wordpress-image-media-management-and-resizing-done-right/trunk/src/view/folder.php

    r715205 r847712  
    1 <div id="vimg-progress-wrapper" style="border: 1px solid #069; display: none;">
    2     <div id="vimg-progress" style="width: 0; height: 22px; background: #08b; display: none;"></div>
     1<div id="vimg-progress-wrapper" style="display: none;">
     2    <div id="vimg-progress"></div>
    33</div>
    44
    5 <div id="vimg-toolbar">
    6     <ul>
    7         <li><a data-action="add" href="#"><?php _e('Add to editor', 'imagepro')?></a></li>
    8         <li><a data-action="library" href="#"><?php _e('Edit in library', 'imagepro')?></a></li>
    9         <li><a data-action="open" href="#"><?php _e('Open', 'imagepro')?></a></li>
    10         <li><a data-action="link" href="#"><?php _e('Show link', 'imagepro')?></a></li>
    11         <li><a data-action="remove" href="#"><?php _e('Delete', 'imagepro')?></a></li>
    12     </ul>   
     5<div id="vimg-toolset">
     6    <div>
     7        <a data-action="remove" id="vimg-toolset-delete">&ndash;</a>
     8
     9        <a data-action="add" id="vimg-toolset-add"><?php _e('Add to post', 'imagepro') ?></a>
     10        <a data-action="library" id="vimg-toolset-edit"><?php _e('Edit', 'imagepro') ?></a>
     11        <a data-action="open" id="vimg-toolset-open"><?php _e('Open', 'imagepro') ?></a>
     12        <a data-action="link" id="vimg-toolset-link"><?php _e('Get link', 'imagepro') ?></a>
     13    </div>
    1314</div>
    1415
    15 <div id="vimg-toolbar-filter">
    16     <label for="vimg-filetype"><?php _e('Show', 'imagepro')?></label>
     16<div id="vimg-toolbar-filter" style="display: none;">
     17    <label for="vimg-filetype"><?php _e('Show', 'imagepro')?>&nbsp;</label>
    1718    <select id="vimg-filetype">
    1819        <option value="" style="font-weight: bold;"><?php _e('All files', 'imagepro')?></option>
     
    2324    </select>
    2425   
    25     <label for="vimg-search"><?php _e('Search', 'imagepro')?></label>
     26    <label for="vimg-search">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<?php _e('Search', 'imagepro')?></label>
    2627    <input type="text" id="vimg-search" />
    2728
     
    3233
    3334<div id="vimg-dbg-content">
    34     Copy &amp; paste the contents of the textarea below when submitting a support request at <a target="_blank" href="http://www.mihaivalentin.com/about-me/#contact">http://www.mihaivalentin.com/about-me/#contact</a><br/>The information will be used only for troubleshooting purposes and may reveal some information about your WordPress setup.
     35    <?php _e('Copy &amp; paste the contents of the textarea below when submitting a support request at <a target="_blank" href="http://www.mihaivalentin.com/about-me/#contact">http://www.mihaivalentin.com/about-me/#contact</a><br/>The information will be used only for troubleshooting purposes and may reveal some information about your WordPress setup.', 'imagepro') ?>
    3536    <textarea style="width: 100%; height: 500px;">
    3637
Note: See TracChangeset for help on using the changeset viewer.