├── .gitignore ├── CHANGELOG.md ├── README.md ├── bower.json ├── dist ├── captionjs.css ├── captionjs.min.css ├── jquery.caption.js └── jquery.caption.min.js ├── gulpfile.js ├── index.html ├── package.json ├── src ├── main.css └── main.js ├── tests.html └── web ├── favicon.ico ├── favicon.png ├── img └── Evening_Return-wide.jpg ├── scripts ├── jquery.lettering.js ├── jquery.localscroll-1.2.7-min.js ├── jquery.scrollTo-1.4.3.1-min.js ├── main.js └── syntaxhighlighter │ ├── index.html │ ├── scripts │ ├── shAutoloader.js │ ├── shBrushAS3.js │ ├── shBrushAppleScript.js │ ├── shBrushBash.js │ ├── shBrushCSharp.js │ ├── shBrushColdFusion.js │ ├── shBrushCpp.js │ ├── shBrushCss.js │ ├── shBrushDelphi.js │ ├── shBrushDiff.js │ ├── shBrushErlang.js │ ├── shBrushGroovy.js │ ├── shBrushHaxe.js │ ├── shBrushJScript.js │ ├── shBrushJava.js │ ├── shBrushJavaFX.js │ ├── shBrushPerl.js │ ├── shBrushPhp.js │ ├── shBrushPlain.js │ ├── shBrushPowerShell.js │ ├── shBrushPython.js │ ├── shBrushRuby.js │ ├── shBrushSass.js │ ├── shBrushScala.js │ ├── shBrushSql.js │ ├── shBrushTAP.js │ ├── shBrushTypeScript.js │ ├── shBrushVb.js │ ├── shBrushXml.js │ ├── shCore.js │ ├── shCore.min.js │ └── shLegacy.js │ └── styles │ ├── shCore.css │ ├── shCoreDefault.css │ ├── shCoreDjango.css │ ├── shCoreEclipse.css │ ├── shCoreEmacs.css │ ├── shCoreFadeToGrey.css │ ├── shCoreMDUltra.css │ ├── shCoreMidnight.css │ ├── shCoreRDark.css │ ├── shThemeDefault.css │ ├── shThemeDjango.css │ ├── shThemeEclipse.css │ ├── shThemeEmacs.css │ ├── shThemeFadeToGrey.css │ ├── shThemeMDUltra.css │ ├── shThemeMidnight.css │ └── shThemeRDark.css └── styles └── main.css /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .htaccess 3 | node_modules 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ### v1.0.2 | 2017-02-03 2 | - Bumping version because I forgot to compile before publishing. D'oh! :( 3 | 4 | ### v1.0.1 | 2017-02-03 5 | - Resetting figcaption values on window resize if 'is_responsive' is enabled. 6 | 7 | ### v1.0.0 | 2017-02-03 8 | - Changed mode 'hide' to 'hidden'. 9 | - Namespaced all classes generated by caption.js. 10 | - Cleaned up website. 11 | - Better organization of files. 12 | - Moving from Grunt to Gulp. 13 | 14 | ### v0.9.9 | 2016-12-16 15 | - Bumping version for NPM release. 16 | 17 | ### v0.9.8 | 2014-10-15 18 | - Added links using the image's data-link attribute. 19 | 20 | ### v0.9.7 | 2014-10-13 21 | - Added option to inherit box model styles from the original image (still need to do padding). 22 | - Fixed incorrect documentation about 'stacked' mode (changed 'static' to 'stacked'). 23 | - Changed some of the default settings (you may need to adjust yours accordingly!). 24 | 25 | ### v0.9.6 | 2014-09-03 26 | - Adding options for responsive sites 27 | 28 | ### v0.9.5 | 2014-03-29 29 | - Fixed sizing error 30 | - Always forcing dimensions if option is set (regardless of whether size can be detected) 31 | 32 | ### v0.9.4 | 2014-03-24 33 | - Fixed #5: error with images not yet having been painted to screen 34 | - Fixed dates in changelog 35 | 36 | ### v0.9.3 | 2013-09-10 37 | - Changed options to have a 'mode' option instead of the booleans 'animated' and 'stacked' 38 | - Added animation to hide caption on hover 39 | - Added CSS file with required styles 40 | - Namespaced CSS 41 | - Moved website (and thus examples) to git repo 42 | 43 | ### v0.9.2 | 2013-09-09 44 | - Added stacked format 45 | - Added animation to show caption on hover 46 | 47 | ### v0.9.1 | 2013-09-09 48 | - Added Schema support 49 | 50 | ### v0.9.0 | 2013-03-31 51 | - Initial release 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Documentation 2 | 3 | Install using NPM: 4 | 5 | ```bash 6 | npm install --save captionjs 7 | ``` 8 | 9 | Install using Bower: 10 | 11 | ```bash 12 | bower install captionjs 13 | ``` 14 | 15 | Below is the basic setup for caption.js. For more info, please see [captionjs.com](http://captionjs.com). 16 | 17 | ```js 18 | $(window).load(function() { 19 | $('img.caption').captionjs({ 20 | 'class_name' : 'captionjs', // Class name for each
21 | 'schema' : true, // Use schema.org markup (i.e., itemtype, itemprop) 22 | 'mode' : 'default', // default | stacked | animated | hidden (deprecated: hide) 23 | 'debug_mode' : false, // Output debug info to the JS console 24 | 'force_dimensions': true, // Force the dimensions in case they cannot be detected (e.g., image is not yet painted to viewport) 25 | 'is_responsive' : false, // Ensure the figure and image change size when in responsive layout. Requires a container to control responsiveness! 26 | 'inherit_styles' : false // Have the caption.js container inherit box-model properties from the original image 27 | }); 28 | }); 29 | ``` 30 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "captionjs", 3 | "description": "An open-source jQuery plugin to easily and semantically add captions to images.", 4 | "main": "", 5 | "authors": [ 6 | "Eric Magnuson " 7 | ], 8 | "license": "MIT", 9 | "homepage": "https://github.com/ericmagnuson/captionjs", 10 | "ignore": [ 11 | "**/.*", 12 | "node_modules", 13 | "bower_components", 14 | "test", 15 | "tests" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /dist/captionjs.css: -------------------------------------------------------------------------------- 1 | .captionjs{line-height:0} 2 | .captionjs figcaption{line-height:1;-ms-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box;width:100%} 3 | .captionjs.captionjs-animated,.captionjs.captionjs-hidden,.captionjs.captionjs-stacked{position:relative;overflow:hidden} 4 | .captionjs.captionjs-animated figcaption,.captionjs.captionjs-hidden figcaption,.captionjs.captionjs-stacked figcaption{position:absolute} 5 | .captionjs.captionjs-stacked figcaption{bottom:0} 6 | .captionjs.captionjs-animated figcaption{-webkit-transition:.25s bottom;transition:.25s bottom} 7 | .captionjs.captionjs-animated:hover figcaption{bottom:0!important} 8 | .captionjs.captionjs-hidden figcaption{-webkit-transition:.25s margin-bottom;transition:.25s margin-bottom} 9 | .captionjs.captionjs-hidden:hover figcaption{margin-bottom:0!important} -------------------------------------------------------------------------------- /dist/captionjs.min.css: -------------------------------------------------------------------------------- 1 | .captionjs{line-height:0}.captionjs figcaption{line-height:1;-ms-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box;width:100%}.captionjs.captionjs-animated,.captionjs.captionjs-hidden,.captionjs.captionjs-stacked{position:relative;overflow:hidden}.captionjs.captionjs-animated figcaption,.captionjs.captionjs-hidden figcaption,.captionjs.captionjs-stacked figcaption{position:absolute}.captionjs.captionjs-stacked figcaption{bottom:0}.captionjs.captionjs-animated figcaption{-webkit-transition:.25s bottom;transition:.25s bottom}.captionjs.captionjs-animated:hover figcaption{bottom:0!important}.captionjs.captionjs-hidden figcaption{-webkit-transition:.25s margin-bottom;transition:.25s margin-bottom}.captionjs.captionjs-hidden:hover figcaption{margin-bottom:0!important} -------------------------------------------------------------------------------- /dist/jquery.caption.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * caption.js | easily and semantically add captions to your images 3 | * https://captionjs.com 4 | * 5 | * Copyright 2013–2017, Eric Magnuson 6 | * Released under the MIT license 7 | * https://github.com/jquery/jquery/blob/master/MIT-LICENSE.txt 8 | * 9 | * v1.0.2 10 | * Date: 2017-02-03 11 | */ 12 | (function($, window, undefined) { 13 | $.fn.captionjs = function(opts) { 14 | 15 | // Default values for options 16 | var defaults = { 17 | 'class_name' : 'captionjs', // Class name for each
18 | 'schema' : true, // Use schema.org markup (i.e., itemtype, itemprop) 19 | 'mode' : 'default', // default | stacked | animated | hidden (deprecated: hide) 20 | 'debug_mode' : false, // Output debug info to the JS console 21 | 'force_dimensions': true, // Force the dimensions in case they cannot be detected (e.g., image is not yet painted to viewport) 22 | 'is_responsive' : false, // Ensure the figure and image change size when in responsive layout. Requires a container to control responsiveness! 23 | 'inherit_styles' : false // Have the caption.js container inherit box-model properties from the original image 24 | }; 25 | 26 | // Extend the options from defaults with user's options 27 | var options = $.extend(defaults, opts || {}); 28 | 29 | // Function to copy styles 30 | var transferStyles = function(property, reset_val, $origin, $target) { 31 | if ($origin.jquery && $target.jquery) // Check that they are jQuery objects 32 | { 33 | $origin.css(property, $target.css(property)); 34 | $target.css(property, reset_val); 35 | } 36 | }; 37 | 38 | // jQuery chainability -- do the magic below 39 | return this.each(function() { 40 | 41 | if (options.debug_mode) console.debug('caption.js | Starting.'); 42 | 43 | // Form basic structures and assign vars 44 | var $this = $(this), // The image 45 | $caption = $this.data('caption') ? $this.data('caption') : $this.attr('alt'), 46 | $figure = $this.wrap('
').after('
').parent(), 47 | $figcaption = $this.next('figcaption').html($caption), 48 | $link = $this.data('link') ? $figcaption.wrapInner('').children('a').css('padding', '0').css('margin', '0') : null, 49 | target_width, 50 | target_height; 51 | 52 | // Fallback for name change of hide to hidden 53 | if (options.mode === 'hide') 54 | { 55 | options.mode = 'hidden'; 56 | } 57 | 58 | // If no caption is supplied, just remove the figcaption. 59 | if ($caption === '') $figcaption.remove(); 60 | 61 | if (options.debug_mode) console.debug('caption.js | Caption: ' + $caption); 62 | 63 | // Determine the appropriate dimensions for the figure, our top-most container for caption.js. 64 | if (options.force_dimensions) 65 | { 66 | if (options.debug_mode) console.debug('caption.js | Forcing dimensions with a clone.'); 67 | 68 | // Create a clone outside of the viewport to detect and then set the dimensions. 69 | var $clone = $figure.clone().css({ 70 | 'position': 'absolute', 71 | 'left' : '-9999px' 72 | }).appendTo('body'); 73 | 74 | target_width = $('img', $clone).outerWidth(); 75 | target_height = $('figcaption', $clone).css('width', target_width).css('clear', 'both').outerHeight(); // Make sure width (and thus line wrapping) is enforced so that the height is correct 76 | 77 | $clone.remove(); 78 | } 79 | else 80 | { 81 | target_width = $this.outerWidth(); 82 | target_height = $figcaption.outerHeight(); 83 | } 84 | 85 | // If responsive, set widths across the board to 100%. We will rely on a 86 | // responsive container to constrain the size of the image. 87 | if (options.is_responsive) 88 | { 89 | target_width = '100%'; 90 | $this.width(target_width); 91 | } 92 | 93 | // Copy styles if need be 94 | if (options.inherit_styles) 95 | { 96 | if ($this.css('display') == 'inline') 97 | $figure.css('display', 'inline-block'); 98 | else 99 | transferStyles('display', 'block', $figure, $this); 100 | 101 | if ($this.css('position') == 'static') 102 | $figure.css('position', 'relative'); 103 | else 104 | transferStyles('position', 'relative', $figure, $this); 105 | 106 | transferStyles('clear', 'both', $figure, $this); 107 | transferStyles('float', 'none', $figure, $this); 108 | transferStyles('margin', '0', $figure, $this); 109 | // transferStyles('padding', '0', $figure, $this); // @todo 110 | $this.css('padding', '0'); 111 | transferStyles('left', 'auto', $figure, $this); 112 | transferStyles('right', 'auto', $figure, $this); 113 | transferStyles('top', 'auto', $figure, $this); 114 | transferStyles('bottom', 'auto', $figure, $this); 115 | transferStyles('z-index', $this.css('z-index'), $figure, $this); 116 | } 117 | 118 | // Set the width of the figure. 119 | $figure.width(target_width); 120 | 121 | // Schema markup if enabled 122 | if (options.schema) 123 | { 124 | $figure.attr({ 125 | 'itemscope': 'itemscope', 126 | 'itemtype': 'http://schema.org/Photograph' 127 | }); 128 | $figcaption.attr('itemprop', 'name'); 129 | $this.attr('itemprop', 'image'); 130 | } 131 | 132 | // Stacked mode 133 | if (options.mode === 'stacked') 134 | { 135 | $figcaption.css({ 136 | 'margin-bottom': '0', 137 | 'bottom': '0' 138 | }); 139 | } 140 | 141 | // Animated mode 142 | if (options.mode === 'animated') 143 | { 144 | $figcaption.css({ 145 | 'margin-bottom': '0', 146 | 'bottom': -target_height 147 | }); 148 | } 149 | 150 | // Hidden mode 151 | if (options.mode === 'hidden') 152 | { 153 | $figcaption.css({ 154 | 'margin-bottom': target_height, 155 | 'bottom': -target_height 156 | }); 157 | } 158 | 159 | // When window resizes, update all the figcaption values if responsive. 160 | if (options.is_responsive) 161 | { 162 | $(window).resize(function(event) { 163 | 164 | target_height = $figcaption.outerHeight(); 165 | 166 | if (options.mode === 'animated') 167 | { 168 | $figcaption.css({ 169 | 'bottom': -target_height 170 | }); 171 | } 172 | 173 | if (options.mode === 'hidden') 174 | { 175 | $figcaption.css({ 176 | 'margin-bottom': target_height, 177 | 'bottom': -target_height 178 | }); 179 | } 180 | 181 | }); 182 | } 183 | 184 | }); 185 | }; 186 | })(jQuery, window); 187 | -------------------------------------------------------------------------------- /dist/jquery.caption.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * caption.js | easily and semantically add captions to your images 3 | * https://captionjs.com 4 | * 5 | * Copyright 2013–2017, Eric Magnuson 6 | * Released under the MIT license 7 | * https://github.com/jquery/jquery/blob/master/MIT-LICENSE.txt 8 | * 9 | * v1.0.2 10 | * Date: 2017-02-03 11 | */ 12 | !function(t,e,o){t.fn.captionjs=function(o){var i={class_name:"captionjs",schema:!0,mode:"default",debug_mode:!1,force_dimensions:!0,is_responsive:!1,inherit_styles:!1},s=t.extend(i,o||{}),n=function(t,e,o,i){o.jquery&&i.jquery&&(o.css(t,i.css(t)),i.css(t,e))};return this.each(function(){s.debug_mode&&console.debug("caption.js | Starting.");var o,i,a=t(this),c=a.data("caption")?a.data("caption"):a.attr("alt"),d=a.wrap('
').after("
").parent(),r=a.next("figcaption").html(c);a.data("link")?r.wrapInner('').children("a").css("padding","0").css("margin","0"):null;if("hide"===s.mode&&(s.mode="hidden"),""===c&&r.remove(),s.debug_mode&&console.debug("caption.js | Caption: "+c),s.force_dimensions){s.debug_mode&&console.debug("caption.js | Forcing dimensions with a clone.");var m=d.clone().css({position:"absolute",left:"-9999px"}).appendTo("body");o=t("img",m).outerWidth(),i=t("figcaption",m).css("width",o).css("clear","both").outerHeight(),m.remove()}else o=a.outerWidth(),i=r.outerHeight();s.is_responsive&&(o="100%",a.width(o)),s.inherit_styles&&("inline"==a.css("display")?d.css("display","inline-block"):n("display","block",d,a),"static"==a.css("position")?d.css("position","relative"):n("position","relative",d,a),n("clear","both",d,a),n("float","none",d,a),n("margin","0",d,a),a.css("padding","0"),n("left","auto",d,a),n("right","auto",d,a),n("top","auto",d,a),n("bottom","auto",d,a),n("z-index",a.css("z-index"),d,a)),d.width(o),s.schema&&(d.attr({itemscope:"itemscope",itemtype:"http://schema.org/Photograph"}),r.attr("itemprop","name"),a.attr("itemprop","image")),"stacked"===s.mode&&r.css({"margin-bottom":"0",bottom:"0"}),"animated"===s.mode&&r.css({"margin-bottom":"0",bottom:-i}),"hidden"===s.mode&&r.css({"margin-bottom":i,bottom:-i}),s.is_responsive&&t(e).resize(function(t){i=r.outerHeight(),"animated"===s.mode&&r.css({bottom:-i}),"hidden"===s.mode&&r.css({"margin-bottom":i,bottom:-i})})})}}(jQuery,window); -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'), 2 | jshint = require('gulp-jshint'), 3 | uglify = require('gulp-uglify'), 4 | concat = require('gulp-concat'), 5 | autoprefixer = require('gulp-autoprefixer'), 6 | clean = require('gulp-clean-css'); 7 | 8 | gulp.task('css', function () { 9 | return gulp 10 | .src('src/main.css') 11 | .pipe(autoprefixer()) 12 | .pipe(clean({ 13 | compatibility: 'ie8', 14 | processImport: true, 15 | keepBreaks: true 16 | // level: 0, 17 | // format: { 18 | // breaks: { 19 | // afterAtRule: false, // controls if a line break comes after an at-rule; e.g. `@charset`; defaults to `false` 20 | // afterBlockBegins: true, // controls if a line break comes after a block begins; e.g. `@media`; defaults to `false` 21 | // afterBlockEnds: true, // controls if a line break comes after a block ends, defaults to `false` 22 | // afterComment: true, // controls if a line break comes after a comment; defaults to `false` 23 | // afterProperty: true, // controls if a line break comes after a property; defaults to `false` 24 | // afterRuleBegins: false, // controls if a line break comes after a rule begins; defaults to `false` 25 | // afterRuleEnds: true, // controls if a line break comes after a rule ends; defaults to `false` 26 | // beforeBlockEnds: true, // controls if a line break comes before a block ends; defaults to `false` 27 | // betweenSelectors: true // controls if a line break comes between selectors; defaults to `false` 28 | // }, 29 | // indentBy: 4, 30 | // spaces: { 31 | // aroundSelectorRelation: true, 32 | // beforeBlockBegins: true, 33 | // beforeValue: true 34 | // } 35 | // } 36 | })) 37 | .pipe(concat('captionjs.css')) 38 | .pipe(gulp.dest('dist/')) 39 | .pipe(clean({ 40 | compatibility: 'ie8', 41 | processImport: true, 42 | keepBreaks: false 43 | })) 44 | .pipe(concat('captionjs.min.css')) 45 | .pipe(gulp.dest('dist/')); 46 | }); 47 | 48 | gulp.task('js', ['jshint'], function () { 49 | return gulp 50 | .src('src/main.js') 51 | .pipe(concat('jquery.caption.js')) 52 | .pipe(gulp.dest('dist/')) 53 | .pipe(uglify({preserveComments: 'license'})) 54 | .pipe(concat('jquery.caption.min.js')) 55 | .pipe(gulp.dest('dist/')); 56 | }); 57 | 58 | gulp.task('jshint', function () { 59 | return gulp 60 | .src('src/main.js') 61 | .pipe(jshint()) 62 | .pipe(jshint.reporter('jshint-stylish')) 63 | .pipe(jshint.reporter('fail')); 64 | }); 65 | 66 | gulp.task('watch', ['css', 'js'], function () { 67 | gulp.watch('src/main.css', ['css']); 68 | gulp.watch('src/main.js', ['js']); 69 | }); 70 | 71 | gulp.task('default', ['css', 'js']); 72 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "captionjs", 3 | "version": "1.0.2", 4 | "description": "An open-source jQuery plugin to easily and semantically add captions to images.", 5 | "author": "Eric Magnuson ", 6 | "license": "MIT", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/ericmagnuson/captionjs.git" 10 | }, 11 | "devDependencies": { 12 | "gulp": "^3.9.1", 13 | "gulp-autoprefixer": "^3.1.1", 14 | "gulp-clean-css": "^2.3.2", 15 | "gulp-concat": "^2.6.0", 16 | "gulp-jshint": "^2.0.0", 17 | "gulp-uglify": "^1.5.3", 18 | "jshint": "^2.9.1", 19 | "jshint-stylish": "^2.1.0" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | // caption.js styles 3 | */ 4 | 5 | /* Main */ 6 | .captionjs { 7 | line-height: 0; 8 | } 9 | .captionjs figcaption { 10 | line-height: 1; 11 | -webkit-box-sizing: border-box; 12 | -moz-box-sizing: border-box; 13 | -ms-box-sizing: border-box; 14 | -o-box-sizing: border-box; 15 | box-sizing: border-box; 16 | width: 100%; 17 | } 18 | .captionjs.captionjs-stacked, 19 | .captionjs.captionjs-animated, 20 | .captionjs.captionjs-hidden { 21 | position: relative; 22 | overflow: hidden; 23 | } 24 | .captionjs.captionjs-stacked figcaption, 25 | .captionjs.captionjs-animated figcaption, 26 | .captionjs.captionjs-hidden figcaption { 27 | position: absolute; 28 | } 29 | 30 | /* Stacked mode */ 31 | .captionjs.captionjs-stacked figcaption { 32 | bottom: 0; 33 | } 34 | 35 | /* Animated mode */ 36 | .captionjs.captionjs-animated figcaption { 37 | -webkit-transition: 0.25s bottom; 38 | -moz-transition: 0.25s bottom; 39 | -ms-transition: 0.25s bottom; 40 | -o-transition: 0.25s bottom; 41 | transition: 0.25s bottom; 42 | } 43 | .captionjs.captionjs-animated:hover figcaption { 44 | bottom: 0 !important; 45 | } 46 | 47 | /* Hide mode */ 48 | .captionjs.captionjs-hidden figcaption { 49 | -webkit-transition: 0.25s margin-bottom; 50 | -moz-transition: 0.25s margin-bottom; 51 | -ms-transition: 0.25s margin-bottom; 52 | -o-transition: 0.25s margin-bottom; 53 | transition: 0.25s margin-bottom; 54 | } 55 | .captionjs.captionjs-hidden:hover figcaption { 56 | margin-bottom: 0 !important; 57 | } 58 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * caption.js | easily and semantically add captions to your images 3 | * https://captionjs.com 4 | * 5 | * Copyright 2013–2017, Eric Magnuson 6 | * Released under the MIT license 7 | * https://github.com/jquery/jquery/blob/master/MIT-LICENSE.txt 8 | * 9 | * v1.0.2 10 | * Date: 2017-02-03 11 | */ 12 | (function($, window, undefined) { 13 | $.fn.captionjs = function(opts) { 14 | 15 | // Default values for options 16 | var defaults = { 17 | 'class_name' : 'captionjs', // Class name for each
18 | 'schema' : true, // Use schema.org markup (i.e., itemtype, itemprop) 19 | 'mode' : 'default', // default | stacked | animated | hidden (deprecated: hide) 20 | 'debug_mode' : false, // Output debug info to the JS console 21 | 'force_dimensions': true, // Force the dimensions in case they cannot be detected (e.g., image is not yet painted to viewport) 22 | 'is_responsive' : false, // Ensure the figure and image change size when in responsive layout. Requires a container to control responsiveness! 23 | 'inherit_styles' : false // Have the caption.js container inherit box-model properties from the original image 24 | }; 25 | 26 | // Extend the options from defaults with user's options 27 | var options = $.extend(defaults, opts || {}); 28 | 29 | // Function to copy styles 30 | var transferStyles = function(property, reset_val, $origin, $target) { 31 | if ($origin.jquery && $target.jquery) // Check that they are jQuery objects 32 | { 33 | $origin.css(property, $target.css(property)); 34 | $target.css(property, reset_val); 35 | } 36 | }; 37 | 38 | // jQuery chainability -- do the magic below 39 | return this.each(function() { 40 | 41 | if (options.debug_mode) console.debug('caption.js | Starting.'); 42 | 43 | // Form basic structures and assign vars 44 | var $this = $(this), // The image 45 | $caption = $this.data('caption') ? $this.data('caption') : $this.attr('alt'), 46 | $figure = $this.wrap('
').after('
').parent(), 47 | $figcaption = $this.next('figcaption').html($caption), 48 | $link = $this.data('link') ? $figcaption.wrapInner('').children('a').css('padding', '0').css('margin', '0') : null, 49 | target_width, 50 | target_height; 51 | 52 | // Fallback for name change of hide to hidden 53 | if (options.mode === 'hide') 54 | { 55 | options.mode = 'hidden'; 56 | } 57 | 58 | // If no caption is supplied, just remove the figcaption. 59 | if ($caption === '') $figcaption.remove(); 60 | 61 | if (options.debug_mode) console.debug('caption.js | Caption: ' + $caption); 62 | 63 | // Determine the appropriate dimensions for the figure, our top-most container for caption.js. 64 | if (options.force_dimensions) 65 | { 66 | if (options.debug_mode) console.debug('caption.js | Forcing dimensions with a clone.'); 67 | 68 | // Create a clone outside of the viewport to detect and then set the dimensions. 69 | var $clone = $figure.clone().css({ 70 | 'position': 'absolute', 71 | 'left' : '-9999px' 72 | }).appendTo('body'); 73 | 74 | target_width = $('img', $clone).outerWidth(); 75 | target_height = $('figcaption', $clone).css('width', target_width).css('clear', 'both').outerHeight(); // Make sure width (and thus line wrapping) is enforced so that the height is correct 76 | 77 | $clone.remove(); 78 | } 79 | else 80 | { 81 | target_width = $this.outerWidth(); 82 | target_height = $figcaption.outerHeight(); 83 | } 84 | 85 | // If responsive, set widths across the board to 100%. We will rely on a 86 | // responsive container to constrain the size of the image. 87 | if (options.is_responsive) 88 | { 89 | target_width = '100%'; 90 | $this.width(target_width); 91 | } 92 | 93 | // Copy styles if need be 94 | if (options.inherit_styles) 95 | { 96 | if ($this.css('display') == 'inline') 97 | $figure.css('display', 'inline-block'); 98 | else 99 | transferStyles('display', 'block', $figure, $this); 100 | 101 | if ($this.css('position') == 'static') 102 | $figure.css('position', 'relative'); 103 | else 104 | transferStyles('position', 'relative', $figure, $this); 105 | 106 | transferStyles('clear', 'both', $figure, $this); 107 | transferStyles('float', 'none', $figure, $this); 108 | transferStyles('margin', '0', $figure, $this); 109 | // transferStyles('padding', '0', $figure, $this); // @todo 110 | $this.css('padding', '0'); 111 | transferStyles('left', 'auto', $figure, $this); 112 | transferStyles('right', 'auto', $figure, $this); 113 | transferStyles('top', 'auto', $figure, $this); 114 | transferStyles('bottom', 'auto', $figure, $this); 115 | transferStyles('z-index', $this.css('z-index'), $figure, $this); 116 | } 117 | 118 | // Set the width of the figure. 119 | $figure.width(target_width); 120 | 121 | // Schema markup if enabled 122 | if (options.schema) 123 | { 124 | $figure.attr({ 125 | 'itemscope': 'itemscope', 126 | 'itemtype': 'http://schema.org/Photograph' 127 | }); 128 | $figcaption.attr('itemprop', 'name'); 129 | $this.attr('itemprop', 'image'); 130 | } 131 | 132 | // Stacked mode 133 | if (options.mode === 'stacked') 134 | { 135 | $figcaption.css({ 136 | 'margin-bottom': '0', 137 | 'bottom': '0' 138 | }); 139 | } 140 | 141 | // Animated mode 142 | if (options.mode === 'animated') 143 | { 144 | $figcaption.css({ 145 | 'margin-bottom': '0', 146 | 'bottom': -target_height 147 | }); 148 | } 149 | 150 | // Hidden mode 151 | if (options.mode === 'hidden') 152 | { 153 | $figcaption.css({ 154 | 'margin-bottom': target_height, 155 | 'bottom': -target_height 156 | }); 157 | } 158 | 159 | // When window resizes, update all the figcaption values if responsive. 160 | if (options.is_responsive) 161 | { 162 | $(window).resize(function(event) { 163 | 164 | target_height = $figcaption.outerHeight(); 165 | 166 | if (options.mode === 'animated') 167 | { 168 | $figcaption.css({ 169 | 'bottom': -target_height 170 | }); 171 | } 172 | 173 | if (options.mode === 'hidden') 174 | { 175 | $figcaption.css({ 176 | 'margin-bottom': target_height, 177 | 'bottom': -target_height 178 | }); 179 | } 180 | 181 | }); 182 | } 183 | 184 | }); 185 | }; 186 | })(jQuery, window); 187 | -------------------------------------------------------------------------------- /web/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericmagnuson/captionjs/01f75bf721b2176098ff3039e141fa26c15d668c/web/favicon.ico -------------------------------------------------------------------------------- /web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericmagnuson/captionjs/01f75bf721b2176098ff3039e141fa26c15d668c/web/favicon.png -------------------------------------------------------------------------------- /web/img/Evening_Return-wide.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericmagnuson/captionjs/01f75bf721b2176098ff3039e141fa26c15d668c/web/img/Evening_Return-wide.jpg -------------------------------------------------------------------------------- /web/scripts/jquery.lettering.js: -------------------------------------------------------------------------------- 1 | /*global jQuery */ 2 | /*! 3 | * Lettering.JS 0.6.1 4 | * 5 | * Copyright 2010, Dave Rupert http://daverupert.com 6 | * Released under the WTFPL license 7 | * http://sam.zoy.org/wtfpl/ 8 | * 9 | * Thanks to Paul Irish - http://paulirish.com - for the feedback. 10 | * 11 | * Date: Mon Sep 20 17:14:00 2010 -0600 12 | */ 13 | (function($){ 14 | function injector(t, splitter, klass, after) { 15 | var a = t.text().split(splitter), inject = ''; 16 | if (a.length) { 17 | $(a).each(function(i, item) { 18 | inject += ''+item+''+after; 19 | }); 20 | t.empty().append(inject); 21 | } 22 | } 23 | 24 | var methods = { 25 | init : function() { 26 | 27 | return this.each(function() { 28 | injector($(this), '', 'char', ''); 29 | }); 30 | 31 | }, 32 | 33 | words : function() { 34 | 35 | return this.each(function() { 36 | injector($(this), ' ', 'word', ' '); 37 | }); 38 | 39 | }, 40 | 41 | lines : function() { 42 | 43 | return this.each(function() { 44 | var r = "eefec303079ad17405c889e092e105b0"; 45 | // Because it's hard to split a
tag consistently across browsers, 46 | // (*ahem* IE *ahem*), we replaces all
instances with an md5 hash 47 | // (of the word "split"). If you're trying to use this plugin on that 48 | // md5 hash string, it will fail because you're being ridiculous. 49 | injector($(this).children("br").replaceWith(r).end(), r, 'line', ''); 50 | }); 51 | 52 | } 53 | }; 54 | 55 | $.fn.lettering = function( method ) { 56 | // Method calling logic 57 | if ( method && methods[method] ) { 58 | return methods[ method ].apply( this, [].slice.call( arguments, 1 )); 59 | } else if ( method === 'letters' || ! method ) { 60 | return methods.init.apply( this, [].slice.call( arguments, 0 ) ); // always pass an array 61 | } 62 | $.error( 'Method ' + method + ' does not exist on jQuery.lettering' ); 63 | return this; 64 | }; 65 | 66 | })(jQuery); -------------------------------------------------------------------------------- /web/scripts/jquery.localscroll-1.2.7-min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * jQuery.LocalScroll - Animated scrolling navigation, using anchors. 3 | * Copyright (c) 2007-2009 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com 4 | * Dual licensed under MIT and GPL. 5 | * Date: 3/11/2009 6 | * @author Ariel Flesler 7 | * @version 1.2.7 8 | **/ 9 | ;(function($){var l=location.href.replace(/#.*/,'');var g=$.localScroll=function(a){$('body').localScroll(a)};g.defaults={duration:1e3,axis:'y',event:'click',stop:true,target:window,reset:true};g.hash=function(a){if(location.hash){a=$.extend({},g.defaults,a);a.hash=false;if(a.reset){var e=a.duration;delete a.duration;$(a.target).scrollTo(0,a);a.duration=e}i(0,location,a)}};$.fn.localScroll=function(b){b=$.extend({},g.defaults,b);return b.lazy?this.bind(b.event,function(a){var e=$([a.target,a.target.parentNode]).filter(d)[0];if(e)i(a,e,b)}):this.find('a,area').filter(d).bind(b.event,function(a){i(a,this,b)}).end().end();function d(){return!!this.href&&!!this.hash&&this.href.replace(this.hash,'')==l&&(!b.filter||$(this).is(b.filter))}};function i(a,e,b){var d=e.hash.slice(1),f=document.getElementById(d)||document.getElementsByName(d)[0];if(!f)return;if(a)a.preventDefault();var h=$(b.target);if(b.lock&&h.is(':animated')||b.onBefore&&b.onBefore.call(b,a,f,h)===false)return;if(b.stop)h.stop(true);if(b.hash){var j=f.id==d?'id':'name',k=$('
').attr(j,d).css({position:'absolute',top:$(window).scrollTop(),left:$(window).scrollLeft()});f[j]='';$('body').prepend(k);location=e.hash;k.remove();f[j]=d}h.scrollTo(f,b).trigger('notify.serialScroll',[f])}})(jQuery); -------------------------------------------------------------------------------- /web/scripts/jquery.scrollTo-1.4.3.1-min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2007-2012 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com 3 | * Dual licensed under MIT and GPL. 4 | * @author Ariel Flesler 5 | * @version 1.4.3.1 6 | */ 7 | ;(function($){var h=$.scrollTo=function(a,b,c){$(window).scrollTo(a,b,c)};h.defaults={axis:'xy',duration:parseFloat($.fn.jquery)>=1.3?0:1,limit:true};h.window=function(a){return $(window)._scrollable()};$.fn._scrollable=function(){return this.map(function(){var a=this,isWin=!a.nodeName||$.inArray(a.nodeName.toLowerCase(),['iframe','#document','html','body'])!=-1;if(!isWin)return a;var b=(a.contentWindow||a).document||a.ownerDocument||a;return/webkit/i.test(navigator.userAgent)||b.compatMode=='BackCompat'?b.body:b.documentElement})};$.fn.scrollTo=function(e,f,g){if(typeof f=='object'){g=f;f=0}if(typeof g=='function')g={onAfter:g};if(e=='max')e=9e9;g=$.extend({},h.defaults,g);f=f||g.duration;g.queue=g.queue&&g.axis.length>1;if(g.queue)f/=2;g.offset=both(g.offset);g.over=both(g.over);return this._scrollable().each(function(){if(e==null)return;var d=this,$elem=$(d),targ=e,toff,attr={},win=$elem.is('html,body');switch(typeof targ){case'number':case'string':if(/^([+-]=)?\d+(\.\d+)?(px|%)?$/.test(targ)){targ=both(targ);break}targ=$(targ,this);if(!targ.length)return;case'object':if(targ.is||targ.style)toff=(targ=$(targ)).offset()}$.each(g.axis.split(''),function(i,a){var b=a=='x'?'Left':'Top',pos=b.toLowerCase(),key='scroll'+b,old=d[key],max=h.max(d,a);if(toff){attr[key]=toff[pos]+(win?0:old-$elem.offset()[pos]);if(g.margin){attr[key]-=parseInt(targ.css('margin'+b))||0;attr[key]-=parseInt(targ.css('border'+b+'Width'))||0}attr[key]+=g.offset[pos]||0;if(g.over[pos])attr[key]+=targ[a=='x'?'width':'height']()*g.over[pos]}else{var c=targ[pos];attr[key]=c.slice&&c.slice(-1)=='%'?parseFloat(c)/100*max:c}if(g.limit&&/^\d+$/.test(attr[key]))attr[key]=attr[key]<=0?0:Math.min(attr[key],max);if(!i&&g.queue){if(old!=attr[key])animate(g.onAfterFirst);delete attr[key]}});animate(g.onAfter);function animate(a){$elem.animate(attr,f,g.easing,a&&function(){a.call(this,e,g)})}}).end()};h.max=function(a,b){var c=b=='x'?'Width':'Height',scroll='scroll'+c;if(!$(a).is('html,body'))return a[scroll]-$(a)[c.toLowerCase()]();var d='client'+c,html=a.ownerDocument.documentElement,body=a.ownerDocument.body;return Math.max(html[scroll],body[scroll])-Math.min(html[d],body[d])};function both(a){return typeof a=='object'?a:{top:a,left:a}}})(jQuery); -------------------------------------------------------------------------------- /web/scripts/main.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | // Init SyntaxHighlighter 3 | SyntaxHighlighter.autoloader( 4 | 'js jscript javascript web/scripts/syntaxhighlighter/scripts/shBrushJScript.js', 5 | 'html xml web/scripts/syntaxhighlighter/scripts/shBrushXml.js', 6 | 'css web/scripts/syntaxhighlighter/scripts/shBrushCss.js' 7 | ); 8 | SyntaxHighlighter.defaults.gutter = false; 9 | SyntaxHighlighter.all(); 10 | 11 | // Init scrollTo 12 | $('nav').localScroll({ 13 | duration : 500, 14 | offset : {top:-70, left:0} 15 | }); 16 | 17 | // Stylize "caption.js" 18 | $("p:contains('caption.js'), h2 a:contains('caption.js')", document.body).contents().each(function() { 19 | if (this.nodeType == 3) 20 | $(this).replaceWith(this.nodeValue.replace(/caption.js/g, "caption.js")); 21 | }); 22 | 23 | $("header h1, .captionjs").lettering(); 24 | 25 | // Fire these enclosed functions after page has faded in 26 | var after_fade_in = function after_fade_in(){ 27 | // Init the sticky nav 28 | var position = $('nav').offset(); 29 | var x_coord = position.top; 30 | var padding_to_add = $('nav').outerHeight(true); 31 | 32 | $(window).scroll(function(){ 33 | var top = $(window).scrollTop(); 34 | if (top > x_coord - 1) 35 | { 36 | $('nav').addClass('sticky'); 37 | $('body > div:first-of-type').css('padding-top', padding_to_add + 'px'); 38 | } 39 | else 40 | { 41 | $('nav').removeClass('sticky'); 42 | $('body > div:first-of-type').css('padding-top', '0'); 43 | } 44 | }); 45 | }; 46 | 47 | // Fade in content 48 | setTimeout(function(){ 49 | $('.js header h1').fadeIn(1500, function(){ 50 | $('.js header h2').fadeIn(1000, function(){ 51 | $('.js #github, .js nav, .js body > div, .js footer').delay(1000).fadeIn(1000, after_fade_in); 52 | }); 53 | }); 54 | }, 500); 55 | 56 | }); 57 | -------------------------------------------------------------------------------- /web/scripts/syntaxhighlighter/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hello SyntaxHighlighter 6 | 7 | 8 | 9 | 10 | 16 | 17 | 18 | 19 | 20 |

