Twitter Email
subspace (/ˈsʌbspɛɪs/)
A Jekyll playground site

Advanced image tag for jquery fancybox

Author: Admin
Title: Example for an advanced Liquid tag for fancybox images
Language: en-US
Created: 20:10 on Sunday, 10. October 2021
Modified: 20:10 on Sunday, 10. October 2021
Keywords: jekyll, ruby, tag, liquid, images
Excerpt:

An advanced liquid tag for embedding images with jquery fancybox in Jekyll.

Tags: Jekyll
Page layout: nonav
Last modified:
20:10 on Sunday, 10. October 2021 | by Admin in Jekyll

In this article we discussed simple tag basics for a Jekyll site. The following example is a bit more advanced and also a bit more special. It’s only useful for people who use jquery Fancybox on their Jekyll site, otherwise this tag would most likely not work at all.

The tag can be used to embed images with different types of formatting (floating, left or right aligned or block image), descriptions, and optionally use fancybox for zooming and better viewing experience.

Basic usage

{% fboximg { "src": "images.foo", "align": "left", "width": "50%" } %}

As you can see, the tag uses JSON for passing parameters like my other tags. This would pull image information from a yaml record foo in the data file _data/images.yaml. Images must be described in yaml record with the format specified below. The parameter src is the only mandatory parameter, all others are optional with reasonable default values.

Some more examples for image sources

A src value of page.media.logo would pull the information from the page’s front matter records which could look like this.

media:
  logo:
    name: logo.jpg
    path: logos/

A value of galleries.2021.vacation.ressort would look for a record with the name ressort in _data/galleries/2021/vacation.yaml and so on. Note that it could also be _data/galleries/2021.yaml with a sub-record ressort in the vacation collection. It’s completely up to you to organize your images and you should generally avoid ambiguity.

So here is the code for this tag

Code: (click to select all)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
require 'json'

# a tag to embed images with jquery fancybox support.
# parameters are expected as JSON string:
# see
#
# https://subspace.cc/en/2021/10/10/advanced-img-tag-fancybox/
# 
# for more information
#
# src: mandatory, a yaml object describing an image.
# =>   if it starts with page. it's excepted to reside
# =>   in the front matter. 
# =>   otherwise it must 

# e.g. an object in  _data/galleries/default.yaml
# images:
# => foo:
# =>   name: foo.jpg
# =>   desc: A test image
# =>   path: default/images/
# =>   long: A long description rendered as overlay and supporting 
#            markdown.
#      thumb: 1
# 
# that image would be accessible as data.galleries.default.images.foo
# the jpg must be under /assets/gfx/default/images/foo.jpg (given by path: + name:)
#
# if thumb: is != 0, a thumb_foo.jpg must be present in the same directory.
#
# Other parameters
# ----------------
# align:  left, right or block. left and right are floating images supporting
# =>      text wrap
# =>      block is a normal block image without text flow.
# width:  width of the image wrapper container. Must be given in CSS notation,
#         e.g. "85%". 
# bc:     Additional CSS class for the wrapping container.
# nolink: If != 0, the image wont be clickable, and no fancybox will show.
#
# Example
# -------
#
# {% fboximg { "src": "page.media.image1", "align": "block", "bc": "borderless" } %}
# #
# note that this tag does not work without fancybox installed on your site and needs
# custom CSS
# see 

