Modifying a link_to hover image in Rails 4 using the asset pipeline

Note: The information provided here is intended for beginners.

While attempting to change the image in a link_to element upon hovering over it, I encountered difficulty achieving the desired effect using CSS. Below, I share the solution I implemented to resolve this issue.

This is the link_to code snippet:

  <%= link_to image_tag('1487789814_back.png'),
      {controller: @controller_action_hash_from_params[:controller],
        action: @controller_action_hash_from_params[:action]},
        sql_text: @sql_text,
      :id => "ralph-back-button-black-img", :class => "ralph-fieldset-back-button" %>

The image '1487789814_back.png' is a simple PNG file located in app/assets/images, depicting a black arrow pointing left. Additionally, '1487789814_back_red.png' from the same directory features a red arrow pointing left. My goal was to have the red arrow display when hovering over a fieldset containing the black arrow.


Identifying the Issue:

The HTML generated by the aforementioned link_to code snippet appeared as follows:

<img src="https://localhost:3000/assets/1487789814_back-731afaae70e04062b25988079e4ef8ab4e6b523f4ac11ff7d142a9ff01e63455.png" alt="1487789814 back">

Please note that the URL 'https://localhost:3000/assets/1487789814_back-731afa...3455.png' may not be accessible as it is an automatically assigned filename by Rails.

Analysis and Resolution Approach:

The issue partly arises because, according to my understanding, CSS cannot override certain HTML attributes such as the 'src' attribute of an image. Hence, conventional CSS techniques like using ':hover' would not work in this scenario. To address this challenge, resorting to JavaScript or jQuery was necessary.


Solution Implemented:

I wish to clarify that while the solution I present worked within my Rails 4 environment, I do not claim it to be the definitive or optimal answer.

If you are utilizing the asset pipeline feature in your Rails project (applicable to versions including Rails 3 and Rails 5), the user-friendly image filenames like '1487789814_back.png' undergo conversion by the asset pipeline system before deployment, resulting in hash-appended filenames. Thus, gaining access to the red arrow image requires knowledge of its corresponding filename within the asset pipeline.

To establish this mapping between the friendly name and asset pipeline name, I leveraged a hidden div styled with 'display:none'.

Here's how it was done in ERB:

<%# This div has display:none.
    We do this in order to preload the images_path as well as create a "map"
      between the friendly name and the asset pipeline name
%>
<div class='ralph_preload'>
  <%= image_tag('1487789814_back.png',      options={class:'ralph_preload_class', id:'1487789814_back'}) %>
  <%= image_tag('1487789814_back_red.png',  options={class:'ralph_preload_class', id:'1487789814_back_red'}) %>
</div>

The resulting HTML produced by the above ERB segment is as follows:

<div class="ralph_preload">
  <img class="ralph_preload_class" id="1487789814_back" src="/assets/1487789814_back-731afaae70e04062b25988079e4ef8ab4e6b523f4ac11ff7d142a9ff01e63455.png" alt="1487789814 back">
  <img class="ralph_preload_class" id="1487789814_back_red" src="/assets/1487789814_back_red-bbd0f2e34f3401cc46d2e4e1e853d472d8c01c9a75f96d78032738bd01b2133b.png" alt="1487789814 back red">
</div>

The associated CSS for this setup is defined as:

.ralph_preload {
  display: none;
}

Furthermore, jQuery scripting was incorporated to facilitate switching the black arrow image to the red variant upon hover:

<script type="text/javascript">
  function get_precache_myStruct_array(outer_div_class){
    var myStruct_array = [];
    $('.'+outer_div_class).find(".ralph_preload_class").each(function(){
      var myStruct = {
        id: this.id,
        src: this.src
      };
      // myStruct_array.push(myStruct);
      myStruct_array[this.id] = myStruct;
    });
    return myStruct_array;
  }

  function is_cached(img_url){
    var imgEle = document.createElement("img");
    imgEle.src = img_url;
    return imgEle.complete || (imgEle.width+imgEle.height) > 0;
  }

  $(document).ready(function(){
    var precache_myStruct_array = get_precache_myStruct_array("ralph_preload");
    $.each(precache_myStruct_array,
      function (index, value) {
        if (!is_cached(value.src)) {
          alert("Not cached!: " + value.src);
        };
    });

    <% if true %>
      $('#ralph-back-button-filedset').hover(function(){
        var precache_myStruct_array = get_precache_myStruct_array("ralph_preload");
        var imageID   = '1487789814_back_red';
        $('#ralph-back-button-black-img > img:nth-child(1)').attr("src", precache_myStruct_array[imageID].src);
      }, function(){
        var precache_myStruct_array = get_precache_myStruct_array("ralph_preload");
        var imageID = '1487789814_back';
        $('#ralph-back-button-black-img > img:nth-child(1)').attr("src", precache_myStruct_array[imageID].src);
      });
    <% end %>

  });
</script>

Within the jQuery code block, the "<% if true %>" / "<% end %>" section serves an inline processing purpose during ERB evaluation. Modifying this to false can aid in debugging using browser tools.


Final Remarks:

In my quest to find a solution to the specified problem, I scoured online resources but didn't come across a direct match to my requirements. I welcome any feedback or corrections to improve the approach discussed herein.

Answer №1

Storing images in the public folder will not result in an additional hash being added to the image name.

