Skip to content

Commit

Permalink
add the ability to position sprite images to the right of the sprite
Browse files Browse the repository at this point in the history
  • Loading branch information
agrobbin committed Jun 4, 2014
1 parent 9d0121f commit 3bdf4e4
Show file tree
Hide file tree
Showing 10 changed files with 92 additions and 20 deletions.
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,26 @@ Assuming file `background.png` in `app/assets/images/application`, you can repea
$application-sprite: spritely-map('application/*.png', $background-repeat: true);
```

### Positioning

When you want to use a sprited image on the right-hand side of an element, it's useful to position that image to the absolute right of the sprite map. To do that for an image name `arrow.png`:

```scss
$application-sprite: spritely-map('application/*.png', $arrow-position: right);
```

The default value is `left`.

#### Global positioning

You can also position all images to the right-hand side of the sprite.

```scss
$application-sprite: spritely-map('application/*.png', $position: right);
```

*Note that per-image positioning will override the global positioning option.*

### Spacing

There are sometimes cases where you want to add some extra spacing (or padding) to a particular image in your sprite. To do so for an image named `foo.png`:
Expand Down
13 changes: 8 additions & 5 deletions lib/spritely/image_set.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
module Spritely
class ImageSet
attr_accessor :top
attr_reader :path, :options, :data, :width, :height
attr_reader :path, :options, :data, :width, :height, :left

def initialize(path, options)
@path = path
@options = options
@data = File.read(path)
@width, @height = data[0x10..0x18].unpack('NN')
@left = 0
end

def name
Expand All @@ -20,10 +21,6 @@ def images
@images ||= []
end

def left
0
end

def outer_height
height + spacing
end
Expand All @@ -36,13 +33,19 @@ def repeated?
!!options[:repeat]
end

def right?
options[:position] == 'right'
end

def position_in!(collection_width)
if repeated?
left_position = 0
while left_position < collection_width
add_image!(left_position)
left_position += width
end
elsif right?
add_image!(@left = collection_width - width)
else
add_image!(0)
end
Expand Down
2 changes: 1 addition & 1 deletion lib/spritely/options.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

module Spritely
class Options < Struct.new(:hash)
GLOBAL_OPTIONS = [:spacing]
GLOBAL_OPTIONS = [:spacing, :position]

def cache_key
stripped_hash.to_s
Expand Down
2 changes: 1 addition & 1 deletion lib/spritely/sass_functions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def spritely_url(sprite_map)
def spritely_position(sprite_map, image_name)
image = find_image(sprite_map, image_name)

x = Sass::Script::Number.new(image.left, image.left == 0 ? [] : ['px'])
x = Sass::Script::Number.new(-image.left, image.left == 0 ? [] : ['px'])
y = Sass::Script::Number.new(-image.top, image.top == 0 ? [] : ['px'])

Sass::Script::List.new([x, y], :space)
Expand Down
Binary file modified spec/fixtures/correct-sprite.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ $application-sprite: spritely-map("application/*.png",
$background-repeat: true,
$football-spacing: 100px,
$mario-spacing: 10px,
$mario-position: right,
$spacing: 5px
);

Expand Down
2 changes: 1 addition & 1 deletion spec/integration/stylesheet_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
it { should include(<<-CSS.strip_heredoc
#mario {
background-image: url(/assets/sprites/application.png);
background-position: 0 -728px;
background-position: -150px -728px;
width: 200px;
height: 214px;
}
Expand Down
48 changes: 47 additions & 1 deletion spec/spritely/image_set_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

describe Spritely::ImageSet do
let(:path) { "#{__dir__}/../fixtures/test/foo.png" }
let(:options) { {repeat: true, spacing: 10} }
let(:options) { {repeat: true, spacing: 10, position: 'right'} }

subject { Spritely::ImageSet.new(path, options) }

Expand Down Expand Up @@ -45,6 +45,22 @@
end
end

describe '#right?' do
it { should be_right }

context 'position option is passed as left' do
let(:options) { {position: 'left'} }

it { should_not be_right }
end

context 'position option is not passed' do
let(:options) { {} }

it { should_not be_right }
end
end

describe '#position_in!' do
class ImageDouble
attr_accessor :top, :left
Expand All @@ -67,6 +83,36 @@ class ImageDouble
expect(second_image.top).to eq(123)
expect(second_image.left).to eq(1)
end

context 'it is also positioned to the right' do
let(:options) { {position: 'right', repeat: true} }

its(:left) { should eq(0) }

it 'should ignore the position option' do
expect(first_image.top).to eq(123)
expect(first_image.left).to eq(0)
expect(second_image.top).to eq(123)
expect(second_image.left).to eq(1)
end
end
end

context 'the image is positioned to the right' do
let(:options) { {position: 'right'} }
let(:image) { ImageDouble.new }

before do
allow(Spritely::Image).to receive(:new).with(File.read(path)).and_return(image)
subject.position_in!(100)
end

its(:left) { should eq(99) }

it 'should set the position of the image' do
expect(image.top).to eq(123)
expect(image.left).to eq(99)
end
end

context 'the image is not repeated' do
Expand Down
14 changes: 8 additions & 6 deletions spec/spritely/options_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,25 @@
'some_new_image_spacing' => Sass::Script::Number.new(789),
'some_new_image_x' => Sass::Script::Number.new(123),
'some_new_image_y' => Sass::Script::Number.new(456),
'some_new_image_position' => Sass::Script::String.new('right'),
'another_image_repeat' => Sass::Script::Bool.new(true),
'yet_another_image_repeat' => Sass::Script::Bool.new(false),
'spacing' => Sass::Script::Number.new(901),
'position' => Sass::Script::String.new('left')
} }

subject(:options) { Spritely::Options.new(hash) }

its(:inspect) { should eq("#<Spritely::Options global_options=#{{spacing: 901}} options=#{{'some-new-image' => {spacing: 789, x: 123, y: 456}, 'another-image' => {spacing: 901, repeat: true}, 'yet-another-image' => {spacing: 901, repeat: false}}}>") }
its(:cache_key) { should eq({some_new_image_spacing: 789, some_new_image_x: 123, some_new_image_y: 456, another_image_repeat: true, yet_another_image_repeat: false, spacing: 901}.to_s) }
its(:inspect) { should eq("#<Spritely::Options global_options=#{{spacing: 901, position: 'left'}} options=#{{'some-new-image' => {spacing: 789, position: 'right', x: 123, y: 456}, 'another-image' => {spacing: 901, position: 'left', repeat: true}, 'yet-another-image' => {spacing: 901, position: 'left', repeat: false}}}>") }
its(:cache_key) { should eq({some_new_image_spacing: 789, some_new_image_x: 123, some_new_image_y: 456, some_new_image_position: 'right', another_image_repeat: true, yet_another_image_repeat: false, spacing: 901, position: 'left'}.to_s) }

its(['some-new-image']) { should eq({spacing: 789, x: 123, y: 456}) }
its(['another-image']) { should eq({spacing: 901, repeat: true}) }
its(['yet-another-image']) { should eq({spacing: 901, repeat: false}) }
its(['some-new-image']) { should eq({spacing: 789, position: 'right', x: 123, y: 456}) }
its(['another-image']) { should eq({spacing: 901, repeat: true, position: 'left'}) }
its(['yet-another-image']) { should eq({spacing: 901, repeat: false, position: 'left'}) }

describe '#[]' do
it 'should fall back to an empty hash' do
expect(options[:unknown]).to eq({spacing: 901})
expect(options[:unknown]).to eq({spacing: 901, position: 'left'})
end
end
end
10 changes: 5 additions & 5 deletions spec/spritely/sass_functions_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,18 @@ def asset_url(path)
end

describe '#spritely_position' do
let(:image) { double(left: 0, top: 12) }
let(:image) { double(left: 10, top: 12) }

subject { evaluate("spritely-position(spritely-map('test/*.png'), 'bar')") }

include_examples "a sprite function that checks image existence"

it { should eq('0 -12px') }
it { should eq('-10px -12px') }

context 'the left is not 0' do
let(:image) { double(left: 10, top: 12) }
context 'the positions are both 0' do
let(:image) { double(left: 0, top: 0) }

it { should eq('10px -12px') }
it { should eq('0 0') }
end
end

Expand Down

0 comments on commit 3bdf4e4

Please sign in to comment.