When you use the YUI editor to resize an image, it uses inline styles to do the work

<img  style="width: 100px; height: 70px;" alt="" src="/files_saw/images/my_image.jpg" />

but the Drupal HTML filter removes this style information upon output.

There are security reasons to remove inline styles apparently, so the easiest quick fix might be to write an input format filter, applied before the Drupal HTML filter that converts the inline css to html tags which will then get through the Drupal HTML filter.

<img  width=100px height=70px alt="" src="/files_saw/images/my_image.jpg" />

Comments

jeffcd’s picture

Assigned: Unassigned » jeffcd
Priority: Normal » Minor

This could be a bit tricky to handle. I will look and see if there is a setting to force the editor not to use style tags and update accordingly.

muhleder’s picture

Yes, I did have a look at making a custom filter that would turn the style tags into html attributes, but it was getting a bit complicated with all the css properties that can be applied using the yui editor.

I did manage to hack the core html filter to allow styles. You have to alter Line 1489 to add width: height: etc to allowed 'protocols' in attribute value and Line 1387 to allow 'style' attribute through. Not the best way of going about things but it could be a start for someone to make a custom filter that allows styles through. The problem is that you also need to prevent css expressions because IE will run javascript through them, which is a security hole. So some sort of regex to remove expression(*) would be required to run through the inline style at a minimum. Not sure if there are any other issues with allowing inline styles.

I ended up modifying the module javascript to link up to imagecache, have to hard code the file path and imagecache presets, not sure how that could be set using an admin interface in drupal, but I think it's quite nice for the end users, they get the images auto-resized on upload, and have a drop down box to pick small, medium or large. Used a bit of css to hide the size inputs on the image editor for now, I'm pretty sure that they can be switched off using the javascript.

Javascript function to replace yui_img_uploader function from the module's javascript