To address this, I created a loop in my controller that retrieved all file names related to "Rails" for my images and saved them in a location for convenient access.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Creating a web responsive grid from scratch: Best practices

Currently, I am engaged in developing a timesheet/billing system for a client's project. One of the main tasks on my plate is to create an effective grid-layout that accurately displays data in its designated positions. We have not yet determined whic ...

What is the best way to incorporate a button that, when clicked, reveals two separate images on the frontend?

describe food option heredescribe juice option hereHow can I create a button using HTML, CSS, JavaScript, and Bootstrap that displays different images for food and juices when clicked? For example, clicking on "food" will display 3 different food images, w ...

Styling tip: Distance the tooltip from its parent element when scrolling through a list

I have a table inside li tag, and I want to display the description on :hover inside td. However, when scrolling through the list, the description content starts to appear with a distance from its parent. Despite trying various combinations of position se ...

Achieving a Customized Header and Footer in Bootstrap 4 Alongside Immersive Google Maps Display with Full Screen Height

I'm facing some challenges while developing a webpage with Bootstrap 4.1. I am working on incorporating a header, Google map that fills the entire content area, and a footer below the map. ------------------------------------------------------------- ...

Determine the overall cost based on varying percentage increases for each step

I am currently working on developing a price estimation calculator. Here is the breakdown: For 1000 MTU, the price will be 0.035, resulting in a total of 35. For 2000 MTU, the price will be 0.034, making the total 67. For 3000 MTU, the price will be 0.03 ...

Storing a Business Hierarchy in Browser Storage with JavaScript

I have developed a hierarchical tree structure on an HTML page where users can customize a company's organizational chart based on their needs. However, I am looking to store this structured data in local storage so that it can be utilized on another ...

How can I make the hover effect only apply to the text and not the entire box?

I'm wondering how I can make the :hover property only affect individual letters in my navigation bar, instead of hovering over the entire box. * { margin: 0px; padding: 0px; } .navigation-bar { height: 3.2em; background: gray; text-align: ...

Struggling with Input Padding Across Different Browsers?

I am facing an issue with my search form that is supposed to look like this: </p> This is the sample HTML code for the search form: <form method="post" action="#" class="search-form"> <input type="text" class="nav-search-input input ...

Customize your QTabBar icons with Qt Stylesheet: Adjusting the icon mode

I am currently working on customizing a QTabBar with a stylesheet in my tool. I use QIcon to create icons for the tabs, allowing me to set different modes such as normal, disabled, and selected. The challenge I am facing is trying to apply a global stylesh ...

Adjust the size of items using a background image that covers the element

I'm struggling with a seemingly simple task here. I've been experimenting with different methods, but I just can't seem to grasp it. On the front page of my website, there is a cover section that contains a logo and a button: <section i ...

Spacing between the rows of a table

I am seeking to achieve a unique visual style for the rows in my table, similar to the one shown below. I attempted to use CSS border properties in the code snippet provided but desire more spacing between each row with a thin border and sharp edges. .dat ...

How can this be written in a shorter amount of CSS code?

Seeking a more optimized solution, I am attempting to write CSS transitions for five different elements (medals/badges). Is there a way to achieve the same effect with less code? Below is the current code: #nav .badges { float:left; height: 173px; width: ...

The dropdown menu extends beyond the boundaries of the page

I am attempting to incorporate a dropdown menu in the upper right corner. Here is what I currently have: https://i.sstatic.net/soHgc.png The dropdown menu that appears extends beyond the page boundaries. This is the code I am using: <link rel="st ...

The origin of the image is specified within the HTML document

I recently encountered an issue while trying to include images in my HTML file. When I used a local file path like background-image: url('file:///C:/Users/faycel/Desktop/site%20guide/paris.jpg'), the image displayed correctly. However, when I tri ...

CSS rules within CSS rules

Is it possible to use nested CSS statements? Rather than repeating classes as shown below: .hello .world1 {} .hello .world2 {} Could we potentially do something along the lines of this instead: .hello { .world1 {} .world2 {} } Is a similar techni ...

Design a row with two columns of the same height - one containing an image, and the other a scrollable

Can anyone provide guidance on creating two responsive Bootstrap 4 columns with equal height, where one column contains an image and the other displays a scrollable list? Check out this fiddle (please note that I want to ensure the list group does not exc ...

flexbox with equal width and height

I have two questions regarding flexboxes but I am unable to find the answers. How can I create 4 boxes with equal width and height, without using the viewport? For instance, if I create a box with 50% width, I want the height to be equal to the width. ...

Is there a way to position an h3 next to a p without generating separate lines?

My html code appears like this: <h3>Corruption, the most infallible symptom of constitutional liberty.</h3> <p>~ Edward Gibbon</p> The output it generates is shown below: I have indicated with an arrow that I would prefer Edward ...

Why does my div keep getting displaced downward?

How can I move the white box, also known as topBoxFlag, to the top of its parent container topBox? Despite my attempts with an absolute layout, it keeps getting pushed down below the red box due to the relative positioning. Is there a more efficient way to ...

Personalize the appearance of dynamically generated DIV elements

This script generates a random number of squares (ranging from 20 to 40) and adds text to each square. The script then calculates the width of each square so that they all fit in a single row. Here is the code snippet: var quantity = Math.floor(Math.ran ...