module Jekyll
  class FBImgTag < Liquid::Tag

    def initialize(tag_name, text, tokens)
      super
      @text = text
      @prefix = "/assets/gfx/"        # you can modify this here or with the prefix parameter
    end

    def render(context)
      if ( @text.nil? || @text.empty? )
        return "img tag error, no parameters"
      end

      # parameters are expected as JSON
      jdata = JSON.parse(@text)
      output = ""
      @o = nil

      # get the config object for the baseurl
      config = context.registers[:site].config
      baseurl = config['baseurl'].blank? ? "" : config['baseurl']

      # get the markdown converter instance
      @converter = context.registers[:site].find_converter_instance(::Jekyll::Converters::Markdown)

      if ( !jdata['prefix'].blank? )
        @prefix = jdata['prefix'].strip
      end

      if ( jdata.key?('src') )

        keys = jdata['src'].split('.')
        keys.each { |x| x.strip }
        length = keys.length()
        if ( length < 2 )
          return "parameter error"
        end

        if ( keys[0] == "page" )
          data = context.registers[:page]
          keys.shift()
          length = keys.length()
        else
          data = context.registers[:site].data
        end

        if ( length == 2 )
          @o = data[keys[0]][keys[1]]
        elsif ( length == 3 )
          @o = data[keys[0]][keys[1]][keys[2]]
        elsif ( length == 4 )
          @o = data[keys[0]][keys[1]][keys[2]][keys[3]]
        elsif ( length == 5 )
          @o = data[keys[0]][keys[1]][keys[2]][keys[3]][keys[4]]
        elsif ( length == 6 )
          @o = data[keys[0]][keys[1]][keys[2]][keys[3]][keys[4]][keys[5]]
        end

        @final_url = ""
        @thumb_url = ""
        @image_id = keys[keys.length() - 1]

        # construct the url, first check for a remote image
        if (@o.key?('url') ) 
          @final_url = @o["url"]      # that's it
          @thumb_url = @final_url
        else
          have_thumb = @o['thumb']
          @final_path = baseurl + @prefix + (@o.key?('path') ? @o['path'] : "" )
          @thumb_url = have_thumb == 1 ? (@final_path + 'thumb_' + @o['name']) : (@final_path + @o['name'])
          @final_url = @final_path + @o['name']
        end
        @width = jdata.key?('width') ? jdata['width'] : "100%"
        @align = jdata.key?('align') ? jdata['align'] : "block"
        @borderclass = jdata.key?('bc') ? jdata['bc'] : ""
        @want_link = jdata.key?('nolink') ? false : true
        @desc = @o['desc'].blank? ? nil : @o['desc']
        @long = @o['long'].blank? ? nil : @o['long']

        if ( @align == "block" )
          output = gen_html_blockimage(context)
        else
          output = gen_html_floatimage(context)
        end
        return output
      end
      return "error"
    end
    def gen_html_blockimage(context)
      result = <<~MARKUP
          <div class="blockimage #{@borderclass}" style="width:#{@width}; margin: auto;">
      MARKUP
      if ( @want_link )
        result += <<~MARKUP
          <a href="#{@final_url}" data-fancybox data-caption="#{@desc}">
        MARKUP
      end
      result += <<~MARKUP
        <figure style="position:relative;">
          <img src="#{@final_url}" alt="#{@desc}" style="width:auto; max-width:100%; height:auto; margin:0 auto;display:block;" />
      MARKUP
      if ( @long != nil )
        result += <<~MARKUP
          <div data-target="tt_#{@image_id}" class="img_overlay_indicator" style="position:absolute;bottom:20px;right:20px;">
          </div>
        MARKUP
      end
      if ( @desc != nil )
        result += <<~MARKUP
          <figcaption style="display:none;">
          #{@desc}
          </figcaption>
        MARKUP
      end

      parsed_long = @long.blank? ? "" : @converter.convert(@long)

      if ( @long != nil )
        result += <<~MARKUP 
        <div id="tt_#{@image_id}" class="img_tooltip blockimage" style="display:none;">
          <div class="tt_closebutton" style="float:right;margin-top:-10px;margin-right:-10px;margin-left:5px;"></div>
          #{parsed_long}
        </div>
        MARKUP
      end
      result += '</figure>'
      if ( @want_link )
        result += '</a>'
      end
      if ( @desc != nil && true )
        result += <<~MARKUP
          <div class="floatimage_title">
            #{@desc}
          </div>
        MARKUP
      end
      result += <<~MARKUP 
        </div>
      MARKUP
      return result
    end

    def gen_html_floatimage(context)
      result = <<~MARKUP
          <div class="floatimage #{@align} #{@borderclass}" style="width:#{@width}; max-width:#{@width};">
      MARKUP
      if ( @want_link )
        result += <<~MARKUP
          <a href="#{@final_url}" data-fancybox="gallery" data-caption="#{@desc}">
        MARKUP
      end
      result += <<~MARKUP
        <figure style="position:relative;">
          <img src="#{@thumb_url}" alt="#{@desc}" style="height:auto; margin:0; display:block;" />
      MARKUP

      if ( @long != nil )
        result += <<~MARKUP
          <div data-target="tt_#{@image_id}" class="img_overlay_indicator" style="position:absolute;bottom:20px;right:20px;">
          </div>
        MARKUP
      end
      if ( @desc != nil )
        result += <<~MARKUP
          <figcaption style="display:none;">
          #{@desc}
          </figcaption>
        MARKUP
      end
      result += '</figure>'

      if ( @want_link )
        result += '</a>'
      end

      parsed_long = @long.blank? ? "" : @converter.convert(@long)

      if ( @long != nil )
        result += <<~MARKUP 
        <div id="tt_#{@image_id}" class="img_tooltip" style="display:none;">
          <div class="tt_closebutton" style="float:right;margin-top:-10px;margin-right:-10px;margin-left:5px;"></div>
          #{parsed_long}
        </div>
        MARKUP
      end

      if ( @desc != nil && true )
        result += <<~MARKUP
          <div class="floatimage_title">
            #{@desc}
          </div>
        MARKUP
      end
      result += <<~MARKUP 
        </div>
      MARKUP
      return result
    end
  end
end
Liquid::Template.register_tag('fboximg', Jekyll::FBImgTag)