├── .gitignore ├── Gemfile ├── LICENSE ├── Rakefile ├── component.json ├── demo └── demo.html ├── okhover.jquery.json ├── readme.md ├── spec └── javascripts │ ├── helpers │ └── jasmine-jquery-1.3.1.js │ ├── okhoverSpec.js │ ├── support │ ├── jasmine.yml │ ├── jasmine_config.rb │ └── jasmine_runner.rb │ └── vendor │ └── jquery.js └── src ├── okhover.js └── okhover.min.js /.gitignore: -------------------------------------------------------------------------------- 1 | *.lock 2 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source :rubygems 2 | 3 | gem 'jasmine' 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010 OKFocus LLC. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | 2 | begin 3 | require 'jasmine' 4 | load 'jasmine/tasks/jasmine.rake' 5 | rescue LoadError 6 | task :jasmine do 7 | abort "Jasmine is not available. In order to run jasmine, you must: (sudo) gem install jasmine" 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /component.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "OKHover", 3 | "version": "1.2", 4 | "main": "./src/okhover.js", 5 | "dependencies": { 6 | "jquery": ">1.7.2" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /demo/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | OKHover demo 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 28 | 29 | 30 |
31 | 32 |
33 | 34 | 35 | OKHover is a jQuery plugin that makes it easy to reproduce the tiled background effect seen on the OKFocus website. It uses HTML5 data attributes and is designed to be simple yet highly customizable. OKHover is open source. Feel free to contribute or fork it on Github, all you can eat. 36 | 37 |

38 | The basic options are as follow 39 |

40 |
41 |   $(document).ready(function(){
42 |       $('div').okhover({
43 |           fadeIn: true,
44 |           fadeOut: true,
45 |           fadeInDuration: 200  
46 |       });  
47 |   });
48 | 
49 | 50 |
51 | 52 |
53 | I'm a link and this is a demo! 54 |

55 | 56 | 57 |
58 | P.S. - AVATAR was a cool movie. 59 |
60 | 61 | 62 |
63 | 64 | 65 | 66 | 75 | 76 | -------------------------------------------------------------------------------- /okhover.jquery.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "okhover", 3 | "version": "1.1.0", 4 | "title": "okhover", 5 | "description": "A jQuery Plugin that creates a memorable tiled background effect, manipulated by mouse movement.", 6 | "homepage": "https://github.com/okfocus/okhover", 7 | "docs": "https://github.com/okfocus/okhover", 8 | "demo": "http://okfoc.us/okhover", 9 | "licenses": [{ 10 | "type": "MIT", 11 | "url": "https://raw.github.com/okfocus/okhover/master/license" 12 | }], 13 | "keywords": ["hover", "background", "effect", "tile", "mouse", "mousemove", "okfocus"], 14 | "author": { 15 | "name": "OKFocus", 16 | "url": "https://github.com/okfocus" 17 | }, 18 | "maintainers": [{ 19 | "name": "Jonathan Vingiano", 20 | "url": "https://github.com/jgv" 21 | }, 22 | { 23 | "name": "Jules LaPlace", 24 | "url": "https://github.com/julescarbon" 25 | }, 26 | { 27 | "name": "Ryder Ripps", 28 | "url": "https://github.com/ryderr" 29 | }], 30 | "repository": { 31 | "type": "git", 32 | "url": "git://github.com/okfocus/okhover.git" 33 | }, 34 | "bugs": "https://github.com/okfocus/okhover/issues", 35 | "dependencies": { 36 | "jquery": ">=1.4" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # okhover by OKFocus 2 | 3 | OKHover is a jQuery plugin that makes it easy to reproduce the tiled background effect seen on the [OKFocus website](http://okfoc.us "OKFocus"). It uses HTML5 data attributes and is designed to be simple yet highly customizable. 4 | 5 | ### Requirements 6 | 7 | The only real technical requirement besides jQuery itself, is declaring the HTML5 doctype for your web application. This is achieved by making sure the first line of your HTML is ``. This ensures that using data attributes will be considered valid markup by browsers. 8 | 9 | ### Usage 10 | 11 | For a simple example, consider this snippet of code: 12 | 13 | ``` html 14 | 19 | ``` 20 | 21 | The above will have no visible effect. To achieve the hovering effect, you'll have to include this javascript after including the OKHover source. 22 | 23 | ``` js 24 | $(function(){ 25 | $('li').okhover(); 26 | }): 27 | ``` 28 | 29 | When you hover on an `
  • `, you'll now see the okhover effect in action. The data attribute `data-image` is a reference to the image that will appear tiled in the background. 30 | 31 | ### Options 32 | 33 | The following options are available to you: 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 |
    optiondescriptiondefault
    fadeInA boolean that controls if the background image will fade infalse
    fadeOutA boolean that controls if the background image will fade outfalse
    fadeInDurationA number that controls how long the fade-in will be (in milliseconds)400 milliseconds
    z-indexA number that controls the z-index of the background div-1
    elIf you would like to the effect to appear somewhere else (any DOM element that supports the background-image property)null
    69 | 70 | Here's an example with a lot of options: 71 | 72 | ``` js 73 | $(function(){ 74 | $('div').okhover({ 75 | fadeIn: true, 76 | fadeOut: true, 77 | fadeInDuration: 2000, 78 | zIndex: 420, 79 | el: 'a' 80 | }); 81 | }); 82 | ``` 83 | 84 | ### Run Tests 85 | 86 | OKFocus tests JavaScript with Jasmine. Run tests: 87 | 88 | ``` sh 89 | $ bundle install 90 | $ rake jasmine 91 | ``` 92 | -------------------------------------------------------------------------------- /spec/javascripts/helpers/jasmine-jquery-1.3.1.js: -------------------------------------------------------------------------------- 1 | 2 | var readFixtures = function() { 3 | return jasmine.getFixtures().proxyCallTo_('read', arguments); 4 | }; 5 | 6 | var preloadFixtures = function() { 7 | jasmine.getFixtures().proxyCallTo_('preload', arguments); 8 | }; 9 | 10 | var loadFixtures = function() { 11 | jasmine.getFixtures().proxyCallTo_('load', arguments); 12 | }; 13 | 14 | var setFixtures = function(html) { 15 | jasmine.getFixtures().set(html); 16 | }; 17 | 18 | var sandbox = function(attributes) { 19 | return jasmine.getFixtures().sandbox(attributes); 20 | }; 21 | 22 | var spyOnEvent = function(selector, eventName) { 23 | jasmine.JQuery.events.spyOn(selector, eventName); 24 | } 25 | 26 | jasmine.getFixtures = function() { 27 | return jasmine.currentFixtures_ = jasmine.currentFixtures_ || new jasmine.Fixtures(); 28 | }; 29 | 30 | jasmine.Fixtures = function() { 31 | this.containerId = 'jasmine-fixtures'; 32 | this.fixturesCache_ = {}; 33 | this.fixturesPath = 'spec/javascripts/fixtures'; 34 | }; 35 | 36 | jasmine.Fixtures.prototype.set = function(html) { 37 | this.cleanUp(); 38 | this.createContainer_(html); 39 | }; 40 | 41 | jasmine.Fixtures.prototype.preload = function() { 42 | this.read.apply(this, arguments); 43 | }; 44 | 45 | jasmine.Fixtures.prototype.load = function() { 46 | this.cleanUp(); 47 | this.createContainer_(this.read.apply(this, arguments)); 48 | }; 49 | 50 | jasmine.Fixtures.prototype.read = function() { 51 | var htmlChunks = []; 52 | 53 | var fixtureUrls = arguments; 54 | for(var urlCount = fixtureUrls.length, urlIndex = 0; urlIndex < urlCount; urlIndex++) { 55 | htmlChunks.push(this.getFixtureHtml_(fixtureUrls[urlIndex])); 56 | } 57 | 58 | return htmlChunks.join(''); 59 | }; 60 | 61 | jasmine.Fixtures.prototype.clearCache = function() { 62 | this.fixturesCache_ = {}; 63 | }; 64 | 65 | jasmine.Fixtures.prototype.cleanUp = function() { 66 | jQuery('#' + this.containerId).remove(); 67 | }; 68 | 69 | jasmine.Fixtures.prototype.sandbox = function(attributes) { 70 | var attributesToSet = attributes || {}; 71 | return jQuery('
    ').attr(attributesToSet); 72 | }; 73 | 74 | jasmine.Fixtures.prototype.createContainer_ = function(html) { 75 | var container; 76 | if(html instanceof jQuery) { 77 | container = jQuery('
    '); 78 | container.html(html); 79 | } else { 80 | container = '
    ' + html + '
    ' 81 | } 82 | jQuery('body').append(container); 83 | }; 84 | 85 | jasmine.Fixtures.prototype.getFixtureHtml_ = function(url) { 86 | if (typeof this.fixturesCache_[url] == 'undefined') { 87 | this.loadFixtureIntoCache_(url); 88 | } 89 | return this.fixturesCache_[url]; 90 | }; 91 | 92 | jasmine.Fixtures.prototype.loadFixtureIntoCache_ = function(relativeUrl) { 93 | var self = this; 94 | var url = this.fixturesPath.match('/$') ? this.fixturesPath + relativeUrl : this.fixturesPath + '/' + relativeUrl; 95 | jQuery.ajax({ 96 | async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded 97 | cache: false, 98 | dataType: 'html', 99 | url: url, 100 | success: function(data) { 101 | self.fixturesCache_[relativeUrl] = data; 102 | }, 103 | error: function(jqXHR, status, errorThrown) { 104 | throw Error('Fixture could not be loaded: ' + url + ' (status: ' + status + ', message: ' + errorThrown.message + ')'); 105 | } 106 | }); 107 | }; 108 | 109 | jasmine.Fixtures.prototype.proxyCallTo_ = function(methodName, passedArguments) { 110 | return this[methodName].apply(this, passedArguments); 111 | }; 112 | 113 | 114 | jasmine.JQuery = function() {}; 115 | 116 | jasmine.JQuery.browserTagCaseIndependentHtml = function(html) { 117 | return jQuery('
    ').append(html).html(); 118 | }; 119 | 120 | jasmine.JQuery.elementToString = function(element) { 121 | return jQuery('
    ').append(element.clone()).html(); 122 | }; 123 | 124 | jasmine.JQuery.matchersClass = {}; 125 | 126 | (function(namespace) { 127 | var data = { 128 | spiedEvents: {}, 129 | handlers: [] 130 | }; 131 | 132 | namespace.events = { 133 | spyOn: function(selector, eventName) { 134 | var handler = function(e) { 135 | data.spiedEvents[[selector, eventName]] = e; 136 | }; 137 | jQuery(selector).bind(eventName, handler); 138 | data.handlers.push(handler); 139 | }, 140 | 141 | wasTriggered: function(selector, eventName) { 142 | return !!(data.spiedEvents[[selector, eventName]]); 143 | }, 144 | 145 | cleanUp: function() { 146 | data.spiedEvents = {}; 147 | data.handlers = []; 148 | } 149 | } 150 | })(jasmine.JQuery); 151 | 152 | (function(){ 153 | var jQueryMatchers = { 154 | toHaveClass: function(className) { 155 | return this.actual.hasClass(className); 156 | }, 157 | 158 | toBeVisible: function() { 159 | return this.actual.is(':visible'); 160 | }, 161 | 162 | toBeHidden: function() { 163 | return this.actual.is(':hidden'); 164 | }, 165 | 166 | toBeSelected: function() { 167 | return this.actual.is(':selected'); 168 | }, 169 | 170 | toBeChecked: function() { 171 | return this.actual.is(':checked'); 172 | }, 173 | 174 | toBeEmpty: function() { 175 | return this.actual.is(':empty'); 176 | }, 177 | 178 | toExist: function() { 179 | return this.actual.size() > 0; 180 | }, 181 | 182 | toHaveAttr: function(attributeName, expectedAttributeValue) { 183 | return hasProperty(this.actual.attr(attributeName), expectedAttributeValue); 184 | }, 185 | 186 | toHaveId: function(id) { 187 | return this.actual.attr('id') == id; 188 | }, 189 | 190 | toHaveHtml: function(html) { 191 | return this.actual.html() == jasmine.JQuery.browserTagCaseIndependentHtml(html); 192 | }, 193 | 194 | toHaveText: function(text) { 195 | if (text && jQuery.isFunction(text.test)) { 196 | return text.test(this.actual.text()); 197 | } else { 198 | return this.actual.text() == text; 199 | } 200 | }, 201 | 202 | toHaveValue: function(value) { 203 | return this.actual.val() == value; 204 | }, 205 | 206 | toHaveData: function(key, expectedValue) { 207 | return hasProperty(this.actual.data(key), expectedValue); 208 | }, 209 | 210 | toBe: function(selector) { 211 | return this.actual.is(selector); 212 | }, 213 | 214 | toContain: function(selector) { 215 | return this.actual.find(selector).size() > 0; 216 | }, 217 | 218 | toBeDisabled: function(selector){ 219 | return this.actual.is(':disabled'); 220 | }, 221 | 222 | // tests the existence of a specific event binding 223 | toHandle: function(eventName) { 224 | var events = this.actual.data("events"); 225 | return events && events[eventName].length > 0; 226 | }, 227 | 228 | // tests the existence of a specific event binding + handler 229 | toHandleWith: function(eventName, eventHandler) { 230 | var stack = this.actual.data("events")[eventName]; 231 | var i; 232 | for (i = 0; i < stack.length; i++) { 233 | if (stack[i].handler == eventHandler) { 234 | return true; 235 | } 236 | } 237 | return false; 238 | } 239 | }; 240 | 241 | var hasProperty = function(actualValue, expectedValue) { 242 | if (expectedValue === undefined) { 243 | return actualValue !== undefined; 244 | } 245 | return actualValue == expectedValue; 246 | }; 247 | 248 | var bindMatcher = function(methodName) { 249 | var builtInMatcher = jasmine.Matchers.prototype[methodName]; 250 | 251 | jasmine.JQuery.matchersClass[methodName] = function() { 252 | if (this.actual instanceof jQuery) { 253 | var result = jQueryMatchers[methodName].apply(this, arguments); 254 | this.actual = jasmine.JQuery.elementToString(this.actual); 255 | return result; 256 | } 257 | 258 | if (builtInMatcher) { 259 | return builtInMatcher.apply(this, arguments); 260 | } 261 | 262 | return false; 263 | }; 264 | }; 265 | 266 | for(var methodName in jQueryMatchers) { 267 | bindMatcher(methodName); 268 | } 269 | })(); 270 | 271 | beforeEach(function() { 272 | this.addMatchers(jasmine.JQuery.matchersClass); 273 | this.addMatchers({ 274 | toHaveBeenTriggeredOn: function(selector) { 275 | this.message = function() { 276 | return [ 277 | "Expected event " + this.actual + " to have been triggered on" + selector, 278 | "Expected event " + this.actual + " not to have been triggered on" + selector 279 | ]; 280 | }; 281 | return jasmine.JQuery.events.wasTriggered(selector, this.actual); 282 | } 283 | }) 284 | }); 285 | 286 | afterEach(function() { 287 | jasmine.getFixtures().cleanUp(); 288 | jasmine.JQuery.events.cleanUp(); 289 | }); 290 | -------------------------------------------------------------------------------- /spec/javascripts/okhoverSpec.js: -------------------------------------------------------------------------------- 1 | describe('okhover', function() { 2 | var list, background, imageUri = 'http://okfoc.us/assets/images/logo.gif' 3 | 4 | beforeEach(function(){ 5 | jasmine.getFixtures().set('
    • okhover
    • '); 6 | this.addMatchers({ 7 | toHaveBackgroundImage: function() { 8 | return /^url/.test(this.actual.css('backgroundImage')); 9 | } 10 | }); 11 | }); 12 | 13 | describe('with default options', function () { 14 | beforeEach(function(){ 15 | list = $('li').okhover(); 16 | background = $('#ok-bg'); 17 | expect(background).toExist(); 18 | }); 19 | 20 | it('mouseover event reveals tiled image', function () { 21 | $('li').trigger('mouseover'); 22 | expect(background).toHaveBackgroundImage(); 23 | }); 24 | 25 | it('mouse out hides background', function() { 26 | $('li').trigger('mouseout'); 27 | expect(background.css('backgroundImage')).toBe('none'); 28 | }); 29 | 30 | }); 31 | 32 | describe('with zindex set', function () { 33 | beforeEach(function(){ 34 | list = $('li').okhover({ zIndex: 666 }); 35 | background = $('#ok-bg'); 36 | expect(background).toExist(); 37 | }); 38 | 39 | it('mouseover event reveals tiled image', function () { 40 | $('li').trigger('mouseover'); 41 | expect(background).toHaveBackgroundImage(); 42 | }); 43 | 44 | it('background zindex is specified by user', function(){ 45 | expect(background.css('zIndex')).toBe('666'); 46 | }); 47 | 48 | it('mouse out hides background', function() { 49 | $('li').trigger('mouseout'); 50 | expect(background.css('backgroundImage')).toBe('none'); 51 | }); 52 | 53 | }); 54 | }); -------------------------------------------------------------------------------- /spec/javascripts/support/jasmine.yml: -------------------------------------------------------------------------------- 1 | # src_files 2 | # 3 | # Return an array of filepaths relative to src_dir to include before jasmine specs. 4 | # Default: [] 5 | # 6 | # EXAMPLE: 7 | # 8 | # src_files: 9 | # - lib/source1.js 10 | # - lib/source2.js 11 | # - dist/**/*.js 12 | # 13 | src_files: 14 | - spec/javascripts/vendor/jquery.js 15 | - src/*.min.js 16 | 17 | # stylesheets 18 | # 19 | # Return an array of stylesheet filepaths relative to src_dir to include before jasmine specs. 20 | # Default: [] 21 | # 22 | # EXAMPLE: 23 | # 24 | # stylesheets: 25 | # - css/style.css 26 | # - stylesheets/*.css 27 | # 28 | stylesheets: 29 | 30 | # helpers 31 | # 32 | # Return an array of filepaths relative to spec_dir to include before jasmine specs. 33 | # Default: ["helpers/**/*.js"] 34 | # 35 | # EXAMPLE: 36 | # 37 | # helpers: 38 | # - helpers/**/*.js 39 | # 40 | helpers: 41 | 42 | # spec_files 43 | # 44 | # Return an array of filepaths relative to spec_dir to include. 45 | # Default: ["**/*[sS]pec.js"] 46 | # 47 | # EXAMPLE: 48 | # 49 | # spec_files: 50 | # - **/*[sS]pec.js 51 | # 52 | spec_files: 53 | 54 | # src_dir 55 | # 56 | # Source directory path. Your src_files must be returned relative to this path. Will use root if left blank. 57 | # Default: project root 58 | # 59 | # EXAMPLE: 60 | # 61 | # src_dir: public 62 | # 63 | src_dir: 64 | 65 | # spec_dir 66 | # 67 | # Spec directory path. Your spec_files must be returned relative to this path. 68 | # Default: spec/javascripts 69 | # 70 | # EXAMPLE: 71 | # 72 | # spec_dir: spec/javascripts 73 | # 74 | spec_dir: 75 | -------------------------------------------------------------------------------- /spec/javascripts/support/jasmine_config.rb: -------------------------------------------------------------------------------- 1 | module Jasmine 2 | class Config 3 | 4 | # Add your overrides or custom config code here 5 | 6 | end 7 | end 8 | 9 | 10 | # Note - this is necessary for rspec2, which has removed the backtrace 11 | module Jasmine 12 | class SpecBuilder 13 | def declare_spec(parent, spec) 14 | me = self 15 | example_name = spec["name"] 16 | @spec_ids << spec["id"] 17 | backtrace = @example_locations[parent.description + " " + example_name] 18 | parent.it example_name, {} do 19 | me.report_spec(spec["id"]) 20 | end 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /spec/javascripts/support/jasmine_runner.rb: -------------------------------------------------------------------------------- 1 | $:.unshift(ENV['JASMINE_GEM_PATH']) if ENV['JASMINE_GEM_PATH'] # for gem testing purposes 2 | 3 | require 'rubygems' 4 | require 'jasmine' 5 | jasmine_config_overrides = File.expand_path(File.join(File.dirname(__FILE__), 'jasmine_config.rb')) 6 | require jasmine_config_overrides if File.exist?(jasmine_config_overrides) 7 | if Jasmine::rspec2? 8 | require 'rspec' 9 | else 10 | require 'spec' 11 | end 12 | 13 | jasmine_config = Jasmine::Config.new 14 | spec_builder = Jasmine::SpecBuilder.new(jasmine_config) 15 | 16 | should_stop = false 17 | 18 | if Jasmine::rspec2? 19 | RSpec.configuration.after(:suite) do 20 | spec_builder.stop if should_stop 21 | end 22 | else 23 | Spec::Runner.configure do |config| 24 | config.after(:suite) do 25 | spec_builder.stop if should_stop 26 | end 27 | end 28 | end 29 | 30 | spec_builder.start 31 | should_stop = true 32 | spec_builder.declare_suites -------------------------------------------------------------------------------- /src/okhover.js: -------------------------------------------------------------------------------- 1 | /* 2 | * OKHover by OKFocus v1.2.1 3 | * http://okfoc.us 4 | * 5 | * Copyright 2012, OKFocus 6 | * Licensed under the MIT license. 7 | * 8 | */ 9 | 10 | (function($){ 11 | 12 | $.okhover = function(el, options){ 13 | var base = this; 14 | base.$el = $(el); 15 | base.el = el; 16 | base.$el.data("okhover", base); 17 | 18 | base.init = function(){ 19 | base.options = $.extend({}, $.okhover.options, options); 20 | 21 | if (!base.options.el) $('body').append('
      '); 22 | 23 | base.build(); 24 | }; 25 | 26 | base.build = function(){ 27 | if (!base.options.el && $('#ok-bg').length == 0) { 28 | throw new Error('Failed to attach the ok-bg div to the DOM'); 29 | } else { 30 | base.start(); 31 | } 32 | }; 33 | 34 | base.start = function () { 35 | 36 | var background = base.options.el ? $(base.options.el) : $("#ok-bg"); 37 | 38 | if (base.options.fadeIn && !base.options.el) background.hide(); 39 | if (base.options.zIndex) background.css('zIndex', base.options.zIndex); 40 | 41 | base.preload(base.$el); 42 | 43 | base.$el.bind({ 44 | mouseover: function(){ 45 | $(this).mousemove(function(e){ 46 | background.css('backgroundPosition', e.pageX + 'px ' + e.pageY + 'px'); 47 | }); 48 | 49 | background.css('backgroundImage', 'url(' + $(this).attr('data-okimage') + ')'); 50 | 51 | if (base.options.fadeIn && !base.options.el) background.css('opacity', 0).stop().fadeTo(base.options.fadeInDuration, 1); 52 | else background.show(); 53 | }, 54 | mouseout: function(){ 55 | if (base.options.fadeOut && !base.options.el) { 56 | background.stop().fadeTo(base.options.fadeOutDuration, 0, function() { $(this).css('backgroundImage', '').hide() }); 57 | } else if (base.options.el) { 58 | background.css('backgroundImage', ''); 59 | } else { 60 | background.css('backgroundImage', '').hide(); 61 | } 62 | } 63 | }); 64 | }; 65 | 66 | base.preload = function(elements) { 67 | elements.each(function(){ 68 | if ($(this).attr('data-okimage')) { 69 | (new Image()).src = $(this).attr('data-okimage'); 70 | } 71 | }); 72 | }; 73 | 74 | base.init(); 75 | }; 76 | 77 | $.okhover.options = { 78 | fadeIn: false, 79 | fadeOut: false, 80 | fadeInDuration: 400, 81 | fadeOutDuration: 400, 82 | zIndex: null, 83 | el: null 84 | }; 85 | 86 | $.fn.okhover = function(options){ 87 | return this.each(function(){ 88 | (new $.okhover(this, options)); 89 | }); 90 | }; 91 | 92 | })(jQuery); 93 | -------------------------------------------------------------------------------- /src/okhover.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | * OKHover by OKFocus v1.2.1 3 | * http://okfoc.us 4 | * 5 | * Copyright 2012, OKFocus 6 | * Licensed under the MIT license. 7 | * 8 | */(function(e){e.okhover=function(t,n){var r=this;r.$el=e(t),r.el=t,r.$el.data("okhover",r),r.init=function(){r.options=e.extend({},e.okhover.options,n),r.options.el||e("body").append('
      '),r.build()},r.build=function(){if(!r.options.el&&e("#ok-bg").length==0)throw new Error("Failed to attach the ok-bg div to the DOM");r.start()},r.start=function(){var t=r.options.el?e(r.options.el):e("#ok-bg");r.options.fadeIn&&!r.options.el&&t.hide(),r.options.zIndex&&t.css("zIndex",r.options.zIndex),r.preload(r.$el),r.$el.bind({mouseover:function(){e(this).mousemove(function(e){t.css("backgroundPosition",e.pageX+"px "+e.pageY+"px")}),t.css("backgroundImage","url("+e(this).attr("data-okimage")+")"),r.options.fadeIn&&!r.options.el?t.css("opacity",0).stop().fadeTo(r.options.fadeInDuration,1):t.show()},mouseout:function(){r.options.fadeOut&&!r.options.el?t.stop().fadeTo(r.options.fadeOutDuration,0,function(){e(this).css("backgroundImage","").hide()}):r.options.el?t.css("backgroundImage",""):t.css("backgroundImage","").hide()}})},r.preload=function(t){t.each(function(){e(this).attr("data-okimage")&&((new Image).src=e(this).attr("data-okimage"))})},r.init()},e.okhover.options={fadeIn:!1,fadeOut:!1,fadeInDuration:400,fadeOutDuration:400,zIndex:null,el:null},e.fn.okhover=function(t){return this.each(function(){new e.okhover(this,t)})}})(jQuery); --------------------------------------------------------------------------------