function yui_img_uploader(rte, upload_url, upload_image_name, base_path) {
  rte.addListener('toolbarLoaded', function() {
    rte.toolbar.addListener('insertimageClick', function(o) {
      try {
        var imgPanel = new YAHOO.util.Element('yui-editor-panel');
        imgPanel.on ('contentReady', function() {
          try {
            var Dom = YAHOO.util.Dom;
						Dom.get('insertimage_url').STR_IMAGE_URL = "true";
            var label = document.createElement('label');
            label.innerHTML = '<strong>Upload:</strong>' +
              '<input type="file" id="insertimage_upload" name="' + upload_image_name +
              '" size="10" style="width: 20%"/>' +
              '<a href="#"  id="insertimage_upload_btn" style="width: 20%; margin-left: 10em;">Upload Image</a>' +
              '</label>';

							//This section gives us the drop down to select the size we want.
							//Imagecache presets are hardcoded here.
							var size_select = document.createElement('label');
	            size_select.innerHTML = '<strong>Image size:</strong>' +
	              '<select id="image_size">' +
								'<option value="yui_small">Choose size..</option>' +
								'<option value="yui_small">Small</option>' +
								'<option value="yui_medium">Medium</option>' +
								'<option value="yui_large">Large</option>' +
								'</select>' +
	              '</label>';

            var img_elem=Dom.get('insertimage_url');
            Dom.getAncestorByTagName(img_elem, 'form').encoding = 'multipart/form-data';
            Dom.insertAfter(label, img_elem.parentNode);

						//This section puts the size selector in place.
						Dom.insertAfter(size_select, label);
            
						//Listener event for the size selector change
						YAHOO.util.Event.on('image_size', 'change', function(ev) {
							var currentUrl =  Dom.get('insertimage_url').value;
							if (currentUrl != '') {
								//get new preset
								var imageCachePreset = Dom.get('image_size').value;
								//strip base file path
								var preset_end=currentUrl.indexOf('/imagecache/');
								var pathToImagecache = currentUrl.substring(0,preset_end+12);
								//strip old preset and add new one								
								var originalUrl = currentUrl.substring(preset_end+12);
								var slash_pos = originalUrl.indexOf('/');
								originalUrl = originalUrl.substring(slash_pos+1);
								newUrl = pathToImagecache + imageCachePreset + '/' + originalUrl;
								
								// Start of code to update the url in rte image editor, 
								// and call imagecache to generate the new size if needed.
								// Code from yui documentation for YAHOO.util.Connect.asyncRequest
								var args = [newUrl];
								var responseSuccess = function(o){
									newUrl = o.argument;
									Dom.get('insertimage_upload').value = '';
									Dom.get('insertimage_url').value = newUrl;
									Dom.get('insertimage_url').focus();
									Dom.get('insertimage_upload').focus();
								};
								var responseFailure = function(o){
									alert("Could not get resized image, please try again.");
								}
								var imageCacheLoaded =
								{
								  success:responseSuccess,
								  failure:responseFailure,
								  argument:args
								};
								//Get the new image from imagecache, then load in RTE to ensure imagecache has created the image
								var transaction = YAHOO.util.Connect.asyncRequest('GET', newUrl, imageCacheLoaded );
							}
							
						});
                                  
            YAHOO.util.Event.on('insertimage_upload_btn', 'click', function(ev) {
              YAHOO.util.Event.stopEvent(ev); // no default click action
              YAHOO.util.Connect.setForm(img_elem.form, true, true);
              var c = YAHOO.util.Connect.asyncRequest('POST', upload_url, { upload:
			    function(r) {
                  try {
                    resp = r.responseText.replace( /<hints .*/i, '');
                    var o = eval('('+resp+')');
                    if (o.status == 'UPLOADED') {
											//Now the original image has been uploaded, alter the url to 
											//be the imagecache path for the size we want.
											var orginalUrl = base_path + o.image_url;
											var imageCachePreset = Dom.get('image_size').value;
											//Hard coded file path. Should replace this with variable, but how?
											var imageCacheInsert = '/files_saw/imagecache/' + imageCachePreset + '/';
											var newUrl = orginalUrl.replace('/files_saw/',imageCacheInsert);
											
											// Start of code to update the url in rte image editor, 
											// and call imagecache to generate the new size if needed.
											// Code from yui documentation for YAHOO.util.Connect.asyncRequest
											var args = [newUrl];
											var responseSuccess = function(o){
												newUrl = o.argument;
												Dom.get('insertimage_upload').value = '';
												Dom.get('insertimage_url').value = newUrl;
												Dom.get('insertimage_url').focus();
												Dom.get('insertimage_upload').focus();
											};
											var responseFailure = function(o){
												alert("Could not upload image, please try again.");
											}
											var imageCacheLoaded =
											{
											  success:responseSuccess,
											  failure:responseFailure,
											  argument:args
											};	
											//Get the new image from imagecache, then load in RTE to ensure imagecache has created the image
											var transaction = YAHOO.util.Connect.asyncRequest('GET', newUrl, imageCacheLoaded ); 

                    }
                    else {
                      alert ("Upload Failed: " + o.status);
                    }
                  }
                  catch (eee) {
                    YAHOO.log(eee.message, 'error');
                  }
                }
              });

              return false;
            });
          }
          catch (ee) {
            YAHOO.log(ee.message, 'error');
          }
        });
      }
      catch (e) {
        YAHOO.log(e.message, 'error');
      }
    });
  });
}
miche’s picture

1. HTML Filter stripping out "style" attributes.
-- I am working on a module that is a filter to use with YUI. It closely replicates the standard HTML Filter.

2. Image size pre-sets
-- I am interested in the above javascript, but didn't have any luck with it working. Has anyone else tried it?

muhleder’s picture

StatusFileSize
new31.28 KB

Here's a zipped copy of the module as it's being used. It has a load of other hacks applied I think, pretty much all in yui_editor.js

The values yui_small etc in the select need to match your imagecache preset names.

I quite like the ease of use, but I think it could do with some error handling, have had a report of it working intermittently under IE.

muhleder’s picture

Don't know if you've seen this, but someone's having a go at putting a filter together that allows inline style.

http://groups.drupal.org/node/15979

miche’s picture

muhleder, thanks for the link!

les lim’s picture

Here's the link to the project referenced in #5:

http://drupal.org/project/wysiwyg_filter

looks like there's only a 6.x release at the moment.

chrisyates’s picture

@muhleder - I modified your code in yui_editor.js and yui_editor.module to allow for dynamically querying imagecache presets as well as file upload directories. I just need to finish the js detection of imagecache's existance, and I'll post up some code shortly. This is for version 5.x-2.6-96.

chrisyates’s picture

Status: Active » Needs review
StatusFileSize
new7.95 KB

Ok, here's my patch against 5.x-2.6-96.

Note that I've done some of the modifications to yui_editor.js in jQuery, as I'm not familiar with YUI's ajax methods, and jQuery is available out of the box on Drupal 5 anyway.

EDIT: I've got an extraneous console.log that needs to be removed.