Hello SyntaxHighlighter

21 | 22 |
23 | function helloSyntaxHighlighter()
24 | {
25 | 	return "hi!";
26 | }
27 | 
28 | 29 | 30 | -------------------------------------------------------------------------------- /web/scripts/syntaxhighlighter/scripts/shAutoloader.js: -------------------------------------------------------------------------------- 1 | /** 2 | * SyntaxHighlighter 3 | * http://alexgorbatchev.com/SyntaxHighlighter 4 | * 5 | * SyntaxHighlighter is donationware. If you are using it, please donate. 6 | * http://alexgorbatchev.com/SyntaxHighlighter/donate.html 7 | * 8 | * @version 9 | * 3.0.9 (Wed, 15 Oct 2014 20:22:15 GMT) 10 | * 11 | * @copyright 12 | * Copyright (C) 2004-2013 Alex Gorbatchev. 13 | * 14 | * @license 15 | * Dual licensed under the MIT and GPL licenses. 16 | */ 17 | (function() { 18 | 19 | var sh = SyntaxHighlighter; 20 | 21 | /** 22 | * Provides functionality to dynamically load only the brushes that a needed to render the current page. 23 | * 24 | * There are two syntaxes that autoload understands. For example: 25 | * 26 | * SyntaxHighlighter.autoloader( 27 | * [ 'applescript', 'Scripts/shBrushAppleScript.js' ], 28 | * [ 'actionscript3', 'as3', 'Scripts/shBrushAS3.js' ] 29 | * ); 30 | * 31 | * or a more easily comprehendable one: 32 | * 33 | * SyntaxHighlighter.autoloader( 34 | * 'applescript Scripts/shBrushAppleScript.js', 35 | * 'actionscript3 as3 Scripts/shBrushAS3.js' 36 | * ); 37 | */ 38 | sh.autoloader = function() 39 | { 40 | var list = arguments, 41 | elements = sh.findElements(), 42 | brushes = {}, 43 | scripts = {}, 44 | all = SyntaxHighlighter.all, 45 | allCalled = false, 46 | allParams = null, 47 | i 48 | ; 49 | 50 | SyntaxHighlighter.all = function(params) 51 | { 52 | allParams = params; 53 | allCalled = true; 54 | }; 55 | 56 | function addBrush(aliases, url) 57 | { 58 | for (var i = 0; i < aliases.length; i++) 59 | brushes[aliases[i]] = url; 60 | }; 61 | 62 | function getAliases(item) 63 | { 64 | return item.pop 65 | ? item 66 | : item.split(/\s+/) 67 | ; 68 | } 69 | 70 | // create table of aliases and script urls 71 | for (i = 0; i < list.length; i++) 72 | { 73 | var aliases = getAliases(list[i]), 74 | url = aliases.pop() 75 | ; 76 | 77 | addBrush(aliases, url); 78 | } 79 | 80 | // dynamically add