Jeavon / Slimsy

Effortless Responsive & Lazy Images with LazySizes and Umbraco
MIT License
72 stars 23 forks source link

Feature Request: ConvertImgToSrcSet for media.cshtml #33

Closed craigs100 closed 1 year ago

craigs100 commented 4 years ago

Create a version of ConvertImgToSrcSet that can be applied safely to media.cshtml so the Slimsy magic can work when adding an Image in a grid layout. Or, if it's already possible, document how it's done.

Jeavon commented 4 years ago

Hey Craig,

If you are using the Picture Helper then I think like this

@inherits UmbracoViewPage<dynamic>

@if (Model.value != null)
{
    var udi = Model.value.udi.ToString();

    var item = Umbraco.Media((string)udi);

    if (item != null)
    {
        var altText = Model.value.altText ?? Model.value.caption ?? string.Empty;

        int width = 160;
        int height = 0;

        if (Model.editor.config != null && Model.editor.config.size != null)
        {
            bool successWidth = Int32.TryParse(Model.editor.config.size.width.ToString(), out width);
            bool successHeight = Int32.TryParse(Model.editor.config.size.height.ToString(), out height);
        }

        @SlimsyHelper.RenderPicture(Url, item, width, height, altText)
    }
    else
    {
        // log something maybe...
    }
    if (Model.value.caption != null)
    {
        <p class="caption">@Model.value.caption</p>
    }
}

I'm not to sure how you get values into Model.editor.config.size, do you?

craigs100 commented 4 years ago

Thanks Jeavon. I just tried it and find that "SlimsyHelper" doesn't exist in the current context. I'm using the v3.0.0-beta5 version.

Jeavon commented 4 years ago

SlimsyHelper is a Razor helper, you can copy if from https://github.com/Jeavon/Slimsy/blob/dev-v3/TestSite/App_Code/SlimsyHelper.cshtml to your own App_Code folder if you want to use it.

Or maybe you already have your own Razor helper?

craigs100 commented 4 years ago

Thanks for the steer Jeavon. I'm altering the code to pass through the crop I need. However, it'd be great if Slimsy had a method you can apply to media.cshtml to simply handle the case where an image is added to a grid, in the same way an RTE or Headline is added, if you get my drift :)

Here's what I ended up with :- App_Code/SlimsyHelper.cshtml


 @using System.Web.Mvc
 @using Slimsy
 @using Umbraco.Core
 @using Umbraco.Core.Models.PublishedContent
 @using Umbraco.Web
 @helper RenderPicture(UrlHelper urlHelper, string cropAlias, IPublishedContent image, string altText = "")
 {
 if (image != null)
 {
     string defaultMimeType;

     var umbracoExtension = image.Value<string>(Constants.Conventions.Media.Extension);

     var defaultFormat = umbracoExtension;

     switch (umbracoExtension)
     {
         case "jpg":
             defaultMimeType = "image/jpeg";
             break;
         case "png":
             defaultMimeType = "image/png";
             break;
         case "gif":
             defaultMimeType = "image/gif";
             break;
         default:
             defaultMimeType = "image/jpeg";
             defaultFormat = "jpg";
             break;
     }

     var imgSrcSet = urlHelper.GetSrcSetUrls(image, cropAlias); //urlHelper.GetSrcSetUrls(image, width, height, Constants.Conventions.Media.File, outputFormat: defaultFormat);

     var imgSrc = urlHelper.GetCropUrl(image, cropAlias); //urlHelper.GetCropUrl(image, width, height, furtherOptions: "&format=" + defaultFormat);

     if (altText == "")
     {
         altText = image.Name;
     }

         <picture>
             <source data-srcset="@imgSrcSet" srcset="@imgSrc" type="@defaultMimeType" data-sizes="auto" />
             <img src="@imgSrc"
                  data-src="@imgSrc"
                  class="lazyload"
                  data-sizes="auto"
                  alt="@altText" />
         </picture>

     }
 }

and Media.cshtml:-

@inherits UmbracoViewPage<dynamic>

 @if (Model.value != null)
 {
   var udi = Model.value.udi.ToString();

   var item = Umbraco.Media(udi);

   if (item != null)
   {
       var altText = Model.value.altText ?? Model.value.caption ?? string.Empty;

       if(Model.value.caption != null) {
             altText = Model.value.caption.ToString();
       }

         @SlimsyHelper.RenderPicture(Url, "SideImage", item, altText)

         if (Model.value.caption != null)
         {
             <p class="caption">@altText</p>
         }
     }
 }
Jeavon commented 4 years ago

That looks good @craigs100 All working?

The problem with a method for this is that not all grids are implemented the same. Having this example is good though. Perhaps we should do more to highlight the Razor helper and how to update rte.cshtml and media.cshtml...?

Happy to hear any suggestions...

craigs100 commented 4 years ago

Not too sure tbh. The tricky bit was the caption funnily enough. I keep getting "System.Net.WebException: The request was aborted: The connection was closed unexpectedly." Wondering if that's due to putting the razor helper in App_Code. It's only cleared by touching web.config, then it appears to work ok. So still looking into it.

The output is:-

<picture>
            <source data-srcset="/media/ycjb305h/landlords.jpg?anchor=center&amp;mode=crop&amp;quality=90&amp;width=160&amp;height=107&amp;rnd=132326448829100000 160w" srcset="/media/ycjb305h/landlords.jpg?anchor=center&amp;mode=crop&amp;quality=90&amp;width=160&amp;height=107&amp;rnd=132326448829100000 160w" type="image/jpeg" data-sizes="auto" sizes="300px">
            <img src="/media/ycjb305h/landlords.jpg?anchor=center&amp;mode=crop&amp;width=300&amp;height=200&amp;rnd=132326448829100000" data-src="/media/ycjb305h/landlords.jpg?anchor=center&amp;mode=crop&amp;width=300&amp;height=200&amp;rnd=132326448829100000" class="lazyautosizes lazyloaded" data-sizes="auto" alt="Keys" sizes="300px" width="300" height="201">
</picture>

All I was imagining was something to handle a media grid item as it exists out of the box, nothing fancy. Those that need fancy can usually sort it out themselves given a bit of a clue ;)

craigs100 commented 4 years ago

Just as I was putting the site to staging I realised I was stuck with a crop. The @SlimsyHelper.RenderPicture(Url, "SideImage", item, altText) means it's not responsive to the grid layout itself. If there was a way to know which layout it was in it wouldn't be a problem as you could just select the appropriate crop for the layout section. So this is helpful but not the final answer as far as the grid is concerned.

Update

Got around this by saving the row.name to ViewData in the grid/bootstrap3.cshtml and detecting it in grid/editors/media.cshtml and switching out the crop based on the row.name (solution courtesy of abjerner & janae)